diff --git a/src/components/cards/OrderCard.tsx b/src/components/cards/OrderCard.tsx index 3480138..3546448 100644 --- a/src/components/cards/OrderCard.tsx +++ b/src/components/cards/OrderCard.tsx @@ -1,24 +1,37 @@ import { formatValue } from '../../lib/format'; -import { Store, Calendar, Package, ShoppingBag } from 'lucide-react'; +import { Store, Calendar, ShoppingBag, Clock, Truck, Package } from 'lucide-react'; import './card.css'; -export function OrderCard({ row, fields }: { row: Record; fields: any[] }) { +export function OrderCard({ row, fields, isDetailView = false }: { row: Record; fields: any[]; isDetailView?: boolean }) { const orderIdStr = row.order_id || '—'; // Extract store lookup object if it exists const storeObj = (row.select_store || row.store) as Record | null; - const storeVal = formatValue(storeObj?.business_name || row.business_name || row.store_name || '—'); + const storeVal = formatValue(storeObj?.business_name || storeObj?.store_name || row.business_name || row.store_name || '—'); + const routeName = formatValue(storeObj?.route_name || storeObj?.route || row.route_name || row.route || '—'); + const areaName = formatValue(storeObj?.area || row.area || row.area_name || '—'); + const distName = formatValue(storeObj?.distributor_name || '—'); + + // Extract User object + const userKey = Object.keys(row).find(k => k.includes('user_id')); + const userObj = userKey ? (row[userKey] as any) : null; + const userName = formatValue(userObj?.name || row.sales_officer || row.user_name || '—'); + const userEmail = formatValue(userObj?.email || row.performed_by_email || row.user_email || '—'); + const initials = userName !== '—' ? String(userName).substring(0, 2).toUpperCase() : 'SO'; // Extract date const dateKey = Object.keys(row).find(k => k.includes('date_of_order')); let dateVal = dateKey && row[dateKey] ? formatValue(row[dateKey]) : '—'; - // Try to append time if it exists + let timeVal = '—'; const timeKey = Object.keys(row).find(k => k.includes('time_of_order')); if (timeKey && row[timeKey]) { - dateVal += ` ${formatValue(row[timeKey])}`; + timeVal = formatValue(row[timeKey]); } + let dateTimeStr = dateVal; + if (timeVal !== '—') dateTimeStr += ` ${timeVal}`; + const stateName = String(row.current_state_name || ''); const isProductive = stateName.toLowerCase().includes('productive') || stateName.toLowerCase().includes('closed') || stateName.toLowerCase().includes('ordered'); const productiveLabel = stateName || 'Pending'; @@ -30,13 +43,20 @@ export function OrderCard({ row, fields }: { row: Record; fields: a const gridField = fields.find(f => f.data_type === 'grid' || String(f.field_key).includes('order_details')); const gridValRaw = gridField ? row[gridField.field_key] : (row.order_details || row.order_details_2 || row.order_details_3); const gridVal = Array.isArray(gridValRaw) ? gridValRaw : []; + const totalItems = gridVal.length; - // Total Kgs + // Totals let totalKgsVal = Number(row.total_kgs || row.total_kgs_2 || row.total_kgs_3 || row.total_weight || row.weight || 0); - if (totalKgsVal === 0 && gridVal.length > 0) { - gridVal.forEach(p => { totalKgsVal += Number(p.row_kgs || p.kgs || p.weight || 0); }) + let totalBagsVal = Number(row.total_bags || row.total_bags_2 || row.total_bags_3 || row.total_quantity || row.quantity || 0); + + if (totalKgsVal === 0 && totalBagsVal === 0 && gridVal.length > 0) { + gridVal.forEach(p => { + totalKgsVal += Number(p.row_kgs || p.kgs || p.weight || 0); + totalBagsVal += Number(p.bags || p.total_bags || p.quantity || 0); + }); } const totalKgs = formatValue(totalKgsVal); + const totalBags = formatValue(totalBagsVal); return (
@@ -55,44 +75,142 @@ export function OrderCard({ row, fields }: { row: Record; fields: a

{storeVal}

-
- -
-
-
DATE & TIME
- {dateVal} -
-
-
TOTAL KGS
- {totalKgs} kg -
-
- - {gridVal.length > 0 && ( -
-

Order Products

-
- {gridVal.map((item, i) => { - const getVal = (key: string) => { - if (item[key] !== undefined) return item[key]; - const keyPattern = new RegExp(`^${key}(_\\d+)?$`); - const match = Object.keys(item).find(k => keyPattern.test(k) || k.includes(key)); - return match ? item[match] : undefined; - }; - - const productName = formatValue(getVal('product_name') || getVal('product_category') || 'Unknown Product'); - const bags = formatValue(getVal('bags') || getVal('total_bags') || getVal('quantity') || 0); - - return ( -
- {productName} - {bags} Bags -
- ); - })} + {!isDetailView && ( + <> +
+
+
+
DATE & TIME
+ {dateTimeStr} +
+
+
TOTAL KGS
+ {totalKgs} kg +
-
+ {gridVal.length > 0 && ( +
+

Order Products

+
+ {gridVal.map((item, i) => { + const getVal = (key: string) => { + if (item[key] !== undefined) return item[key]; + const keyPattern = new RegExp(`^${key}(_\\d+)?$`); + const match = Object.keys(item).find(k => keyPattern.test(k) || k.includes(key)); + return match ? item[match] : undefined; + }; + + const productName = formatValue(getVal('product_name') || getVal('product_category') || 'Unknown Product'); + const bags = formatValue(getVal('bags') || getVal('total_bags') || getVal('quantity') || 0); + + return ( +
+ {productName} + {bags} Bags +
+ ); + })} +
+
+ )} + )} + + {isDetailView && ( + <> + {distName !== '—' && ( +
+ +

{distName}

+
+ )} + + {/* Route & Assignment */} +
+
+

Route

+

{routeName}

+
+
+

Area

+

{areaName}

+
+
+

Sales Officer

+
+
+ {initials} +
+
+

{userName}

+ {userEmail !== '—' && ( +

{userEmail}

+ )} +
+
+
+
+ +
+
+

DATE

+

{dateVal}

+
+ {timeVal !== '—' && ( +
+

TIME

+

{timeVal}

+
+ )} +
+ + {gridVal.length > 0 && ( +
+
+

Order Products

+ + {totalItems} {totalItems === 1 ? 'Item' : 'Items'} + +
+
+ {gridVal.map((item, i) => { + const getVal = (key: string) => { + if (item[key] !== undefined) return item[key]; + const keyPattern = new RegExp(`^${key}(_\\d+)?$`); + const match = Object.keys(item).find(k => keyPattern.test(k) || k.includes(key)); + return match ? item[match] : undefined; + }; + + const productName = formatValue(getVal('product_name') || getVal('product_category') || 'Unknown Product'); + const bags = formatValue(getVal('bags') || getVal('total_bags') || getVal('quantity') || 0); + + return ( +
+ {productName} + {bags} Bags +
+ ); + })} +
+
+ )} + + {/* Logistics Totals at the bottom */} + {(Number(totalKgsVal) > 0 || Number(totalBagsVal) > 0) && ( +
+
+ Total Weight + {totalKgs} Kgs +
+
+ Total Quantity + {totalBags} Bags +
+
+ )} + + )} +
); } diff --git a/src/components/dv/OrderDetail.tsx b/src/components/dv/OrderDetail.tsx index 181d48c..c7fea06 100644 --- a/src/components/dv/OrderDetail.tsx +++ b/src/components/dv/OrderDetail.tsx @@ -1,20 +1,27 @@ import { orderBookingClient } from '../../api/clients'; import { ORDER_BOOKING } from '../../api/config'; -import { DetailView } from './DetailView'; +import { useDetailViewData } from './useDetailViewData'; +import { OrderCard } from '../cards/OrderCard'; export interface WiredDetailViewProps { instanceId: string | number; columns?: 1 | 2 | 3; } -export function OrderDetail({ instanceId, columns = 2 }: WiredDetailViewProps) { +export function OrderDetail({ instanceId }: WiredDetailViewProps) { + const { data, config, loading, error } = useDetailViewData( + orderBookingClient, + ORDER_BOOKING.detailViews.ORDERS, + instanceId + ); + + if (loading) return
Loading Order Details...
; + if (error) return
{error}
; + if (!data) return
No data found.
; + return ( - +
+ +
); }