diff --git a/ipi-survey-platform/src/pages/Admin/configuration/CompanyProfile.jsx b/ipi-survey-platform/src/pages/Admin/configuration/CompanyProfile.jsx index 852dbd1..8fda6bd 100644 --- a/ipi-survey-platform/src/pages/Admin/configuration/CompanyProfile.jsx +++ b/ipi-survey-platform/src/pages/Admin/configuration/CompanyProfile.jsx @@ -106,7 +106,7 @@ const createEmptyProfile = () => ({ contactEmail: '', contactWebsite: '', // Corporate / head office contact details - corporateSameAs: false, + corporateSameAs: true, corporateName: '', corporateAddress: '', corporateCityTown: '', @@ -812,18 +812,28 @@ const CompanyProfile = () => { setActiveStep((prev) => Math.min(prev + 1, formSteps.length - 1)); }, [activeStep, form.userProfilePassword, form.userProfileConfirmPassword, formSteps.length, validateStepFields]); - const handleToggleStatus = (item) => { - const updatedStatus = item.status === 'Active' ? 'Inactive' : 'Active'; - - // Optional: call your API to update backend - // await updateEstablishmentStatus(item.id, updatedStatus); - - setEstablishments((prev) => - prev.map((est) => - est.id === item.id ? { ...est, status: updatedStatus } : est + const handleToggleStatus = async (establishmentId, currentStatus) => { + try { + const newStatus = !currentStatus; + await updateEstablishment(establishmentId, { is_active: newStatus }); + + // Update the local state to reflect the change + setProfiles(prevProfiles => + prevProfiles.map(profile => + profile.apiId === establishmentId + ? { ...profile, isActive: newStatus, status: newStatus ? 'Active' : 'Inactive' } + : profile ) ); - }; + + showToast('success', `Establishment ${newStatus ? 'activated' : 'deactivated'} successfully`); + } catch (error) { + console.error('Error updating status:', error); + const message = error?.response?.data?.message || 'Failed to update status. Please try again.'; + showToast('error', message); + } +}; + const filteredProfiles = React.useMemo(() => { if (!debouncedSearch.trim()) return profiles; @@ -848,7 +858,7 @@ const CompanyProfile = () => { const renderStatusBadge = (status) => { const statusMap = { active: { text: 'Active', bgColor: 'bg-[#F3FAF4]', textColor: 'text-[#2F663C]' }, - inactive: { text: 'Inactive', bgColor: 'bg-[#FEF2F2]', textColor: 'text-[#B91C1C]' }, + inactive: { text: 'Inactive', bgColor: 'bg-[#E9EDF3]', textColor: 'text-[#232528]' }, pending: { text: 'Pending', bgColor: 'bg-[#FFFBEB]', textColor: 'text-[#B45309]' }, // Add more status mappings as needed }; @@ -901,19 +911,21 @@ const CompanyProfile = () => { /> - + */} @@ -1890,7 +1902,11 @@ const loadProfiles = async () => { {isLoading ? (
- + +
+ ) : profiles.length === 0 ? ( +
+

No results found

) : ( ({ + survey_name: '', establishment: '-', // Default to hyphen year: '', quarter: '', startDate: '', endDate: '', - gracePeriod: '', + gracePeriod: '0 days', submissionCount: '0', - status: '', + status: 'Active', // Default to Active }); const QuarterlyWindows = () => { @@ -41,6 +43,21 @@ const QuarterlyWindows = () => { const [currentPage, setCurrentPage] = React.useState(1); const pageSize = 10; const [isLoading, setIsLoading] = React.useState(false); + const [toast, setToast] = React.useState({ show: false, message: '', type: 'success' }); + + // Format date to yyyy-MM-dd for input fields + const formatDateForInput = (dateString) => { + if (!dateString) return ''; + const date = new Date(dateString); + return date.toISOString().split('T')[0]; + }; + + // Format date for display + const formatDateForDisplay = (dateString) => { + if (!dateString) return ''; + const date = new Date(dateString); + return date.toLocaleDateString('en-GB'); + }; // Fetch quarterly windows data on component mount React.useEffect(() => { @@ -52,13 +69,14 @@ const QuarterlyWindows = () => { // Transform the API response to match the expected format const formattedData = response.data.map(item => ({ id: item.id, - establishment: item.establishment || '-', // Default to hyphen if empty + survey_name: item.survey_name || '', + establishment: item.establishment || '-', year: item.year?.toString() || '', quarter: item.quarter || '', - startDate: item.start_date ? new Date(item.start_date).toLocaleDateString('en-GB') : '', - endDate: item.end_date ? new Date(item.end_date).toLocaleDateString('en-GB') : '', + startDate: item.start_date || '', + endDate: item.end_date || '', gracePeriod: item.grace_periods_days ? `${item.grace_periods_days} days` : '0 days', - submissionCount: '0', // Default value since it's not in the API response + submissionCount: '0', status: item.is_active ? 'Active' : 'Inactive' })); setQuarterData(formattedData); @@ -95,6 +113,7 @@ const QuarterlyWindows = () => { if (!matchesStatus) return false; if (!term) return true; const haystack = [ + item.survey_name, item.establishment, item.year, item.quarter, @@ -111,11 +130,11 @@ const QuarterlyWindows = () => { }, [quarterData, searchTerm, statusFilter]); const rows = filteredRows.map((item) => [ - item.establishment, + item.survey_name || '-', item.year, item.quarter, - item.startDate, - item.endDate, + item.startDate ? formatDateForDisplay(item.startDate) : '-', + item.endDate ? formatDateForDisplay(item.endDate) : '-', item.gracePeriod, item.submissionCount, , @@ -145,9 +164,15 @@ const QuarterlyWindows = () => { const openEditModal = (index) => { const selected = quarterData[index]; + // Ensure dates are in the correct format for the form inputs + const formData = { + ...selected, + startDate: selected.startDate ? formatDateForInput(selected.startDate) : '', + endDate: selected.endDate ? formatDateForInput(selected.endDate) : '' + }; setEditingRow(index); - setForm({ ...selected }); - setOriginalForm({ ...selected }); + setForm(formData); + setOriginalForm(formData); setModalMode('edit'); }; @@ -171,6 +196,8 @@ const QuarterlyWindows = () => { } }; + + const openDeleteConfirm = (index) => { setDeletingRow(index); setShowDeleteConfirm(true); @@ -181,22 +208,41 @@ const QuarterlyWindows = () => { setDeletingRow(null); }; + const showToast = (message, type = 'success') => { + setToast({ show: true, message, type }); + setTimeout(() => setToast({ ...toast, show: false }), 4000); + }; + const handleSave = async () => { try { - const formatDate = (dateString) => { + if (!form.survey_name || !form.year || !form.quarter || !form.startDate || !form.endDate) { + showToast('Please fill in all required fields', 'error'); + return; + } + const formatDateForAPI = (dateString) => { if (!dateString) return ''; - const [day, month, year] = dateString.split('/'); - return `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')}`; + // If already in YYYY-MM-DD format + if (dateString.match(/^\d{4}-\d{2}-\d{2}$/)) { + return dateString; + } + // Handle DD/MM/YYYY format + if (dateString.includes('/')) { + const [day, month, year] = dateString.split('/'); + return `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')}`; + } + // For any other format, let the Date object handle it + return new Date(dateString).toISOString().split('T')[0]; }; const formattedData = { - year: parseInt(form.year, 10) || 0, - quarter: form.quarter || 'Q1', - start_date: formatDate(form.startDate) || new Date().toISOString().split('T')[0], - end_date: formatDate(form.endDate) || new Date().toISOString().split('T')[0], - grace_periods_days: parseInt(form.gracePeriod?.split(' ')[0], 10) || 0, + survey_name: form.survey_name || '', + year: form.year ? parseInt(form.year, 10) : 0, + quarter: form.quarter || '', + start_date: form.startDate ? formatDateForAPI(form.startDate) : '', + end_date: form.endDate ? formatDateForAPI(form.endDate) : '', + grace_periods_days: form.gracePeriod ? parseInt(form.gracePeriod.split(' ')[0], 10) || 0 : 0, is_active: form.status === 'Active', - establishment: '-', // Default to hyphen if empty + establishment: form.establishment || '-', }; if (modalMode === 'add') { @@ -212,9 +258,17 @@ const QuarterlyWindows = () => { status: formattedData.is_active ? 'Active' : 'Inactive' }; setQuarterData((prev) => [...prev, newItem]); + showToast('Quarterly window added successfully!'); + } else { + showToast('Failed to add quarterly window', 'error'); } } else if (modalMode === 'edit' && editingRow !== null) { - const response = await updateQuarterlyWindow(quarterData[editingRow].id, formattedData); + const itemId = quarterData[editingRow]?.id; + if (!itemId) { + showToast('Error: Could not find the item to update', 'error'); + return; + } + const response = await updateQuarterlyWindow(itemId, formattedData); if (response.status === 'success') { setQuarterData((prev) => prev.map((item, idx) => @@ -230,24 +284,60 @@ const QuarterlyWindows = () => { : item ) ); + showToast('Quarterly window updated successfully!'); + } else { + showToast('Failed to update quarterly window', 'error'); } } handleCloseModal(); } catch (error) { console.error('Error saving quarterly window:', error); - // You might want to add error handling UI here + showToast('An error occurred while saving. Please try again.', 'error'); } }; - const handleDelete = () => { - if (deletingRow !== null) { - setQuarterData((prev) => prev.filter((_, index) => index !== deletingRow)); + const handleDelete = async () => { + if (deletingRow === null) return; + + try { + // First, get the item to ensure we have the latest data + const itemToDelete = quarterData[deletingRow]; + if (!itemToDelete?.id) { + showToast('Error: Could not find the item to delete', 'error'); + closeDeleteConfirm(); + return; + } + + // Call the delete API with the ID + const response = await deleteQuarterlyWindow(itemToDelete.id); + + if (response.status === 'success') { + // Update the UI by removing the deleted item + setQuarterData(prev => prev.filter(item => item.id !== itemToDelete.id)); + showToast('Quarterly window deleted successfully!'); + } else { + showToast(response.message || 'Failed to delete quarterly window', 'error'); + } + } catch (error) { + console.error('Error deleting quarterly window:', error); + showToast('An error occurred while deleting. Please try again.', 'error'); + } finally { closeDeleteConfirm(); } }; return ( -
+ <> + {toast.show && ( +
+ setToast({ ...toast, show: false })} + /> +
+ )} +

Quarterly Windows

@@ -421,8 +511,8 @@ const QuarterlyWindows = () => {
setForm({ ...form, establishment: e.target.value })} + value={form.survey_name} + onChange={(e) => setForm({ ...form, survey_name: e.target.value })} placeholder="Enter survey name" />
@@ -557,6 +647,7 @@ const QuarterlyWindows = () => {
)}
+ ); };