Added changes in edit profile

This commit is contained in:
Malini 2026-01-06 16:08:06 +05:30
parent 1b48b6019f
commit 8ddfe28897
4 changed files with 242 additions and 143 deletions

View File

@ -33,6 +33,19 @@ const Input = ({ placeholder = '', type = 'text', value = '', onChange = () => {
borderColor = 'border-[#92722A]';
}
// Handle input change with validation
const handleChange = (e) => {
if (type === 'number') {
// Only allow numbers and empty string
const newValue = e.target.value;
if (newValue === '' || /^\d+$/.test(newValue)) {
onChange(e);
}
} else {
onChange(e);
}
};
// Prevent wheel event from changing the number input value
const handleWheel = (e) => {
if (type === 'number') {
@ -40,18 +53,28 @@ const Input = ({ placeholder = '', type = 'text', value = '', onChange = () => {
}
};
// Prevent typing non-numeric characters in number inputs
const handleKeyPress = (e) => {
if (type === 'number' && !/^\d$/.test(e.key) && e.key !== 'Backspace' && e.key !== 'Delete' && e.key !== 'Tab') {
e.preventDefault();
}
};
return (
<div className="relative">
<input
type={type}
type={type === 'number' ? 'text' : type}
inputMode={type === 'number' ? 'numeric' : undefined}
pattern={type === 'number' ? '[0-9]*' : undefined}
placeholder={placeholder}
value={value}
onChange={onChange}
onChange={handleChange}
onKeyPress={handleKeyPress}
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
onWheel={handleWheel}
required={required}
className={`block w-full h-10 rounded-md border-2 ${borderColor} focus:ring-0 px-4 text-sm ${bgColor} transition-colors [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none`}
className={`block w-full h-10 rounded-md border-2 ${borderColor} focus:ring-0 px-4 text-sm ${bgColor} transition-colors`}
/>
</div>
);

View File

@ -67,10 +67,16 @@ const ManageSubmissions = () => {
const [error, setError] = React.useState(null);
const [search, setSearch] = React.useState('');
const [year, setYear] = React.useState('');
const [quarter, setQuarter] = React.useState('All');
// Function to get current quarter (1-4)
const getCurrentQuarter = () => {
const month = new Date().getMonth();
return `Q${Math.floor(month / 3) + 1}`;
};
const [quarter, setQuarter] = React.useState(getCurrentQuarter());
const [emirate, setEmirate] = React.useState('All');
const [status, setStatus] = React.useState('All');
const [selectedQuarter, setSelectedQuarter] = React.useState('All');
const [selectedQuarter, setSelectedQuarter] = React.useState(getCurrentQuarter());
const [selectedYear, setSelectedYear] = React.useState(new Date().getFullYear().toString());
const [currentPage, setCurrentPage] = React.useState(1);
const [toast, setToast] = React.useState(null);

View File

@ -657,11 +657,11 @@ const CompanyProfile = () => {
const formSteps = React.useMemo(
() => [
{ label: 'User Profile' },
{ label: 'Identification Particulars' },
{ label: 'Establishment Contact Details' },
{ label: 'Profile' },
{ label: 'Details' },
{ label: 'Contact Details' },
{ label: 'Products' },
{ label: 'Employment in Establishment' },
{ label: 'Employment Details' },
],
[]
);
@ -676,7 +676,7 @@ const CompanyProfile = () => {
{ 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)' },
{ field: 'industryCodeProduction', label: 'Industry Code (Current Production)' },
],
2: [
{ field: 'contactName', label: 'Name' },
@ -902,7 +902,7 @@ const CompanyProfile = () => {
return (
<div className="space-y-4">
<div className="space-y-2">
<h4 className="text-[16px] font-semibold text-[#232528] mb-2">User Profile</h4>
<h4 className="text-[16px] font-semibold text-[#232528] mb-2">Profile</h4>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 items-start">
<TextField
label="Name"
@ -986,7 +986,7 @@ const CompanyProfile = () => {
<div className="space-y-4">
<div className="space-y-2">
<h4 className="text-[16px] font-semibold text-[#232528]">
Identification Particulars
Details
</h4>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
@ -1017,6 +1017,8 @@ const CompanyProfile = () => {
onChange={handleFormChange('industryCodeBusiness')}
placeholder="Enter Code"
width="100%"
required
error={fieldErrors.industryCodeBusiness}
readOnly={modalMode === 'view'}
/>
@ -1026,6 +1028,8 @@ const CompanyProfile = () => {
onChange={handleFormChange('industryCodeProduction')}
placeholder="Enter Code"
width="100%"
required
error={fieldErrors.industryCodeProduction}
readOnly={modalMode === 'view'}
/>
</div>
@ -1077,7 +1081,7 @@ const CompanyProfile = () => {
return (
<div className="space-y-4">
<div>
<h4 className="text-[16px] font-semibold text-[#232528]">Establishment Contact Details</h4>
<h4 className="text-[16px] font-semibold text-[#232528]">Contact Details</h4>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<TextField
@ -1220,7 +1224,7 @@ const CompanyProfile = () => {
case 4:
return (
<div className="space-y-4">
<h4 className="text-[16px] font-semibold text-[#232528] mb-4">Employment in Establishment</h4>
<h4 className="text-[16px] font-semibold text-[#232528] mb-4">Employment Details</h4>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<TextField
label="Number of Emirati Male"
@ -1368,47 +1372,79 @@ const CompanyProfile = () => {
</div>
</div>
{/* Selected Products Panel */}
<div className="bg-white rounded-lg border border-[#E5E7EB] overflow-hidden">
<div className="bg-[#F9FAFB] px-4 py-3 border-b border-[#E5E7EB] flex justify-between items-center">
<h5 className="text-sm font-medium text-[#111827]">Selected Products</h5>
{selectedProducts.length > 0 && (
<span className="bg-[#FEF3C7] text-[#92400E] text-xs font-medium px-2 py-0.5 rounded-full">
{selectedProducts.length} selected
</span>
)}
</div>
<div className="p-4">
{selectedProducts.length > 0 ? (
<ul className="divide-y divide-[#E5E7EB] max-h-96 overflow-y-auto">
{selectedProducts.map((product) => (
<li key={product.id} className="p-3 hover:bg-[#F9FAFB] flex justify-between items-center">
<div>
<div className="text-sm font-medium text-[#111827]">
{product.hs_code || product.hsCode || ''}
{(product.hs_code || product.hsCode) ? ' - ' : ''}
{product.product_name || product.productName || product.label || 'Unnamed Product'}
</div>
</div>
{modalMode !== 'view' && (
<button
type="button"
onClick={() => handleRemoveProduct(product)}
className="text-[#EF4444] hover:text-[#DC2626] text-sm font-medium"
>
Remove
</button>
)}
</li>
))}
</ul>
) : (
<div className="p-4 text-center text-sm text-[#6B7280] border border-[#E5E7EB] rounded-md">
-
</div>
)}
{/* Selected Products Panel */}
<div className="bg-white rounded-lg border border-[#E5E7EB] overflow-hidden">
<div className="bg-[#F9FAFB] px-4 py-3 border-b border-[#E5E7EB] flex justify-between items-center">
<h5 className="text-sm font-medium text-[#111827]">Selected Products</h5>
{selectedProducts.length > 0 && (
<span className="bg-[#FEF3C7] text-[#92400E] text-xs font-medium px-2 py-0.5 rounded-full">
{selectedProducts.length} selected
</span>
)}
</div>
<div className="p-4">
{selectedProducts.length > 0 ? (
<ul className="divide-y divide-[#E5E7EB] max-h-96 overflow-y-auto">
{selectedProducts.map((product) => {
// Extract product name and HS code
let name = product.product_name || product.productName || product.label || '';
let hsCode = product.hs_code || product.hsCode || product.value;
// If name contains a pattern like "59061000 - Product Name", extract the product name and HS code
const nameParts = name.split(' - ');
if (nameParts.length > 1 && /^\d+$/.test(nameParts[0])) {
hsCode = nameParts[0];
name = nameParts.slice(1).join(' - ').trim();
}
return (
<li
key={hsCode}
className="p-3 hover:bg-[#F9FAFB] flex justify-between items-center"
>
<div>
{/* Product Name */}
<div className="text-sm font-medium text-[#111827]">
{name || 'Unnamed Product'}
</div>
{/* HS Code under it */}
{hsCode && (
<div className="text-xs text-[#6B7280] mt-1">
HS Code: {hsCode}
</div>
)}
</div>
{/* Remove button */}
{modalMode !== 'view' && (
<button
type="button"
onClick={() => handleRemoveProduct(product)}
className="text-[#EF4444] hover:text-[#DC2626] text-sm font-medium"
>
Remove
</button>
)}
</li>
);
})}
</ul>
) : (
<div className="p-4 text-center text-sm text-[#6B7280] border border-[#E5E7EB] rounded-md">
-
</div>
)}
</div>
</div>
</div>
</div>
);
@ -2385,6 +2421,7 @@ const handleView = async (id) => {
const emptyProfile = createEmptyProfile();
Object.assign(emptyProfile, computeEmploymentTotals(emptyProfile));
setModalMode('add');
setIsViewMode(false); // Ensure view mode is false when adding
setForm(emptyProfile);
setEditingRow(null);
setActiveStep(0);
@ -2408,6 +2445,7 @@ const handleView = async (id) => {
setForm(emptyProfile);
setEditingRow(null);
setModalMode('add');
setIsViewMode(false); // Ensure view mode is false when adding
initialSnapshotRef.current = emptyProfile;
corporateBackupRef.current = captureCorporateValues(emptyProfile);
setIsDirty(false);

View File

@ -106,11 +106,11 @@ const EditCompanyProfile = () => {
const formSteps = React.useMemo(
() => [
{ label: 'User Profile' },
{ label: 'Identification Particulars' },
{ label: 'Establishment Contact Details' },
{ label: 'Profile' },
{ label: 'Details' },
{ label: 'Contact Details' },
{ label: 'Products' },
{ label: 'Employment in Establishment' },
{ label: 'Employment Details' },
],
[]
);
@ -122,14 +122,14 @@ const EditCompanyProfile = () => {
{ field: 'userProfileEmail', label: 'Email' },
],
1: [
{ field: 'permanentFactoryCode', label: 'Permanent Factory Code' },
// { 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: 'contactAddress', label: 'Address' },
{ field: 'contactEmirate', label: 'Emirate' },
{ field: 'contactCityTown', label: 'City/Town' },
{ field: 'contactEmail', label: 'Email' },
@ -636,7 +636,7 @@ const EditCompanyProfile = () => {
return (
<div className="space-y-4">
<div className="space-y-2">
<h4 className="text-[16px] font-semibold text-[#232528] mb-2">User Profile</h4>
<h4 className="text-[16px] font-semibold text-[#232528] mb-2">Profile</h4>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 items-start">
<TextField
label="Name"
@ -679,7 +679,7 @@ const EditCompanyProfile = () => {
return (
<div className="space-y-4">
<div className="space-y-2">
<h4 className="text-[16px] font-semibold text-[#232528]">Identification Particulars</h4>
<h4 className="text-[16px] font-semibold text-[#232528]">Details</h4>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<TextField
label="Permanent Factory Code"
@ -687,7 +687,7 @@ const EditCompanyProfile = () => {
onChange={(e) => handleFormChange("permanentFactoryCode", e.target.value)}
placeholder="Enter Factory Code"
width="100%"
required
// required
error={fieldErrors.permanentFactoryCode}
/>
<TextField
@ -753,7 +753,7 @@ const EditCompanyProfile = () => {
return (
<div className="space-y-4">
<div>
<h4 className="text-[16px] font-semibold text-[#232528]">Establishment Contact Details</h4>
<h4 className="text-[16px] font-semibold text-[#232528]">Contact Details</h4>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<TextField
@ -771,7 +771,7 @@ const EditCompanyProfile = () => {
onChange={(e) => handleFormChange("contactAddress", e.target.value)}
placeholder="Enter Address"
width="100%"
required
// required
error={fieldErrors.contactAddress}
/>
<SelectField
@ -878,7 +878,7 @@ const EditCompanyProfile = () => {
<div className="flex items-center justify-between">
{/* Left side: Products Header */}
<div className="flex items-baseline">
<h4 className="text-[16px] font-semibold text-[#232528] whitespace-nowrap">Products</h4>
<h4 className="text-[16px] font-semibold text-[#232528] whitespace-nowrap">Products <span className="text-red-500">*</span></h4>
<a
href="/assets/images/HS-Code UAE (002).pdf"
target="_blank"
@ -891,7 +891,8 @@ const EditCompanyProfile = () => {
{/* Right side: Icons */}
<div className="flex items-center gap-4 text-sm text-medium-600">
<div className="flex items-center gap-1">
<span className="font-semibold">Added By:</span>
<div className="flex items-center ml-0 gap-1">
<MdAdminPanelSettings className="text-[#92722A] text-lg" />
<span>Admin User</span>
</div>
@ -948,6 +949,9 @@ const EditCompanyProfile = () => {
<div className="text-sm font-medium text-[#111827]">
{product.label}
</div>
{product.hs_code && (
<div className="text-xs text-gray-500">HS Code - {product.hs_code}</div>
)}
</div>
<button
type="button"
@ -974,71 +978,79 @@ const EditCompanyProfile = () => {
</div>
{/* Selected Products Panel */}
<div className="bg-white rounded-lg border border-[#E5E7EB] overflow-hidden">
<div className="bg-[#F9FAFB] px-4 py-3 border-b border-[#E5E7EB] flex justify-between items-center">
<h5 className="text-sm font-medium text-[#111827]">Selected Products</h5>
{selectedProducts.length > 0 && (
<span className="bg-[#FEF3C7] text-[#92400E] text-xs font-medium px-2 py-0.5 rounded-full">
{selectedProducts.length} selected
</span>
)}
</div>
<div className="p-4">
{selectedProducts.length > 0 ? (
<ul className="divide-y divide-[#E5E7EB] max-h-96 overflow-y-auto">
{selectedProducts.map((product) => {
const isNewlyAdded = newlyAddedProductIds.has(product.value);
return (
<li key={product.value} className="p-3 hover:bg-[#F9FAFB] flex justify-between items-center">
<div className="flex items-center gap-2">
{/* {product.action_done_by === "admin_users" ? (
<MdAdminPanelSettings className="text-[#92722A] text-lg" title="Added by Admin" />
) : (
<FaBuilding className="text-[#92722A]" title="Added by Establishment" />
)} */}
{product.action_done_by === "admin_users" ? (
<MdAdminPanelSettings
className="text-[#92722A] text-lg flex-shrink-0 w-6 h-6"
title="Added by Admin"
/>
) : (
<FaBuilding
className="text-[#92722A] flex-shrink-0 w-6 h-5"
title="Added by Establishment"
/>
)}
<div>
<div className="text-sm font-medium text-[#111827]">
{product.label}
</div>
{product.hs_code && (
<div className="text-xs text-gray-500 mt-1">
HS Code: {product.hs_code}
</div>
)}
</div>
</div>
{isNewlyAdded && (
<button
type="button"
onClick={() => handleRemoveProduct(product)}
className="text-[#EF4444] hover:text-[#DC2626] text-sm font-medium"
title="Remove product"
>
Remove
</button>
)}
</li>
);
})}
</ul>
) : (
<div className="p-4 text-center text-sm text-[#6B7280] border border-[#E5E7EB] rounded-md">
No products selected
</div>
)}
<div className="bg-white rounded-lg border border-[#E5E7EB] overflow-hidden">
<div className="bg-[#F9FAFB] px-4 py-3 border-b border-[#E5E7EB] flex justify-between items-center">
<h5 className="text-sm font-medium text-[#111827]">Selected Products</h5>
{selectedProducts.length > 0 && (
<span className="bg-[#FEF3C7] text-[#92400E] text-xs font-medium px-2 py-0.5 rounded-full">
{selectedProducts.length} selected
</span>
)}
</div>
<div className="p-4">
{selectedProducts.length > 0 ? (
<ul className="divide-y divide-[#E5E7EB] max-h-96 overflow-y-auto">
{selectedProducts.map((product) => {
const isNewlyAdded = newlyAddedProductIds.has(product.value);
// extract hs + name
const hsCode = product.label?.split(" - ")[0] ?? "";
const productName = product.label?.split(" - ")[1] ?? product.label;
return (
<li
key={product.value}
className="p-3 hover:bg-[#F9FAFB] flex justify-between items-center"
>
<div className="flex items-center gap-2">
{product.action_done_by === "admin_users" ? (
<MdAdminPanelSettings
className="text-[#92722A] text-lg flex-shrink-0 w-6 h-6"
title="Added by Admin"
/>
) : (
<FaBuilding
className="text-[#92722A] flex-shrink-0 w-6 h-5"
title="Added by Establishment"
/>
)}
<div>
<div className="text-sm font-medium text-[#111827]">
{productName}
</div>
<div className="text-xs text-gray-500 mt-1">
HS Code: {hsCode}
</div>
</div>
</div>
{isNewlyAdded && (
<button
type="button"
onClick={() => handleRemoveProduct(product)}
className="text-[#EF4444] hover:text-[#DC2626] text-sm font-medium"
title="Remove product"
>
Remove
</button>
)}
</li>
);
})}
</ul>
) : (
<div className="p-4 text-center text-sm text-[#6B7280] border border-[#E5E7EB] rounded-md">
No products selected
</div>
)}
</div>
</div>
</div>
</div>
);
@ -1046,47 +1058,67 @@ const EditCompanyProfile = () => {
return (
<div className="space-y-4">
<div>
<h4 className="text-[16px] font-semibold text-[#232528]">Employment in Establishment</h4>
<h4 className="text-[16px] font-semibold text-[#232528]">Employment Details</h4>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<TextField
label="Number of Emirati Male"
value={form.employmentEmiratiMale || ""}
onChange={(e) => handleFormChange("employmentEmiratiMale", e.target.value)}
onChange={(e) => {
if (e.target.value === '' || /^\d+$/.test(e.target.value)) {
handleFormChange("employmentEmiratiMale", e.target.value);
}
}}
placeholder="Enter Count"
width="100%"
type="number"
required
type="text"
inputMode="numeric"
pattern="[0-9]*"
error={fieldErrors.employmentEmiratiMale}
/>
<TextField
label="Number of Non-Emirati Male"
value={form.employmentNonEmiratiMale || ""}
onChange={(e) => handleFormChange("employmentNonEmiratiMale", e.target.value)}
onChange={(e) => {
if (e.target.value === '' || /^\d+$/.test(e.target.value)) {
handleFormChange("employmentNonEmiratiMale", e.target.value);
}
}}
placeholder="Enter Count"
width="100%"
type="number"
required
type="text"
inputMode="numeric"
pattern="[0-9]*"
error={fieldErrors.employmentNonEmiratiMale}
/>
<TextField
label="Number of Emirati Female"
value={form.employmentEmiratiFemale || ""}
onChange={(e) => handleFormChange("employmentEmiratiFemale", e.target.value)}
onChange={(e) => {
if (e.target.value === '' || /^\d+$/.test(e.target.value)) {
handleFormChange("employmentEmiratiFemale", e.target.value);
}
}}
placeholder="Enter Count"
width="100%"
type="number"
required
type="text"
inputMode="numeric"
pattern="[0-9]*"
error={fieldErrors.employmentEmiratiFemale}
/>
<TextField
label="Number of Non-Emirati Female"
value={form.employmentNonEmiratiFemale || ""}
onChange={(e) => handleFormChange("employmentNonEmiratiFemale", e.target.value)}
onChange={(e) => {
if (e.target.value === '' || /^\d+$/.test(e.target.value)) {
handleFormChange("employmentNonEmiratiFemale", e.target.value);
}
}}
placeholder="Enter Count"
width="100%"
type="number"
required
type="text"
inputMode="numeric"
pattern="[0-9]*"
error={fieldErrors.employmentNonEmiratiFemale}
/>
<TextField
@ -1122,7 +1154,7 @@ const EditCompanyProfile = () => {
{/* Header */}
<div className="px-6 pt-6 pb-4 border-b border-gray-200">
<h2 className="text-xl font-bold text-gray-900">Edit Company Profile</h2>
<h2 className="text-xl font-bold text-gray-900">Edit Profile</h2>
</div>
{/* Body */}