"use client";
import * as React from "react";
import { Button } from "~/components/ui/button";
import { Card, CardContent } from "~/components/ui/card";
import { Input } from "~/components/ui/input";
import { Label } from "~/components/ui/label";
import { DatePicker } from "~/components/ui/date-picker";
import { NumberInput } from "~/components/ui/number-input";
import {
Trash2,
Plus,
GripVertical,
ChevronUp,
ChevronDown,
} from "lucide-react";
import { cn } from "~/lib/utils";
interface InvoiceItem {
id: string;
date: Date;
description: string;
hours: number;
rate: number;
amount: number;
}
interface InvoiceLineItemsProps {
items: InvoiceItem[];
onAddItem: () => void;
onRemoveItem: (index: number) => void;
onUpdateItem: (
index: number,
field: string,
value: string | number | Date,
) => void;
onMoveUp: (index: number) => void;
onMoveDown: (index: number) => void;
className?: string;
}
interface LineItemRowProps {
item: InvoiceItem;
index: number;
canRemove: boolean;
onRemove: (index: number) => void;
onUpdate: (
index: number,
field: string,
value: string | number | Date,
) => void;
onMoveUp: (index: number) => void;
onMoveDown: (index: number) => void;
isFirst: boolean;
isLast: boolean;
}
function LineItemRow({
item,
index,
canRemove,
onRemove,
onUpdate,
}: LineItemRowProps) {
return (
{/* Drag Handle */}
{/* Main Content */}
{/* Description */}
onUpdate(index, "description", e.target.value)}
placeholder="Describe the work performed..."
className="w-full text-sm font-medium"
/>
{/* Controls Row */}
{/* Date */}
onUpdate(index, "date", date ?? new Date())
}
size="sm"
className="h-9 w-36"
/>
{/* Hours */}
onUpdate(index, "hours", value)}
min={0}
step={0.25}
width="auto"
className="h-9 w-32"
/>
{/* Rate */}
onUpdate(index, "rate", value)}
min={0}
step={1}
prefix="$"
width="auto"
className="h-9 w-32"
/>
{/* Amount */}
${(item.hours * item.rate).toFixed(2)}
{/* Actions */}
);
}
function MobileLineItem({
item,
index,
canRemove,
onRemove,
onUpdate,
onMoveUp,
onMoveDown,
isFirst,
isLast,
}: LineItemRowProps) {
return (
{/* Description */}
onUpdate(index, "description", e.target.value)}
placeholder="Describe the work performed..."
className="pl-3 text-sm"
/>
{/* Date */}
onUpdate(index, "date", date ?? new Date())}
size="sm"
/>
{/* Hours and Rate in a row */}
onUpdate(index, "hours", value)}
min={0}
step={0.25}
width="full"
/>
onUpdate(index, "rate", value)}
min={0}
step={1}
prefix="$"
width="full"
/>
{/* Bottom section with controls, item name, and total */}
Item
#
{index + 1}
Total
${(item.hours * item.rate).toFixed(2)}
);
}
export function InvoiceLineItems({
items,
onAddItem,
onRemoveItem,
onUpdateItem,
onMoveUp,
onMoveDown,
className,
}: InvoiceLineItemsProps) {
const canRemoveItems = items.length > 1;
return (
{/* Desktop and Mobile Cards */}
{items.map((item, index) => (
{/* Desktop/Tablet Card */}
{/* Mobile Card */}
))}
{/* Add Item Button */}
);
}