feat(calendar): month-view calendar bound to calendar_events
Replaces the template's static-data calendar with a multi-tenant calendar backed by Appwrite calendar_events. Schema/validation: - lib/validation/calendar.ts (calendarEventSchema with cross-field check end >= start) - lib/appwrite/calendar-actions.ts: createCalendarEventAction, updateCalendarEventAction, deleteCalendarEventAction. Date inputs (HTML datetime-local 'YYYY-MM-DDTHH:mm', date 'YYYY-MM-DD') are normalized to ISO 8601 before write. - lib/appwrite/calendar-queries.ts: listCalendarEvents with optional start/end range queries. UI: - /calendar server page: pulls events + customers, hands to CalendarClient. - CalendarClient: month grid (6 rows × 7 cols), Monday-first, today badge, prev/next/Bugün nav. Multi-day events show on every day in their range. Each day cell shows up to 3 event chips with start time prefix; '+N daha' for overflow. Hover reveals a + button to add an event on that day. - EventFormSheet: title, all-day switch (toggles input type between date and datetime-local), start/end with validation, customer FK, color preset (blue/green/amber/red/violet/slate). Sentinel '__none__' for nullable Selects. When editing, footer shows a destructive 'Sil' ghost button on the left that triggers the parent's confirm dialog. Color tokens centralized in COLOR_BG map; falls back to primary tint. Removed all template calendar files (calendars.tsx, calendar-main, etc.) since the data model didn't match.
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const calendarEventSchema = z
|
||||
.object({
|
||||
title: z.string().trim().min(1, "Başlık zorunlu.").max(255),
|
||||
description: z
|
||||
.string()
|
||||
.trim()
|
||||
.max(2000)
|
||||
.optional()
|
||||
.transform((v) => (v ? v : undefined)),
|
||||
start: z.string().min(1, "Başlangıç zorunlu."),
|
||||
end: z.string().min(1, "Bitiş zorunlu."),
|
||||
allDay: z
|
||||
.union([z.boolean(), z.literal("on"), z.literal(""), z.undefined()])
|
||||
.transform((v) => v === true || v === "on")
|
||||
.optional(),
|
||||
customerId: z.string().optional().transform((v) => (v ? v : undefined)),
|
||||
color: z.string().optional().transform((v) => (v ? v : undefined)),
|
||||
})
|
||||
.refine((d) => new Date(d.end).getTime() >= new Date(d.start).getTime(), {
|
||||
message: "Bitiş tarihi başlangıçtan önce olamaz.",
|
||||
path: ["end"],
|
||||
});
|
||||
|
||||
export type CalendarEventInput = z.infer<typeof calendarEventSchema>;
|
||||
Reference in New Issue
Block a user