From 923423f25ac8c9754d72469d27d05967c738d3de Mon Sep 17 00:00:00 2001 From: Raj kumar <150310085+rajku-dev@users.noreply.github.com> Date: Fri, 24 Jan 2025 10:54:00 +0530 Subject: [PATCH 01/68] Fix: Unwanted scrolling and spacing on availability page (#10130) --- src/components/Users/UserAvailabilityTab.tsx | 4 ++-- src/pages/Scheduling/ScheduleExceptions.tsx | 2 +- src/pages/Scheduling/ScheduleTemplates.tsx | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/Users/UserAvailabilityTab.tsx b/src/components/Users/UserAvailabilityTab.tsx index 6ac227bec67..5ed92fd25e8 100644 --- a/src/components/Users/UserAvailabilityTab.tsx +++ b/src/components/Users/UserAvailabilityTab.tsx @@ -210,7 +210,7 @@ export default function UserAvailabilityTab({ userData: user }: Props) {
- + {view === "schedule" && (
- + {templates.map((template) => (
diff --git a/src/pages/Scheduling/ScheduleExceptions.tsx b/src/pages/Scheduling/ScheduleExceptions.tsx index 50a8074505a..7480c49a323 100644 --- a/src/pages/Scheduling/ScheduleExceptions.tsx +++ b/src/pages/Scheduling/ScheduleExceptions.tsx @@ -36,7 +36,7 @@ export default function ScheduleExceptions({ if (items.length === 0) { return ( -
+

{t("no_scheduled_exceptions_found")}

diff --git a/src/pages/Scheduling/ScheduleTemplates.tsx b/src/pages/Scheduling/ScheduleTemplates.tsx index 5d32b332910..4050c8e4866 100644 --- a/src/pages/Scheduling/ScheduleTemplates.tsx +++ b/src/pages/Scheduling/ScheduleTemplates.tsx @@ -36,7 +36,7 @@ export default function ScheduleTemplates({ if (items.length === 0) { return ( -
+

{t("no_schedule_templates_found")}

From 1a1afd65d3f58297d02250f5835a64f464360e21 Mon Sep 17 00:00:00 2001 From: Nikhila C <115739037+NikhilA8606@users.noreply.github.com> Date: Fri, 24 Jan 2025 12:14:51 +0530 Subject: [PATCH 02/68] Added `date-field` reusable component; Migrated old DateFormFields to new UI components (#10049) --- public/locale/en.json | 2 + .../Form/FormFields/DateFormField.tsx | 59 ------- .../Patient/PatientRegistration.tsx | 99 ++---------- .../Questionnaire/QuestionnaireForm.tsx | 1 + src/components/ui/date-field.tsx | 153 ++++++++++++++++++ src/components/ui/date-picker.tsx | 4 +- src/hooks/useFileManager.tsx | 31 ++-- .../PatientRegistration.tsx | 25 +-- 8 files changed, 197 insertions(+), 177 deletions(-) delete mode 100644 src/components/Form/FormFields/DateFormField.tsx create mode 100644 src/components/ui/date-field.tsx diff --git a/public/locale/en.json b/public/locale/en.json index 6987c9aaec0..70b63168575 100644 --- a/public/locale/en.json +++ b/public/locale/en.json @@ -1688,6 +1688,7 @@ "prn_reason": "PRN Reason", "procedure_suggestions": "Procedure Suggestions", "procedures_select_placeholder": "Select procedures to add details", + "proceed": "Proceed", "professional_info": "Professional Information", "professional_info_note": "View or update user's professional information", "professional_info_note_self": "View or update your professional information", @@ -2012,6 +2013,7 @@ "start_time": "Start Time", "start_time_must_be_before_end_time": "Start time must be before end time", "state": "State", + "state_reason_for_archiving": "State reason for archiving {{name}} file?", "status": "Status", "stop": "Stop", "stop_recording": "Stop Recording", diff --git a/src/components/Form/FormFields/DateFormField.tsx b/src/components/Form/FormFields/DateFormField.tsx deleted file mode 100644 index f8834522302..00000000000 --- a/src/components/Form/FormFields/DateFormField.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import DateInputV2 from "@/components/Common/DateInputV2"; -import FormField from "@/components/Form/FormFields/FormField"; -import { - FormFieldBaseProps, - useFormFieldPropsResolver, -} from "@/components/Form/FormFields/Utils"; - -import { classNames } from "@/Utils/utils"; - -type Props = FormFieldBaseProps & { - containerClassName?: string; - placeholder?: string; - max?: Date; - min?: Date; - disableFuture?: boolean; - disablePast?: boolean; - allowTime?: boolean; - popOverClassName?: string; -}; - -/** - * @deprecated use shadcn/ui's date-picker instead - */ -const DateFormField = (props: Props) => { - const field = useFormFieldPropsResolver(props); - return ( - - void} - disabled={field.disabled} - max={props.max ?? (props.disableFuture ? new Date() : undefined)} - min={props.min ?? (props.disablePast ? yesterday() : undefined)} - placeholder={props.placeholder} - allowTime={props.allowTime} - popOverClassName={props.popOverClassName} - /> - - ); -}; - -export default DateFormField; - -const yesterday = () => { - const date = new Date(); - date.setDate(date.getDate() - 1); - return date; -}; diff --git a/src/components/Patient/PatientRegistration.tsx b/src/components/Patient/PatientRegistration.tsx index 543e87148f6..13d8b211ed8 100644 --- a/src/components/Patient/PatientRegistration.tsx +++ b/src/components/Patient/PatientRegistration.tsx @@ -13,6 +13,7 @@ import SectionNavigator from "@/CAREUI/misc/SectionNavigator"; import Autocomplete from "@/components/ui/autocomplete"; import { Button } from "@/components/ui/button"; import { Checkbox } from "@/components/ui/checkbox"; +import DateField from "@/components/ui/date-field"; import { Form, FormControl, @@ -513,95 +514,15 @@ export default function PatientRegistration( render={({ field }) => ( -
-
- {t("day")} - - { - form.setValue( - "date_of_birth", - `${form.watch("date_of_birth")?.split("-")[0]}-${form.watch("date_of_birth")?.split("-")[1]}-${e.target.value}`, - ); - const day = parseInt(e.target.value); - if ( - e.target.value.length === 2 && - day >= 1 && - day <= 31 - ) { - document - .getElementById("dob-month-input") - ?.focus(); - } - }} - data-cy="dob-day-input" - /> -
- -
- {t("month")} - - { - form.setValue( - "date_of_birth", - `${form.watch("date_of_birth")?.split("-")[0]}-${e.target.value}-${form.watch("date_of_birth")?.split("-")[2]}`, - ); - const month = parseInt(e.target.value); - if ( - e.target.value.length === 2 && - month >= 1 && - month <= 12 - ) { - document - .getElementById("dob-year-input") - ?.focus(); - } - }} - data-cy="dob-month-input" - /> -
- -
- {t("year")} - - - form.setValue( - "date_of_birth", - `${e.target.value}-${form.watch("date_of_birth")?.split("-")[1]}-${form.watch("date_of_birth")?.split("-")[2]}`, - ) - } - data-cy="dob-year-input" - /> -
-
+ + field.onChange(date?.toISOString()) + } + id="dob" + />
diff --git a/src/components/Questionnaire/QuestionnaireForm.tsx b/src/components/Questionnaire/QuestionnaireForm.tsx index a5b89383b8e..389da98633f 100644 --- a/src/components/Questionnaire/QuestionnaireForm.tsx +++ b/src/components/Questionnaire/QuestionnaireForm.tsx @@ -157,6 +157,7 @@ export function QuestionnaireForm({ }; const handleSubmissionError = (results: ValidationErrorResponse[]) => { + toast.error("Form Errr"); const updatedForms = [...questionnaireForms]; const errorMessages: string[] = []; diff --git a/src/components/ui/date-field.tsx b/src/components/ui/date-field.tsx new file mode 100644 index 00000000000..bd1506184f1 --- /dev/null +++ b/src/components/ui/date-field.tsx @@ -0,0 +1,153 @@ +import { useEffect, useState } from "react"; +import { useTranslation } from "react-i18next"; + +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; + +import dayjs from "@/Utils/dayjs"; + +interface DateFieldProps { + date?: Date; + onChange?: (date?: Date) => void; + disabled?: boolean; + id?: string; +} + +const isValidDate = (year: string, month: string, day: string): boolean => { + const parsedDate = dayjs(`${year}-${month}-${day}`, "YYYY-MM-DD", true); + return parsedDate.isValid(); +}; + +export default function DateField({ + date, + onChange, + disabled, + id = "date-field", +}: DateFieldProps) { + const { t } = useTranslation(); + const [day, setDay] = useState(""); + const [month, setMonth] = useState(""); + const [year, setYear] = useState(""); + + useEffect(() => { + if (date) { + setDay(date.getDate().toString().padStart(2, "0")); + setMonth((date.getMonth() + 1).toString().padStart(2, "0")); + setYear(date.getFullYear().toString()); + } else { + setDay(""); + setMonth(""); + setYear(""); + } + }, [date]); + + const handleDayChange = (e: React.ChangeEvent) => { + const newDay = e.target.value; + setDay(newDay); + + if ( + newDay.length === 2 && + parseInt(newDay) >= 1 && + parseInt(newDay) <= 31 + ) { + if (isValidDate(year, month, newDay) && onChange) { + const updatedDate = new Date( + parseInt(year), + parseInt(month) - 1, + parseInt(newDay), + ); + onChange(updatedDate); + } + document.getElementById(`${id}-month-input`)?.focus(); + } + }; + + const handleMonthChange = (e: React.ChangeEvent) => { + const newMonth = e.target.value; + setMonth(newMonth); + + if ( + newMonth.length === 2 && + parseInt(newMonth) >= 1 && + parseInt(newMonth) <= 12 + ) { + if (isValidDate(year, newMonth, day) && onChange) { + const updatedDate = new Date( + parseInt(year), + parseInt(newMonth) - 1, + parseInt(day), + ); + onChange(updatedDate); + } + + document.getElementById(`${id}-year-input`)?.focus(); + } + }; + + const handleYearChange = (e: React.ChangeEvent) => { + const newYear = e.target.value; + setYear(newYear); + + if (newYear.length === 4 && parseInt(newYear) >= 1900) { + if (isValidDate(newYear, month, day) && onChange) { + const updatedDate = new Date( + parseInt(newYear), + parseInt(month) - 1, + parseInt(day), + ); + onChange(updatedDate); + } + } + }; + + return ( +
+
+ + +
+ +
+ + +
+ +
+ + +
+
+ ); +} diff --git a/src/components/ui/date-picker.tsx b/src/components/ui/date-picker.tsx index 30ca74560e0..32d23132362 100644 --- a/src/components/ui/date-picker.tsx +++ b/src/components/ui/date-picker.tsx @@ -16,9 +16,10 @@ import { interface DatePickerProps { date?: Date; onChange?: (date?: Date) => void; + disabled?: (date: Date) => boolean; } -export function DatePicker({ date, onChange }: DatePickerProps) { +export function DatePicker({ date, onChange, disabled }: DatePickerProps) { const [open, setOpen] = useState(false); return ( @@ -44,6 +45,7 @@ export function DatePicker({ date, onChange }: DatePickerProps) { setOpen(false); }} initialFocus + disabled={disabled} /> diff --git a/src/hooks/useFileManager.tsx b/src/hooks/useFileManager.tsx index 1a4ab610d9b..cc3d8f754d5 100644 --- a/src/hooks/useFileManager.tsx +++ b/src/hooks/useFileManager.tsx @@ -1,16 +1,20 @@ import { useMutation, useQueryClient } from "@tanstack/react-query"; import { t } from "i18next"; import { useState } from "react"; +import { Trans } from "react-i18next"; import { toast } from "sonner"; +import { cn } from "@/lib/utils"; + import CareIcon from "@/CAREUI/icons/CareIcon"; import { Button } from "@/components/ui/button"; +import { Label } from "@/components/ui/label"; +import { Textarea } from "@/components/ui/textarea"; import DialogModal from "@/components/Common/Dialog"; import FilePreviewDialog from "@/components/Common/FilePreviewDialog"; import { StateInterface } from "@/components/Files/FileUpload"; -import TextAreaFormField from "@/components/Form/FormFields/TextAreaFormField"; import TextFormField from "@/components/Form/FormFields/TextFormField"; import { FileUploadModel } from "@/components/Patient/models"; @@ -290,22 +294,29 @@ export default function useFileManager( className="mx-2 my-4 flex w-full flex-col" >
- + }} + /> + +