Admin Dashboard updated design & API integration done

This commit is contained in:
Senthamilselvi 2025-10-29 16:47:09 +05:30
commit 00d403ea6f
30 changed files with 783 additions and 324 deletions

View File

@ -1,3 +1,3 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M16.6922 7.94254L10.4422 14.1925C10.3842 14.2506 10.3152 14.2967 10.2393 14.3282C10.1635 14.3597 10.0821 14.3758 10 14.3758C9.91788 14.3758 9.83655 14.3597 9.76067 14.3282C9.6848 14.2967 9.61587 14.2506 9.55782 14.1925L3.30782 7.94254C3.19055 7.82526 3.12466 7.6662 3.12466 7.50035C3.12466 7.3345 3.19055 7.17544 3.30782 7.05816C3.4251 6.94088 3.58416 6.875 3.75001 6.875C3.91586 6.875 4.07492 6.94088 4.1922 7.05816L10 12.8668L15.8078 7.05816C15.8659 7.00009 15.9348 6.95403 16.0107 6.9226C16.0866 6.89117 16.1679 6.875 16.25 6.875C16.3321 6.875 16.4135 6.89117 16.4893 6.9226C16.5652 6.95403 16.6341 7.00009 16.6922 7.05816C16.7503 7.11623 16.7963 7.18517 16.8278 7.26104C16.8592 7.33691 16.8754 7.41823 16.8754 7.50035C16.8754 7.58247 16.8592 7.66379 16.8278 7.73966C16.7963 7.81553 16.7503 7.88447 16.6922 7.94254Z" fill="#92722A"/>
<path d="M16.6925 7.94229L10.4425 14.1923C10.3845 14.2504 10.3156 14.2965 10.2397 14.328C10.1638 14.3594 10.0825 14.3756 10.0003 14.3756C9.91821 14.3756 9.83688 14.3594 9.76101 14.328C9.68514 14.2965 9.61621 14.2504 9.55816 14.1923L3.30816 7.94229C3.19088 7.82502 3.125 7.66596 3.125 7.5001C3.125 7.33425 3.19088 7.17519 3.30816 7.05792C3.42544 6.94064 3.5845 6.87476 3.75035 6.87476C3.9162 6.87476 4.07526 6.94064 4.19253 7.05792L10.0003 12.8665L15.8082 7.05792C15.8662 6.99985 15.9352 6.95378 16.011 6.92236C16.0869 6.89093 16.1682 6.87476 16.2503 6.87476C16.3325 6.87476 16.4138 6.89093 16.4897 6.92236C16.5655 6.95378 16.6345 6.99985 16.6925 7.05792C16.7506 7.11598 16.7967 7.18492 16.8281 7.26079C16.8595 7.33666 16.8757 7.41798 16.8757 7.5001C16.8757 7.58223 16.8595 7.66354 16.8281 7.73941C16.7967 7.81528 16.7506 7.88422 16.6925 7.94229Z" fill="#92722A"/>
</svg>

Before

Width:  |  Height:  |  Size: 949 B

After

Width:  |  Height:  |  Size: 967 B

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 967 B

After

Width:  |  Height:  |  Size: 967 B

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 1013 B

After

Width:  |  Height:  |  Size: 1013 B

View File

@ -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 }) => (
<NavLink

View File

@ -1,5 +1,5 @@
import React from 'react';
import CaretDownActive from '../../assets/images/CaretDown - active.svg';
import CaretDownActive from '../../assets/images/caretdown-active.svg';
import CalendarIcon from '../../assets/images/uil_calender.svg';
const baseInputStyles = {
@ -89,11 +89,18 @@ export const TextField = ({
: focused && !readOnly
? focusBorderColors[variant]
: idleBorderColors[variant] || idleBorderColors.default;
if (hasError) {
inputStyle.backgroundColor = '#FEF2F2';
inputStyle.color = '#B91C1C';
}
if (!hasError && variant !== 'toolbar') {
inputStyle.color = '#232528';
}
if (readOnly) {
inputStyle.backgroundColor = '#F9FAFB';
}
if (variant !== 'toolbar') {
inputStyle.color = '#232528';
if (!hasError && variant === 'toolbar') {
inputStyle.color = '#5F646D';
}
return (
<div style={wrapperStyle} className="w-full">
@ -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',

View File

@ -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 (
<div className={`flex items-center gap-3 ${className}`} role="status" aria-live="polite">
<span
className={`inline-block ${sizeClass} rounded-full border-solid border-[#92722A] border-t-transparent animate-spin`}
/>
{label ? <span className="text-sm text-[#4B5563]">{label}</span> : null}
</div>
);
};
export default Loader;

View File

@ -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:

View File

@ -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();

View File

@ -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';

View File

@ -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 }) => (

View File

@ -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 = () => {} }) => (
<input

View File

@ -1,6 +1,6 @@
import React from 'react';
import Table from '../../common/Table';
import BackVendor from '../../../assets/images/backvector.svg';
import BackVendor from '../../../assets/images/caretdown-black.svg';
const Card = ({ title, children }) => (
<div className="bg-white w-full rounded-lg shadow-sm ring-1 ring-gray-200">

View File

@ -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';

View File

@ -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';

View File

@ -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';

View File

@ -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 = [
{

View File

@ -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';

View File

@ -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';

View File

@ -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 = () => ({

View File

@ -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";

View File

@ -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';

View File

@ -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 = {

View File

@ -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';

View File

@ -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";

View File

@ -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,

View File

@ -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;
};

View File

@ -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,
};