added assigned org to project
This commit is contained in:
parent
133024bc5c
commit
005fdb3490
@ -1,11 +1,12 @@
|
|||||||
import React from 'react'
|
import React, { useEffect } from 'react'
|
||||||
import ManageOrganization from './components/Organization/ManageOrganization'
|
// import ManageOrganization from './components/Organization/ManageOrganization'
|
||||||
import { useOrganizationModal } from './hooks/useOrganization';
|
import { useOrganizationModal } from './hooks/useOrganization';
|
||||||
|
import OrganizationModal from './components/Organization/OrganizationModal';
|
||||||
|
|
||||||
const ModalProvider = () => {
|
const ModalProvider = () => {
|
||||||
const { isOpen } = useOrganizationModal();
|
const { isOpen,onClose } = useOrganizationModal();
|
||||||
|
|
||||||
return <>{isOpen && <ManageOrganization />}</>;
|
return <>{isOpen && <OrganizationModal />}</>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,9 +1,208 @@
|
|||||||
import React from 'react'
|
import React, { useMemo, useState } from "react";
|
||||||
|
import { useProjectAssignedServices } from "../../hooks/useProjects";
|
||||||
|
import { useSelectedProject } from "../../slices/apiDataManager";
|
||||||
|
import {
|
||||||
|
useOrganizationType,
|
||||||
|
useServices,
|
||||||
|
} from "../../hooks/masterHook/useMaster";
|
||||||
|
import Label from "../common/Label";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import { assignedOrgToProject } from "./OrganizationSchema";
|
||||||
|
import {
|
||||||
|
useAssignOrgToProject,
|
||||||
|
useOrganizationModal,
|
||||||
|
} from "../../hooks/useOrganization";
|
||||||
|
|
||||||
const AssignOrg = () => {
|
const AssignOrg = ({ setStep }) => {
|
||||||
|
const { isOpen, orgData, startStep, onOpen, onClose, prevStep } =
|
||||||
|
useOrganizationModal();
|
||||||
|
const selectedProject = useSelectedProject();
|
||||||
|
const { data: masterService, isLoading: isMasterserviceLoading } =
|
||||||
|
useServices();
|
||||||
|
const { data: projectServices, isLoading } =
|
||||||
|
useProjectAssignedServices(selectedProject);
|
||||||
|
const { data: orgType, isLoading: orgLoading } = useOrganizationType();
|
||||||
|
|
||||||
|
const { mutate: AssignToProject, isPending } = useAssignOrgToProject(
|
||||||
|
() => {}
|
||||||
|
);
|
||||||
|
|
||||||
|
const mergedServices = useMemo(() => {
|
||||||
|
if (!masterService || !projectServices) return [];
|
||||||
|
|
||||||
|
const combined = [...masterService?.data, ...projectServices];
|
||||||
|
|
||||||
|
const unique = combined.filter(
|
||||||
|
(item, index, self) => index === self.findIndex((s) => s.id === item.id)
|
||||||
|
);
|
||||||
|
|
||||||
|
return unique;
|
||||||
|
}, [masterService, projectServices]);
|
||||||
|
|
||||||
|
const {
|
||||||
|
register,
|
||||||
|
setValue,
|
||||||
|
handleSubmit,
|
||||||
|
formState: { errors },
|
||||||
|
} = useForm({
|
||||||
|
resolver: zodResolver(assignedOrgToProject),
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmit = (formData) => {
|
||||||
|
const payload = {
|
||||||
|
...formData,
|
||||||
|
projectId: selectedProject,
|
||||||
|
organizationId: orgData.id,
|
||||||
|
parentOrganizationId: null,
|
||||||
|
};
|
||||||
|
AssignToProject(payload);
|
||||||
|
};
|
||||||
|
const handleEdit = () => {
|
||||||
|
onOpen({ startStep: 4 , orgData:orgData});
|
||||||
|
};
|
||||||
|
if (isMasterserviceLoading || isLoading)
|
||||||
|
return <div className="text-center">Loading....</div>;
|
||||||
return (
|
return (
|
||||||
<div>AssignOrg</div>
|
<div className="row text-black mb-3">
|
||||||
)
|
<div className="col-12 mb-3">
|
||||||
}
|
<div className="d-flex justify-content-between align-items-center text-start mb-2">
|
||||||
|
<div className="fw-semibold text-wrap">{orgData.name}</div>
|
||||||
|
<div className="text-end">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={handleEdit}
|
||||||
|
className="btn btn-link p-0"
|
||||||
|
>
|
||||||
|
<i className="bx bx-edit text-secondary"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
export default AssignOrg
|
<div className="col-md-6 mb-3">
|
||||||
|
<div className="d-flex">
|
||||||
|
<label
|
||||||
|
className="form-label me-2 mb-0 fw-semibold text-start"
|
||||||
|
style={{ minWidth: "130px" }}
|
||||||
|
>
|
||||||
|
Constact Person :
|
||||||
|
</label>
|
||||||
|
<div className="text-muted">{orgData.name}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-md-6 mb-3">
|
||||||
|
<div className="d-flex">
|
||||||
|
<label
|
||||||
|
className="form-label me-2 mb-0 fw-semibold text-start"
|
||||||
|
style={{ minWidth: "130px" }}
|
||||||
|
>
|
||||||
|
Contact Number :
|
||||||
|
</label>
|
||||||
|
<div className="text-muted">{orgData.contactNumber}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-md-6 mb-3">
|
||||||
|
<div className="d-flex">
|
||||||
|
<label
|
||||||
|
className="form-label me-2 mb-0 fw-semibold text-start"
|
||||||
|
style={{ minWidth: "130px" }}
|
||||||
|
>
|
||||||
|
Email Address :
|
||||||
|
</label>
|
||||||
|
<div className="text-muted">{orgData.email}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-12 mb-3">
|
||||||
|
<div className="d-flex">
|
||||||
|
<label
|
||||||
|
className="form-label me-2 mb-0 fw-semibold text-start text-wrap"
|
||||||
|
style={{ maxWidth: "130px" }}
|
||||||
|
>
|
||||||
|
Service provider Id (SPRID) :
|
||||||
|
</label>
|
||||||
|
<div className="text-muted">{orgData.sprid}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-12 mb-3">
|
||||||
|
<div className="d-flex">
|
||||||
|
<label
|
||||||
|
className="form-label me-1 mb-0 fw-semibold text-start"
|
||||||
|
style={{ minWidth: "130px" }}
|
||||||
|
>
|
||||||
|
Address :
|
||||||
|
</label>
|
||||||
|
<div className="text-muted text-start">{orgData.address}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="text-black text-start">
|
||||||
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
|
<div className="mb-1 text-start">
|
||||||
|
<Label htmlFor="organizationTypeId" required>
|
||||||
|
Organization Type
|
||||||
|
</Label>
|
||||||
|
<select
|
||||||
|
{...register("organizationTypeId")}
|
||||||
|
className="form-select form-select-sm"
|
||||||
|
>
|
||||||
|
<option value="">Select type</option>
|
||||||
|
{orgType?.data.map((type) => (
|
||||||
|
<option key={type.id} value={type.id}>
|
||||||
|
{type.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
{errors.organizationTypeId && (
|
||||||
|
<span className="danger-text">
|
||||||
|
{errors.organizationTypeId.message}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mb-3">
|
||||||
|
<label className="form-label">Select Services</label>
|
||||||
|
{mergedServices?.map((service) => (
|
||||||
|
<div key={service.id} className="form-check">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
value={service.id}
|
||||||
|
{...register("serviceIds")}
|
||||||
|
className="form-check-input"
|
||||||
|
/>
|
||||||
|
<label className="form-check-label">{service.name}</label>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
{errors.serviceIds && (
|
||||||
|
<div className="text-danger small">
|
||||||
|
{errors.serviceIds.message}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Buttons */}
|
||||||
|
<div className="d-flex justify-content-between mt-3">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-xs btn-outline-secondary"
|
||||||
|
onClick={() => onOpen({ startStep: prevStep })}
|
||||||
|
disabled={isPending}
|
||||||
|
>
|
||||||
|
<i className="bx bx-left-arrow-alt"></i> Back
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
className="btn btn-sm btn-primary"
|
||||||
|
disabled={isPending}
|
||||||
|
>
|
||||||
|
{isPending ? "Please wait..." : "Add"}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AssignOrg;
|
||||||
|
142
src/components/Organization/ManagOrg.jsx
Normal file
142
src/components/Organization/ManagOrg.jsx
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
import React, { useEffect } from "react";
|
||||||
|
import { FormProvider, useForm } from "react-hook-form";
|
||||||
|
import {
|
||||||
|
useCreateOrganization,
|
||||||
|
useOrganizationModal,
|
||||||
|
useUpdateOrganization,
|
||||||
|
} from "../../hooks/useOrganization";
|
||||||
|
import {
|
||||||
|
defaultOrganizationValues,
|
||||||
|
organizationSchema,
|
||||||
|
} from "./OrganizationSchema";
|
||||||
|
import Label from "../common/Label";
|
||||||
|
import { useGlobalServices } from "../../hooks/masterHook/useMaster";
|
||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import SelectMultiple from "../common/SelectMultiple";
|
||||||
|
|
||||||
|
const ManagOrg = () => {
|
||||||
|
const { data: service, isLoading } = useGlobalServices();
|
||||||
|
const { isOpen, orgData, startStep, onOpen, onClose, prevStep } =
|
||||||
|
useOrganizationModal();
|
||||||
|
|
||||||
|
const method = useForm({
|
||||||
|
resolver: zodResolver(organizationSchema),
|
||||||
|
defaultValues: defaultOrganizationValues,
|
||||||
|
});
|
||||||
|
|
||||||
|
const {
|
||||||
|
handleSubmit,
|
||||||
|
register,
|
||||||
|
reset,
|
||||||
|
formState: { errors },
|
||||||
|
} = method;
|
||||||
|
|
||||||
|
// Create & Update mutations
|
||||||
|
const { mutate: createOrganization, isPending: isCreating } = useCreateOrganization(() => {
|
||||||
|
reset(defaultOrganizationValues);
|
||||||
|
onOpen({ startStep: 1 });
|
||||||
|
onClose();
|
||||||
|
});
|
||||||
|
|
||||||
|
const { mutate: updateOrganization, isPending: isUpdating } = useUpdateOrganization(() => {
|
||||||
|
reset(defaultOrganizationValues);
|
||||||
|
onOpen({ startStep: 1 });
|
||||||
|
onClose();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Prefill form if editing
|
||||||
|
useEffect(() => {
|
||||||
|
if (orgData) {
|
||||||
|
console.log(orgData)
|
||||||
|
reset({
|
||||||
|
name: orgData.name || "",
|
||||||
|
contactPerson: orgData.contactPerson || "",
|
||||||
|
contactNumber: orgData.contactNumber || "",
|
||||||
|
email: orgData.email || "",
|
||||||
|
serviceIds: orgData.services?.map(s => s.id) || [],
|
||||||
|
address: orgData.address || "",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [orgData, reset]);
|
||||||
|
|
||||||
|
const onSubmit = (payload) => {
|
||||||
|
if (orgData?.id) {
|
||||||
|
updateOrganization({ id: orgData.id, ...payload });
|
||||||
|
} else {
|
||||||
|
createOrganization(payload);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormProvider {...method}>
|
||||||
|
<form className="form" onSubmit={handleSubmit(onSubmit)}>
|
||||||
|
<div className="mb-1 text-start">
|
||||||
|
<Label htmlFor="name" required>Organization Name</Label>
|
||||||
|
<input className="form-control form-control-sm" {...register("name")} />
|
||||||
|
{errors.name && <span className="danger-text">{errors.name.message}</span>}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mb-1 text-start">
|
||||||
|
<Label htmlFor="contactPerson" required>Contact Person</Label>
|
||||||
|
<input className="form-control form-control-sm" {...register("contactPerson")} />
|
||||||
|
{errors.contactPerson && <span className="danger-text">{errors.contactPerson.message}</span>}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mb-1 text-start">
|
||||||
|
<Label htmlFor="contactNumber" required>Contact Number</Label>
|
||||||
|
<input className="form-control form-control-sm" {...register("contactNumber")} />
|
||||||
|
{errors.contactNumber && <span className="danger-text">{errors.contactNumber.message}</span>}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mb-1 text-start">
|
||||||
|
<Label htmlFor="email" required>Email Address</Label>
|
||||||
|
<input className="form-control form-control-sm" {...register("email")} />
|
||||||
|
{errors.email && <span className="danger-text">{errors.email.message}</span>}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mb-1 text-start">
|
||||||
|
<SelectMultiple
|
||||||
|
name="serviceIds"
|
||||||
|
label="Services"
|
||||||
|
required
|
||||||
|
valueKey="id"
|
||||||
|
options={service?.data || []}
|
||||||
|
/>
|
||||||
|
{errors.serviceIds && <span className="danger-text">{errors.serviceIds.message}</span>}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mb-1 text-start">
|
||||||
|
<Label htmlFor="address" required>Address</Label>
|
||||||
|
<textarea
|
||||||
|
className="form-control form-control-sm"
|
||||||
|
{...register("address")}
|
||||||
|
rows={2}
|
||||||
|
/>
|
||||||
|
{errors.address && <span className="danger-text">{errors.address.message}</span>}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="d-flex justify-content-between gap-2 my-2">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-sm btn-outline-secondary"
|
||||||
|
onClick={() => onOpen({ startStep: prevStep })}
|
||||||
|
>
|
||||||
|
← --Back
|
||||||
|
</button>
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
className="btn btn-sm btn-primary"
|
||||||
|
disabled={isCreating || isUpdating || isLoading}
|
||||||
|
>
|
||||||
|
{isCreating || isUpdating ? "Please Wait..." : orgData ? "Update" : "Submit"}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</FormProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export default ManagOrg;
|
@ -15,14 +15,15 @@ import {
|
|||||||
import Label from "../common/Label";
|
import Label from "../common/Label";
|
||||||
import SelectMultiple from "../common/SelectMultiple";
|
import SelectMultiple from "../common/SelectMultiple";
|
||||||
import { useServices } from "../../hooks/masterHook/useMaster";
|
import { useServices } from "../../hooks/masterHook/useMaster";
|
||||||
|
import AssignOrg from "./AssignOrg";
|
||||||
|
|
||||||
const ManageOrganization = ({
|
const ManageOrganization = ({
|
||||||
projectOrganizations = ["ee"],
|
projectOrganizations ,
|
||||||
organizationId = null,
|
organizationId = null,
|
||||||
}) => {
|
}) => {
|
||||||
const [step, setStep] = useState(1);
|
const [step, setStep] = useState(1);
|
||||||
const orgModal = useOrganizationModal();
|
const orgModal = useOrganizationModal();
|
||||||
const { data: masterService, isLoading } = useServices();
|
const { data: masterService, isLoading } = useServices();
|
||||||
const [searchText, setSearchText] = useState();
|
const [searchText, setSearchText] = useState();
|
||||||
const [SPRID, setSPRID] = useState("");
|
const [SPRID, setSPRID] = useState("");
|
||||||
const { data: orgList, isLoading: orgLoading } = useOrganizationsList(
|
const { data: orgList, isLoading: orgLoading } = useOrganizationsList(
|
||||||
@ -39,7 +40,7 @@ const ManageOrganization = ({
|
|||||||
resolver: zodResolver(organizationSchema),
|
resolver: zodResolver(organizationSchema),
|
||||||
defaultValues: defaultOrganizationValues,
|
defaultValues: defaultOrganizationValues,
|
||||||
});
|
});
|
||||||
console.log(masterService);
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
@ -76,7 +77,7 @@ const ManageOrganization = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (step === 3) {
|
if (step === 3) {
|
||||||
return "Create Organization";
|
return "Assign Organization";
|
||||||
}
|
}
|
||||||
|
|
||||||
return "Manage Organization"; // fallback
|
return "Manage Organization"; // fallback
|
||||||
@ -238,105 +239,11 @@ const ManageOrganization = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
||||||
{/* ---------- STEP 2: Existing Organization Details ---------- */}
|
{/* ---------- STEP 2: Existing Organization Details ---------- */}
|
||||||
{step === 3 && (
|
{step === 3 && (
|
||||||
<div className="row text-black mb-3">
|
<AssignOrg Organization={Organization} setStep={setStep}/>
|
||||||
<div className="col-12 mb-3"></div>
|
|
||||||
<div className="text-start mb-2">
|
|
||||||
<div className="text-muted">{Organization.name}</div>
|
|
||||||
</div>
|
|
||||||
{/* Row 1 */}
|
|
||||||
<div className="col-md-6 mb-3">
|
|
||||||
<div className="d-flex">
|
|
||||||
<label
|
|
||||||
className="form-label me-2 mb-0 fw-semibold text-start"
|
|
||||||
style={{ minWidth: "130px" }}
|
|
||||||
>
|
|
||||||
Constact Person :
|
|
||||||
</label>
|
|
||||||
<div className="text-muted">{Organization.name}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="col-md-6 mb-3">
|
|
||||||
<div className="d-flex">
|
|
||||||
<label
|
|
||||||
className="form-label me-2 mb-0 fw-semibold text-start"
|
|
||||||
style={{ minWidth: "130px" }}
|
|
||||||
>
|
|
||||||
Contact Number :
|
|
||||||
</label>
|
|
||||||
<div className="text-muted">{Organization.contactNumber}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="col-md-6 mb-3">
|
|
||||||
<div className="d-flex">
|
|
||||||
<label
|
|
||||||
className="form-label me-2 mb-0 fw-semibold text-start"
|
|
||||||
style={{ minWidth: "130px" }}
|
|
||||||
>
|
|
||||||
Email Address :
|
|
||||||
</label>
|
|
||||||
<div className="text-muted">{Organization.email}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="col-12 mb-3">
|
|
||||||
<div className="d-flex">
|
|
||||||
<label
|
|
||||||
className="form-label me-2 mb-0 fw-semibold text-start text-wrap"
|
|
||||||
style={{ maxWidth: "130px" }}
|
|
||||||
>
|
|
||||||
Service provider Id (SPRID) :
|
|
||||||
</label>
|
|
||||||
<div className="text-muted">{Organization.sprid}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="col-12 mb-3">
|
|
||||||
<div className="d-flex">
|
|
||||||
<label
|
|
||||||
className="form-label me-1 mb-0 fw-semibold text-start"
|
|
||||||
style={{ minWidth: "130px" }}
|
|
||||||
>
|
|
||||||
Address :
|
|
||||||
</label>
|
|
||||||
<div className="text-muted text-start">
|
|
||||||
{Organization.address}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="text-black text-start">
|
|
||||||
<div className="mb-2">
|
|
||||||
<Label className="fs-6">Add Services</Label>
|
|
||||||
<ul className="list-group list-group-flush">
|
|
||||||
{masterService.data &&
|
|
||||||
masterService.data?.map((serv) => (
|
|
||||||
<li className="list-group-item py-1">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
className="form-check-input me-2"
|
|
||||||
/>
|
|
||||||
{serv.name}
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="d-flex justify-content-between mt-3">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="btn btn-xs btn-outline-secondary"
|
|
||||||
onClick={() => setStep(1)}
|
|
||||||
>
|
|
||||||
<i className="bx bx-left-arrow-alt"></i> Back
|
|
||||||
</button>
|
|
||||||
<button type="button" className="btn btn-sm btn-primary">
|
|
||||||
Add
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* ---------- STEP 3: Add New Organization ---------- */}
|
{/* ---------- STEP 3: Add New Organization ---------- */}
|
||||||
@ -405,7 +312,7 @@ const ManageOrganization = ({
|
|||||||
label="Services"
|
label="Services"
|
||||||
required
|
required
|
||||||
valueKey="id"
|
valueKey="id"
|
||||||
options={services?.data || []}
|
options={masterService?.data || []}
|
||||||
/>
|
/>
|
||||||
{errors.serviceIds && (
|
{errors.serviceIds && (
|
||||||
<span className="danger-text">{errors.serviceIds.message}</span>
|
<span className="danger-text">{errors.serviceIds.message}</span>
|
||||||
@ -435,14 +342,7 @@ const ManageOrganization = ({
|
|||||||
← Back
|
← Back
|
||||||
</button>
|
</button>
|
||||||
<div>
|
<div>
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="btn btn-sm btn-secondary me-2"
|
|
||||||
onClick={orgModal.onClose}
|
|
||||||
disabled={isPending || isLoading}
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="btn btn-sm btn-primary"
|
className="btn btn-sm btn-primary"
|
||||||
|
110
src/components/Organization/OrgPicker.jsx
Normal file
110
src/components/Organization/OrgPicker.jsx
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
import { useOrganizationModal } from "../../hooks/useOrganization";
|
||||||
|
import Label from "../common/Label";
|
||||||
|
|
||||||
|
const OrgPicker = ({
|
||||||
|
title,
|
||||||
|
placeholder,
|
||||||
|
orgs = [],
|
||||||
|
searchValue,
|
||||||
|
setSearchValue,
|
||||||
|
}) => {
|
||||||
|
const { isOpen, orgData, startStep, onOpen, onClose, prevStep } =
|
||||||
|
useOrganizationModal();
|
||||||
|
|
||||||
|
const handleBack = () => {
|
||||||
|
if (startStep === prevStep) {
|
||||||
|
onOpen({ startStep: 2,prevStep:1 });
|
||||||
|
} else {
|
||||||
|
onOpen({ startStep: 2 });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div className="d-block">
|
||||||
|
<div className="text-start mb-1">
|
||||||
|
<Label className="text-secondary">{title}1</Label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={searchValue}
|
||||||
|
onChange={(e) => setSearchValue?.(e.target.value)}
|
||||||
|
className="form-control form-control-sm w-auto"
|
||||||
|
placeholder={placeholder}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* ---- Organization list ---- */}
|
||||||
|
<div className="py-2 text-tiny text-center">
|
||||||
|
<div className="d-flex flex-column gap-2 border-0 bg-none">
|
||||||
|
{orgs?.map((org) => (
|
||||||
|
<div
|
||||||
|
key={org.id}
|
||||||
|
className="list-group-item list-group-item-action d-flex align-items-center cursor-pointer border-0 hover-overlay border-bottom rounded-none pb-1 shadow-1-strong rounded"
|
||||||
|
>
|
||||||
|
<div className="d-flex align-items-center justify-content-center me-3">
|
||||||
|
<i className="bx bx-building-house bx-md text-primary"></i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="w-100">
|
||||||
|
<div className="d-flex justify-content-between cursor-pointer">
|
||||||
|
<div className="user-info text-start">
|
||||||
|
<h6 className="mb-1 fw-normal">{org.name}</h6>
|
||||||
|
</div>
|
||||||
|
<div className="add-btn">
|
||||||
|
<button
|
||||||
|
className="btn btn-primary btn-xs"
|
||||||
|
onClick={onOpen.bind(null, { startStep: 3, orgData: org })}
|
||||||
|
>
|
||||||
|
select
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{startStep !== 2 && (
|
||||||
|
<div className="mt-4">
|
||||||
|
<p className="text-secondary">
|
||||||
|
Don't have required organization, Please find using{" "}
|
||||||
|
<span
|
||||||
|
className="text-mutes cursor-pointer text-decoration-underline"
|
||||||
|
onClick={() => {
|
||||||
|
onOpen({ startStep: 2, });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
SPRID
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* ---- Footer buttons ---- */}
|
||||||
|
<div
|
||||||
|
className={`d-flex justify-content-end
|
||||||
|
text-secondary mt-3`}
|
||||||
|
>
|
||||||
|
{startStep > 1 && prevStep < startStep && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-xs btn-outline-secondary"
|
||||||
|
onClick={handleBack}
|
||||||
|
>
|
||||||
|
<i className="bx bx-left-arrow-alt"></i> Back
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-xs btn-secondary"
|
||||||
|
onClick={() => onOpen({ startStep: 4 })}
|
||||||
|
>
|
||||||
|
<i className="bx bx-plus-circle me-2"></i>
|
||||||
|
Add New Organization
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default OrgPicker;
|
145
src/components/Organization/OrgPicker2.jsx
Normal file
145
src/components/Organization/OrgPicker2.jsx
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import {
|
||||||
|
useOrganizationBySPRID,
|
||||||
|
useOrganizationModal,
|
||||||
|
} from "../../hooks/useOrganization";
|
||||||
|
import Label from "../common/Label";
|
||||||
|
import { useDebounce } from "../../utils/appUtils";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import { spridSchema } from "./OrganizationSchema";
|
||||||
|
import { OrgCardSkeleton } from "./OrganizationSkeleton";
|
||||||
|
|
||||||
|
// Zod schema: only allow exactly 4 digits
|
||||||
|
|
||||||
|
const OrgPicker2 = ({ title, placeholder }) => {
|
||||||
|
const { startStep, prevStep, onOpen } = useOrganizationModal();
|
||||||
|
|
||||||
|
const {
|
||||||
|
register,
|
||||||
|
handleSubmit,
|
||||||
|
formState: { errors },
|
||||||
|
watch,
|
||||||
|
} = useForm({
|
||||||
|
resolver: zodResolver(spridSchema),
|
||||||
|
defaultValues: { spridSearchText: "" },
|
||||||
|
});
|
||||||
|
|
||||||
|
const [SPRID, setSPRID] = useState("");
|
||||||
|
|
||||||
|
const { data, isLoading, isError, error, refetch } =
|
||||||
|
useOrganizationBySPRID(SPRID);
|
||||||
|
|
||||||
|
const onSubmit = (formdata) => {
|
||||||
|
setSPRID(formdata.spridSearchText);
|
||||||
|
};
|
||||||
|
console.log(data)
|
||||||
|
const SP = watch("spridSearchText")
|
||||||
|
return (
|
||||||
|
<div className="d-block">
|
||||||
|
<form
|
||||||
|
className="d-flex flex-row gap-6 text-start align-items-center"
|
||||||
|
onSubmit={handleSubmit(onSubmit)}
|
||||||
|
>
|
||||||
|
<div className="d-flex flex-column">
|
||||||
|
<Label className="text-secondary">{title}</Label>
|
||||||
|
<input
|
||||||
|
type="search"
|
||||||
|
|
||||||
|
{...register("spridSearchText")}
|
||||||
|
className="form-control form-control-sm w-auto"
|
||||||
|
placeholder={placeholder || "Enter Service Provider ID"}
|
||||||
|
maxLength={4}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-4">
|
||||||
|
<button type="submit" className="btn btn-sm btn-primary">
|
||||||
|
<i className="bx bx-sm bx-search-alt-2"></i> Search
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<div className="text-start danger-text">
|
||||||
|
{" "}
|
||||||
|
{errors.spridSearchText && (
|
||||||
|
<p className="text-danger small mt-1">
|
||||||
|
{errors.spridSearchText.message}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* ---- Organization list ---- */}
|
||||||
|
{isLoading ? (
|
||||||
|
<OrgCardSkeleton />
|
||||||
|
) : data && data.length > 0 ? (
|
||||||
|
<div className="py-2 text-tiny text-center">
|
||||||
|
<div className="d-flex flex-column gap-2 border-0 bg-none">
|
||||||
|
{data.map((org) => (
|
||||||
|
<div
|
||||||
|
key={org.id}
|
||||||
|
className="list-group-item list-group-item-action d-flex align-items-center cursor-pointer border-0 hover-overlay shadow-1-strong rounded"
|
||||||
|
>
|
||||||
|
<div className="d-flex align-items-center justify-content-center me-3">
|
||||||
|
<i className="bx bx-building-house bx-md text-primary"></i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="w-100">
|
||||||
|
<div className="d-flex justify-content-between cursor-pointer">
|
||||||
|
<div className="user-info text-start">
|
||||||
|
<h6 className="mb-1 fw-normal">{org.name}</h6>
|
||||||
|
</div>
|
||||||
|
<div className="add-btn">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-primary btn-sm"
|
||||||
|
onClick={() => onOpen({ startStep: 3, orgData: org })}
|
||||||
|
>
|
||||||
|
select
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : SPRID ? (
|
||||||
|
<div className="py-3 text-center text-secondary">
|
||||||
|
No organization found for "{SPRID}"
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="py-12 text-center text-tiny text-black">
|
||||||
|
Type a Service Provider ID to find an organization.
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{/* ---- Footer buttons ---- */}
|
||||||
|
{/* ---- Footer buttons ---- */}
|
||||||
|
<div className="d-flex justify-content-between text-secondary mt-3">
|
||||||
|
{startStep > 1 && prevStep !== startStep && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-xs btn-outline-secondary"
|
||||||
|
onClick={() => onOpen({ startStep: prevStep })}
|
||||||
|
>
|
||||||
|
<i className="bx bx-left-arrow-alt"></i> Back
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-xs btn-secondary"
|
||||||
|
onClick={() => onOpen({ startStep: 4 })}
|
||||||
|
>
|
||||||
|
<i className="bx bx-plus-circle me-2"></i>
|
||||||
|
Add New Organization
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default OrgPicker2;
|
130
src/components/Organization/OrganizationModal.jsx
Normal file
130
src/components/Organization/OrganizationModal.jsx
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import React, { useMemo, useState } from "react";
|
||||||
|
import { FormProvider, useForm } from "react-hook-form";
|
||||||
|
import {
|
||||||
|
defaultOrganizationValues,
|
||||||
|
organizationSchema,
|
||||||
|
} from "./OrganizationSchema";
|
||||||
|
import Modal from "../common/Modal";
|
||||||
|
import {
|
||||||
|
useCreateOrganization,
|
||||||
|
useOrganizationBySPRID,
|
||||||
|
useOrganizationModal,
|
||||||
|
useOrganizationsList,
|
||||||
|
} from "../../hooks/useOrganization";
|
||||||
|
import Label from "../common/Label";
|
||||||
|
import SelectMultiple from "../common/SelectMultiple";
|
||||||
|
import { useServices } from "../../hooks/masterHook/useMaster";
|
||||||
|
import AssignOrg from "./AssignOrg";
|
||||||
|
import ManagOrg from "./ManagOrg";
|
||||||
|
import OrgPicker from "./OrgPicker";
|
||||||
|
import OrgPicker2 from "./OrgPicker2";
|
||||||
|
|
||||||
|
const OrganizationModal = () => {
|
||||||
|
const { isOpen, orgData, startStep, onOpen, onClose, onToggle } =
|
||||||
|
useOrganizationModal();
|
||||||
|
const { data: masterService, isLoading } = useServices();
|
||||||
|
const [searchText, setSearchText] = useState();
|
||||||
|
const [SPRID, setSPRID] = useState("");
|
||||||
|
const { data: orgList, isLoading: orgLoading } = useOrganizationsList(
|
||||||
|
20,
|
||||||
|
1,
|
||||||
|
true,
|
||||||
|
searchText
|
||||||
|
);
|
||||||
|
|
||||||
|
const [Organization, setOrganization] = useState({});
|
||||||
|
|
||||||
|
const method = useForm({
|
||||||
|
resolver: zodResolver(organizationSchema),
|
||||||
|
defaultValues: defaultOrganizationValues,
|
||||||
|
});
|
||||||
|
|
||||||
|
const {
|
||||||
|
handleSubmit,
|
||||||
|
register,
|
||||||
|
reset,
|
||||||
|
formState: { errors },
|
||||||
|
} = method;
|
||||||
|
|
||||||
|
const { mutate: CreateOrganization, isPending } = useCreateOrganization(
|
||||||
|
() => {
|
||||||
|
reset(defaultOrganizationValues);
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const onSubmit = (OrgPayload) => {
|
||||||
|
CreateOrganization(OrgPayload);
|
||||||
|
};
|
||||||
|
|
||||||
|
const RenderTitle = useMemo(() => {
|
||||||
|
if (orgData) {
|
||||||
|
return "Assign Organization";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startStep === 1) {
|
||||||
|
return orgData && orgData !== null
|
||||||
|
? "Add Organization"
|
||||||
|
: "Choose Organization";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startStep === 2) {
|
||||||
|
return "Choose Organization";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startStep === 3) {
|
||||||
|
return "Assign Organization";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Manage Organization";
|
||||||
|
}, [startStep, orgData]);
|
||||||
|
|
||||||
|
const contentBody = (
|
||||||
|
<div>
|
||||||
|
{/* ---------- STEP 1: Service Provider- Form Own Tenant list ---------- */}
|
||||||
|
{startStep === 1 && (
|
||||||
|
<OrgPicker
|
||||||
|
title="Find Organization"
|
||||||
|
placeholder="Enter Organization"
|
||||||
|
orgs={orgList}
|
||||||
|
projectOrganizations={orgData}
|
||||||
|
searchValue={SPRID}
|
||||||
|
setSearchValue={setSPRID}
|
||||||
|
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{startStep === 2 && (
|
||||||
|
<OrgPicker2
|
||||||
|
title="Find Organization"
|
||||||
|
placeholder="Enter Service Provider Id"
|
||||||
|
projectOrganizations={orgData}
|
||||||
|
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* ---------- STEP 2: Existing Organization Details ---------- */}
|
||||||
|
{startStep === 3 && Organization && (
|
||||||
|
<AssignOrg Organization={Organization} />
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* ---------- STEP 3: Add New Organization ---------- */}
|
||||||
|
{startStep === 4 && (
|
||||||
|
|
||||||
|
<ManagOrg />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
isOpen={isOpen}
|
||||||
|
onClose={onClose}
|
||||||
|
title={RenderTitle}
|
||||||
|
body={contentBody}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default OrganizationModal;
|
@ -30,3 +30,28 @@ export const defaultOrganizationValues = {
|
|||||||
email: "",
|
email: "",
|
||||||
serviceIds: [],
|
serviceIds: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export const assignedOrgToProject = z.object({
|
||||||
|
// projectId: z.string().uuid({ message: "Invalid projectId format" }),
|
||||||
|
// organizationId: z.string().string({ message: "Invalid organizationId format" }),
|
||||||
|
// parentOrganizationId: z
|
||||||
|
// .string()
|
||||||
|
// .nullable()
|
||||||
|
// .optional(),
|
||||||
|
serviceIds: z.preprocess(
|
||||||
|
(val) => (Array.isArray(val) ? val : []),
|
||||||
|
z
|
||||||
|
.array(z.string().uuid({ message: "Invalid serviceId format" }))
|
||||||
|
.nonempty({ message: "At least one service must be selected" })
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
organizationTypeId: z.string().min(1,{ message: "Organization is required" }),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const spridSchema = z.object({
|
||||||
|
spridSearchText: z
|
||||||
|
.string()
|
||||||
|
.regex(/^\d{4}$/, { message: "SPRID must be exactly 4 digits" }),
|
||||||
|
})
|
||||||
|
39
src/components/Organization/OrganizationSkeleton.jsx
Normal file
39
src/components/Organization/OrganizationSkeleton.jsx
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
const SkeletonLine = ({ height = 20, width = "100%", className = "" }) => (
|
||||||
|
<div
|
||||||
|
className={`skeleton mb-2 ${className}`}
|
||||||
|
style={{
|
||||||
|
height,
|
||||||
|
width,
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
);
|
||||||
|
export const OrgCardSkeleton = () => {
|
||||||
|
return (
|
||||||
|
<div className="row p-5">
|
||||||
|
|
||||||
|
{[...Array(1)].map((_, idx) => (
|
||||||
|
<div
|
||||||
|
key={idx}
|
||||||
|
className="list-group-item d-flex align-items-center border-0 shadow-sm rounded mb-3"
|
||||||
|
>
|
||||||
|
<div className="d-flex align-items-center justify-content-center me-3 p-1">
|
||||||
|
<SkeletonLine height={40} width={40} className="rounded-circle" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div className="w-100 px-1">
|
||||||
|
<div className="d-flex justify-content-between px-">
|
||||||
|
<div className="user-info text-start">
|
||||||
|
<SkeletonLine height={16} width="120px" className="mb-1" />
|
||||||
|
<SkeletonLine height={12} width="80px" />
|
||||||
|
</div>
|
||||||
|
<div className="add-btn px-2">
|
||||||
|
<SkeletonLine height={30} width="60px" className="rounded" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
@ -3,7 +3,7 @@ import { useOrganizationModal } from "../../hooks/useOrganization";
|
|||||||
import { useSelectedProject } from "../../slices/apiDataManager";
|
import { useSelectedProject } from "../../slices/apiDataManager";
|
||||||
|
|
||||||
const ProjectOrganizations = () => {
|
const ProjectOrganizations = () => {
|
||||||
const orgModal = useOrganizationModal();
|
const {onOpen,startStep} = useOrganizationModal();
|
||||||
const selectedProject = useSelectedProject()
|
const selectedProject = useSelectedProject()
|
||||||
return (
|
return (
|
||||||
<div className="card">
|
<div className="card">
|
||||||
@ -12,7 +12,7 @@ const ProjectOrganizations = () => {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="link-button btn btn-xs rounded-md link-button-sm m-1 btn-primary"
|
className="link-button btn btn-xs rounded-md link-button-sm m-1 btn-primary"
|
||||||
onClick={() => orgModal.onOpen(selectedProject)}
|
onClick={() => onOpen({startStep:1})}
|
||||||
>
|
>
|
||||||
<i className="bx bx-plus-circle me-2"></i>
|
<i className="bx bx-plus-circle me-2"></i>
|
||||||
Add Organization
|
Add Organization
|
||||||
|
@ -12,7 +12,13 @@ import showToast from "../../services/toastService";
|
|||||||
export const useServices = ()=>{
|
export const useServices = ()=>{
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey:["services"],
|
queryKey:["services"],
|
||||||
queryFn:async()=> await MasterRespository.getServices()
|
queryFn:async()=> await MasterRespository.getMasterServices()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
export const useGlobalServices = ()=>{
|
||||||
|
return useQuery({
|
||||||
|
queryKey:["globalServices"],
|
||||||
|
queryFn:async()=> await MasterRespository.getGlobalServices()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,6 +232,12 @@ const {
|
|||||||
|
|
||||||
return { DocumentCategories, isError, isLoading, error };
|
return { DocumentCategories, isError, isLoading, error };
|
||||||
}
|
}
|
||||||
|
export const useOrganizationType =()=>{
|
||||||
|
return useQuery({
|
||||||
|
queryKey:["orgType"],
|
||||||
|
queryFn:async()=>await MasterRespository.getOrganizationType()
|
||||||
|
})
|
||||||
|
}
|
||||||
// ===Application Masters Query=================================================
|
// ===Application Masters Query=================================================
|
||||||
|
|
||||||
const fetchMasterData = async (masterType) => {
|
const fetchMasterData = async (masterType) => {
|
||||||
|
@ -10,24 +10,40 @@ import showToast from "../services/toastService";
|
|||||||
|
|
||||||
export const useOrganizationModal = () => {
|
export const useOrganizationModal = () => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const { isOpen, orgData } = useSelector(
|
const { isOpen, orgData, startStep, prevStep } = useSelector(
|
||||||
(state) => state.localVariables.OrganizationModal
|
(state) => state.localVariables.OrganizationModal
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isOpen,
|
isOpen,
|
||||||
orgData,
|
orgData,
|
||||||
onOpen: (dat) =>
|
startStep,
|
||||||
dispatch(openOrgModal({ isOpen: true, orgData: dat || null })),
|
prevStep,
|
||||||
|
onOpen: (options = {}) =>
|
||||||
|
dispatch(
|
||||||
|
openOrgModal({
|
||||||
|
isOpen: true,
|
||||||
|
orgData: options.orgData ?? orgData ?? null,
|
||||||
|
startStep: options.startStep ?? startStep ?? 1,
|
||||||
|
// only override prevStep if explicitly passed
|
||||||
|
prevStep: options.prevStep ?? prevStep ?? 1,
|
||||||
|
})
|
||||||
|
),
|
||||||
onClose: () => dispatch(closeOrgModal()),
|
onClose: () => dispatch(closeOrgModal()),
|
||||||
onToggle: () => dispatch(toggleOrgModal()),
|
onToggle: () => dispatch(toggleOrgModal()),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const useOrganizationBySPRID =(sprid)=>{
|
export const useOrganizationBySPRID =(sprid)=>{
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey:["organization by",sprid],
|
queryKey:["organization by",sprid],
|
||||||
queryFn:async()=>await OrganizationRepository.getOrganizationBySPRID(sprid),
|
queryFn:async()=>{
|
||||||
|
|
||||||
|
const resp = await OrganizationRepository.getOrganizationBySPRID(sprid);
|
||||||
|
return resp.data;
|
||||||
|
},
|
||||||
enabled:!!sprid
|
enabled:!!sprid
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -83,3 +99,45 @@ export const useCreateOrganization = (onSuccessCallback) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useAssignOrgToProject=()=>{
|
||||||
|
const useClient = useQueryClient();
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: async (payload) =>
|
||||||
|
await OrganizationRepository.assignOrganizationToProject(payload),
|
||||||
|
onSuccess: (_, variables) => {
|
||||||
|
// useClient.invalidateQueries({ queryKey: ["organizationList"] });
|
||||||
|
showToast("Organization successfully", "success");
|
||||||
|
if (onSuccessCallback) onSuccessCallback();
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
showToast(
|
||||||
|
error.response.data.message ||
|
||||||
|
error.message ||
|
||||||
|
"Something went wrong please try again !",
|
||||||
|
"error"
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useUpdateOrganization=()=>{
|
||||||
|
const useClient = useQueryClient();
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: async (payload) =>
|
||||||
|
await OrganizationRepository.assignOrganizationToProject(payload),
|
||||||
|
onSuccess: (_, variables) => {
|
||||||
|
// useClient.invalidateQueries({ queryKey: ["organizationList"] });
|
||||||
|
showToast("Organization successfully", "success");
|
||||||
|
if (onSuccessCallback) onSuccessCallback();
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
showToast(
|
||||||
|
error.response.data.message ||
|
||||||
|
error.message ||
|
||||||
|
"Something went wrong please try again !",
|
||||||
|
"error"
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
@ -4,7 +4,8 @@ import { useOrganizationModal } from "../../hooks/useOrganization";
|
|||||||
import OrganizationsList from "../../components/Organization/OrganizationsList";
|
import OrganizationsList from "../../components/Organization/OrganizationsList";
|
||||||
|
|
||||||
const OrganizationPage = () => {
|
const OrganizationPage = () => {
|
||||||
const orgModal = useOrganizationModal()
|
const { isOpen, orgData, startStep, onOpen, } =
|
||||||
|
useOrganizationModal();
|
||||||
const [searchText,setSearchText] = useState("")
|
const [searchText,setSearchText] = useState("")
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -33,7 +34,7 @@ const OrganizationPage = () => {
|
|||||||
type="button"
|
type="button"
|
||||||
className="p-1 me-1 m-sm-0 bg-primary rounded-circle"
|
className="p-1 me-1 m-sm-0 bg-primary rounded-circle"
|
||||||
title="Add New Organization"
|
title="Add New Organization"
|
||||||
onClick={()=>orgModal.onOpen()}
|
onClick={()=>onOpen({ startStep: 1, })}
|
||||||
>
|
>
|
||||||
<i className="bx bx-plus fs-4 text-white"></i>
|
<i className="bx bx-plus fs-4 text-white"></i>
|
||||||
</button>
|
</button>
|
||||||
|
@ -109,5 +109,8 @@ export const MasterRespository = {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
getServices:()=>api.get("/api/Master/global-service/list")
|
getGlobalServices:()=>api.get("/api/Master/global-service/list"),
|
||||||
|
getMasterServices:()=>api.get("/api/Master/service/list"),
|
||||||
|
|
||||||
|
getOrganizationType:()=>api.get('/api/Master/organization-type/list')
|
||||||
};
|
};
|
||||||
|
@ -10,7 +10,7 @@ const OrganizationRepository = {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
getOrganizationBySPRID :()=>api.get(`/api/Organization/list?sprid=${sprid}`),
|
getOrganizationBySPRID :(sprid)=>api.get(`/api/Organization/list?sprid=${sprid}`),
|
||||||
|
|
||||||
assignOrganizationToProject:(data)=>api.post(`/api/Organization/assign/project`,data)
|
assignOrganizationToProject:(data)=>api.post(`/api/Organization/assign/project`,data)
|
||||||
};
|
};
|
||||||
|
@ -13,8 +13,10 @@ const localVariablesSlice = createSlice({
|
|||||||
reload:false,
|
reload:false,
|
||||||
|
|
||||||
OrganizationModal:{
|
OrganizationModal:{
|
||||||
isOpen:false,
|
isOpen: false,
|
||||||
orgData:null,
|
orgData: null,
|
||||||
|
prevStep:null,
|
||||||
|
startStep: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
@ -39,31 +41,24 @@ const localVariablesSlice = createSlice({
|
|||||||
},
|
},
|
||||||
|
|
||||||
openOrgModal: (state, action) => {
|
openOrgModal: (state, action) => {
|
||||||
debugger;
|
state.OrganizationModal.isOpen = true;
|
||||||
|
state.OrganizationModal.orgData = action.payload?.orgData || null;
|
||||||
|
|
||||||
if (typeof action.payload === "boolean") {
|
if (state.OrganizationModal.startStep) {
|
||||||
state.OrganizationModal.isOpen = action.payload;
|
state.OrganizationModal.prevStep = state.OrganizationModal.startStep;
|
||||||
if (!action.payload) {
|
|
||||||
state.OrganizationModal.orgData = null;
|
|
||||||
}
|
|
||||||
} else if (typeof action.payload === "object") {
|
|
||||||
const { isOpen, orgData } = action.payload;
|
|
||||||
state.OrganizationModal.isOpen =
|
|
||||||
typeof isOpen === "boolean" ? isOpen : state.OrganizationModal.isOpen;
|
|
||||||
state.OrganizationModal.orgData =
|
|
||||||
orgData !== undefined ? orgData : state.OrganizationModal.orgData;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
,
|
state.OrganizationModal.startStep = action.payload?.startStep || 1;
|
||||||
|
},
|
||||||
closeOrgModal: (state) => {
|
closeOrgModal: (state) => {
|
||||||
state.OrganizationModal.isOpen = false;
|
state.OrganizationModal.isOpen = false;
|
||||||
|
state.OrganizationModal.orgData = null;
|
||||||
|
state.OrganizationModal.startStep = 1;
|
||||||
|
state.OrganizationModal.prevStep = null;
|
||||||
},
|
},
|
||||||
toggleOrgModal: (state) => {
|
toggleOrgModal: (state) => {
|
||||||
state.OrganizationModal.isOpen = !state.OrganizationModal.isOpen;
|
state.OrganizationModal.isOpen = !state.OrganizationModal.isOpen;
|
||||||
},
|
},
|
||||||
addedOrgModal:(state,action)=>{
|
|
||||||
state.OrganizationModal.orgData = action.payload;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user