From 9986f7c16b3ff16a75330de09947da3540a122a1 Mon Sep 17 00:00:00 2001 From: Malini Date: Fri, 7 Nov 2025 19:02:38 +0530 Subject: [PATCH] bug fixed in admin dashboard --- .../src/components/admin/SubmissionTable.jsx | 28 +- .../src/components/common/StatusBadge.jsx | 2 + .../dashboard/SubmissionHistory.jsx | 18 +- .../components/dashboard/SurveyCarousel.jsx | 2 +- .../components/overview/DetailedOverview.jsx | 9 +- .../components/overview/ProductDetails.jsx | 13 +- .../survey/ReviewSubmit/ReviewSubmit.jsx | 10 +- .../src/pages/Admin/ValidationReview.jsx | 267 +++++++++++------- .../src/pages/Admin/Validations.jsx | 6 + .../Admin/configuration/CompanyProfile.jsx | 2 + .../src/pages/History/History.jsx | 70 +++-- .../src/pages/Overview/Overview.jsx | 1 + .../src/pages/Survey/Survey.jsx | 204 ++++++++++--- 13 files changed, 458 insertions(+), 174 deletions(-) diff --git a/ipi-survey-platform/src/components/admin/SubmissionTable.jsx b/ipi-survey-platform/src/components/admin/SubmissionTable.jsx index 5229c97..86c4bbe 100644 --- a/ipi-survey-platform/src/components/admin/SubmissionTable.jsx +++ b/ipi-survey-platform/src/components/admin/SubmissionTable.jsx @@ -84,10 +84,16 @@ const SubmissionTable = ({ selectedQuarter, selectedYear }) => { Rejected ); - } else if (normalized === 'pending') { + } else if (normalized === 'submitted') { return ( - Pending + Submitted + + ); + } else if (normalized === 'resubmitted') { + return ( + + Resubmitted ); } else { @@ -133,12 +139,14 @@ const SubmissionTable = ({ selectedQuarter, selectedYear }) => { return (
+ className="border border-[#E5E7EB] bg-white shadow-[0_8px_16px_rgba(15,23,42,0.05)] rounded-[6px] w-full overflow-hidden py-2" + style={{ + minHeight: filtered.length === 0 || loading ? 'auto' : '200px', + }} + > +

+ {titleText} +

{/*

@@ -155,7 +163,7 @@ const SubmissionTable = ({ selectedQuarter, selectedYear }) => { No Submission Found

) : ( -
+
{ diff --git a/ipi-survey-platform/src/components/common/StatusBadge.jsx b/ipi-survey-platform/src/components/common/StatusBadge.jsx index 3a95ba1..60f51da 100644 --- a/ipi-survey-platform/src/components/common/StatusBadge.jsx +++ b/ipi-survey-platform/src/components/common/StatusBadge.jsx @@ -3,12 +3,14 @@ import React from 'react'; const toneClasses = { green: 'bg-[#F3FAF4] text-[#2F663C] ring-1 ring-[#C4E5CC]', gray: 'bg-[#E9EDF3] text-[#232528] ring-1 ring-[#D6DBE4]', + resubmitted: 'bg-[#F9F7ED] text-[#8B8000] ring-1 ring-[#E5DFC5]', }; const normalizeTone = (tone, status) => { if (tone) return tone; const normalizedStatus = String(status || '').toLowerCase(); if (normalizedStatus === 'active' || normalizedStatus === 'open') return 'green'; + if (normalizedStatus === 'resubmitted') return 'resubmitted'; return 'gray'; }; diff --git a/ipi-survey-platform/src/components/dashboard/SubmissionHistory.jsx b/ipi-survey-platform/src/components/dashboard/SubmissionHistory.jsx index b8b1f60..cf8abf1 100644 --- a/ipi-survey-platform/src/components/dashboard/SubmissionHistory.jsx +++ b/ipi-survey-platform/src/components/dashboard/SubmissionHistory.jsx @@ -30,16 +30,28 @@ const getStatusBadge = (status) => { Approved ); + } else if (normalized === 'submitted') { + return ( + + Submitted + + ); + } else if (normalized === 'resubmitted') { + return ( + + Resubmitted + + ); } else if (['pending', 'under review', 'in-progress'].includes(normalized)) { return ( Under Review ); - } else if (['rejected', 'returned'].includes(normalized)) { + } else if (normalized === 'rejected') { return ( - Returned + Rejected ); } else { @@ -63,7 +75,7 @@ const downloadCsv = (data) => { const normalized = String(item.status || '').toLowerCase(); if (normalized === 'approved') return 'Approved'; if (['pending', 'under review', 'in-progress'].includes(normalized)) return 'Under Review'; - if (['rejected', 'returned'].includes(normalized)) return 'Returned'; + if (['rejected', 'rejected'].includes(normalized)) return 'Returned'; return item.status || '—'; })(); diff --git a/ipi-survey-platform/src/components/dashboard/SurveyCarousel.jsx b/ipi-survey-platform/src/components/dashboard/SurveyCarousel.jsx index aae8120..19b39cd 100644 --- a/ipi-survey-platform/src/components/dashboard/SurveyCarousel.jsx +++ b/ipi-survey-platform/src/components/dashboard/SurveyCarousel.jsx @@ -30,7 +30,7 @@ const SurveyCarousel = ({ setCurrentIndex((prev) => (prev === surveys.length - 1 ? 0 : prev + 1)); return ( -
+

diff --git a/ipi-survey-platform/src/components/overview/DetailedOverview.jsx b/ipi-survey-platform/src/components/overview/DetailedOverview.jsx index 1940f75..dd964d5 100644 --- a/ipi-survey-platform/src/components/overview/DetailedOverview.jsx +++ b/ipi-survey-platform/src/components/overview/DetailedOverview.jsx @@ -44,7 +44,8 @@ export const DetailedOverview = ({ submission, onBack }) => { 'Approved': 'bg-[#F3FAF4] text-[#2F663C]', 'Submitted': 'bg-[#E7F5FF] text-[#003CFF]', 'Pending': 'bg-[#F9F7ED] text-[#7C5E24]', - 'Rejected': 'bg-[#FEF2F2] text-[#B52520]' + 'Rejected': 'bg-[#FEF2F2] text-[#B52520]', + 'Resubmitted': 'bg-[#F9F7ED] text-[#7C5E24]' }; const statusClass = statusMap[status] || 'bg-gray-100 text-gray-800'; @@ -172,7 +173,7 @@ export const DetailedOverview = ({ submission, onBack }) => { product.current_cost || '0', product.forecast_quantity || '0', product.forecast_cost || '0', - product.status || 'Pending' + product.status || 'Submitted' ].map((value) => `"${String(value).replace(/"/g, '""')}"`).join(',')); }); @@ -231,8 +232,8 @@ export const DetailedOverview = ({ submission, onBack }) => { productData.hs_code || '—', productData.product_name || '—', unit.uom || 'N/A', - product.previous_quantity || '0', - `AED ${product.previous_cost || '0'}`, + product.current_quantity || '0', + `AED ${product.current_cost || '0'}`, // {}, isSubmitting = false, hasSubmitted = false, + submitButtonText = 'Submit', }) => { const [confirm, setConfirm] = React.useState(false); const [remarks, setRemarks] = React.useState(() => { @@ -734,11 +735,10 @@ const ReviewSubmit = ({

Remarks

-
- - ))} + +
+ {/*

+ Green ▲ indicates upward trend;{' '} + Red ▼ indicates downward trend compared to previous month or quarter +

*/} +

+ Remarks: NA +

+ +
+ + +
+

+ +))} +
) : (

No products found for this submission.

diff --git a/ipi-survey-platform/src/pages/Admin/Validations.jsx b/ipi-survey-platform/src/pages/Admin/Validations.jsx index e0d101d..3547d31 100644 --- a/ipi-survey-platform/src/pages/Admin/Validations.jsx +++ b/ipi-survey-platform/src/pages/Admin/Validations.jsx @@ -13,6 +13,8 @@ const STATUS_VARIANTS = { Approved: { background: '#F3FAF4', text: '#2F663C', border: '#F3FAF4' }, Pending: { background: '#E7F5FF', text: '#286CFF', border: '#E7F5FF' }, Rejected: { background: '#FEF2F2', text: '#B52520', border: '#FEF2F2' }, + Resubmitted: { background: '#F9F7ED', text: '#7C5E24', border: '#FEF2F2' }, + Submitted: { background: '#E7F5FF', text: '#003CFF', border: '#FEF2F2' }, }; const SUMMARY_VARIANTS = { @@ -20,8 +22,12 @@ const SUMMARY_VARIANTS = { approved: { background: '#F3FAF4', label: '#2F663C', value: '#232528' }, pending: { background: '#E7F5FF', label: '#003CFF', value: '#232528' }, rejected: { background: '#FEF2F2', label: '#B52520', value: '#232528' }, + resubmitted: { background: '#F9F7ED', text: '#7C5E24', border: '#FEF2F2' }, + submitted: { background: '#E7F5FF', text: '#003CFF', border: '#FEF2F2' }, + }; + const formatDateTime = (value) => { if (!value) return '—'; const date = new Date(value); diff --git a/ipi-survey-platform/src/pages/Admin/configuration/CompanyProfile.jsx b/ipi-survey-platform/src/pages/Admin/configuration/CompanyProfile.jsx index c4ee233..49f77eb 100644 --- a/ipi-survey-platform/src/pages/Admin/configuration/CompanyProfile.jsx +++ b/ipi-survey-platform/src/pages/Admin/configuration/CompanyProfile.jsx @@ -1947,6 +1947,7 @@ const requiredFields = [ factory_name: form.establishmentName || form.contactName || '', permanent_factory_code: form.permanentFactoryCode || '', industry_code: form.industryCodeBusiness || form.industryCodeCurrent || '', + industry_code_production: form.industryCodeBusiness || form.industryCodeCurrent || '', license_number: form.uniqueLicenseNumber || '', isic_code: form.isicCode || form.industryCodeBusiness || '', description: form.industryDescription || '', @@ -2025,6 +2026,7 @@ const requiredFields = [ factory_name: form.establishmentName || form.contactName || '', permanent_factory_code: form.permanentFactoryCode || '', industry_code: form.industryCodeBusiness || form.industryCodeCurrent || '', + industry_code_production: form.industryCodeBusiness || form.industryCodeCurrent || '', license_number: form.uniqueLicenseNumber || '', isic_code: form.isicCode || form.industryCodeBusiness || '', description: form.industryDescription || '', diff --git a/ipi-survey-platform/src/pages/History/History.jsx b/ipi-survey-platform/src/pages/History/History.jsx index a220858..3f20cfc 100644 --- a/ipi-survey-platform/src/pages/History/History.jsx +++ b/ipi-survey-platform/src/pages/History/History.jsx @@ -11,15 +11,40 @@ const BreadcrumbVector = '/assets/images/Breadcrumb-vector.svg'; const caretDownSrc = '/assets/images/CaretDown.svg'; const Badge = ({ variant = 'default', children }) => { + // Define all possible status variants and their styles const styles = { - approved: 'bg-[#F3FAF4] text-[#2F663C]', - submitted: 'bg-[#E7F5FF] text-[#003CFF]', - pending: 'bg-[#F9F7ED] text-[#7C5E24]', - rejected: 'bg-[#FEF2F2] text-[#B52520]', - default: 'bg-gray-50 text-gray-700', + // Approved status + approved: 'text-green-700 bg-green-50', + + // Submitted status + submitted: 'text-green-700 bg-green-50', + + // Under Review status (includes pending and in-progress) + 'under review': 'text-blue-600 bg-blue-50', + pending: 'text-blue-600 bg-blue-50', + 'in-progress': 'text-blue-600 bg-blue-50', + + // Rejected status (includes returned) + rejected: 'text-red-600 bg-red-50', + returned: 'text-red-600 bg-red-50', + + // Resubmitted status + resubmitted: 'text-[#7C5E24] bg-[#F9F7ED]', + + // Default fallback + default: 'text-gray-600 bg-gray-50', }; + + // Normalize the variant key + const normalizedVariant = String(variant || '').toLowerCase().trim(); + + // Get the appropriate style, fallback to default if not found + const style = styles[normalizedVariant] || styles.default; + return ( - + {children} ); @@ -180,8 +205,9 @@ const formatExportDateTime = (value) => { const text = String(status || '').toLowerCase(); if (text === 'approved') return 'approved'; if (text === 'submitted') return 'submitted'; - if (text === 'rejected') return 'rejected'; - if (text === 'pending' || text === 'in-progress' || text === 'under review') return 'pending'; + if (text === 'resubmitted') return 'resubmitted'; + if (text === 'rejected' || text === 'returned') return 'rejected'; + if (text === 'pending' || text === 'in-progress' || text === 'under review') return 'under review'; return 'default'; }, []); @@ -375,7 +401,7 @@ const filteredRows = useMemo(() => { 'Quarter', 'HS Code', 'Product', - 'Status', + { name: 'Status', className: 'text-center' }, 'Actors', 'Details' ]; @@ -850,14 +876,24 @@ const tableRows = auditHistory.map((entry, index) => { loading={loading} error={error} className="mt-4" - pagination={{ - currentPage: pagination.currentPage, - onPageChange: handlePageChange, - pageSize: pagination.pageSize, - totalItems: pagination.totalItems, - pageSizeOptions: [10, 25, 50, 100], - onPageSizeChange: handlePageSizeChange, - }} + columnWidths={[ + { width: 180, style: { whiteSpace: 'normal', wordWrap: 'break-word' } }, // Submission Date + { width: 80, style: { whiteSpace: 'normal', wordWrap: 'break-word' } }, // Year + { width: 80, style: { whiteSpace: 'normal', wordWrap: 'break-word' } }, // Quarter + { width: 120, style: { whiteSpace: 'normal', wordWrap: 'break-word' } }, // HS Code + { width: 200, style: { whiteSpace: 'normal', wordWrap: 'break-word' } }, // Product + { width: 130, align: 'center', style: { whiteSpace: 'normal', wordWrap: 'break-word' } }, // Status + { width: 140, style: { whiteSpace: 'normal', wordWrap: 'break-word' } }, // Actors + { width: 270, style: { whiteSpace: 'normal', wordWrap: 'break-word' } } // Details + ]} + pagination={{ + currentPage: pagination.currentPage, + onPageChange: handlePageChange, + pageSize: pagination.pageSize, + totalItems: pagination.totalItems, + pageSizeOptions: [10, 25, 50, 100], + onPageSizeChange: handlePageSizeChange, + }} renderCell={(value, ri, ci) => { if (ci === 5) { // Status column return {formatStatus(filteredRows[ri]?.status)}; diff --git a/ipi-survey-platform/src/pages/Overview/Overview.jsx b/ipi-survey-platform/src/pages/Overview/Overview.jsx index 8120201..dda524f 100644 --- a/ipi-survey-platform/src/pages/Overview/Overview.jsx +++ b/ipi-survey-platform/src/pages/Overview/Overview.jsx @@ -14,6 +14,7 @@ const statusStyles = { submitted: 'text-[#003CFF] bg-[#E7F5FF]', pending: 'text-[#7C5E24] bg-[#F9F7ED]', rejected: 'text-[#B52520] bg-[#FEF2F2]', + resubmitted: 'text-[#7C5E24] bg-[#F9F7ED]', }; const formatDate = (dateString) => { diff --git a/ipi-survey-platform/src/pages/Survey/Survey.jsx b/ipi-survey-platform/src/pages/Survey/Survey.jsx index aba2fef..2d7402a 100644 --- a/ipi-survey-platform/src/pages/Survey/Survey.jsx +++ b/ipi-survey-platform/src/pages/Survey/Survey.jsx @@ -1,6 +1,6 @@ import React from 'react'; import { useLocation, useNavigate } from 'react-router-dom'; -import { submitSurvey, fetchSubmissionDetail } from '@/services/submissions/submissionService'; +import { submitSurvey, fetchSubmissionDetail, resubmitSurvey } from '@/services/submissions/submissionService'; import { fetchEstablishmentDetail, fetchEstablishmentDashboard } from '@/services/establishments/establishmentService'; import EstablishmentInfo from '@/components/survey/EstablishmentInfo/EstablishmentInfo'; import HeaderBar from '@/components/layout/HeaderBar'; @@ -71,6 +71,8 @@ const Survey = () => { const [establishmentLoading, setEstablishmentLoading] = React.useState(false); const [establishmentError, setEstablishmentError] = React.useState(''); const isViewMode = React.useMemo(() => Boolean(locationState.submission), [locationState.submission]); + const isResubmit = React.useMemo(() => locationState?.isResubmit === true, [locationState?.isResubmit]); + const submissionId = React.useMemo(() => locationState?.submissionId || locationState?.submission?.id, [locationState]); const toastTimeoutRef = React.useRef(null); React.useEffect(() => { @@ -98,8 +100,18 @@ const Survey = () => { const initializeSurveyData = async () => { try { + // If this is a resubmission, use the quarter and year from the submission + if (isResubmit && locationState?.submission) { + if (!cancelled) { + setEstablishmentData(prev => ({ + ...prev, + quarter: locationState.submission.quarter || '', + year: locationState.submission.year?.toString() || '' + })); + } + } // If quarter and year are not provided in location state, fetch them - if (!locationState?.currentQuarter || !locationState?.currentYear) { + else if (!locationState?.currentQuarter || !locationState?.currentYear) { const { quarter, year } = await fetchCurrentQuarterAndYear(); if (!cancelled) { setEstablishmentData(prev => ({ @@ -128,7 +140,7 @@ const Survey = () => { return () => { cancelled = true; }; - }, [locationState?.currentQuarter, locationState?.currentYear]); // Only depend on these values + }, [locationState?.currentQuarter, locationState?.currentYear]); React.useEffect(() => { let cancelled = false; @@ -204,19 +216,39 @@ const Survey = () => { const mergeEstablishmentData = (detail) => { const summary = locationState.submission || {}; + const establishment = detail?.establishment || {}; + return { quarter: ensureString(detail?.quarter) || ensureString(summary.quarter) || '', year: ensureString(detail?.year) || ensureString(summary.year) || '', - establishmentName: ensureString(summary.establishment_name) || establishmentData.establishmentName || '', - permanentFactoryCode: - ensureString(summary.permanent_factory_code) || - ensureString(detail?.establishment_id) || - establishmentData.permanentFactoryCode || '', - industryCode: ensureString(summary.industry_code) || establishmentData.industryCode || '', - licenseNumber: ensureString(summary.license_number) || establishmentData.licenseNumber || '', - isicCode: ensureString(summary.isic_code) || establishmentData.isicCode || '', - emirate: ensureString(summary.emirate) || establishmentData.emirate || '', - employeeInfo: { ...establishmentData.employeeInfo }, + establishmentName: ensureString(establishment.factory_name) || + ensureString(summary.establishment_name) || + establishmentData.establishmentName || '', + permanentFactoryCode: ensureString(establishment.permanent_factory_code) || + ensureString(summary.permanent_factory_code) || + ensureString(detail?.establishment_id) || + establishmentData.permanentFactoryCode || '', + industryCode: ensureString(establishment.industry_code) || + ensureString(summary.industry_code) || + establishmentData.industryCode || '', + licenseNumber: ensureString(establishment.license_number) || + ensureString(summary.license_number) || + establishmentData.licenseNumber || '', + isicCode: ensureString(establishment.isic_code) || + ensureString(summary.isic_code) || + establishmentData.isicCode || '', + emirate: ensureString(establishment.establishment_emirate_id) || + ensureString(establishment.emirate) || + ensureString(summary.emirate) || + establishmentData.emirate || '', + employeeInfo: { + emiratiMale: ensureString(establishment.emirati_male) || establishmentData.employeeInfo.emiratiMale || '', + emiratiFemale: ensureString(establishment.emirati_female) || establishmentData.employeeInfo.emiratiFemale || '', + nonEmiratiMale: ensureString(establishment.non_emirati_male) || establishmentData.employeeInfo.nonEmiratiMale || '', + nonEmiratiFemale: ensureString(establishment.non_emirati_female) || establishmentData.employeeInfo.nonEmiratiFemale || '', + totalEmirati: ensureString(establishment.total_emirati) || establishmentData.employeeInfo.totalEmirati || '', + totalEmployees: ensureString(establishment.total_employees) || establishmentData.employeeInfo.totalEmployees || '', + }, }; }; @@ -224,20 +256,50 @@ const Survey = () => { if (!Array.isArray(detailProducts)) return []; return detailProducts.map((product, index) => ({ id: product?.id ?? index + 1, + productId: product?.product_id || product?.product?.id || '', product: ensureString(product?.product?.product_name) || ensureString(product?.product_id) || '', - unit: ensureString(product?.unit?.name) || ensureString(product?.unit_id) || '', + unit: ensureString(product?.unit?.uom) || ensureString(product?.unit?.name) || ensureString(product?.unit_id) || '', + unitId: product?.unit_id || product?.unit?.id || '', capacity: ensureString(product?.annual_installed_capacity), - previousQuantity: ensureString(product?.previous_quantity), - previousCost: ensureString(product?.previous_cost), - currentQuantity: ensureString(product?.current_quantity), - currentCost: ensureString(product?.current_cost), - forecastQuantity: ensureString(product?.forecast_quantity), - forecastCost: ensureString(product?.forecast_cost), - variationReason: ensureString(product?.variation_reason_master_id), - otherVariationReason: ensureString(product?.other_variation_reason), - zeroTargetReason: ensureString(product?.zero_target_reason_master_id), - otherZeroTargetReason: ensureString(product?.other_zero_target_reason), - remarks: ensureString(product?.remarks), + + // Previous Quarter (Q4) - October, November, December + octQuantity: ensureString(product?.previous_quantity_period_one || ''), + novQuantity: ensureString(product?.previous_quantity_period_two || ''), + decQuantity: ensureString(product?.previous_quantity_period_three || ''), + octCost: ensureString(product?.previous_cost_period_one || ''), + novCost: ensureString(product?.previous_cost_period_two || ''), + decCost: ensureString(product?.previous_cost_period_three || ''), + + // Current Quarter (Q1) - January, February, March + janQuantity: ensureString(product?.current_quantity_period_one || ''), + febQuantity: ensureString(product?.current_quantity_period_two || ''), + marQuantity: ensureString(product?.current_quantity_period_three || ''), + janCost: ensureString(product?.current_cost_period_one || ''), + febCost: ensureString(product?.current_cost_period_two || ''), + marCost: ensureString(product?.current_cost_period_three || ''), + + // Forecast Quarter (Q2) - April, May, June + aprQuantity: ensureString(product?.forecast_quantity_period_one || ''), + mayQuantity: ensureString(product?.forecast_quantity_period_two || ''), + junQuantity: ensureString(product?.forecast_quantity_period_three || ''), + aprCost: ensureString(product?.forecast_cost_period_one || ''), + mayCost: ensureString(product?.forecast_cost_period_two || ''), + junCost: ensureString(product?.forecast_cost_period_three || ''), + + // Totals (for backward compatibility) + previousQuantity: ensureString(product?.previous_quantity || ''), + previousCost: ensureString(product?.previous_cost || ''), + currentQuantity: ensureString(product?.current_quantity || ''), + currentCost: ensureString(product?.current_cost || ''), + forecastQuantity: ensureString(product?.forecast_quantity || ''), + forecastCost: ensureString(product?.forecast_cost || ''), + + // Reasons and remarks + variationReason: ensureString(product?.variation_reason_master_id || ''), + otherVariationReason: ensureString(product?.other_variation_reason || ''), + zeroTargetReason: ensureString(product?.zero_target_reason_master_id || ''), + otherZeroTargetReason: ensureString(product?.other_zero_target_reason || ''), + remarks: ensureString(product?.remarks || '') })); }; @@ -309,7 +371,7 @@ const Survey = () => { return String(value); }, []); - const buildSubmissionPayload = React.useCallback(() => { + const buildSubmissionPayload = React.useCallback((isResubmitFlow = false) => { const info = establishmentData?.employeeInfo ?? {}; return { quarter: establishmentData?.quarter ?? '', @@ -324,11 +386,13 @@ const Survey = () => { products: productsData.map((product) => { const variationId = parseNumber(product.variationReason, null); const zeroTargetId = parseNumber(product.zeroTargetReason, null); + const productId = parseNumber(product.id); // Map monthly data to period-specific fields return { + ...(isResubmitFlow && productId ? { id: productId } : {}), // Only include ID during resubmit product_id: parseNumber(product.productId) || parseNumber(product.product), - unit_id: parseNumber(product.unit), + unit_id: parseNumber(product.unitId) || parseNumber(product.unit), annual_installed_capacity: stringify(product.capacity), // Previous Quarter (Q4) - October, November, December @@ -412,7 +476,31 @@ const Survey = () => { } }; - const handleSubmit = React.useCallback(async () => { + const handleSubmit = React.useCallback(async (e) => { + if (e) e.preventDefault(); + if (isSubmitting) return; + + // Validate current step before proceeding + if (step === 1) { + const establishmentError = validateEstablishmentInfo(); + if (establishmentError) { + setError(establishmentError); + return; + } + } else if (step === 2) { + const productError = validateProductData(); + if (productError) { + setError(productError); + return; + } + } + + // If this is the final step (step 3) and it's a resubmission, include the submission ID + if (step === 3 && isResubmit && submissionId) { + await handleResubmit(); + return; + } + setIsSubmitting(true); try { const payload = buildSubmissionPayload(); @@ -432,6 +520,57 @@ const Survey = () => { } }, [buildSubmissionPayload, showToast]); + const handleResubmit = async () => { + setIsSubmitting(true); + setError(''); + + try { + const payload = { + ...buildSubmissionPayload(true), // Pass true to indicate resubmission flow + status: 'Resubmitted', // Set status to Resubmitted for resubmissions + id: submissionId // Include submission ID in the payload + }; + + // Use the resubmitSurvey API with the submission ID and payload + await resubmitSurvey(submissionId, payload); + + setShowSuccessPopup(true); + setHasSubmitted(true); + showToast('success', 'Survey resubmitted successfully!'); + } catch (error) { + console.error('Resubmission failed:', error); + const message = error?.response?.data?.message || error?.message || 'Failed to resubmit survey. Please try again.'; + setError(message); + showToast('error', message); + } finally { + setIsSubmitting(false); + } + }; + + const handleFinalSubmit = async () => { + if (isResubmit && submissionId) { + await handleResubmit(); + return; + } + + setIsSubmitting(true); + setError(''); + + try { + const payload = buildSubmissionPayload(); + await submitSurvey(payload); + setShowSuccessPopup(true); + setHasSubmitted(true); + showToast('success', 'Survey submitted successfully!'); + } catch (error) { + const message = error?.response?.data?.message || error?.message || 'Failed to submit survey. Please try again.'; + setError(message); + showToast('error', message); + } finally { + setIsSubmitting(false); + } + }; + const StepBadge = ({ state, number }) => { if (state === 'active') { return ( @@ -634,7 +773,8 @@ const Survey = () => { establishment={establishmentData} products={productsData} onBack={() => setStep(2)} - onSubmit={handleSubmit} + onSubmit={handleFinalSubmit} + submitButtonText={isResubmit ? 'Resubmit' : 'Submit'} toast={toast} onToastClose={() => { if (toastTimeoutRef.current) { @@ -644,7 +784,7 @@ const Survey = () => { setToast(null); }} isSubmitting={isSubmitting} - hasSubmitted={hasSubmitted} + hasSubmitted={false} /> )}
@@ -674,12 +814,12 @@ const Survey = () => { {/* Title */}

- Submission successful + {isResubmit ? 'Resubmission successful' : 'Submission successful'}

{/* Message */}

- Thank you. Your IP Quarterly Survey for {establishmentData?.quarter} {establishmentData?.year} has been submitted. + Thank you. Your IP Quarterly Survey for {establishmentData?.quarter} {establishmentData?.year} has been {isResubmit ? 'resubmitted' : 'submitted'}.

{/* Button */}