diff --git a/ipi-survey-platform/src/assets/images/CaretDown.svg b/ipi-survey-platform/src/assets/images/CaretDown.svg index 7163c83..58ed51c 100644 --- a/ipi-survey-platform/src/assets/images/CaretDown.svg +++ b/ipi-survey-platform/src/assets/images/CaretDown.svg @@ -1,3 +1,3 @@ - + diff --git a/ipi-survey-platform/src/assets/images/Active - User.svg b/ipi-survey-platform/src/assets/images/active-user.svg similarity index 100% rename from ipi-survey-platform/src/assets/images/Active - User.svg rename to ipi-survey-platform/src/assets/images/active-user.svg diff --git a/ipi-survey-platform/src/assets/images/CaretDown - active.svg b/ipi-survey-platform/src/assets/images/caretdown-active.svg similarity index 100% rename from ipi-survey-platform/src/assets/images/CaretDown - active.svg rename to ipi-survey-platform/src/assets/images/caretdown-active.svg diff --git a/ipi-survey-platform/src/assets/images/Inactive - user.svg b/ipi-survey-platform/src/assets/images/inactive-user.svg similarity index 100% rename from ipi-survey-platform/src/assets/images/Inactive - user.svg rename to ipi-survey-platform/src/assets/images/inactive-user.svg diff --git a/ipi-survey-platform/src/assets/images/PencilSimple - inactive.svg b/ipi-survey-platform/src/assets/images/pencilsimple-inactive.svg similarity index 100% rename from ipi-survey-platform/src/assets/images/PencilSimple - inactive.svg rename to ipi-survey-platform/src/assets/images/pencilsimple-inactive.svg diff --git a/ipi-survey-platform/src/components/admin/AdminHeader.jsx b/ipi-survey-platform/src/components/admin/AdminHeader.jsx index bc3c62a..379eddd 100644 --- a/ipi-survey-platform/src/components/admin/AdminHeader.jsx +++ b/ipi-survey-platform/src/components/admin/AdminHeader.jsx @@ -1,15 +1,15 @@ import React from 'react'; import { NavLink, useNavigate } from 'react-router-dom'; -import Logo from '../../assets/images/FCSCLogo.svg'; +import Logo from '../../assets/images/fcsclogo.svg'; import DashboardIconActive from '../../assets/images/cuida_dashboard-outline.svg'; import DashboardIconInactive from '../../assets/images/cuida_dashboard-outline-inactive.svg'; -import CheckCircleActive from '../../assets/images/CheckCircle-active.svg'; +import CheckCircleActive from '../../assets/images/checkcircle-active.svg'; import ConfigActive from '../../assets/images/configrationicon-active.svg'; import ConfigInactive from '../../assets/images/configrationicon-inactive.svg'; -import UserActive from '../../assets/images/User-active.svg'; -import UserInactive from '../../assets/images/User-inactive.svg'; +import UserActive from '../../assets/images/user-active.svg'; +import UserInactive from '../../assets/images/user-inactive.svg'; import ManageSubmissionInactive from '../../assets/images/managesubmission - inactive.svg'; -import BellIconAsset from '../../assets/images/Bell.svg'; +import BellIconAsset from '../../assets/images/bell.svg'; const NavItem = ({ label, to, iconActive, iconInactive, end = false }) => ( @@ -196,7 +203,10 @@ export const SelectField = ({ : focused ? focusBorderColors[variant] : idleBorderColors[variant] || idleBorderColors.default; - if (variant === 'toolbar') { + if (hasError) { + inputStyle.backgroundColor = '#FEF2F2'; + inputStyle.color = '#B91C1C'; + } else if (variant === 'toolbar') { inputStyle.color = hasValue && value !== 'All' && value !== 'Status' && value !== 'Year' && value !== 'Quarter' && value !== 'Emirates' ? '#232528' : '#5F646D'; } else { inputStyle.color = hasValue ? '#232528' : '#232528'; @@ -307,7 +317,7 @@ export const PhoneField = ({ alignItems: 'center', border: `2px solid ${borderColor}`, borderRadius: '4px', - backgroundColor: readOnly ? '#F9FAFB' : '#FFFFFF', + backgroundColor: readOnly ? '#F9FAFB' : hasError ? '#FEF2F2' : '#FFFFFF', transition: 'border-color 0.2s ease', height: '40px', paddingRight: '8px', @@ -319,7 +329,7 @@ export const PhoneField = ({ paddingLeft: '12px', paddingRight: '24px', fontSize: '14px', - color: '#232528', + color: hasError ? '#B91C1C' : '#232528', appearance: 'none', WebkitAppearance: 'none', MozAppearance: 'none', @@ -332,7 +342,7 @@ export const PhoneField = ({ outline: 'none', background: 'transparent', fontSize: '14px', - color: '#232528', + color: hasError ? '#B91C1C' : '#232528', padding: '0 0 0 8px', }; const arrowStyle = { @@ -436,7 +446,7 @@ export const DateField = ({ wrapperStyle.width = typeof width === 'number' ? `${width}px` : width; } const inputStyle = { - ...baseInputStyle, + ...(baseInputStyles?.default || {}), ...style, color: value ? '#232528' : '#232528', borderColor: focused ? '#92722A' : '#CBA344', diff --git a/ipi-survey-platform/src/components/common/Loader.jsx b/ipi-survey-platform/src/components/common/Loader.jsx index 8d1c8b6..61b7ac5 100644 --- a/ipi-survey-platform/src/components/common/Loader.jsx +++ b/ipi-survey-platform/src/components/common/Loader.jsx @@ -1 +1,22 @@ +import React from 'react'; + +const sizeClassMap = { + sm: 'h-4 w-4 border-2', + md: 'h-6 w-6 border-2', + lg: 'h-10 w-10 border-4', +}; + +const Loader = ({ size = 'md', label = '', className = '' }) => { + const sizeClass = sizeClassMap[size] || sizeClassMap.md; + return ( +
+ + {label ? {label} : null} +
+ ); +}; + +export default Loader; diff --git a/ipi-survey-platform/src/components/common/Table.jsx b/ipi-survey-platform/src/components/common/Table.jsx index 0b0ea8f..2752f2f 100644 --- a/ipi-survey-platform/src/components/common/Table.jsx +++ b/ipi-survey-platform/src/components/common/Table.jsx @@ -1,8 +1,8 @@ import React from 'react'; -import CaretLeftIcon from '../../assets/images/CaretLeft.svg'; -import CaretRightIcon from '../../assets/images/CaretRight.svg'; -import CaretDoubleLeftIcon from '../../assets/images/CaretDoubleLeft.svg'; -import CaretDoubleRightIcon from '../../assets/images/CaretDoubleRight.svg'; +import CaretLeftIcon from '../../assets/images/caretleft.svg'; +import CaretRightIcon from '../../assets/images/caretright.svg'; +import CaretDoubleLeftIcon from '../../assets/images/caretdoubleleft.svg'; +import CaretDoubleRightIcon from '../../assets/images/caretdoubleright.svg'; // Generic, reusable table // Props: diff --git a/ipi-survey-platform/src/components/dashboard/SubmissionHistory.jsx b/ipi-survey-platform/src/components/dashboard/SubmissionHistory.jsx index 6f22162..127c0f1 100644 --- a/ipi-survey-platform/src/components/dashboard/SubmissionHistory.jsx +++ b/ipi-survey-platform/src/components/dashboard/SubmissionHistory.jsx @@ -2,7 +2,7 @@ import React from 'react'; import { useNavigate } from 'react-router-dom'; import Table from '../common/Table'; import SearchIcon from '../../assets/images/material-symbols_search-rounded.svg'; -import CaretDown from '../../assets/images/CaretDown.svg'; +import CaretDown from '../../assets/images/caretdown.svg'; const getStatusClass = (status) => { const normalized = String(status || '').toLowerCase(); diff --git a/ipi-survey-platform/src/components/layout/HeaderBar.jsx b/ipi-survey-platform/src/components/layout/HeaderBar.jsx index 33c0d9b..95bea4e 100644 --- a/ipi-survey-platform/src/components/layout/HeaderBar.jsx +++ b/ipi-survey-platform/src/components/layout/HeaderBar.jsx @@ -1,7 +1,7 @@ import React from 'react'; import { NavLink, useNavigate } from 'react-router-dom'; -import Logo from '../../assets/images/FCSCLogo.svg'; -import SurveyIconActive from '../../assets/images/Vector.svg'; +import Logo from '../../assets/images/fcsclogo.svg'; +import SurveyIconActive from '../../assets/images/vector.svg'; import SurveyIconInactive from '../../assets/images/vectorblack.svg'; import DashboardIconActive from '../../assets/images/cuida_dashboard-outline.svg'; import DashboardIconInactive from '../../assets/images/cuida_dashboard-outline-inactive.svg'; diff --git a/ipi-survey-platform/src/components/survey/EstablishmentInfo/EstablishmentInfo.jsx b/ipi-survey-platform/src/components/survey/EstablishmentInfo/EstablishmentInfo.jsx index 9362384..cbe0b8d 100644 --- a/ipi-survey-platform/src/components/survey/EstablishmentInfo/EstablishmentInfo.jsx +++ b/ipi-survey-platform/src/components/survey/EstablishmentInfo/EstablishmentInfo.jsx @@ -1,6 +1,5 @@ import React from 'react'; import CaretDown from '../../../assets/images/caretdown.svg'; -import PrimaryButton from '../../../assets/images/primarybutton.svg'; import BackVendor from '../../../assets/images/backvector.svg'; const Field = ({ label, placeholder = '', type = 'text', value = '', onChange = () => {}, disabled = false }) => ( diff --git a/ipi-survey-platform/src/components/survey/ProductData/ProductData.jsx b/ipi-survey-platform/src/components/survey/ProductData/ProductData.jsx index 0aef6a5..250c489 100644 --- a/ipi-survey-platform/src/components/survey/ProductData/ProductData.jsx +++ b/ipi-survey-platform/src/components/survey/ProductData/ProductData.jsx @@ -5,7 +5,7 @@ import { fetchProducts, fetchUnits, } from '../../../services/masters/masterService.js'; -import CaretDown from '../../../assets/images/caretdown.svg'; +import CaretDown from '../../../assets/images/caretdown-black.svg'; const Input = ({ placeholder = '', type = 'text', value = '', onChange = () => {} }) => ( (
diff --git a/ipi-survey-platform/src/pages/Admin/ValidationReview.jsx b/ipi-survey-platform/src/pages/Admin/ValidationReview.jsx index d03bd15..be147cf 100644 --- a/ipi-survey-platform/src/pages/Admin/ValidationReview.jsx +++ b/ipi-survey-platform/src/pages/Admin/ValidationReview.jsx @@ -2,8 +2,8 @@ import React from 'react'; import { Link, useNavigate, useParams } from 'react-router-dom'; import AdminHeader from '../../components/admin/AdminHeader'; import CaretUp from '../../assets/images/caret-up.svg'; -import EstablishmentIcon from '../../assets/images/Establishment.svg'; -import EstablishmentIdIcon from '../../assets/images/Establishmentid.svg'; +import EstablishmentIcon from '../../assets/images/establishment.svg'; +import EstablishmentIdIcon from '../../assets/images/establishmentid.svg'; import EmailIcon from '../../assets/images/emailid.svg'; import EmiratesIcon from '../../assets/images/emirates.svg'; import TotalEmployeesIcon from '../../assets/images/totalemployess.svg'; diff --git a/ipi-survey-platform/src/pages/Admin/Validations.jsx b/ipi-survey-platform/src/pages/Admin/Validations.jsx index 4f4987d..d6bb35d 100644 --- a/ipi-survey-platform/src/pages/Admin/Validations.jsx +++ b/ipi-survey-platform/src/pages/Admin/Validations.jsx @@ -3,7 +3,7 @@ import { Link, useNavigate } from 'react-router-dom'; import AdminHeader from '../../components/admin/AdminHeader'; import Table from '../../components/common/Table'; import SearchIcon from '../../assets/images/material-symbols_search-rounded.svg'; -import DownloadIcon from '../../assets/images/DownloadSimple.svg'; +import DownloadIcon from '../../assets/images/downloadsimple.svg'; import CaretUp from '../../assets/images/caret-up.svg'; import { SelectField } from '../../components/common/FormControls'; import { getSubmissions } from '../../services/admin/submission.js'; diff --git a/ipi-survey-platform/src/pages/Admin/configuration/AdminUsers.jsx b/ipi-survey-platform/src/pages/Admin/configuration/AdminUsers.jsx index 9fbb3f3..d3497a9 100644 --- a/ipi-survey-platform/src/pages/Admin/configuration/AdminUsers.jsx +++ b/ipi-survey-platform/src/pages/Admin/configuration/AdminUsers.jsx @@ -1,15 +1,15 @@ import React from 'react'; import Table from '../../../components/common/Table'; import SearchIcon from '../../../assets/images/material-symbols_search-rounded.svg'; -import ExportIcon from '../../../assets/images/DownloadSimple.svg'; +import ExportIcon from '../../../assets/images/downloadsimple.svg'; import AddIcon from '../../../assets/images/ic_baseline-plus.svg'; -import PencilActive from '../../../assets/images/PencilSimple.svg'; -import PencilInactive from '../../../assets/images/PencilSimple - inactive.svg'; -import TrashActive from '../../../assets/images/Trash - active.svg'; -import TrashInactive from '../../../assets/images/Trash - Inactive.svg'; -import AdminUserIcon from '../../../assets/images/UserGear.svg'; -import ActiveUserIcon from '../../../assets/images/Active - User.svg'; -import InactiveUserIcon from '../../../assets/images/Inactive - user.svg'; +import PencilActive from '../../../assets/images/pencilsimple.svg'; +import PencilInactive from '../../../assets/images/pencilsimple-inactive.svg'; +import TrashActive from '../../../assets/images/trash - active.svg'; +import TrashInactive from '../../../assets/images/trash - inactive.svg'; +import AdminUserIcon from '../../../assets/images/usergear.svg'; +import ActiveUserIcon from '../../../assets/images/active-user.svg'; +import InactiveUserIcon from '../../../assets/images/inactive-user.svg'; import ResetPasswordIcon from '../../../assets/images/hugeicons_reset-password.svg'; import ResetPasswordInactiveIcon from '../../../assets/images/hugeicons_reset-password-inactive.svg'; diff --git a/ipi-survey-platform/src/pages/Admin/configuration/CompanyProfile.jsx b/ipi-survey-platform/src/pages/Admin/configuration/CompanyProfile.jsx index b5a8429..19451ae 100644 --- a/ipi-survey-platform/src/pages/Admin/configuration/CompanyProfile.jsx +++ b/ipi-survey-platform/src/pages/Admin/configuration/CompanyProfile.jsx @@ -1,6 +1,8 @@ - import React from 'react'; +import React from 'react'; import Table from '../../../components/common/Table'; +import Loader from '../../../components/common/Loader'; import { TextField, SelectField, PhoneField } from '../../../components/common/FormControls'; +import { fetchEmirates, fetchCityTowns } from '../../../services/masters/masterService'; import { createEstablishment, fetchEstablishments, @@ -9,12 +11,12 @@ import { deleteEstablishment, } from '../../../services/establishments/establishmentService'; import SearchIcon from '../../../assets/images/material-symbols_search-rounded.svg'; -import DownloadIcon from '../../../assets/images/DownloadSimple.svg'; +import DownloadIcon from '../../../assets/images/downloadsimple.svg'; import AddIcon from '../../../assets/images/ic_baseline-plus.svg'; -import PencilActive from '../../../assets/images/PencilSimple.svg'; -import PencilInactive from '../../../assets/images/PencilSimple - inactive.svg'; -import TrashActive from '../../../assets/images/Trash - active.svg'; -import TrashInactive from '../../../assets/images/Trash - Inactive.svg'; +import PencilActive from '../../../assets/images/pencilsimple.svg'; +import PencilInactive from '../../../assets/images/pencilsimple-inactive.svg'; +import TrashActive from '../../../assets/images/trash - active.svg'; +import TrashInactive from '../../../assets/images/trash - inactive.svg'; import ResetPasswordActive from '../../../assets/images/hugeicons_reset-password.svg'; import ResetPasswordInactive from '../../../assets/images/hugeicons_reset-password-inactive.svg'; import DeleteIcon from '../../../assets/images/delete.svg'; @@ -37,27 +39,6 @@ const validatePasswordComplexity = (password) => { return ''; }; -const emirateOptions = [ - { label: 'Abu Dhabi', value: 'Abu Dhabi' }, - { label: 'Dubai', value: 'Dubai' }, - { label: 'Sharjah', value: 'Sharjah' }, - { label: 'Ajman', value: 'Ajman' }, - { label: 'Umm Al Quwain', value: 'Umm Al Quwain' }, - { label: 'Ras Al Khaimah', value: 'Ras Al Khaimah' }, - { label: 'Fujairah', value: 'Fujairah' }, -]; - -const cityOptions = [ - { label: 'Abu Dhabi', value: 'Abu Dhabi' }, - { label: 'Al Ain', value: 'Al Ain' }, - { label: 'Dubai', value: 'Dubai' }, - { label: 'Sharjah', value: 'Sharjah' }, - { label: 'Ajman', value: 'Ajman' }, - { label: 'Umm Al Quwain', value: 'Umm Al Quwain' }, - { label: 'Ras Al Khaimah', value: 'Ras Al Khaimah' }, - { label: 'Fujairah', value: 'Fujairah' }, -]; - const countryCodeOptions = [{ label: '+971', value: '+971' }]; const WEBSITE_URL_PATTERN = /^(https?:\/\/)?([\w-]+\.)+[\w-]{2,}(\/[^\s]*)?$/i; @@ -108,7 +89,9 @@ const createEmptyProfile = () => ({ contactName: '', contactAddress: '', contactCityTown: '', + contactCityTownId: '', contactEmirate: '', + contactEmirateId: '', contactPostalCode: '', contactPoBox: '', contactMakaniNumber: '', @@ -123,7 +106,9 @@ const createEmptyProfile = () => ({ corporateName: '', corporateAddress: '', corporateCityTown: '', + corporateCityTownId: '', corporateEmirate: '', + corporateEmirateId: '', corporatePostalCode: '', corporatePoBox: '', corporateMakaniNumber: '', @@ -140,163 +125,164 @@ const createEmptyProfile = () => ({ employmentNonEmiratiFemale: '', employmentTotalEmployees: '', employmentTotalEmirati: '', + createdById: '', }); -const companyProfilesSeed = [ - { - ...createEmptyProfile(), - establishmentName: 'CASCADE MARINE FOODS LLC', - emirate: 'Sharjah', - isicCode: '2098', - establishmentId: 'MSCensus-23-04-001276', - products: '10', - totalEmployees: '300', - createdBy: 'Amend (Owner)', - createdOn: '18/10/2025', - lastUpdated: 'Omar', - contactName: 'CASCADE MARINE FOODS LLC', - contactEmirate: 'Sharjah', - corporateName: 'CASCADE MARINE FOODS LLC', - }, - { - ...createEmptyProfile(), - establishmentName: 'Khazan Meat Factory', - emirate: 'Sharjah', - isicCode: '1098', - establishmentId: 'MSCensus-23-05-002829', - products: '6', - totalEmployees: '100', - createdBy: 'Sara (Admin)', - createdOn: '18/10/2025', - lastUpdated: 'Abdul', - contactName: 'Khazan Meat Factory', - contactEmirate: 'Sharjah', - corporateName: 'Khazan Meat Factory', - }, - { - ...createEmptyProfile(), - establishmentName: 'Spinneys Fresh Food Industries L.L.C', - emirate: 'Dubai', - isicCode: '3198', - establishmentId: 'MSCensus-Dubai-1407', - products: '8', - totalEmployees: '40', - createdBy: 'Shaik (Admin)', - createdOn: '18/10/2025', - lastUpdated: 'Abdul', - contactName: 'Spinneys Fresh Food Industries L.L.C', - contactEmirate: 'Dubai', - corporateName: 'Spinneys Fresh Food Industries L.L.C', - }, - { - ...createEmptyProfile(), - establishmentName: 'Freshly Frozen Foods Factory L.L.C', - emirate: 'Dubai', - isicCode: '2098', - establishmentId: 'MSCensus-Dubai-906', - products: '4', - totalEmployees: '50', - createdBy: 'Abdul (Manager)', - createdOn: '18/10/2025', - lastUpdated: 'Abdul', - contactName: 'Freshly Frozen Foods Factory L.L.C', - contactEmirate: 'Dubai', - corporateName: 'Freshly Frozen Foods Factory L.L.C', - }, - { - ...createEmptyProfile(), - establishmentName: 'Sahar Food Industry (L.L.C)', - emirate: 'Dubai', - isicCode: '1095', - establishmentId: 'MSCensus-Dubai-472', - products: '8', - totalEmployees: '80', - createdBy: 'Amend (Owner)', - createdOn: '18/10/2025', - lastUpdated: 'Abdul', - contactName: 'Sahar Food Industry (L.L.C)', - contactEmirate: 'Dubai', - corporateName: 'Sahar Food Industry (L.L.C)', - }, - { - ...createEmptyProfile(), - establishmentName: 'Continental Food Processing LLC', - emirate: 'Ajman', - isicCode: '0035', - establishmentId: 'MSCensus-23-06-005496', - products: '5', - totalEmployees: '400', - createdBy: 'Sara (Admin)', - createdOn: '18/10/2025', - lastUpdated: 'Abdul', - contactName: 'Continental Food Processing LLC', - contactEmirate: 'Ajman', - corporateName: 'Continental Food Processing LLC', - }, - { - ...createEmptyProfile(), - establishmentName: 'Al Khazna Poultry Farm', - emirate: 'Abu Dhabi', - isicCode: '0986', - establishmentId: 'MSCensus-23-05-002320', - products: '7', - totalEmployees: '800', - createdBy: 'Sara (Admin)', - createdOn: '18/10/2025', - lastUpdated: 'Fathima', - contactName: 'Al Khazna Poultry Farm', - contactEmirate: 'Abu Dhabi', - corporateName: 'Al Khazna Poultry Farm', - }, - { - ...createEmptyProfile(), - establishmentName: 'Diamond Meat Processing L.L.C', - emirate: 'Abu Dhabi', - isicCode: '8766', - establishmentId: 'MSCensus-23-05-002899', - products: '7', - totalEmployees: '300', - createdBy: 'Sara (Admin)', - createdOn: '18/10/2025', - lastUpdated: 'Abdul', - contactName: 'Diamond Meat Processing L.L.C', - contactEmirate: 'Abu Dhabi', - corporateName: 'Diamond Meat Processing L.L.C', - }, - { - ...createEmptyProfile(), - establishmentName: 'Alliance Foods Co L.L.C', - emirate: 'Abu Dhabi', - isicCode: '9883', - establishmentId: 'MSCensus-Dubai-128', - products: '7', - totalEmployees: '200', - createdBy: 'Amend (Owner)', - createdOn: '18/10/2025', - lastUpdated: 'Abdul', - contactName: 'Alliance Foods Co L.L.C', - contactEmirate: 'Abu Dhabi', - corporateName: 'Alliance Foods Co L.L.C', - }, - { - ...createEmptyProfile(), - establishmentName: 'Krustasia Foods L.L.C', - emirate: 'Dubai', - isicCode: '9986', - establishmentId: 'MSCensus-23-05-002320', - products: '8', - totalEmployees: '500', - createdBy: 'Sara (Admin)', - createdOn: '18/10/2025', - lastUpdated: 'Fathima', - contactName: 'Krustasia Foods L.L.C', - contactEmirate: 'Dubai', - corporateName: 'Krustasia Foods L.L.C', - }, -]; +// const companyProfilesSeed = [ +// { +// ...createEmptyProfile(), +// establishmentName: 'CASCADE MARINE FOODS LLC', +// emirate: 'Sharjah', +// isicCode: '2098', +// establishmentId: 'MSCensus-23-04-001276', +// products: '10', +// totalEmployees: '300', +// createdBy: 'Amend (Owner)', +// createdOn: '18/10/2025', +// lastUpdated: 'Omar', +// contactName: 'CASCADE MARINE FOODS LLC', +// contactEmirate: 'Sharjah', +// corporateName: 'CASCADE MARINE FOODS LLC', +// }, +// { +// ...createEmptyProfile(), +// establishmentName: 'Khazan Meat Factory', +// emirate: 'Sharjah', +// isicCode: '1098', +// establishmentId: 'MSCensus-23-05-002829', +// products: '6', +// totalEmployees: '100', +// createdBy: 'Sara (Admin)', +// createdOn: '18/10/2025', +// lastUpdated: 'Abdul', +// contactName: 'Khazan Meat Factory', +// contactEmirate: 'Sharjah', +// corporateName: 'Khazan Meat Factory', +// }, +// { +// ...createEmptyProfile(), +// establishmentName: 'Spinneys Fresh Food Industries L.L.C', +// emirate: 'Dubai', +// isicCode: '3198', +// establishmentId: 'MSCensus-Dubai-1407', +// products: '8', +// totalEmployees: '40', +// createdBy: 'Shaik (Admin)', +// createdOn: '18/10/2025', +// lastUpdated: 'Abdul', +// contactName: 'Spinneys Fresh Food Industries L.L.C', +// contactEmirate: 'Dubai', +// corporateName: 'Spinneys Fresh Food Industries L.L.C', +// }, +// { +// ...createEmptyProfile(), +// establishmentName: 'Freshly Frozen Foods Factory L.L.C', +// emirate: 'Dubai', +// isicCode: '2098', +// establishmentId: 'MSCensus-Dubai-906', +// products: '4', +// totalEmployees: '50', +// createdBy: 'Abdul (Manager)', +// createdOn: '18/10/2025', +// lastUpdated: 'Abdul', +// contactName: 'Freshly Frozen Foods Factory L.L.C', +// contactEmirate: 'Dubai', +// corporateName: 'Freshly Frozen Foods Factory L.L.C', +// }, +// { +// ...createEmptyProfile(), +// establishmentName: 'Sahar Food Industry (L.L.C)', +// emirate: 'Dubai', +// isicCode: '1095', +// establishmentId: 'MSCensus-Dubai-472', +// products: '8', +// totalEmployees: '80', +// createdBy: 'Amend (Owner)', +// createdOn: '18/10/2025', +// lastUpdated: 'Abdul', +// contactName: 'Sahar Food Industry (L.L.C)', +// contactEmirate: 'Dubai', +// corporateName: 'Sahar Food Industry (L.L.C)', +// }, +// { +// ...createEmptyProfile(), +// establishmentName: 'Continental Food Processing LLC', +// emirate: 'Ajman', +// isicCode: '0035', +// establishmentId: 'MSCensus-23-06-005496', +// products: '5', +// totalEmployees: '400', +// createdBy: 'Sara (Admin)', +// createdOn: '18/10/2025', +// lastUpdated: 'Abdul', +// contactName: 'Continental Food Processing LLC', +// contactEmirate: 'Ajman', +// corporateName: 'Continental Food Processing LLC', +// }, +// { +// ...createEmptyProfile(), +// establishmentName: 'Al Khazna Poultry Farm', +// emirate: 'Abu Dhabi', +// isicCode: '0986', +// establishmentId: 'MSCensus-23-05-002320', +// products: '7', +// totalEmployees: '800', +// createdBy: 'Sara (Admin)', +// createdOn: '18/10/2025', +// lastUpdated: 'Fathima', +// contactName: 'Al Khazna Poultry Farm', +// contactEmirate: 'Abu Dhabi', +// corporateName: 'Al Khazna Poultry Farm', +// }, +// { +// ...createEmptyProfile(), +// establishmentName: 'Diamond Meat Processing L.L.C', +// emirate: 'Abu Dhabi', +// isicCode: '8766', +// establishmentId: 'MSCensus-23-05-002899', +// products: '7', +// totalEmployees: '300', +// createdBy: 'Sara (Admin)', +// createdOn: '18/10/2025', +// lastUpdated: 'Abdul', +// contactName: 'Diamond Meat Processing L.L.C', +// contactEmirate: 'Abu Dhabi', +// corporateName: 'Diamond Meat Processing L.L.C', +// }, +// { +// ...createEmptyProfile(), +// establishmentName: 'Alliance Foods Co L.L.C', +// emirate: 'Abu Dhabi', +// isicCode: '9883', +// establishmentId: 'MSCensus-Dubai-128', +// products: '7', +// totalEmployees: '200', +// createdBy: 'Amend (Owner)', +// createdOn: '18/10/2025', +// lastUpdated: 'Abdul', +// contactName: 'Alliance Foods Co L.L.C', +// contactEmirate: 'Abu Dhabi', +// corporateName: 'Alliance Foods Co L.L.C', +// }, +// { +// ...createEmptyProfile(), +// establishmentName: 'Krustasia Foods L.L.C', +// emirate: 'Dubai', +// isicCode: '9986', +// establishmentId: 'MSCensus-23-05-002320', +// products: '8', +// totalEmployees: '500', +// createdBy: 'Sara (Admin)', +// createdOn: '18/10/2025', +// lastUpdated: 'Fathima', +// contactName: 'Krustasia Foods L.L.C', +// contactEmirate: 'Dubai', +// }, +// ]; const CompanyProfile = () => { - const [profiles, setProfiles] = React.useState(companyProfilesSeed); + const [profiles, setProfiles] = React.useState([]); + const [isLoading, setIsLoading] = React.useState(false); const [form, setForm] = React.useState(createEmptyProfile()); const [modalMode, setModalMode] = React.useState(null); const [editingRow, setEditingRow] = React.useState(null); @@ -306,6 +292,8 @@ const CompanyProfile = () => { const [currentPage, setCurrentPage] = React.useState(1); const [pageSize, setPageSize] = React.useState(pageSizeOptions[0]); const [searchTerm, setSearchTerm] = React.useState(''); + const [selectedEmirateFilter, setSelectedEmirateFilter] = React.useState(''); + const [selectedStatusFilter, setSelectedStatusFilter] = React.useState(''); const [debouncedSearch, setDebouncedSearch] = React.useState(''); const [sortConfig, setSortConfig] = React.useState({ field: 'establishmentName', direction: 'asc' }); const [activeStep, setActiveStep] = React.useState(0); @@ -316,12 +304,29 @@ const CompanyProfile = () => { const [saveWarning, setSaveWarning] = React.useState(false); const [saveError, setSaveError] = React.useState(''); const [toast, setToast] = React.useState(null); + const [emirateOptions, setEmirateOptions] = React.useState([]); + const [emirateLookup, setEmirateLookup] = React.useState({}); + const [contactCityOptions, setContactCityOptions] = React.useState([]); + const [corporateCityOptions, setCorporateCityOptions] = React.useState([]); const [fieldErrors, setFieldErrors] = React.useState({}); const [isDirty, setIsDirty] = React.useState(false); const initialSnapshotRef = React.useRef(createEmptyProfile()); const toastTimeoutRef = React.useRef(null); const [isDeletingApi, setIsDeletingApi] = React.useState(false); + const showToast = React.useCallback((type, message) => { + if (!message) return; + if (toastTimeoutRef.current) { + window.clearTimeout(toastTimeoutRef.current); + toastTimeoutRef.current = null; + } + setToast({ type, message }); + toastTimeoutRef.current = window.setTimeout(() => { + setToast(null); + toastTimeoutRef.current = null; + }, 3000); + }, []); + const computeEmploymentTotals = React.useCallback((nextForm) => { const emiratiMale = Number(nextForm.employmentEmiratiMale) || 0; const emiratiFemale = Number(nextForm.employmentEmiratiFemale) || 0; @@ -562,16 +567,6 @@ const CompanyProfile = () => { required error={fieldErrors.contactAddress} /> - { required error={fieldErrors.contactEmirate} /> + + { error={fieldErrors.corporateAddress} readOnly={form.corporateSameAs} /> - { error={fieldErrors.corporateEmirate} readOnly={form.corporateSameAs} /> + + { 'Created By', renderSortableHeader('Created on', 'createdOn'), renderSortableHeader('Last Updated', 'lastUpdated'), + 'Status', 'Actions', ]; @@ -999,7 +1013,8 @@ const CompanyProfile = () => { base[7] = 152; // Created By base[8] = 148; // Created on base[9] = 136; // Last Updated - base[10] = 119; // Actions + base[10] = 120; // Status + base[11] = 119; // Actions return base; }, [headers.length]); @@ -1008,7 +1023,9 @@ const CompanyProfile = () => { contactName: 'corporateName', contactAddress: 'corporateAddress', contactCityTown: 'corporateCityTown', + contactCityTownId: 'corporateCityTownId', contactEmirate: 'corporateEmirate', + contactEmirateId: 'corporateEmirateId', contactPostalCode: 'corporatePostalCode', contactPoBox: 'corporatePoBox', contactMakaniNumber: 'corporateMakaniNumber', @@ -1133,6 +1150,24 @@ const CompanyProfile = () => { return items; }, [filteredProfiles, sortConfig]); + const renderStatusBadge = React.useCallback((status) => { + const normalized = typeof status === 'string' ? status.trim().toLowerCase() : ''; + const isActiveStatus = normalized !== 'inactive'; + const label = isActiveStatus ? 'Active' : 'Inactive'; + const baseClasses = + 'inline-flex items-center justify-center px-3 py-1 text-xs font-medium rounded-md border'; + const activeClasses = 'text-[#1A7F37] bg-[#ECFDF3] border-[#ABEFC6]'; + const inactiveClasses = 'text-[#344054] bg-[#F8F9FC] border-[#D0D5DD]'; + return ( + + {label} + + ); + }, []); + const displayedRows = sortedProfiles.map((item) => { const isEditing = editingRow !== null && profiles[editingRow]?.establishmentId === item.establishmentId; @@ -1150,6 +1185,7 @@ const CompanyProfile = () => { item.createdBy, item.createdOn, item.lastUpdated, + renderStatusBadge(item.status), (
- @@ -1851,19 +2182,25 @@ const CompanyProfile = () => {
- + {isLoading ? ( +
+ +
+ ) : ( +
+ )} {modalMode && (
diff --git a/ipi-survey-platform/src/pages/Admin/configuration/Establishment.jsx b/ipi-survey-platform/src/pages/Admin/configuration/Establishment.jsx index d7efdab..7742848 100644 --- a/ipi-survey-platform/src/pages/Admin/configuration/Establishment.jsx +++ b/ipi-survey-platform/src/pages/Admin/configuration/Establishment.jsx @@ -2,12 +2,12 @@ import React from 'react'; import Table from '../../../components/common/Table'; import { TextField, SelectField } from '../../../components/common/FormControls'; import SearchIcon from '../../../assets/images/material-symbols_search-rounded.svg'; -import ExportIcon from '../../../assets/images/DownloadSimple.svg'; +import ExportIcon from '../../../assets/images/downloadsimple.svg'; import AddIcon from '../../../assets/images/ic_baseline-plus.svg'; -import PencilActive from '../../../assets/images/PencilSimple.svg'; -import PencilInactive from '../../../assets/images/PencilSimple - inactive.svg'; -import TrashActive from '../../../assets/images/Trash - active.svg'; -import TrashInactive from '../../../assets/images/Trash - Inactive.svg'; +import PencilActive from '../../../assets/images/pencilsimple.svg'; +import PencilInactive from '../../../assets/images/pencilsimple-inactive.svg'; +import TrashActive from '../../../assets/images/trash - active.svg'; +import TrashInactive from '../../../assets/images/trash - inactive.svg'; const establishmentsSeed = [ { diff --git a/ipi-survey-platform/src/pages/Admin/configuration/IsicHsCodes.jsx b/ipi-survey-platform/src/pages/Admin/configuration/IsicHsCodes.jsx index fdef260..0044b95 100644 --- a/ipi-survey-platform/src/pages/Admin/configuration/IsicHsCodes.jsx +++ b/ipi-survey-platform/src/pages/Admin/configuration/IsicHsCodes.jsx @@ -1,12 +1,12 @@ import React from 'react'; import Table from '../../../components/common/Table'; -import DownloadIcon from '../../../assets/images/DownloadSimple.svg'; -import UploadImportIcon from '../../../assets/images/Upload-import.svg'; +import DownloadIcon from '../../../assets/images/downloadsimple.svg'; +import UploadImportIcon from '../../../assets/images/upload-import.svg'; import AddIcon from '../../../assets/images/ic_baseline-plus.svg'; -import PencilActive from '../../../assets/images/PencilSimple.svg'; -import PencilInactive from '../../../assets/images/PencilSimple - inactive.svg'; -import TrashActive from '../../../assets/images/Trash - active.svg'; -import TrashInactive from '../../../assets/images/Trash - Inactive.svg'; +import PencilActive from '../../../assets/images/pencilsimple.svg'; +import PencilInactive from '../../../assets/images/pencilsimple-inactive.svg'; +import TrashActive from '../../../assets/images/trash - active.svg'; +import TrashInactive from '../../../assets/images/trash - inactive.svg'; import DeleteIcon from '../../../assets/images/delete.svg'; import StatusBadge from '../../../components/common/StatusBadge'; import { TextField, SelectField } from '../../../components/common/FormControls'; diff --git a/ipi-survey-platform/src/pages/Admin/configuration/QuarterlyWindows.jsx b/ipi-survey-platform/src/pages/Admin/configuration/QuarterlyWindows.jsx index 9ab5737..9fe44f1 100644 --- a/ipi-survey-platform/src/pages/Admin/configuration/QuarterlyWindows.jsx +++ b/ipi-survey-platform/src/pages/Admin/configuration/QuarterlyWindows.jsx @@ -1,15 +1,15 @@ import React from 'react'; import Table from '../../../components/common/Table'; -import DownloadIcon from '../../../assets/images/DownloadSimple.svg'; +import DownloadIcon from '../../../assets/images/downloadsimple.svg'; import AddIcon from '../../../assets/images/ic_baseline-plus.svg'; -import PencilActive from '../../../assets/images/PencilSimple.svg'; -import PencilInactive from '../../../assets/images/PencilSimple - inactive.svg'; -import TrashActive from '../../../assets/images/Trash - active.svg'; -import TrashInactive from '../../../assets/images/Trash - Inactive.svg'; +import PencilActive from '../../../assets/images/pencilsimple.svg'; +import PencilInactive from '../../../assets/images/pencilsimple-inactive.svg'; +import TrashActive from '../../../assets/images/trash - active.svg'; +import TrashInactive from '../../../assets/images/trash - inactive.svg'; import DeleteIcon from '../../../assets/images/delete.svg'; -import CaretDownActive from '../../../assets/images/CaretDown - active.svg'; +import CaretDownActive from '../../../assets/images/caretdown-active.svg'; import SearchIcon from '../../../assets/images/material-symbols_search-rounded.svg'; -import CaretDown from '../../../assets/images/CaretDown-black.svg'; +import CaretDown from '../../../assets/images/caretdown-black.svg'; import { TextField, SelectField, DateField } from '../../../components/common/FormControls'; import StatusBadge from '../../../components/common/StatusBadge'; diff --git a/ipi-survey-platform/src/pages/Admin/configuration/UnitMaster.jsx b/ipi-survey-platform/src/pages/Admin/configuration/UnitMaster.jsx index 886eb38..aa8969e 100644 --- a/ipi-survey-platform/src/pages/Admin/configuration/UnitMaster.jsx +++ b/ipi-survey-platform/src/pages/Admin/configuration/UnitMaster.jsx @@ -1,16 +1,16 @@ import React from 'react'; import Table from '../../../components/common/Table'; -import DownloadIcon from '../../../assets/images/DownloadSimple.svg'; +import DownloadIcon from '../../../assets/images/downloadsimple.svg'; import AddIcon from '../../../assets/images/ic_baseline-plus.svg'; -import PencilActive from '../../../assets/images/PencilSimple.svg'; -import PencilInactive from '../../../assets/images/PencilSimple - inactive.svg'; -import TrashActive from '../../../assets/images/Trash - active.svg'; -import TrashInactive from '../../../assets/images/Trash - Inactive.svg'; +import PencilActive from '../../../assets/images/pencilsimple.svg'; +import PencilInactive from '../../../assets/images/pencilsimple-inactive.svg'; +import TrashActive from '../../../assets/images/trash - active.svg'; +import TrashInactive from '../../../assets/images/trash - inactive.svg'; import DeleteIcon from '../../../assets/images/delete.svg'; import StatusBadge from '../../../components/common/StatusBadge'; import { TextField, SelectField } from '../../../components/common/FormControls'; -import CaretDownIcon from '../../../assets/images/CaretDown - active.svg'; -import RectangleIcon from '../../../assets/images/Rectangle.svg'; +import CaretDownIcon from '../../../assets/images/caretdown-active.svg'; +import RectangleIcon from '../../../assets/images/rectangle.svg'; import CheckboxIcon from '../../../assets/images/checkbox.svg'; const createEmptyUnitForm = () => ({ diff --git a/ipi-survey-platform/src/pages/ChangePassword/ChangePassword.jsx b/ipi-survey-platform/src/pages/ChangePassword/ChangePassword.jsx index 4d2d294..93c1ed6 100644 --- a/ipi-survey-platform/src/pages/ChangePassword/ChangePassword.jsx +++ b/ipi-survey-platform/src/pages/ChangePassword/ChangePassword.jsx @@ -1,5 +1,5 @@ import React from "react"; -import Logo from "../../assets/images/FCSCLogo.svg"; +import Logo from "../../assets/images/fcsclogo.svg"; import { useNavigate, useLocation } from "react-router-dom"; import apiClient from "../../services/api/apiClient.js"; diff --git a/ipi-survey-platform/src/pages/ForgotPassword/ForgotPassword.jsx b/ipi-survey-platform/src/pages/ForgotPassword/ForgotPassword.jsx index 99a912b..c90930a 100644 --- a/ipi-survey-platform/src/pages/ForgotPassword/ForgotPassword.jsx +++ b/ipi-survey-platform/src/pages/ForgotPassword/ForgotPassword.jsx @@ -1,5 +1,5 @@ import React from 'react'; -import Logo from '../../assets/images/FCSCLogo.svg'; +import Logo from '../../assets/images/fcsclogo.svg'; import { useNavigate } from 'react-router-dom'; import { requestPasswordReset } from '../../services/auth/authService.js'; diff --git a/ipi-survey-platform/src/pages/History/History.jsx b/ipi-survey-platform/src/pages/History/History.jsx index 7c1b854..0bddc6e 100644 --- a/ipi-survey-platform/src/pages/History/History.jsx +++ b/ipi-survey-platform/src/pages/History/History.jsx @@ -4,7 +4,7 @@ import Table from '../../components/common/Table'; import HeaderBar from '../../components/layout/HeaderBar'; import { fetchSubmissionHistory } from '../../services/submissions/submissionService.js'; import SearchIcon from '../../assets/images/material-symbols_search-rounded.svg'; -import CaretDown from '../../assets/images/CaretDown.svg'; +import CaretDown from '../../assets/images/caretdown.svg'; const Badge = ({ variant = 'default', children }) => { const styles = { diff --git a/ipi-survey-platform/src/pages/Login/Login.jsx b/ipi-survey-platform/src/pages/Login/Login.jsx index e131bf0..36cdb51 100644 --- a/ipi-survey-platform/src/pages/Login/Login.jsx +++ b/ipi-survey-platform/src/pages/Login/Login.jsx @@ -1,5 +1,5 @@ import React from 'react'; -import Logo from '../../assets/images/FCSCLogo.svg'; +import Logo from '../../assets/images/fcsclogo.svg'; import { useNavigate } from 'react-router-dom'; import { login } from '../../services/auth/authService.js'; diff --git a/ipi-survey-platform/src/pages/PublicContactForm.jsx b/ipi-survey-platform/src/pages/PublicContactForm.jsx index 2aadab5..ef8425e 100644 --- a/ipi-survey-platform/src/pages/PublicContactForm.jsx +++ b/ipi-survey-platform/src/pages/PublicContactForm.jsx @@ -1,5 +1,5 @@ import React, { useState, useEffect } from "react"; -import Logo from "../assets/images/FCSCLogo.svg"; +import Logo from "../assets/images/fcsclogo.svg"; import { useNavigate } from "react-router-dom"; import apiClient from "../services/api/apiClient.js"; diff --git a/ipi-survey-platform/src/pages/Survey/Survey.jsx b/ipi-survey-platform/src/pages/Survey/Survey.jsx index 28c5480..86b75b8 100644 --- a/ipi-survey-platform/src/pages/Survey/Survey.jsx +++ b/ipi-survey-platform/src/pages/Survey/Survey.jsx @@ -6,7 +6,7 @@ import EstablishmentInfo from '../../components/survey/EstablishmentInfo/Establi import HeaderBar from '../../components/layout/HeaderBar'; import ProductData from '../../components/survey/ProductData/ProductData'; import ReviewSubmit from '../../components/survey/ReviewSubmit/ReviewSubmit'; -import CheckCircleActive from '../../assets/images/CircleFrame.svg'; +import CheckCircleActive from '../../assets/images/circleframe.svg'; const createEmptyProduct = (id) => ({ id, diff --git a/ipi-survey-platform/src/services/establishments/establishmentService.js b/ipi-survey-platform/src/services/establishments/establishmentService.js index dc15d1c..a4adc76 100644 --- a/ipi-survey-platform/src/services/establishments/establishmentService.js +++ b/ipi-survey-platform/src/services/establishments/establishmentService.js @@ -4,8 +4,38 @@ import resolveEstablishmentId from '../utils/establishment.js'; const dashboardEndpoint = '/establishment_dashboard'; const establishmentsEndpoint = '/establishments'; -export const fetchEstablishments = async (config = {}) => { - const response = await getRequest(establishmentsEndpoint, config); +const buildEstablishmentQueryParams = (params = {}) => { + const { + page, + limit, + search, + emirateId, + isicCode, + status, + sortBy, + sortOrder, + export: exportFormat, + } = params; + + const query = {}; + if (page !== undefined) query.page = page; + if (limit !== undefined) query.limit = limit; + if (search) query.search = search; + if (emirateId) query.emirate_id = emirateId; + if (isicCode) query.isic_code = isicCode; + if (status) query.status = status; + if (sortBy) query.sort_by = sortBy; + if (sortOrder) query.sort_order = sortOrder; + if (exportFormat) query.export = exportFormat; + return query; +}; + +export const fetchEstablishments = async ({ params, ...config } = {}) => { + const query = buildEstablishmentQueryParams(params); + const response = await getRequest(establishmentsEndpoint, { + ...config, + params: { ...(config.params || {}), ...query }, + }); return response.data; }; diff --git a/ipi-survey-platform/src/services/masters/masterService.js b/ipi-survey-platform/src/services/masters/masterService.js index f60f5df..944cdde 100644 --- a/ipi-survey-platform/src/services/masters/masterService.js +++ b/ipi-survey-platform/src/services/masters/masterService.js @@ -5,6 +5,8 @@ const endpoints = { zeroTargetReasons: '/zero_target_reason', products: '/products', units: '/unit_master', + emirates: '/emirates', + cityTowns: '/city-towns', }; const extractReasons = (payload) => { @@ -72,6 +74,38 @@ const toUnitOption = (item) => { return null; }; +const toEmirateOption = (item) => { + if (item === undefined || item === null) return null; + if (typeof item === 'string' || typeof item === 'number') { + const value = toStringOrNull(item); + return value ? { label: value, value } : null; + } + if (typeof item === 'object') { + const id = toStringOrNull(item.id ?? item.value ?? item.code); + const name = toStringOrNull(item.name ?? item.label ?? item.description); + const finalLabel = name ?? id; + if (!finalLabel) return null; + return { label: finalLabel, value: id ?? finalLabel, raw: item }; + } + return null; +}; + +const toCityOption = (item) => { + if (item === undefined || item === null) return null; + if (typeof item === 'string' || typeof item === 'number') { + const value = toStringOrNull(item); + return value ? { label: value, value } : null; + } + if (typeof item === 'object') { + const id = toStringOrNull(item.id ?? item.value ?? item.code); + const name = toStringOrNull(item.name ?? item.label ?? item.description); + const finalLabel = name ?? id; + if (!finalLabel) return null; + return { label: finalLabel, value: id ?? finalLabel, raw: item }; + } + return null; +}; + export const getVariationReasons = async (config = {}) => { const response = await getRequest(endpoints.variationReasons, config); return response.data; @@ -116,6 +150,30 @@ export const fetchUnits = async ({ signal } = {}) => { return list.map(toUnitOption).filter(Boolean); }; +export const getEmirates = async (config = {}) => { + const response = await getRequest(endpoints.emirates, config); + return response.data; +}; + +export const fetchEmirates = async ({ signal } = {}) => { + const data = await getEmirates({ signal }); + const list = extractReasons(data); + return list.map(toEmirateOption).filter(Boolean); +}; + +export const getCityTowns = async (emirateId, config = {}) => { + const params = { ...(config.params || {}), emirate_id: emirateId }; + const response = await getRequest(endpoints.cityTowns, { ...config, params }); + return response.data; +}; + +export const fetchCityTowns = async ({ emirateId, signal } = {}) => { + if (!emirateId) return []; + const data = await getCityTowns(emirateId, { signal }); + const list = extractReasons(data); + return list.map(toCityOption).filter(Boolean); +}; + export default { getVariationReasons, fetchVariationReasons, @@ -125,4 +183,8 @@ export default { fetchProducts, getUnits, fetchUnits, + getEmirates, + fetchEmirates, + getCityTowns, + fetchCityTowns, };