working calendar, code may be messy

This commit is contained in:
2025-02-27 17:50:26 +01:00
parent a4b75596c7
commit 09d6fcc0dd
5 changed files with 183 additions and 147 deletions
+13 -11
View File
@@ -72,16 +72,17 @@ export async function PUT(req: NextRequest) {
{ status: HttpStatusCode.NotFound }
);
database.schedules.insertOne({
account: session.user,
scheduled,
content,
platforms,
});
return NextResponse.json(
{
message: 'ok',
id: (
await database.schedules.insertOne({
account: session.user,
scheduled,
content,
platforms,
})
).insertedId,
},
{ status: HttpStatusCode.Ok }
);
@@ -128,12 +129,13 @@ export async function GET(req: NextRequest) {
export async function DELETE(req: NextRequest) {
const url = new URL(req.url);
const sessionId = url.searchParams.get('id');
const date = url.searchParams.get('date');
const schedule = url.searchParams.get('schedule');
if (typeof sessionId !== 'string' || typeof date !== 'string')
if (typeof sessionId !== 'string' || typeof schedule !== 'string')
return NextResponse.json(
{
message: 'Invalid structure, required param `id=` and `date=`',
message:
'Invalid structure, required param `id=` and `schedule=`',
},
{ status: HttpStatusCode.BadRequest }
);
@@ -151,8 +153,8 @@ export async function DELETE(req: NextRequest) {
);
const result = await database.schedules.deleteMany({
_id: new ObjectId(schedule),
account: session.user,
scheduled: date,
});
if (result.deletedCount === 0)
+147 -81
View File
@@ -8,112 +8,178 @@ import { ScheduleRemoveRequest } from '@/utils';
import axios from 'axios';
import { format } from 'date-fns';
import { PlusCircle, Trash } from 'lucide-react';
import { useState } from 'react';
import { PlusCircle, Trash2 } from 'lucide-react';
export interface CalendarSchedule {
date: Date;
platforms: { user: string }[];
id: string;
}
const weekdays = [
'Mon',
'Tue',
'Wed',
'Thu',
'Fri',
'Sat',
'Sun',
const weekdays: [string, number, number, number][] = [
['Mon', 2025, 2, 24],
['Tue', 2025, 2, 25],
['Wed', 2025, 2, 26],
['Thu', 2025, 2, 27],
['Fri', 2025, 2, 28],
['Sat', 2025, 2, 29],
['Sun', 2025, 3, 1],
];
const times = ['12 PM', '1 PM', '2 PM', '3 PM', '4 PM', '5 PM', '6 PM', '7 PM', '8 PM', '9 PM', '10 PM', '11 PM'];
const times: [string, number][] = [
['12 PM', 12],
['1 PM', 13],
['2 PM', 14],
['3 PM', 15],
['4 PM', 16],
['5 PM', 17],
['6 PM', 18],
['7 PM', 19],
['8 PM', 20],
['9 PM', 21],
['10 PM', 22],
['11 PM', 23],
];
export default function Calendar({
setDialog,
sessionId,
events,
setDate,
date,
setEvents,
}: {
setDialog: (b: boolean) => void;
sessionId: string;
events: CalendarSchedule[];
date: Date;
setDate: (d: Date) => void;
setEvents: (events: CalendarSchedule[]) => void;
}) {
const [selected, setSelected] = useState(0);
return (
<div className="flex flex-col">
<div className="grid grid-cols-1 w-full h-20 mb-2">
<div className="grid grid-cols-7 ml-20">
{weekdays.map((w, i) => (
<div key={i} className="border">
<p className="w-max mx-auto">{w}</p>
</div>
))}
</div>
</div>
<div className="grid grid-cols-1 gap-2 w-full">
{times.map((w, i) => (
<div key={i} className="flex">
<p className="w-20 border py-4">
<p className="w-max mx-auto">{w}</p>
</p>
<div className="grid grid-cols-7 w-full ml-1">
{weekdays.map((w, i) => (
<div key={i} className="border py-4"></div>
<div className="flex gap-2">
{/* Times column */}
<div className="w-20 flex flex-col gap-2">
<div className="h-24"></div>{' '}
{/* Empty space for alignment */}
<div className="grid grid-rows-10 h-full gap-2">
{times.map((t, j) => (
<div
key={j}
className="flex pr-2 h-16 border rounded-xl"
>
<p className="size-max m-auto">{t[0]}</p>
</div>
))}
</div>
</div>
))}
{/* Calendar grid */}
<div className="grid grid-cols-7 gap-2 flex-1">
{weekdays.map((w, i) => (
<div key={i} className="flex flex-col h-full gap-2">
<div className="border rounded-md h-24 flex">
<p className="size-max mx-auto">{w[0]}</p>
</div>
<div className="grid grid-rows-10 h-full gap-2">
{times.map((t, j) => {
const event = events.find((e) => {
console.log(
e.date.getHours(),
t[1]
);
return (
e.date.getFullYear() === w[1] &&
e.date.getMonth() === w[2] &&
e.date.getDate() === w[3] &&
e.date.getHours() === t[1]
);
});
return (
<ContextMenu key={j}>
<ContextMenuTrigger>
<div
className={`border rounded-xl w-full h-16 ${
event
? 'bg-primary/20'
: ''
}`}
>
{event && (
<div className="p-2 text-sm flex items-center justify-center">
{/* <LampIcon className="h-6 w-6" /> */}
</div>
)}
</div>
</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuItem
onClick={() => {
setDialog(true);
setDate(
new Date(
w[1],
w[2],
w[3],
t[1],
0,
0
)
);
}}
>
<PlusCircle className="mr-2 h-4 w-4" />
<p>New post</p>
</ContextMenuItem>
{event && (
<ContextMenuItem
onClick={() => {
axios
.delete(
`/api/posts`,
{
params: {
id: sessionId,
schedule:
event.id,
} satisfies ScheduleRemoveRequest,
}
)
.then(
() => {
setEvents(
events.filter(
(
e
) =>
e.id !==
event.id
)
);
}
);
}}
>
<Trash2 className="mr-2 h-4 w-4 text-red-500" />
<p className="text-red-500">
Delete post
</p>
</ContextMenuItem>
)}
</ContextMenuContent>
</ContextMenu>
);
})}
</div>
</div>
))}
</div>
</div>
</div>
</div>
);
// <div className="grid grid-cols-1 w-full">
// <div className="grid grid-cols-7">
// {weekdays.map((w, i) => (
// <div key={i}>
// <p className="w-max mx-auto">{w}</p>
// </div>
// ))}
// </div>
// </div>
// return (
// <ContextMenu>
// <ContextMenuTrigger></ContextMenuTrigger>
// <ContextMenuContent>
// <ContextMenuItem
// onClick={() => {
// setDialog(true);
// }}
// >
// <PlusCircle className="w-4 mt-0.5" />{' '}
// <p className="ml-1">New post</p>
// </ContextMenuItem>
// {selected ? (
// <ContextMenuItem
// onClick={() => {
// if (selected) {
// axios.delete(`/api/posts`, {
// params: {
// id: sessionId,
// date: format(
// events[selected].date,
// 'y-MM-dd hh:mm'
// ),
// } satisfies ScheduleRemoveRequest,
// });
// }
// }}
// className=""
// >
// <Trash className="w-4 mt-0.5 text-red-500" />{' '}
// <p className="ml-1 text-red-500">Delete</p>
// </ContextMenuItem>
// ) : (
// ''
// )}
// </ContextMenuContent>
// </ContextMenu>
// );
}
+12 -41
View File
@@ -1,59 +1,27 @@
'use client';
import { useCalendarApp, ScheduleXCalendar } from '@schedule-x/react';
import { createViewWeek } from '@schedule-x/calendar';
import { createEventsServicePlugin } from '@schedule-x/events-service';
import { createDragAndDropPlugin } from '@schedule-x/drag-and-drop';
import '@/calendar-theme.css';
import { MouseEventHandler, useEffect, useState } from 'react';
import { useEffect, useState } from 'react';
import App from '@/components/app';
import { format, parse } from 'date-fns';
import PostDialog, { today } from './postDialog';
import axios from 'axios';
import Cookies from 'js-cookie';
import { Schedule, ScheduleRemoveRequest, ScheduleRequest } from '@/utils';
import Calendar, { CalendarSchedule } from './calendar';
function closestChild(children: any, clientX: number, clientY: number) {
let closestElement = null;
let closestDistance = Infinity;
for (let child of children) {
const childRect = child.getBoundingClientRect();
const dx = Math.abs(clientX - (childRect.left + childRect.width / 2));
const dy = Math.abs(clientY - (childRect.top + childRect.height / 2));
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < closestDistance) {
closestDistance = distance;
closestElement = child;
}
}
return closestElement;
}
export default function CalendarApp() {
const eventsService = useState(() => createEventsServicePlugin())[0];
const dragAndDrop = useState(() => createDragAndDropPlugin())[0];
const [eventCount, setEventCount] = useState(0);
const sessionId = Cookies.get('session_id') || '';
const calendar = useCalendarApp({
views: [createViewWeek()],
events: [],
plugins: [eventsService, dragAndDrop],
isDark: true,
});
const [events, setEvents] = useState<CalendarSchedule[]>([]);
useEffect(() => {
axios.get(`/api/posts/?id=${sessionId}`).then((response) => {
setEvents(response.data.schedules as CalendarSchedule[]);
const v = response.data.schedules.map((e: any) => ({
date: parse(e.scheduled, 'yyyy-MM-dd HH:mm', new Date()),
platforms: e.platforms,
id: e._id,
}));
setEvents(v);
setEventCount(response.data.schedules.length);
});
}, []);
@@ -63,14 +31,14 @@ export default function CalendarApp() {
return (
<App>
<div>
<div className="flex flex-1 flex-col p-6 px-5 md:px-7 h-max">
<PostDialog
date={date}
setDate={setDate}
newPostDialogOpen={postDialog}
setNewPostDialogOpen={setDialog}
setEvents={(e) => {
calendar.events.add(e);
setEvents([...events, e]);
setEventCount(eventCount + 1);
}}
eventId={eventCount}
@@ -81,6 +49,9 @@ export default function CalendarApp() {
setDialog={setDialog}
sessionId={sessionId}
events={events}
date={date}
setDate={setDate}
setEvents={setEvents}
/>
</div>
</App>
+10 -13
View File
@@ -26,6 +26,7 @@ import { Label } from '@/components/ui/label';
import { useState } from 'react';
import axios from 'axios';
import { PostRequest, ScheduleRequest } from '@/utils';
import { CalendarSchedule } from './calendar';
type PostDialogProps = {
newPostDialogOpen: boolean;
@@ -33,7 +34,7 @@ type PostDialogProps = {
date: Date;
setDate: (d: Date) => void;
eventId: number;
setEvents: (e: CalendarEventExternal) => void;
setEvents: (e: CalendarSchedule) => void;
sessionId: string;
};
@@ -137,24 +138,20 @@ export default function PostDialog({
Post now
</Button>
<Button
onClick={() => {
const end = new Date(date);
end.setHours(date.getHours() + 1);
addEvent({
title: 'Post',
id: eventId,
start: format(date, 'y-MM-dd hh:mm'),
end: format(end, 'y-MM-dd hh:mm'),
});
axios.put('/api/posts', {
onClick={async () => {
const { data } = await axios.put('/api/posts', {
scheduled: format(date, 'y-MM-dd hh:mm'),
sessionId,
platforms: ['andjksds'],
content,
} satisfies ScheduleRequest);
addEvent({
id: data.id,
date,
platforms: [{ user: 'andjksds' }],
});
setNewPostDialogOpen(false);
}}
>
+1 -1
View File
@@ -13,7 +13,7 @@ export interface ScheduleRequest extends PostRequest {
}
export interface ScheduleRemoveRequest {
date: string;
schedule: string;
id: string;
}