diff --git a/ipi-survey-platform/public/assets/images/Breadcrumb-vector.svg b/ipi-survey-platform/public/assets/images/Breadcrumb-vector.svg new file mode 100644 index 0000000..7f6287a --- /dev/null +++ b/ipi-survey-platform/public/assets/images/Breadcrumb-vector.svg @@ -0,0 +1,3 @@ + + + diff --git a/ipi-survey-platform/src/App.jsx b/ipi-survey-platform/src/App.jsx index 50c2289..4c77988 100644 --- a/ipi-survey-platform/src/App.jsx +++ b/ipi-survey-platform/src/App.jsx @@ -13,6 +13,7 @@ import History from '@/pages/History/History'; import ChangePassword from '@/pages/ChangePassword/ChangePassword'; import ForgotPassword from '@/pages/ForgotPassword/ForgotPassword'; import PublicContactForm from '@/pages/PublicContactForm'; +import EditCompanyProfile from '@/pages/Admin/configuration/EditCompanyProfile'; const RequireRole = ({ allowedRoles = [], children }) => { let role @@ -160,6 +161,24 @@ function App() { )} /> + + + + + } + /> + + + + } + /> + } /> } /> } /> diff --git a/ipi-survey-platform/src/components/survey/EstablishmentInfo/EstablishmentInfo.jsx b/ipi-survey-platform/src/components/survey/EstablishmentInfo/EstablishmentInfo.jsx index 51eb9ad..c02c10d 100644 --- a/ipi-survey-platform/src/components/survey/EstablishmentInfo/EstablishmentInfo.jsx +++ b/ipi-survey-platform/src/components/survey/EstablishmentInfo/EstablishmentInfo.jsx @@ -10,14 +10,16 @@ import { useNavigate } from 'react-router-dom'; const Field = ({ label, placeholder = '', type = 'text', value = '', onChange = () => {}, disabled = true }) => (
- +
); @@ -84,6 +86,12 @@ const EstablishmentInfo = ({ const handleCloseInfo = () => { setShowInfoCard(false); }; + // Debug log to see what data is being received + React.useEffect(() => { + console.log('EstablishmentInfo data:', data); + console.log('Establishment contact email from data:', data?.establishment_contact_email); + }, [data]); + const info = React.useMemo( () => ({ quarter: '', @@ -94,6 +102,7 @@ const EstablishmentInfo = ({ licenseNumber: '', isicCode: '', emirate: '', + establishment_contact_email: data?.establishment_contact_email || '', employeeInfo: { ...defaultEmployeeInfo, ...(data.employeeInfo || {}), @@ -129,7 +138,7 @@ const handleEditProfile = (e) => { sessionStorage.setItem('edit_profile_from', 'EstablishmentUser'); // Navigate to profile edit page - navigate(`/admin/configuration/profile?edit=${establishmentId}`); + navigate(`/profile/edit/${establishmentId}`); }; const handleEmployeeChange = (field) => (event) => { @@ -274,14 +283,14 @@ const handleEditProfile = (e) => {

Reporting Period

- +
{["2022", "2023", "2024", "2025"].map(year => ( @@ -329,42 +339,49 @@ const handleEditProfile = (e) => { placeholder="Enter Establishment Name" value={info.establishmentName} onChange={handleFieldChange('establishmentName')} - disabled={loading} + disabled={true} + /> + {/* Email field is hidden but data remains in form state */}
@@ -372,7 +389,7 @@ const handleEditProfile = (e) => {
{/* Employee Information */} -

Employee Information

+

Employees (Headcount)

{ type="number" value={info.employeeInfo.emiratiMale} onChange={handleEmployeeChange('emiratiMale')} - disabled={loading} + disabled={true} /> { type="number" value={info.employeeInfo.nonEmiratiMale} onChange={handleEmployeeChange('nonEmiratiMale')} - disabled={loading} + disabled={true} /> { type="number" value={info.employeeInfo.emiratiFemale} onChange={handleEmployeeChange('emiratiFemale')} - disabled={loading} + disabled={true} /> { type="number" value={info.employeeInfo.nonEmiratiFemale} onChange={handleEmployeeChange('nonEmiratiFemale')} - disabled={loading} + disabled={true} /> { type="number" value={info.employeeInfo.totalEmployees} onChange={handleEmployeeChange('totalEmployees')} - disabled={loading} + disabled={true} /> { type="number" value={info.employeeInfo.totalEmirati} onChange={handleEmployeeChange('totalEmirati')} - disabled={loading} + disabled={true} />
diff --git a/ipi-survey-platform/src/components/survey/ProductData/ProductData.jsx b/ipi-survey-platform/src/components/survey/ProductData/ProductData.jsx index dc6842c..6163d9a 100644 --- a/ipi-survey-platform/src/components/survey/ProductData/ProductData.jsx +++ b/ipi-survey-platform/src/components/survey/ProductData/ProductData.jsx @@ -10,6 +10,7 @@ const caretDownSrc = '/assets/images/CaretDown-black.svg'; const clockIcon = '/assets/images/mingcute_time-line.svg'; const calendarIcon = '/assets/images/Duedate.svg'; const nextIcon = '/assets/images/mdi_page-next-outline.svg'; +const trashActiveSrc = '/assets/images/Trash - active.svg'; const Input = ({ placeholder = '', type = 'text', value = '', onChange = () => {}, required = false }) => { const [isFocused, setIsFocused] = React.useState(false); @@ -454,7 +455,7 @@ const ProductData = ({
-

Product Data

+

Products

)}
@@ -722,9 +724,9 @@ const ProductData = ({ />
-
+
- +
- +
- + { return [ { icon: establishmentIconSrc, label: 'Establishment Name', value: establishment.establishmentName }, { icon: establishmentIdIconSrc, label: 'Establishment ID', value: establishment.licenseNumber }, - { icon: emailIconSrc, label: 'Email', value: establishment.email }, + { icon: emailIconSrc, label: 'Email', value: establishment.establishment_contact_email }, { icon: emiratesIconSrc, label: 'Emirate', value: establishment.emirate }, ]; }; diff --git a/ipi-survey-platform/src/pages/Admin/configuration/EditCompanyProfile.jsx b/ipi-survey-platform/src/pages/Admin/configuration/EditCompanyProfile.jsx new file mode 100644 index 0000000..9387ab8 --- /dev/null +++ b/ipi-survey-platform/src/pages/Admin/configuration/EditCompanyProfile.jsx @@ -0,0 +1,1245 @@ +import React, { useState, useMemo, useCallback, useEffect, useRef } from "react"; +import { useNavigate, useParams } from 'react-router-dom'; +import { TextField, SelectField, PhoneField } from "@/components/common/FormControls"; +import Loader from "@/components/common/Loader"; +import { fetchEstablishmentDetail, updateEstablishment } from '@/services/establishments/establishmentService'; +import { fetchEmirates, fetchCityTowns } from '@/services/masters/masterService'; + +// Helper functions +const createEmptyProfile = () => ({ + // Add all form fields with empty/default values here + userProfileName: '', + userProfileEmail: '', + // Add other fields as needed +}); + +const mapApiEstablishmentToProfile = (apiData) => { + console.log('API Data to map:', apiData); + + // If the API response has a data property, use that + const data = apiData.data || apiData; + + // Map API response to form fields + return { + // User Profile (using first user from users array) + userProfileName: data.users?.[0]?.name || '', + userProfileEmail: data.users?.[0]?.email || '', + + // Identification Particulars + permanentFactoryCode: data.permanent_factory_code || '', + uniqueLicenseNumber: data.license_number || '', + industryCodeBusiness: data.isic_code || '', + industryCodeCurrent: data.isic_code || '', + + // Establishment Contact Details + contactName: data.factory_name || '', + contactAddress: data.establishment_address || '', + contactCityTown: data.establishment_city?.name || '', + contactCityTownId: data.establishment_city?.id || '', + contactEmirate: data.establishment_emirate?.name || '', + contactEmirateId: data.establishment_emirate?.id || '', + contactMakaniNumber: data.establishment_makani_number || '', + contactPersonName: data.establishment_contact_person_name || '', + contactMobileNumber: data.establishment_mobile_number || '', + contactEmail: data.establishment_contact_email || '', + contactPostalCode: data.establishment_postal_code || '', + contactPoBox: data.establishment_po_box || '', + contactWebsite: data.establishment_website || '', + + // Corporate/Head Office + corporateName: data.corporate_name || '', + corporateAddress: data.corporate_address || '', + corporateCityTown: data.corporate_city?.name || '', + corporateCityTownId: data.corporate_city?.id || '', + corporateEmirate: data.corporate_emirate?.name || '', + corporateEmirateId: data.corporate_emirate?.id || '', + corporateMakaniNumber: data.corporate_makani_number || '', + corporateContactPersonName: data.corporate_contact_person_name || '', + corporateMobileNumber: data.corporate_mobile_number || '', + corporateEmail: data.corporate_email || '', + corporatePostalCode: data.corporate_postal_code || '', + corporatePoBox: data.corporate_po_box || '', + corporateWebsite: data.corporate_website || '', + corporateSameAs: data.corporate_same_as_establishment || false, + + // Employment + employmentEmiratiMale: data.emirati_male || 0, + employmentEmiratiFemale: data.emirati_female || 0, + employmentNonEmiratiMale: data.non_emirati_male || 0, + employmentNonEmiratiFemale: data.non_emirati_female || 0, + }; +}; + +const contactToCorporateMap = { + contactName: 'corporateName', + contactAddress: 'corporateAddress', + contactCityTown: 'corporateCityTown', + contactEmirate: 'corporateEmirate', + contactCityTownId: 'corporateCityTownId', + contactEmirateId: 'corporateEmirateId', + contactMakaniNumber: 'corporateMakaniNumber', + contactPersonName: 'corporateContactPersonName', + contactMobileNumber: 'corporateMobileNumber', + contactEmail: 'corporateEmail', + contactPostalCode: 'corporatePostalCode', + contactPoBox: 'corporatePoBox', + contactWebsite: 'corporateWebsite', +}; + +const computeEmploymentTotals = (data) => { + const emiratiMale = parseInt(data.employmentEmiratiMale) || 0; + const nonEmiratiMale = parseInt(data.employmentNonEmiratiMale) || 0; + const emiratiFemale = parseInt(data.employmentEmiratiFemale) || 0; + const nonEmiratiFemale = parseInt(data.employmentNonEmiratiFemale) || 0; + + const totalEmployees = emiratiMale + nonEmiratiMale + emiratiFemale + nonEmiratiFemale; + const totalEmirati = emiratiMale + emiratiFemale; + + return { + employmentTotalEmployees: totalEmployees, + employmentTotalEmirati: totalEmirati + }; +}; + +const captureCorporateValues = (data) => { + const corporateData = {}; + Object.values(contactToCorporateMap).forEach(key => { + corporateData[key] = data[key]; + }); + return corporateData; +}; + +const EditCompanyProfile = ({ onClose: propOnClose }) => { + const navigate = useNavigate(); + const { id: establishmentId } = useParams(); + + // Define default onClose function that navigates to survey page + const onClose = propOnClose || (() => navigate('/survey')); + const [loading, setLoading] = useState(false); + const [form, setForm] = useState(createEmptyProfile()); + const [activeStep, setActiveStep] = useState(0); + const [fieldErrors, setFieldErrors] = useState({}); + const [passwordError, setPasswordError] = useState(""); + const [confirmError, setConfirmError] = useState(""); + const [passwordReuseError, setPasswordReuseError] = useState(""); + + // State for emirate and city options + const [emirateOptions, setEmirateOptions] = useState([]); + const [emirateLookup, setEmirateLookup] = useState({}); + const [contactCityOptions, setContactCityOptions] = useState([]); + const [corporateCityOptions, setCorporateCityOptions] = useState([]); + const initialSnapshotRef = useRef(null); + const corporateBackupRef = useRef(null); + + const formSteps = React.useMemo( + () => [ + { label: 'User Profile' }, + { label: 'Identification Particulars' }, + { label: 'Establishment Contact Details' }, + { label: 'Corporate / Head Office Contact' }, + { label: 'Employment in Establishment' }, + ], + [] + ); + + const requiredFieldsByStep = React.useMemo( + () => ({ + 0: [ + { field: 'userProfileName', label: 'Name' }, + { field: 'userProfileEmail', label: 'Email' }, + ], + 1: [ + { field: 'permanentFactoryCode', label: 'Permanent Factory Code' }, + { field: 'uniqueLicenseNumber', label: 'Unique License Number' }, + { field: 'industryCodeBusiness', label: 'Industry Code (Business Register)' }, + { field: 'industryCodeCurrent', label: 'Industry Code (Current Production)' }, + ], + 2: [ + { field: 'contactName', label: 'Name' }, + { field: 'contactAddress', label: 'Address' }, + { field: 'contactCityTown', label: 'City/Town' }, + { field: 'contactEmirate', label: 'Emirate' }, + { field: 'contactMakaniNumber', label: 'Makani Number' }, + { field: 'contactPersonName', label: 'Contact Person Name' }, + { field: 'contactMobileNumber', label: 'Mobile Number' }, + { field: 'contactEmail', label: 'Email' }, + ], + 3: [ + { field: 'corporateName', label: 'Name' }, + { field: 'corporateAddress', label: 'Address' }, + { field: 'corporateCityTown', label: 'City/Town' }, + { field: 'corporateEmirate', label: 'Emirate' }, + { field: 'corporateMakaniNumber', label: 'Makani Number' }, + { field: 'corporateContactPersonName', label: 'Contact Person Name' }, + { field: 'corporateMobileNumber', label: 'Mobile Number' }, + { field: 'corporateEmail', label: 'Email' }, + ], + 4: [ + { field: 'employmentEmiratiMale', label: 'Number of Emirati Male' }, + { field: 'employmentNonEmiratiMale', label: 'Number of Non-Emirati Male' }, + { field: 'employmentEmiratiFemale', label: 'Number of Emirati Female' }, + { field: 'employmentNonEmiratiFemale', label: 'Number of Non-Emirati Female' }, + ], + }), + [] + ); + + const validateStepFields = useCallback((stepIndex) => { + // Reset password reuse error when validating + setPasswordReuseError(""); + const requiredFields = requiredFieldsByStep[stepIndex] || []; + if (!requiredFields.length) return true; + + let valid = true; + setFieldErrors((prevErrors) => { + const nextErrors = { ...prevErrors }; + requiredFields.forEach(({ field, label }) => { + if (!form[field]) { + nextErrors[field] = `${label} is required.`; + valid = false; + } + }); + return nextErrors; + }); + return valid; + }, [form, requiredFieldsByStep]); + + const handleFormChange = useCallback((field, value) => { + // Handle city selection + if (field === 'contactCityTown') { + const foundCity = contactCityOptions.find(option => option.value === value || option.label === value); + setForm(prev => ({ + ...prev, + contactCityTown: foundCity?.name || '', + contactCityTownId: foundCity?.id || '' + })); + return; + } + + if (field === 'corporateCityTown') { + const foundCity = corporateCityOptions.find(option => option.value === value || option.label === value); + setForm(prev => ({ + ...prev, + corporateCityTown: foundCity?.name || '', + corporateCityTownId: foundCity?.id || '' + })); + return; + } + setForm((prev) => ({ ...prev, [field]: value })); + setFieldErrors((prev) => ({ ...prev, [field]: "" })); + + // Clear password errors when user starts typing + if (field === 'userProfilePassword') { + setPasswordError(""); + setPasswordReuseError(""); + } + if (field === 'userProfileConfirmPassword') { + setConfirmError(""); + } + }, []); + + const handleFormSubmit = async (e) => { + e.preventDefault(); + if (validateStepFields(activeStep)) { + if (activeStep < formSteps.length - 1) { + setActiveStep(activeStep + 1); + } else { + try { + setLoading(true); + + // Prepare the data for API + const establishmentData = { + factory_name: form.contactName, + establishment_address: form.contactAddress, + establishment_city: form.contactCityTownId, + establishment_emirate: form.contactEmirateId, + establishment_makani_number: form.contactMakaniNumber, + establishment_contact_person_name: form.contactPersonName, + establishment_mobile_number: form.contactMobileNumber, + establishment_contact_email: form.contactEmail, + establishment_postal_code: form.contactPostalCode, + establishment_po_box: form.contactPoBox, + establishment_website: form.contactWebsite, + + // Corporate/Head Office + corporate_name: form.corporateName, + corporate_address: form.corporateAddress, + corporate_city: form.corporateCityTownId, + corporate_emirate: form.corporateEmirateId, + corporate_makani_number: form.corporateMakaniNumber, + corporate_contact_person_name: form.corporateContactPersonName, + corporate_mobile_number: form.corporateMobileNumber, + corporate_email: form.corporateEmail, + corporate_postal_code: form.corporatePostalCode, + corporate_po_box: form.corporatePoBox, + corporate_website: form.corporateWebsite, + corporate_same_as_establishment: form.corporateSameAs, + + // Employment + emirati_male: form.employmentEmiratiMale || 0, + emirati_female: form.employmentEmiratiFemale || 0, + non_emirati_male: form.employmentNonEmiratiMale || 0, + non_emirati_female: form.employmentNonEmiratiFemale || 0, + }; + + console.log('Submitting establishment data:', { + establishmentId, + establishmentData + }); + + // If establishmentId exists, update the establishment + if (establishmentId) { + console.log('Updating establishment with ID:', establishmentId); + const response = await updateEstablishment(establishmentId, establishmentData); + console.log('Update response:', response); + + // Show success message + alert('Establishment updated successfully!'); + + // Redirect to the dashboard or previous page + navigate('/dashboard'); + } else { + // Handle case where no establishmentId is provided + console.error('No establishment ID provided for update'); + alert('Error: No establishment ID provided for update'); + } + + } catch (error) { + console.error('Error updating establishment:', error); + alert('Failed to update establishment. Please try again.'); + } finally { + setLoading(false); + } + } + } + }; + + const handleNext = useCallback(() => { + if (validateStepFields(activeStep)) { + if (activeStep < formSteps.length - 1) { + setActiveStep(activeStep + 1); + } + } + }, [activeStep, formSteps.length, validateStepFields]); + + const handlePrev = useCallback(() => { + if (activeStep > 0) setActiveStep(activeStep - 1); + }, [activeStep]); + + // Fetch establishment details when ID is provided + useEffect(() => { + const fetchData = async () => { + console.log('Establishment ID:', establishmentId); + + if (!establishmentId) { + console.log('No establishment ID provided'); + return; + } + + try { + setLoading(true); + console.log('Fetching establishment details for ID:', establishmentId); + + const response = await fetchEstablishmentDetail(establishmentId) + .then(res => { + console.log('Raw API Response:', res); + return res; + }) + .catch(error => { + console.error('API call failed:', { + message: error.message, + status: error.response?.status, + data: error.response?.data, + config: error.config + }); + throw error; + }); + + console.log('API Response:', response); + + if (!response) { + console.error('Empty response received'); + return; + } + + const mappedProfile = mapApiEstablishmentToProfile(response); + console.log('Mapped Profile:', mappedProfile); + + const formData = { + ...createEmptyProfile(), + ...mappedProfile, + apiId: establishmentId, + corporateSameAs: Boolean(mappedProfile.corporateSameAs) + }; + + console.log('Form Data before corporate same as:', formData); + + if (formData.corporateSameAs) { + Object.entries(contactToCorporateMap).forEach(([source, target]) => { + formData[target] = formData[source]; + }); + } + + const totals = computeEmploymentTotals(formData); + Object.assign(formData, totals); + + console.log('Final Form Data:', formData); + + setForm(formData); + initialSnapshotRef.current = formData; + corporateBackupRef.current = captureCorporateValues(formData); + + } catch (error) { + console.error('Failed to load establishment details:', { + error, + message: error.message, + response: error.response?.data, + status: error.response?.status + }); + } finally { + setLoading(false); + } + }; + + fetchData(); + }, [establishmentId]); + + // Load cities based on selected emirate + const loadCities = useCallback(async (emirateId, setCityOptions) => { + if (!emirateId) { + setCityOptions([]); + return; + } + + try { + const response = await fetchCityTowns({ emirateId: Number(emirateId) }); + const options = Array.isArray(response) ? response : (response.data || []); + + const formatted = options.map((option) => ({ + label: option.name || option.label, + value: String(option.id || option.value), + name: option.name || option.label, + id: String(option.id || option.value) + })); + + setCityOptions(formatted); + return formatted; + } catch (error) { + console.error('Failed to load cities:', error); + setCityOptions([]); + return []; + } + }, []); + + // Load emirates on component mount + useEffect(() => { + let cancelled = false; + const controller = new AbortController(); + + const loadEmirates = async () => { + try { + const options = await fetchEmirates({ signal: controller.signal }); + if (cancelled) return; + + const formatted = options.map((option) => ({ + label: option.name || option.label, + value: String(option.id || option.value), + name: option.name || option.label, + id: String(option.id || option.value) + })); + + const lookup = {}; + formatted.forEach((option) => { + lookup[option.value] = option.label; + }); + + setEmirateOptions(formatted); + setEmirateLookup(lookup); + } catch (error) { + if (cancelled) return; + console.error('Failed to load emirates:', error); + } + }; + + loadEmirates(); + + return () => { + cancelled = true; + controller.abort(); + }; + }, []); + + // Load contact cities when emirate changes + useEffect(() => { + const loadContactCities = async () => { + if (form.contactEmirateId) { + await loadCities(form.contactEmirateId, setContactCityOptions); + + // If we have a city ID but it's not in the options, try to find and add it + if (form.contactCityTownId && !contactCityOptions.some(city => city.id === form.contactCityTownId)) { + const cities = await loadCities(form.contactEmirateId, setContactCityOptions); + const currentCity = cities.find(city => city.id === form.contactCityTownId); + if (currentCity) { + setContactCityOptions(prev => [...prev, currentCity]); + } + } + } else { + setContactCityOptions([]); + } + }; + + loadContactCities(); + }, [form.contactEmirateId, form.contactCityTownId, loadCities]); + + // Load corporate cities when emirate changes + useEffect(() => { + const loadCorporateCities = async () => { + if (form.corporateEmirateId) { + await loadCities(form.corporateEmirateId, setCorporateCityOptions); + + // If we have a city ID but it's not in the options, try to find and add it + if (form.corporateCityTownId && !corporateCityOptions.some(city => city.id === form.corporateCityTownId)) { + const cities = await loadCities(form.corporateEmirateId, setCorporateCityOptions); + const currentCity = cities.find(city => city.id === form.corporateCityTownId); + if (currentCity) { + setCorporateCityOptions(prev => [...prev, currentCity]); + } + } + } else { + setCorporateCityOptions([]); + } + }; + + loadCorporateCities(); + }, [form.corporateEmirateId, form.corporateCityTownId, loadCities]); + + // Calculate totals when employment numbers change + useEffect(() => { + const totals = computeEmploymentTotals(form); + setForm(prev => ({ + ...prev, + ...totals + })); + }, [ + form.employmentEmiratiMale, + form.employmentNonEmiratiMale, + form.employmentEmiratiFemale, + form.employmentNonEmiratiFemale + ]); + + // Handle corporate same as establishment + useEffect(() => { + if (form.corporateSameAs) { + // Save current corporate values if this is the first time checking + if (!corporateBackupRef.current) { + corporateBackupRef.current = captureCorporateValues(form); + } + + // Copy contact details to corporate + const corporateUpdates = {}; + Object.entries(contactToCorporateMap).forEach(([source, target]) => { + corporateUpdates[target] = form[source]; + // Also copy the ID fields + if (source.endsWith('CityTown')) { + corporateUpdates[`${target}Id`] = form[`${source}Id`]; + } else if (source.endsWith('Emirate')) { + corporateUpdates[`${target}Id`] = form[`${source}Id`]; + } + }); + + setForm(prev => ({ + ...prev, + ...corporateUpdates + })); + } else if (corporateBackupRef.current) { + // Restore original corporate values + setForm(prev => ({ + ...prev, + ...corporateBackupRef.current + })); + corporateBackupRef.current = null; + } + }, [form.corporateSameAs, form.contactName, form.contactAddress, form.contactCityTown, form.contactEmirate, form.contactCityTownId, form.contactEmirateId]); + + const handleSave = async () => { + console.log("Submitted data:", form); + + try { + setLoading(true); + + // Prepare the data for API + const establishmentData = { + factory_name: form.contactName, + establishment_address: form.contactAddress, + establishment_city: form.contactCityTownId, + establishment_emirate: form.contactEmirateId, + establishment_makani_number: form.contactMakaniNumber, + establishment_contact_person_name: form.contactPersonName, + establishment_mobile_number: form.contactMobileNumber, + establishment_contact_email: form.contactEmail, + establishment_postal_code: form.contactPostalCode, + establishment_po_box: form.contactPoBox, + establishment_website: form.contactWebsite, + + // Corporate/Head Office + corporate_name: form.corporateName, + corporate_address: form.corporateAddress, + corporate_city: form.corporateCityTownId, + corporate_emirate: form.corporateEmirateId, + corporate_makani_number: form.corporateMakaniNumber, + corporate_contact_person_name: form.corporateContactPersonName, + corporate_mobile_number: form.corporateMobileNumber, + corporate_email: form.corporateEmail, + corporate_postal_code: form.corporatePostalCode, + corporate_po_box: form.corporatePoBox, + corporate_website: form.corporateWebsite, + corporate_same_as_establishment: form.corporateSameAs, + + // Employment + emirati_male: form.employmentEmiratiMale || 0, + emirati_female: form.employmentEmiratiFemale || 0, + non_emirati_male: form.employmentNonEmiratiMale || 0, + non_emirati_female: form.employmentNonEmiratiFemale || 0, + }; + + if (establishmentId) { + console.log('Updating establishment with ID:', establishmentId); + await updateEstablishment(establishmentId, establishmentData); + alert('Profile updated successfully!'); + onClose(); + } else { + console.error('No establishment ID provided for update'); + alert('Error: No establishment ID provided for update'); + } + } catch (error) { + console.error('Error saving profile:', error); + alert('Failed to update profile. Please try again.'); + } finally { + setLoading(false); + } + }; + + const renderStepContent = () => { + switch (activeStep) { + case 0: + return ( +
+
+

User Profile

+
+ handleFormChange("userProfileName", e.target.value)} + placeholder="Enter name" + width="100%" + required + error={fieldErrors.userProfileName} + /> + handleFormChange("userProfileEmail", e.target.value)} + placeholder="Enter email" + width="100%" + type="email" + required + error={fieldErrors.userProfileEmail} + /> +
+ handleFormChange("userProfilePassword", e.target.value)} + placeholder="Enter password" + width="100%" + type="password" + showToggle + className={passwordError || passwordReuseError ? 'border-red-500' : ''} + /> + {passwordError &&

{passwordError}

} + {passwordReuseError &&

{passwordReuseError}

} +
+
+ handleFormChange("userProfileConfirmPassword", e.target.value)} + placeholder="Confirm password" + width="100%" + type="password" + showToggle + className={confirmError ? 'border-red-500' : ''} + /> + {confirmError &&

{confirmError}

} +
+
+
+
+ ); + case 1: + return ( +
+
+

Identification Particulars

+
+ handleFormChange("permanentFactoryCode", e.target.value)} + placeholder="Enter Factory Code" + width="100%" + required + error={fieldErrors.permanentFactoryCode} + /> + handleFormChange("uniqueLicenseNumber", e.target.value)} + placeholder="Enter License Number" + width="100%" + required + error={fieldErrors.uniqueLicenseNumber} + /> + handleFormChange("industryCodeBusiness", e.target.value)} + placeholder="Enter Code" + width="100%" + required + error={fieldErrors.industryCodeBusiness} + /> + handleFormChange("industryCodeCurrent", e.target.value)} + placeholder="Enter Code" + width="100%" + required + error={fieldErrors.industryCodeCurrent} + /> +
+ handleFormChange("industryDescription", e.target.value)} + placeholder="Enter Description" + width="100%" + multiline + rows={3} + /> +
+
+
+
+ ); + case 2: + return ( +
+
+

Establishment Contact Details

+
+
+ handleFormChange("contactName", e.target.value)} + placeholder="Enter Name" + width="100%" + required + error={fieldErrors.contactName} + /> + handleFormChange("contactAddress", e.target.value)} + placeholder="Enter Address" + width="100%" + required + error={fieldErrors.contactAddress} + /> + { + const selectedValue = e.target.value; + const selectedEmirate = emirateOptions.find(opt => opt.value === selectedValue); + + // Update emirate fields + handleFormChange("contactEmirate", selectedEmirate?.name || ''); + handleFormChange("contactEmirateId", selectedEmirate?.id || ''); + + // Clear city fields + handleFormChange("contactCityTown", ''); + handleFormChange("contactCityTownId", ''); + + // Load cities for the selected emirate + if (selectedEmirate?.id) { + const cities = await loadCities(selectedEmirate.id, setContactCityOptions); + setContactCityOptions(cities); + } else { + setContactCityOptions([]); + } + }} + options={emirateOptions.map(opt => ({ + value: opt.value, + label: opt.label + }))} + placeholder="Select Emirate" + width="100%" + required + error={fieldErrors.contactEmirate} + /> + { + const selectedValue = e.target.value; + const selectedCity = contactCityOptions.find(opt => opt.value === selectedValue); + if (selectedCity) { + handleFormChange("contactCityTown", selectedCity.value); + } + }} + options={contactCityOptions.map(opt => ({ + value: opt.value, + label: opt.label + }))} + placeholder={form.contactEmirate ? "Select City/Town" : "Select emirate first"} + width="100%" + required + disabled={!form.contactEmirate} + error={fieldErrors.contactCityTown} + /> + handleFormChange("contactPostalCode", e.target.value)} + placeholder="Enter Postal Code" + width="100%" + /> + handleFormChange("contactPoBox", e.target.value)} + placeholder="Enter P.O. Box" + width="100%" + /> + handleFormChange("contactMakaniNumber", e.target.value)} + placeholder="Enter Makani Number" + width="100%" + required + error={fieldErrors.contactMakaniNumber} + /> + handleFormChange("contactPersonName", e.target.value)} + placeholder="Enter Contact Person Name" + width="100%" + required + error={fieldErrors.contactPersonName} + /> + handleFormChange("contactPersonDesignation", e.target.value)} + placeholder="Enter contact person designation" + width="100%" + /> + handleFormChange("contactMobileNumber", value)} + placeholder="Enter Mobile Number" + width="100%" + required + error={fieldErrors.contactMobileNumber} + /> + handleFormChange("contactEmail", e.target.value)} + placeholder="Enter Email" + width="100%" + type="email" + required + error={fieldErrors.contactEmail} + /> + + handleFormChange("contactWebsite", e.target.value)} + placeholder="Enter Website" + width="100%" + /> +
+
+ ); + case 3: + return ( +
+
+
+

Corporate/Head Office Contact

+
+ +
+{/*
*/} +
+ handleFormChange("corporateName", e.target.value)} + placeholder="Enter Name" + width="100%" + required + disabled={form.corporateSameAs} + error={fieldErrors.corporateName} + /> + handleFormChange("corporateAddress", e.target.value)} + placeholder="Enter Address" + width="100%" + required + disabled={form.corporateSameAs} + error={fieldErrors.corporateAddress} + /> + {form.corporateSameAs ? ( + <> + + + + ) : ( + <> + handleFormChange("corporateEmirate", e.target.value)} + options={emirateOptions.map(opt => ({ + value: opt.name, + label: opt.name + }))} + placeholder="Select Emirate" + width="100%" + required + error={fieldErrors.corporateEmirate} + /> + { + const selectedValue = e.target.value; + const selectedCity = corporateCityOptions.find(opt => opt.value === selectedValue); + if (selectedCity) { + handleFormChange("corporateCityTown", selectedCity.value); + } + }} + options={corporateCityOptions.map(opt => ({ + value: opt.value, + label: opt.label + }))} + placeholder={form.corporateEmirateId ? "Select City/Town" : "Select emirate first"} + width="100%" + required + disabled={!form.corporateEmirateId} + error={fieldErrors.corporateCityTown} + /> + + )} + handleFormChange("corporatePostalCode", e.target.value)} + placeholder="Enter Postal Code" + width="100%" + disabled={form.corporateSameAs} + /> + handleFormChange("corporatePoBox", e.target.value)} + placeholder="Enter P.O. Box" + width="100%" + disabled={form.corporateSameAs} + /> + handleFormChange("corporateMakaniNumber", e.target.value)} + placeholder="Enter Makani Number" + width="100%" + required + disabled={form.corporateSameAs} + error={fieldErrors.corporateMakaniNumber} + /> + handleFormChange("corporateContactPersonName", e.target.value)} + placeholder="Enter Contact Person Name" + width="100%" + required + disabled={form.corporateSameAs} + error={fieldErrors.corporateContactPersonName} + /> + handleFormChange("corporateContactPersonDesignation", e.target.value)} + placeholder="Enter contact person designation" + width="100%" + disabled={form.corporateSameAs} + /> + handleFormChange("corporateMobileNumber", value)} + placeholder="Enter Mobile Number" + width="100%" + required + disabled={form.corporateSameAs} + error={fieldErrors.corporateMobileNumber} + /> + handleFormChange("corporateEmail", e.target.value)} + placeholder="Enter Email" + width="100%" + type="email" + required + disabled={form.corporateSameAs} + error={fieldErrors.corporateEmail} + /> + handleFormChange("corporateWebsite", e.target.value)} + placeholder="Enter Website" + width="100%" + disabled={form.corporateSameAs} + /> +
+
+ ); + case 4: + return ( +
+
+

Employment in Establishment

+
+
+ handleFormChange("employmentEmiratiMale", e.target.value)} + placeholder="Enter Count" + width="100%" + type="number" + required + error={fieldErrors.employmentEmiratiMale} + /> + handleFormChange("employmentNonEmiratiMale", e.target.value)} + placeholder="Enter Count" + width="100%" + type="number" + required + error={fieldErrors.employmentNonEmiratiMale} + /> + handleFormChange("employmentEmiratiFemale", e.target.value)} + placeholder="Enter Count" + width="100%" + type="number" + required + error={fieldErrors.employmentEmiratiFemale} + /> + handleFormChange("employmentNonEmiratiFemale", e.target.value)} + placeholder="Enter Count" + width="100%" + type="number" + required + error={fieldErrors.employmentNonEmiratiFemale} + /> + + +
+
+ ); + default: + return null; + } + }; + + return ( +
+
+ {loading && } + + {/* Header */} +
+
+

Edit Company Profile

+
+ +
+ + {/* Body */} +
+ +
+
+ {renderStepContent()} +
+
+
+ + {/* Footer */} +
+
+
+ {loading ? ( + + + + + + Saving profile… + + ) : ( + + )} +
+ {activeStep === formSteps.length - 1 ? ( +
+ + +
+ ) : ( + + )} +
+
+
+
+ ); +}; + +export default EditCompanyProfile; diff --git a/ipi-survey-platform/src/pages/Survey/Survey.jsx b/ipi-survey-platform/src/pages/Survey/Survey.jsx index d90d2cf..82181ef 100644 --- a/ipi-survey-platform/src/pages/Survey/Survey.jsx +++ b/ipi-survey-platform/src/pages/Survey/Survey.jsx @@ -6,6 +6,7 @@ import EstablishmentInfo from '@/components/survey/EstablishmentInfo/Establishme import HeaderBar from '@/components/layout/HeaderBar'; import ProductData from '@/components/survey/ProductData/ProductData'; import ReviewSubmit from '@/components/survey/ReviewSubmit/ReviewSubmit'; +import BreadcrumbVector from '/assets/images/Breadcrumb-vector.svg'; const checkCircleActiveSrc = '/assets/images/CircleFrame.svg'; @@ -154,6 +155,7 @@ const Survey = () => { licenseNumber: ensureString(detail?.license_number) || prev.licenseNumber, isicCode: ensureString(detail?.isic_code) || prev.isicCode, emirate: ensureString(detail?.establishment_emirate?.name) || ensureString(detail?.emirate) || prev.emirate, + establishment_contact_email: ensureString(detail?.establishment_contact_email) || prev.establishment_contact_email || '', employeeInfo: { ...prev.employeeInfo, emiratiMale: ensureString(detail?.emirati_male) || prev.employeeInfo.emiratiMale, @@ -470,12 +472,57 @@ const Survey = () => {
+ {/* Breadcrumb Navigation */} + + {/* Step Header Bar */} -
+
{/* Stepper container */} -
+
{/* Step 1 */}
{ Establishment Information
+ + {/* Divider line */} +
= 2 ? 'bg-[#B68A35]' : 'bg-[#C3C6CB]'}`}>
{/* Step 2 */}
{ Product Data
+ + {/* Divider line after Step 2 */} +
= 3 ? 'bg-[#B68A35]' : 'bg-[#C3C6CB]'}`}>
{/* Step 3 */}