split edit-slot-form into files
This commit is contained in:
parent
f9f485728c
commit
d56ee1052d
@ -1,96 +0,0 @@
|
||||
'use client';
|
||||
import { ScheduleSlotsContext } from '@/context/schedule-slots';
|
||||
import { useSlotMutation, useSlotQuery } from '@/hooks/slots';
|
||||
import { combineDateTime, getTimeString } from '@/utils/date';
|
||||
import { type SlotFieldsFragment } from '@repo/graphql/types';
|
||||
import { Button } from '@repo/ui/components/ui/button';
|
||||
import { Input } from '@repo/ui/components/ui/input';
|
||||
import { Loader, Pencil, Save } from 'lucide-react';
|
||||
import { type FormEvent, use, useEffect, useState } from 'react';
|
||||
|
||||
type Props = Pick<SlotFieldsFragment, 'documentId'>;
|
||||
|
||||
type TimeTextProps = { readonly date: Date };
|
||||
|
||||
export function EditSlotForm({ documentId }: Readonly<Props>) {
|
||||
const [editMode, setEditMode] = useState(false);
|
||||
|
||||
const [startTime, setStartTime] = useState('');
|
||||
const [endTime, setEndTime] = useState('');
|
||||
|
||||
const { selectedDate } = use(ScheduleSlotsContext);
|
||||
|
||||
const { data, isLoading: isLoadingSlotQuery } = useSlotQuery({ documentId });
|
||||
const { isPending: isPendingSlotMutation, mutate } = useSlotMutation({ documentId });
|
||||
|
||||
const handleSubmit = (event: FormEvent) => {
|
||||
event.preventDefault();
|
||||
if (startTime && endTime) {
|
||||
mutate({
|
||||
data: {
|
||||
dateend: combineDateTime(selectedDate, endTime).toISOString(),
|
||||
datestart: combineDateTime(selectedDate, startTime).toISOString(),
|
||||
},
|
||||
documentId,
|
||||
});
|
||||
setStartTime('');
|
||||
setEndTime('');
|
||||
}
|
||||
|
||||
setEditMode(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (editMode) {
|
||||
setStartTime(getTimeString(data?.slot?.datestart));
|
||||
setEndTime(getTimeString(data?.slot?.dateend));
|
||||
}
|
||||
}, [data?.slot?.dateend, data?.slot?.datestart, editMode]);
|
||||
|
||||
return (
|
||||
<form className="grid grid-cols-[auto_1fr_1fr_auto] items-center gap-2" onSubmit={handleSubmit}>
|
||||
<span className="text-base font-bold">•</span>
|
||||
{editMode ? (
|
||||
<>
|
||||
<div className="flex-1">
|
||||
<Input
|
||||
id="start-time"
|
||||
onChange={(event) => setStartTime(event.target.value)}
|
||||
required
|
||||
type="time"
|
||||
value={startTime}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<Input
|
||||
id="end-time"
|
||||
onChange={(event) => setEndTime(event.target.value)}
|
||||
required
|
||||
type="time"
|
||||
value={endTime}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<TimeText date={data?.slot?.datestart} />
|
||||
<TimeText date={data?.slot?.dateend} />
|
||||
</>
|
||||
)}
|
||||
|
||||
<Button
|
||||
disabled={isLoadingSlotQuery || isPendingSlotMutation}
|
||||
onClick={editMode ? undefined : () => setEditMode(true)}
|
||||
type={editMode ? 'submit' : 'button'}
|
||||
>
|
||||
{editMode ? <Save className="size-4" /> : <Pencil className="size-4" />}
|
||||
</Button>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
function TimeText({ date }: TimeTextProps) {
|
||||
if (!date) return <Loader className="animate-spin" />;
|
||||
|
||||
return <span className="p-1 text-lg font-bold">{getTimeString(date)}</span>;
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
'use client';
|
||||
import { EditableTimePair, ReadonlyTimePair } from '../components';
|
||||
import { Context } from '../context';
|
||||
import { type Props } from '../types';
|
||||
import { ScheduleSlotsContext } from '@/context/schedule-slots';
|
||||
import { useSlotMutation, useSlotQuery } from '@/hooks/slots';
|
||||
import { combineDateTime } from '@/utils/date';
|
||||
import { Button } from '@repo/ui/components/ui/button';
|
||||
import { Pencil, Save } from 'lucide-react';
|
||||
import { type FormEvent, use } from 'react';
|
||||
|
||||
export function Form(props: Readonly<Props>) {
|
||||
const { documentId } = props;
|
||||
|
||||
const { editMode, endTime, setEditMode, setEndTime, setStartTime, startTime } = use(Context);
|
||||
|
||||
const { selectedDate } = use(ScheduleSlotsContext);
|
||||
|
||||
const { isLoading: isLoadingSlotQuery } = useSlotQuery({ documentId });
|
||||
const { isPending: isPendingSlotMutation, mutate } = useSlotMutation({ documentId });
|
||||
|
||||
const handleSubmit = (event: FormEvent) => {
|
||||
event.preventDefault();
|
||||
if (startTime && endTime) {
|
||||
mutate({
|
||||
data: {
|
||||
dateend: combineDateTime(selectedDate, endTime).toISOString(),
|
||||
datestart: combineDateTime(selectedDate, startTime).toISOString(),
|
||||
},
|
||||
documentId,
|
||||
});
|
||||
setStartTime('');
|
||||
setEndTime('');
|
||||
}
|
||||
|
||||
setEditMode(false);
|
||||
};
|
||||
|
||||
const TimePair = editMode ? EditableTimePair : ReadonlyTimePair;
|
||||
|
||||
return (
|
||||
<form className="grid grid-cols-[auto_1fr_1fr_auto] items-center gap-2" onSubmit={handleSubmit}>
|
||||
<span className="text-base font-bold">•</span>
|
||||
<TimePair {...props} />
|
||||
|
||||
<Button
|
||||
disabled={isLoadingSlotQuery || isPendingSlotMutation}
|
||||
onClick={editMode ? undefined : () => setEditMode(true)}
|
||||
type={editMode ? 'submit' : 'button'}
|
||||
>
|
||||
{editMode ? <Save className="size-4" /> : <Pencil className="size-4" />}
|
||||
</Button>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
export * from './form';
|
||||
export * from './time-pair';
|
||||
@ -0,0 +1,56 @@
|
||||
'use client';
|
||||
import { Context } from '../context';
|
||||
import { type Props } from '../types';
|
||||
import { useSlotQuery } from '@/hooks/slots';
|
||||
import { getTimeString } from '@/utils/date';
|
||||
import { Input } from '@repo/ui/components/ui/input';
|
||||
import { Loader } from 'lucide-react';
|
||||
import { use, useEffect } from 'react';
|
||||
|
||||
export function EditableTimePair({ documentId }: Readonly<Props>) {
|
||||
const { editMode, endTime, setEndTime, setStartTime, startTime } = use(Context);
|
||||
const { data } = useSlotQuery({ documentId });
|
||||
|
||||
useEffect(() => {
|
||||
if (editMode) {
|
||||
setStartTime(getTimeString(data?.slot?.datestart));
|
||||
setEndTime(getTimeString(data?.slot?.dateend));
|
||||
}
|
||||
}, [data?.slot?.dateend, data?.slot?.datestart, editMode, setEndTime, setStartTime]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex-1">
|
||||
<Input
|
||||
id="start-time"
|
||||
onChange={(event) => setStartTime(event.target.value)}
|
||||
required
|
||||
type="time"
|
||||
value={startTime}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<Input
|
||||
id="end-time"
|
||||
onChange={(event) => setEndTime(event.target.value)}
|
||||
required
|
||||
type="time"
|
||||
value={endTime}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export function ReadonlyTimePair({ documentId }: Readonly<Props>) {
|
||||
const { data } = useSlotQuery({ documentId });
|
||||
|
||||
if (!data) return <Loader className="animate-spin" />;
|
||||
|
||||
return (
|
||||
<>
|
||||
<span className="p-1 text-lg font-bold">{getTimeString(data?.slot?.datestart)}</span>
|
||||
<span className="p-1 text-lg font-bold">{getTimeString(data?.slot?.dateend)}</span>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
'use client';
|
||||
import { createContext, type PropsWithChildren, useMemo, useState } from 'react';
|
||||
|
||||
type ContextType = {
|
||||
editMode: boolean;
|
||||
endTime: string;
|
||||
setEditMode: (value: boolean) => void;
|
||||
setEndTime: (value: string) => void;
|
||||
setStartTime: (value: string) => void;
|
||||
startTime: string;
|
||||
};
|
||||
export const Context = createContext<ContextType>({} as ContextType);
|
||||
|
||||
export function ContextProvider({ children }: Readonly<PropsWithChildren>) {
|
||||
const [editMode, setEditMode] = useState(false);
|
||||
const [startTime, setStartTime] = useState('');
|
||||
const [endTime, setEndTime] = useState('');
|
||||
|
||||
const value = useMemo(() => {
|
||||
return {
|
||||
editMode,
|
||||
endTime,
|
||||
setEditMode,
|
||||
setEndTime,
|
||||
setStartTime,
|
||||
startTime,
|
||||
};
|
||||
}, [editMode, endTime, setEditMode, startTime]);
|
||||
|
||||
return <Context value={value}>{children}</Context>;
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
'use client';
|
||||
import { Form } from './components';
|
||||
import { ContextProvider } from './context';
|
||||
import { type Props } from './types';
|
||||
|
||||
export function EditSlotForm(props: Readonly<Props>) {
|
||||
return (
|
||||
<ContextProvider>
|
||||
<Form {...props} />
|
||||
</ContextProvider>
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
'use client';
|
||||
import { type SlotFieldsFragment } from '@repo/graphql/types';
|
||||
|
||||
export type Props = Pick<SlotFieldsFragment, 'documentId'>;
|
||||
Loading…
x
Reference in New Issue
Block a user