From 482f8a9bcb103ce10ea012572d113e5a9268b1b5 Mon Sep 17 00:00:00 2001 From: "pramod.mahajan" Date: Sat, 27 Sep 2025 23:54:44 +0530 Subject: [PATCH] added organization api in repo. and removed unuse files --- public/assets/img/orglogo.png | Bin 0 -> 7408 bytes src/components/Employee/DemoTable.jsx | 172 --------- src/components/Employee/EmployeeList.jsx | 7 - src/components/Employee/EmployeeSchema.jsx | 124 +++++++ src/components/Employee/ManageEmployee.jsx | 335 ++++++++---------- src/components/Organization/AssignOrg.jsx | 30 +- src/components/Organization/ManagOrg.jsx | 4 +- .../Organization/OrgPickerFromSPId.jsx | 2 +- .../Organization/OrganizationModal.jsx | 11 +- .../Organization/OrganizationSkeleton.jsx | 79 +++++ .../Organization/OrganizationsList.jsx | 2 +- .../Organization/ViewOrganization.jsx | 103 ++++++ src/components/common/DatePicker.jsx | 67 ++-- src/hooks/useEmployees.js | 2 +- src/hooks/useOrganization.js | 15 +- src/pages/employee/EmployeeList.jsx | 1 - src/repositories/OrganizationRespository.jsx | 2 + 17 files changed, 537 insertions(+), 419 deletions(-) create mode 100644 public/assets/img/orglogo.png delete mode 100644 src/components/Employee/DemoTable.jsx delete mode 100644 src/components/Employee/EmployeeList.jsx create mode 100644 src/components/Employee/EmployeeSchema.jsx create mode 100644 src/components/Organization/ViewOrganization.jsx diff --git a/public/assets/img/orglogo.png b/public/assets/img/orglogo.png new file mode 100644 index 0000000000000000000000000000000000000000..51ce9299b12492bd15453b5a66dbd1194bd12368 GIT binary patch literal 7408 zcmds6YgAKL7QQzLBnSuy1+5HVZNZK}0>~pg3@Vw}5%B>QEns*DA3QW56ax1~T2WD1 zI93s%vAV2QRM4nIBoINSj`Ao~!2mW91%U*TLLh;><^=nv|C}|;mii+(_dNDJ=j^?| zZ=bX8p^afQ^LZc6gCNNKv$Y|cAqXn~zb6DNXxXyi?8l(MF;=Z#1wq$KOf_*vpbj%P z(^f;*+UkL8YR}eG+s>j0|Nt=mX=XbQ5F^!Zf+Ada`gZNwRZ~-wnwpxD zl5*q54LlytVzDF=$)!t|Iy*ZF1j2<27vkdL%*@PAo;>;F$rBolR#8zA6ciK^5`w{C zuvqM}Wy_W4&p)fx>P3qd9Y22jz<~qy_V%u>uHoU~(b3UqX=%VH-+X;- z3|Ixu+#D7T1rI(;HdNx*(L$huMt@riDkd3gw=qF!cwP(r<3GDrLeL`NXCbR1a(YIe zZ{xT#w*32rC28Tu`$LRY_4_O!{F8L9%o3Mqc_cpA=7W#1o_}BVz{#mFbo@?`0v+j* z$qMdNeS1rpRheDAWrI?m^PFjseZubfT?v&T!%HnmX3nt-Lj|NVG>!x}$6^lL!mA=oT8N*{T+pJjyd9lHj`l_ds+RHBJV&M;HNo$056@CD1;T1qNfPEjFHSSg zRo)doGBSH-YV&)FZOlCyDP_nX(xbYTD}9ltTN*WNuKseLw?q9YIuGBWtJ>RbnZZWM zhfz~p>n2>ZQ|z&i#2A=q1KSbG&J%dS0(+{!2s5}0<8Dc!S^d#N`<%sey}6I(dvsef zP~N0aeRbFylWdL&Ba~4IeoJC)mx#YYw|#|LW0I}rKx4F>ys&YLqDL#NPHk^kzaOls z+lZy-Q8rv&)&! za>2EJgsZS56pDOUJ#i9tskWNZF!xix;cNfXe zAjmevNj%^uuS_x4oa9o*l1of-$N&gi1+%uqY&Sr|R&KCv4Qgiqi&4G7w65Y=_`pPi zu}yOf*!lBC4oWZu5=Yyh28#OEL22z+N5gsnqPQJ{)T^73@!LuKd_7mMxJ=jG7k=9M zN}&8+GM{CgGcL7BULbdd9m51xaQXuI3!J^xds8h1D)}*-D(mBD+XtoD(pi;sMW78mNqp^{!=Bv5YrYdYpi#{Gv;LnsyeWw); zppJKx?TS-s&gdIY5IKu|ZS0U-L}A@V%S%LVqf6)TUf+qULgny-0>b~7v)r^EI z1Uf0coJ*;vsOwPCrfAJ+YkjPvkdvP#D2bVt6o;9q(gpvb(%pBJ|+Eo$yyiUVF4ykRZ_|LwsrfO7J$4NYr>79Y?WYbY~yC}+pYo{LHbQb$&w z)(X3gG^_XgS~NwYh*&on8_ZRudBxv8<7hMYC>EE)krpgbEk)fhxEtSq9l(la4Lj#( z@a?tnhT_>wY=MS;cqNyj=C*Wlb{lI_CORE@Iohqvsq<|pWm~j{t3FS8%)0p_P>4I= zh9;RJY#N7yoJ zvb-`w9FQ@_PKVRqfPGGe!nZfiYh#u~G!|;%i`8vrP7q}sy1mS)Q{^xvI$9%A(i(qa z-Hf_u%sRFAJ>vn2>fAX!Kz8CD1%NxbYI8OJ6d6fHv<8e!K?lKq8>->?upJcW=J<%W{hvJp3nO0 z-UfcZ`Hk~c0s0ul6P;9MOGDBTMHY-SPNy(tbh>N+e&yj}BpXqL121Tw^@4#`tcU?P z@4aGrjg(34kaZMX@|*cu+eyjE>^?Px%$y!PUpahQD=Qe*RcT}O7wOB~bwBBbUW0p* z^amKb{+%Tl7hbWKSLyJ)ri)?byj=0(F_xn>sr8e0loJN`pk}+~n6aWlY=P8)_bA9Y zwrt%yNj`7?Nf%UCQo;YFeB}-OPDXY2N8-sqo?ci@&TI7M=jxw21m-m^FkBtxPVVIG zlR9!9iYUGbcpR?gXxUt4)Z<vXU<< z|D{&HGu=P0@i=D`nYue=sviCZ#!43aUtdXTT=W({Nc@O2~kxOsR+ki7i8R`{=2v7F@RPa=ItaJBfIKx%s8j^r;50zPh}6>gqh z5hRko7unyF^hThBIF%0sA`CMy_c8qAh($ literal 0 HcmV?d00001 diff --git a/src/components/Employee/DemoTable.jsx b/src/components/Employee/DemoTable.jsx deleted file mode 100644 index 1d645cc3..00000000 --- a/src/components/Employee/DemoTable.jsx +++ /dev/null @@ -1,172 +0,0 @@ -import React from "react"; - -const DemoTable = () => { - return ( -
-
-
-
- - - - - - - - - - - - - - -
idNameEmailDateSalaryStatusAction
-
-
-
-
-
- New Record -
- -
-
-
-
- -
- - - - -
-
-
- -
- - - - -
-
-
- -
- - - - -
-
- You can use letters, numbers & periods -
-
-
- -
- - - - -
-
-
- -
- - - - -
-
-
- - -
-
-
-
- -
- -
- -
-
- -
-
- ); -}; - -export default DemoTable; diff --git a/src/components/Employee/EmployeeList.jsx b/src/components/Employee/EmployeeList.jsx deleted file mode 100644 index 5a79c6ce..00000000 --- a/src/components/Employee/EmployeeList.jsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from "react"; - -const EmployeeList = () => { - return
EmployeeList
; -}; - -export default EmployeeList; \ No newline at end of file diff --git a/src/components/Employee/EmployeeSchema.jsx b/src/components/Employee/EmployeeSchema.jsx new file mode 100644 index 00000000..ba540ef4 --- /dev/null +++ b/src/components/Employee/EmployeeSchema.jsx @@ -0,0 +1,124 @@ +import { z } from "zod" + + +const mobileNumberRegex = /^[0-9]\d{9}$/; + +export const employeeSchema = + z.object({ + firstName: z.string().min(1, { message: "First Name is required" }), + middleName: z.string().optional(), + lastName: z.string().min(1, { message: "Last Name is required" }), + email: z + .string() + .max(80, "Email cannot exceed 80 characters") + .optional() + .refine((val) => !val || /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val), { + message: "Invalid email format", + }) + .refine( + (val) => { + if (!val) return true; + const [local, domain] = val.split("@"); + return ( + val.length <= 320 && local?.length <= 64 && domain?.length <= 255 + ); + }, + { + message: "Email local or domain part is too long", + } + ), + currentAddress: z + .string() + .min(1, { message: "Current Address is required" }) + .max(500, { message: "Address cannot exceed 500 characters" }), + birthDate: z + .string() + .min(1, { message: "Birth Date is required" }) + .refine( + (date, ctx) => { + return new Date(date) <= new Date(); + }, + { + message: "Birth date cannot be in the future", + } + ), + joiningDate: z + .string() + .min(1, { message: "Joining Date is required" }) + .refine( + (date, ctx) => { + return new Date(date) <= new Date(); + }, + { + message: "Joining date cannot be in the future", + } + ), + emergencyPhoneNumber: z + .string() + .min(1, { message: "Phone Number is required" }) + .regex(mobileNumberRegex, { message: "Invalid phone number " }), + emergencyContactPerson: z + .string() + .min(1, { message: "Emergency Contact Person is required" }) + .regex(/^[A-Za-z\s]+$/, { + message: "Emergency Contact Person must contain only letters", + }), + aadharNumber: z + .string() + .optional() + .refine((val) => !val || /^\d{12}$/.test(val), { + message: "Aadhar card must be exactly 12 digits long", + }), + gender: z + .string() + .min(1, { message: "Gender is required" }) + .refine((val) => val !== "Select Gender", { + message: "Please select a gender", + }), + panNumber: z + .string() + .optional() + .refine((val) => !val || /^[A-Z]{5}[0-9]{4}[A-Z]{1}$/.test(val), { + message: "Invalid PAN number", + }), + permanentAddress: z + .string() + .min(1, { message: "Permanent Address is required" }) + .max(500, { message: "Address cannot exceed 500 characters" }), + phoneNumber: z + .string() + .min(1, { message: "Phone Number is required" }) + .regex(mobileNumberRegex, { message: "Invalid phone number " }), + jobRoleId: z.string().min(1, { message: "Role is required" }), + organizationId:z.string().min(1,{message:"Organization is required"}), + hasApplicationAccess:z.boolean().default(false), + }).refine((data) => { + if (data.hasApplicationAccess) { + return data.email && data.email.trim() !== ""; + } + return true; +}, { + message: "Email is required when employee has access", + path: ["email"], +}); + + +export const defatEmployeeObj = { + firstName: "", + middleName: "", + lastName: "", + email: "", + currentAddress: "", + birthDate: "", + joiningDate: "", + emergencyPhoneNumber: "", + emergencyContactPerson: "", + aadharNumber: "", + gender: "", + panNumber: "", + permanentAddress: "", + phoneNumber: "", + jobRoleId: null, + organizationId:"", + hasApplicationAccess:false + } \ No newline at end of file diff --git a/src/components/Employee/ManageEmployee.jsx b/src/components/Employee/ManageEmployee.jsx index 81a4c4d2..f57ca994 100644 --- a/src/components/Employee/ManageEmployee.jsx +++ b/src/components/Employee/ManageEmployee.jsx @@ -1,36 +1,37 @@ import React, { useEffect, useState } from "react"; -import showToast from "../../services/toastService"; -import EmployeeRepository from "../../repositories/EmployeeRepository"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; -import { z } from "zod"; + import useMaster from "../../hooks/masterHook/useMaster"; import { useDispatch } from "react-redux"; import { changeMaster } from "../../slices/localVariablesSlice"; import { Link, useNavigate, useParams } from "react-router-dom"; import { formatDate } from "../../utils/dateUtils"; -import { useEmployeeProfile, useUpdateEmployee } from "../../hooks/useEmployees"; import { - cacheData, - clearCacheKey, - getCachedData, -} from "../../slices/apiDataManager"; -import { clearApiCacheKey } from "../../slices/apiCacheSlice"; -import { useMutation } from "@tanstack/react-query"; + useEmployeeProfile, + useUpdateEmployee, +} from "../../hooks/useEmployees"; + import Label from "../common/Label"; import DatePicker from "../common/DatePicker"; - -const mobileNumberRegex = /^[0-9]\d{9}$/; +import { defatEmployeeObj, employeeSchema } from "./EmployeeSchema"; +import { useOrganizationsList } from "../../hooks/useOrganization"; +import { ITEMS_PER_PAGE } from "../../utils/constants"; const ManageEmployee = ({ employeeId, onClosed, IsAllEmployee }) => { const dispatch = useDispatch(); const { mutate: updateEmployee, isPending } = useUpdateEmployee(); - + const { + data: organzationList, + isLoading, + isError, + error: EempError, + } = useOrganizationsList(ITEMS_PER_PAGE, 1, true); const { employee, error, loading: empLoading, - refetch + refetch, } = useEmployeeProfile(employeeId); useEffect(() => { @@ -38,6 +39,7 @@ const ManageEmployee = ({ employeeId, onClosed, IsAllEmployee }) => { }, [employeeId]); const [disabledEmail, setDisabledEmail] = useState(false); + const { data: job_role, loading } = useMaster(); const [isloading, setLoading] = useState(false); const navigation = useNavigate(); @@ -45,98 +47,9 @@ const ManageEmployee = ({ employeeId, onClosed, IsAllEmployee }) => { const [currentAddressLength, setCurrentAddressLength] = useState(0); const [permanentAddressLength, setPermanentAddressLength] = useState(0); - const userSchema = z.object({ - ...(employeeId ? { id: z.string().optional() } : {}), - firstName: z.string().min(1, { message: "First Name is required" }), - middleName: z.string().optional(), - lastName: z.string().min(1, { message: "Last Name is required" }), - email: z - .string() - .max(80, "Email cannot exceed 80 characters") - .optional() - .refine((val) => !val || /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val), { - message: "Invalid email format", - }) - .refine( - (val) => { - if (!val) return true; - const [local, domain] = val.split("@"); - return ( - val.length <= 320 && local?.length <= 64 && domain?.length <= 255 - ); - }, - { - message: "Email local or domain part is too long", - } - ), - currentAddress: z - .string() - .min(1, { message: "Current Address is required" }) - .max(500, { message: "Address cannot exceed 500 characters" }), - birthDate: z - .string() - .min(1, { message: "Birth Date is required" }) - .refine( - (date, ctx) => { - return new Date(date) <= new Date(); - }, - { - message: "Birth date cannot be in the future", - } - ), - joiningDate: z - .string() - .min(1, { message: "Joining Date is required" }) - .refine( - (date, ctx) => { - return new Date(date) <= new Date(); - }, - { - message: "Joining date cannot be in the future", - } - ), - emergencyPhoneNumber: z - .string() - .min(1, { message: "Phone Number is required" }) - .regex(mobileNumberRegex, { message: "Invalid phone number " }), - emergencyContactPerson: z - .string() - .min(1, { message: "Emergency Contact Person is required" }) - .regex(/^[A-Za-z\s]+$/, { - message: "Emergency Contact Person must contain only letters", - }), - aadharNumber: z - .string() - .optional() - .refine((val) => !val || /^\d{12}$/.test(val), { - message: "Aadhar card must be exactly 12 digits long", - }), - gender: z - .string() - .min(1, { message: "Gender is required" }) - .refine((val) => val !== "Select Gender", { - message: "Please select a gender", - }), - panNumber: z - .string() - .optional() - .refine((val) => !val || /^[A-Z]{5}[0-9]{4}[A-Z]{1}$/.test(val), { - message: "Invalid PAN number", - }), - permanentAddress: z - .string() - .min(1, { message: "Permanent Address is required" }) - .max(500, { message: "Address cannot exceed 500 characters" }), - phoneNumber: z - .string() - .min(1, { message: "Phone Number is required" }) - .regex(mobileNumberRegex, { message: "Invalid phone number " }), - jobRoleId: z.string().min(1, { message: "Role is required" }), - }); - useEffect(() => { - refetch() - }, []) + refetch(); + }, []); const { register, @@ -147,25 +60,8 @@ const ManageEmployee = ({ employeeId, onClosed, IsAllEmployee }) => { reset, getValues, } = useForm({ - resolver: zodResolver(userSchema), - defaultValues: { - id: currentEmployee?.id || null, - firstName: currentEmployee?.firstName || "", - middleName: currentEmployee?.middleName || "", - lastName: currentEmployee?.lastName || "", - email: currentEmployee?.email || "", - currentAddress: currentEmployee?.currentAddress || "", - birthDate: formatDate(currentEmployee?.birthDate) || "", - joiningDate: formatDate(currentEmployee?.joiningDate) || "", - emergencyPhoneNumber: currentEmployee?.emergencyPhoneNumber || "", - emergencyContactPerson: currentEmployee?.emergencyContactPerson || "", - aadharNumber: currentEmployee?.aadharNumber || "", - gender: currentEmployee?.gender || "", - panNumber: currentEmployee?.panNumber || "", - permanentAddress: currentEmployee?.permanentAddress || "", - phoneNumber: currentEmployee?.phoneNumber || "", - jobRoleId: currentEmployee?.jobRoleId.toString() || null, - }, + resolver: zodResolver(employeeSchema), + defaultValues: defatEmployeeObj, mode: "onChange", }); @@ -176,7 +72,13 @@ const ManageEmployee = ({ employeeId, onClosed, IsAllEmployee }) => { data.email = null; } - updateEmployee({ ...data, IsAllEmployee }, { + const payload = { ...data, IsAllEmployee }; + + if (employeeId) { + payload.id = employeeId; + } + + updateEmployee(payload, { onSuccess: () => { reset(); onClosed(); @@ -184,7 +86,6 @@ const ManageEmployee = ({ employeeId, onClosed, IsAllEmployee }) => { }); }; - useEffect(() => { if (!loading && !error && employee) { setCurrentEmployee(employee); @@ -195,37 +96,47 @@ const ManageEmployee = ({ employeeId, onClosed, IsAllEmployee }) => { reset( currentEmployee ? { - id: currentEmployee.id || null, - firstName: currentEmployee.firstName || "", - middleName: currentEmployee.middleName || "", - lastName: currentEmployee.lastName || "", - email: currentEmployee.email || "", - currentAddress: currentEmployee.currentAddress || "", - birthDate: formatDate(currentEmployee.birthDate) || "", - joiningDate: formatDate(currentEmployee.joiningDate) || "", - emergencyPhoneNumber: currentEmployee.emergencyPhoneNumber || "", - emergencyContactPerson: - currentEmployee.emergencyContactPerson || "", - aadharNumber: currentEmployee.aadharNumber || "", - gender: currentEmployee.gender || "", - panNumber: currentEmployee.panNumber || "", - permanentAddress: currentEmployee.permanentAddress || "", - phoneNumber: currentEmployee.phoneNumber || "", - jobRoleId: currentEmployee.jobRoleId?.toString() || "", - } + id: currentEmployee.id || null, + firstName: currentEmployee.firstName || "", + middleName: currentEmployee.middleName || "", + lastName: currentEmployee.lastName || "", + email: currentEmployee.email || "", + currentAddress: currentEmployee.currentAddress || "", + birthDate: formatDate(currentEmployee.birthDate) || "", + joiningDate: formatDate(currentEmployee.joiningDate) || "", + emergencyPhoneNumber: currentEmployee.emergencyPhoneNumber || "", + emergencyContactPerson: + currentEmployee.emergencyContactPerson || "", + aadharNumber: currentEmployee.aadharNumber || "", + gender: currentEmployee.gender || "", + panNumber: currentEmployee.panNumber || "", + permanentAddress: currentEmployee.permanentAddress || "", + phoneNumber: currentEmployee.phoneNumber || "", + jobRoleId: currentEmployee.jobRoleId?.toString() || "", + organizationId: currentEmployee.organizationId || "", + hasApplicationAccess: currentEmployee.hasApplicationAccess || false, + } : {} ); setCurrentAddressLength(currentEmployee?.currentAddress?.length || 0); setPermanentAddressLength(currentEmployee?.permanentAddress?.length || 0); }, [currentEmployee, reset]); + const hasAccessAplication = watch("hasApplicationAccess"); return ( <>
-

{employee ? "Update Employee" : "Create Employee"}

+
+

+ {" "} + {employee ? "Update Employee" : "Create Employee"} +

{" "} +
- + { }} /> {errors.firstName && ( -
+
{errors.firstName.message}
)} @@ -267,14 +181,18 @@ const ManageEmployee = ({ employeeId, onClosed, IsAllEmployee }) => { }} /> {errors.middleName && ( -
+
{errors.middleName.message}
)}
-
- + { }} /> {errors.lastName && ( -
+
{errors.lastName.message}
)}
-
-
Email
+ { )}
- + {
- +
- - {" "} - {500 - currentAddressLength} characters left - + {500 - currentAddressLength} characters left
{errors.currentAddress && (
{ }} >
- - {500 - permanentAddressLength} characters left - + {500 - permanentAddressLength} characters left
{errors.permanentAddress && (
{ )}
+ + {/* -------------- */} +
+
+ +
+ +
+ {errors.organizationId && ( +
+ {errors.organizationId.message} +
+ )} +
+ +
+ +
+
+ + {/* --------------- */}
{" "}
@@ -488,7 +469,9 @@ const ManageEmployee = ({ employeeId, onClosed, IsAllEmployee }) => {
- +
-
-
- )} -
- -
- ); }; diff --git a/src/components/Organization/AssignOrg.jsx b/src/components/Organization/AssignOrg.jsx index e30a417c..d0886a62 100644 --- a/src/components/Organization/AssignOrg.jsx +++ b/src/components/Organization/AssignOrg.jsx @@ -93,8 +93,15 @@ const AssignOrg = ({ setStep }) => {
{/* Organization Info Display */}
-
-
{orgData.name}
+
+
+ logo

{orgData.name}

+
- +
Organization Info
{/* Contact Info */}
@@ -114,7 +121,7 @@ const AssignOrg = ({ setStep }) => { className="form-label me-2 mb-0 fw-semibold" style={{ minWidth: "130px" }} > - Contact Person : + Contact Person :
{orgData.contactPerson}
@@ -125,7 +132,7 @@ const AssignOrg = ({ setStep }) => { className="form-label me-2 mb-0 fw-semibold" style={{ minWidth: "130px" }} > - Contact Number : + Contact Number :
{orgData.contactNumber}
@@ -136,7 +143,7 @@ const AssignOrg = ({ setStep }) => { className="form-label me-2 mb-0 fw-semibold" style={{ minWidth: "130px" }} > - Email Address : + Email Address :
{orgData.email}
@@ -147,7 +154,8 @@ const AssignOrg = ({ setStep }) => { className="form-label me-2 mb-0 fw-semibold" style={{ maxWidth: "130px" }} > - Service provider Id (SPRID) : + + Service Provider Id (SPRID) :
{orgData.sprid}
@@ -158,7 +166,7 @@ const AssignOrg = ({ setStep }) => { className="form-label me-1 mb-0 fw-semibold" style={{ minWidth: "130px" }} > - Address : + Address :
{orgData.address}
@@ -233,11 +241,11 @@ const AssignOrg = ({ setStep }) => {
diff --git a/src/components/Organization/ManagOrg.jsx b/src/components/Organization/ManagOrg.jsx index 0f4aa49e..cd27ff9b 100644 --- a/src/components/Organization/ManagOrg.jsx +++ b/src/components/Organization/ManagOrg.jsx @@ -2,6 +2,7 @@ import React, { useEffect } from "react"; import { FormProvider, useForm } from "react-hook-form"; import { useCreateOrganization, + useOrganization, useOrganizationModal, useUpdateOrganization, } from "../../hooks/useOrganization"; @@ -18,6 +19,7 @@ const ManagOrg = () => { const { data: service, isLoading } = useGlobalServices(); const { flowType, orgData, startStep, onOpen, onClose, prevStep } = useOrganizationModal(); + const {data:organization,isLoading:organizationLoading,isError,error} = useOrganization(orgData?.id); const method = useForm({ resolver: zodResolver(organizationSchema), @@ -45,7 +47,7 @@ const ManagOrg = () => { onOpen({ startStep: 1 }); onClose(); }); - +console.log(organization) // Prefill form if editing useEffect(() => { if (orgData) { diff --git a/src/components/Organization/OrgPickerFromSPId.jsx b/src/components/Organization/OrgPickerFromSPId.jsx index 0a46778c..69774947 100644 --- a/src/components/Organization/OrgPickerFromSPId.jsx +++ b/src/components/Organization/OrgPickerFromSPId.jsx @@ -78,7 +78,7 @@ const OrgPickerFromSPId = ({ title, placeholder }) => {
logo { const { isOpen, orgData, startStep, onOpen, onClose, onToggle } = @@ -53,7 +54,7 @@ const OrganizationModal = () => { }; const RenderTitle = useMemo(() => { - if (orgData) { + if (orgData && startStep === 3 ) { return "Assign Organization"; } @@ -70,8 +71,11 @@ const OrganizationModal = () => { if (startStep === 3) { return "Assign Organization"; } + if(startStep === 5){ + return "Organization Details" + } - return "Manage Organization"; + return `${orgData ? "Update":"Create"} Organization`; }, [startStep, orgData]); const contentBody = ( @@ -94,6 +98,9 @@ const OrganizationModal = () => { {/* ---------- STEP 3: Add New Organization ---------- */} {startStep === 4 && } + + {/* ---------- STEP 3: View Organization ---------- */} + {startStep === 5 && }
); diff --git a/src/components/Organization/OrganizationSkeleton.jsx b/src/components/Organization/OrganizationSkeleton.jsx index bdb5feff..841815dc 100644 --- a/src/components/Organization/OrganizationSkeleton.jsx +++ b/src/components/Organization/OrganizationSkeleton.jsx @@ -42,3 +42,82 @@ export const OrgCardSkeleton = () => {
); }; + + +export const OrgDetailsSkeleton = () => { + return ( +
+ {/* Header */} +
+
+ {/* Logo + Name */} +
+ + +
+ + {/* Status Badge */} + +
+
+ + {/* Section Title */} +
+ +
+ + {/* Contact Person */} +
+
+ + +
+
+ + {/* Contact Number */} +
+
+ + +
+
+ + {/* Email */} +
+
+ + +
+
+ + {/* SPRID */} +
+
+ + +
+
+ + {/* Employees */} +
+
+ + +
+
+ + {/* Address */} +
+
+ + +
+
+ + {/* Section Title 2 */} +
+ +
+
+ ); +}; diff --git a/src/components/Organization/OrganizationsList.jsx b/src/components/Organization/OrganizationsList.jsx index b7ea28e5..6e170a2f 100644 --- a/src/components/Organization/OrganizationsList.jsx +++ b/src/components/Organization/OrganizationsList.jsx @@ -129,7 +129,7 @@ const OrganizationsList = ({searchText}) => { ))}
- + onOpen({startStep:5,orgData:org.id,flowType:"view"})}> onOpen({startStep:4,orgData:org,flowType:"edit"})}>
diff --git a/src/components/Organization/ViewOrganization.jsx b/src/components/Organization/ViewOrganization.jsx new file mode 100644 index 00000000..74c898b1 --- /dev/null +++ b/src/components/Organization/ViewOrganization.jsx @@ -0,0 +1,103 @@ +import React from "react"; +import { useOrganization } from "../../hooks/useOrganization"; +import { OrgDetailsSkeleton } from "./OrganizationSkeleton"; + +const VieworgDataanization = ({ orgId }) => { + const { data, isLoading, isError, error } = useOrganization(orgId); + if (isLoading) return ; + if (isError) return
{error.message}
; + return ( +
+ {/* Header */} +
+
+
+ logo

{data?.data?.name}

+
+
+ {data?.data.isActive ? "Active":"In-Active"} +
+
+
+
Organization Info
+ {/* Contact Info */} +
+
+ +
{data?.data?.contactPerson}
+
+
+
+
+ +
{data?.data?.contactNumber}
+
+
+
+
+ +
{data?.data?.email}
+
+
+
+
+ +
{data?.data?.sprid}
+
+
+ +
+
+ +
{data?.data?.activeEmployeeCount}
+
+
+
+
+ +
{data?.data?.address}
+
+
+
Projects And Services
+
+ ) +}; + +export default VieworgDataanization; diff --git a/src/components/common/DatePicker.jsx b/src/components/common/DatePicker.jsx index acb9007f..6b73dc36 100644 --- a/src/components/common/DatePicker.jsx +++ b/src/components/common/DatePicker.jsx @@ -1,14 +1,13 @@ import { useEffect, useRef } from "react"; import { useController } from "react-hook-form"; - const DatePicker = ({ name, control, placeholder = "DD-MM-YYYY", className = "", allowText = false, - maxDate, // removed default new Date() + maxDate, minDate, ...rest }) => { @@ -22,43 +21,43 @@ const DatePicker = ({ }); useEffect(() => { - if (inputRef.current) { - flatpickr(inputRef.current, { - dateFormat: "d-m-Y", - allowInput: allowText, - defaultDate: value - ? flatpickr.parseDate(value, "Y-m-d") - : null, - maxDate: maxDate ?? undefined, // only applied if passed - minDate: minDate ? new Date(minDate.split("T")[0]) : undefined, - onChange: function (selectedDates) { - if (selectedDates.length > 0) { - // store in YYYY-MM-DD - const formatted = flatpickr.formatDate(selectedDates[0], "Y-m-d"); - onChange(formatted); - } else { - onChange(""); - } - }, - ...rest - }); - } + if (!inputRef.current) return; + + const fp = flatpickr(inputRef.current, { + dateFormat: "d-m-Y", + allowInput: allowText, + defaultDate: value ? new Date(value) : null, // safely convert to Date + maxDate: maxDate ? new Date(maxDate) : undefined, + minDate: minDate ? new Date(minDate) : undefined, + onChange: (selectedDates) => { + if (selectedDates.length > 0) { + onChange(flatpickr.formatDate(selectedDates[0], "Y-m-d")); + } else { + onChange(""); + } + }, + ...rest + }); + + return () => { + fp.destroy(); // clean up on unmount + }; }, [inputRef, value, allowText, maxDate, minDate, rest, onChange]); + const displayValue = value ? flatpickr.formatDate(new Date(value), "d-m-Y") : ""; + return ( -
+
{ + if (allowText) { + onChange(e.target.value); // allow manual typing if enabled + } + }} ref={(el) => { inputRef.current = el; ref(el); @@ -70,7 +69,7 @@ const DatePicker = ({ { - if (inputRef.current && inputRef.current._flatpickr) { + if (inputRef.current?._flatpickr) { inputRef.current._flatpickr.open(); } }} diff --git a/src/hooks/useEmployees.js b/src/hooks/useEmployees.js index 58a12e5a..477b18f7 100644 --- a/src/hooks/useEmployees.js +++ b/src/hooks/useEmployees.js @@ -221,7 +221,7 @@ export const useUpdateEmployee = () => { mutationFn: (employeeData) => EmployeeRepository.manageEmployee(employeeData), onSuccess: (_, variables) => { - const id = variables.id || variables.employeeId; + const id = variables?.id || variables?.employeeId; const isAllEmployee = variables.IsAllEmployee; // Cache invalidation diff --git a/src/hooks/useOrganization.js b/src/hooks/useOrganization.js index d6c93693..2248f7bc 100644 --- a/src/hooks/useOrganization.js +++ b/src/hooks/useOrganization.js @@ -37,6 +37,13 @@ export const useOrganizationModal = () => { // ================================Query============================================================= +export const useOrganization=(id)=>{ +return useQuery({ + queryKey:["organization",id], + queryFn:async()=> await OrganizationRepository.getOrganizaion(id), + enabled:!!id +}) +} export const useOrganizationBySPRID = (sprid) => { return useQuery({ queryKey: ["organization by", sprid], @@ -167,11 +174,11 @@ export const useAssignOrgToTenant = (onSuccessCallback) => { export const useUpdateOrganization = () => { const useClient = useQueryClient(); return useMutation({ - mutationFn: async (payload) => - await OrganizationRepository.assignOrganizationToProject(payload), + mutationFn: async ({orgId,payload}) => + await OrganizationRepository.updateOrganizaion(orgId,payload), onSuccess: (_, variables) => { - // useClient.invalidateQueries({ queryKey: ["organizationList"] }); - showToast("Organization successfully", "success"); + useClient.invalidateQueries({ queryKey: ["organizationList"] }); + showToast("Organization Updated successfully", "success"); if (onSuccessCallback) onSuccessCallback(); }, onError: (error) => { diff --git a/src/pages/employee/EmployeeList.jsx b/src/pages/employee/EmployeeList.jsx index b0f10a75..fc77ba1c 100644 --- a/src/pages/employee/EmployeeList.jsx +++ b/src/pages/employee/EmployeeList.jsx @@ -751,7 +751,6 @@ const EmployeeList = () => {
) : ( - //
diff --git a/src/repositories/OrganizationRespository.jsx b/src/repositories/OrganizationRespository.jsx index 28bbf3ce..818cdb59 100644 --- a/src/repositories/OrganizationRespository.jsx +++ b/src/repositories/OrganizationRespository.jsx @@ -2,6 +2,8 @@ import { api } from "../utils/axiosClient"; const OrganizationRepository = { createOrganization: (data) => api.post("/api/Organization/create", data), + updateOrganizaion:(id,data)=>api.put(`/api/Organization/edit/${id}`), + getOrganizaion:(id)=>api.get(`/api/Organization/details/${id}`), getOrganizationList: (pageSize, pageNumber, active, sprid, searchString) => { return api.get( `/api/Organization/list?pageSize=${pageSize}&pageNumber=${pageNumber}&active=${active}&${