5a50d77515
Adds sharing (residence share codes, join, user management, .casera file export/import), subscription status with feature comparison, notification preferences with bell icon, profile settings (edit info, change password, theme picker, delete account), onboarding wizard with create/join paths, enhanced dashboard with stats cards, Recharts completion chart, recent activity feed, and task report PDF download. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
76 lines
2.5 KiB
TypeScript
76 lines
2.5 KiB
TypeScript
"use client";
|
|
|
|
import Link from "next/link";
|
|
import { Phone, Mail, Star } from "lucide-react";
|
|
import { Card, CardContent, CardHeader, CardTitle, CardDescription, CardAction } from "@/components/ui/card";
|
|
import { Badge } from "@/components/ui/badge";
|
|
import { Button } from "@/components/ui/button";
|
|
import type { ContractorResponse } from "@/lib/api/contractors";
|
|
|
|
interface ContractorCardProps {
|
|
contractor: ContractorResponse;
|
|
onToggleFavorite: (id: number) => void;
|
|
}
|
|
|
|
export function ContractorCard({ contractor, onToggleFavorite }: ContractorCardProps) {
|
|
return (
|
|
<Card className="transition-shadow hover:shadow-md">
|
|
<CardHeader>
|
|
<Link href={`/app/contractors/${contractor.id}`} className="hover:underline">
|
|
<CardTitle>{contractor.name}</CardTitle>
|
|
</Link>
|
|
{contractor.company && (
|
|
<CardDescription>{contractor.company}</CardDescription>
|
|
)}
|
|
<CardAction>
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
className="size-8"
|
|
onClick={(e) => {
|
|
e.preventDefault();
|
|
onToggleFavorite(contractor.id);
|
|
}}
|
|
>
|
|
<Star
|
|
className={
|
|
contractor.is_favorite
|
|
? "size-4 fill-yellow-400 text-yellow-400"
|
|
: "size-4 text-muted-foreground"
|
|
}
|
|
/>
|
|
</Button>
|
|
</CardAction>
|
|
</CardHeader>
|
|
<CardContent>
|
|
{contractor.specialties.length > 0 && (
|
|
<div className="flex flex-wrap gap-1 mb-3">
|
|
{contractor.specialties.map((s) => (
|
|
<Badge key={s.id} variant="secondary">
|
|
{s.icon && <span className="mr-1">{s.icon}</span>}
|
|
{s.name}
|
|
</Badge>
|
|
))}
|
|
</div>
|
|
)}
|
|
<div className="flex items-center gap-2">
|
|
{contractor.phone && (
|
|
<Button variant="outline" size="icon" className="size-8" asChild>
|
|
<a href={`tel:${contractor.phone}`} onClick={(e) => e.stopPropagation()}>
|
|
<Phone className="size-4" />
|
|
</a>
|
|
</Button>
|
|
)}
|
|
{contractor.email && (
|
|
<Button variant="outline" size="icon" className="size-8" asChild>
|
|
<a href={`mailto:${contractor.email}`} onClick={(e) => e.stopPropagation()}>
|
|
<Mail className="size-4" />
|
|
</a>
|
|
</Button>
|
|
)}
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
}
|