diff --git a/__test__/components/DateTimeField.test.tsx b/__test__/components/DateTimeField.test.tsx index acb09b9..ac9a8fb 100644 --- a/__test__/components/DateTimeField.test.tsx +++ b/__test__/components/DateTimeField.test.tsx @@ -279,4 +279,65 @@ describe("DateTimeFields", () => { "dateTimeFields.endTime" ); }); + + describe("DateTimeFields - Drag and Drop Display Logic", () => { + // Test 1.1: Display 2 fields when drag from allday slot (multiple days) + it("displays only 2 date fields when allday=true and multiple days", async () => { + await renderField({ + allday: true, + hasEndDateChanged: false, + startDate: "2025-07-18", + endDate: "2025-07-20", + showEndDate: true, + showMore: false, + }); + + expect(screen.getByTestId("start-date-input")).toBeInTheDocument(); + expect(screen.getByTestId("end-date-input")).toBeInTheDocument(); + expect(screen.queryByTestId("start-time-input")).not.toBeInTheDocument(); + expect(screen.queryByTestId("end-time-input")).not.toBeInTheDocument(); + }); + + // Test 1.2: Display 4 fields when drag from week view (multiple days) + it("displays 4 fields when allday=false, hasEndDateChanged=true, and multiple days", async () => { + await renderField({ + allday: false, + hasEndDateChanged: true, + startDate: "2025-07-18", + endDate: "2025-07-20", + startTime: "09:00", + endTime: "10:00", + showEndDate: true, + showMore: false, + }); + + expect(screen.getByTestId("start-date-input")).toBeInTheDocument(); + expect(screen.getByTestId("start-time-input")).toBeInTheDocument(); + expect(screen.getByTestId("end-date-input")).toBeInTheDocument(); + expect(screen.getByTestId("end-time-input")).toBeInTheDocument(); + }); + + // Test 1.3: Display single date + time fields + it("displays single date field with time fields for single day event", async () => { + await renderField({ + allday: false, + hasEndDateChanged: false, + startDate: "2025-07-18", + endDate: "2025-07-18", + startTime: "09:00", + endTime: "10:00", + showEndDate: false, + showMore: false, + }); + + const startDateInput = screen.getByTestId("start-date-input"); + expect(startDateInput).toHaveAttribute( + "aria-label", + "dateTimeFields.date" + ); + expect(screen.getByTestId("start-time-input")).toBeInTheDocument(); + expect(screen.getByTestId("end-time-input")).toBeInTheDocument(); + expect(screen.queryByTestId("end-date-input")).not.toBeInTheDocument(); + }); + }); }); diff --git a/__test__/features/Events/EventModal.test.tsx b/__test__/features/Events/EventModal.test.tsx index d9a83bd..543ba6a 100644 --- a/__test__/features/Events/EventModal.test.tsx +++ b/__test__/features/Events/EventModal.test.tsx @@ -344,4 +344,126 @@ describe("EventPopover", () => { ) ); }); + + describe("EventModal - Drag and Drop Scenarios", () => { + // Test 2.1: Drag from allday slot (single day) + it("sets allday=true when drag from allday slot (single day)", async () => { + const selectedRange = { + startStr: "2025-07-18", + endStr: "2025-07-19", + start: new Date("2025-07-18"), + end: new Date("2025-07-19"), + allDay: true, + } as unknown as DateSelectArg; + + renderPopover(selectedRange); + + const allDayCheckbox = screen.getByLabelText("event.form.allDay"); + await waitFor(() => { + expect(allDayCheckbox).toBeChecked(); + }); + }); + + // Test 2.2: Drag from allday slot (multiple days) + it("sets allday=true and shows 2 date fields when drag from allday slot (multiple days)", async () => { + const selectedRange = { + startStr: "2025-07-18", + endStr: "2025-07-21", + start: new Date("2025-07-18"), + end: new Date("2025-07-21"), + allDay: true, + } as unknown as DateSelectArg; + + renderPopover(selectedRange); + + const allDayCheckbox = screen.getByLabelText("event.form.allDay"); + await waitFor(() => { + expect(allDayCheckbox).toBeChecked(); + }); + + // Verify only date fields are shown + await waitFor(() => { + expect(screen.getByTestId("start-date-input")).toBeInTheDocument(); + expect(screen.getByTestId("end-date-input")).toBeInTheDocument(); + expect( + screen.queryByTestId("start-time-input") + ).not.toBeInTheDocument(); + expect(screen.queryByTestId("end-time-input")).not.toBeInTheDocument(); + }); + }); + + // Test 2.3: Drag from week view (single day) + it("keeps allday=false when drag from week view (single day)", async () => { + const selectedRange = { + startStr: "2025-07-18T09:00", + endStr: "2025-07-18T10:00", + start: new Date("2025-07-18T09:00"), + end: new Date("2025-07-18T10:00"), + allDay: false, + } as unknown as DateSelectArg; + + renderPopover(selectedRange); + + const allDayCheckbox = screen.getByLabelText("event.form.allDay"); + await waitFor(() => { + expect(allDayCheckbox).not.toBeChecked(); + }); + + // Verify time fields are shown + await waitFor(() => { + expect(screen.getByTestId("start-time-input")).toBeInTheDocument(); + expect(screen.getByTestId("end-time-input")).toBeInTheDocument(); + }); + }); + + // Test 2.4: Drag from week view (multiple days) - CRITICAL TEST + it("keeps allday=false and shows 4 fields when drag from week view (multiple days)", async () => { + const selectedRange = { + startStr: "2025-07-18T09:00", + endStr: "2025-07-20T10:00", + start: new Date("2025-07-18T09:00"), + end: new Date("2025-07-20T10:00"), + allDay: false, + } as unknown as DateSelectArg; + + renderPopover(selectedRange); + + const allDayCheckbox = screen.getByLabelText("event.form.allDay"); + await waitFor(() => { + expect(allDayCheckbox).not.toBeChecked(); // CRITICAL: should NOT be checked + }); + + // Verify all 4 fields are shown + await waitFor(() => { + expect(screen.getByTestId("start-date-input")).toBeInTheDocument(); + expect(screen.getByTestId("start-time-input")).toBeInTheDocument(); + expect(screen.getByTestId("end-date-input")).toBeInTheDocument(); + expect(screen.getByTestId("end-time-input")).toBeInTheDocument(); + }); + }); + + // Test 2.5: Drag from week view (multiple days) - fallback path + it("handles drag from week view (multiple days) with Date objects only", async () => { + const selectedRange = { + start: new Date("2025-07-18T09:00"), + end: new Date("2025-07-20T10:00"), + allDay: false, + } as unknown as DateSelectArg; + + renderPopover(selectedRange); + + const allDayCheckbox = screen.getByLabelText("event.form.allDay"); + await waitFor(() => { + expect(allDayCheckbox).not.toBeChecked(); + }); + + // Verify all 4 fields are shown + await waitFor(() => { + expect(screen.getByTestId("start-date-input")).toBeInTheDocument(); + expect(screen.getByTestId("start-time-input")).toBeInTheDocument(); + expect(screen.getByTestId("end-date-input")).toBeInTheDocument(); + expect(screen.getByTestId("end-time-input")).toBeInTheDocument(); + }); + }); + }); }); diff --git a/src/components/Event/components/DateTimeFields.tsx b/src/components/Event/components/DateTimeFields.tsx index 3653fbf..2fbb814 100644 --- a/src/components/Event/components/DateTimeFields.tsx +++ b/src/components/Event/components/DateTimeFields.tsx @@ -104,10 +104,26 @@ export const DateTimeFields: React.FC = ({ }); }, [startDate, endDate, startTime, endTime, getCurrentDuration]); + const spansMultipleDays = React.useMemo(() => { + return startDate !== endDate; + }, [startDate, endDate]); + const isExpanded = showMore; const shouldShowEndDateNormal = allday || showEndDate; - const showSingleDateField = !isExpanded && !shouldShowEndDateNormal; - const showFourFieldsNormal = !isExpanded && showEndDate && !allday; + // Show full 4 fields when: + // 1. Non-allday with hasEndDateChanged + // 2. Multiple days with hasEndDateChanged (supports drag from week/month view grid with allday checked) + // 3. Multiple days without allday (original behavior) + const shouldShowFullFieldsInNormal = + (!allday && hasEndDateChanged) || + (hasEndDateChanged && spansMultipleDays) || + (spansMultipleDays && !allday); + const showSingleDateField = + !isExpanded && !shouldShowEndDateNormal && !shouldShowFullFieldsInNormal; + + // When shouldShowFullFieldsInNormal is true, show time fields even if allday is true + // This supports the case: drag from week/month view grid with multiple days + const shouldShowTimeFields = !allday || shouldShowFullFieldsInNormal; const startDateLabel = showSingleDateField ? t("dateTimeFields.date") @@ -328,7 +344,7 @@ export const DateTimeFields: React.FC = ({ flexDirection="column" sx={{ maxWidth: showMore ? "calc(100% - 145px)" : "100%" }} > - {isExpanded || showFourFieldsNormal ? ( + {isExpanded || shouldShowFullFieldsInNormal ? ( <> @@ -351,7 +367,7 @@ export const DateTimeFields: React.FC = ({ }} /> - {!allday && ( + {shouldShowTimeFields && ( = ({ }} /> - {!allday && ( + {shouldShowTimeFields && (