CRUD Events and React interaction

This commit is contained in:
cdricms
2025-01-27 17:58:47 +01:00
parent 9843158803
commit ac7e97527f
17 changed files with 887 additions and 349 deletions

View File

@@ -48,7 +48,7 @@ export default function ShortcodesPage() {
};
return (
<div className="container mx-auto py-10">
<div className="container mx-auto px-4 py-10">
<h1 className="text-2xl font-bold mb-5">Shortcodes</h1>
{isLoading && (
<Loader2 className="flex w-full min-w-0 flex-col gap-1 justify-center animate-spin" />

View File

@@ -1,276 +1,20 @@
"use client";
import Planning from "@/components/planning.tsx";
import { useApi } from "@/hooks/use-api";
import { type CalendarEventExternal } from "@schedule-x/calendar";
import { Loader2 } from "lucide-react";
import { request, useApi } from "@/hooks/use-api";
import "@schedule-x/theme-shadcn/dist/index.css";
import { useNextCalendarApp, ScheduleXCalendar } from "@schedule-x/react";
import { createEventsServicePlugin } from "@schedule-x/events-service";
import {
CalendarEventExternal,
createViewDay,
createViewWeek,
} from "@schedule-x/calendar";
import { useEffect, useState } from "react";
import { format } from "date-fns";
import { Dialog } from "@radix-ui/react-dialog";
import {
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { CalendarIcon } from "lucide-react";
import { Calendar } from "@/components/ui/calendar";
import { cn } from "@/lib/utils";
import { requestFormReset } from "react-dom";
const Page = () => {
const {
data: requestedEvents,
isLoading,
success,
mutate,
} = useApi<CalendarEventExternal[]>("/events", undefined, false, false);
const Planning = () => {
const plugins = [createEventsServicePlugin()];
const [eventSelected, setEventSelected] =
useState<CalendarEventExternal | null>(null);
const [events, setEvents] = useState<CalendarEventExternal[]>([
{
id: "1", // TODO put an uuid there
title: "Event 1",
start: format(new Date(Date.now()), "yyyy-MM-dd HH:mm"),
end: format(
new Date(Date.now() + 1 * 3600 * 1000),
"yyyy-MM-dd HH:mm",
),
},
]);
const [requestCreateEvent, setRequestCreateEvent] = useState(false)
const calendar = useNextCalendarApp(
{
theme: "shadcn",
views: [createViewDay(), createViewWeek()],
defaultView: "week",
isDark: true,
isResponsive: true,
locale: "fr-FR",
dayBoundaries: {
start: "06:00",
end: "00:00",
},
events,
callbacks: {
onEventClick(event, e) {
setEventSelected(event);
},
async onClickDateTime(dateTime) {
setRequestCreateEvent(true)
const newEvent: CalendarEventExternal = {
id: "5",
title: "Event 1",
start: dateTime,
end: format(
new Date(dateTime).getTime() + (1000 * 60 * 60),
"yyyy-MM-dd HH:mm",
),
}
try {
const res = await request<undefined>(
`/events/new`,
{
method: "POST",
body: JSON.stringify(newEvent),
requiresAuth: true,
csrfToken: false
},)
if (res.status === "Error") {
console.log("Error")
}
if (res.status === "Success") {
console.log("Success")
}
} catch (e) {
console.log(e)
}
},
},
},
plugins,
);
const {data: requestedEvents, isLoading, success} = useApi("/events", {
onSuccess: (data) => {
calendar?.events.set(data)
}
}, false, false)
useEffect(() => {
// get all events
calendar?.events.getAll();
}, []);
return (
<div>
<div className="m-8">
<ScheduleXCalendar calendarApp={calendar} />
</div>
<Dialog
open={eventSelected !== null || false}
onOpenChange={(open) => {
setEventSelected((e) => (open ? e : null));
}}
>
<DialogContent className="sm:max-w-md">
<DialogHeader>
<DialogTitle>{eventSelected?.title}</DialogTitle>
<DialogDescription>
{eventSelected?.description}
</DialogDescription>
</DialogHeader>
<div className="grid gap-4 py-4">
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="start" className="text-right">
Début
</Label>
{/*<Popover>
<PopoverTrigger asChild>
<Button
variant={"outline"}
className={cn(
"w-[240px] pl-3 text-left font-normal",
!eventSelected?.start &&
"text-muted-foreground",
)}
>
{eventSelected?.start ? (
format(eventSelected?.start, "PPP")
) : (
<span>Choisissez une date.</span>
)}
<CalendarIcon className="ml-auto h-4 w-4 opacity-50" />
</Button>
</PopoverTrigger>
<PopoverContent
className="w-auto p-0"
align="start"
>
<Calendar
mode="single"
selected={
new Date(
eventSelected?.start ??
Date.now(),
)
}
// onSelect={field.onChange}
disabled={(date) =>
date > new Date() ||
date < new Date("1900-01-01")
}
initialFocus
/>
</PopoverContent>
</Popover> */}
<Input
id="start"
value={eventSelected?.start || ""}
onChange={(e) => {
const val = e.currentTarget.value;
setEventSelected((ev) => {
if (ev)
return {
...ev,
start: val,
};
return ev;
});
}}
className="col-span-3"
/>
</div>
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="end" className="text-right">
Fin
</Label>
<Input
id="end"
value={eventSelected?.end || ""}
onChange={(e) => {
const val = e.currentTarget.value
setEventSelected((ev) => {
if (ev)
return {
...ev,
end: val,
};
return ev;
})
}}
className="col-span-3"
/>
</div>
</div>
<DialogFooter className="flex flex-row justify-end">
<Button className="bg-red-700"
onClick={async () => {
calendar?.events?.remove(eventSelected!.id)
try {
const res = await request<undefined>(
`/events/${eventSelected!.id}/delete`,
{
method: "DELETE",
body: JSON.stringify(eventSelected),
requiresAuth: false,
csrfToken: false
},)
if (res.status === "Error") {
console.log("Error")
}
if (res.status === "Success") {
console.log("Success")
}
} catch (e) {
console.log(e)
}
}}
type="submit">
Supprimer
</Button>
<Button className="bg-blue-500"
onClick={async () => {
calendar?.events?.update(eventSelected!)
try {
const res = await request<undefined>(
`/events/${eventSelected!.id}/update`,
{
method: "PATCH",
body: JSON.stringify(eventSelected),
requiresAuth: true,
csrfToken: false
},)
if (res.status === "Error") {
console.log("Error")
}
if (res.status === "Success") {
console.log("Success")
}
} catch (e) {
console.log(e)
}
}}
type="submit">
Actualiser
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</div>
);
if (isLoading) return <Loader2 className="animate-spin" />;
if (success)
return <Planning events={requestedEvents ?? []} mutate={mutate} />;
};
export default Planning;
export default Page;