Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM, PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source files covering clients, berths, interests/pipeline, documents/EOI, expenses/invoices, email, notifications, dashboard, admin, and client portal. CI/CD via Gitea Actions with Docker builds. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
68
src/components/interests/pipeline-card.tsx
Normal file
68
src/components/interests/pipeline-card.tsx
Normal file
@@ -0,0 +1,68 @@
|
||||
'use client';
|
||||
|
||||
import { useSortable } from '@dnd-kit/sortable';
|
||||
import { CSS } from '@dnd-kit/utilities';
|
||||
import { differenceInDays } from 'date-fns';
|
||||
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
|
||||
interface PipelineCardProps {
|
||||
id: string;
|
||||
clientName: string | null;
|
||||
berthMooringNumber: string | null;
|
||||
leadCategory: string | null;
|
||||
updatedAt: string | Date;
|
||||
}
|
||||
|
||||
const LEAD_CATEGORY_COLORS: Record<string, string> = {
|
||||
general_interest: 'secondary',
|
||||
specific_qualified: 'default',
|
||||
hot_lead: 'destructive',
|
||||
};
|
||||
|
||||
export function PipelineCard({
|
||||
id,
|
||||
clientName,
|
||||
berthMooringNumber,
|
||||
leadCategory,
|
||||
updatedAt,
|
||||
}: PipelineCardProps) {
|
||||
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
|
||||
id,
|
||||
});
|
||||
|
||||
const style = {
|
||||
transform: CSS.Transform.toString(transform),
|
||||
transition,
|
||||
opacity: isDragging ? 0.5 : 1,
|
||||
};
|
||||
|
||||
const daysInStage = differenceInDays(new Date(), new Date(updatedAt));
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={setNodeRef}
|
||||
style={style}
|
||||
{...attributes}
|
||||
{...listeners}
|
||||
className="bg-card border rounded-md p-3 shadow-sm cursor-grab active:cursor-grabbing space-y-2"
|
||||
>
|
||||
<p className="text-sm font-medium truncate">{clientName ?? 'Unknown client'}</p>
|
||||
|
||||
{berthMooringNumber && (
|
||||
<p className="text-xs text-muted-foreground">Berth: {berthMooringNumber}</p>
|
||||
)}
|
||||
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
{leadCategory && (
|
||||
<Badge variant={(LEAD_CATEGORY_COLORS[leadCategory] as any) ?? 'secondary'}>
|
||||
{leadCategory.replace(/_/g, ' ')}
|
||||
</Badge>
|
||||
)}
|
||||
<span className="text-xs text-muted-foreground ml-auto">
|
||||
{daysInStage}d
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user