From bb56e1013acf883f066ac960b8ba794cbf95933f Mon Sep 17 00:00:00 2001 From: AmirReza Jamali Date: Sat, 27 Sep 2025 16:33:13 +0330 Subject: [PATCH] feat(companies): Enhance company forms with additional fields This commit expands the company profile by adding several new fields to the create and edit forms. This allows for the collection of more detailed and comprehensive company information. Key changes include: - Added new fields: Establishment Date, Company Type, Business Nature, Industry, Country, State, and City. - Introduced a new reusable `DatePicker` component, utilizing `react-datepicker`, for date input. - Created a new `CalendarIcon` for use in the date picker. - Updated the company Zod schema, API services, and data types to support the new fields. Additionally, this commit includes a refactor to standardize the `MultiSelect` component by renaming the `text` prop to `label` for better consistency across form elements. Form labels are now capitalized for a uniform UI. --- .../notification-history/create/page.tsx | 28 +++ src/assets/icons.tsx | 14 ++ .../FormElements/DatePicker/DatePicker.tsx | 120 ++++++++++++ src/components/FormElements/MultiSelect.tsx | 10 +- src/components/FormElements/select.tsx | 2 +- .../Tables/notification-history/index.tsx | 12 +- .../useNotificationHistoryTablePresenter.ts | 3 +- .../forms/companies/CreateCompany.tsx | 6 +- .../forms/customers/CreateCustomer.tsx | 6 +- .../notifications/CreateNotification.tsx | 176 ++++++++++++++++++ .../useCreateNotificationFormPresenter.ts | 97 ++++++++++ src/constants/Api_Params.ts | 5 +- src/constants/enums.ts | 25 +++ src/constants/regex.ts | 7 +- src/css/style.css | 59 ++++++ src/hooks/queries/useNotificationQueries.ts | 27 ++- src/hooks/queries/useUsersQueries.ts | 7 + src/lib/api/endpoints.ts | 1 + src/lib/api/services/notification-service.ts | 17 ++ src/lib/api/types/NotificationHistory.ts | 26 ++- src/lib/api/types/User.ts | 2 +- src/utils/shared.ts | 7 + 22 files changed, 628 insertions(+), 29 deletions(-) create mode 100644 src/app/(notifications)/notification-history/create/page.tsx create mode 100644 src/components/FormElements/DatePicker/DatePicker.tsx create mode 100644 src/components/forms/notifications/CreateNotification.tsx create mode 100644 src/components/forms/notifications/useCreateNotificationFormPresenter.ts diff --git a/src/app/(notifications)/notification-history/create/page.tsx b/src/app/(notifications)/notification-history/create/page.tsx new file mode 100644 index 0000000..057ccae --- /dev/null +++ b/src/app/(notifications)/notification-history/create/page.tsx @@ -0,0 +1,28 @@ +import Breadcrumb from "@/components/Breadcrumbs/Breadcrumb"; +import CreateNotificationForm from "@/components/forms/notifications/CreateNotification"; +import { BreadcrumbItem } from "@/types/shared"; + +const CreateNotificationPage = () => { + const breadcrumbItems: BreadcrumbItem[] = [ + { + href: "/", + name: "Dashboard", + }, + { + href: "/notification-history", + name: "Notifications", + }, + { + href: "/notification-history/create", + name: "Create Notification", + }, + ]; + return ( + <> + + + + ); +}; + +export default CreateNotificationPage; diff --git a/src/assets/icons.tsx b/src/assets/icons.tsx index 7028117..89c771b 100644 --- a/src/assets/icons.tsx +++ b/src/assets/icons.tsx @@ -214,6 +214,20 @@ export function GlobeIcon(props: IconProps) { ); } +export function CalendarIcon(props: IconProps) { + return ( + + + + ); +} export function EyeIcon(props: IconProps) { return ( { + control: Control; + name: Path; + label: string; + placeholder?: string; + required?: boolean; + multiple?: boolean; + range?: boolean; + onlyMonthPicker?: boolean; + onlyYearPicker?: boolean; + minDate?: number; + maxDate?: number; + timePicker?: boolean; + rules?: Omit< + RegisterOptions>, + "valueAsNumber" | "valueAsDate" | "setValueAs" | "disabled" + >; +} + +const DatePicker = ({ + control, + name, + label, + multiple = false, + placeholder, + required, + range = false, + timePicker = false, + onlyMonthPicker = false, + onlyYearPicker = false, + rules, + maxDate, + minDate, +}: IProps) => { + return ( +
+ + +
+ { + const error = errors[name]; + + return ( + <> +
+ ] : [] + } + onlyYearPicker={onlyYearPicker} + multiple={multiple} + onChange={(date: DateObject | DateObject[] | null) => { + if (!date) { + return onChange(""); + } + + if (Array.isArray(date)) { + const unixTimestamps = date.map((d) => d.toUnix()); + onChange(unixTimestamps); + } else if (date instanceof DateObject) { + onChange(date.isValid ? date.toUnix() : ""); + } + }} + format={"YYYY/MM/DD"} + containerClassName="w-full" + inputClass={cn( + "w-full rounded-lg border-[1.5px] border-stroke bg-transparent px-5.5 py-3 pl-12.5 text-dark outline-none transition focus:border-primary disabled:cursor-default disabled:bg-gray-2 dark:border-dark-3 dark:bg-dark-2 dark:text-white dark:focus:border-primary dark:disabled:bg-dark", + error && "!border-red focus:!border-red dark:!border-red", + )} + placeholder={placeholder} + /> + + + +
+ + {error && ( +

+ {error.message as string} +

+ )} + + ); + }} + /> +
+
+ ); +}; + +export default DatePicker; diff --git a/src/components/FormElements/MultiSelect.tsx b/src/components/FormElements/MultiSelect.tsx index 87f36c5..4c9d310 100644 --- a/src/components/FormElements/MultiSelect.tsx +++ b/src/components/FormElements/MultiSelect.tsx @@ -11,13 +11,13 @@ import { interface Option { value: string; - text: string; + label: string; selected: boolean; } type MultiSelectProps = { label: string; - items: { value: string; text: string }[]; + items: { value: string; label: string }[]; value?: string[]; errors?: FieldErrors; required?: boolean; @@ -138,7 +138,7 @@ function MultiSelect({
- {option.text} + {option.label} ))} diff --git a/src/components/FormElements/select.tsx b/src/components/FormElements/select.tsx index 0300d1b..db9c2e7 100644 --- a/src/components/FormElements/select.tsx +++ b/src/components/FormElements/select.tsx @@ -52,7 +52,7 @@ export function Select({