Revert "Added save as draft flow"

This reverts commit 8f3234167a.
This commit is contained in:
Malini 2026-02-04 20:02:50 +05:30
parent 8f3234167a
commit 73fe26edc4
6 changed files with 60 additions and 804 deletions

View File

@ -6,10 +6,7 @@ import HeaderBar from '@/components/layout/HeaderBar';
import DetailedOverview from '@/components/overview/DetailedOverview';
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) => {
if (!value) return '—';
const date = new Date(value);
@ -141,45 +138,13 @@ export const SubmissionHistory = ({ history = [], loading = false, error = '' })
const [searchTerm, setSearchTerm] = React.useState('');
const [selectedSubmission, setSelectedSubmission] = React.useState(null);
const [currentPage, setCurrentPage] = React.useState(1);
const [hoveredDelete, setHoveredDelete] = React.useState(null);
const pageSize = 10;
const navigate = useNavigate();
const handleViewDetails = (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(() => {
if (!Array.isArray(history)) return [];
return history.map((entry, index) => {
@ -221,7 +186,6 @@ const handleDeleteDraft = async (e, submission) => {
const tableRows = filtered.map((item) => {
const productsLabel = `${item.products}`;
const isDraft = item.status.toLowerCase() === 'draft';
return [
item.survey_name,
item.year,
@ -229,47 +193,12 @@ const handleDeleteDraft = async (e, submission) => {
getStatusBadge(item.status),
<span className="whitespace-nowrap">{item.submission_on}</span>,
productsLabel,
<div className="flex items-center gap-2">
{isDraft ? (
<>
<button
onClick={(e) => {
e.stopPropagation();
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>
<button
onClick={() => handleViewDetails(item)}
className="text-[#9E792B] hover:text-[#7b5f22] font-medium"
>
View Details
</button>,
];
});

View File

@ -175,65 +175,6 @@ const EstablishmentInfo = ({
localStorage.setItem('surveyRemarks', remarksresubmit)
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
if (location.state?.fromResubmit && data?.quarter && data?.year) {
const surveyPeriod = {
@ -242,7 +183,7 @@ const EstablishmentInfo = ({
endDate: data.end_date || ''
};
localStorage.setItem('currentSurveyPeriod', JSON.stringify(surveyPeriod));
localStorage.setItem('currentQuarter', data.quarter);
localStorage.setItem('currentQuarter', data.quarter); // Store quarter separately
localStorage.setItem('currentYear', data.year);
return surveyPeriod;
}

View File

@ -1,8 +1,6 @@
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 { getQuarterPeriods, getPreviousForecastData, getEstablishmentProducts , submitSurvey,resubmitSurvey} from '@/services/submissions/submissionService';
import { getQuarterPeriods, getPreviousForecastData, getEstablishmentProducts } from '@/services/submissions/submissionService';
import {
fetchVariationReasons,
fetchZeroTargetReasons,
@ -304,17 +302,6 @@ const Select = ({
<img src={caretDownSrc} alt="open" className="h-4 w-4" />
)}
</div>
<ToastContainer
position="top-right"
autoClose={3000}
hideProgressBar={false}
newestOnTop={false}
closeOnClick
rtl={false}
pauseOnFocusLoss
draggable
pauseOnHover
/>
</div>
);
};
@ -391,10 +378,6 @@ const ProductData = ({
const [unitOptions, setUnitOptions] = React.useState([]);
const [isLoadingUnits, setIsLoadingUnits] = React.useState(false);
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
useEffect(() => {
@ -471,256 +454,6 @@ const ProductData = ({
fetchQuarterPeriods();
}, [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(() => {
const variationController = new AbortController();
const zeroController = new AbortController();
@ -883,7 +616,7 @@ useEffect(() => {
endDate: ''
}));
// const location = useLocation();
const location = useLocation();
// Update surveyData when props or location changes
React.useEffect(() => {
@ -1462,7 +1195,7 @@ useEffect(() => {
<div className="flex items-center space-x-1">
<img src={calendarIcon} alt="" className="h-4 w-4" />
<span className="font-medium">Due:</span>
<span className="text-sm text-[#6C4527] whitespace-nowrap">
<span className="text-sm text-[#6C4527] whitespace-nowrap">
{surveyData.endDate ? (
new Date(surveyData.endDate).toLocaleDateString('en-US', {
year: 'numeric',
@ -2172,37 +1905,24 @@ useEffect(() => {
<div className="flex flex-col sm:flex-row justify-between gap-5 mt-6">
<div className="flex-1">
<button
onClick={onBack}
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">
<path strokeLinecap="round" strokeLinejoin="round" d="M15 19l-7-7 7-7" />
</svg>
<span>Back</span>
</button>
</div>
<div className="flex items-center gap-3">
<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
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>
<button
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"
>
<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" />
</svg>
<span>Back</span>
</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>
{(hasError || isInitialLoad) && (

View File

@ -1,6 +1,6 @@
import React, { useState, useEffect } from 'react';
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';
const caretUpSrc = '/assets/images/caret-up.svg';
const caretDownSrc = '/assets/images/CaretDown-black.svg';
@ -360,9 +360,7 @@ const ReviewSubmit = ({
const [emirateName, setEmirateName] = useState('');
const [variationReasons, setVariationReasons] = useState([]);
const [zeroTargetReasons, setZeroTargetReasons] = useState([]);
const [isSavingDraft, setIsSavingDraft] = React.useState(false);
const [productOptions, setProductOptions] = React.useState([]);
useEffect(() => {
const fetchEmiratesData = async () => {
try {
@ -445,193 +443,6 @@ const ReviewSubmit = ({
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 = () => {
try {
const submissionData = formatSubmissionData(
@ -1231,16 +1042,6 @@ const ReviewSubmit = ({
<img src={caretDownSrc} alt="" className="h-4 w-4 rotate-90" />
<span>Back</span>
</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
disabled={!confirm || isSubmitting}
onClick={onSubmit}
@ -1254,7 +1055,6 @@ const ReviewSubmit = ({
</button>
</div>
</div>
</div>
</div>
</div>
);

View File

@ -1,18 +1,13 @@
// src/pages/Overview/Overview.jsx
import React, { useState, useEffect, useMemo } from 'react';
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 Table from '@/components/common/Table';
import DetailedOverview from '@/components/overview/DetailedOverview';
const searchIconSrc = '/assets/images/material-symbols_search-rounded.svg';
const caretDownSrc = '/assets/images/CaretDown.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 = {
approved: 'text-[#2F663C] bg-[#F3FAF4]',
@ -51,18 +46,6 @@ const Overview = () => {
setSelectedSubmission(location.state.selectedSubmission);
}
}, [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(() => {
const fetchSubmissions = async () => {
@ -130,48 +113,9 @@ const Overview = () => {
) : '-',
record.status,
formatDate(record.created_at),
record.status === 'Draft' ? (
<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',
'View Details',
]);
}, [filteredRows, uae_currency]);
}, [filteredRows]);
const handlePageChange = (newPage) => {
setPagination(prev => ({

View File

@ -799,114 +799,36 @@ const Survey = () => {
}
};
// const handleFinalSubmit = async () => {
// if (isResubmit && submissionId) {
// await handleResubmit();
// return;
// }
const handleFinalSubmit = async () => {
if (isResubmit && submissionId) {
await handleResubmit();
return;
}
// setIsSubmitting(true);
// setError('');
setIsSubmitting(true);
setError('');
// try {
// const payload = buildSubmissionPayload();
// await submitSurvey(payload);
// setShowSuccessPopup(true);
// setHasSubmitted(true);
// showToast('success', 'Survey submitted successfully!');
// localStorage.removeItem('surveyRemarks');
// // Clear the stored survey data after successful submission
// localStorage.removeItem('currentSurvey');
// // Remove currentSurveyPeriod from localStorage
// localStorage.removeItem('currentSurveyPeriod');
// } catch (error) {
// const message = error?.response?.data?.message || error?.message || 'Failed to submit survey. Please try again.';
// console.error('Submission Error:', error);
// setError(message);
// showToast('error', message);
// } finally {
// 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;
try {
const payload = buildSubmissionPayload();
await submitSurvey(payload);
setShowSuccessPopup(true);
setHasSubmitted(true);
showToast('success', 'Survey submitted successfully!');
localStorage.removeItem('surveyRemarks');
// Clear the stored survey data after successful submission
localStorage.removeItem('currentSurvey');
// Remove currentSurveyPeriod from localStorage
localStorage.removeItem('currentSurveyPeriod');
} catch (error) {
const message = error?.response?.data?.message || error?.message || 'Failed to submit survey. Please try again.';
console.error('Submission Error:', error);
setError(message);
showToast('error', message);
} finally {
setIsSubmitting(false);
}
};
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 }) => {
if (state === 'active') {
return (