From d138c602037b3ad880dbc262bda471b052f75bd3 Mon Sep 17 00:00:00 2001 From: Ace Date: Fri, 26 Jun 2026 21:36:09 +0200 Subject: [PATCH] Fixing calander --- Web_Calendar/calendar/page.tsx | 299 +++++++++++++----- Web_Calendar/types.ts | 7 +- .../migrations/017_calendar_developer.sql | 4 + .../migrations/018_website_creation_type.sql | 8 + .../migrations/019_allow_null_start_time.sql | 2 + database/migrations/run_all.sql | 9 + scripts/precheck.mjs | 36 ++- src/app/(dashboard)/calendar/page.tsx | 243 ++++++++++---- src/app/api/event-users/route.ts | 6 +- src/app/api/events/[id]/route.ts | 47 ++- src/app/api/events/route.ts | 88 +++++- src/app/globals.css | 5 +- src/types/index.ts | 7 +- 13 files changed, 598 insertions(+), 163 deletions(-) create mode 100644 database/migrations/017_calendar_developer.sql create mode 100644 database/migrations/018_website_creation_type.sql create mode 100644 database/migrations/019_allow_null_start_time.sql diff --git a/Web_Calendar/calendar/page.tsx b/Web_Calendar/calendar/page.tsx index c1e8783..e8930c0 100644 --- a/Web_Calendar/calendar/page.tsx +++ b/Web_Calendar/calendar/page.tsx @@ -21,17 +21,14 @@ import { useNotifications } from "@/providers/notification-provider" import { toast } from "sonner" import { ChevronLeft, ChevronRight, Plus, Calendar, Clock, Phone, - Video, Users, CheckCircle2, XCircle, RotateCcw, Loader2, - ArrowUpRight, Zap, StickyNote, + Users, CheckCircle2, XCircle, RotateCcw, Loader2, + ArrowUpRight, Zap, StickyNote, Globe, } from "lucide-react" const EVENT_ICONS: Record = { - meeting: Users, call: Phone, - chat: Video, follow_up: Clock, - demo: Calendar, - other: Calendar, + website_creation: Globe, } function eventVars(type: EventType) { @@ -85,14 +82,20 @@ export default function CalendarPage() { const [editingEvent, setEditingEvent] = useState(null) const [detailEvent, setDetailEvent] = useState(null) - const [users, setUsers] = useState<{ id: string; name: string; email: string }[]>([]) + const [users, setUsers] = useState<{ id: string; name: string; email: string; role: string }[]>([]) + const [leads, setLeads] = useState<{ id: string; contactName: string; companyName: string }[]>([]) const [formTitle, setFormTitle] = useState("") const [formDescription, setFormDescription] = useState("") - const [formType, setFormType] = useState("meeting") + const [formType, setFormType] = useState("website_creation") const [formDate, setFormDate] = useState("") const [formTime, setFormTime] = useState("") const [formDuration, setFormDuration] = useState("30") const [formParticipantId, setFormParticipantId] = useState("") + const [formDeveloperId, setFormDeveloperId] = useState("") + const [formLeadId, setFormLeadId] = useState("") + const [formClientName, setFormClientName] = useState("") + const [formClientEmail, setFormClientEmail] = useState("") + const [formClientPhone, setFormClientPhone] = useState("") const [formSaving, setFormSaving] = useState(false) const [editNotes, setEditNotes] = useState(false) const [notesText, setNotesText] = useState("") @@ -124,6 +127,10 @@ export default function CalendarPage() { .then((r) => r.json()) .then((data) => setUsers(data.users || [])) .catch(() => {}) + fetch("/api/leads?limit=200") + .then((r) => r.json()) + .then((data) => setLeads((Array.isArray(data) ? data : data?.leads || []).map((l: any) => ({ id: l.id, contactName: l.contactName, companyName: l.companyName })))) + .catch(() => {}) }, [user, router]) useEffect(() => { @@ -158,7 +165,7 @@ export default function CalendarPage() { const getEventsForDay = useCallback((day: number) => { const dateStr = `${currentYear}-${String(currentMonth + 1).padStart(2, "0")}-${String(day).padStart(2, "0")}` - return events.filter((e) => e.startTime.startsWith(dateStr)) + return events.filter((e) => e.startTime && e.startTime.startsWith(dateStr)) }, [events, currentYear, currentMonth]) const isToday = (day: number) => { @@ -169,9 +176,14 @@ export default function CalendarPage() { setEditingEvent(null) setFormTitle("") setFormDescription("") - setFormType("meeting") + setFormType("website_creation") setFormDuration("30") setFormParticipantId("") + setFormDeveloperId("") + setFormLeadId("") + setFormClientName("") + setFormClientEmail("") + setFormClientPhone("") const d = day ? new Date(currentYear, currentMonth, day) : new Date() setFormDate(d.toISOString().split("T")[0]) setFormTime("10:00") @@ -184,9 +196,14 @@ export default function CalendarPage() { setFormDescription(event.description || "") setFormType(event.eventType) setFormDuration(String(event.durationMinutes || 30)) - setFormDate(new Date(event.startTime).toISOString().split("T")[0]) - setFormTime(new Date(event.startTime).toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit", hour12: false })) + setFormDate(event.startTime ? new Date(event.startTime).toISOString().split("T")[0] : "") + setFormTime(event.startTime ? new Date(event.startTime).toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit", hour12: false }) : "10:00") setFormParticipantId(event.participantId || "") + setFormDeveloperId(event.developerId || "") + setFormLeadId(event.leadId || "") + setFormClientName(event.clientName || "") + setFormClientEmail(event.clientEmail || "") + setFormClientPhone(event.clientPhone || "") setDialogOpen(true) } @@ -198,23 +215,35 @@ export default function CalendarPage() { setFormSaving(true) try { - const startTime = new Date(`${formDate}T${formTime}:00`).toISOString() - let endTime = null - if (formDuration) { - const end = new Date(startTime) - end.setMinutes(end.getMinutes() + parseInt(formDuration)) - endTime = end.toISOString() - } - const body: Record = { title: formTitle.trim(), description: formDescription.trim() || null, eventType: formType, - startTime, - endTime, - durationMinutes: formDuration ? parseInt(formDuration) : null, } + + let startTime: string | undefined + if (formType !== "website_creation") { + startTime = new Date(`${formDate}T${formTime}:00`).toISOString() + let endTime = null + if (formDuration) { + const end = new Date(startTime) + end.setMinutes(end.getMinutes() + parseInt(formDuration)) + endTime = end.toISOString() + } + body.startTime = startTime + body.endTime = endTime + body.durationMinutes = formDuration ? parseInt(formDuration) : null + } else if (formDate) { + startTime = new Date(`${formDate}T00:00:00`).toISOString() + body.startTime = startTime + } + + if (formClientName) body.clientName = formClientName + if (formClientEmail) body.clientEmail = formClientEmail + if (formClientPhone) body.clientPhone = formClientPhone if (formParticipantId) body.participantId = formParticipantId + if (formDeveloperId) body.developerId = formDeveloperId + if (formLeadId) body.leadId = formLeadId let res if (editingEvent) { @@ -235,11 +264,13 @@ export default function CalendarPage() { const data = await res.json() if (editingEvent) { - setEvents((prev) => prev.map((e) => e.id === editingEvent.id ? { ...data.event, participant: e.participant, lead: e.lead } : e)) + setEvents((prev) => prev.map((e) => e.id === editingEvent.id ? { ...data.event, participant: e.participant, developer: e.developer, lead: e.lead } : e)) toast.success("Event updated") } else { setEvents((prev) => [...prev, data.event]) - addNotification("event_scheduled", `Event created: ${formTitle}`, `Scheduled for ${formatDate(startTime)} at ${formatTime(startTime)}`, "/calendar") + if (startTime) { + addNotification("event_scheduled", `Event created: ${formTitle}`, `Scheduled for ${formatDate(startTime)} at ${formatTime(startTime)}`, "/calendar") + } toast.success("Event created") } @@ -260,7 +291,7 @@ export default function CalendarPage() { }) if (!res.ok) throw new Error("Failed to update") const data = await res.json() - setEvents((prev) => prev.map((e) => e.id === event.id ? { ...data.event, participant: e.participant, lead: e.lead } : e)) + setEvents((prev) => prev.map((e) => e.id === event.id ? { ...data.event, participant: e.participant, developer: e.developer, lead: e.lead } : e)) toast.success(`Event ${newStatus}`) setDetailEvent(null) } catch { @@ -446,6 +477,11 @@ export default function CalendarPage() { > {event.title} + {event.lead && ( + + {event.lead.contactName} + + )} ) @@ -464,6 +500,15 @@ export default function CalendarPage() { })} + {/* Unscheduled projects bar */} + {events.filter(e => !e.startTime && e.eventType === "website_creation").length > 0 && ( +
+ + + {events.filter(e => !e.startTime && e.eventType === "website_creation").length} unscheduled project(s) + +
+ )} @@ -534,12 +579,19 @@ export default function CalendarPage() { {event.status} -
- - {formatDate(event.startTime)} - · - {formatTime(event.startTime)} -
+ {event.startTime ? ( +
+ + {formatDate(event.startTime)} + · + {formatTime(event.startTime)} +
+ ) : ( +
+ + Website project — no schedule +
+ )} {event.durationMinutes && (
@@ -547,21 +599,20 @@ export default function CalendarPage() {
)}
- - {event.userId === user?.id - ? (event.participant?.name.charAt(0) || "?") - : (event.creator?.name.charAt(0) || "?")} - - - {event.userId === user?.id - ? (event.participant?.name || "No participant") - : (event.creator?.name || "Unknown")} - + {event.developerId === user?.id ? ( + <> + + {event.creator?.name.charAt(0) || "?"} + + + Assigned by {event.creator?.name || "Unknown"} + + + ) : event.lead ? ( + + {event.lead.contactName}{event.lead.companyName ? ` — ${event.lead.companyName}` : ""} + + ) : null}
@@ -579,7 +630,7 @@ export default function CalendarPage() { {/* Create/Edit Dialog */} - +
Date setFormDate(e.target.value)} className="h-10" />
-
+
setFormTime(e.target.value)} className="h-10" />
+ {formType === "website_creation" && ( +
+

Client Details

+
+ + setFormClientName(e.target.value)} placeholder="Client full name" className="h-10" /> +
+
+ + setFormClientEmail(e.target.value)} placeholder="client@example.com" className="h-10" /> +
+
+ + setFormClientPhone(e.target.value)} placeholder="+1 555-123-4567" className="h-10" /> +
+
+ )}
@@ -621,19 +689,16 @@ export default function CalendarPage() { - Meeting + Website Creation Call - Video Chat Follow Up - Demo - Other
- -