bug fixed

This commit is contained in:
Malini 2025-11-13 15:39:26 +05:30
parent 346790205a
commit 234f6c4794
7 changed files with 1154 additions and 794 deletions

View File

@ -279,11 +279,11 @@ function App() {
} }
/> />
</Route> */} </Route> */}
<Route path="/profile/edit/:id" element={ {/* <Route path="/profile/edit/:id" element={
<RequireRole allowedRoles={['EstablishmentUser']}> <RequireRole allowedRoles={['EstablishmentUser']}>
<EditCompanyProfile /> <EditCompanyProfile />
</RequireRole> </RequireRole>
} /> } /> */}
{/* <Route {/* <Route
path="/admin/configuration/profile/:id?" path="/admin/configuration/profile/:id?"
element={ element={
@ -292,6 +292,14 @@ function App() {
</RequireRole> </RequireRole>
} }
/> */} /> */}
<Route
path="/edit-profile/:id"
element={
<RequireRole allowedRoles={['EstablishmentUser']}>
<EditCompanyProfile />
</RequireRole>
}
/>
<Route path="/change-password" element={<ChangePassword />} /> <Route path="/change-password" element={<ChangePassword />} />
<Route path="/forgot-password" element={<ForgotPassword />} /> <Route path="/forgot-password" element={<ForgotPassword />} />
<Route path="/reset-password" element={<PublicContactForm />} /> <Route path="/reset-password" element={<PublicContactForm />} />

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import { NavLink, useNavigate } from 'react-router-dom'; import { NavLink, useNavigate } from 'react-router-dom';
const logoSrc = '/assets/images/FCSCLogo.svg'; const logoSrc = '/assets/images/FCSCLogo.svg';
const surveyIconActiveSrc = '/assets/images/Vector.svg'; const surveyIconActiveSrc = '/assets/images/Vector.svg';
const surveyIconInactiveSrc = '/assets/images/Vectorblack.svg'; const surveyIconInactiveSrc = '/assets/images/Vectorblack.svg';
@ -10,7 +10,7 @@ const historyIconActiveSrc = '/assets/images/mdi_history.svg';
const historyIconInactiveSrc = '/assets/images/history.svg'; const historyIconInactiveSrc = '/assets/images/history.svg';
const overviewIconActiveSrc = '/assets/images/mdi_file-find-outline.svg'; const overviewIconActiveSrc = '/assets/images/mdi_file-find-outline.svg';
const overviewIconInactiveSrc = '/assets/images/mdi_file-find-outline-active.svg'; const overviewIconInactiveSrc = '/assets/images/mdi_file-find-outline-active.svg';
const HeaderBar = () => { const HeaderBar = () => {
const [open, setOpen] = React.useState(false); const [open, setOpen] = React.useState(false);
const [userName, setUserName] = React.useState('User'); const [userName, setUserName] = React.useState('User');
@ -18,7 +18,8 @@ const HeaderBar = () => {
const [userOpen, setUserOpen] = React.useState(false); const [userOpen, setUserOpen] = React.useState(false);
const profileRef = React.useRef(null); const profileRef = React.useRef(null);
const navigate = useNavigate(); const navigate = useNavigate();
const establishmentId = sessionStorage.getItem("establishment_id") || "";
// Close dropdown when clicking outside // Close dropdown when clicking outside
React.useEffect(() => { React.useEffect(() => {
const handleClickOutside = (event) => { const handleClickOutside = (event) => {
@ -26,13 +27,13 @@ const HeaderBar = () => {
setUserOpen(false); setUserOpen(false);
} }
}; };
document.addEventListener('mousedown', handleClickOutside); document.addEventListener('mousedown', handleClickOutside);
return () => { return () => {
document.removeEventListener('mousedown', handleClickOutside); document.removeEventListener('mousedown', handleClickOutside);
}; };
}, []); }, []);
React.useEffect(() => { React.useEffect(() => {
let parsed; let parsed;
try { try {
@ -52,7 +53,7 @@ const HeaderBar = () => {
setUserEmail(email); setUserEmail(email);
} }
}, []); }, []);
const onLogout = () => { const onLogout = () => {
try { try {
sessionStorage.removeItem('auth_token'); sessionStorage.removeItem('auth_token');
@ -63,12 +64,12 @@ const HeaderBar = () => {
setUserOpen(false); setUserOpen(false);
navigate('/index'); navigate('/index');
}; };
const onChangePassword = () => { const onChangePassword = () => {
setUserOpen(false); setUserOpen(false);
navigate('/reset-password'); navigate('/reset-password');
}; };
const initials = React.useMemo(() => { const initials = React.useMemo(() => {
const source = userName || userEmail; const source = userName || userEmail;
if (!source) return 'U'; if (!source) return 'U';
@ -97,10 +98,10 @@ const HeaderBar = () => {
<NavLink <NavLink
to="/survey" to="/survey"
className={({ isActive, isPending }) => `inline-flex items-center gap-2 pb-1 border-b-2 ${ className={({ isActive, isPending }) => `inline-flex items-center gap-2 pb-1 border-b-2 ${
isActive isActive
? 'text-[#92722A] font-medium border-[#92722A]' ? 'text-[#92722A] font-medium border-[#92722A]'
: (window.location.pathname === '/dashboard' || window.location.pathname === '/overview') : (window.location.pathname === '/dashboard' || window.location.pathname === '/overview')
? 'text-gray-400 cursor-not-allowed' ? 'text-gray-400 cursor-not-allowed'
: 'text-[#232528] hover:text-gray-900 border-transparent' : 'text-[#232528] hover:text-gray-900 border-transparent'
}`} }`}
onClick={(e) => { onClick={(e) => {
@ -111,10 +112,10 @@ const HeaderBar = () => {
> >
{({ isActive }) => ( {({ isActive }) => (
<> <>
<img <img
src={isActive ? surveyIconActiveSrc : surveyIconInactiveSrc} src={isActive ? surveyIconActiveSrc : surveyIconInactiveSrc}
alt="Survey" alt="Survey"
className={`h-[18px] w-[18px] ${(window.location.pathname === '/dashboard' || window.location.pathname === '/overview') ? 'opacity-50' : ''}`} className={`h-[18px] w-[18px] ${(window.location.pathname === '/dashboard' || window.location.pathname === '/overview') ? 'opacity-50' : ''}`}
/> />
<span>Survey</span> <span>Survey</span>
</> </>
@ -131,6 +132,37 @@ const HeaderBar = () => {
</> </>
)} )}
</NavLink> </NavLink>
<NavLink
to={`/edit-profile/${establishmentId}`}
className={({ isActive }) =>
`inline-flex items-center gap-2 pb-1 border-b-2 ${
isActive
? "text-[#92722A] font-medium border-[#92722A]"
: "text-[#232528] hover:text-gray-900 border-transparent"
}`
}
>
{({ isActive }) => (
<>
<svg
className={`h-[16px] w-[18px] ${
isActive ? "text-[#92722A]" : "text-[#232528]"
}`}
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
/>
</svg>
<span>Profile</span>
</>
)}
</NavLink>
{/* <NavLink {/* <NavLink
to="/history" to="/history"
className={({ isActive }) => `inline-flex items-center gap-2 pb-1 border-b-2 ${isActive ? 'text-[#92722A] font-medium border-[#92722A]' : 'text-[#232528] hover:text-gray-900 border-transparent'}`} className={({ isActive }) => `inline-flex items-center gap-2 pb-1 border-b-2 ${isActive ? 'text-[#92722A] font-medium border-[#92722A]' : 'text-[#232528] hover:text-gray-900 border-transparent'}`}
@ -199,27 +231,27 @@ const HeaderBar = () => {
<img src={dashboardIconInactiveSrc} alt="Dashboard" className="h-[18px] w-[18px]" /> <img src={dashboardIconInactiveSrc} alt="Dashboard" className="h-[18px] w-[18px]" />
<span>Dashboard</span> <span>Dashboard</span>
</NavLink> </NavLink>
<NavLink <NavLink
to="/survey" to="/survey"
onClick={(e) => { onClick={(e) => {
if (window.location.pathname === '/dashboard') { if (window.location.pathname === '/dashboard') {
e.preventDefault(); e.preventDefault();
} else { } else {
setOpen(false); setOpen(false);
} }
}} }}
className={({ isActive }) => `inline-flex items-center gap-2 px-2 py-2 rounded border-b-2 ${ className={({ isActive }) => `inline-flex items-center gap-2 px-2 py-2 rounded border-b-2 ${
isActive isActive
? 'text-[#92722A] bg-[#F2ECCF] border-[#92722A]' ? 'text-[#92722A] bg-[#F2ECCF] border-[#92722A]'
: window.location.pathname === '/dashboard' : window.location.pathname === '/dashboard'
? 'text-gray-400 cursor-not-allowed bg-gray-100' ? 'text-gray-400 cursor-not-allowed bg-gray-100'
: 'text-[#232528] hover:bg-gray-100 border-transparent' : 'text-[#232528] hover:bg-gray-100 border-transparent'
}`} }`}
> >
<img <img
src={surveyIconInactiveSrc} src={surveyIconInactiveSrc}
alt="Survey" alt="Survey"
className={`h-[18px] w-[18px] ${window.location.pathname === '/dashboard' ? 'opacity-50' : ''}`} className={`h-[18px] w-[18px] ${window.location.pathname === '/dashboard' ? 'opacity-50' : ''}`}
/> />
<span>Survey</span> <span>Survey</span>
</NavLink> </NavLink>
@ -265,5 +297,5 @@ const HeaderBar = () => {
</header> </header>
); );
}; };
export default HeaderBar; export default HeaderBar;

View File

@ -236,19 +236,33 @@ const EstablishmentInfo = ({
}); });
}; };
// const handleEditProfile = (e) => {
// e.preventDefault();
// const establishmentId = sessionStorage.getItem('establishment_id');
// if (!establishmentId) {
// alert('No establishment ID found in session');
// return;
// }
// localStorage.setItem('returnTo', window.location.pathname);
// sessionStorage.setItem('edit_profile_from', 'EstablishmentUser');
// // navigate(`/profile/edit/${establishmentId}`);
// };
const handleEditProfile = (e) => { const handleEditProfile = (e) => {
e.preventDefault(); e.preventDefault();
const establishmentId = sessionStorage.getItem('establishment_id'); const establishmentId = sessionStorage.getItem('establishment_id');
if (!establishmentId) { if (!establishmentId) {
alert('No establishment ID found in session'); alert('No establishment ID found in session');
return; return;
} }
localStorage.setItem('returnTo', window.location.pathname); localStorage.setItem('returnTo', window.location.pathname);
sessionStorage.setItem('edit_profile_from', 'EstablishmentUser'); sessionStorage.setItem('edit_profile_from', 'EstablishmentUser');
navigate(`/profile/edit/${establishmentId}`); navigate(`/edit-profile/${establishmentId}`);
}; };
const handleEmployeeChange = (field) => (event) => { const handleEmployeeChange = (field) => (event) => {
onChange({ onChange({
...info, ...info,
@ -375,7 +389,7 @@ const EstablishmentInfo = ({
here here
</a>. </a>.
</p> */} </p> */}
<p className="text-sm text-[#043DFF] bg-[#E7F5FF]"> {/* <p className="text-sm text-[#043DFF] bg-[#E7F5FF]">
<span className="font-medium">Need to update details?</span> Go to Profile {' '} <span className="font-medium">Need to update details?</span> Go to Profile {' '}
<a <a
href={`/admin/configuration/profile/edit=${sessionStorage.getItem('establishment_id') || ''}`} href={`/admin/configuration/profile/edit=${sessionStorage.getItem('establishment_id') || ''}`}
@ -386,7 +400,17 @@ const EstablishmentInfo = ({
Edit Profile Edit Profile
</a> </a>
. Changes saved there will appear here. . Changes saved there will appear here.
</p> </p> */}
<p className="text-sm text-[#043DFF] bg-[#E7F5FF]">
<span className="font-medium">Need to update details?</span> Go to Profile {' '}
<a
href={`/admin/configuration/edit-profile/${sessionStorage.getItem('establishment_id') || ''}`}
className="underline font-medium text-[#043DFF] hover:text-[#063B82]"
onClick={handleEditProfile}
>
Edit Profile
</a>
</p>
</div> </div>
<div className="flex items-center gap-2 mb-2"> <div className="flex items-center gap-2 mb-2">
<h2 className="text-lg font-semibold text-[#232528]">Step 1: Review Establishment Information</h2> <h2 className="text-lg font-semibold text-[#232528]">Step 1: Review Establishment Information</h2>

View File

@ -15,6 +15,8 @@ const AddAdminUsers = ({ isOpen, onClose, onSave }) => {
}); });
const [errors, setErrors] = useState({}); const [errors, setErrors] = useState({});
const [passwordError, setPasswordError] = useState('');
const [passwordTouched, setPasswordTouched] = useState(false);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [toastData, setToastData] = useState(null); // 👈 for custom toast const [toastData, setToastData] = useState(null); // 👈 for custom toast
@ -41,16 +43,14 @@ const AddAdminUsers = ({ isOpen, onClose, onSave }) => {
if (!formData.status) newErrors.status = 'Status is required'; if (!formData.status) newErrors.status = 'Status is required';
if (!formData.password) { const passwordValidation = validatePassword(formData.password);
newErrors.password = 'Password is required'; if (passwordValidation) {
} else if (formData.password.length < 8) { newErrors.password = passwordValidation;
newErrors.password = 'Password must be at least 8 characters';
} else if (formData.password.length > 12) {
newErrors.password = 'Password cannot exceed 12 characters';
} }
if (formData.password !== formData.confirmPassword) if (formData.password !== formData.confirmPassword) {
newErrors.confirmPassword = 'Passwords do not match'; newErrors.confirmPassword = 'Passwords do not match';
}
return newErrors; return newErrors;
}; };
@ -70,10 +70,38 @@ const AddAdminUsers = ({ isOpen, onClose, onSave }) => {
} }
}, [isOpen]); }, [isOpen]);
const validatePassword = (password) => {
if (!password) return 'Password is required';
if (password.length < 8) return 'Password must be at least 8 characters';
if (!/[A-Z]/.test(password)) return 'Must contain at least one uppercase letter';
if (!/[a-z]/.test(password)) return 'Must contain at least one lowercase letter';
if (!/\d/.test(password)) return 'Must contain at least one number';
if (!/[!@#$%^&*]/.test(password)) return 'Must contain at least one special character (!@#$%^&*)';
return '';
};
const handleChange = (e) => { const handleChange = (e) => {
const { name, value } = e.target; const { name, value } = e.target;
setFormData((prev) => ({ ...prev, [name]: value })); setFormData((prev) => ({ ...prev, [name]: value }));
// Clear any existing error for this field
if (errors[name]) setErrors((prev) => ({ ...prev, [name]: '' })); if (errors[name]) setErrors((prev) => ({ ...prev, [name]: '' }));
// Real-time password validation
if (name === 'password') {
setPasswordTouched(true);
const error = validatePassword(value);
setPasswordError(error);
}
// Clear confirm password error when either password changes
if ((name === 'password' || name === 'confirmPassword') && formData.password && formData.confirmPassword) {
if (formData.password !== formData.confirmPassword) {
setErrors(prev => ({ ...prev, confirmPassword: 'Passwords do not match' }));
} else {
setErrors(prev => ({ ...prev, confirmPassword: '' }));
}
}
}; };
const handleSubmit = async (e) => { const handleSubmit = async (e) => {
@ -156,29 +184,37 @@ const AddAdminUsers = ({ isOpen, onClose, onSave }) => {
placeholder="Enter email" placeholder="Enter email"
/> />
<TextField <div className="relative">
label="Password" <TextField
name="password" label="Password"
type="password" name="password"
value={formData.password} type="password"
onChange={handleChange} value={formData.password}
error={errors.password} onChange={handleChange}
required onBlur={() => setPasswordTouched(true)}
placeholder="Enter password" error={passwordTouched && passwordError ? passwordError : ''}
showToggle required
/> placeholder="Enter password"
showToggle
/>
</div>
<TextField <div className="relative">
label="Confirm Password" <TextField
name="confirmPassword" label="Confirm Password"
type="password" name="confirmPassword"
value={formData.confirmPassword} type="password"
onChange={handleChange} value={formData.confirmPassword}
error={errors.confirmPassword} onChange={handleChange}
required error={errors.confirmPassword}
placeholder="Confirm password" required
showToggle placeholder="Confirm password"
/> showToggle
/>
{formData.confirmPassword && !errors.confirmPassword && (
<p className="mt-1 text-xs text-green-600">Passwords match</p>
)}
</div>
<div className="md:col-span-2 space-y-2"> <div className="md:col-span-2 space-y-2">
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">

View File

@ -15,20 +15,33 @@ export const getUnits = async () => {
export const createUnit = async (unitData) => { export const createUnit = async (unitData) => {
try { try {
// Log the data being sent for debugging
console.log('Creating unit with data:', unitData);
const response = await postRequest(UNIT_MASTER_ENDPOINT, unitData); const response = await postRequest(UNIT_MASTER_ENDPOINT, unitData);
console.log('Unit created successfully:', response.data);
return response.data; return response.data;
} catch (error) { } catch (error) {
console.error('Error creating unit:', error); console.error('Error creating unit:', error);
console.error('Error details:', {
status: error.response?.status,
data: error.response?.data,
headers: error.response?.headers
});
throw error; throw error;
} }
}; };
export const updateUnit = async (id, unitData) => { export const updateUnit = async (id, unitData) => {
try { try {
console.log('Updating unit with data:', unitData);
const response = await putRequest(`${UNIT_MASTER_ENDPOINT}/${id}`, unitData); const response = await putRequest(`${UNIT_MASTER_ENDPOINT}/${id}`, unitData);
console.log('Unit updated successfully:', response.data);
return response.data; return response.data;
} catch (error) { } catch (error) {
console.error('Error updating unit:', error); console.error('Error updating unit:', error);
console.error('Error details:', error.response?.data);
throw error; throw error;
} }
}; };
@ -36,9 +49,25 @@ export const updateUnit = async (id, unitData) => {
export const deleteUnit = async (id) => { export const deleteUnit = async (id) => {
try { try {
const response = await deleteRequest(`${UNIT_MASTER_ENDPOINT}/${id}`); const response = await deleteRequest(`${UNIT_MASTER_ENDPOINT}/${id}`);
console.log('Unit deleted successfully:', response.data);
return response.data; return response.data;
} catch (error) { } catch (error) {
console.error('Error deleting unit:', error); console.error('Error deleting unit:', error);
console.error('Error details:', error.response?.data);
throw error; throw error;
} }
}; };
export const uploadUnitCSV = async (formData) => {
try {
const response = await postRequest(`${UNIT_MASTER_ENDPOINT}/uploadCSV`, formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
return response.data;
} catch (error) {
console.error('Error uploading unit CSV:', error);
throw error;
}
};