From e14d5089cbef1d1fa7df770cca16b531583c6474 Mon Sep 17 00:00:00 2001 From: Joe Karow <58997957+JoeKarow@users.noreply.github.com> Date: Thu, 3 Aug 2023 18:20:55 -0400 Subject: [PATCH] pair programming updates --- .../HoursDrawer/HoursDrawer.stories.tsx | 2 + .../data-portal/HoursDrawer/HoursDrawer.tsx | 219 +++++++++--------- 2 files changed, 106 insertions(+), 115 deletions(-) diff --git a/packages/ui/components/data-portal/HoursDrawer/HoursDrawer.stories.tsx b/packages/ui/components/data-portal/HoursDrawer/HoursDrawer.stories.tsx index f347f91766..0e56b28dc8 100644 --- a/packages/ui/components/data-portal/HoursDrawer/HoursDrawer.stories.tsx +++ b/packages/ui/components/data-portal/HoursDrawer/HoursDrawer.stories.tsx @@ -6,6 +6,7 @@ import { fieldOpt } from '~ui/mockData/fieldOpt' import { geoMocks } from '~ui/mockData/geo' import { location } from '~ui/mockData/location' import { organization } from '~ui/mockData/organization' +import { orgHours } from '~ui/mockData/orgHours' import { service } from '~ui/mockData/orgService' import { HoursDrawer } from './HoursDrawer' @@ -37,6 +38,7 @@ export default { type: 'mutation', response: { id: 'oloc_00000RECORD22ID' }, }), + orgHours.forHoursDrawer, ], }, args: { diff --git a/packages/ui/components/data-portal/HoursDrawer/HoursDrawer.tsx b/packages/ui/components/data-portal/HoursDrawer/HoursDrawer.tsx index 8443ca3fa0..0921ea2df5 100644 --- a/packages/ui/components/data-portal/HoursDrawer/HoursDrawer.tsx +++ b/packages/ui/components/data-portal/HoursDrawer/HoursDrawer.tsx @@ -15,21 +15,22 @@ import { UnstyledButton, } from '@mantine/core' import { TimeInput } from '@mantine/dates' -import { zodResolver } from '@mantine/form' -import { useDebouncedValue, useDisclosure } from '@mantine/hooks' +import { Form, useForm, zodResolver } from '@mantine/form' +import { useDebouncedValue, useDisclosure, useListState } from '@mantine/hooks' import { DateTime, Interval } from 'luxon' -import { type ComponentPropsWithRef, forwardRef, useEffect, useState } from 'react' +import { type ComponentPropsWithRef, forwardRef, type ReactNode, useEffect, useMemo, useState } from 'react' import timezones from 'timezones-list' import { z } from 'zod' import { type ApiOutput } from '@weareinreach/api' +import { generateId } from '@weareinreach/db/lib/idGen' import { Breadcrumb } from '~ui/components/core/Breadcrumb' import { Button } from '~ui/components/core/Button' import { useCustomVariant } from '~ui/hooks/useCustomVariant' import { Icon } from '~ui/icon' import { trpc as api } from '~ui/lib/trpcClient' -import { HoursDrawerFormProvider, useForm } from './HoursDrawerContext' +// import { HoursDrawerFormProvider, useForm } from './HoursDrawerContext' const useStyles = createStyles((theme) => ({ drawerContent: { @@ -53,17 +54,27 @@ const useStyles = createStyles((theme) => ({ }, })) -const FormSchema = z.object({ - data: z - .object({ - dayIndex: z.coerce.number().nullable(), - start: z.coerce.date().nullable(), - end: z.coerce.date().nullable(), - close: z.coerce.boolean().nullable(), - tz: z.string().nullable(), - }) - .partial(), -}) +const FormSchema = z + .object({ + data: z + .object({ + id: z.string().optional(), + dayIndex: z.coerce.number(), + start: z + .string({ required_error: 'Start time is required', invalid_type_error: 'Invalid entry' }) + .length(5), + end: z + .string({ required_error: 'End time is required', invalid_type_error: 'Invalid entry' }) + .length(5), + closed: z.coerce.boolean(), + tz: z.string().nullable(), + delete: z.boolean().optional(), + }) + .array(), + }) + .superRefine((val, ctx) => { + // https://zod.dev/?id=superrefine + }) const schemaTransform = ({ id, data }: FormSchema) => ({ id, @@ -103,16 +114,19 @@ const sortedTimezoneData = timezoneData.sort((a, b) => { }) const _HoursDrawer = forwardRef(({ locationId, ...props }, ref) => { - const [opened, handler] = useDisclosure(false) + const [opened, handler] = useDisclosure(true) //TODO: Change back to 'false' when done. const [isSaved, setIsSaved] = useState(false) - const form = useForm({ + const form = useForm>({ validate: zodResolver(FormSchema), - initialValues: { data: [] }, - transformValues: FormSchema.transform(schemaTransform).parse, + initialValues: { + data: [], + }, }) const [tzValue, setTzValue] = useState(null) const { classes } = useStyles() const variants = useCustomVariant() + + /** Remove this */ const [checked, setChecked] = useState<{ [key: number]: boolean }>({ 0: false, // Sunday 1: false, // Monday @@ -122,6 +136,7 @@ const _HoursDrawer = forwardRef(({ location 5: false, // Friday 6: false, // Saturday }) + /** Remove this */ const [timeValues, setTimeValues] = useState<{ [key: number]: { start: Date | null; end: Date | null } }>({ @@ -133,117 +148,76 @@ const _HoursDrawer = forwardRef(({ location 5: { start: null, end: null }, // Friday 6: { start: null, end: null }, // Saturday }) - console.log(timeValues) - const handleUpdate = () => { - //TODO save to DB instead of sending to console.log - const data = generateDataArray() - console.log(data) - } - - const TimeRangeComponent = (title: string, dayIndex: number) => { - const [timeRangeGroups, setTimeRangeGroups] = useState([]) // Define the type for state variable - const handleCheckboxChange = (event: React.ChangeEvent) => { - const { checked } = event.currentTarget + //data comes back here + const { data: initialData } = api.orgHours.forHoursDrawer.useQuery(locationId ?? '', { + onSuccess: (data) => form.setValues({ data }), + }) + console.log('form values', form.values) - setChecked((prevChecked) => { - if (checked) { - setTimeRangeGroups([]) - setTimeValues((prevTimeValues) => ({ - ...prevTimeValues, - [dayIndex]: { - start: DateTime.fromMillis(0).toUTC().toISO(), // Set start time to 1970-01-01T00:00:00.000Z - end: DateTime.fromObject( - { year: 1970, month: 1, day: 1, hour: 23, minute: 59, second: 59, millisecond: 0 }, - { zone: 'utc' } - ).toISO(), // Set end time to 1970-01-01T23:59:59.000Z - }, - })) - } + // Docs: https://mantine.dev/form/nested/ - return { - ...prevChecked, - [dayIndex]: checked, - } - }) - } + const handleUpdate = () => { + //TODO save to DB instead of sending to console.log + // const data = generateDataArray() + console.log('clicked save', form.isValid(), form.errors) + } - const handleAddTimeRangeGroup = () => { - // Add a new time range group to the state - setTimeRangeGroups((prevTimeRangeGroups) => [ - ...prevTimeRangeGroups, - + const TimeRangeComponent = ({ arrayIdx }: { arrayIdx: number }) => { + return ( + + handleTimeChange(event, dayIndex, 'start')} name='start' + {...form.getInputProps(`data.${arrayIdx}.start`)} + onFocus={undefined} /> handleTimeChange(event, dayIndex, 'end')} name='end' + {...form.getInputProps(`data.${arrayIdx}.end`)} + onFocus={undefined} /> - , - ]) - } - - const handleTimeChange = ( - event: React.ChangeEvent, - dayIndex: number, - timeType: 'start' | 'end' - ) => { - const { name, value } = event.currentTarget - const [hours, minutes] = value.split(':') - - const date = new Date(1970, 0, 1, parseInt(hours, 10), parseInt(minutes, 10)) - - setTimeValues((prevTimeValues) => ({ - ...prevTimeValues, - [dayIndex]: { - ...prevTimeValues[dayIndex], - [name]: date, - }, - })) + + + + ) + } + const DayWrap = ({ dayIndex, children }: { dayIndex: number; children: ReactNode }) => { + const days = { + 0: 'Sunday', + 1: 'Monday', + 2: 'Tuesday', + 3: 'Wednesday', + 4: 'Thursday', + 5: 'Friday', + 6: 'Saturday', } - const isCheckboxChecked = checked[dayIndex] - return ( - {title} - + {days[dayIndex.toString()] ?? ''} + - - handleTimeChange(event, dayIndex, 'start')} - name='start' - /> - handleTimeChange(event, dayIndex, 'end')} - name='end' - /> - - {timeRangeGroups} {/* Render the dynamically added HTML when button is clicked*/} -