diff --git a/package.json b/package.json index 7fb48c3..60ce11a 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.1.0", "private": true, "scripts": { - "dev": "next dev", + "dev": "next dev -p 3006", "build": "next build", "start": "next start", "lint": "eslint" diff --git a/src/app/(dashboard)/dashboard/page.tsx b/src/app/(dashboard)/dashboard/page.tsx index bda9349..6b36c95 100644 --- a/src/app/(dashboard)/dashboard/page.tsx +++ b/src/app/(dashboard)/dashboard/page.tsx @@ -1,12 +1,13 @@ "use client" -import { useState } from "react" +import { useState, useEffect } from "react" import { PageHeader } from "@/components/shared/page-header" import { StatCard } from "@/components/dashboard/stat-card" +import { StatCardSkeleton } from "@/components/dashboard/stat-card-skeleton" import { RecentLeadsTable } from "@/components/dashboard/recent-leads-table" import { LeadStatusChart } from "@/components/dashboard/lead-status-chart" import { LeadsPerMonthChart } from "@/components/dashboard/leads-per-month-chart" -import { dashboardStats } from "@/data/dashboard" +import { getDashboardStats } from "@/data/dashboard" import { Users, UserPlus, @@ -23,19 +24,26 @@ import { SelectTrigger, SelectValue, } from "@/components/ui/select" +import { DashboardStats } from "@/types" export default function DashboardPage() { - const stats = dashboardStats const [period, setPeriod] = useState("6months") + const [stats, setStats] = useState(null) - const statCards = [ - { title: "Total Leads", value: stats.totalLeads, icon: Users, variant: "blue" as const, description: "All time" }, - { title: "Open Leads", value: stats.openLeads, icon: UserPlus, variant: "blue" as const, description: "Needs attention" }, - { title: "Contacted", value: stats.contactedLeads, icon: PhoneCall, variant: "amber" as const, description: "In conversation" }, - { title: "Pending", value: stats.pendingLeads, icon: Clock, variant: "purple" as const, description: "Awaiting decision" }, - { title: "Closed", value: stats.closedLeads, icon: CheckCircle2, variant: "emerald" as const, description: "Won" }, - { title: "Conversion Rate", value: `${stats.conversionRate}%`, icon: TrendingUp, variant: "emerald" as const, description: `${stats.closedLeads} of ${stats.totalLeads} leads` }, - ] + useEffect(() => { + setStats(getDashboardStats(period)) + }, [period]) + + const statCards = stats + ? [ + { title: "Total Leads", value: stats.totalLeads, icon: Users, variant: "blue" as const, description: stats.periodLabel }, + { title: "Open Leads", value: stats.openLeads, icon: UserPlus, variant: "blue" as const, description: "Needs attention" }, + { title: "Contacted", value: stats.contactedLeads, icon: PhoneCall, variant: "amber" as const, description: "In conversation" }, + { title: "Pending", value: stats.pendingLeads, icon: Clock, variant: "purple" as const, description: "Awaiting decision" }, + { title: "Closed", value: stats.closedLeads, icon: CheckCircle2, variant: "emerald" as const, description: "Won" }, + { title: "Conversion Rate", value: `${stats.conversionRate}%`, icon: TrendingUp, variant: "emerald" as const, description: `${stats.closedLeads} of ${stats.totalLeads} leads` }, + ] + : [] return (
@@ -55,17 +63,20 @@ export default function DashboardPage() {
- {statCards.map((card, i) => ( - - ))} + {stats + ? statCards.map((card, i) => ( + + )) + : Array.from({ length: 6 }).map((_, i) => ) + }
- - + +
- +
) } diff --git a/src/app/(dashboard)/leads/page.tsx b/src/app/(dashboard)/leads/page.tsx index 94114be..578043c 100644 --- a/src/app/(dashboard)/leads/page.tsx +++ b/src/app/(dashboard)/leads/page.tsx @@ -6,15 +6,21 @@ import { LeadsTable } from "@/components/leads/leads-table" import { LeadsTableToolbar } from "@/components/leads/leads-table-toolbar" import { LeadFormDialog } from "@/components/leads/lead-form-dialog" import { leads } from "@/data/leads" +import { filterLeadsByPeriod } from "@/lib/date-utils" export default function LeadsPage() { const [search, setSearch] = useState("") const [statusFilter, setStatusFilter] = useState("all") + const [periodFilter, setPeriodFilter] = useState("all") const [createOpen, setCreateOpen] = useState(false) const filteredLeads = useMemo(() => { let result = leads + if (periodFilter && periodFilter !== "all") { + result = filterLeadsByPeriod(result, periodFilter) + } + if (search) { const q = search.toLowerCase() result = result.filter( @@ -31,7 +37,7 @@ export default function LeadsPage() { } return result - }, [search, statusFilter]) + }, [search, statusFilter, periodFilter]) return (
@@ -47,6 +53,8 @@ export default function LeadsPage() { onSearchChange={setSearch} statusFilter={statusFilter} onStatusFilterChange={setStatusFilter} + periodFilter={periodFilter} + onPeriodFilterChange={setPeriodFilter} onCreateClick={() => setCreateOpen(true)} />
diff --git a/src/components/dashboard/leads-per-month-chart.tsx b/src/components/dashboard/leads-per-month-chart.tsx index 1be8046..b245d36 100644 --- a/src/components/dashboard/leads-per-month-chart.tsx +++ b/src/components/dashboard/leads-per-month-chart.tsx @@ -4,14 +4,14 @@ import { useState, useMemo } from "react" import { motion } from "framer-motion" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" -interface MonthlyData { - month: string +interface IntervalData { + label: string leads: number closed: number } interface LeadsPerMonthChartProps { - data: MonthlyData[] + data: IntervalData[] } const BAR_GRADIENT_TOP = "#3B6AB8" @@ -138,7 +138,7 @@ export function LeadsPerMonthChart({ data }: LeadsPerMonthChartProps) { return ( setHovered(i)} onMouseLeave={() => setHovered(null)} style={{ cursor: "pointer" }} @@ -188,7 +188,7 @@ export function LeadsPerMonthChart({ data }: LeadsPerMonthChartProps) { fontWeight={isActive ? 600 : 400} textAnchor="middle" > - {d.month} + {d.label} ) @@ -216,7 +216,7 @@ export function LeadsPerMonthChart({ data }: LeadsPerMonthChartProps) { }} >
- {activeDatum.month} + {activeDatum.label}
diff --git a/src/components/leads/leads-table-toolbar.tsx b/src/components/leads/leads-table-toolbar.tsx index 605386b..4ff4416 100644 --- a/src/components/leads/leads-table-toolbar.tsx +++ b/src/components/leads/leads-table-toolbar.tsx @@ -1,6 +1,5 @@ "use client" -import { useState } from "react" import { Input } from "@/components/ui/input" import { Button } from "@/components/ui/button" import { @@ -10,14 +9,15 @@ import { SelectTrigger, SelectValue, } from "@/components/ui/select" -import { Search, Plus, SlidersHorizontal } from "lucide-react" -import { LeadStatus } from "@/types" +import { Search, Plus } from "lucide-react" interface LeadsTableToolbarProps { search: string onSearchChange: (value: string) => void statusFilter: string onStatusFilterChange: (value: string) => void + periodFilter: string + onPeriodFilterChange: (value: string) => void onCreateClick: () => void } @@ -26,6 +26,8 @@ export function LeadsTableToolbar({ onSearchChange, statusFilter, onStatusFilterChange, + periodFilter, + onPeriodFilterChange, onCreateClick, }: LeadsTableToolbarProps) { return ( @@ -40,6 +42,18 @@ export function LeadsTableToolbar({ />
+ -