mirror of
https://git.coastit.co.za/caitlin/CRM_ENVR.git
synced 2026-07-10 11:15:43 +02:00
157 lines
5.5 KiB
TypeScript
157 lines
5.5 KiB
TypeScript
"use client"
|
|
|
|
import Link from "next/link"
|
|
import { motion } from "framer-motion"
|
|
import { PageHeader } from "@/components/shared/page-header"
|
|
import { LeadDetailsCard } from "@/components/leads/lead-details-card"
|
|
import { LeadStatusBadge } from "@/components/leads/lead-status-badge"
|
|
import { NoteTimeline } from "@/components/notes/note-timeline"
|
|
import { NoteForm } from "@/components/notes/note-form"
|
|
import { Button } from "@/components/ui/button"
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
} from "@/components/ui/select"
|
|
import { getLeadById } from "@/data/leads"
|
|
import { getNotesByLeadId } from "@/data/notes"
|
|
import { use } from "react"
|
|
import { ArrowLeft, Edit, ExternalLink } from "lucide-react"
|
|
|
|
export default function LeadDetailsPage({ params }: { params: Promise<{ id: string }> }) {
|
|
const { id } = use(params)
|
|
const lead = getLeadById(id)
|
|
const leadNotes = lead ? getNotesByLeadId(lead.id) : []
|
|
|
|
if (!lead) {
|
|
return (
|
|
<div className="flex items-center justify-center h-[60vh]">
|
|
<div className="text-center">
|
|
<h2 className="text-2xl font-bold">Lead not found</h2>
|
|
<p className="mt-2 text-muted-foreground">The lead you are looking for does not exist.</p>
|
|
<Link href="/leads" className="mt-4 inline-block">
|
|
<Button variant="outline">
|
|
<ArrowLeft className="mr-2 h-4 w-4" />
|
|
Back to Leads
|
|
</Button>
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<Link
|
|
href="/leads"
|
|
className="inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground transition-colors"
|
|
>
|
|
<ArrowLeft className="h-4 w-4" />
|
|
Back to leads
|
|
</Link>
|
|
|
|
<PageHeader
|
|
title={
|
|
<div className="flex items-center gap-3">
|
|
<span>{lead.companyName}</span>
|
|
<LeadStatusBadge status={lead.status} />
|
|
</div>
|
|
}
|
|
description={lead.contactName}
|
|
>
|
|
<div className="flex items-center gap-3">
|
|
<Select defaultValue={lead.status}>
|
|
<SelectTrigger className="h-9 w-[140px]">
|
|
<SelectValue />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="open">Open</SelectItem>
|
|
<SelectItem value="contacted">Contacted</SelectItem>
|
|
<SelectItem value="pending">Pending</SelectItem>
|
|
<SelectItem value="closed">Closed</SelectItem>
|
|
<SelectItem value="ignored">Ignored</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
<Button className="gap-2">
|
|
<Edit className="h-4 w-4" />
|
|
Edit
|
|
</Button>
|
|
</div>
|
|
</PageHeader>
|
|
|
|
<div className="grid gap-6 lg:grid-cols-3">
|
|
<div className="space-y-6 lg:col-span-2">
|
|
<LeadDetailsCard lead={lead} />
|
|
<div className="space-y-6">
|
|
<NoteForm leadId={lead.id} />
|
|
<NoteTimeline notes={leadNotes} />
|
|
</div>
|
|
</div>
|
|
|
|
<div className="space-y-6">
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.3, delay: 0.1 }}
|
|
>
|
|
<div className="rounded-lg border bg-card">
|
|
<div className="border-b px-6 py-4">
|
|
<h3 className="font-semibold">Activity</h3>
|
|
</div>
|
|
<div className="divide-y">
|
|
{[
|
|
{ action: "Lead created", date: lead.createdAt, user: lead.assignedUser?.name || "System" },
|
|
...leadNotes.slice(0, 3).map((n) => ({
|
|
action: "Note added",
|
|
date: n.createdAt,
|
|
user: n.authorName,
|
|
})),
|
|
].map((activity, i) => (
|
|
<div key={i} className="px-6 py-3">
|
|
<div className="flex items-center gap-2">
|
|
<div className="h-2 w-2 rounded-full bg-primary/60 shrink-0" />
|
|
<p className="text-sm">{activity.action}</p>
|
|
</div>
|
|
<p className="mt-0.5 text-xs text-muted-foreground pl-4">
|
|
by {activity.user} · {new Date(activity.date).toLocaleDateString(undefined, {
|
|
month: "short",
|
|
day: "numeric",
|
|
hour: "2-digit",
|
|
minute: "2-digit",
|
|
})}
|
|
</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</motion.div>
|
|
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.3, delay: 0.2 }}
|
|
>
|
|
<div className="rounded-lg border bg-card">
|
|
<div className="border-b px-6 py-4">
|
|
<h3 className="font-semibold">Quick Actions</h3>
|
|
</div>
|
|
<div className="p-4 space-y-2">
|
|
<Button variant="outline" className="w-full justify-start" size="sm">
|
|
<ExternalLink className="mr-2 h-4 w-4" />
|
|
Send Email
|
|
</Button>
|
|
<Button variant="outline" className="w-full justify-start" size="sm">
|
|
<ExternalLink className="mr-2 h-4 w-4" />
|
|
Call Lead
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</motion.div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|