- {value.map((row, i) => (
-
-
-
-
-
Row {i + 1}
-
- {columns.map(col => {
- const val = row[col.id];
- if (col.data_type === 'select' || col.data_type === 'multiselect') {
- // Cascade filter options
- const allOpts = col.properties?.options || [];
- let filteredOpts = allOpts;
-
- // Specific logic for product_name depending on product_category
- if (col.id === 'product_name' || col.name === 'Product Name') {
- const catCol = columns.find(c => c.id === 'product_category' || c.name === 'Product Category');
- if (catCol) {
- const selectedCategory = row[catCol.id] as string;
- if (selectedCategory) {
- filteredOpts = allOpts.filter(opt => {
- const labelStr = String(opt.label || opt.value || '');
- return labelStr.startsWith(selectedCategory);
- });
- }
- }
- } else {
- // Generic _raw cascading for other fields just in case
- filteredOpts = allOpts.filter(opt => {
- if (!opt._raw) return true;
- for (const [rowKey, rowVal] of Object.entries(row)) {
- if (rowKey === col.id || rowVal == null || rowVal === '') continue;
- const rawKey = Object.keys(opt._raw).find(rk => rk === rowKey || rk.replace(/_/g, '') === rowKey.replace(/_/g, ''));
- if (rawKey && String(opt._raw[rawKey]) !== String(rowVal)) {
- return false;
- }
- }
- return true;
- });
- }
+
+ {value.map((row, i) => {
+ let productName = 'Unknown Product';
+ let bags = '0';
- return (
-
- ))}
+ );
+ })}
)}
-
+
+
+
+
+
+
+
+
+
+ {editingIdx !== null ? (
+ <> Edit Row>
+ ) : (
+ <>Add New Item>
+ )}
+
+
+
+
+
);
}
diff --git a/src/components/rv/OrdersView.tsx b/src/components/rv/OrdersView.tsx
index 8e08dc9..8fab1b2 100644
--- a/src/components/rv/OrdersView.tsx
+++ b/src/components/rv/OrdersView.tsx
@@ -8,10 +8,11 @@ export interface WiredRecordViewProps {
headerActions?: React.ReactNode;
rowActions?: (row: Record
) => React.ReactNode;
refreshKey?: number;
+ initialFilters?: Record;
}
/** Orders record view (Order Booking workflow). */
-export function OrdersView({ onRowClick, pageSize, headerActions, rowActions, refreshKey }: WiredRecordViewProps) {
+export function OrdersView({ onRowClick, pageSize, headerActions, rowActions, refreshKey, initialFilters }: WiredRecordViewProps) {
return (
);
}
diff --git a/src/components/rv/RecordView.tsx b/src/components/rv/RecordView.tsx
index ee9e76c..9c94469 100644
--- a/src/components/rv/RecordView.tsx
+++ b/src/components/rv/RecordView.tsx
@@ -39,6 +39,8 @@ export interface RecordViewProps {
sortBy?: string;
/** Sort direction */
sortDir?: 'asc' | 'desc';
+ /** Default filters to apply initially. */
+ initialFilters?: Record;
}
/**
@@ -60,11 +62,12 @@ export function RecordView({
sortBy,
sortDir,
omitColumns,
+ initialFilters = {},
}: RecordViewProps) {
const [page, setPage] = useState(1);
const [search, setSearch] = useState('');
const [debounced, setDebounced] = useState('');
- const [activeFilters, setActiveFilters] = useState>({});
+ const [activeFilters, setActiveFilters] = useState>(initialFilters);
const [resp, setResp] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
diff --git a/src/screens/CallsPage.tsx b/src/screens/CallsPage.tsx
index 0bd6938..5488583 100644
--- a/src/screens/CallsPage.tsx
+++ b/src/screens/CallsPage.tsx
@@ -2,7 +2,7 @@ import { useNavigate, useParams } from 'react-router-dom';
import { Modal } from '../components/reusable';
import { CallsView } from '../components/rv';
import { CallDetail } from '../components/dv';
-import { useState } from 'react';
+import { useEffect, useState } from 'react';
import { Button } from '../components/buttons/Button';
import { Plus } from 'lucide-react';
import { DynamicForm } from '../components/forms/DynamicForm';
@@ -17,11 +17,74 @@ export function CallsPage() {
const [refreshKey, setRefreshKey] = useState(0);
const [activeActivity, setActiveActivity] = useState<{ id: string; name: string } | null>(null);
+ const [selectedRow, setSelectedRow] = useState | null>(null);
+ const [miningLoading, setMiningLoading] = useState(false);
+ const [miningPrefill, setMiningPrefill] = useState | undefined>();
+
+ useEffect(() => {
+ if (instanceId != null && !selectedRow) {
+ orderBookingClient.recordView(ORDER_BOOKING.recordViews.CALLS, {
+ page: 1,
+ limit: 1,
+ filters: [{ field_key: 'instance_id', value: String(instanceId), data_type: 'number' }]
+ }).then(res => {
+ if (res.data && res.data.length > 0) {
+ setSelectedRow(res.data[0]);
+ }
+ }).catch(err => console.error("Failed to fetch selected row:", err));
+ }
+ }, [instanceId, selectedRow]);
+
+ const handlePotentialMiningClick = async () => {
+ setMiningLoading(true);
+ setMiningPrefill(undefined);
+ try {
+ const storeCode = selectedRow?.store_code || selectedRow?.code || selectedRow?.store?.store_code;
+
+ if (!storeCode) {
+ console.warn("Store code not found on selected row, proceeding anyway.");
+ }
+
+ const payload = {
+ store_code: storeCode,
+ instance_id: String(instanceId)
+ };
+
+ const response = await orderBookingClient.request<{ potential: { potential: any[] } }>(
+ 'POST',
+ '/api/papi2/potential-mining',
+ payload,
+ { 'TemplateID': '146' }
+ );
+
+ const rawPotential = response.potential?.potential || [];
+ const mappedPotential = rawPotential.map((row: any) => {
+ const cat = row.product_category || row.product_category_ || row.category;
+ return {
+ ...row,
+ product_category_: cat,
+ product_category: cat,
+ productcategory: cat,
+ category: cat,
+ product_category_1: cat
+ };
+ });
+
+ setMiningPrefill({ potential: mappedPotential });
+ setActiveActivity({ id: ORDER_BOOKING.activities.POTENTIAL_MINING.uid, name: 'Potential Mining' });
+ } catch (e: any) {
+ alert("Failed to fetch potential mining data: " + (e.message || "Unknown error"));
+ } finally {
+ setMiningLoading(false);
+ }
+ };
+
return (
<>
{
+ setSelectedRow(row);
const id = row.instance_id as number | string | undefined;
if (id != null) navigate(`/calls/${id}`);
}}
@@ -56,14 +119,33 @@ export function CallsPage() {
width="lg"
actions={
<>
-
-
+ }
+ />
+
+ setIsCreating(false)}
+ title="Place Order"
+ width="md"
+ >
+ {
+ setIsCreating(false);
+ setRefreshKey(k => k + 1);
+ }}
+ onCancel={() => setIsCreating(false)}
+ />
+
+
+ {
+ navigate(`/my-orders`);
+ }}
+ title={instanceId != null ? `Order #${instanceId}` : undefined}
+ width="lg"
+ >
+ {instanceId != null && }
+
+ >
+ );
+}
diff --git a/src/screens/OrdersPage.tsx b/src/screens/OrdersPage.tsx
index 3f85b3a..d2651c5 100644
--- a/src/screens/OrdersPage.tsx
+++ b/src/screens/OrdersPage.tsx
@@ -15,8 +15,6 @@ export function OrdersPage() {
const navigate = useNavigate();
const [isCreating, setIsCreating] = useState(false);
const [refreshKey, setRefreshKey] = useState(0);
- const [activeActivity, setActiveActivity] = useState<{ id: string; name: string } | null>(null);
-
return (
<>
navigate(`/orders`)}
+ onClose={() => {
+ navigate(`/orders`);
+ }}
title={instanceId != null ? `Order #${instanceId}` : undefined}
width="lg"
- actions={
- <>
- setActiveActivity({ id: ORDER_BOOKING.activities.POTENTIAL_MINING.uid, name: 'Potential Mining' })}>
- Potential Mining
-
- setActiveActivity({ id: ORDER_BOOKING.activities.PLACE_ORDER.uid, name: 'Place Order' })}>
- Place Order
-
- >
- }
>
{instanceId != null && }
-
- setActiveActivity(null)}
- title={activeActivity?.name}
- width="md"
- >
- {activeActivity && instanceId != null && (
- {
- setActiveActivity(null);
- setRefreshKey(k => k + 1);
- }}
- onCancel={() => setActiveActivity(null)}
- />
- )}
-
>
);
}
diff --git a/src/screens/tabs.ts b/src/screens/tabs.ts
index 2912e2b..f9a47c1 100644
--- a/src/screens/tabs.ts
+++ b/src/screens/tabs.ts
@@ -1,4 +1,4 @@
-import { Store, Phone, ShoppingCart, ClipboardList, type LucideIcon } from 'lucide-react';
+import { Store, Phone, ShoppingCart, ClipboardList, FileText, type LucideIcon } from 'lucide-react';
import {
OrdersView,
CallsView,
@@ -14,7 +14,7 @@ import {
type WiredDetailViewProps,
} from '../components/dv';
-export type ScreenKey = 'orders' | 'calls' | 'stores' | 'daily';
+export type ScreenKey = 'orders' | 'my-orders' | 'calls' | 'stores' | 'daily' | 'sales-report';
export interface ScreenDef {
key: ScreenKey;
@@ -28,9 +28,11 @@ export interface ScreenDef {
export const SCREENS: ScreenDef[] = [
{ key: 'orders', label: 'Orders', icon: ShoppingCart, View: OrdersView, Detail: OrderDetail, noun: 'Order' },
+ { key: 'my-orders', label: 'My Orders', icon: ShoppingCart, View: OrdersView, Detail: OrderDetail, noun: 'My Order' },
{ key: 'calls', label: 'Calls', icon: Phone, View: CallsView, Detail: CallDetail, noun: 'Call' },
{ key: 'stores', label: 'Stores', icon: Store, View: StoresView, Detail: StoreDetail, noun: 'Store' },
{ key: 'daily', label: 'Daily Logs', icon: ClipboardList, View: DailyLogsView, Detail: DailyLogDetail, noun: 'Daily Log' },
+ { key: 'sales-report', label: 'Sales Report', icon: FileText, View: null as any, Detail: null as any, noun: 'Sales Report' },
];
export function screenByKey(key: string | undefined): ScreenDef | undefined {