mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage
synced 2026-04-11 18:28:15 +00:00
feat: build Lead Workspace page with KPIs, source grid, lead cards, and sidebar widgets
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,11 +1,91 @@
|
||||
import { TopBar } from "@/components/layout/top-bar";
|
||||
import { useState } from 'react';
|
||||
|
||||
import { Button } from '@/components/base/buttons/button';
|
||||
import { TopBar } from '@/components/layout/top-bar';
|
||||
import { KpiCards } from '@/components/leads/kpi-cards';
|
||||
import { SourceGrid } from '@/components/leads/source-grid';
|
||||
import { LeadCard } from '@/components/leads/lead-card';
|
||||
import { AgingWidget } from '@/components/leads/aging-widget';
|
||||
import { FollowupWidget } from '@/components/leads/followup-widget';
|
||||
import { AlertsWidget } from '@/components/leads/alerts-widget';
|
||||
import { useLeads } from '@/hooks/use-leads';
|
||||
import { useFollowUps } from '@/hooks/use-follow-ups';
|
||||
import type { LeadSource } from '@/types/entities';
|
||||
|
||||
export const LeadWorkspacePage = () => {
|
||||
const [sourceFilter, setSourceFilter] = useState<LeadSource | null>(null);
|
||||
|
||||
const { leads, total } = useLeads({ source: sourceFilter ?? undefined, status: 'NEW' });
|
||||
const { leads: allLeads } = useLeads();
|
||||
const { overdue, upcoming } = useFollowUps();
|
||||
|
||||
const displayLeads = leads.slice(0, 10);
|
||||
|
||||
const handleAssign = () => {
|
||||
// placeholder
|
||||
};
|
||||
|
||||
const handleMessage = () => {
|
||||
// placeholder
|
||||
};
|
||||
|
||||
const handleMarkSpam = () => {
|
||||
// placeholder
|
||||
};
|
||||
|
||||
const handleMerge = () => {
|
||||
// placeholder
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-1 flex-col">
|
||||
<TopBar title="Lead Workspace" subtitle="Ramaiah Memorial Hospital · Last 24 hours" />
|
||||
<div className="flex flex-1 items-center justify-center p-8">
|
||||
<p className="text-tertiary">Lead Workspace — coming soon</p>
|
||||
<div className="flex flex-1 overflow-hidden">
|
||||
{/* Main content */}
|
||||
<div className="flex-1 space-y-6 overflow-y-auto p-7">
|
||||
<KpiCards leads={allLeads} />
|
||||
|
||||
<div>
|
||||
<div className="mb-3 flex items-center justify-between">
|
||||
<h2 className="font-display text-md font-bold text-primary">Lead Sources</h2>
|
||||
<span className="text-xs text-quaternary">Click to filter</span>
|
||||
</div>
|
||||
<SourceGrid leads={allLeads} onSourceFilter={setSourceFilter} activeSource={sourceFilter} />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="mb-3.5 flex items-center justify-between">
|
||||
<h2 className="font-display text-md font-bold text-primary">New Leads</h2>
|
||||
<Button href="/leads" color="link-color" size="sm">
|
||||
View All {total} Leads
|
||||
</Button>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
{displayLeads.map((lead) => (
|
||||
<LeadCard
|
||||
key={lead.id}
|
||||
lead={lead}
|
||||
onAssign={handleAssign}
|
||||
onMessage={handleMessage}
|
||||
onMarkSpam={handleMarkSpam}
|
||||
onMerge={handleMerge}
|
||||
/>
|
||||
))}
|
||||
{displayLeads.length === 0 && (
|
||||
<p className="py-8 text-center text-sm text-tertiary">
|
||||
No leads match the current filters.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right sidebar */}
|
||||
<aside className="hidden w-80 space-y-5 overflow-y-auto border-l border-secondary bg-primary p-5 xl:block">
|
||||
<AgingWidget leads={allLeads} />
|
||||
<FollowupWidget overdue={overdue} upcoming={upcoming} />
|
||||
<AlertsWidget leads={allLeads} />
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user