mirror of
https://github.com/skidoodle/budgetable.git
synced 2025-02-15 03:39:14 +01:00
Refactor: Break down single table component into multiple modular components
This commit is contained in:
parent
8c9688017b
commit
95380493cb
33 changed files with 1562 additions and 6642 deletions
134
src/components/table-row.tsx
Normal file
134
src/components/table-row.tsx
Normal file
|
@ -0,0 +1,134 @@
|
|||
import { Input } from "@/components/ui/input";
|
||||
import { TableRow, TableCell } from "@/components/ui/table";
|
||||
import Link from "next/link";
|
||||
import StatusBadge from "@/components/status-badge";
|
||||
import DeleteDialog from "@/components/delete-dialog";
|
||||
|
||||
interface Budgetable {
|
||||
id: string;
|
||||
title: string;
|
||||
price: number;
|
||||
link: string;
|
||||
note?: string;
|
||||
status: "Paid" | "Unpaid";
|
||||
}
|
||||
|
||||
interface TRowProps {
|
||||
row: Budgetable;
|
||||
isEditing: boolean;
|
||||
setData: React.Dispatch<React.SetStateAction<Budgetable[]>>;
|
||||
recentlyUpdatedRowId: string | null;
|
||||
handleSave: (
|
||||
updatedRow: Budgetable,
|
||||
originalRow: Budgetable,
|
||||
) => Promise<void>;
|
||||
handleDeleteRow: (id: string) => Promise<void>;
|
||||
toggleStatus: (row: Budgetable) => Promise<void>;
|
||||
}
|
||||
|
||||
const TRow: React.FC<TRowProps> = ({
|
||||
row,
|
||||
isEditing,
|
||||
setData,
|
||||
recentlyUpdatedRowId,
|
||||
handleSave,
|
||||
handleDeleteRow,
|
||||
toggleStatus,
|
||||
}) => (
|
||||
<TableRow
|
||||
className={`transition-opacity ${
|
||||
recentlyUpdatedRowId === row.id ? "blur-sm opacity-50" : ""
|
||||
}`}
|
||||
>
|
||||
<TableCell>
|
||||
{isEditing ? (
|
||||
<Input
|
||||
value={row.title}
|
||||
onChange={(e) =>
|
||||
setData((prev) =>
|
||||
prev.map((item) =>
|
||||
item.id === row.id ? { ...item, title: e.target.value } : item,
|
||||
),
|
||||
)
|
||||
}
|
||||
onBlur={() => handleSave(row, { ...row })}
|
||||
/>
|
||||
) : (
|
||||
<span>{row.title}</span>
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
{isEditing ? (
|
||||
<Input
|
||||
type="number"
|
||||
value={row.price}
|
||||
onChange={(e) =>
|
||||
setData((prev) =>
|
||||
prev.map((item) =>
|
||||
item.id === row.id
|
||||
? { ...item, price: Number.parseFloat(e.target.value) || 0 }
|
||||
: item,
|
||||
),
|
||||
)
|
||||
}
|
||||
onBlur={() => handleSave(row, { ...row })}
|
||||
/>
|
||||
) : (
|
||||
<span>{row.price.toLocaleString()} HUF</span>
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
{isEditing ? (
|
||||
<Input
|
||||
value={row.link}
|
||||
onChange={(e) =>
|
||||
setData((prev) =>
|
||||
prev.map((item) =>
|
||||
item.id === row.id ? { ...item, link: e.target.value } : item,
|
||||
),
|
||||
)
|
||||
}
|
||||
onBlur={() => handleSave(row, { ...row })}
|
||||
/>
|
||||
) : row.link ? (
|
||||
<Link
|
||||
href={row.link}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-blue-500 underline"
|
||||
>
|
||||
Visit
|
||||
</Link>
|
||||
) : (
|
||||
<span className="text-gray-400 italic">No link</span>
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
{isEditing ? (
|
||||
<Input
|
||||
value={row.note || ""}
|
||||
onChange={(e) =>
|
||||
setData((prev) =>
|
||||
prev.map((item) =>
|
||||
item.id === row.id ? { ...item, note: e.target.value } : item,
|
||||
),
|
||||
)
|
||||
}
|
||||
onBlur={() => handleSave(row, { ...row })}
|
||||
/>
|
||||
) : (
|
||||
<span>{row.note || "-"}</span>
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<StatusBadge status={row.status} toggleStatus={() => toggleStatus(row)} />
|
||||
</TableCell>
|
||||
{isEditing && (
|
||||
<TableCell>
|
||||
<DeleteDialog onConfirm={() => handleDeleteRow(row.id)} />
|
||||
</TableCell>
|
||||
)}
|
||||
</TableRow>
|
||||
);
|
||||
|
||||
export default TRow;
|
Loading…
Add table
Add a link
Reference in a new issue