resolved click & drag bug
This commit is contained in:
parent
901c766ced
commit
a352a50b63
@ -14,7 +14,9 @@ export default function CalendarPage() {
|
||||
const queryClient = useQueryClient();
|
||||
const [showForm, setShowForm] = useState(false);
|
||||
const [editingEvent, setEditingEvent] = useState<CalendarEvent | null>(null);
|
||||
const [selectedDate, setSelectedDate] = useState<string | null>(null);
|
||||
const [selectedStart, setSelectedStart] = useState<string | null>(null);
|
||||
const [selectedEnd, setSelectedEnd] = useState<string | null>(null);
|
||||
const [selectedAllDay, setSelectedAllDay] = useState(false);
|
||||
|
||||
const { data: events = [] } = useQuery({
|
||||
queryKey: ['calendar-events'],
|
||||
@ -24,8 +26,43 @@ export default function CalendarPage() {
|
||||
},
|
||||
});
|
||||
|
||||
const eventDropMutation = useMutation({
|
||||
mutationFn: async ({ id, start, end, allDay }: { id: number; start: string; end: string; allDay: boolean }) => {
|
||||
const toLocalDatetime = (d: Date): string => {
|
||||
const pad = (n: number) => n.toString().padStart(2, '0');
|
||||
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
|
||||
};
|
||||
|
||||
const updateEventTimes = (
|
||||
id: number,
|
||||
start: string,
|
||||
end: string,
|
||||
allDay: boolean,
|
||||
revert: () => void,
|
||||
) => {
|
||||
// Optimistically update cache so re-renders don't snap back
|
||||
queryClient.setQueryData<CalendarEvent[]>(['calendar-events'], (old) =>
|
||||
old?.map((e) =>
|
||||
e.id === id
|
||||
? { ...e, start_datetime: start, end_datetime: end, all_day: allDay }
|
||||
: e,
|
||||
),
|
||||
);
|
||||
|
||||
eventMutation.mutate({ id, start, end, allDay, revert });
|
||||
};
|
||||
|
||||
const eventMutation = useMutation({
|
||||
mutationFn: async ({
|
||||
id,
|
||||
start,
|
||||
end,
|
||||
allDay,
|
||||
}: {
|
||||
id: number;
|
||||
start: string;
|
||||
end: string;
|
||||
allDay: boolean;
|
||||
revert: () => void;
|
||||
}) => {
|
||||
const response = await api.put(`/events/${id}`, {
|
||||
start_datetime: start,
|
||||
end_datetime: end,
|
||||
@ -35,11 +72,12 @@ export default function CalendarPage() {
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['calendar-events'] });
|
||||
toast.success('Event moved');
|
||||
toast.success('Event updated');
|
||||
},
|
||||
onError: (error) => {
|
||||
onError: (error, variables) => {
|
||||
variables.revert();
|
||||
queryClient.invalidateQueries({ queryKey: ['calendar-events'] });
|
||||
toast.error(getErrorMessage(error, 'Failed to move event'));
|
||||
toast.error(getErrorMessage(error, 'Failed to update event'));
|
||||
},
|
||||
});
|
||||
|
||||
@ -61,31 +99,49 @@ export default function CalendarPage() {
|
||||
}
|
||||
};
|
||||
|
||||
const toLocalDatetime = (d: Date): string => {
|
||||
const pad = (n: number) => n.toString().padStart(2, '0');
|
||||
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
|
||||
};
|
||||
|
||||
const handleEventDrop = (info: EventDropArg) => {
|
||||
const id = parseInt(info.event.id);
|
||||
const start = info.event.allDay
|
||||
? info.event.startStr
|
||||
: info.event.start ? toLocalDatetime(info.event.start) : info.event.startStr;
|
||||
: info.event.start
|
||||
? toLocalDatetime(info.event.start)
|
||||
: info.event.startStr;
|
||||
const end = info.event.allDay
|
||||
? info.event.endStr || info.event.startStr
|
||||
: info.event.end ? toLocalDatetime(info.event.end) : start;
|
||||
eventDropMutation.mutate({ id, start, end, allDay: info.event.allDay });
|
||||
: info.event.end
|
||||
? toLocalDatetime(info.event.end)
|
||||
: start;
|
||||
updateEventTimes(id, start, end, info.event.allDay, info.revert);
|
||||
};
|
||||
|
||||
const handleEventResize = (info: { event: EventDropArg['event']; revert: () => void }) => {
|
||||
const id = parseInt(info.event.id);
|
||||
const start = info.event.allDay
|
||||
? info.event.startStr
|
||||
: info.event.start
|
||||
? toLocalDatetime(info.event.start)
|
||||
: info.event.startStr;
|
||||
const end = info.event.allDay
|
||||
? info.event.endStr || info.event.startStr
|
||||
: info.event.end
|
||||
? toLocalDatetime(info.event.end)
|
||||
: start;
|
||||
updateEventTimes(id, start, end, info.event.allDay, info.revert);
|
||||
};
|
||||
|
||||
const handleDateSelect = (selectInfo: DateSelectArg) => {
|
||||
setSelectedDate(selectInfo.startStr);
|
||||
setSelectedStart(selectInfo.startStr);
|
||||
setSelectedEnd(selectInfo.endStr);
|
||||
setSelectedAllDay(selectInfo.allDay);
|
||||
setShowForm(true);
|
||||
};
|
||||
|
||||
const handleCloseForm = () => {
|
||||
setShowForm(false);
|
||||
setEditingEvent(null);
|
||||
setSelectedDate(null);
|
||||
setSelectedStart(null);
|
||||
setSelectedEnd(null);
|
||||
setSelectedAllDay(false);
|
||||
};
|
||||
|
||||
return (
|
||||
@ -112,6 +168,7 @@ export default function CalendarPage() {
|
||||
weekends={true}
|
||||
eventClick={handleEventClick}
|
||||
eventDrop={handleEventDrop}
|
||||
eventResize={handleEventResize}
|
||||
select={handleDateSelect}
|
||||
height="auto"
|
||||
/>
|
||||
@ -119,7 +176,13 @@ export default function CalendarPage() {
|
||||
</div>
|
||||
|
||||
{showForm && (
|
||||
<EventForm event={editingEvent} initialDate={selectedDate} onClose={handleCloseForm} />
|
||||
<EventForm
|
||||
event={editingEvent}
|
||||
initialStart={selectedStart}
|
||||
initialEnd={selectedEnd}
|
||||
initialAllDay={selectedAllDay}
|
||||
onClose={handleCloseForm}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -20,7 +20,9 @@ import { Checkbox } from '@/components/ui/checkbox';
|
||||
|
||||
interface EventFormProps {
|
||||
event: CalendarEvent | null;
|
||||
initialDate?: string | null;
|
||||
initialStart?: string | null;
|
||||
initialEnd?: string | null;
|
||||
initialAllDay?: boolean;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
@ -54,11 +56,11 @@ function formatForInput(dt: string, allDay: boolean, fallbackTime: string = '09:
|
||||
return allDay ? toDateOnly(dt) : toDatetimeLocal(dt, fallbackTime);
|
||||
}
|
||||
|
||||
export default function EventForm({ event, initialDate, onClose }: EventFormProps) {
|
||||
export default function EventForm({ event, initialStart, initialEnd, initialAllDay, onClose }: EventFormProps) {
|
||||
const queryClient = useQueryClient();
|
||||
const isAllDay = event?.all_day ?? false;
|
||||
const rawStart = event?.start_datetime || initialDate || '';
|
||||
const rawEnd = event?.end_datetime || initialDate || '';
|
||||
const isAllDay = event?.all_day ?? initialAllDay ?? false;
|
||||
const rawStart = event?.start_datetime || initialStart || '';
|
||||
const rawEnd = event?.end_datetime || initialEnd || '';
|
||||
const [formData, setFormData] = useState({
|
||||
title: event?.title || '',
|
||||
description: event?.description || '',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user