f48cb7e249
- Bumped NEXT_PUBLIC_APP_VERSION to 2.0.3 for the latest release. - Improved Cypress test for customer feedback page to handle delayed route transitions. - Refactored CompanyDetailsPage to enhance layout and added new components for better structure. - Updated TenderDetails to conditionally render location and currency information based on validity checks. - Added data-cy attributes to various form elements and tables for improved testing capabilities.
96 lines
2.9 KiB
TypeScript
96 lines
2.9 KiB
TypeScript
import { cn } from "@/lib/utils";
|
|
import { useId } from "react";
|
|
import {
|
|
type FieldErrors,
|
|
type FieldValues,
|
|
type Path,
|
|
type UseFormRegister,
|
|
type UseFormRegisterReturn,
|
|
} from "react-hook-form";
|
|
|
|
type PropsType<T extends FieldValues> = {
|
|
name: Path<T>;
|
|
label: string;
|
|
placeholder?: string;
|
|
required?: boolean;
|
|
disabled?: boolean;
|
|
active?: boolean;
|
|
className?: string;
|
|
icon?: React.ReactNode;
|
|
defaultValue?: string;
|
|
dataCy?: string;
|
|
handleChange?: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
|
|
register?: UseFormRegister<T>;
|
|
errors?: FieldErrors<T>;
|
|
} & Partial<UseFormRegisterReturn>;
|
|
|
|
export function TextAreaGroup<T extends FieldValues>({
|
|
name,
|
|
label,
|
|
placeholder,
|
|
required,
|
|
disabled,
|
|
active,
|
|
className,
|
|
icon,
|
|
defaultValue,
|
|
dataCy,
|
|
handleChange,
|
|
register,
|
|
errors,
|
|
onChange,
|
|
onBlur,
|
|
ref,
|
|
...props
|
|
}: PropsType<T>) {
|
|
const id = useId();
|
|
|
|
const error = errors && errors[name];
|
|
|
|
return (
|
|
<div className={cn(className)}>
|
|
<label
|
|
htmlFor={id}
|
|
className="mb-3 block text-body-sm font-semibold text-dark dark:text-white"
|
|
>
|
|
{label}
|
|
{required && <span className="ml-1 select-none text-error">*</span>}
|
|
</label>
|
|
|
|
<div className="relative mt-3 [&_svg]:pointer-events-none [&_svg]:absolute [&_svg]:left-5.5 [&_svg]:top-5.5 [&_svg]:text-dark-5 dark:[&_svg]:text-white/75">
|
|
<textarea
|
|
id={id}
|
|
name={name}
|
|
ref={ref}
|
|
rows={6}
|
|
placeholder={placeholder}
|
|
defaultValue={defaultValue}
|
|
onChange={(e) => {
|
|
onChange?.(e);
|
|
handleChange?.(e);
|
|
}}
|
|
onBlur={onBlur}
|
|
className={cn(
|
|
"w-full rounded-xl border border-stroke/70 bg-white/90 px-5.5 py-3 text-dark shadow-[0_1px_2px_rgba(16,24,40,0.04),0_8px_20px_rgba(16,24,40,0.04)] outline-none backdrop-blur-[1px] transition-all duration-200 focus:border-primary/70 focus:bg-white focus:shadow-[0_0_0_2px_rgba(59,130,246,0.14),0_10px_24px_rgba(59,130,246,0.08)] disabled:cursor-default disabled:bg-gray-2/70 data-[active=true]:border-primary/70 dark:border-dark-3/80 dark:bg-dark-2/85 dark:text-white dark:focus:border-primary/80 dark:focus:shadow-[0_0_0_2px_rgba(59,130,246,0.2),0_10px_24px_rgba(15,23,42,0.45)] dark:disabled:bg-dark dark:data-[active=true]:border-primary/80",
|
|
error &&
|
|
"border-red/80 focus:border-red focus:shadow-[0_0_0_2px_rgba(239,68,68,0.16),0_10px_24px_rgba(239,68,68,0.1)] dark:border-red/80 dark:focus:shadow-[0_0_0_2px_rgba(239,68,68,0.24),0_10px_24px_rgba(127,29,29,0.45)]",
|
|
icon && "py-5 pl-13 pr-5",
|
|
)}
|
|
required={required}
|
|
disabled={disabled}
|
|
data-active={active}
|
|
data-cy={dataCy}
|
|
/>
|
|
|
|
{icon}
|
|
</div>
|
|
|
|
{error && (
|
|
<p className="text-red mt-1.5 text-sm font-medium">
|
|
{error.message as string}
|
|
</p>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|