bug fixed hscodes import
This commit is contained in:
parent
a09d2ab2fa
commit
022ca1d207
@ -27,8 +27,14 @@ const AdminDashboard = () => {
|
|||||||
grace_periods_days: 0
|
grace_periods_days: 0
|
||||||
});
|
});
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [selectedQuarter, setSelectedQuarter] = useState('All');
|
// Function to get current quarter (1-4)
|
||||||
const [selectedYear, setSelectedYear] = useState('All');
|
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 isMounted = useRef(false);
|
||||||
const prevParams = useRef({ quarter: null, year: null });
|
const prevParams = useRef({ quarter: null, year: null });
|
||||||
|
|
||||||
@ -119,7 +125,6 @@ const AdminDashboard = () => {
|
|||||||
onChange={(e) => setSelectedQuarter(e.target.value)}
|
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]"
|
className="border border-[#D0D5DD] rounded-md h-8 px-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#92722A]"
|
||||||
>
|
>
|
||||||
<option value="All">All</option>
|
|
||||||
<option value="Q1">Q1</option>
|
<option value="Q1">Q1</option>
|
||||||
<option value="Q2">Q2</option>
|
<option value="Q2">Q2</option>
|
||||||
<option value="Q3">Q3</option>
|
<option value="Q3">Q3</option>
|
||||||
@ -131,7 +136,6 @@ const AdminDashboard = () => {
|
|||||||
onChange={(e) => setSelectedYear(e.target.value)}
|
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]"
|
className="border border-[#D0D5DD] rounded-md h-8 px-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#92722A]"
|
||||||
>
|
>
|
||||||
<option value="All">All</option>
|
|
||||||
{Array.from(
|
{Array.from(
|
||||||
{ length: new Date().getFullYear() - 2021 },
|
{ length: new Date().getFullYear() - 2021 },
|
||||||
(_, i) => new Date().getFullYear() - i
|
(_, i) => new Date().getFullYear() - i
|
||||||
|
|||||||
@ -308,10 +308,10 @@ React.useEffect(() => {
|
|||||||
|
|
||||||
// First, get the current quarter and year
|
// First, get the current quarter and year
|
||||||
const response = await apiClient.get('/admin_dashboard');
|
const response = await apiClient.get('/admin_dashboard');
|
||||||
// const currentQuarter = response?.data?.selected_quarter || 'Q1';
|
const currentQuarter = response?.data?.selected_quarter || 'Q1';
|
||||||
const currentQuarter = 'All';
|
// const currentQuarter = 'All';
|
||||||
// const currentYear = response?.data?.selected_year || new Date().getFullYear().toString();
|
const currentYear = response?.data?.selected_year || new Date().getFullYear().toString();
|
||||||
const currentYear = 'All';
|
// const currentYear = 'All';
|
||||||
// Set the filter states
|
// Set the filter states
|
||||||
setSelectedQuarter(currentQuarter);
|
setSelectedQuarter(currentQuarter);
|
||||||
setSelectedYear(currentYear);
|
setSelectedYear(currentYear);
|
||||||
|
|||||||
@ -124,17 +124,43 @@ const ImportModal = ({ isOpen, onClose, onImport }) => {
|
|||||||
setLoading(true);
|
setLoading(true);
|
||||||
setError('');
|
setError('');
|
||||||
|
|
||||||
// Simulate file upload - replace with actual API call
|
// Call the uploadCSV API from productService
|
||||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
const response = await productService.uploadCSV(file);
|
||||||
|
|
||||||
// Call the onImport callback with the file
|
// Check the response status
|
||||||
await onImport(file);
|
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
|
// Reset and close on success
|
||||||
setFile(null);
|
setFile(null);
|
||||||
onClose();
|
onClose();
|
||||||
} catch (err) {
|
} 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 {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
@ -313,6 +339,7 @@ const IsicHsCodes = () => {
|
|||||||
const [unitOptions, setUnitOptions] = React.useState([]);
|
const [unitOptions, setUnitOptions] = React.useState([]);
|
||||||
const [toast, setToast] = React.useState({ show: false, message: '', type: 'success' });
|
const [toast, setToast] = React.useState({ show: false, message: '', type: 'success' });
|
||||||
const [showImportModal, setShowImportModal] = React.useState(false);
|
const [showImportModal, setShowImportModal] = React.useState(false);
|
||||||
|
const [isRefreshing, setIsRefreshing] = React.useState(false);
|
||||||
|
|
||||||
// Get user profile from session
|
// Get user profile from session
|
||||||
const userProfile = React.useMemo(() => {
|
const userProfile = React.useMemo(() => {
|
||||||
@ -756,16 +783,26 @@ const IsicHsCodes = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setIsLoading(true);
|
setError('');
|
||||||
setError(null);
|
|
||||||
|
|
||||||
|
// 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 = {
|
const productData = {
|
||||||
product_name: form.product,
|
|
||||||
is_active: form.status === 'Active',
|
|
||||||
hs_code: form.code,
|
hs_code: form.code,
|
||||||
|
product_name: form.product,
|
||||||
unit_id: form.unit ? parseInt(form.unit) : null,
|
unit_id: form.unit ? parseInt(form.unit) : null,
|
||||||
created_by: userProfile?.id || null,
|
is_active: form.status === 'Active',
|
||||||
...(form.description && { hs_description: form.description })
|
hs_description: form.description || '',
|
||||||
|
created_by: userProfile?.id || null
|
||||||
};
|
};
|
||||||
|
|
||||||
if (modalMode === 'edit' && editingRow !== 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 (
|
return (
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
{toast.show && (
|
{toast.show && (
|
||||||
@ -889,7 +996,7 @@ const IsicHsCodes = () => {
|
|||||||
<ImportModal
|
<ImportModal
|
||||||
isOpen={showImportModal}
|
isOpen={showImportModal}
|
||||||
onClose={() => setShowImportModal(false)}
|
onClose={() => setShowImportModal(false)}
|
||||||
onImport={handleImportCSV}
|
onImport={handleImportSuccess}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="bg-white w-full rounded-lg shadow-sm ring-1 ring-[#E5E7EB]">
|
<div className="bg-white w-full rounded-lg shadow-sm ring-1 ring-[#E5E7EB]">
|
||||||
|
|||||||
@ -77,6 +77,24 @@ export const productService = {
|
|||||||
throw enhancedError;
|
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;
|
export default productService;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user