From 2803c3f8ad345104cc52e1f35f7c6f0e3e867d77 Mon Sep 17 00:00:00 2001 From: Gibson Han Date: Mon, 1 Apr 2024 13:27:58 -0700 Subject: [PATCH 1/6] ui: implementation of redesign date-range-picker --- .../components/calendar/option-data/months.ts | 15 ++ .../date-picker/date-picker-calendar.tsx | 191 +++++++++++++++++ .../date-picker/date-picker-suggestions.tsx | 25 +++ .../date-picker/date-picker.stories.tsx | 18 ++ .../components/date-picker/date-picker.tsx | 194 ++++++++++++++++++ .../ui/src/components/date-picker/index.ts | 1 + .../utils/create-two-month-calendar.ts | 40 ++++ 7 files changed, 484 insertions(+) create mode 100644 packages/ui/src/components/date-picker/date-picker-calendar.tsx create mode 100644 packages/ui/src/components/date-picker/date-picker-suggestions.tsx create mode 100644 packages/ui/src/components/date-picker/date-picker.stories.tsx create mode 100644 packages/ui/src/components/date-picker/date-picker.tsx create mode 100644 packages/ui/src/components/date-picker/index.ts create mode 100644 packages/ui/src/components/date-picker/utils/create-two-month-calendar.ts diff --git a/packages/ui/src/components/calendar/option-data/months.ts b/packages/ui/src/components/calendar/option-data/months.ts index 3c0dd3b4..8956e42e 100644 --- a/packages/ui/src/components/calendar/option-data/months.ts +++ b/packages/ui/src/components/calendar/option-data/months.ts @@ -5,6 +5,21 @@ export type MONTHS_OPTION = { text: string; }; +export const MONTH_NAMES: string[] = [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December", +]; + export const MONTHS_RANGE: MONTHS_OPTION[] = [ { value: 0, text: "January" }, { value: 1, text: "February" }, diff --git a/packages/ui/src/components/date-picker/date-picker-calendar.tsx b/packages/ui/src/components/date-picker/date-picker-calendar.tsx new file mode 100644 index 00000000..5c02b8e4 --- /dev/null +++ b/packages/ui/src/components/date-picker/date-picker-calendar.tsx @@ -0,0 +1,191 @@ +import { useState } from "react"; +import ArrowForwardIosIcon from "@mui/icons-material/ArrowForwardIos"; +import ArrowBackIosNewIcon from "@mui/icons-material/ArrowBackIosNew"; +import { isEmpty } from "lodash"; + +import { Month, MONTH_NAMES } from "../calendar/option-data/months"; +import { Year } from "../calendar/option-data/years"; +import { CalendarDate } from "../calendar/utils/create-calendar"; +import { twMerge } from "tailwind-merge"; +import { createTwoMonthCalendar, CALENDAR_MONTH } from "./utils/create-two-month-calendar"; +import { isEqual } from "../calendar/utils/is-equal"; +import { addMonths } from "date-fns"; + +interface DatePickerCalendarProps { + initDate?: Date; + endDate: Date | null; + startDate: Date | null; + setEndDate: (arg0: Date | null) => void; + setStartDate: (arg0: Date | null) => void; + handleReset: () => void; +} + +export default function DatePickerCalendar(props: DatePickerCalendarProps) { + const { initDate = new Date(), startDate, endDate, setStartDate, setEndDate } = props; + + const [date, setDate] = useState(initDate); + const [month, setMonth] = useState(initDate.getMonth() as Month); + const [year, setYear] = useState(initDate.getFullYear()); + const [firstMonth, secondMonth] = createTwoMonthCalendar(year as Year, month); + + function handleUpdateMonth(type: "prev" | "next") { + const modify = type === "prev" ? -1 : 1; + const newDate = addMonths(new Date(date), modify); + + setMonth(newDate.getMonth() as Month); + setYear(newDate.getFullYear() as Year); + setDate(newDate); + } + + const handleSelected = ({ day, month, year }: CalendarDate) => { + const newDate = new Date(year, month, day); + + if (!startDate && !endDate) { + setStartDate(newDate); + } else if (startDate && !endDate) { + setEndDate(newDate); + } else { + /** + * This handles the edge cases when new End date comes before start date + * Note: state is represent as date, but in system refer to CalendarDate interface + * EG: + * t-0 state: + * start : July 16, 1969 + * end : July 24, 1969 + * + * t-1 state: + * new End : July 15, 1969 selected + * + * t-final state: + * start : July 15, 1969 + * end : null + */ + + if (startDate && newDate < startDate) { + setStartDate(newDate); + setEndDate(null); + } else { + setEndDate(newDate); + } + } + }; + + return ( +
+ {/**Calendar Month Nav */} +
+
+ +
+ {MONTH_NAMES[month]} + {year} +
+
+ +
+
+ {MONTH_NAMES[(month + 1) % 12]} + {(month + 1) % 12 === 0 ? year + 1 : year} +
+ +
+
+ + {/** Actual Calendars */} +
+
+ + + + {["M", "T", "W", "T", "F", "S", "S"].map((ele: string, index: number) => ( + + ))} + + + + {firstMonth.map((week: CALENDAR_MONTH[], weekIdx: number) => ( + + {week.map((ele: CALENDAR_MONTH, colIdx: number) => { + if (isEmpty(ele)) { + return + ); + })} + + ))} + +
+ {ele} +
; + } + const { day, month, year } = ele as CalendarDate; + const key = `first-month-${month}/${day}/${year}`; + const isSelected = isEqual(ele as CalendarDate, startDate) || isEqual(ele as CalendarDate, endDate); + const isCurrDate = isEqual(ele as CalendarDate, initDate); + + return ( + handleSelected(ele as CalendarDate)} + className={twMerge( + "h-8 w-8 text-center text-xs font-normal leading-[18.8px]", + isCurrDate && "inline-flex items-center justify-center rounded-full border-[1px]", + !isSelected && "rounded-full hover:bg-blue-200", + isSelected && "text-white-100 rounded-full bg-blue-500", + )}> + {day} +
+
+
+ + + + {["M", "T", "W", "T", "F", "S", "S"].map((ele: string, index: number) => ( + + ))} + + + + {secondMonth.map((week: CALENDAR_MONTH[], weekIdx: number) => ( + + {week.map((ele: CALENDAR_MONTH, colIdx: number) => { + if (isEmpty(ele)) { + return + ); + })} + + ))} + +
+ {ele} +
; + } + const { day, month, year } = ele as CalendarDate; + const key = `second-month-${month}/${day}/${year}`; + const isSelected = isEqual(ele as CalendarDate, startDate) || isEqual(ele as CalendarDate, endDate); + const isCurrDate = isEqual(ele as CalendarDate, initDate); + + return ( + handleSelected(ele as CalendarDate)} + className={twMerge( + "h-8 w-8 text-center text-xs font-normal leading-[18.8px]", + isCurrDate && "inline-flex items-center justify-center rounded-full border-[1px]", + !isSelected && "rounded-full hover:bg-blue-200", + isSelected && "text-white-100 rounded-full bg-blue-500", + )}> + {day} +
+
+
+
+ ); +} diff --git a/packages/ui/src/components/date-picker/date-picker-suggestions.tsx b/packages/ui/src/components/date-picker/date-picker-suggestions.tsx new file mode 100644 index 00000000..d7f76137 --- /dev/null +++ b/packages/ui/src/components/date-picker/date-picker-suggestions.tsx @@ -0,0 +1,25 @@ +import _ from "lodash"; +import RadioGroup from "../radio-group"; + +interface DatePickerSuggestion { + onSuggestionChange: (arg0: string) => void; +} + +export enum RelativeDatePresets { + "YEARS_1" = "Past 1 Year", + "YTD" = "Year to Date", + "MONTHS_3" = "3 Months", + "MONTHS_1" = "1 Month", +} + +const CITATION_DATE_PRESETS = _.map(RelativeDatePresets, (value) => value); + +export default function DatePickerSuggestions(props: DatePickerSuggestion) { + const { onSuggestionChange } = props; + + return ( +
+ +
+ ); +} diff --git a/packages/ui/src/components/date-picker/date-picker.stories.tsx b/packages/ui/src/components/date-picker/date-picker.stories.tsx new file mode 100644 index 00000000..918edae0 --- /dev/null +++ b/packages/ui/src/components/date-picker/date-picker.stories.tsx @@ -0,0 +1,18 @@ +import { Meta, StoryObj } from "@storybook/react"; +import DatePicker from "./date-picker"; + +const meta: Meta = { + title: "Components/Date Picker", + component: DatePicker, +}; + +type DatePickerStory = StoryObj; + +export const Default: DatePickerStory = { + render: (args) => , + args: { + //todo + }, +}; + +export default meta; diff --git a/packages/ui/src/components/date-picker/date-picker.tsx b/packages/ui/src/components/date-picker/date-picker.tsx new file mode 100644 index 00000000..d30087ea --- /dev/null +++ b/packages/ui/src/components/date-picker/date-picker.tsx @@ -0,0 +1,194 @@ +import { useState } from "react"; +import { Modal, ModalContent, ModalTrigger } from "../modal"; + +import ChevronRightIcon from "@mui/icons-material/ChevronRight"; +import DateRangeIcon from "@mui/icons-material/DateRange"; +import { addMonths, addYears, startOfYear } from "date-fns"; +import { twMerge } from "tailwind-merge"; + +import Button, { ButtonVariant } from "../button"; +import DatePickerSuggestions, { RelativeDatePresets } from "./date-picker-suggestions"; +import DatePickerCalendar from "./date-picker-calendar"; +import Input from "../input"; +import { formatToMiddleEndian } from "@lucky-parking/utilities/dist/date"; + +interface DatePickerProps { + onDateRangeValueChange?: (arg0: { [key: string]: Date }) => void | null; +} + +type selectedCalendar = "exact" | "suggestions"; + +export default function DatePicker(props: DatePickerProps) { + const { onDateRangeValueChange = null } = props; + + const [isCalendarVisible, setCalendarVisible] = useState(false); + const [selected, setSelected] = useState("exact"); + const [selectedDates, setSelectedDates] = useState<{ [key: string]: Date | null }>({ + start: null, + end: null, + }); + const [startDate, setStartDate] = useState(null); + const [endDate, setEndDate] = useState(null); + + const handleApply = () => { + if (startDate && endDate) { + const payload = { + start: startDate, + end: endDate, + }; + setSelectedDates(payload); + onDateRangeValueChange && onDateRangeValueChange(payload); + } + + setCalendarVisible(false); + }; + + const handleSuggestionChange = (value: string) => { + const today = new Date(); + + switch (value) { + case RelativeDatePresets.YEARS_1: { + const oneYearAgo = addYears(today, -1); + setStartDate(oneYearAgo); + setEndDate(today); + break; + } + + case RelativeDatePresets.YTD: { + const firstDateOfTheYear = startOfYear(today); + setStartDate(firstDateOfTheYear); + setEndDate(today); + break; + } + + case RelativeDatePresets.MONTHS_1: { + const oneMonthFromToday = addMonths(today, 1); + setStartDate(today); + setEndDate(oneMonthFromToday); + break; + } + + case RelativeDatePresets.MONTHS_3: { + const threeMonthFromToday = addMonths(today, 3); + setStartDate(today); + setEndDate(threeMonthFromToday); + break; + } + + default: + console.log("oopies mom's spaghetti o something went wrong!"); + } + }; + + const handleReset = () => { + setStartDate(null); + setEndDate(null); + }; + + return ( +
+ + +
setCalendarVisible((prevState) => !prevState)}> +
+ +
+ {(selectedDates.start && formatToMiddleEndian(selectedDates.start)) || "start date"} +
+
+ +
+ +
+ {(selectedDates.end && formatToMiddleEndian(selectedDates.end)) || "end date"} +
+
+
+
+ +
+ + +
+ +
+ +
+ {selected === "exact" ? ( + + ) : ( + + )} +
+ +
+
+ Start Date + +
+ +
+ End Date + +
+
+ +
+ + {/** Call to Action */} +
+ + +
+ + +
+
+ + +
+ ); +} diff --git a/packages/ui/src/components/date-picker/index.ts b/packages/ui/src/components/date-picker/index.ts new file mode 100644 index 00000000..bc2a5f1e --- /dev/null +++ b/packages/ui/src/components/date-picker/index.ts @@ -0,0 +1 @@ +export { default } from "./date-picker.tsx"; diff --git a/packages/ui/src/components/date-picker/utils/create-two-month-calendar.ts b/packages/ui/src/components/date-picker/utils/create-two-month-calendar.ts new file mode 100644 index 00000000..e1387acb --- /dev/null +++ b/packages/ui/src/components/date-picker/utils/create-two-month-calendar.ts @@ -0,0 +1,40 @@ +import { CalendarDate } from "@/components/calendar/utils/create-calendar"; + +export type CALENDAR_MONTH = CalendarDate | object | null; + +export function createTwoMonthCalendar(year: number, month: number) { + const firstMonth = createCalendarMonth(year, month); + const nextMonth = (month + 1) % 12; + const secondMonth = createCalendarMonth(year, nextMonth); + + return [firstMonth, secondMonth]; +} + +export function createCalendarMonth(year: number, month: number) { + const startDay = 1; + const currentDate = new Date(year, month, 1); + + currentDate.setDate(currentDate.getDate() - ((currentDate.getDay() - startDay + 7) % 7)); + + // Initialize a two-dimensional array to hold the calendar + const calendar: CALENDAR_MONTH[][] = []; + // Populate the calendar with dates + for (let row = 0; row < 5; row++) { + calendar[row] = []; + for (let col = 0; col < 7; col++) { + //append days for current month and next month + + calendar[row][col] = + currentDate.getMonth() === month + ? { + day: currentDate.getDate(), + month: currentDate.getMonth(), + year: currentDate.getFullYear(), + } + : {}; + + currentDate.setDate(currentDate.getDate() + 1); + } + } + return calendar; +} From 397515de089c33ec3ac6f539689deabbe1a11b4a Mon Sep 17 00:00:00 2001 From: Gibson Han Date: Mon, 1 Apr 2024 13:28:38 -0700 Subject: [PATCH 2/6] ui: add test to redesigned date-range-picker component --- .../date-picker/date-picker-calendar.test.tsx | 91 +++++++++++++++++++ .../date-picker-suggestions.test.tsx | 17 ++++ .../date-picker/date-picker.test.tsx | 74 +++++++++++++++ 3 files changed, 182 insertions(+) create mode 100644 packages/ui/src/components/date-picker/date-picker-calendar.test.tsx create mode 100644 packages/ui/src/components/date-picker/date-picker-suggestions.test.tsx create mode 100644 packages/ui/src/components/date-picker/date-picker.test.tsx diff --git a/packages/ui/src/components/date-picker/date-picker-calendar.test.tsx b/packages/ui/src/components/date-picker/date-picker-calendar.test.tsx new file mode 100644 index 00000000..4c12a39f --- /dev/null +++ b/packages/ui/src/components/date-picker/date-picker-calendar.test.tsx @@ -0,0 +1,91 @@ +import "@testing-library/jest-dom"; +import { render, screen } from "@testing-library/react"; +import DatePickerCalendar from "./date-picker-calendar"; +import { MONTH_NAMES } from "../calendar/option-data/months"; +import userEvent from "@testing-library/user-event"; + +describe("Date Range 2 month Calendar", () => { + const todayDate = new Date(); + + beforeEach(async () => { + render( + {}} + setEndDate={() => {}} + handleReset={() => {}} + />, + ); + }); + + test("renders Back Arrow Icon", () => { + expect(screen.getByTestId("ArrowBackIosNewIcon")).toBeInTheDocument(); + }); + + test("renders Forward Arrow Icon", () => { + expect(screen.getByTestId("ArrowForwardIosIcon")).toBeInTheDocument(); + }); + + test("renders current month and next month", () => { + const currMonthIdx = todayDate.getMonth(); + const nextMonthIdx = (currMonthIdx + 1) % 12; + + expect(screen.getByText(MONTH_NAMES[currMonthIdx])).toBeInTheDocument(); + expect(screen.getByText(MONTH_NAMES[nextMonthIdx])).toBeInTheDocument(); + }); + + test("render current month's year and next month's year", () => { + const currMonthIdx = todayDate.getMonth(); + const nextMonthIdx = (currMonthIdx + 1) % 12; + + expect(screen.getByText(MONTH_NAMES[currMonthIdx])).toBeInTheDocument(); + expect(screen.getByText(MONTH_NAMES[nextMonthIdx])).toBeInTheDocument(); + }); +}); + +describe("Date Range Call to Action ", () => { + const date = new Date("11-25-2024"); + const user = userEvent.setup(); + beforeEach(async () => { + render( + {}} + setEndDate={() => {}} + handleReset={() => {}} + />, + ); + }); + + test("renders current month and next month", () => { + expect(screen.getByText("November")).toBeInTheDocument(); + expect(screen.getByText("December")).toBeInTheDocument(); + expect(screen.getByText((_, ele) => ele?.textContent === "2024")).toBeInTheDocument(); + }); + + test("render December 2024 and January 2025 when Forward Arrow is pressed", async () => { + const nextMonthButton = screen.getByRole("button", { name: /next-months/i }); + await user.click(nextMonthButton); + + expect(screen.getByText("December")).toBeInTheDocument(); + expect(screen.getByText("2024")).toBeInTheDocument(); + + expect(screen.getByText("January")).toBeInTheDocument(); + expect(screen.getByText("2025")).toBeInTheDocument(); + }); + + test("render October 2024 and November 2024 when Forward Arrow is pressed", async () => { + const nextMonthButton = screen.getByRole("button", { name: /prev-months/i }); + await user.click(nextMonthButton); + + expect(screen.getByText("October")).toBeInTheDocument(); + expect(screen.getByText("November")).toBeInTheDocument(); + expect(screen.getByText((_, ele) => ele?.textContent === "2024")).toBeInTheDocument(); + }); +}); diff --git a/packages/ui/src/components/date-picker/date-picker-suggestions.test.tsx b/packages/ui/src/components/date-picker/date-picker-suggestions.test.tsx new file mode 100644 index 00000000..17c45865 --- /dev/null +++ b/packages/ui/src/components/date-picker/date-picker-suggestions.test.tsx @@ -0,0 +1,17 @@ +import "@testing-library/jest-dom"; +import { render, screen } from "@testing-library/react"; +import DatePickerSuggestions from "./date-picker-suggestions"; + +describe("Date Input", () => { + beforeEach(() => { + render( console.log(value)} />); + }); + + test("renders radio group and all it's options", () => { + expect(screen.getByLabelText("Past 1 Year")); + expect(screen.getByLabelText("Year to Date")); + expect(screen.getByLabelText("3 Months")); + expect(screen.getByLabelText("1 Month")); + expect(screen.queryByLabelText("It's over 9000")).not.toBeInTheDocument(); + }); +}); diff --git a/packages/ui/src/components/date-picker/date-picker.test.tsx b/packages/ui/src/components/date-picker/date-picker.test.tsx new file mode 100644 index 00000000..67cd0f2c --- /dev/null +++ b/packages/ui/src/components/date-picker/date-picker.test.tsx @@ -0,0 +1,74 @@ +import "@testing-library/jest-dom"; +import { render, screen } from "@testing-library/react"; +import DatePicker from "./date-picker"; +import userEvent from "@testing-library/user-event"; + +describe("Date Input", () => { + beforeEach(() => { + render( + console.log(JSON.stringify(value))} />, + ); + }); + + test("renders DateRangeIcon", () => { + expect(screen.getByTestId("DateRangeIcon")).toBeInTheDocument(); + }); + + test("renders start date text", () => { + expect(screen.getByText("start date")).toBeInTheDocument(); + }); + -test("renders ChevronRightIcon", () => { + expect(screen.getByTestId("ChevronRightIcon")).toBeInTheDocument(); + }); + + test("renders end date text", () => { + expect(screen.getByText("end date")).toBeInTheDocument(); + }); +}); + +describe("Date Input's Modal", () => { + const user = userEvent.setup(); + beforeEach(async () => { + render( + console.log(JSON.stringify(value))} + />, + ); + + const dateRangeModalTrigger = screen.getByLabelText("open-date-range-modal"); + await user.click(dateRangeModalTrigger); + }); + + test("renders date-range-picker trigger button", () => { + expect(screen.getByLabelText("open-date-range-modal")).toBeInTheDocument(); + }); + + test("renders Exact button", async () => { + expect(screen.getByRole("button", { name: /Exact/i })).toBeInTheDocument(); + }); + + test("renders Suggestions button", () => { + expect(screen.getByRole("button", { name: /Suggestions/i })).toBeInTheDocument(); + }); + + test("renders Reset button", () => { + expect(screen.getByRole("button", { name: /reset/i })).toBeInTheDocument(); + }); + + test("renders Clear button", () => { + expect(screen.getByRole("button", { name: /cancel/i })).toBeInTheDocument(); + }); + + test("renders Apply button", () => { + expect(screen.getByRole("button", { name: /apply/i })).toBeInTheDocument(); + }); + + test("renders Start Date Label Text", () => { + expect(screen.getByText("Start Date")).toBeInTheDocument(); + }); + + test("renders End Date Label Text", () => { + expect(screen.getByText("End Date")).toBeInTheDocument(); + }); +}); From 62f2a168208ff40844a710d93de4e61b3978786f Mon Sep 17 00:00:00 2001 From: Gibson Han Date: Mon, 8 Apr 2024 15:10:46 -0700 Subject: [PATCH 3/6] fix ui: adjust calendar to start on sunday --- .../ui/src/components/date-picker/date-picker-calendar.tsx | 4 ++-- .../components/date-picker/utils/create-two-month-calendar.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/ui/src/components/date-picker/date-picker-calendar.tsx b/packages/ui/src/components/date-picker/date-picker-calendar.tsx index 5c02b8e4..3c884e40 100644 --- a/packages/ui/src/components/date-picker/date-picker-calendar.tsx +++ b/packages/ui/src/components/date-picker/date-picker-calendar.tsx @@ -101,7 +101,7 @@ export default function DatePickerCalendar(props: DatePickerCalendarProps) { - {["M", "T", "W", "T", "F", "S", "S"].map((ele: string, index: number) => ( + {["S", "M", "T", "W", "T", "F", "S"].map((ele: string, index: number) => (
@@ -145,7 +145,7 @@ export default function DatePickerCalendar(props: DatePickerCalendarProps) { - {["M", "T", "W", "T", "F", "S", "S"].map((ele: string, index: number) => ( + {["S", "M", "T", "W", "T", "F", "S"].map((ele: string, index: number) => ( + ); + })} + + ))} + +
diff --git a/packages/ui/src/components/date-picker/utils/create-two-month-calendar.ts b/packages/ui/src/components/date-picker/utils/create-two-month-calendar.ts index e1387acb..1f9fd0f9 100644 --- a/packages/ui/src/components/date-picker/utils/create-two-month-calendar.ts +++ b/packages/ui/src/components/date-picker/utils/create-two-month-calendar.ts @@ -11,7 +11,7 @@ export function createTwoMonthCalendar(year: number, month: number) { } export function createCalendarMonth(year: number, month: number) { - const startDay = 1; + const startDay = 0; const currentDate = new Date(year, month, 1); currentDate.setDate(currentDate.getDate() - ((currentDate.getDay() - startDay + 7) % 7)); From 4a8dcb569c199af702d45a4ac8c1628e9fdf1a65 Mon Sep 17 00:00:00 2001 From: Gibson Han Date: Mon, 8 Apr 2024 15:44:08 -0700 Subject: [PATCH 4/6] fix ui: center calendar titles --- .../date-picker/date-picker-calendar.tsx | 217 +++++++++--------- 1 file changed, 113 insertions(+), 104 deletions(-) diff --git a/packages/ui/src/components/date-picker/date-picker-calendar.tsx b/packages/ui/src/components/date-picker/date-picker-calendar.tsx index 3c884e40..25062175 100644 --- a/packages/ui/src/components/date-picker/date-picker-calendar.tsx +++ b/packages/ui/src/components/date-picker/date-picker-calendar.tsx @@ -72,118 +72,127 @@ export default function DatePickerCalendar(props: DatePickerCalendarProps) { return (
- {/**Calendar Month Nav */} -
-
- -
- {MONTH_NAMES[month]} - {year} +
+
+ {/*Left Calendar Nav*/} +
+ +
+ {MONTH_NAMES[month]} + {year} +
+
-
-
-
- {MONTH_NAMES[(month + 1) % 12]} - {(month + 1) % 12 === 0 ? year + 1 : year} + {/*Left Calendar*/} +
+ + + + {["S", "M", "T", "W", "T", "F", "S"].map((ele: string, index: number) => ( + + ))} + + + + {firstMonth.map((week: CALENDAR_MONTH[], weekIdx: number) => ( + + {week.map((ele: CALENDAR_MONTH, colIdx: number) => { + if (isEmpty(ele)) { + return + ); + })} + + ))} + +
+ {ele} +
; + } + const { day, month, year } = ele as CalendarDate; + const key = `first-month-${month}/${day}/${year}`; + const isSelected = + isEqual(ele as CalendarDate, startDate) || isEqual(ele as CalendarDate, endDate); + const isCurrDate = isEqual(ele as CalendarDate, initDate); + + return ( + handleSelected(ele as CalendarDate)} + className={twMerge( + "h-8 w-8 text-center text-xs font-normal leading-[18.8px]", + isCurrDate && "inline-flex items-center justify-center rounded-full border-[1px]", + !isSelected && "rounded-full hover:bg-blue-200", + isSelected && "text-white-100 rounded-full bg-blue-500", + )}> + {day} +
-
-
- {/** Actual Calendars */} -
-
- - - - {["S", "M", "T", "W", "T", "F", "S"].map((ele: string, index: number) => ( - - ))} - - - - {firstMonth.map((week: CALENDAR_MONTH[], weekIdx: number) => ( - - {week.map((ele: CALENDAR_MONTH, colIdx: number) => { - if (isEmpty(ele)) { - return - ); - })} + {/**Right Calendar*/} +
+
- {ele} -
; - } - const { day, month, year } = ele as CalendarDate; - const key = `first-month-${month}/${day}/${year}`; - const isSelected = isEqual(ele as CalendarDate, startDate) || isEqual(ele as CalendarDate, endDate); - const isCurrDate = isEqual(ele as CalendarDate, initDate); +
+ {/**Right Calendar Nav */} +
+ +
+ {MONTH_NAMES[(month + 1) % 12]} + {(month + 1) % 12 === 0 ? year + 1 : year} +
+ +
- return ( -
handleSelected(ele as CalendarDate)} - className={twMerge( - "h-8 w-8 text-center text-xs font-normal leading-[18.8px]", - isCurrDate && "inline-flex items-center justify-center rounded-full border-[1px]", - !isSelected && "rounded-full hover:bg-blue-200", - isSelected && "text-white-100 rounded-full bg-blue-500", - )}> - {day} -
+ + + {["S", "M", "T", "W", "T", "F", "S"].map((ele: string, index: number) => ( + + ))} - ))} - -
+ {ele} +
-
-
- - - - {["S", "M", "T", "W", "T", "F", "S"].map((ele: string, index: number) => ( - - ))} - - - - {secondMonth.map((week: CALENDAR_MONTH[], weekIdx: number) => ( - - {week.map((ele: CALENDAR_MONTH, colIdx: number) => { - if (isEmpty(ele)) { - return + {secondMonth.map((week: CALENDAR_MONTH[], weekIdx: number) => ( + + {week.map((ele: CALENDAR_MONTH, colIdx: number) => { + if (isEmpty(ele)) { + return - ); - })} - - ))} - -
- {ele} -
; - } - const { day, month, year } = ele as CalendarDate; - const key = `second-month-${month}/${day}/${year}`; - const isSelected = isEqual(ele as CalendarDate, startDate) || isEqual(ele as CalendarDate, endDate); - const isCurrDate = isEqual(ele as CalendarDate, initDate); + +
; + } + const { day, month, year } = ele as CalendarDate; + const key = `second-month-${month}/${day}/${year}`; + const isSelected = + isEqual(ele as CalendarDate, startDate) || isEqual(ele as CalendarDate, endDate); + const isCurrDate = isEqual(ele as CalendarDate, initDate); - return ( - handleSelected(ele as CalendarDate)} - className={twMerge( - "h-8 w-8 text-center text-xs font-normal leading-[18.8px]", - isCurrDate && "inline-flex items-center justify-center rounded-full border-[1px]", - !isSelected && "rounded-full hover:bg-blue-200", - isSelected && "text-white-100 rounded-full bg-blue-500", - )}> - {day} -
+ return ( +
handleSelected(ele as CalendarDate)} + className={twMerge( + "h-8 w-8 text-center text-xs font-normal leading-[18.8px]", + isCurrDate && "inline-flex items-center justify-center rounded-full border-[1px]", + !isSelected && "rounded-full hover:bg-blue-200", + isSelected && "text-white-100 rounded-full bg-blue-500", + )}> + {day} +
+ From 63d8ae5ae545fbf8e6e5a7d05e8056d643c70e7b Mon Sep 17 00:00:00 2001 From: Gibson Han Date: Mon, 8 Apr 2024 15:58:36 -0700 Subject: [PATCH 5/6] fix ui: adjust suggested relative dates --- .../date-picker/date-picker-suggestions.tsx | 4 ++-- .../components/date-picker/date-picker.tsx | 20 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/ui/src/components/date-picker/date-picker-suggestions.tsx b/packages/ui/src/components/date-picker/date-picker-suggestions.tsx index d7f76137..e9a6ae28 100644 --- a/packages/ui/src/components/date-picker/date-picker-suggestions.tsx +++ b/packages/ui/src/components/date-picker/date-picker-suggestions.tsx @@ -7,9 +7,9 @@ interface DatePickerSuggestion { export enum RelativeDatePresets { "YEARS_1" = "Past 1 Year", + "MONTHS_3" = "Past 3 Months", + "MONTHS_1" = "Past 1 Month", "YTD" = "Year to Date", - "MONTHS_3" = "3 Months", - "MONTHS_1" = "1 Month", } const CITATION_DATE_PRESETS = _.map(RelativeDatePresets, (value) => value); diff --git a/packages/ui/src/components/date-picker/date-picker.tsx b/packages/ui/src/components/date-picker/date-picker.tsx index d30087ea..69803cc7 100644 --- a/packages/ui/src/components/date-picker/date-picker.tsx +++ b/packages/ui/src/components/date-picker/date-picker.tsx @@ -54,24 +54,24 @@ export default function DatePicker(props: DatePickerProps) { break; } - case RelativeDatePresets.YTD: { - const firstDateOfTheYear = startOfYear(today); - setStartDate(firstDateOfTheYear); + case RelativeDatePresets.MONTHS_3: { + const threeMonthAgo = addMonths(today, -3); + setStartDate(threeMonthAgo); setEndDate(today); break; } case RelativeDatePresets.MONTHS_1: { - const oneMonthFromToday = addMonths(today, 1); - setStartDate(today); - setEndDate(oneMonthFromToday); + const oneMonthAgo = addMonths(today, -1); + setStartDate(oneMonthAgo); + setEndDate(today); break; } - case RelativeDatePresets.MONTHS_3: { - const threeMonthFromToday = addMonths(today, 3); - setStartDate(today); - setEndDate(threeMonthFromToday); + case RelativeDatePresets.YTD: { + const firstDateOfTheYear = startOfYear(today); + setStartDate(firstDateOfTheYear); + setEndDate(today); break; } From 02a0231f52f3d2562b4db8f2f4057bba3cc32680 Mon Sep 17 00:00:00 2001 From: Gibson Han Date: Mon, 8 Apr 2024 16:00:01 -0700 Subject: [PATCH 6/6] fix ui: rename suggestion radio test --- .../components/date-picker/date-picker-suggestions.test.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/ui/src/components/date-picker/date-picker-suggestions.test.tsx b/packages/ui/src/components/date-picker/date-picker-suggestions.test.tsx index 17c45865..4d02564a 100644 --- a/packages/ui/src/components/date-picker/date-picker-suggestions.test.tsx +++ b/packages/ui/src/components/date-picker/date-picker-suggestions.test.tsx @@ -2,16 +2,16 @@ import "@testing-library/jest-dom"; import { render, screen } from "@testing-library/react"; import DatePickerSuggestions from "./date-picker-suggestions"; -describe("Date Input", () => { +describe("Date Range Suggestions Radio Group", () => { beforeEach(() => { render( console.log(value)} />); }); test("renders radio group and all it's options", () => { expect(screen.getByLabelText("Past 1 Year")); + expect(screen.getByLabelText("Past 3 Months")); + expect(screen.getByLabelText("Past 1 Month")); expect(screen.getByLabelText("Year to Date")); - expect(screen.getByLabelText("3 Months")); - expect(screen.getByLabelText("1 Month")); expect(screen.queryByLabelText("It's over 9000")).not.toBeInTheDocument(); }); });