151 lines
5.0 KiB
TypeScript
151 lines
5.0 KiB
TypeScript
"use client";
|
|
|
|
import { Button } from "@/components/ui/button";
|
|
import {
|
|
DropdownMenu,
|
|
DropdownMenuContent,
|
|
DropdownMenuItem,
|
|
DropdownMenuTrigger,
|
|
} from "@/components/ui/dropdown-menu";
|
|
import {
|
|
Collapsible,
|
|
CollapsibleContent,
|
|
CollapsibleTrigger,
|
|
} from "@/components/ui/collapsible";
|
|
import { CategoryIcon } from "@/components/ui/category-icon";
|
|
import {
|
|
Plus,
|
|
MoreVertical,
|
|
Pencil,
|
|
Trash2,
|
|
ChevronDown,
|
|
ChevronRight,
|
|
} from "lucide-react";
|
|
import { useIsMobile } from "@/hooks/use-mobile";
|
|
import { CategoryCard } from "./category-card";
|
|
import type { Category } from "@/lib/types";
|
|
|
|
interface ParentCategoryRowProps {
|
|
parent: Category;
|
|
children: Category[];
|
|
stats: { total: number; count: number };
|
|
isExpanded: boolean;
|
|
onToggleExpanded: () => void;
|
|
formatCurrency: (amount: number) => string;
|
|
getCategoryStats: (categoryId: string) => { total: number; count: number };
|
|
onEdit: (category: Category) => void;
|
|
onDelete: (categoryId: string) => void;
|
|
onNewCategory: (parentId: string) => void;
|
|
}
|
|
|
|
export function ParentCategoryRow({
|
|
parent,
|
|
children,
|
|
stats,
|
|
isExpanded,
|
|
onToggleExpanded,
|
|
formatCurrency,
|
|
getCategoryStats,
|
|
onEdit,
|
|
onDelete,
|
|
onNewCategory,
|
|
}: ParentCategoryRowProps) {
|
|
const isMobile = useIsMobile();
|
|
|
|
return (
|
|
<div className="border rounded-lg bg-card">
|
|
<Collapsible open={isExpanded} onOpenChange={onToggleExpanded}>
|
|
<div className="flex items-center justify-between px-2 md:px-3 py-1.5 md:py-2">
|
|
<CollapsibleTrigger asChild>
|
|
<button className="flex items-center gap-1.5 md:gap-2 hover:opacity-80 transition-opacity flex-1 min-w-0">
|
|
{isExpanded ? (
|
|
<ChevronDown className="w-3 h-3 md:w-4 md:h-4 text-muted-foreground shrink-0" />
|
|
) : (
|
|
<ChevronRight className="w-3 h-3 md:w-4 md:h-4 text-muted-foreground shrink-0" />
|
|
)}
|
|
<div
|
|
className="w-5 h-5 md:w-7 md:h-7 rounded-full flex items-center justify-center shrink-0"
|
|
style={{ backgroundColor: `${parent.color}20` }}
|
|
>
|
|
<CategoryIcon
|
|
icon={parent.icon}
|
|
color={parent.color}
|
|
size={isMobile ? 10 : 14}
|
|
/>
|
|
</div>
|
|
<span className="font-medium text-xs md:text-sm truncate">{parent.name}</span>
|
|
{!isMobile && (
|
|
<span className="text-xs md:text-sm text-muted-foreground shrink-0">
|
|
{children.length} • {stats.count} opération
|
|
{stats.count > 1 ? "s" : ""} • {formatCurrency(stats.total)}
|
|
</span>
|
|
)}
|
|
{isMobile && (
|
|
<span className="text-[10px] md:text-xs text-muted-foreground shrink-0">
|
|
{children.length} • {stats.count} 💳
|
|
</span>
|
|
)}
|
|
</button>
|
|
</CollapsibleTrigger>
|
|
|
|
<div className="flex items-center gap-0.5 md:gap-1 shrink-0 ml-1 md:ml-2">
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
className="h-6 w-6 md:h-7 md:w-7"
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
onNewCategory(parent.id);
|
|
}}
|
|
>
|
|
<Plus className="w-3 h-3 md:w-4 md:h-4" />
|
|
</Button>
|
|
<DropdownMenu>
|
|
<DropdownMenuTrigger asChild>
|
|
<Button variant="ghost" size="icon" className="h-6 w-6 md:h-7 md:w-7">
|
|
<MoreVertical className="w-3 h-3 md:w-4 md:h-4" />
|
|
</Button>
|
|
</DropdownMenuTrigger>
|
|
<DropdownMenuContent align="end">
|
|
<DropdownMenuItem onClick={() => onEdit(parent)}>
|
|
<Pencil className="w-4 h-4 mr-2" />
|
|
Modifier
|
|
</DropdownMenuItem>
|
|
<DropdownMenuItem
|
|
onClick={() => onDelete(parent.id)}
|
|
className="text-red-600"
|
|
>
|
|
<Trash2 className="w-4 h-4 mr-2" />
|
|
Supprimer
|
|
</DropdownMenuItem>
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
</div>
|
|
</div>
|
|
|
|
<CollapsibleContent>
|
|
{children.length > 0 ? (
|
|
<div className="px-2 md:px-3 pb-2 space-y-1 ml-4 md:ml-6 border-l-2 border-muted md:ml-5">
|
|
{children.map((child) => (
|
|
<CategoryCard
|
|
key={child.id}
|
|
category={child}
|
|
stats={getCategoryStats(child.id)}
|
|
formatCurrency={formatCurrency}
|
|
onEdit={onEdit}
|
|
onDelete={onDelete}
|
|
/>
|
|
))}
|
|
</div>
|
|
) : (
|
|
<div className="px-3 pb-2 ml-11 text-xs text-muted-foreground italic">
|
|
Aucune sous-catégorie
|
|
</div>
|
|
)}
|
|
</CollapsibleContent>
|
|
</Collapsible>
|
|
</div>
|
|
);
|
|
}
|
|
|