Fixing calander
This commit is contained in:
+225
-74
@@ -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<EventType, React.ElementType> = {
|
||||
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<CalendarEvent | null>(null)
|
||||
const [detailEvent, setDetailEvent] = useState<CalendarEvent | null>(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<EventType>("meeting")
|
||||
const [formType, setFormType] = useState<EventType>("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<string, unknown> = {
|
||||
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() {
|
||||
>
|
||||
<Icon className="h-2 w-2 shrink-0 opacity-50" />
|
||||
<span className="truncate font-medium">{event.title}</span>
|
||||
{event.lead && (
|
||||
<span className="shrink-0 text-[9px] font-semibold text-muted-foreground/50 ml-auto">
|
||||
{event.lead.contactName}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</button>
|
||||
)
|
||||
@@ -464,6 +500,15 @@ export default function CalendarPage() {
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
{/* Unscheduled projects bar */}
|
||||
{events.filter(e => !e.startTime && e.eventType === "website_creation").length > 0 && (
|
||||
<div className="flex items-center gap-2 px-3 py-2 rounded-lg border bg-gradient-to-r from-violet-500/5 to-transparent shrink-0">
|
||||
<Globe className="h-3.5 w-3.5 text-violet-500/70" />
|
||||
<span className="text-xs font-semibold text-violet-600 dark:text-violet-400">
|
||||
{events.filter(e => !e.startTime && e.eventType === "website_creation").length} unscheduled project(s)
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -534,12 +579,19 @@ export default function CalendarPage() {
|
||||
{event.status}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5 mt-1 text-[10px] text-muted-foreground/60 font-medium">
|
||||
<Clock className="h-3 w-3" />
|
||||
{formatDate(event.startTime)}
|
||||
<span className="text-muted-foreground/20">·</span>
|
||||
{formatTime(event.startTime)}
|
||||
</div>
|
||||
{event.startTime ? (
|
||||
<div className="flex items-center gap-1.5 mt-1 text-[10px] text-muted-foreground/60 font-medium">
|
||||
<Clock className="h-3 w-3" />
|
||||
{formatDate(event.startTime)}
|
||||
<span className="text-muted-foreground/20">·</span>
|
||||
{formatTime(event.startTime)}
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex items-center gap-1.5 mt-1 text-[10px] text-muted-foreground/40 font-medium">
|
||||
<Globe className="h-3 w-3" />
|
||||
Website project — no schedule
|
||||
</div>
|
||||
)}
|
||||
{event.durationMinutes && (
|
||||
<div className="flex items-center gap-1 mt-0.5 text-[10px] text-muted-foreground/40 font-medium">
|
||||
<Zap className="h-2.5 w-2.5" />
|
||||
@@ -547,21 +599,20 @@ export default function CalendarPage() {
|
||||
</div>
|
||||
)}
|
||||
<div className="flex items-center gap-1 mt-1">
|
||||
<span className={cn(
|
||||
"h-3.5 w-3.5 rounded-full text-[7px] flex items-center justify-center font-bold ring-1",
|
||||
event.userId === user?.id
|
||||
? "bg-primary/10 text-primary ring-primary/20"
|
||||
: "bg-muted text-muted-foreground/60 ring-border",
|
||||
)}>
|
||||
{event.userId === user?.id
|
||||
? (event.participant?.name.charAt(0) || "?")
|
||||
: (event.creator?.name.charAt(0) || "?")}
|
||||
</span>
|
||||
<span className="text-[10px] text-muted-foreground/60 font-medium">
|
||||
{event.userId === user?.id
|
||||
? (event.participant?.name || "No participant")
|
||||
: (event.creator?.name || "Unknown")}
|
||||
</span>
|
||||
{event.developerId === user?.id ? (
|
||||
<>
|
||||
<span className="h-3.5 w-3.5 rounded-full text-[7px] flex items-center justify-center font-bold ring-1 bg-amber-500/10 text-amber-600 dark:text-amber-400 ring-amber-500/20">
|
||||
{event.creator?.name.charAt(0) || "?"}
|
||||
</span>
|
||||
<span className="text-[10px] text-muted-foreground/60 font-medium">
|
||||
Assigned by {event.creator?.name || "Unknown"}
|
||||
</span>
|
||||
</>
|
||||
) : event.lead ? (
|
||||
<span className="text-[10px] text-muted-foreground/60 font-medium">
|
||||
{event.lead.contactName}{event.lead.companyName ? ` — ${event.lead.companyName}` : ""}
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -579,7 +630,7 @@ export default function CalendarPage() {
|
||||
|
||||
{/* Create/Edit Dialog */}
|
||||
<Dialog open={dialogOpen} onOpenChange={setDialogOpen}>
|
||||
<DialogContent className="sm:max-w-[520px]">
|
||||
<DialogContent className="sm:max-w-[520px] max-h-[90vh] overflow-y-auto">
|
||||
<DialogHeader>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className={cn(
|
||||
@@ -608,11 +659,28 @@ export default function CalendarPage() {
|
||||
<Label htmlFor="date" className="text-xs font-semibold">Date</Label>
|
||||
<Input id="date" type="date" value={formDate} onChange={(e) => setFormDate(e.target.value)} className="h-10" />
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<div className={cn("space-y-2", formType === "website_creation" && "opacity-40 pointer-events-none")}>
|
||||
<Label htmlFor="time" className="text-xs font-semibold">Time</Label>
|
||||
<Input id="time" type="time" value={formTime} onChange={(e) => setFormTime(e.target.value)} className="h-10" />
|
||||
</div>
|
||||
</div>
|
||||
{formType === "website_creation" && (
|
||||
<div className="space-y-4 rounded-xl border bg-muted/20 p-4">
|
||||
<p className="text-xs font-semibold text-muted-foreground/70 uppercase tracking-wider">Client Details</p>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="clientName" className="text-xs font-semibold">Name</Label>
|
||||
<Input id="clientName" value={formClientName} onChange={(e) => setFormClientName(e.target.value)} placeholder="Client full name" className="h-10" />
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="clientEmail" className="text-xs font-semibold">Email</Label>
|
||||
<Input id="clientEmail" type="email" value={formClientEmail} onChange={(e) => setFormClientEmail(e.target.value)} placeholder="client@example.com" className="h-10" />
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="clientPhone" className="text-xs font-semibold">Phone</Label>
|
||||
<Input id="clientPhone" type="tel" value={formClientPhone} onChange={(e) => setFormClientPhone(e.target.value)} placeholder="+1 555-123-4567" className="h-10" />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="type" className="text-xs font-semibold">Type</Label>
|
||||
@@ -621,19 +689,16 @@ export default function CalendarPage() {
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="meeting">Meeting</SelectItem>
|
||||
<SelectItem value="website_creation">Website Creation</SelectItem>
|
||||
<SelectItem value="call">Call</SelectItem>
|
||||
<SelectItem value="chat">Video Chat</SelectItem>
|
||||
<SelectItem value="follow_up">Follow Up</SelectItem>
|
||||
<SelectItem value="demo">Demo</SelectItem>
|
||||
<SelectItem value="other">Other</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="duration" className="text-xs font-semibold">Duration</Label>
|
||||
<Select value={formDuration} onValueChange={setFormDuration}>
|
||||
<SelectTrigger id="duration" className="h-10">
|
||||
<SelectTrigger id="duration" className={cn("h-10", formType === "website_creation" && "opacity-40 pointer-events-none")}>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
@@ -664,8 +729,40 @@ export default function CalendarPage() {
|
||||
</Select>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="description" className="text-xs font-semibold">Description</Label>
|
||||
<Textarea id="description" value={formDescription} onChange={(e) => setFormDescription(e.target.value)} placeholder="Add any notes or agenda items..." rows={3} className="resize-none" />
|
||||
<Label htmlFor="developer" className="text-xs font-semibold">Assign Developer</Label>
|
||||
<Select value={formDeveloperId || "__none__"} onValueChange={(v) => setFormDeveloperId(v === "__none__" ? "" : v)}>
|
||||
<SelectTrigger id="developer" className="h-10">
|
||||
<SelectValue placeholder="Select a developer…" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="__none__">None</SelectItem>
|
||||
{users.map((u) => (
|
||||
<SelectItem key={u.id} value={u.id}>
|
||||
{u.name} {u.role ? `(${u.role})` : ""}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="lead" className="text-xs font-semibold">Client</Label>
|
||||
<Select value={formLeadId || "__none__"} onValueChange={(v) => setFormLeadId(v === "__none__" ? "" : v)}>
|
||||
<SelectTrigger id="lead" className="h-10">
|
||||
<SelectValue placeholder="Select a client lead…" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="__none__">None</SelectItem>
|
||||
{leads.map((l) => (
|
||||
<SelectItem key={l.id} value={l.id}>
|
||||
{l.contactName}{l.companyName ? ` — ${l.companyName}` : ""}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="description" className="text-xs font-semibold">Project Details</Label>
|
||||
<Textarea id="description" value={formDescription} onChange={(e) => setFormDescription(e.target.value)} placeholder="Describe the project, requirements, and any relevant details..." rows={3} className="resize-none" />
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter className="flex items-center justify-between border-t pt-4">
|
||||
@@ -690,7 +787,7 @@ export default function CalendarPage() {
|
||||
{/* Event Detail Dialog */}
|
||||
<Dialog open={!!detailEvent} onOpenChange={(open) => { if (!open) setDetailEvent(null) }}>
|
||||
{detailEvent && (
|
||||
<DialogContent className="sm:max-w-[460px]">
|
||||
<DialogContent className="sm:max-w-[460px] max-h-[90vh] overflow-y-auto">
|
||||
<DialogHeader>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="p-3 rounded-xl border shadow-sm" style={eventBgStyle(detailEvent.eventType)}>
|
||||
@@ -711,22 +808,29 @@ export default function CalendarPage() {
|
||||
</DialogHeader>
|
||||
<div className="space-y-4">
|
||||
{/* Date / Time */}
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div className="p-3.5 rounded-xl bg-gradient-to-br from-muted/50 to-muted/20 border shadow-sm">
|
||||
<div className="flex items-center gap-2 text-[10px] font-semibold text-muted-foreground/50 uppercase tracking-wider mb-1.5">
|
||||
<Calendar className="h-3.5 w-3.5" />
|
||||
Date
|
||||
{detailEvent.startTime ? (
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div className="p-3.5 rounded-xl bg-gradient-to-br from-muted/50 to-muted/20 border shadow-sm">
|
||||
<div className="flex items-center gap-2 text-[10px] font-semibold text-muted-foreground/50 uppercase tracking-wider mb-1.5">
|
||||
<Calendar className="h-3.5 w-3.5" />
|
||||
Date
|
||||
</div>
|
||||
<p className="text-sm font-bold">{formatDate(detailEvent.startTime)}</p>
|
||||
</div>
|
||||
<p className="text-sm font-bold">{formatDate(detailEvent.startTime)}</p>
|
||||
</div>
|
||||
<div className="p-3.5 rounded-xl bg-gradient-to-br from-muted/50 to-muted/20 border shadow-sm">
|
||||
<div className="flex items-center gap-2 text-[10px] font-semibold text-muted-foreground/50 uppercase tracking-wider mb-1.5">
|
||||
<Clock className="h-3.5 w-3.5" />
|
||||
Time
|
||||
<div className="p-3.5 rounded-xl bg-gradient-to-br from-muted/50 to-muted/20 border shadow-sm">
|
||||
<div className="flex items-center gap-2 text-[10px] font-semibold text-muted-foreground/50 uppercase tracking-wider mb-1.5">
|
||||
<Clock className="h-3.5 w-3.5" />
|
||||
Time
|
||||
</div>
|
||||
<p className="text-sm font-bold">{formatTime(detailEvent.startTime)}</p>
|
||||
</div>
|
||||
<p className="text-sm font-bold">{formatTime(detailEvent.startTime)}</p>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="p-3.5 rounded-xl bg-gradient-to-br from-muted/50 to-muted/20 border shadow-sm">
|
||||
<p className="text-[10px] font-semibold text-muted-foreground/50 uppercase tracking-wider mb-1.5">Schedule</p>
|
||||
<p className="text-sm text-muted-foreground/50 italic">No scheduled time — website creation project</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Duration + Type */}
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
@@ -751,11 +855,26 @@ export default function CalendarPage() {
|
||||
{/* Description */}
|
||||
{detailEvent.description && (
|
||||
<div className="p-3.5 rounded-xl bg-gradient-to-br from-muted/50 to-muted/20 border shadow-sm">
|
||||
<p className="text-[10px] font-semibold text-muted-foreground/50 uppercase tracking-wider mb-1.5">Description</p>
|
||||
<p className="text-[10px] font-semibold text-muted-foreground/50 uppercase tracking-wider mb-1.5">Project Details</p>
|
||||
<p className="text-sm whitespace-pre-wrap leading-relaxed">{detailEvent.description}</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Client details */}
|
||||
{(detailEvent.clientName || detailEvent.clientEmail || detailEvent.clientPhone) && (
|
||||
<div className="p-3.5 rounded-xl bg-gradient-to-br from-violet-500/5 to-violet-500/[0.02] border shadow-sm">
|
||||
<p className="text-[10px] font-semibold text-muted-foreground/50 uppercase tracking-wider mb-1.5 flex items-center gap-1.5">
|
||||
<Users className="h-3 w-3" />
|
||||
Client Details
|
||||
</p>
|
||||
<div className="space-y-1">
|
||||
{detailEvent.clientName && <p className="text-sm font-bold">{detailEvent.clientName}</p>}
|
||||
{detailEvent.clientEmail && <p className="text-sm text-muted-foreground/70">{detailEvent.clientEmail}</p>}
|
||||
{detailEvent.clientPhone && <p className="text-sm text-muted-foreground/70">{detailEvent.clientPhone}</p>}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Linked lead */}
|
||||
{detailEvent.lead && (
|
||||
<div className="p-3.5 rounded-xl bg-gradient-to-br from-muted/50 to-muted/20 border shadow-sm">
|
||||
@@ -802,6 +921,32 @@ export default function CalendarPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Developer */}
|
||||
<div className="p-3.5 rounded-xl bg-gradient-to-br from-amber-500/5 to-amber-500/[0.02] border shadow-sm">
|
||||
<p className="text-[10px] font-semibold text-muted-foreground/50 uppercase tracking-wider mb-1.5 flex items-center gap-1.5">
|
||||
<Users className="h-3 w-3" />
|
||||
{detailEvent.developerId === user?.id ? "You (Developer)" : "Developer"}
|
||||
</p>
|
||||
{detailEvent.developer ? (
|
||||
<p className="text-sm font-bold flex items-center gap-2">
|
||||
<span className="h-6 w-6 rounded-full bg-amber-500/10 text-amber-600 dark:text-amber-400 text-[10px] flex items-center justify-center font-bold ring-1 ring-amber-500/20">
|
||||
{detailEvent.developer.name.charAt(0).toUpperCase()}
|
||||
</span>
|
||||
<span className="truncate">{detailEvent.developer.name}</span>
|
||||
{detailEvent.developer.role && (
|
||||
<span className="text-[10px] font-medium text-muted-foreground/50 capitalize shrink-0">({detailEvent.developer.role})</span>
|
||||
)}
|
||||
</p>
|
||||
) : (
|
||||
<p className="text-sm text-muted-foreground/50 italic">No developer assigned</p>
|
||||
)}
|
||||
{detailEvent.developerId === user?.id && detailEvent.userId !== user?.id && (
|
||||
<p className="text-[11px] text-muted-foreground/60 mt-1.5 font-medium">
|
||||
Assigned by {detailEvent.creator?.name || "Unknown"}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Participant Notes (editable by both parties) */}
|
||||
<div className="p-3.5 rounded-xl bg-gradient-to-br from-muted/50 to-muted/20 border shadow-sm">
|
||||
<div className="flex items-center justify-between mb-1.5">
|
||||
@@ -836,9 +981,15 @@ export default function CalendarPage() {
|
||||
<DialogFooter className="flex items-center gap-2 border-t pt-4">
|
||||
{detailEvent.status === "scheduled" && (
|
||||
<>
|
||||
<Button variant="default" size="sm" onClick={() => updateEventStatus(detailEvent, "completed")} className="shadow-sm">
|
||||
<CheckCircle2 className="h-4 w-4 mr-1.5" /> Complete
|
||||
</Button>
|
||||
{detailEvent.developerId === user?.id ? (
|
||||
<Button variant="default" size="default" onClick={() => updateEventStatus(detailEvent, "completed")} className="shadow-sm bg-emerald-600 hover:bg-emerald-700">
|
||||
<CheckCircle2 className="h-4 w-4 mr-1.5" /> Mark Done
|
||||
</Button>
|
||||
) : (
|
||||
<Button variant="default" size="sm" onClick={() => updateEventStatus(detailEvent, "completed")} className="shadow-sm">
|
||||
<CheckCircle2 className="h-4 w-4 mr-1.5" /> Complete
|
||||
</Button>
|
||||
)}
|
||||
<Button variant="outline" size="sm" onClick={() => updateEventStatus(detailEvent, "cancelled")}>
|
||||
<XCircle className="h-4 w-4 mr-1.5" /> Cancel
|
||||
</Button>
|
||||
|
||||
Reference in New Issue
Block a user