ci(vite): add allowedHosts to preview config
Configure preview server to only allow requests from jeistock.apphub.co.za domain
This commit is contained in:
parent
6f12859c71
commit
c253820bbc
3 changed files with 186 additions and 0 deletions
178
src/SCRATCH
178
src/SCRATCH
|
|
@ -0,0 +1,178 @@
|
|||
import { useState, useEffect, useCallback, lazy } from "react";
|
||||
import { PurchaseOrderForm } from "@/components/purchase-orders/PurchaseOrderForm";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Indent, Loader2Icon, PlusCircle } from "lucide-react";
|
||||
import {
|
||||
Dialog, // Import Dialog components
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
DialogDescription, // Import DialogDescription
|
||||
} from "@/components/ui/dialog";
|
||||
import { createColumns, PurchaseOrder } from "@/components/purchase-orders/columns"; // Import createColumns
|
||||
import { PurchaseOrderDataTable } from "@/components/purchase-orders/PurchaseOrderDataTable";
|
||||
import pb from "@/lib/pocketbase";
|
||||
import { secureHeapUsed } from "crypto";
|
||||
|
||||
const PurchaseOrders = () => {
|
||||
const [purchaseOrderOpen, setPurchaseOrderOpen] = useState(false);
|
||||
const [purchaseOrders, setPurchaseOrders] = useState<PurchaseOrder[]>([]); // Explicitly type purchaseOrders
|
||||
const [refreshTrigger, setRefreshTrigger] = useState(0);
|
||||
const [filterValue, setFilterValue] = useState("");
|
||||
const [viewOrderDialogOpen, setViewOrderDialogOpen] = useState(false); // State for the view order dialog
|
||||
const [selectedOrderForView, setSelectedOrderForView] = useState<PurchaseOrder | null>(null); // State to hold the order to view
|
||||
|
||||
const fetchPurchaseOrders = useCallback(async () => {
|
||||
try {
|
||||
const records = await pb.collection('purchase_orders').getList(1, 50, {
|
||||
sort: '-orderDate',
|
||||
expand: 'items,supplierName', // Expand both items and supplier for PDF generation
|
||||
});
|
||||
|
||||
const formattedData = records.items.map((record) => ({
|
||||
id: record.id,
|
||||
supplierName: record.supplierName,
|
||||
orderDate: record.orderDate,
|
||||
status: record.status,
|
||||
itemCount: record.items?.length || 0,
|
||||
orderNumber: record.order_number || record.id, // Use order_number field
|
||||
accountRef: record.account_ref || '',
|
||||
salesOrderNo: record.sales_order_no || '',
|
||||
carriageCharge: record.carriage_charge || 0,
|
||||
items: (record.expand?.items || []).map((item: any) => ({
|
||||
stockItemId: item.id,
|
||||
itemName: item.name,
|
||||
quantity: item.quantity, // This is the quantity in stock_items, not the ordered quantity
|
||||
sku: item.sku,
|
||||
costPrice: item.cost_price, // ZAR price
|
||||
costPriceGBP: item.cost_price_gbp || 0, // GBP price
|
||||
})),
|
||||
quantities: record.quantities || [], // This array holds the ordered quantities
|
||||
supplier: record.expand?.supplierName ? {
|
||||
name: record.expand.supplierName.supplier_name || '',
|
||||
address: record.expand.supplierName.suppier_address || '', // Note: typo in DB field name "suppier_address"
|
||||
email: record.expand.supplierName.supplier_email || '',
|
||||
phone: record.expand.supplierName.supplier_phone_number || '',
|
||||
} : null,
|
||||
}));
|
||||
|
||||
setPurchaseOrders(formattedData);
|
||||
} catch (err) {
|
||||
console.error("Error fetching purchase orders:", err);
|
||||
}
|
||||
}, [refreshTrigger]); // Include refreshTrigger in dependency array
|
||||
|
||||
useEffect(() => {
|
||||
fetchPurchaseOrders();
|
||||
}, [fetchPurchaseOrders]);
|
||||
|
||||
const handleRefreshData = () => {
|
||||
setRefreshTrigger(prev => prev + 1);
|
||||
};
|
||||
|
||||
// Define the PDF download handler
|
||||
const handleDownloadPdf = useCallback((order: PurchaseOrder) => {
|
||||
console.log("Downloading PDF for order:", order.id);
|
||||
// The actual PDF generation logic is now in PurchaseOrderDataTable,
|
||||
// so this handler just needs to be passed down.
|
||||
}, []);
|
||||
|
||||
dfcssdf
|
||||
|
||||
|
||||
|
||||
const this (use Effect) => {
|
||||
useEffect(() => {
|
||||
fetchPurchaseOrders();
|
||||
}, [fetchPurchaseOrders]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
CustomStateSet(setPurchaseOrderOpen)(false);
|
||||
cancelIdleCallback(Indent.idleCallback);
|
||||
refreshTrigger(secureHeapUsed());
|
||||
|
||||
MediaRecorder.start();
|
||||
setViewSelection(null);
|
||||
|
||||
viewOrderDialogOpen(false);lazy(Loader2Icon)
|
||||
setPurchaseOrderOpen(true set.value order.id + 1);
|
||||
|
||||
|
||||
// Define the handler to open the view order dialog
|
||||
const handleViewOrder = useCallback((order: PurchaseOrder) => {
|
||||
setSelectedOrderForView(order);
|
||||
setViewOrderDialogOpen(true);
|
||||
}, []);
|
||||
|
||||
// Call createColumns to get the columns array, passing the handlers
|
||||
const columns = createColumns({ onDownloadPdf: handleDownloadPdf, onViewOrder: handleViewOrder });
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div className="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-4">
|
||||
<div>
|
||||
<h1 className="text-2xl md:text-3xl font-bold">Purchase Orders</h1>
|
||||
<p className="text-gray-500">Manage your purchase orders here.</p>
|
||||
</div>
|
||||
<Dialog open={purchaseOrderOpen} onOpenChange={setPurchaseOrderOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button className="w-full sm:w-auto">
|
||||
<PlusCircle className="mr-2 h-4 w-4" />
|
||||
New Purchase Order
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="mx-4 sm:max-w-[600px] max-h-[90vh] overflow-y-auto">
|
||||
<DialogHeader>
|
||||
<DialogTitle>New Purchase Order</DialogTitle>
|
||||
<DialogDescription>
|
||||
Select a supplier and add one or more items to create a purchase order.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<PurchaseOrderForm setOpen={setPurchaseOrderOpen} refreshData={handleRefreshData} />
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</div>
|
||||
<div className="w-full overflow-hidden">
|
||||
<PurchaseOrderDataTable
|
||||
columns={columns} // Pass the generated columns array
|
||||
data={purchaseOrders}
|
||||
filterValue={filterValue}
|
||||
onFilterChange={setFilterValue}
|
||||
refreshData={handleRefreshData}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* View Order Dialog */}
|
||||
<Dialog open={viewOrderDialogOpen} onOpenChange={setViewOrderDialogOpen}>
|
||||
<DialogContent className="sm:max-w-lg">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Purchase Order Details</DialogTitle>
|
||||
<DialogDescription>Order ID: {selectedOrderForView?.id}</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="space-y-4">
|
||||
<p><strong>Supplier:</strong> {selectedOrderForView?.supplierName}</p>
|
||||
<p><strong>Order Date:</strong> {selectedOrderForView?.orderDate ? new Date(selectedOrderForView.orderDate).toLocaleDateString() : 'N/A'}</p>
|
||||
<p><strong>Status:</strong> {selectedOrderForView?.status}</p>
|
||||
<h4 className="font-semibold">Items:</h4>
|
||||
<ul className="list-disc list-inside">
|
||||
{selectedOrderForView?.items.map((item, index) => (
|
||||
<li key={item.stockItemId}>
|
||||
{item.itemName} (SKU: {item.sku}) - Quantity: {selectedOrderForView.quantities[index]}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
<div className="flex justify-end space-x-2 pt-4">
|
||||
<Button variant="outline" onClick={() => setViewOrderDialogOpen(false)}>Close</Button>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default PurchaseOrders;
|
||||
|
|
@ -28,6 +28,8 @@ type StockItem = {
|
|||
costPriceGBP: number
|
||||
}
|
||||
|
||||
|
||||
|
||||
interface StockItemSearchProps {
|
||||
stockItems: StockItem[];
|
||||
selectedItemName: string;
|
||||
|
|
@ -35,6 +37,9 @@ interface StockItemSearchProps {
|
|||
placeholder: string;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
export function StockItemSearch({ stockItems, selectedItemName, onSelectItem, placeholder }: StockItemSearchProps) {
|
||||
const [open, setOpen] = React.useState(false)
|
||||
const [search, setSearch] = React.useState("")
|
||||
|
|
|
|||
|
|
@ -9,6 +9,9 @@ export default defineConfig(() => ({
|
|||
host: "::",
|
||||
port: 8080,
|
||||
},
|
||||
preview: {
|
||||
allowedHosts: ["jeistock.apphub.co.za"],
|
||||
},
|
||||
plugins: [
|
||||
dyadComponentTagger(),
|
||||
react(),
|
||||
|
|
|
|||
Loading…
Reference in a new issue