diff --git a/ipi-survey-platform/src/pages/Admin/AdminDashboard.jsx b/ipi-survey-platform/src/pages/Admin/AdminDashboard.jsx index a7e54ef..e25786b 100644 --- a/ipi-survey-platform/src/pages/Admin/AdminDashboard.jsx +++ b/ipi-survey-platform/src/pages/Admin/AdminDashboard.jsx @@ -27,8 +27,14 @@ const AdminDashboard = () => { grace_periods_days: 0 }); const [loading, setLoading] = useState(true); - const [selectedQuarter, setSelectedQuarter] = useState('All'); - const [selectedYear, setSelectedYear] = useState('All'); + // Function to get current quarter (1-4) + const getCurrentQuarter = () => { + const month = new Date().getMonth(); + return `Q${Math.floor(month / 3) + 1}`; + }; + + const [selectedQuarter, setSelectedQuarter] = useState(getCurrentQuarter()); + const [selectedYear, setSelectedYear] = useState(new Date().getFullYear().toString()); const isMounted = useRef(false); const prevParams = useRef({ quarter: null, year: null }); @@ -119,7 +125,6 @@ const AdminDashboard = () => { onChange={(e) => setSelectedQuarter(e.target.value)} className="border border-[#D0D5DD] rounded-md h-8 px-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#92722A]" > - @@ -131,7 +136,6 @@ const AdminDashboard = () => { onChange={(e) => setSelectedYear(e.target.value)} className="border border-[#D0D5DD] rounded-md h-8 px-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#92722A]" > - {Array.from( { length: new Date().getFullYear() - 2021 }, (_, i) => new Date().getFullYear() - i diff --git a/ipi-survey-platform/src/pages/Admin/Validations.jsx b/ipi-survey-platform/src/pages/Admin/Validations.jsx index 761658b..ef70a2d 100644 --- a/ipi-survey-platform/src/pages/Admin/Validations.jsx +++ b/ipi-survey-platform/src/pages/Admin/Validations.jsx @@ -308,10 +308,10 @@ React.useEffect(() => { // First, get the current quarter and year const response = await apiClient.get('/admin_dashboard'); - // const currentQuarter = response?.data?.selected_quarter || 'Q1'; - const currentQuarter = 'All'; - // const currentYear = response?.data?.selected_year || new Date().getFullYear().toString(); - const currentYear = 'All'; + const currentQuarter = response?.data?.selected_quarter || 'Q1'; + // const currentQuarter = 'All'; + const currentYear = response?.data?.selected_year || new Date().getFullYear().toString(); + // const currentYear = 'All'; // Set the filter states setSelectedQuarter(currentQuarter); setSelectedYear(currentYear); diff --git a/ipi-survey-platform/src/pages/Admin/configuration/IsicHsCodes.jsx b/ipi-survey-platform/src/pages/Admin/configuration/IsicHsCodes.jsx index 64f8639..6a8c402 100644 --- a/ipi-survey-platform/src/pages/Admin/configuration/IsicHsCodes.jsx +++ b/ipi-survey-platform/src/pages/Admin/configuration/IsicHsCodes.jsx @@ -124,17 +124,43 @@ const ImportModal = ({ isOpen, onClose, onImport }) => { setLoading(true); setError(''); - // Simulate file upload - replace with actual API call - await new Promise(resolve => setTimeout(resolve, 2000)); + // Call the uploadCSV API from productService + const response = await productService.uploadCSV(file); - // Call the onImport callback with the file - await onImport(file); + // Check the response status + if (response.status === 'failed') { + let errorMsg = response.message || 'Import failed'; + + // Add duplicate HS codes to the error message if they exist + if (response.duplicate_hs_codes_in_system?.length > 0) { + errorMsg += `\nDuplicate HS codes found: ${response.duplicate_hs_codes_in_system.join(', ')}`; + } + + // Show error summary if available + if (response.summary) { + errorMsg += `\nTotal records: ${response.summary.total_records}`; + errorMsg += `\nImported: ${response.summary.imported}`; + errorMsg += `\nSkipped: ${response.summary.skipped}`; + + if (response.summary.errors?.length > 0) { + errorMsg += `\n\nErrors:\n${response.summary.errors.join('\n')}`; + } + } + + setError(errorMsg); + return; + } + + // Call the onImport callback with the response data + await onImport(response); // Reset and close on success setFile(null); onClose(); } catch (err) { - setError('Failed to import file. Please try again.'); + console.error('Error uploading CSV:', err); + const errorMessage = err.response?.data?.message || 'Failed to import file. Please try again.'; + setError(errorMessage); } finally { setLoading(false); } @@ -313,6 +339,7 @@ const IsicHsCodes = () => { const [unitOptions, setUnitOptions] = React.useState([]); const [toast, setToast] = React.useState({ show: false, message: '', type: 'success' }); const [showImportModal, setShowImportModal] = React.useState(false); + const [isRefreshing, setIsRefreshing] = React.useState(false); // Get user profile from session const userProfile = React.useMemo(() => { @@ -756,16 +783,26 @@ const IsicHsCodes = () => { } try { - setIsLoading(true); - setError(null); + setError(''); + // Get user profile from session storage for created_by + let userProfile = null; + try { + const userProfileStr = sessionStorage.getItem('user_profile'); + if (userProfileStr) { + userProfile = JSON.parse(userProfileStr); + } + } catch (error) { + console.error('Error getting user from session:', error); + } + const productData = { - product_name: form.product, - is_active: form.status === 'Active', hs_code: form.code, + product_name: form.product, unit_id: form.unit ? parseInt(form.unit) : null, - created_by: userProfile?.id || null, - ...(form.description && { hs_description: form.description }) + is_active: form.status === 'Active', + hs_description: form.description || '', + created_by: userProfile?.id || null }; if (modalMode === 'edit' && editingRow !== null) { @@ -875,6 +912,76 @@ const IsicHsCodes = () => { } }; + const handleImportSuccess = async () => { + try { + setIsRefreshing(true); + const response = await productService.getProducts(); + const products = Array.isArray(response?.data) ? response.data : response?.data?.data || []; + + // Get user profile from session storage for created_by + let createdByName = '-'; + try { + const userProfileStr = sessionStorage.getItem('user_profile'); + if (userProfileStr) { + const userProfile = JSON.parse(userProfileStr); + createdByName = userProfile.name || createdByName; + } + } catch (error) { + console.error('Error getting user from session:', error); + } + + if (products.length > 0) { + const formattedData = products.map((product) => { + const createdDate = product.created_at + ? new Date(product.created_at).toLocaleDateString('en-GB') + : '-'; + + const updatedDate = product.updated_at + ? new Date(product.updated_at).toLocaleDateString('en-GB') + : createdDate; + + // Use the product's created_by_user if available, otherwise fall back to current user + const creatorName = product.created_by_user?.name || + (product.created_by ? createdByName : '-'); + + return { + id: product.id, + code: product.hs_code || 'N/A', + product: product.product_name || 'N/A', + unit: product.unit?.uom || 'N/A', + estimatedMapped: 0, + createdBy: creatorName, + createdOn: createdDate, + updated: updatedDate, + status: product.is_active ? 'Active' : 'Inactive', + description: product.hs_description || '', + _createdAt: product.created_at, + _updatedAt: product.updated_at, + created_by: product.created_by || null + }; + }); + + setRowsData(formattedData); + setFilteredData(formattedData); + } + + setToast({ + show: true, + message: 'Data imported successfully!', + type: 'success' + }); + } catch (err) { + console.error('Error refreshing product list:', err); + setToast({ + show: true, + message: 'Data imported but failed to refresh the list. ' + (err.response?.data?.message || 'Please refresh the page manually.'), + type: 'error' + }); + } finally { + setIsRefreshing(false); + } +}; + return (
{toast.show && ( @@ -889,7 +996,7 @@ const IsicHsCodes = () => { setShowImportModal(false)} - onImport={handleImportCSV} + onImport={handleImportSuccess} />
diff --git a/ipi-survey-platform/src/services/configuration/productService.js b/ipi-survey-platform/src/services/configuration/productService.js index 9e0a27e..fc419e5 100644 --- a/ipi-survey-platform/src/services/configuration/productService.js +++ b/ipi-survey-platform/src/services/configuration/productService.js @@ -77,6 +77,24 @@ export const productService = { throw enhancedError; } }, +uploadCSV: async (file) => { + try { + const formData = new FormData(); + formData.append('file', file); + + const response = await postRequest('/products/uploadCSV', formData, { + headers: { + 'Content-Type': 'multipart/form-data' + } + }); + + // Return the full response data + return response.data; + } catch (error) { + console.error('Error in productService.uploadCSV:', error); + throw error; + } +} }; export default productService;