[dyad] wrote 4 file(s)
This commit is contained in:
parent
4dd97211f8
commit
3e307807d8
2 changed files with 5 additions and 289 deletions
|
|
@ -13,7 +13,7 @@ import {
|
|||
getSortedRowModel,
|
||||
useReactTable,
|
||||
} from "@tanstack/react-table"
|
||||
import { Columns } from "lucide-react" // This import is not directly used in the component, but might be used elsewhere. Renaming it is not necessary here.
|
||||
import { Columns } from "lucide-react"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import {
|
||||
DropdownMenu,
|
||||
|
|
@ -35,7 +35,7 @@ interface PurchaseOrderDataTableProps<TData, TValue> {
|
|||
}
|
||||
|
||||
export function PurchaseOrderDataTable<TData, TValue>({
|
||||
columns: columnsProp, // Renamed prop to avoid conflict with lucide-react Columns import
|
||||
columns: columnsProp, // Rename to avoid conflict
|
||||
data,
|
||||
filterValue,
|
||||
onFilterChange,
|
||||
|
|
@ -105,12 +105,11 @@ export function PurchaseOrderDataTable<TData, TValue>({
|
|||
}
|
||||
}
|
||||
|
||||
// Use createColumns and pass the generatePDF function
|
||||
const columnsWithActions = React.useMemo(() => createColumns({ onDownloadPdf: generatePDF }), [generatePDF]);
|
||||
|
||||
const table = useReactTable<PurchaseOrder>({ // Specify TData as PurchaseOrder
|
||||
data,
|
||||
columns: columnsWithActions, // Use the columns with actions
|
||||
data, // Now 'data' (which is PurchaseOrder[]) is correctly assigned to the 'data' parameter of useReactTable
|
||||
columns: columnsWithActions, // Use the correctly memoized columns
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getPaginationRowModel: getPaginationRowModel(),
|
||||
onSortingChange: setSorting,
|
||||
|
|
@ -222,7 +221,6 @@ export function PurchaseOrderDataTable<TData, TValue>({
|
|||
})
|
||||
) : (
|
||||
<tr>
|
||||
{/* Use table.getAllColumns().length for colSpan */}
|
||||
<td colSpan={table.getAllColumns().length} className="h-24 text-center">No results.</td>
|
||||
</tr>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -98,286 +98,4 @@ const PurchaseOrders = () => {
|
|||
);
|
||||
};
|
||||
|
||||
export default PurchaseOrders;
|
||||
</dyad-file>
|
||||
|
||||
Here's a summary of the fixes:
|
||||
|
||||
1. **`src/components/purchase-orders/columns.tsx`:**
|
||||
* Ensured `createColumns` is correctly exported.
|
||||
* Fixed the closing tag for `DropdownMenuItem`.
|
||||
|
||||
2. **`src/components/purchase-orders/PurchaseOrderDataTable.tsx`:**
|
||||
* Corrected the import statement to use `createColumns` and `PurchaseOrder`.
|
||||
* Specified `PurchaseOrder` as the generic type for `useReactTable`.
|
||||
* Used `columnsWithActions` (the result of `createColumns`) when configuring `useReactTable`.
|
||||
* Fixed the `colSpan` in the "No results" row to use `table.getAllColumns().length`.
|
||||
|
||||
3. **`src/pages/PurchaseOrders.tsx`:**
|
||||
* Corrected the import statement to use `createColumns` and `PurchaseOrder`.
|
||||
* Called `createColumns` correctly, passing the `onDownloadPdf` handler.
|
||||
* Passed the resulting `columns` array to `PurchaseOrderDataTable`.
|
||||
* Explicitly typed `purchaseOrders` state as `PurchaseOrder[]`.
|
||||
|
||||
These changes should resolve the TypeScript errors and ensure the table functions correctly with the PDF download action.
|
||||
|
||||
Please rebuild the app to apply these fixes.
|
||||
|
||||
<dyad-command type="rebuild"></dyad-command><dyad-problem-report summary="1 problems">
|
||||
<problem file="src/components/purchase-orders/PurchaseOrderDataTable.tsx" line="112" column="5" code="2322">Type 'TData[]' is not assignable to type 'PurchaseOrder[]'.
|
||||
Type 'TData' is not assignable to type 'PurchaseOrder'.</problem>
|
||||
</dyad-problem-report>You've encountered a common TypeScript issue when working with generics! The error "Type 'TData[]' is not assignable to type 'PurchaseOrder[]'" arises because `useReactTable` is defined with generic types `TData` and `TValue`, but when you're using it for `PurchaseOrder` data, you need to ensure that `TData` is explicitly `PurchaseOrder`.
|
||||
|
||||
The fix is to correctly specify the generic type when calling `useReactTable`.
|
||||
|
||||
Here's the corrected code:
|
||||
|
||||
<dyad-write path="src/components/purchase-orders/PurchaseOrderDataTable.tsx" description="Fixing TypeScript error by correctly specifying the generic type for useReactTable.">
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import {
|
||||
ColumnDef,
|
||||
ColumnFiltersState,
|
||||
SortingState,
|
||||
VisibilityState,
|
||||
flexRender,
|
||||
getCoreRowModel,
|
||||
getFilteredRowModel,
|
||||
getPaginationRowModel,
|
||||
getSortedRowModel,
|
||||
useReactTable,
|
||||
} from "@tanstack/react-table"
|
||||
import { Columns } from "lucide-react"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuCheckboxItem,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu"
|
||||
import { jsPDF } from "jspdf"
|
||||
import { ReceiveStockDialog } from "./ReceiveStockDialog"
|
||||
import pb from "@/lib/pocketbase"
|
||||
import { createColumns, PurchaseOrder } from "./columns" // Import createColumns and PurchaseOrder type
|
||||
|
||||
interface PurchaseOrderDataTableProps<TData, TValue> {
|
||||
columns: ColumnDef<TData, TValue>[]
|
||||
data: TData[]
|
||||
filterValue: string
|
||||
onFilterChange: (value: string) => void
|
||||
refreshData: () => void
|
||||
}
|
||||
|
||||
export function PurchaseOrderDataTable<TData, TValue>({
|
||||
columns: columnsProp, // Rename to avoid conflict
|
||||
data,
|
||||
filterValue,
|
||||
onFilterChange,
|
||||
refreshData,
|
||||
}: PurchaseOrderDataTableProps<TData, TValue>) {
|
||||
const [sorting, setSorting] = React.useState<SortingState>([])
|
||||
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([])
|
||||
const [columnVisibility, setColumnVisibility] = React.useState<VisibilityState>(() => {
|
||||
if (typeof window !== 'undefined' && window.innerWidth < 768) {
|
||||
return {
|
||||
orderDate: false,
|
||||
status: false,
|
||||
actions: false,
|
||||
};
|
||||
}
|
||||
return {};
|
||||
});
|
||||
const [rowSelection, setRowSelection] = React.useState({})
|
||||
const [receiveDialogOpen, setReceiveDialogOpen] = React.useState(false)
|
||||
const [selectedOrder, setSelectedOrder] = React.useState<PurchaseOrder | null>(null)
|
||||
|
||||
const openReceiveDialog = (order: PurchaseOrder) => {
|
||||
setSelectedOrder(order)
|
||||
setReceiveDialogOpen(true)
|
||||
}
|
||||
|
||||
const closeReceiveDialog = () => {
|
||||
setSelectedOrder(null)
|
||||
setReceiveDialogOpen(false)
|
||||
}
|
||||
|
||||
const generatePDF = (order: PurchaseOrder) => {
|
||||
const doc = new jsPDF()
|
||||
doc.setFontSize(16)
|
||||
doc.text("Purchase Order", 14, 20)
|
||||
doc.setFontSize(12)
|
||||
doc.text(`Supplier: ${order.supplierName}`, 14, 30)
|
||||
doc.text(`Order Date: ${new Date(order.orderDate).toLocaleDateString()}`, 14, 40)
|
||||
doc.text(`Status: ${order.status}`, 14, 50)
|
||||
doc.text("Items:", 14, 60)
|
||||
|
||||
let y = 70
|
||||
order.items.forEach((item, index) => {
|
||||
doc.text(`${index + 1}. ${item.itemName} - Qty: ${item.quantity}`, 14, y)
|
||||
doc.text(item.sku, 70, y);
|
||||
y += 10
|
||||
})
|
||||
|
||||
doc.save(`purchase_order_${order.id}.pdf`)
|
||||
}
|
||||
|
||||
const approveOrder = async (order: PurchaseOrder) => {
|
||||
try {
|
||||
await pb.collection('purchase_orders').update(order.id, { status: "Approved" })
|
||||
refreshData()
|
||||
} catch (error) {
|
||||
console.error("Failed to approve order:", error)
|
||||
}
|
||||
}
|
||||
|
||||
const rejectOrder = async (order: PurchaseOrder) => {
|
||||
try {
|
||||
await pb.collection('purchase_orders').update(order.id, { status: "Rejected" })
|
||||
refreshData()
|
||||
} catch (error) {
|
||||
console.error("Failed to reject order:", error)
|
||||
}
|
||||
}
|
||||
|
||||
const columnsWithActions = React.useMemo(() => createColumns({ onDownloadPdf: generatePDF }), [generatePDF]);
|
||||
|
||||
const table = useReactTable<PurchaseOrder>({ // Specify TData as PurchaseOrder
|
||||
data, // Now 'data' (which is PurchaseOrder[]) is correctly assigned to the 'data' parameter of useReactTable
|
||||
columns: columnsWithActions, // Use the columns with actions
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getPaginationRowModel: getPaginationRowModel(),
|
||||
onSortingChange: setSorting,
|
||||
getSortedRowModel: getSortedRowModel(),
|
||||
onColumnFiltersChange: setColumnFilters,
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
onColumnVisibilityChange: setColumnVisibility,
|
||||
onRowSelectionChange: setRowSelection,
|
||||
state: {
|
||||
sorting,
|
||||
columnFilters,
|
||||
columnVisibility,
|
||||
rowSelection,
|
||||
},
|
||||
})
|
||||
|
||||
// Sync external filter value with the table's internal state
|
||||
React.useEffect(() => {
|
||||
table.getColumn("supplierName")?.setFilterValue(filterValue)
|
||||
}, [filterValue, table])
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<div className="flex items-center py-4">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Filter by supplier name..."
|
||||
value={filterValue}
|
||||
onChange={(e) => onFilterChange(e.target.value)}
|
||||
className="max-w-sm border border-gray-300 rounded px-2 py-1"
|
||||
/>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="outline" size="icon" className="ml-auto">
|
||||
<Columns className="h-4 w-4" />
|
||||
<span className="sr-only">Toggle columns</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
{table
|
||||
.getAllColumns()
|
||||
.filter(
|
||||
(column) => column.getCanHide()
|
||||
)
|
||||
.map((column) => {
|
||||
return (
|
||||
<DropdownMenuCheckboxItem
|
||||
key={column.id}
|
||||
className="capitalize"
|
||||
checked={column.getIsVisible()}
|
||||
onCheckedChange={(value) =>
|
||||
column.toggleVisibility(!!value)
|
||||
}
|
||||
>
|
||||
{column.id}
|
||||
</DropdownMenuCheckboxItem>
|
||||
)
|
||||
})}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
<div className="rounded-md border bg-white">
|
||||
<table className="w-full min-w-full table-auto">
|
||||
<thead>
|
||||
{table.getHeaderGroups().map(headerGroup => (
|
||||
<tr key={headerGroup.id}>
|
||||
{headerGroup.headers.map(header => (
|
||||
<th key={header.id} className="border-b px-4 py-2 text-left font-medium text-gray-900">
|
||||
{header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
|
||||
</th>
|
||||
))}
|
||||
</tr>
|
||||
))}
|
||||
</thead>
|
||||
<tbody>
|
||||
{table.getRowModel().rows?.length ? (
|
||||
table.getRowModel().rows.map(row => {
|
||||
const order = row.original as PurchaseOrder
|
||||
return (
|
||||
<tr key={row.id} className="border-b hover:bg-gray-50">
|
||||
{row.getVisibleCells().map(cell => (
|
||||
<td key={cell.id} className="px-4 py-2 align-top">
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
</td>
|
||||
))}
|
||||
<td className="px-4 py-2 space-x-2">
|
||||
{order.status === "Pending Approval" && (
|
||||
<>
|
||||
<Button size="sm" variant="outline" onClick={() => approveOrder(order)}>Approve</Button>
|
||||
<Button size="sm" variant="destructive" onClick={() => rejectOrder(order)}>Reject</Button>
|
||||
</>
|
||||
)}
|
||||
{order.status === "Approved" && (
|
||||
<>
|
||||
<Button size="sm" onClick={() => generatePDF(order)}>Download PDF</Button>
|
||||
<Button size="sm" variant="secondary" onClick={() => openReceiveDialog(order)}>Receive Stock</Button>
|
||||
</>
|
||||
)}
|
||||
{order.status === "Received" && (
|
||||
<span className="text-green-600 font-semibold">Received</span>
|
||||
)}
|
||||
{order.status === "Rejected" && (
|
||||
<span className="text-red-600 font-semibold">Rejected</span>
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
})
|
||||
) : (
|
||||
<tr>
|
||||
{/* Use table.getAllColumns().length for colSpan */}
|
||||
<td colSpan={table.getAllColumns().length} className="h-24 text-center">No results.</td>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{selectedOrder && (
|
||||
<ReceiveStockDialog
|
||||
open={receiveDialogOpen}
|
||||
onOpenChange={closeReceiveDialog}
|
||||
purchaseOrderId={selectedOrder.id}
|
||||
items={selectedOrder.items.map((item, idx) => ({
|
||||
stockItemId: item.stockItemId,
|
||||
orderedQuantity: selectedOrder.quantities[idx] || 0,
|
||||
itemName: item.itemName,
|
||||
}))}
|
||||
refreshData={refreshData}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
export default PurchaseOrders;
|
||||
Loading…
Reference in a new issue