From 1357935eadc9b44c927725613ef82c20c17e8d0e Mon Sep 17 00:00:00 2001 From: suryacp23 Date: Wed, 22 Jul 2026 10:58:44 +0530 Subject: [PATCH] potential mining api error fixed --- src/components/forms/DynamicForm.tsx | 97 ++++++++++++++++--- src/components/forms/fields/WfLookupField.tsx | 14 +-- src/components/reusable/AnalyticsChart.tsx | 2 + src/lib/format.ts | 19 +++- src/screens/CallsPage.tsx | 5 +- src/screens/DailyLogsPage.tsx | 1 - src/screens/MyOrdersPage.tsx | 1 - src/screens/OrdersPage.tsx | 1 - src/screens/StoresPage.tsx | 1 - 9 files changed, 110 insertions(+), 31 deletions(-) diff --git a/src/components/forms/DynamicForm.tsx b/src/components/forms/DynamicForm.tsx index 400ff3d..f2581f2 100644 --- a/src/components/forms/DynamicForm.tsx +++ b/src/components/forms/DynamicForm.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from 'react'; +import { useState, useEffect, useRef } from 'react'; import type { ZinoClient } from '../../api/client'; import type { FormScreenResponse } from '../../api/types'; import { Button } from '../buttons/Button'; @@ -17,7 +17,7 @@ import { WfLookupField, RadioField, } from './fields'; -import { ORDER_BOOKING } from '../../api/config'; +import { ORDER_BOOKING, STORE } from '../../api/config'; export interface DynamicFormProps { client: ZinoClient; @@ -122,9 +122,14 @@ export function DynamicForm({ client, activityId: initialActivityId, instanceId: const [submitting, setSubmitting] = useState(false); const [submitError, setSubmitError] = useState(null); - const handleFieldChange = (fieldId: string, newVal: unknown) => { + const clickedActionRef = useRef(null); + + const handleFieldChange = (fieldId: string, newVal: unknown, fullRow?: any) => { setValues(prev => { const next = { ...prev, [fieldId]: newVal }; + if (fullRow) { + next[`${fieldId}_row`] = fullRow; + } // Auto-calculate order_details totals const getBaseIdForField = (id: string) => id.replace(/_\d+$/, ''); @@ -174,15 +179,22 @@ export function DynamicForm({ client, activityId: initialActivityId, instanceId: // Filter out disabled fields (usually server-generated IDs) const fields = schema.fields.filter(f => !f.properties?.disabled); + const actionField = fields.find(f => f.name.toLowerCase() === 'action' && f.data_type === 'radio'); + const normalFields = fields.filter(f => f !== actionField); + const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setSubmitting(true); setSubmitError(null); try { const payload: Record = {}; + const finalValues = { ...values }; + if (actionField && clickedActionRef.current) { + finalValues[actionField.id] = clickedActionRef.current; + } for (const f of fields) { - const val = values[f.id]; + const val = finalValues[f.id]; if (val == null) continue; if (f.data_type === 'phone' && typeof val === 'string') { @@ -243,11 +255,52 @@ export function DynamicForm({ client, activityId: initialActivityId, instanceId: if (nextActivity) { let nextPrefillData = undefined; if (nextActivity.activity_uid === ORDER_BOOKING.activities.POTENTIAL_MINING.uid) { + let storeCodeToSend = String((values['select_store_row'] as any)?.store_code || (chainedPrefillData?.['select_store_row'] as any)?.store_code || ''); + + if (!storeCodeToSend) { + let storeId = values['select_store'] || chainedPrefillData?.['select_store'] || (schema?.prefill_data as any)?.select_store || (schema?.data as any)?.select_store; + if (typeof storeId === 'object' && storeId !== null) { + storeCodeToSend = (storeId as any).store_code || storeCodeToSend; + storeId = (storeId as any).value || (storeId as any).instance_id || String(storeId); + } + if (!storeCodeToSend && storeId) { + try { + const detailRes = await client.detailView(STORE.detailViews.STORE, storeId); + if (detailRes.data && detailRes.data.store_code) { + storeCodeToSend = String(detailRes.data.store_code); + } + } catch(e) { + try { + const lookupRes = await client.wfLookupRecords({ + activityId: ORDER_BOOKING.activities.LOG_VISIT.uid, + fieldId: ORDER_BOOKING.activities.LOG_VISIT.fields.selectStore, + formData: { ...(chainedPrefillData as any || {}), ...values, ...(schema?.prefill_data as any || {}) }, + limit: 500 + }); + const arr = Array.isArray(lookupRes) ? lookupRes : (lookupRes.data || lookupRes.records || []); + const row = arr.find((r: any) => String(r.instance_id || r.id) === String(storeId)); + if (row && row.store_code) { + storeCodeToSend = String(row.store_code); + } + } catch (err) { + console.error("Failed to fetch store code:", err); + } + } + } + } + + if (!storeCodeToSend) { + storeCodeToSend = String(values['select_store'] || chainedPrefillData?.['select_store'] || (schema?.prefill_data as any)?.select_store || ''); + } + try { const pmRes = await client.request<{ potential: { potential: any[] } }>( 'POST', '/api/papi2/potential-mining', - { instance_id: String(res.instance_id ?? currentInstanceId) }, + { + instance_id: String(res.instance_id ?? currentInstanceId), + store_code: storeCodeToSend + }, { 'TemplateID': '146' } ); const rawPotential = pmRes.potential?.potential || []; @@ -268,11 +321,11 @@ export function DynamicForm({ client, activityId: initialActivityId, instanceId: } } - if (nextPrefillData) { - setChainedPrefillData(nextPrefillData); - } else { - setChainedPrefillData(undefined); - } + setChainedPrefillData(prev => ({ + ...prev, + ...values, + ...(nextPrefillData || {}) + })); setChainQueue(pending); setCurrentActivityId(nextActivity.activity_uid); @@ -290,7 +343,7 @@ export function DynamicForm({ client, activityId: initialActivityId, instanceId: return (
- {fields.map(f => { + {normalFields.map(f => { const type = f.data_type; const val = values[f.id]; const isDisabled = schema.field_defaults?.[f.id]?.disabled; @@ -308,7 +361,7 @@ export function DynamicForm({ client, activityId: initialActivityId, instanceId: activityId={currentActivityId} fieldId={f.id} formData={values} - onChange={(newVal) => handleFieldChange(f.id, newVal)} + onChange={(newVal, fullRow) => handleFieldChange(f.id, newVal, fullRow)} /> ); } @@ -456,9 +509,23 @@ export function DynamicForm({ client, activityId: initialActivityId, instanceId: Cancel )} - + {actionField && actionField.properties?.options ? ( + actionField.properties.options.map((opt: any) => ( + + )) + ) : ( + + )}
); diff --git a/src/components/forms/fields/WfLookupField.tsx b/src/components/forms/fields/WfLookupField.tsx index 568066e..efe1be8 100644 --- a/src/components/forms/fields/WfLookupField.tsx +++ b/src/components/forms/fields/WfLookupField.tsx @@ -6,7 +6,7 @@ export interface WfLookupFieldProps { label: string; required?: boolean; value: string | number; - onChange: (val: string) => void; + onChange: (val: string, fullRow?: any) => void; client: ZinoClient; config: any; // wf_lookup_config properties?: any; // parent field properties @@ -17,14 +17,13 @@ export interface WfLookupFieldProps { export function WfLookupField({ label, required, value, onChange, client, config, activityId, fieldId, formData }: WfLookupFieldProps) { const [options, setOptions] = useState<{ label: string; value: string }[]>([]); - const [loading, setLoading] = useState(true); + const [records, setRecords] = useState([]); const formDataStr = JSON.stringify(formData); useEffect(() => { let mounted = true; - setLoading(true); const timer = setTimeout(() => { client.wfLookupRecords({ activityId, @@ -36,6 +35,7 @@ export function WfLookupField({ label, required, value, onChange, client, config if (!mounted) return; // The API might return { data: [...] } or { records: [...] } or just an array const arr = Array.isArray(res) ? res : (res.data || res.records || []); + setRecords(arr); const displayFields = config?.display_fields || []; @@ -59,9 +59,6 @@ export function WfLookupField({ label, required, value, onChange, client, config }) .catch(err => { console.error("Failed to load wf_lookup records:", err); - }) - .finally(() => { - if (mounted) setLoading(false); }); }, 300); @@ -76,7 +73,10 @@ export function WfLookupField({ label, required, value, onChange, client, config label={label} required={required} value={String(value || '')} - onChange={onChange} + onChange={(val) => { + const row = records.find(r => String(r.instance_id || r.id) === val); + onChange(val, row); + }} options={options} /> ); diff --git a/src/components/reusable/AnalyticsChart.tsx b/src/components/reusable/AnalyticsChart.tsx index d3651a4..c29377e 100644 --- a/src/components/reusable/AnalyticsChart.tsx +++ b/src/components/reusable/AnalyticsChart.tsx @@ -86,6 +86,8 @@ export function AnalyticsChart({ data }: AnalyticsChartProps) { chartType = 4; // Donut } else if (lowerKey.includes('brand') || lowerKey.includes('product')) { chartType = 5; // Table + } else if (lowerKey.includes('monthly')) { + chartType = 0; // Bar } const renderChartContent = () => { diff --git a/src/lib/format.ts b/src/lib/format.ts index d26e8bf..a822d93 100644 --- a/src/lib/format.ts +++ b/src/lib/format.ts @@ -26,10 +26,22 @@ export function formatValue(value: unknown, fieldKey?: string): string { const isTimeOnly = lowerKey.includes('time'); const isDateOnly = lowerKey.includes('date'); + const isYearZero = typeof value === 'string' && value.startsWith('0000-01-01'); + if (isTimeOnly && !isDateOnly) { - return date.toLocaleTimeString('en-IN', { hour: 'numeric', minute: '2-digit', hour12: true }); + return date.toLocaleTimeString('en-IN', { + hour: 'numeric', + minute: '2-digit', + hour12: true, + ...(isYearZero && { timeZone: 'UTC' }) + }); } else if (isDateOnly && !isTimeOnly) { - return date.toLocaleDateString('en-IN', { day: 'numeric', month: 'short', year: 'numeric' }); + return date.toLocaleDateString('en-IN', { + day: 'numeric', + month: 'short', + year: 'numeric', + ...(isYearZero && { timeZone: 'UTC' }) + }); } else { return date.toLocaleString('en-IN', { day: 'numeric', @@ -37,7 +49,8 @@ export function formatValue(value: unknown, fieldKey?: string): string { year: 'numeric', hour: 'numeric', minute: '2-digit', - hour12: true + hour12: true, + ...(isYearZero && { timeZone: 'UTC' }) }); } } diff --git a/src/screens/CallsPage.tsx b/src/screens/CallsPage.tsx index c0676d3..8710063 100644 --- a/src/screens/CallsPage.tsx +++ b/src/screens/CallsPage.tsx @@ -6,7 +6,6 @@ import { useEffect, useState } from 'react'; import { Button } from '../components/buttons/Button'; import { Plus } from 'lucide-react'; import { DynamicForm } from '../components/forms/DynamicForm'; -import { formatActivityName } from '../lib/format'; import { ORDER_BOOKING } from '../api/config'; import { orderBookingClient } from '../api/clients'; @@ -139,7 +138,9 @@ export function CallsPage() { placeOrderAction={ (() => { const stateName = String(selectedRow.current_state_name || selectedRow.current_state_name_ || selectedRow.current_state || selectedRow.status || '').toLowerCase(); - if (stateName.includes('ordered') || stateName === 'ordered' || stateName.includes('order')) { + if (stateName === 'no order' || stateName === 'no_order') { + return null; + } else if (stateName.includes('ordered') || stateName === 'ordered' || stateName.includes('order')) { return (