parent
8f3234167a
commit
73fe26edc4
@ -6,10 +6,7 @@ import HeaderBar from '@/components/layout/HeaderBar';
|
|||||||
import DetailedOverview from '@/components/overview/DetailedOverview';
|
import DetailedOverview from '@/components/overview/DetailedOverview';
|
||||||
|
|
||||||
const searchIconSrc = '/assets/images/material-symbols_search-rounded.svg';
|
const searchIconSrc = '/assets/images/material-symbols_search-rounded.svg';
|
||||||
const pencilIconSrc = '/assets/images/PencilSimple.svg';
|
|
||||||
import { fetchSubmissionDetail } from '@/services/submissions/submissionService';
|
|
||||||
const trashActiveSrc = '/assets/images/Trash - active.svg';
|
|
||||||
const trashInactiveSrc = '/assets/images/Trash - Inactive.svg';
|
|
||||||
const formatDateTime = (value) => {
|
const formatDateTime = (value) => {
|
||||||
if (!value) return '—';
|
if (!value) return '—';
|
||||||
const date = new Date(value);
|
const date = new Date(value);
|
||||||
@ -141,45 +138,13 @@ export const SubmissionHistory = ({ history = [], loading = false, error = '' })
|
|||||||
const [searchTerm, setSearchTerm] = React.useState('');
|
const [searchTerm, setSearchTerm] = React.useState('');
|
||||||
const [selectedSubmission, setSelectedSubmission] = React.useState(null);
|
const [selectedSubmission, setSelectedSubmission] = React.useState(null);
|
||||||
const [currentPage, setCurrentPage] = React.useState(1);
|
const [currentPage, setCurrentPage] = React.useState(1);
|
||||||
const [hoveredDelete, setHoveredDelete] = React.useState(null);
|
|
||||||
|
|
||||||
const pageSize = 10;
|
const pageSize = 10;
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const handleViewDetails = (submission) => {
|
const handleViewDetails = (submission) => {
|
||||||
navigate('/overview', { state: { selectedSubmission: submission } });
|
navigate('/overview', { state: { selectedSubmission: submission } });
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleEdit = async (submission) => {
|
|
||||||
if (submission.status.toLowerCase() === 'draft') {
|
|
||||||
try {
|
|
||||||
const submissionData = await fetchSubmissionDetail(submission.id);
|
|
||||||
navigate('/survey', {
|
|
||||||
state: {
|
|
||||||
submission: submissionData,
|
|
||||||
isEdit: true,
|
|
||||||
fromDraft: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error fetching submission details:', error);
|
|
||||||
// Optionally show an error message to the user
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDeleteDraft = async (e, submission) => {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
try {
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error deleting submission:', error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const normalizedHistory = React.useMemo(() => {
|
const normalizedHistory = React.useMemo(() => {
|
||||||
if (!Array.isArray(history)) return [];
|
if (!Array.isArray(history)) return [];
|
||||||
return history.map((entry, index) => {
|
return history.map((entry, index) => {
|
||||||
@ -221,7 +186,6 @@ const handleDeleteDraft = async (e, submission) => {
|
|||||||
|
|
||||||
const tableRows = filtered.map((item) => {
|
const tableRows = filtered.map((item) => {
|
||||||
const productsLabel = `${item.products}`;
|
const productsLabel = `${item.products}`;
|
||||||
const isDraft = item.status.toLowerCase() === 'draft';
|
|
||||||
return [
|
return [
|
||||||
item.survey_name,
|
item.survey_name,
|
||||||
item.year,
|
item.year,
|
||||||
@ -229,47 +193,12 @@ const handleDeleteDraft = async (e, submission) => {
|
|||||||
getStatusBadge(item.status),
|
getStatusBadge(item.status),
|
||||||
<span className="whitespace-nowrap">{item.submission_on}</span>,
|
<span className="whitespace-nowrap">{item.submission_on}</span>,
|
||||||
productsLabel,
|
productsLabel,
|
||||||
<div className="flex items-center gap-2">
|
<button
|
||||||
{isDraft ? (
|
onClick={() => handleViewDetails(item)}
|
||||||
<>
|
className="text-[#9E792B] hover:text-[#7b5f22] font-medium"
|
||||||
<button
|
>
|
||||||
onClick={(e) => {
|
View Details
|
||||||
e.stopPropagation();
|
</button>,
|
||||||
handleEdit(item);
|
|
||||||
}}
|
|
||||||
className="p-1 focus:outline-none"
|
|
||||||
title="Edit Draft"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
src={pencilIconSrc}
|
|
||||||
alt="Edit"
|
|
||||||
className="h-5 w-5 opacity-60 hover:opacity-100 transition-opacity"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
onClick={(e) => handleDeleteDraft(e, item)}
|
|
||||||
onMouseEnter={() => setHoveredDelete(item.id)}
|
|
||||||
onMouseLeave={() => setHoveredDelete(null)}
|
|
||||||
className="p-1 focus:outline-none"
|
|
||||||
title="Delete Draft"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
src={hoveredDelete === item.id ? trashInactiveSrc : trashActiveSrc}
|
|
||||||
alt="Delete"
|
|
||||||
className="h-5 w-5 transition-opacity"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<button
|
|
||||||
onClick={() => handleViewDetails(item)}
|
|
||||||
className="text-[#9E792B] hover:text-[#7b5f22] font-medium"
|
|
||||||
>
|
|
||||||
View Details
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -175,65 +175,6 @@ const EstablishmentInfo = ({
|
|||||||
localStorage.setItem('surveyRemarks', remarksresubmit)
|
localStorage.setItem('surveyRemarks', remarksresubmit)
|
||||||
|
|
||||||
const [surveyData, setSurveyData] = React.useState(() => {
|
const [surveyData, setSurveyData] = React.useState(() => {
|
||||||
// For draft submission, use the data from the submission
|
|
||||||
|
|
||||||
if (location.state?.fromDraft && location.state?.submission) {
|
|
||||||
const submission = location.state.submission;
|
|
||||||
// Extract data from submission
|
|
||||||
const submissionData = submission.data || {};
|
|
||||||
const quarter = submissionData.quarter || '';
|
|
||||||
const year = submissionData.year || '';
|
|
||||||
const endDate = submission.quarter_window?.end_date || '';
|
|
||||||
|
|
||||||
// Extract establishment info
|
|
||||||
const establishmentData = submissionData.establishment || {};
|
|
||||||
|
|
||||||
// Extract employee data from establishment object
|
|
||||||
const employeeData = establishmentData.employee_info || establishmentData || {};
|
|
||||||
|
|
||||||
// Update the parent component with the submission data
|
|
||||||
onChange({
|
|
||||||
...data,
|
|
||||||
...submissionData,
|
|
||||||
establishmentId: establishmentData.id,
|
|
||||||
establishmentName: establishmentData.factory_name,
|
|
||||||
permanentFactoryCode: establishmentData.permanent_factory_code,
|
|
||||||
|
|
||||||
industryCode: establishmentData.industry_code,
|
|
||||||
licenseNumber: establishmentData.license_number,
|
|
||||||
isicCode: establishmentData.isic_code,
|
|
||||||
emirate: establishmentData.establishment_emirate_id,
|
|
||||||
establishment_contact_email: establishmentData.establishment_contact_email,
|
|
||||||
employeeInfo: {
|
|
||||||
...defaultEmployeeInfo,
|
|
||||||
emiratiMale: employeeData.emirati_male || '',
|
|
||||||
nonEmiratiMale: employeeData.non_emirati_male || '',
|
|
||||||
emiratiFemale: employeeData.emirati_female || '',
|
|
||||||
nonEmiratiFemale: employeeData.non_emirati_female || '',
|
|
||||||
totalEmployees: employeeData.total_employees || '',
|
|
||||||
totalEmirati: employeeData.total_emirati || ''
|
|
||||||
},
|
|
||||||
quarter,
|
|
||||||
year,
|
|
||||||
end_date: endDate
|
|
||||||
});
|
|
||||||
|
|
||||||
const surveyPeriod = {
|
|
||||||
quarter,
|
|
||||||
year,
|
|
||||||
endDate
|
|
||||||
};
|
|
||||||
|
|
||||||
localStorage.setItem('currentSurveyPeriod', JSON.stringify(surveyPeriod));
|
|
||||||
localStorage.setItem('currentQuarter', quarter);
|
|
||||||
localStorage.setItem('currentYear', year);
|
|
||||||
|
|
||||||
// Store the full submission data for reference
|
|
||||||
localStorage.setItem('currentSubmission', JSON.stringify(submissionData));
|
|
||||||
|
|
||||||
return surveyPeriod;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For resubmission, use the quarter/year from the submission data
|
// For resubmission, use the quarter/year from the submission data
|
||||||
if (location.state?.fromResubmit && data?.quarter && data?.year) {
|
if (location.state?.fromResubmit && data?.quarter && data?.year) {
|
||||||
const surveyPeriod = {
|
const surveyPeriod = {
|
||||||
@ -242,7 +183,7 @@ const EstablishmentInfo = ({
|
|||||||
endDate: data.end_date || ''
|
endDate: data.end_date || ''
|
||||||
};
|
};
|
||||||
localStorage.setItem('currentSurveyPeriod', JSON.stringify(surveyPeriod));
|
localStorage.setItem('currentSurveyPeriod', JSON.stringify(surveyPeriod));
|
||||||
localStorage.setItem('currentQuarter', data.quarter);
|
localStorage.setItem('currentQuarter', data.quarter); // Store quarter separately
|
||||||
localStorage.setItem('currentYear', data.year);
|
localStorage.setItem('currentYear', data.year);
|
||||||
return surveyPeriod;
|
return surveyPeriod;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { toast, ToastContainer } from 'react-toastify';
|
|
||||||
import 'react-toastify/dist/ReactToastify.css';
|
|
||||||
// import { useLocation } from 'react-router-dom';
|
// import { useLocation } from 'react-router-dom';
|
||||||
import { getQuarterPeriods, getPreviousForecastData, getEstablishmentProducts , submitSurvey,resubmitSurvey} from '@/services/submissions/submissionService';
|
import { getQuarterPeriods, getPreviousForecastData, getEstablishmentProducts } from '@/services/submissions/submissionService';
|
||||||
import {
|
import {
|
||||||
fetchVariationReasons,
|
fetchVariationReasons,
|
||||||
fetchZeroTargetReasons,
|
fetchZeroTargetReasons,
|
||||||
@ -304,17 +302,6 @@ const Select = ({
|
|||||||
<img src={caretDownSrc} alt="open" className="h-4 w-4" />
|
<img src={caretDownSrc} alt="open" className="h-4 w-4" />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<ToastContainer
|
|
||||||
position="top-right"
|
|
||||||
autoClose={3000}
|
|
||||||
hideProgressBar={false}
|
|
||||||
newestOnTop={false}
|
|
||||||
closeOnClick
|
|
||||||
rtl={false}
|
|
||||||
pauseOnFocusLoss
|
|
||||||
draggable
|
|
||||||
pauseOnHover
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -391,10 +378,6 @@ const ProductData = ({
|
|||||||
const [unitOptions, setUnitOptions] = React.useState([]);
|
const [unitOptions, setUnitOptions] = React.useState([]);
|
||||||
const [isLoadingUnits, setIsLoadingUnits] = React.useState(false);
|
const [isLoadingUnits, setIsLoadingUnits] = React.useState(false);
|
||||||
const [unitsError, setUnitsError] = React.useState(null);
|
const [unitsError, setUnitsError] = React.useState(null);
|
||||||
const [isSavingDraft, setIsSavingDraft] = React.useState(false);
|
|
||||||
|
|
||||||
|
|
||||||
const location = useLocation(); // Add this line
|
|
||||||
|
|
||||||
// Debug: Log products data when it changes
|
// Debug: Log products data when it changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -471,256 +454,6 @@ const ProductData = ({
|
|||||||
fetchQuarterPeriods();
|
fetchQuarterPeriods();
|
||||||
}, [quarter, year]);
|
}, [quarter, year]);
|
||||||
|
|
||||||
const handleSaveDraft = async () => {
|
|
||||||
try {
|
|
||||||
setIsSavingDraft(true);
|
|
||||||
|
|
||||||
// Get current submission from localStorage
|
|
||||||
const currentSubmissionStr = localStorage.getItem('currentSubmission');
|
|
||||||
if (!currentSubmissionStr) {
|
|
||||||
throw new Error('Current submission data not found');
|
|
||||||
}
|
|
||||||
const currentSubmission = JSON.parse(currentSubmissionStr);
|
|
||||||
const currentQuarter = localStorage.getItem('currentQuarter');
|
|
||||||
const currentYear = localStorage.getItem('currentYear')
|
|
||||||
// Get establishment ID from current submission
|
|
||||||
const submissionId = currentSubmission.id; // Changed this line to get ID from currentSubmission
|
|
||||||
|
|
||||||
const establishmentId = currentSubmission.establishment_id;
|
|
||||||
if (!establishmentId) {
|
|
||||||
throw new Error('Establishment ID not found in submission');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get user profile from localStorage
|
|
||||||
const userProfileStr = localStorage.getItem('user_profile');
|
|
||||||
if (!userProfileStr) {
|
|
||||||
throw new Error('User profile not found');
|
|
||||||
}
|
|
||||||
const userProfile = JSON.parse(userProfileStr);
|
|
||||||
const createdById = userProfile?.id;
|
|
||||||
if (!createdById) {
|
|
||||||
throw new Error('User ID not found in profile');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get quarter and year from current submission
|
|
||||||
const effectiveQuarter = currentQuarter;
|
|
||||||
const effectiveYear = currentYear;
|
|
||||||
if (!effectiveQuarter || !effectiveYear) {
|
|
||||||
throw new Error('Quarter and year are required in submission');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get establishment data
|
|
||||||
const establishment = currentSubmission.establishment;
|
|
||||||
if (!establishment) {
|
|
||||||
throw new Error('Establishment data not found in submission');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare products data in the required format
|
|
||||||
const formattedProducts = products.map(product => {
|
|
||||||
// Get the selected product option to access product_id
|
|
||||||
const selectedProduct = productOptions.find(p => p.value === product.product);
|
|
||||||
const existingProduct = currentSubmission.products?.find(p =>
|
|
||||||
p.product_id === product.product_id ||
|
|
||||||
p.product?.id === product.product_id
|
|
||||||
);
|
|
||||||
return {
|
|
||||||
id: existingProduct?.id || 0,
|
|
||||||
product_id: selectedProduct?.product_id || product.product_id || null,
|
|
||||||
unit_id: product.unit?.toString() || '', // Ensure unit_id is a string
|
|
||||||
annual_installed_capacity: product.capacity || '0',
|
|
||||||
previous_quantity_period_one: product.octQuantity || '0',
|
|
||||||
previous_quantity_period_two: product.novQuantity || '0',
|
|
||||||
previous_quantity_period_three: product.decQuantity || '0',
|
|
||||||
previous_cost_period_one: product.octCost || '0',
|
|
||||||
previous_cost_period_two: product.novCost || '0',
|
|
||||||
previous_cost_period_three: product.decCost || '0',
|
|
||||||
current_quantity_period_one: product.janQuantity || '0',
|
|
||||||
current_quantity_period_two: product.febQuantity || '0',
|
|
||||||
current_quantity_period_three: product.marQuantity || '0',
|
|
||||||
current_cost_period_one: product.janCost || '0',
|
|
||||||
current_cost_period_two: product.febCost || '0',
|
|
||||||
current_cost_period_three: product.marCost || '0',
|
|
||||||
forecast_quantity_period_one: product.aprQuantity || '0',
|
|
||||||
forecast_quantity_period_two: product.mayQuantity || '0',
|
|
||||||
forecast_quantity_period_three: product.junQuantity || '0',
|
|
||||||
forecast_cost_period_one: product.aprCost || '0',
|
|
||||||
forecast_cost_period_two: product.mayCost || '0',
|
|
||||||
forecast_cost_period_three: product.junCost || '0',
|
|
||||||
// Previous quarter (Q4) - October
|
|
||||||
previous_quantity: product.octQuantity || '0',
|
|
||||||
previous_cost: product.octCost || '0',
|
|
||||||
// Current quarter (Q1) - Using November as current (as per previous implementation)
|
|
||||||
// If you want to use a different field for current, replace novQuantity/novCost with the appropriate field
|
|
||||||
current_quantity: product.novQuantity || '0',
|
|
||||||
current_cost: product.novCost || '0',
|
|
||||||
// Next quarter forecast (Q2) - December
|
|
||||||
forecast_quantity: product.decQuantity || '0',
|
|
||||||
forecast_cost: product.decCost || '0',
|
|
||||||
variation_reason_master_id: product.variationReason || '',
|
|
||||||
other_variation_reason: product.otherVariationReason || '',
|
|
||||||
zero_target_reason_master_id: product.zeroTargetReason || '',
|
|
||||||
other_zero_target_reason: product.otherZeroTargetReason || '',
|
|
||||||
remarks: product.remarks || remarks || '' // Use product.remarks if available, otherwise use the component's remarks state
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
// Prepare the complete payload with values from currentSubmission
|
|
||||||
const payload = {
|
|
||||||
establishment_id: establishmentId,
|
|
||||||
quarter: effectiveQuarter,
|
|
||||||
year: effectiveYear,
|
|
||||||
emirati_male: establishment.emirati_male || 0,
|
|
||||||
emirati_female: establishment.emirati_female || 0,
|
|
||||||
non_emirati_male: establishment.non_emirati_male || 0,
|
|
||||||
non_emirati_female: establishment.non_emirati_female || 0,
|
|
||||||
total_emirati: establishment.total_emirati || 0,
|
|
||||||
total_employees: establishment.total_employees || 0,
|
|
||||||
status: "Draft",
|
|
||||||
created_by: createdById,
|
|
||||||
products: formattedProducts
|
|
||||||
};
|
|
||||||
|
|
||||||
// Example: const response = await api.saveDraft(payload);
|
|
||||||
let response;
|
|
||||||
if (submissionId) {
|
|
||||||
// Update existing submission
|
|
||||||
response = await resubmitSurvey(submissionId, payload);
|
|
||||||
toast.success('Draft updated successfully', {
|
|
||||||
position: "top-right",
|
|
||||||
autoClose: 3000,
|
|
||||||
hideProgressBar: false,
|
|
||||||
closeOnClick: true,
|
|
||||||
pauseOnHover: true,
|
|
||||||
draggable: true
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Create new submission
|
|
||||||
response = await submitSurvey(payload);
|
|
||||||
|
|
||||||
// Update local storage with the new submission ID if this was a create operation
|
|
||||||
if (response && response.id) {
|
|
||||||
const updatedSubmission = { ...currentSubmission, id: response.id };
|
|
||||||
localStorage.setItem('currentSubmission', JSON.stringify(updatedSubmission));
|
|
||||||
}
|
|
||||||
|
|
||||||
toast.success('Draft saved successfully', {
|
|
||||||
position: "top-right",
|
|
||||||
autoClose: 3000,
|
|
||||||
hideProgressBar: false,
|
|
||||||
closeOnClick: true,
|
|
||||||
pauseOnHover: true,
|
|
||||||
draggable: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error saving draft:', error);
|
|
||||||
toast.error(error.message || 'Failed to save draft');
|
|
||||||
} finally {
|
|
||||||
setIsSavingDraft(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Add this useEffect hook after the existing hooks
|
|
||||||
useEffect(() => {
|
|
||||||
const loadDraftData = () => {
|
|
||||||
try {
|
|
||||||
const isEditMode = location.state?.isEdit || false;
|
|
||||||
|
|
||||||
// Clear existing data if not in edit mode
|
|
||||||
if (!isEditMode) {
|
|
||||||
onProductsChange([{ id: Date.now() }]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentSubmissionStr = localStorage.getItem('currentSubmission');
|
|
||||||
if (!currentSubmissionStr) return;
|
|
||||||
|
|
||||||
const currentSubmission = JSON.parse(currentSubmissionStr);
|
|
||||||
|
|
||||||
if (currentSubmission.status === 'Draft' && currentSubmission.products && currentSubmission.products.length > 0) {
|
|
||||||
const formattedProducts = currentSubmission.products.map(product => {
|
|
||||||
// Get product name and HS code from the nested product object
|
|
||||||
const productName = product.product?.product_name || '';
|
|
||||||
const hsCode = product.product?.hs_code || '';
|
|
||||||
const displayName = productName ? `${hsCode} - ${productName}` : '';
|
|
||||||
return {
|
|
||||||
id: product.id,
|
|
||||||
product_id: product.product_id,
|
|
||||||
product: product.product_id?.toString() || '', // This should be the ID as string
|
|
||||||
productId: product.product_id?.toString() || '', // Also include as productId
|
|
||||||
name: displayName, // This will be used in displayValue
|
|
||||||
product_name: product.product?.product_name || '', // Raw name if needed
|
|
||||||
hs_code: hsCode, // Include HS code separately
|
|
||||||
productName: productName, // Include product name separately
|
|
||||||
product_value: product.product_id?.toString() || '',
|
|
||||||
unit: product.unit_id ? product.unit_id.toString() : '',
|
|
||||||
unit_name: product.unit?.uom || '', // Add unit name for display
|
|
||||||
capacity: product.annual_installed_capacity || '0',
|
|
||||||
|
|
||||||
// Previous quarter (Q4) - October, November, December
|
|
||||||
octQuantity: product.previous_quantity_period_one || '0',
|
|
||||||
octCost: product.previous_cost_period_one || '0',
|
|
||||||
novQuantity: product.previous_quantity_period_two || '0',
|
|
||||||
novCost: product.previous_cost_period_two || '0',
|
|
||||||
decQuantity: product.previous_quantity_period_three || '0',
|
|
||||||
decCost: product.previous_cost_period_three || '0',
|
|
||||||
|
|
||||||
// Current quarter (Q1) - January, February, March
|
|
||||||
janQuantity: product.current_quantity_period_one || '0',
|
|
||||||
janCost: product.current_cost_period_one || '0',
|
|
||||||
febQuantity: product.current_quantity_period_two || '0',
|
|
||||||
febCost: product.current_cost_period_two || '0',
|
|
||||||
marQuantity: product.current_quantity_period_three || '0',
|
|
||||||
marCost: product.current_cost_period_three || '0',
|
|
||||||
|
|
||||||
// Forecast quarter (Q2) - April, May, June
|
|
||||||
aprQuantity: product.forecast_quantity_period_one || '0',
|
|
||||||
aprCost: product.forecast_cost_period_one || '0',
|
|
||||||
mayQuantity: product.forecast_quantity_period_two || '0',
|
|
||||||
mayCost: product.forecast_cost_period_two || '0',
|
|
||||||
junQuantity: product.forecast_quantity_period_three || '0',
|
|
||||||
junCost: product.forecast_cost_period_three || '0',
|
|
||||||
|
|
||||||
// Variation reasons
|
|
||||||
variationReason: product.variation_reason_master_id?.toString() || '',
|
|
||||||
otherVariationReason: product.other_variation_reason || '',
|
|
||||||
zeroTargetReason: product.zero_target_reason_master_id?.toString() || '',
|
|
||||||
otherZeroTargetReason: product.other_zero_target_reason || '',
|
|
||||||
remarks: product.remarks || ''
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
onProductsChange(formattedProducts);
|
|
||||||
setSelectedProductIds(formattedProducts.map(p => p.product_id));
|
|
||||||
|
|
||||||
// Set remarks if available
|
|
||||||
if (currentSubmission.products[0]?.remarks) {
|
|
||||||
setRemarks(currentSubmission.products[0].remarks);
|
|
||||||
if (typeof window !== 'undefined') {
|
|
||||||
localStorage.setItem('surveyRemarks', currentSubmission.products[0].remarks);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set quarter and year in localStorage if not already set
|
|
||||||
if (currentSubmission.quarter && currentSubmission.year) {
|
|
||||||
localStorage.setItem('currentQuarter', currentSubmission.quarter);
|
|
||||||
localStorage.setItem('currentYear', currentSubmission.year.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error loading draft data:', error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (isInitialLoad) {
|
|
||||||
loadDraftData();
|
|
||||||
setIsInitialLoad(false);
|
|
||||||
}
|
|
||||||
}, [isInitialLoad, onProductsChange, location.state]);
|
|
||||||
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const variationController = new AbortController();
|
const variationController = new AbortController();
|
||||||
const zeroController = new AbortController();
|
const zeroController = new AbortController();
|
||||||
@ -883,7 +616,7 @@ useEffect(() => {
|
|||||||
endDate: ''
|
endDate: ''
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// const location = useLocation();
|
const location = useLocation();
|
||||||
|
|
||||||
// Update surveyData when props or location changes
|
// Update surveyData when props or location changes
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
@ -1462,7 +1195,7 @@ useEffect(() => {
|
|||||||
<div className="flex items-center space-x-1">
|
<div className="flex items-center space-x-1">
|
||||||
<img src={calendarIcon} alt="" className="h-4 w-4" />
|
<img src={calendarIcon} alt="" className="h-4 w-4" />
|
||||||
<span className="font-medium">Due:</span>
|
<span className="font-medium">Due:</span>
|
||||||
<span className="text-sm text-[#6C4527] whitespace-nowrap">
|
<span className="text-sm text-[#6C4527] whitespace-nowrap">
|
||||||
{surveyData.endDate ? (
|
{surveyData.endDate ? (
|
||||||
new Date(surveyData.endDate).toLocaleDateString('en-US', {
|
new Date(surveyData.endDate).toLocaleDateString('en-US', {
|
||||||
year: 'numeric',
|
year: 'numeric',
|
||||||
@ -2172,37 +1905,24 @@ useEffect(() => {
|
|||||||
|
|
||||||
|
|
||||||
<div className="flex flex-col sm:flex-row justify-between gap-5 mt-6">
|
<div className="flex flex-col sm:flex-row justify-between gap-5 mt-6">
|
||||||
<div className="flex-1">
|
<button
|
||||||
<button
|
onClick={onBack}
|
||||||
onClick={onBack}
|
className="inline-flex items-center gap-2 h-9 px-4 rounded-md border border-[#92722A] text-[#92722A] bg-transparent hover:bg-[#92722A]/10"
|
||||||
className="inline-flex items-center justify-center gap-2 h-9 px-4 rounded-md border border-[#92722A] text-[#92722A] bg-transparent hover:bg-[#92722A]/10"
|
>
|
||||||
>
|
<svg xmlns="http://www.w3.org/2000/svg" className="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
<path strokeLinecap="round" strokeLinejoin="round" d="M15 19l-7-7 7-7" />
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" d="M15 19l-7-7 7-7" />
|
</svg>
|
||||||
</svg>
|
<span>Back</span>
|
||||||
<span>Back</span>
|
</button>
|
||||||
</button>
|
<button
|
||||||
</div>
|
onClick={handleNext}
|
||||||
<div className="flex items-center gap-3">
|
className="inline-flex items-center gap-2 h-9 px-5 rounded-md bg-[#92722A] text-white hover:bg-[#7b5c1f] cursor-pointer"
|
||||||
<button
|
>
|
||||||
className="inline-flex items-center justify-center h-9 px-4 rounded-md border border-[#92722A] text-[#92722A] bg-transparent hover:bg-[#F5F0E1] transition-colors"
|
<span>Next</span>
|
||||||
onClick={handleSaveDraft}
|
<svg xmlns="http://www.w3.org/2000/svg" className="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
||||||
disabled={isSavingDraft}
|
<path strokeLinecap="round" strokeLinejoin="round" d="M9 5l7 7-7 7" />
|
||||||
>
|
</svg>
|
||||||
{/* <span>Save as Draft</span> */}
|
</button>
|
||||||
{isSavingDraft ? 'Saving...' : 'Save as Draft'}
|
|
||||||
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
onClick={handleNext}
|
|
||||||
className="inline-flex items-center gap-2 h-9 px-5 rounded-md bg-[#92722A] text-white hover:bg-[#7b5c1f] cursor-pointer"
|
|
||||||
>
|
|
||||||
<span>Next</span>
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" d="M9 5l7 7-7 7" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{(hasError || isInitialLoad) && (
|
{(hasError || isInitialLoad) && (
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import Table from '@/components/common/Table';
|
import Table from '@/components/common/Table';
|
||||||
import { getQuarterPeriods , resubmitSurvey } from '@/services/submissions/submissionService';
|
import { getQuarterPeriods } from '@/services/submissions/submissionService';
|
||||||
import { getEmirates, fetchVariationReasons, fetchZeroTargetReasons } from '@/services/masters/masterService';
|
import { getEmirates, fetchVariationReasons, fetchZeroTargetReasons } from '@/services/masters/masterService';
|
||||||
const caretUpSrc = '/assets/images/caret-up.svg';
|
const caretUpSrc = '/assets/images/caret-up.svg';
|
||||||
const caretDownSrc = '/assets/images/CaretDown-black.svg';
|
const caretDownSrc = '/assets/images/CaretDown-black.svg';
|
||||||
@ -360,9 +360,7 @@ const ReviewSubmit = ({
|
|||||||
const [emirateName, setEmirateName] = useState('');
|
const [emirateName, setEmirateName] = useState('');
|
||||||
const [variationReasons, setVariationReasons] = useState([]);
|
const [variationReasons, setVariationReasons] = useState([]);
|
||||||
const [zeroTargetReasons, setZeroTargetReasons] = useState([]);
|
const [zeroTargetReasons, setZeroTargetReasons] = useState([]);
|
||||||
const [isSavingDraft, setIsSavingDraft] = React.useState(false);
|
|
||||||
const [productOptions, setProductOptions] = React.useState([]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchEmiratesData = async () => {
|
const fetchEmiratesData = async () => {
|
||||||
try {
|
try {
|
||||||
@ -445,193 +443,6 @@ const ReviewSubmit = ({
|
|||||||
return '';
|
return '';
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleSaveDraft = async () => {
|
|
||||||
try {
|
|
||||||
setIsSavingDraft(true);
|
|
||||||
|
|
||||||
// Get current submission from localStorage
|
|
||||||
const currentSubmissionStr = localStorage.getItem('currentSubmission');
|
|
||||||
if (!currentSubmissionStr) {
|
|
||||||
throw new Error('Current submission data not found');
|
|
||||||
}
|
|
||||||
const currentSubmission = JSON.parse(currentSubmissionStr);
|
|
||||||
const currentQuarter = localStorage.getItem('currentQuarter');
|
|
||||||
const currentYear = localStorage.getItem('currentYear');
|
|
||||||
|
|
||||||
// Get establishment ID from current submission
|
|
||||||
const submissionId = currentSubmission.id;
|
|
||||||
const establishmentId = currentSubmission.establishment_id;
|
|
||||||
|
|
||||||
if (!establishmentId) {
|
|
||||||
throw new Error('Establishment ID not found in submission');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get user profile from localStorage
|
|
||||||
const userProfileStr = localStorage.getItem('user_profile');
|
|
||||||
if (!userProfileStr) {
|
|
||||||
throw new Error('User profile not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
const userProfile = JSON.parse(userProfileStr);
|
|
||||||
const createdById = userProfile?.id;
|
|
||||||
|
|
||||||
if (!createdById) {
|
|
||||||
throw new Error('User ID not found in profile');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get quarter and year from current submission
|
|
||||||
const effectiveQuarter = currentQuarter;
|
|
||||||
const effectiveYear = currentYear;
|
|
||||||
|
|
||||||
if (!effectiveQuarter || !effectiveYear) {
|
|
||||||
throw new Error('Quarter and year are required in submission');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get establishment data
|
|
||||||
const establishment = currentSubmission.establishment;
|
|
||||||
if (!establishment) {
|
|
||||||
throw new Error('Establishment data not found in submission');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare products data
|
|
||||||
const formattedProducts = products.map(product => ({
|
|
||||||
id: product.id || 0,
|
|
||||||
product_id: product.product_id || null,
|
|
||||||
unit_id: product.unit || '',
|
|
||||||
annual_installed_capacity: product.capacity || '0',
|
|
||||||
previous_quantity_period_one: product.octQuantity || '0',
|
|
||||||
previous_quantity_period_two: product.novQuantity || '0',
|
|
||||||
previous_quantity_period_three: product.decQuantity || '0',
|
|
||||||
previous_cost_period_one: product.octCost || '0',
|
|
||||||
previous_cost_period_two: product.novCost || '0',
|
|
||||||
previous_cost_period_three: product.decCost || '0',
|
|
||||||
current_quantity_period_one: product.janQuantity || '0',
|
|
||||||
current_quantity_period_two: product.febQuantity || '0',
|
|
||||||
current_quantity_period_three: product.marQuantity || '0',
|
|
||||||
current_cost_period_one: product.janCost || '0',
|
|
||||||
current_cost_period_two: product.febCost || '0',
|
|
||||||
current_cost_period_three: product.marCost || '0',
|
|
||||||
forecast_quantity_period_one: product.aprQuantity || '0',
|
|
||||||
forecast_quantity_period_two: product.mayQuantity || '0',
|
|
||||||
forecast_quantity_period_three: product.junQuantity || '0',
|
|
||||||
forecast_cost_period_one: product.aprCost || '0',
|
|
||||||
forecast_cost_period_two: product.mayCost || '0',
|
|
||||||
forecast_cost_period_three: product.junCost || '0',
|
|
||||||
variation_reason_master_id: product.variationReason || null,
|
|
||||||
other_variation_reason: product.otherVariationReason || '',
|
|
||||||
zero_target_reason_master_id: product.zeroTargetReason || null,
|
|
||||||
other_zero_target_reason: product.otherZeroTargetReason || '',
|
|
||||||
remarks: product.remarks || ''
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Prepare the complete payload
|
|
||||||
const payload = {
|
|
||||||
establishment_id: establishmentId,
|
|
||||||
quarter: effectiveQuarter,
|
|
||||||
year: effectiveYear,
|
|
||||||
emirati_male: establishment.emirati_male || 0,
|
|
||||||
emirati_female: establishment.emirati_female || 0,
|
|
||||||
non_emirati_male: establishment.non_emirati_male || 0,
|
|
||||||
non_emirati_female: establishment.non_emirati_female || 0,
|
|
||||||
total_emirati: establishment.total_emirati || 0,
|
|
||||||
total_employees: establishment.total_employees || 0,
|
|
||||||
status: "Draft",
|
|
||||||
created_by: createdById,
|
|
||||||
products: formattedProducts
|
|
||||||
};
|
|
||||||
let response;
|
|
||||||
try {
|
|
||||||
if (submissionId) {
|
|
||||||
// Update existing submission
|
|
||||||
response = await resubmitSurvey(submissionId, payload);
|
|
||||||
// Handle different response formats
|
|
||||||
const responseData = response?.data || response;
|
|
||||||
|
|
||||||
if (responseData) {
|
|
||||||
// Update local storage with the updated submission
|
|
||||||
const updatedSubmission = {
|
|
||||||
...currentSubmission,
|
|
||||||
...responseData,
|
|
||||||
updated_at: new Date().toISOString()
|
|
||||||
};
|
|
||||||
localStorage.setItem('currentSubmission', JSON.stringify(updatedSubmission));
|
|
||||||
|
|
||||||
toast.success('Draft updated successfully', {
|
|
||||||
position: "top-right",
|
|
||||||
autoClose: 3000,
|
|
||||||
hideProgressBar: false,
|
|
||||||
closeOnClick: true,
|
|
||||||
pauseOnHover: true,
|
|
||||||
draggable: true
|
|
||||||
});
|
|
||||||
return; // Success, exit the function
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Create new submission
|
|
||||||
response = await submitSurvey(payload);
|
|
||||||
// Handle different response formats
|
|
||||||
const responseData = response?.data || response;
|
|
||||||
|
|
||||||
if (responseData && (responseData.id || responseData.submission_id)) {
|
|
||||||
// Update local storage with the new submission ID
|
|
||||||
const updatedSubmission = {
|
|
||||||
...currentSubmission,
|
|
||||||
id: responseData.id || responseData.submission_id,
|
|
||||||
status: 'Draft',
|
|
||||||
created_at: new Date().toISOString()
|
|
||||||
};
|
|
||||||
localStorage.setItem('currentSubmission', JSON.stringify(updatedSubmission));
|
|
||||||
|
|
||||||
toast.success('Draft saved successfully', {
|
|
||||||
position: "top-right",
|
|
||||||
autoClose: 3000,
|
|
||||||
hideProgressBar: false,
|
|
||||||
closeOnClick: true,
|
|
||||||
pauseOnHover: true,
|
|
||||||
draggable: true
|
|
||||||
});
|
|
||||||
return; // Success, exit the function
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we get here, the response wasn't in the expected format
|
|
||||||
throw new Error('Unexpected response format from server');
|
|
||||||
|
|
||||||
} catch (apiError) {
|
|
||||||
console.error('API Error details:', {
|
|
||||||
message: apiError.message,
|
|
||||||
response: apiError.response,
|
|
||||||
stack: apiError.stack
|
|
||||||
});
|
|
||||||
|
|
||||||
// If we have a response with error details, use that
|
|
||||||
if (apiError.response?.data) {
|
|
||||||
const errorMessage = apiError.response.data.message || apiError.response.data.error || 'Unknown server error';
|
|
||||||
throw new Error(`Server error: ${errorMessage}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, rethrow the original error
|
|
||||||
throw apiError;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error in handleSaveDraft:', {
|
|
||||||
name: error.name,
|
|
||||||
message: error.message,
|
|
||||||
stack: error.stack
|
|
||||||
});
|
|
||||||
|
|
||||||
toast.error(error.message || 'Failed to save draft. Please try again.', {
|
|
||||||
position: "top-right",
|
|
||||||
autoClose: 5000,
|
|
||||||
hideProgressBar: false,
|
|
||||||
closeOnClick: true,
|
|
||||||
pauseOnHover: true,
|
|
||||||
draggable: true
|
|
||||||
});
|
|
||||||
} finally {
|
|
||||||
setIsSavingDraft(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const handleSubmit = () => {
|
const handleSubmit = () => {
|
||||||
try {
|
try {
|
||||||
const submissionData = formatSubmissionData(
|
const submissionData = formatSubmissionData(
|
||||||
@ -1231,16 +1042,6 @@ const ReviewSubmit = ({
|
|||||||
<img src={caretDownSrc} alt="" className="h-4 w-4 rotate-90" />
|
<img src={caretDownSrc} alt="" className="h-4 w-4 rotate-90" />
|
||||||
<span>Back</span>
|
<span>Back</span>
|
||||||
</button>
|
</button>
|
||||||
<div className="flex gap-4">
|
|
||||||
<button
|
|
||||||
className="inline-flex items-center justify-center h-9 px-4 rounded-md border border-[#92722A] text-[#92722A] bg-transparent hover:bg-[#F5F0E1] transition-colors"
|
|
||||||
onClick={handleSaveDraft}
|
|
||||||
disabled={isSavingDraft}
|
|
||||||
>
|
|
||||||
{/* <span>Save as Draft</span> */}
|
|
||||||
{isSavingDraft ? 'Saving...' : 'Save as Draft'}
|
|
||||||
|
|
||||||
</button>
|
|
||||||
<button
|
<button
|
||||||
disabled={!confirm || isSubmitting}
|
disabled={!confirm || isSubmitting}
|
||||||
onClick={onSubmit}
|
onClick={onSubmit}
|
||||||
@ -1254,7 +1055,6 @@ const ReviewSubmit = ({
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,18 +1,13 @@
|
|||||||
// src/pages/Overview/Overview.jsx
|
// src/pages/Overview/Overview.jsx
|
||||||
import React, { useState, useEffect, useMemo } from 'react';
|
import React, { useState, useEffect, useMemo } from 'react';
|
||||||
import { useNavigate, useLocation } from 'react-router-dom';
|
import { useNavigate, useLocation } from 'react-router-dom';
|
||||||
import { getSubmissions, getSubmissionHistoryByEstablishment, fetchSubmissionDetail } from '@/services/submissions/submissionService';
|
import { getSubmissions, getSubmissionHistoryByEstablishment } from '@/services/submissions/submissionService';
|
||||||
import HeaderBar from '@/components/layout/HeaderBar';
|
import HeaderBar from '@/components/layout/HeaderBar';
|
||||||
import Table from '@/components/common/Table';
|
import Table from '@/components/common/Table';
|
||||||
import DetailedOverview from '@/components/overview/DetailedOverview';
|
import DetailedOverview from '@/components/overview/DetailedOverview';
|
||||||
const searchIconSrc = '/assets/images/material-symbols_search-rounded.svg';
|
const searchIconSrc = '/assets/images/material-symbols_search-rounded.svg';
|
||||||
const caretDownSrc = '/assets/images/CaretDown.svg';
|
const caretDownSrc = '/assets/images/CaretDown.svg';
|
||||||
const downloadIconSrc = '/assets/images/DownloadSimple.svg';
|
const downloadIconSrc = '/assets/images/DownloadSimple.svg';
|
||||||
const pencilActiveSrc = '/assets/images/PencilSimple.svg';
|
|
||||||
const pencilInactiveSrc = '/assets/images/pencilsimple-inactive.svg';
|
|
||||||
// const deleteIconSrc = '/assets/images/delete.svg';
|
|
||||||
const deleteIconSrc = '/assets/images/Trash - active.svg';
|
|
||||||
const trashInactiveSrc = '/assets/images/Trash - Inactive.svg';
|
|
||||||
|
|
||||||
const statusStyles = {
|
const statusStyles = {
|
||||||
approved: 'text-[#2F663C] bg-[#F3FAF4]',
|
approved: 'text-[#2F663C] bg-[#F3FAF4]',
|
||||||
@ -51,18 +46,6 @@ const Overview = () => {
|
|||||||
setSelectedSubmission(location.state.selectedSubmission);
|
setSelectedSubmission(location.state.selectedSubmission);
|
||||||
}
|
}
|
||||||
}, [location.state]);
|
}, [location.state]);
|
||||||
const handleDeleteDraft = async (e, record) => {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
try {
|
|
||||||
// Add your delete logic here
|
|
||||||
// Example: await deleteSubmission(record.id);
|
|
||||||
// You might want to add a confirmation dialog before deleting
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error deleting submission:', error);
|
|
||||||
// Optionally show an error message to the user
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchSubmissions = async () => {
|
const fetchSubmissions = async () => {
|
||||||
@ -130,48 +113,9 @@ const Overview = () => {
|
|||||||
) : '-',
|
) : '-',
|
||||||
record.status,
|
record.status,
|
||||||
formatDate(record.created_at),
|
formatDate(record.created_at),
|
||||||
record.status === 'Draft' ? (
|
'View Details',
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<button
|
|
||||||
onClick={async (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
try {
|
|
||||||
const submissionData = await fetchSubmissionDetail(record.id);
|
|
||||||
navigate('/survey', {
|
|
||||||
state: {
|
|
||||||
submission: submissionData,
|
|
||||||
isEdit: true,
|
|
||||||
fromDraft: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error fetching submission details:', error);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
className="focus:outline-none"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
src={pencilActiveSrc}
|
|
||||||
alt="Edit"
|
|
||||||
className="h-5 w-5 opacity-60 hover:opacity-100 transition-opacity"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
onClick={(e) => handleDeleteDraft(e, record)}
|
|
||||||
className="focus:outline-none"
|
|
||||||
title="Delete Draft"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
src={deleteIconSrc}
|
|
||||||
alt="Delete"
|
|
||||||
className="h-5 w-5 opacity-60 hover:opacity-100 transition-opacity text-red-500"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
) : 'View Details',
|
|
||||||
]);
|
]);
|
||||||
}, [filteredRows, uae_currency]);
|
}, [filteredRows]);
|
||||||
|
|
||||||
const handlePageChange = (newPage) => {
|
const handlePageChange = (newPage) => {
|
||||||
setPagination(prev => ({
|
setPagination(prev => ({
|
||||||
|
|||||||
@ -799,114 +799,36 @@ const Survey = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// const handleFinalSubmit = async () => {
|
const handleFinalSubmit = async () => {
|
||||||
// if (isResubmit && submissionId) {
|
if (isResubmit && submissionId) {
|
||||||
// await handleResubmit();
|
await handleResubmit();
|
||||||
// return;
|
return;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// setIsSubmitting(true);
|
setIsSubmitting(true);
|
||||||
// setError('');
|
setError('');
|
||||||
|
|
||||||
// try {
|
try {
|
||||||
// const payload = buildSubmissionPayload();
|
const payload = buildSubmissionPayload();
|
||||||
// await submitSurvey(payload);
|
await submitSurvey(payload);
|
||||||
// setShowSuccessPopup(true);
|
setShowSuccessPopup(true);
|
||||||
// setHasSubmitted(true);
|
setHasSubmitted(true);
|
||||||
// showToast('success', 'Survey submitted successfully!');
|
showToast('success', 'Survey submitted successfully!');
|
||||||
// localStorage.removeItem('surveyRemarks');
|
localStorage.removeItem('surveyRemarks');
|
||||||
// // Clear the stored survey data after successful submission
|
// Clear the stored survey data after successful submission
|
||||||
// localStorage.removeItem('currentSurvey');
|
localStorage.removeItem('currentSurvey');
|
||||||
// // Remove currentSurveyPeriod from localStorage
|
// Remove currentSurveyPeriod from localStorage
|
||||||
// localStorage.removeItem('currentSurveyPeriod');
|
localStorage.removeItem('currentSurveyPeriod');
|
||||||
// } catch (error) {
|
} catch (error) {
|
||||||
// const message = error?.response?.data?.message || error?.message || 'Failed to submit survey. Please try again.';
|
const message = error?.response?.data?.message || error?.message || 'Failed to submit survey. Please try again.';
|
||||||
// console.error('Submission Error:', error);
|
console.error('Submission Error:', error);
|
||||||
// setError(message);
|
setError(message);
|
||||||
// showToast('error', message);
|
showToast('error', message);
|
||||||
// } finally {
|
} finally {
|
||||||
// setIsSubmitting(false);
|
setIsSubmitting(false);
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
const handleFinalSubmit = async () => {
|
|
||||||
if (isResubmit && submissionId) {
|
|
||||||
await handleResubmit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setIsSubmitting(true);
|
|
||||||
setError('');
|
|
||||||
|
|
||||||
try {
|
|
||||||
const payload = buildSubmissionPayload();
|
|
||||||
const currentSubmissionStr = localStorage.getItem('currentSubmission');
|
|
||||||
let submissionId = null;
|
|
||||||
let currentSubmission = null;
|
|
||||||
|
|
||||||
if (currentSubmissionStr) {
|
|
||||||
currentSubmission = JSON.parse(currentSubmissionStr);
|
|
||||||
submissionId = currentSubmission.id;
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (currentSubmission?.products?.length) {
|
|
||||||
payload.products = payload.products.map((product, index) => {
|
|
||||||
const existingProduct = currentSubmission.products[index];
|
|
||||||
return {
|
|
||||||
...product,
|
|
||||||
id: existingProduct?.id || 0, // Include existing product ID or 0 for new products
|
|
||||||
product_id: product.product_id || existingProduct?.product_id // Ensure product_id is included
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let response;
|
|
||||||
|
|
||||||
if (submissionId) {
|
|
||||||
// Update existing draft submission
|
|
||||||
response = await resubmitSurvey(submissionId, {
|
|
||||||
...payload,
|
|
||||||
status: 'Submitted'
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Create new submission
|
|
||||||
response = await submitSurvey({
|
|
||||||
...payload,
|
|
||||||
status: 'Submitted'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update local storage with the submitted submission and product IDs
|
|
||||||
if (response && (response.data || response.id)) {
|
|
||||||
const responseData = response.data || response;
|
|
||||||
const updatedSubmission = {
|
|
||||||
...(currentSubmission || {}),
|
|
||||||
id: responseData.id || responseData.submission_id,
|
|
||||||
status: 'Submitted',
|
|
||||||
submitted_at: new Date().toISOString()
|
|
||||||
};
|
|
||||||
|
|
||||||
// Update product IDs if they exist in the response
|
|
||||||
if (responseData.products && Array.isArray(responseData.products)) {
|
|
||||||
updatedSubmission.products = responseData.products.map((product, index) => ({
|
|
||||||
...(currentSubmission?.products?.[index] || {}), // Keep existing product data
|
|
||||||
id: product.id, // Update with new product ID from response
|
|
||||||
product_id: product.product_id // Ensure product_id is also updated
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
localStorage.setItem('currentSubmission', JSON.stringify(updatedSubmission));
|
|
||||||
}
|
|
||||||
|
|
||||||
setShowSuccessPopup(true);
|
|
||||||
setHasSubmitted(true);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error submitting survey:', error);
|
|
||||||
setError(error.message || 'Failed to submit survey. Please try again.');
|
|
||||||
} finally {
|
|
||||||
setIsSubmitting(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const StepBadge = ({ state, number }) => {
|
const StepBadge = ({ state, number }) => {
|
||||||
if (state === 'active') {
|
if (state === 'active') {
|
||||||
return (
|
return (
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user