Files
neta/app/(dashboard)/calendar/page.tsx
T
Poyraz Avsever 7ee3104158 feat(calendar): implement calendar event management with create, update, and delete functionalities
- Added actions for creating, updating, and deleting calendar events in `actions.ts`.
- Introduced `CalendarClient` component to handle event display and interaction in `calendar-client.tsx`.
- Refactored `CalendarPage` to fetch events, clients, projects, and tasks from Supabase and pass them to `CalendarClient`.
- Enhanced form handling for event creation and editing with proper validation and error handling.
2026-06-04 19:53:44 +03:00

108 lines
3.1 KiB
TypeScript

import {
CalendarClient,
type CalendarEventItem,
type CalendarRelationOption,
type CalendarTaskOption,
} from "@/app/(dashboard)/calendar/calendar-client";
import { createClient } from "@/lib/supabase/server";
type CalendarEventRow = {
id: string;
title: string;
description: string | null;
type: CalendarEventItem["type"];
starts_at: string;
ends_at: string | null;
client_id: string | null;
project_id: string | null;
task_id: string | null;
clients: { name: string } | { name: string }[] | null;
projects: { name: string } | { name: string }[] | null;
tasks: { title: string } | { title: string }[] | null;
};
export default async function CalendarPage() {
const supabase = await createClient();
const {
data: { user },
} = await supabase.auth.getUser();
if (!user) {
return null;
}
const [{ data: eventRows }, { data: clientRows }, { data: projectRows }, { data: taskRows }] =
await Promise.all([
supabase
.from("calendar_events")
.select("id, title, description, type, starts_at, ends_at, client_id, project_id, task_id, clients(name), projects(name), tasks(title)")
.eq("user_id", user.id)
.order("starts_at", { ascending: true }),
supabase
.from("clients")
.select("id, name")
.eq("user_id", user.id)
.neq("status", "archived")
.order("name", { ascending: true }),
supabase
.from("projects")
.select("id, name")
.eq("user_id", user.id)
.neq("status", "cancelled")
.order("name", { ascending: true }),
supabase
.from("tasks")
.select("id, title")
.eq("user_id", user.id)
.neq("status", "done")
.order("created_at", { ascending: false }),
]);
const events: CalendarEventItem[] = ((eventRows || []) as unknown as CalendarEventRow[]).map((event) => ({
id: event.id,
title: event.title,
description: event.description,
type: normalizeType(event.type),
starts_at: event.starts_at,
ends_at: event.ends_at,
client_id: event.client_id,
project_id: event.project_id,
task_id: event.task_id,
clientName: getRelationName(event.clients),
projectName: getRelationName(event.projects),
taskTitle: getRelationTitle(event.tasks),
}));
return (
<CalendarClient
events={events}
clients={(clientRows || []) as CalendarRelationOption[]}
projects={(projectRows || []) as CalendarRelationOption[]}
tasks={(taskRows || []) as CalendarTaskOption[]}
/>
);
}
function getRelationName(relation: CalendarEventRow["clients"] | CalendarEventRow["projects"]) {
if (!relation) return null;
return Array.isArray(relation) ? relation[0]?.name || null : relation.name;
}
function getRelationTitle(relation: CalendarEventRow["tasks"]) {
if (!relation) return null;
return Array.isArray(relation) ? relation[0]?.title || null : relation.title;
}
function normalizeType(type: string): CalendarEventItem["type"] {
if (
type === "meeting" ||
type === "deadline" ||
type === "personal" ||
type === "finance"
) {
return type;
}
return "focus";
}