bug fixed in company profile
This commit is contained in:
parent
e1280c4568
commit
a09d2ab2fa
@ -13,11 +13,26 @@ const overviewIconInactiveSrc = '/assets/images/mdi_file-find-outline-active.svg
|
|||||||
|
|
||||||
const HeaderBar = () => {
|
const HeaderBar = () => {
|
||||||
const [open, setOpen] = React.useState(false);
|
const [open, setOpen] = React.useState(false);
|
||||||
const [userOpen, setUserOpen] = React.useState(false);
|
|
||||||
const [userName, setUserName] = React.useState('User');
|
const [userName, setUserName] = React.useState('User');
|
||||||
const [userEmail, setUserEmail] = React.useState('');
|
const [userEmail, setUserEmail] = React.useState('');
|
||||||
|
const [userOpen, setUserOpen] = React.useState(false);
|
||||||
|
const profileRef = React.useRef(null);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
// Close dropdown when clicking outside
|
||||||
|
React.useEffect(() => {
|
||||||
|
const handleClickOutside = (event) => {
|
||||||
|
if (profileRef.current && !profileRef.current.contains(event.target)) {
|
||||||
|
setUserOpen(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener('mousedown', handleClickOutside);
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener('mousedown', handleClickOutside);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
let parsed;
|
let parsed;
|
||||||
try {
|
try {
|
||||||
@ -127,32 +142,38 @@ const HeaderBar = () => {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</NavLink> */}
|
</NavLink> */}
|
||||||
<div className="relative">
|
<div className="relative" ref={profileRef}>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setUserOpen((v) => !v)}
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
setUserOpen((v) => !v);
|
||||||
|
}}
|
||||||
className="h-8 w-8 rounded-full bg-gray-200 grid place-items-center text-[12px] text-gray-700 cursor-pointer"
|
className="h-8 w-8 rounded-full bg-gray-200 grid place-items-center text-[12px] text-gray-700 cursor-pointer"
|
||||||
aria-label="Profile"
|
aria-label="Profile"
|
||||||
|
aria-expanded={userOpen}
|
||||||
>
|
>
|
||||||
{initials}
|
{initials}
|
||||||
</button>
|
</button>
|
||||||
{userOpen && (
|
{userOpen && (
|
||||||
<div className="absolute right-0 mt-3 w-48 rounded-lg border border-[#E2E8F0] bg-white shadow-lg z-50">
|
<div className="absolute right-0 mt-3 w-64 rounded-[12px] border border-[#E2E8F0] bg-white shadow-[0_20px_30px_rgba(15,23,42,0.12)] z-50">
|
||||||
<div className="px-4 py-3 border-b border-[#F1F5F9] text-center space-y-0.5">
|
<div className="px-4 py-3 border-b border-[#F1F5F9] text-left space-y-1">
|
||||||
<p className="text-sm font-semibold text-[#232528] truncate" title={userName}>{userName}</p>
|
<p className="text-sm font-semibold text-[#232528] truncate" title={userName}>
|
||||||
{userEmail && <p className="text-xs text-[#64748B] truncate" title={userEmail}>{userEmail}</p>}
|
{userName?.replace(/([a-z])([A-Z])/g, '$1 $2')}
|
||||||
|
</p>
|
||||||
|
{userEmail && <p className="text-xs text-[#6B7280] truncate" title={userEmail}>{userEmail}</p>}
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={onChangePassword}
|
onClick={onChangePassword}
|
||||||
className="w-full px-4 py-2.5 text-center text-sm text-[#232528] hover:bg-[#F2ECCF] transition-colors"
|
className="w-full px-4 py-2.5 text-left text-sm text-[#232528] hover:bg-[#F2ECCF]"
|
||||||
>
|
>
|
||||||
Change Password
|
Change Password
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={onLogout}
|
onClick={onLogout}
|
||||||
className="w-full px-4 py-2.5 text-center text-sm text-[#B91C1C] hover:bg-[#FEE2E2] transition-colors"
|
className="w-full px-4 py-2.5 text-left text-sm text-[#B91C1C] hover:bg-[#FEE2E2] transition-colors"
|
||||||
>
|
>
|
||||||
Logout
|
Logout
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@ -187,8 +187,6 @@ const EstablishmentInfo = ({
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const establishmentId = sessionStorage.getItem('establishment_id');
|
const establishmentId = sessionStorage.getItem('establishment_id');
|
||||||
console.log('Edit Profile clicked, establishment_id:', establishmentId);
|
|
||||||
|
|
||||||
if (!establishmentId) {
|
if (!establishmentId) {
|
||||||
alert('No establishment ID found in session');
|
alert('No establishment ID found in session');
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -644,7 +644,6 @@ const location = useLocation();
|
|||||||
product_id: productId
|
product_id: productId
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('Calling getPreviousForecastData with params:', params);
|
|
||||||
|
|
||||||
const response = await getPreviousForecastData(
|
const response = await getPreviousForecastData(
|
||||||
establishmentId,
|
establishmentId,
|
||||||
|
|||||||
@ -64,10 +64,10 @@ const ManageSubmissions = () => {
|
|||||||
const [error, setError] = React.useState(null);
|
const [error, setError] = React.useState(null);
|
||||||
const [search, setSearch] = React.useState('');
|
const [search, setSearch] = React.useState('');
|
||||||
const [year, setYear] = React.useState('');
|
const [year, setYear] = React.useState('');
|
||||||
const [quarter, setQuarter] = React.useState('');
|
const [quarter, setQuarter] = React.useState('All');
|
||||||
const [emirate, setEmirate] = React.useState('');
|
const [emirate, setEmirate] = React.useState('All');
|
||||||
const [status, setStatus] = React.useState('All');
|
const [status, setStatus] = React.useState('All');
|
||||||
const [selectedQuarter, setSelectedQuarter] = React.useState('Q1');
|
const [selectedQuarter, setSelectedQuarter] = React.useState('All');
|
||||||
const [selectedYear, setSelectedYear] = React.useState(new Date().getFullYear().toString());
|
const [selectedYear, setSelectedYear] = React.useState(new Date().getFullYear().toString());
|
||||||
const [currentPage, setCurrentPage] = React.useState(1);
|
const [currentPage, setCurrentPage] = React.useState(1);
|
||||||
const [toast, setToast] = React.useState(null);
|
const [toast, setToast] = React.useState(null);
|
||||||
@ -181,7 +181,7 @@ const ManageSubmissions = () => {
|
|||||||
// Validate the rejection reason
|
// Validate the rejection reason
|
||||||
if (!rejectReason.trim()) {
|
if (!rejectReason.trim()) {
|
||||||
setShowRejectError(true);
|
setShowRejectError(true);
|
||||||
showToast('error', 'Please provide a reason for rejection');
|
// showToast('error', 'Please provide a reason for rejection');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,9 +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 currentYear = response?.data?.selected_year || new Date().getFullYear().toString();
|
const currentQuarter = 'All';
|
||||||
|
// const currentYear = response?.data?.selected_year || new Date().getFullYear().toString();
|
||||||
|
const currentYear = 'All';
|
||||||
// Set the filter states
|
// Set the filter states
|
||||||
setSelectedQuarter(currentQuarter);
|
setSelectedQuarter(currentQuarter);
|
||||||
setSelectedYear(currentYear);
|
setSelectedYear(currentYear);
|
||||||
@ -462,8 +463,9 @@ React.useEffect(() => {
|
|||||||
<SelectField
|
<SelectField
|
||||||
value={selectedQuarter}
|
value={selectedQuarter}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setSelectedQuarter(e.target.value);
|
const value = e.target.value || 'All';
|
||||||
setQuarter(e.target.value);
|
setSelectedQuarter(value);
|
||||||
|
setQuarter(value);
|
||||||
}}
|
}}
|
||||||
options={quarterOptions.map((v) => ({ label: v, value: v }))}
|
options={quarterOptions.map((v) => ({ label: v, value: v }))}
|
||||||
placeholder="Quarter"
|
placeholder="Quarter"
|
||||||
@ -826,29 +828,19 @@ React.useEffect(() => {
|
|||||||
{showRejectError && !rejectReason.trim() && (
|
{showRejectError && !rejectReason.trim() && (
|
||||||
<p className="mt-1 text-sm text-red-600">Reason for rejection is required</p>
|
<p className="mt-1 text-sm text-red-600">Reason for rejection is required</p>
|
||||||
)}
|
)}
|
||||||
<p className="mt-1 text-xs text-right text-[#6B7280] italic">
|
|
||||||
Please refer to the screenshot
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-4 flex justify-end gap-3">
|
<div className="mt-4 flex justify-end gap-3">
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={handleCloseRejectModal}
|
|
||||||
className="px-4 py-2 text-sm font-medium text-[#92722A] bg-white border border-[#92722A] rounded-md shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-[#92722A]"
|
|
||||||
disabled={isRejecting}
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={handleRejectConfirm}
|
onClick={handleRejectConfirm}
|
||||||
className="px-4 py-2 text-sm font-medium text-white bg-[#92722A] border border-transparent rounded-md shadow-sm hover:bg-[#7c5e24] focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-[#92722A] flex items-center gap-2"
|
className="px-4 py-2 text-sm font-medium text-white bg-[#92722A] border border-transparent rounded-md shadow-sm hover:bg-[#7c5e24] focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-[#92722A] flex items-center gap-2"
|
||||||
disabled={isRejecting || !rejectReason.trim()}
|
disabled={isRejecting}
|
||||||
>
|
>
|
||||||
{isRejecting ? (
|
{isRejecting ? (
|
||||||
<>
|
<>
|
||||||
<svg className="animate-spin h-4 w-4 text-[#92722A]" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
<svg className="animate-spin h-4 w-4 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
|
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
|
||||||
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8z"></path>
|
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8z"></path>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
@ -404,11 +404,9 @@ const AdminUsers = () => {
|
|||||||
confirm_password: confirmPassword
|
confirm_password: confirmPassword
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('🔄 Initiating admin password reset for user:', resetUser.id);
|
|
||||||
|
|
||||||
const res = await changeAdminUserPassword(resetUser.id, passwordData);
|
const res = await changeAdminUserPassword(resetUser.id, passwordData);
|
||||||
|
|
||||||
console.log('✅ Admin password reset response:', res);
|
|
||||||
|
|
||||||
// Check for success based on common response patterns
|
// Check for success based on common response patterns
|
||||||
const success =
|
const success =
|
||||||
|
|||||||
@ -27,7 +27,8 @@ const inactiveToggleSrc = '/assets/images/Toggle-inactive.svg';
|
|||||||
|
|
||||||
|
|
||||||
const PASSWORD_POLICY = {
|
const PASSWORD_POLICY = {
|
||||||
minLength: 12,
|
minLength: 8,
|
||||||
|
minRecommendedLength: 12,
|
||||||
complexityPattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\w\s]).+$/,
|
complexityPattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\w\s]).+$/,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -84,6 +85,16 @@ const formatApiDate = (value) => {
|
|||||||
return `${day}/${month}/${year}`;
|
return `${day}/${month}/${year}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const formatDate = (dateString) => {
|
||||||
|
if (!dateString) return '-';
|
||||||
|
const date = new Date(dateString);
|
||||||
|
if (Number.isNaN(date.getTime())) return '-';
|
||||||
|
const day = String(date.getDate()).padStart(2, '0');
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||||
|
const year = date.getFullYear();
|
||||||
|
return `${day}/${month}/${year}`;
|
||||||
|
};
|
||||||
|
|
||||||
const createEmptyProfile = () => ({
|
const createEmptyProfile = () => ({
|
||||||
apiId: null,
|
apiId: null,
|
||||||
userProfileName: '',
|
userProfileName: '',
|
||||||
@ -195,6 +206,19 @@ const CompanyProfile = () => {
|
|||||||
const [productSearchTerm, setProductSearchTerm] = React.useState('');
|
const [productSearchTerm, setProductSearchTerm] = React.useState('');
|
||||||
const [isLoadingProducts, setIsLoadingProducts] = React.useState(false);
|
const [isLoadingProducts, setIsLoadingProducts] = React.useState(false);
|
||||||
const [isRefreshing, setIsRefreshing] = React.useState(false);
|
const [isRefreshing, setIsRefreshing] = React.useState(false);
|
||||||
|
const [isUpdating, setIsUpdating] = React.useState(false);
|
||||||
|
|
||||||
|
const handleCloseModal = () => {
|
||||||
|
setModalMode(null);
|
||||||
|
setEditingRow(null);
|
||||||
|
setForm(createEmptyProfile());
|
||||||
|
setActiveStep(0);
|
||||||
|
setFieldErrors({});
|
||||||
|
setPasswordError('');
|
||||||
|
setConfirmError('');
|
||||||
|
setPasswordReuseError('');
|
||||||
|
setSelectedProducts([]);
|
||||||
|
};
|
||||||
|
|
||||||
const showToast = React.useCallback((type, message) => {
|
const showToast = React.useCallback((type, message) => {
|
||||||
if (!message) return;
|
if (!message) return;
|
||||||
@ -328,11 +352,9 @@ const CompanyProfile = () => {
|
|||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
const profile = sessionStorage.getItem('user_profile');
|
const profile = sessionStorage.getItem('user_profile');
|
||||||
// console.log("profile123",profile)
|
|
||||||
const userProfile = React.useMemo(() => {
|
const userProfile = React.useMemo(() => {
|
||||||
try {
|
try {
|
||||||
const profile = sessionStorage.getItem('user_profile');
|
const profile = sessionStorage.getItem('user_profile');
|
||||||
// console.log("profile",profile)
|
|
||||||
return profile ? JSON.parse(profile) : null;
|
return profile ? JSON.parse(profile) : null;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error parsing user profile:', error);
|
console.error('Error parsing user profile:', error);
|
||||||
@ -943,9 +965,9 @@ const CompanyProfile = () => {
|
|||||||
<li key={product.id} className="p-3 hover:bg-[#F9FAFB] flex justify-between items-center">
|
<li key={product.id} className="p-3 hover:bg-[#F9FAFB] flex justify-between items-center">
|
||||||
<div>
|
<div>
|
||||||
<div className="text-sm font-medium text-[#111827]">
|
<div className="text-sm font-medium text-[#111827]">
|
||||||
{product.hsCode || ''}
|
{product.hs_code || product.hsCode || ''}
|
||||||
{product.hsCode && (product.productName || product.label || product.product_name) ? ' - ' : ''}
|
{product.hs_code || product.hsCode ? ' - ' : ''}
|
||||||
{product.productName || product.label || product.product_name || ''}
|
{product.product_name || product.productName || product.label || 'Unnamed Product'}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
@ -1065,7 +1087,7 @@ const loadProducts = async () => {
|
|||||||
productsData = Array.isArray(response.data) ? response.data : response.data.products || [];
|
productsData = Array.isArray(response.data) ? response.data : response.data.products || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Processed products data:', productsData);
|
('Processed products data:', productsData);
|
||||||
|
|
||||||
// Update the products state with the formatted data
|
// Update the products state with the formatted data
|
||||||
const formattedProducts = productsData.map(p => ({
|
const formattedProducts = productsData.map(p => ({
|
||||||
@ -1111,26 +1133,21 @@ const loadProducts = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleAddProduct = (product) => {
|
const handleAddProduct = (product) => {
|
||||||
console.log('Adding product:', product);
|
|
||||||
setSelectedProducts(prev => {
|
setSelectedProducts(prev => {
|
||||||
const updated = [...prev, product];
|
const updated = [...prev, product];
|
||||||
console.log('Updated selected products:', updated);
|
|
||||||
return updated;
|
return updated;
|
||||||
});
|
});
|
||||||
// Remove from available products
|
// Remove from available products
|
||||||
setAvailableProducts(prev => prev.filter(p => p.id !== product.id));
|
setAvailableProducts(prev => prev.filter(p => p.id !== product.id));
|
||||||
setAvailableProducts(prev => {
|
setAvailableProducts(prev => {
|
||||||
const updated = prev.filter(p => p.id !== product.id);
|
const updated = prev.filter(p => p.id !== product.id);
|
||||||
console.log('Updated available products after add:', updated);
|
|
||||||
return updated;
|
return updated;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRemoveProduct = (product) => {
|
const handleRemoveProduct = (product) => {
|
||||||
console.log('Removing product:', product);
|
|
||||||
setSelectedProducts(prev => {
|
setSelectedProducts(prev => {
|
||||||
const updated = prev.filter(p => p.id !== product.id);
|
const updated = prev.filter(p => p.id !== product.id);
|
||||||
console.log('Updated selected products after removal:', updated);
|
|
||||||
return updated;
|
return updated;
|
||||||
});
|
});
|
||||||
// Add back to available products if not already there
|
// Add back to available products if not already there
|
||||||
@ -1250,7 +1267,7 @@ const loadProducts = async () => {
|
|||||||
item.totalEmployees,
|
item.totalEmployees,
|
||||||
item.createdBy,
|
item.createdBy,
|
||||||
item.createdOn,
|
item.createdOn,
|
||||||
item.lastUpdated,
|
item.updated_at ? formatDate(item.updated_at) : (item.lastUpdated || '-'),
|
||||||
renderStatusBadge(item.status),
|
renderStatusBadge(item.status),
|
||||||
(
|
(
|
||||||
<div className="flex items-center gap-2" key={`actions-${item.establishmentId}`}>
|
<div className="flex items-center gap-2" key={`actions-${item.establishmentId}`}>
|
||||||
@ -1509,8 +1526,6 @@ const corporateFieldKeys = Object.values(contactToCorporateMap);
|
|||||||
creatorName = name.replace(/([a-zA-Z])([A-Z])/g, '$1 $2');
|
creatorName = name.replace(/([a-zA-Z])([A-Z])/g, '$1 $2');
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Creator ID:', item?.created_by, 'Current User ID:', currentUser?.id);
|
|
||||||
console.log('Creator Name:', creatorName);
|
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -1536,7 +1551,8 @@ const corporateFieldKeys = Object.values(contactToCorporateMap);
|
|||||||
createdBy: creatorName,
|
createdBy: creatorName,
|
||||||
createdById: item?.created_by ?? base.createdById,
|
createdById: item?.created_by ?? base.createdById,
|
||||||
createdOn: formatApiDate(item?.created_at),
|
createdOn: formatApiDate(item?.created_at),
|
||||||
lastUpdated: item?.updated_by ?? formatApiDate(item?.updated_at),
|
updated_at: item?.updated_at ? new Date(item.updated_at).toISOString() : null,
|
||||||
|
lastUpdated: formatApiDate(item?.updated_at),
|
||||||
contactName: item?.factory_name || '',
|
contactName: item?.factory_name || '',
|
||||||
// contactEmail: item?.email ?? '',
|
// contactEmail: item?.email ?? '',
|
||||||
contactEmail: item?.establishment_contact_email ?? base.contactEmail,
|
contactEmail: item?.establishment_contact_email ?? base.contactEmail,
|
||||||
@ -1571,6 +1587,17 @@ const corporateFieldKeys = Object.values(contactToCorporateMap);
|
|||||||
employmentTotalEmployees: totalEmployees !== '' && totalEmployees !== null ? String(totalEmployees) : '',
|
employmentTotalEmployees: totalEmployees !== '' && totalEmployees !== null ? String(totalEmployees) : '',
|
||||||
userProfileName: primaryUser?.name ?? base.userProfileName,
|
userProfileName: primaryUser?.name ?? base.userProfileName,
|
||||||
userProfileEmail: primaryUser?.email ?? base.userProfileEmail,
|
userProfileEmail: primaryUser?.email ?? base.userProfileEmail,
|
||||||
|
establishment_products: Array.isArray(item?.establishment_products)
|
||||||
|
? item.establishment_products.map(p => ({
|
||||||
|
id: p.id || p.product_id || 0,
|
||||||
|
product_id: p.product_id || p.id || 0,
|
||||||
|
hsCode: p.hs_code || p.hsCode || '',
|
||||||
|
productName: p.product_name || p.productName || p.label || '',
|
||||||
|
label: p.product_name || p.productName || p.label || '',
|
||||||
|
value: p.hs_code || p.hsCode || '',
|
||||||
|
...p
|
||||||
|
}))
|
||||||
|
: [],
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@ -1612,8 +1639,6 @@ const loadProfiles = async () => {
|
|||||||
|
|
||||||
// Log the complete response structure for debugging
|
// Log the complete response structure for debugging
|
||||||
console.group('API Response Details');
|
console.group('API Response Details');
|
||||||
console.log('Full response:', response);
|
|
||||||
console.log('Response data:', payload);
|
|
||||||
console.groupEnd();
|
console.groupEnd();
|
||||||
|
|
||||||
const records = Array.isArray(payload?.data) ? payload.data : Array.isArray(payload) ? payload : [];
|
const records = Array.isArray(payload?.data) ? payload.data : Array.isArray(payload) ? payload : [];
|
||||||
@ -1763,6 +1788,40 @@ const loadProfiles = async () => {
|
|||||||
...computeEmploymentTotals(mapped)
|
...computeEmploymentTotals(mapped)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// Set selected products if available
|
||||||
|
if (mapped.establishment_products && Array.isArray(mapped.establishment_products)) {
|
||||||
|
// Map the products to ensure they have all required fields
|
||||||
|
const formattedProducts = mapped.establishment_products.map(p => {
|
||||||
|
// Use nested product object if it exists, otherwise fall back to root properties
|
||||||
|
const productData = p.product || {};
|
||||||
|
const productName = productData.product_name || p.product_name || 'Unnamed Product';
|
||||||
|
const hsCode = productData.hs_code || p.hs_code || '';
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: p.id || 0,
|
||||||
|
product_id: p.product_id || 0,
|
||||||
|
hs_code: hsCode,
|
||||||
|
hsCode: hsCode,
|
||||||
|
product_name: productName,
|
||||||
|
productName: productName,
|
||||||
|
label: `${productName}${hsCode ? ` (${hsCode})` : ''}`,
|
||||||
|
value: p.product_id ? String(p.product_id) : '',
|
||||||
|
establishment_id: p.establishment_id,
|
||||||
|
...productData, // Spread the nested product data
|
||||||
|
product: productData // Keep the nested product object for reference
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("Formatted Products:", formattedProducts);
|
||||||
|
setSelectedProducts(formattedProducts);
|
||||||
|
} else {
|
||||||
|
setSelectedProducts([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug log
|
||||||
|
console.log('Setting form with products:', mapped.establishment_products);
|
||||||
|
console.log('Setting selectedProducts:', selectedProducts);
|
||||||
|
|
||||||
initialSnapshotRef.current = { ...mapped, ...computeEmploymentTotals(mapped) };
|
initialSnapshotRef.current = { ...mapped, ...computeEmploymentTotals(mapped) };
|
||||||
corporateBackupRef.current = captureCorporateValues(mapped);
|
corporateBackupRef.current = captureCorporateValues(mapped);
|
||||||
} else {
|
} else {
|
||||||
@ -2117,11 +2176,22 @@ const requiredFields = [
|
|||||||
return `${day}/${month}/${year}`;
|
return `${day}/${month}/${year}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getCurrentISODate = () => {
|
||||||
|
return new Date().toISOString();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
const handleSaveForm = async (e) => {
|
const handleSaveForm = async (e) => {
|
||||||
// Prevent default form submission behavior
|
// Prevent default form submission behavior
|
||||||
if (e) {
|
if (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prevent multiple submissions
|
||||||
|
if (isUpdating || isSaving) return;
|
||||||
|
|
||||||
|
// Show loading state
|
||||||
|
setIsSaving(true);
|
||||||
if (!validateStepFields(activeStep)) {
|
if (!validateStepFields(activeStep)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2226,7 +2296,7 @@ const requiredFields = [
|
|||||||
total_emirati: Number(totalEmirati) || 0,
|
total_emirati: Number(totalEmirati) || 0,
|
||||||
total_employees: Number(employmentTotals) || 0,
|
total_employees: Number(employmentTotals) || 0,
|
||||||
created_by: currentUserId?.id,
|
created_by: currentUserId?.id,
|
||||||
created_by_name: currentUserId?.name, // Add this line
|
created_by_name: currentUserId?.name,
|
||||||
establishment_user: {
|
establishment_user: {
|
||||||
name: form.userProfileName || '',
|
name: form.userProfileName || '',
|
||||||
email: form.userProfileEmail || '',
|
email: form.userProfileEmail || '',
|
||||||
@ -2238,7 +2308,6 @@ const requiredFields = [
|
|||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
const apiResponse = await createEstablishment(apiPayload);
|
const apiResponse = await createEstablishment(apiPayload);
|
||||||
console.log('API Response:', apiResponse);
|
|
||||||
const successMessage = apiResponse?.message || 'Establishment added successfully.';
|
const successMessage = apiResponse?.message || 'Establishment added successfully.';
|
||||||
showToast('success', successMessage);
|
showToast('success', successMessage);
|
||||||
const createdRecord = apiResponse?.data;
|
const createdRecord = apiResponse?.data;
|
||||||
@ -2261,9 +2330,17 @@ const requiredFields = [
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const targetId = form.apiId ?? profiles[editingRow]?.apiId ?? null;
|
let targetId = form.apiId ?? profiles[editingRow]?.apiId ?? null;
|
||||||
|
if (!targetId) {
|
||||||
|
showToast('error', 'Unable to update: Missing establishment ID');
|
||||||
|
setIsSaving(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setIsUpdating(true);
|
||||||
if (targetId === null || targetId === undefined) {
|
if (targetId === null || targetId === undefined) {
|
||||||
throw new Error('Unable to update establishment. Missing identifier.');
|
setIsUpdating(false);
|
||||||
|
showToast('error', 'Unable to update establishment. Missing identifier.');
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
const establishmentUserPayload = {
|
const establishmentUserPayload = {
|
||||||
name: form.userProfileName || '',
|
name: form.userProfileName || '',
|
||||||
@ -2315,19 +2392,62 @@ const requiredFields = [
|
|||||||
non_emirati_female: Number(form.employmentNonEmiratiFemale) || 0,
|
non_emirati_female: Number(form.employmentNonEmiratiFemale) || 0,
|
||||||
total_emirati: (Number(form.employmentEmiratiMale) || 0) + (Number(form.employmentEmiratiFemale) || 0),
|
total_emirati: (Number(form.employmentEmiratiMale) || 0) + (Number(form.employmentEmiratiFemale) || 0),
|
||||||
total_employees: Number(form.employmentTotalEmployees) || 0,
|
total_employees: Number(form.employmentTotalEmployees) || 0,
|
||||||
updated_by: 1 // Replace with actual user ID from your auth context
|
updated_by: 1,
|
||||||
|
updated_at: getCurrentISODate(),
|
||||||
|
establishment_products: Array.isArray(selectedProducts) && selectedProducts.length > 0
|
||||||
|
? selectedProducts.map(p => ({
|
||||||
|
id: p.id, // Include the establishment_product ID for updates
|
||||||
|
product_id: p.product_id || p.product?.id || p.id, // The actual product ID
|
||||||
|
_destroy: false // Flag to indicate not to delete this association
|
||||||
|
}))
|
||||||
|
: [{ product_id: 0 }]
|
||||||
};
|
};
|
||||||
|
|
||||||
if (establishmentUserPayload.name || establishmentUserPayload.email || establishmentUserPayload.password) {
|
if (establishmentUserPayload.name || establishmentUserPayload.email || establishmentUserPayload.password) {
|
||||||
updatePayload.establishment_user = establishmentUserPayload;
|
updatePayload.establishment_user = establishmentUserPayload;
|
||||||
}
|
}
|
||||||
updatePayload.establishment_products = Array.isArray(selectedProducts) && selectedProducts.length > 0
|
try {
|
||||||
? selectedProducts.map(p => ({ product_id: p.id || p.product_id || 0 }))
|
// Show loading state
|
||||||
: [{ product_id: 0 }];
|
setIsUpdating(true);
|
||||||
const apiResponse = await updateEstablishment(targetId, updatePayload);
|
|
||||||
console.log("apiResponse",apiResponse)
|
const apiResponse = await updateEstablishment(targetId, updatePayload);
|
||||||
const successMessage = apiResponse?.message || 'Establishment updated successfully.';
|
console.log("apiResponse", apiResponse);
|
||||||
showToast('success', successMessage);
|
const successMessage = apiResponse?.message || 'Establishment updated successfully.';
|
||||||
apiResultData = apiResponse?.data;
|
showToast('success', successMessage);
|
||||||
|
|
||||||
|
// Update the local state with the updated data
|
||||||
|
const updatedProfile = {
|
||||||
|
...form,
|
||||||
|
...updatePayload,
|
||||||
|
establishment_products: selectedProducts,
|
||||||
|
apiId: targetId
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update the profiles list
|
||||||
|
setProfiles(prev =>
|
||||||
|
prev.map(profile =>
|
||||||
|
profile.apiId === targetId ? updatedProfile : profile
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Close the modal and reset form
|
||||||
|
handleCloseModal();
|
||||||
|
|
||||||
|
// Refresh the page after a short delay to show the success message
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.reload();
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
// Return the updated data
|
||||||
|
return apiResponse?.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error updating establishment:', error);
|
||||||
|
const errorMessage = error.response?.data?.message || error.message || 'Failed to update establishment';
|
||||||
|
showToast('error', errorMessage);
|
||||||
|
throw error; // Re-throw to be caught by the outer try-catch
|
||||||
|
} finally {
|
||||||
|
setIsUpdating(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const payload = {
|
const payload = {
|
||||||
@ -2400,12 +2520,15 @@ const requiredFields = [
|
|||||||
setModalMode(null);
|
setModalMode(null);
|
||||||
setEditingRow(null);
|
setEditingRow(null);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.error('Error saving form:', error);
|
||||||
const message = error?.response?.data?.message || error?.message || 'Failed to save profile. Please try again.';
|
const message = error?.response?.data?.message || error?.message || 'Failed to save profile. Please try again.';
|
||||||
setSaveError(message);
|
setSaveError(message);
|
||||||
setSaveWarning(false);
|
setSaveWarning(false);
|
||||||
|
showToast('error', message);
|
||||||
return;
|
return;
|
||||||
} finally {
|
} finally {
|
||||||
setIsSaving(false);
|
setIsSaving(false);
|
||||||
|
setIsUpdating(false);
|
||||||
const elapsed = performance.now() - startTime;
|
const elapsed = performance.now() - startTime;
|
||||||
if (elapsed > 1200) {
|
if (elapsed > 1200) {
|
||||||
setSaveWarning(true);
|
setSaveWarning(true);
|
||||||
@ -2719,7 +2842,7 @@ const requiredFields = [
|
|||||||
onClick={handleSaveForm}
|
onClick={handleSaveForm}
|
||||||
disabled={isSaving}
|
disabled={isSaving}
|
||||||
>
|
>
|
||||||
{isSaving ? 'Saving…' : modalMode === 'edit' ? 'Update' : 'Add'}
|
{isUpdating ? 'Updating…' : isSaving ? 'Saving…' : modalMode === 'edit' ? 'Update' : 'Add'}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@ -47,8 +47,6 @@ const createEmptyProfile = () => ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const mapApiEstablishmentToProfile = (apiData) => {
|
const mapApiEstablishmentToProfile = (apiData) => {
|
||||||
console.log('API Data to map:', apiData);
|
|
||||||
|
|
||||||
const data = apiData.data || apiData;
|
const data = apiData.data || apiData;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -505,10 +505,7 @@ const IsicHsCodes = () => {
|
|||||||
try {
|
try {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
const productId = selected.id;
|
const productId = selected.id;
|
||||||
console.log(`Fetching product details for ID: ${productId}`);
|
|
||||||
const response = await productService.getProductById(productId);
|
const response = await productService.getProductById(productId);
|
||||||
console.log('Product details response:', response);
|
|
||||||
|
|
||||||
if (response && response.data) {
|
if (response && response.data) {
|
||||||
const product = response.data;
|
const product = response.data;
|
||||||
setForm({
|
setForm({
|
||||||
@ -541,11 +538,7 @@ const IsicHsCodes = () => {
|
|||||||
try {
|
try {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
const productId = selected.id;
|
const productId = selected.id;
|
||||||
console.log(`Fetching product details for editing ID: ${productId}`);
|
|
||||||
|
|
||||||
const response = await productService.getProductById(productId);
|
const response = await productService.getProductById(productId);
|
||||||
console.log('Product details for edit:', response);
|
|
||||||
|
|
||||||
if (response && response.data) {
|
if (response && response.data) {
|
||||||
const product = response.data;
|
const product = response.data;
|
||||||
setForm({
|
setForm({
|
||||||
@ -573,8 +566,6 @@ const IsicHsCodes = () => {
|
|||||||
|
|
||||||
const handleDelete = async (paginationIndex) => {
|
const handleDelete = async (paginationIndex) => {
|
||||||
const dataIndex = (currentPage - 1) * pageSize + paginationIndex;
|
const dataIndex = (currentPage - 1) * pageSize + paginationIndex;
|
||||||
console.log('Delete button clicked, paginationIndex:', paginationIndex, 'dataIndex:', dataIndex);
|
|
||||||
|
|
||||||
if (dataIndex < 0 || dataIndex >= rowsData.length) {
|
if (dataIndex < 0 || dataIndex >= rowsData.length) {
|
||||||
console.error('Invalid row index for deletion');
|
console.error('Invalid row index for deletion');
|
||||||
return;
|
return;
|
||||||
@ -590,11 +581,7 @@ const IsicHsCodes = () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
console.log('Fetching product details before deletion, ID:', productId);
|
|
||||||
|
|
||||||
const response = await productService.getProductById(productId);
|
const response = await productService.getProductById(productId);
|
||||||
console.log('Product details from API:', response);
|
|
||||||
|
|
||||||
if (!response || !response.data) {
|
if (!response || !response.data) {
|
||||||
throw new Error('Invalid product data received');
|
throw new Error('Invalid product data received');
|
||||||
}
|
}
|
||||||
@ -628,7 +615,6 @@ const IsicHsCodes = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleDeleteConfirm = async () => {
|
const handleDeleteConfirm = async () => {
|
||||||
console.log('Delete confirmed, deletingRowIndex:', deletingRowIndex);
|
|
||||||
|
|
||||||
if (deletingRowIndex === null || deletingRowIndex < 0 || deletingRowIndex >= rowsData.length) {
|
if (deletingRowIndex === null || deletingRowIndex < 0 || deletingRowIndex >= rowsData.length) {
|
||||||
const errorMsg = 'Invalid row selected for deletion';
|
const errorMsg = 'Invalid row selected for deletion';
|
||||||
@ -649,8 +635,6 @@ const IsicHsCodes = () => {
|
|||||||
throw new Error('No product ID found for deletion');
|
throw new Error('No product ID found for deletion');
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Deleting product:', { productId, product });
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await productService.deleteProduct(productId);
|
await productService.deleteProduct(productId);
|
||||||
|
|
||||||
@ -717,8 +701,6 @@ const IsicHsCodes = () => {
|
|||||||
const handleImportCSV = async (file) => {
|
const handleImportCSV = async (file) => {
|
||||||
try {
|
try {
|
||||||
// Simulate CSV processing - replace with actual API call
|
// Simulate CSV processing - replace with actual API call
|
||||||
console.log('Importing file:', file);
|
|
||||||
|
|
||||||
// Simulate successful import
|
// Simulate successful import
|
||||||
await new Promise(resolve => setTimeout(resolve, 1500));
|
await new Promise(resolve => setTimeout(resolve, 1500));
|
||||||
|
|
||||||
@ -835,11 +817,8 @@ const IsicHsCodes = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Creating new product...');
|
|
||||||
try {
|
try {
|
||||||
const response = await productService.createProduct(productData);
|
const response = await productService.createProduct(productData);
|
||||||
console.log('Create response:', response);
|
|
||||||
|
|
||||||
const selectedUnit = unitOptions.find(u => u.value === form.unit);
|
const selectedUnit = unitOptions.find(u => u.value === form.unit);
|
||||||
|
|
||||||
const newProduct = {
|
const newProduct = {
|
||||||
@ -858,7 +837,6 @@ const IsicHsCodes = () => {
|
|||||||
|
|
||||||
setRowsData(prev => [newProduct, ...prev]);
|
setRowsData(prev => [newProduct, ...prev]);
|
||||||
setFilteredData(prev => [newProduct, ...prev]);
|
setFilteredData(prev => [newProduct, ...prev]);
|
||||||
console.log('Product created successfully');
|
|
||||||
showToast('Product created successfully!', 'success');
|
showToast('Product created successfully!', 'success');
|
||||||
closeModal();
|
closeModal();
|
||||||
} catch (createError) {
|
} catch (createError) {
|
||||||
|
|||||||
@ -274,9 +274,8 @@ const UnitMaster = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const selectedProducts = Array.isArray(form.productsMapped) ? form.productsMapped : [];
|
const selectedProducts = Array.isArray(form.productsMapped) ? form.productsMapped : [];
|
||||||
console.log(selectedProducts,"selectedProducts");
|
|
||||||
|
|
||||||
// ✅ Check for duplicate unit name
|
// Check for duplicate unit name
|
||||||
const nameExists = units.some(
|
const nameExists = units.some(
|
||||||
unit => unit.uom?.toLowerCase().trim() === form.unitName.toLowerCase().trim()
|
unit => unit.uom?.toLowerCase().trim() === form.unitName.toLowerCase().trim()
|
||||||
);
|
);
|
||||||
|
|||||||
@ -140,7 +140,7 @@ useEffect(() => {
|
|||||||
? hscodeFilter.split(" - ")[1].trim()
|
? hscodeFilter.split(" - ")[1].trim()
|
||||||
: hscodeFilter.trim();
|
: hscodeFilter.trim();
|
||||||
|
|
||||||
console.log("📦 Loading audit history with:", {
|
console.log("Loading audit history with:", {
|
||||||
yearFilter,
|
yearFilter,
|
||||||
quarterFilter,
|
quarterFilter,
|
||||||
productName,
|
productName,
|
||||||
@ -170,7 +170,6 @@ useEffect(() => {
|
|||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
console.log("✅ Loaded audit history rows:", data.length);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(" Error loading audit history:", error);
|
console.error(" Error loading audit history:", error);
|
||||||
setAuditHistory([]);
|
setAuditHistory([]);
|
||||||
@ -616,7 +615,6 @@ const tableRows = auditHistory.map((entry, index) => {
|
|||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const value = e.target.value;
|
const value = e.target.value;
|
||||||
setSearchTerm(value);
|
setSearchTerm(value);
|
||||||
console.log("🔍 Searching for:", value);
|
|
||||||
}}
|
}}
|
||||||
className="w-64 h-10 border border-gray-300 rounded-md px-3 text-sm focus:outline-none focus:ring-1 focus:ring-blue-500"
|
className="w-64 h-10 border border-gray-300 rounded-md px-3 text-sm focus:outline-none focus:ring-1 focus:ring-blue-500"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -15,7 +15,6 @@ const SubmissionDetails = () => {
|
|||||||
try {
|
try {
|
||||||
const response = await fetchSubmissionDetail(submissionId);
|
const response = await fetchSubmissionDetail(submissionId);
|
||||||
const data = response.data;
|
const data = response.data;
|
||||||
console.log("data",data)
|
|
||||||
setSubmission({
|
setSubmission({
|
||||||
id: submissionId,
|
id: submissionId,
|
||||||
survey_name: 'Industrial Production Survey',
|
survey_name: 'Industrial Production Survey',
|
||||||
|
|||||||
@ -41,14 +41,11 @@ export const getSubmissions = async (params = {}) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const url = `/submissions?${queryParams.toString()}`;
|
const url = `/submissions?${queryParams.toString()}`;
|
||||||
console.log('Making API request to:', url);
|
|
||||||
|
|
||||||
const response = await apiClient.get(url);
|
const response = await apiClient.get(url);
|
||||||
console.log('API response received:', response);
|
|
||||||
|
|
||||||
// Check if response.data is an array or has a data property
|
// Check if response.data is an array or has a data property
|
||||||
const responseData = Array.isArray(response.data) ? response.data : response.data?.data;
|
const responseData = Array.isArray(response.data) ? response.data : response.data?.data;
|
||||||
console.log('Processed response data:', responseData);
|
|
||||||
|
|
||||||
return responseData || [];
|
return responseData || [];
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@ -45,8 +45,7 @@ export const changeAdminUserPassword = async (id, passwordData) => {
|
|||||||
try {
|
try {
|
||||||
if (!id) throw new Error("Invalid user ID");
|
if (!id) throw new Error("Invalid user ID");
|
||||||
|
|
||||||
console.log('🔍 Debug: Changing password for admin user:', id);
|
console.log('Debug: Password data received:', {
|
||||||
console.log('🔍 Debug: Password data received:', {
|
|
||||||
hasOldPassword: !!passwordData.old_password,
|
hasOldPassword: !!passwordData.old_password,
|
||||||
hasNewPassword: !!passwordData.new_password,
|
hasNewPassword: !!passwordData.new_password,
|
||||||
hasConfirmPassword: !!passwordData.confirm_password
|
hasConfirmPassword: !!passwordData.confirm_password
|
||||||
@ -59,17 +58,15 @@ export const changeAdminUserPassword = async (id, passwordData) => {
|
|||||||
confirm_password: passwordData.confirm_password
|
confirm_password: passwordData.confirm_password
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('🔍 Debug: Final request data being sent:', requestData);
|
|
||||||
|
|
||||||
// Use the correct endpoint for admin users
|
// Use the correct endpoint for admin users
|
||||||
// const response = await putRequest(`/admin_users/${id}/change-password`, requestData);
|
// const response = await putRequest(`/admin_users/${id}/change-password`, requestData);
|
||||||
const response = await putRequest(`admin_users/${id}/change-password`, requestData);
|
const response = await putRequest(`admin_users/${id}/change-password`, requestData);
|
||||||
|
|
||||||
console.log('🔍 Debug: Admin password change successful:', response.data);
|
|
||||||
return response.data;
|
return response.data;
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("❌ Error changing admin user password:", error);
|
console.error("Error changing admin user password:", error);
|
||||||
|
|
||||||
if (error.response) {
|
if (error.response) {
|
||||||
console.error("🔍 Debug: API error response:", {
|
console.error("🔍 Debug: API error response:", {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user