269 lines
8.8 KiB
JavaScript
269 lines
8.8 KiB
JavaScript
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,
|
|
useAssignOrgToTenant,
|
|
useOrganizationModal,
|
|
} from "../../hooks/useOrganization";
|
|
|
|
const AssignOrg = ({ setStep }) => {
|
|
const { isOpen, orgData, startStep, onOpen, flowType, prevStep, onClose } =
|
|
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: isPendingProject } =
|
|
useAssignOrgToProject(() => onClose());
|
|
const { mutate: AssignToTenant, isPending: isPendingTenat } =
|
|
useAssignOrgToTenant(() => {
|
|
onClose();
|
|
});
|
|
const isPending = isPendingProject || isPendingTenat;
|
|
const mergedServices = useMemo(() => {
|
|
if (!masterService || !projectServices) return [];
|
|
const combined = [...masterService?.data, ...projectServices];
|
|
return combined.filter(
|
|
(item, index, self) => index === self.findIndex((s) => s.id === item.id)
|
|
);
|
|
}, [masterService, projectServices]);
|
|
|
|
const resolver =
|
|
flowType === "default" ? undefined : zodResolver(assignedOrgToProject);
|
|
|
|
const {
|
|
register,
|
|
handleSubmit,
|
|
setValue,
|
|
formState: { errors },
|
|
} = useForm({
|
|
resolver,
|
|
defaultValues: {
|
|
organizationTypeId: "",
|
|
serviceIds: [],
|
|
},
|
|
});
|
|
|
|
const onSubmit = (formData) => {
|
|
if (flowType === "default") {
|
|
const payload = orgData.id;
|
|
|
|
AssignToTenant(payload);
|
|
} else {
|
|
const payload = {
|
|
...formData,
|
|
projectId: selectedProject,
|
|
organizationId: orgData.id,
|
|
parentOrganizationId: null,
|
|
};
|
|
AssignToProject(payload);
|
|
}
|
|
};
|
|
|
|
const handleEdit = () => {
|
|
onOpen({ startStep: 4, orgData });
|
|
};
|
|
|
|
const handleBack = () => {
|
|
if (prevStep === 1 && flowType === "assign") {
|
|
onOpen({ startStep: prevStep });
|
|
} else if (prevStep === 1 && flowType !== "assign") {
|
|
onOpen({ startStep: 1 });
|
|
} else {
|
|
onOpen({ startStep: 2 });
|
|
}
|
|
};
|
|
|
|
if (isMasterserviceLoading || isLoading)
|
|
return <div className="text-center">Loading....</div>;
|
|
|
|
return (
|
|
<div className="row text-black text-start mb-3">
|
|
{/* Organization Info Display */}
|
|
<div className="col-12 mb-3">
|
|
<div className="d-flex justify-content-between align-items-center text-start mb-1">
|
|
<div className="d-flex flex-row gap-2 align-items-center text-wrap">
|
|
<img
|
|
src="/public/assets/img/orgLogo.png"
|
|
alt="logo"
|
|
width={40}
|
|
height={40}
|
|
/> <p className="fw-semibold fs-6 m-0">{orgData.name}</p>
|
|
</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>
|
|
<div className="d-flex text-secondary mb-2"> <i className="bx bx-sm bx-info-circle me-1" /> Organization Info</div>
|
|
{/* Contact Info */}
|
|
<div className="col-md-6 mb-3">
|
|
<div className="d-flex">
|
|
<label
|
|
className="form-label me-2 mb-0 fw-semibold"
|
|
style={{ minWidth: "130px" }}
|
|
>
|
|
<i className="bx bx-sm bx-user me-1" /> Contact Person :
|
|
</label>
|
|
<div className="text-muted">{orgData.contactPerson}</div>
|
|
</div>
|
|
</div>
|
|
<div className="col-md-6 mb-3">
|
|
<div className="d-flex">
|
|
<label
|
|
className="form-label me-2 mb-0 fw-semibold"
|
|
style={{ minWidth: "130px" }}
|
|
>
|
|
<i className='bx bx-sm me-1 bx-phone'></i> 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"
|
|
style={{ minWidth: "130px" }}
|
|
>
|
|
<i className='bx bx-sm me-1 bx-envelope'></i> 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"
|
|
style={{ maxWidth: "130px" }}
|
|
>
|
|
<i className="bx bx-sm me-1 bx-barcode"></i>
|
|
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"
|
|
style={{ minWidth: "130px" }}
|
|
>
|
|
<i className='bx bx-sm me-1 bx-map'></i> Address :
|
|
</label>
|
|
<div className="text-muted text-start">{orgData.address}</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Form */}
|
|
<div className="text-black text-start">
|
|
<form onSubmit={handleSubmit(onSubmit)}>
|
|
{/* Show fields only if flowType is NOT default */}
|
|
{flowType !== "default" && (
|
|
<>
|
|
{/* Organization Type */}
|
|
<div className="mb-3 text-start">
|
|
<Label htmlFor="organizationTypeId" className="mb-3 fw-semibold" required>
|
|
Organization Type
|
|
</Label>
|
|
<div className="d-flex flex-wrap gap-3 mt-1">
|
|
{orgType?.data.map((type) => (
|
|
<div
|
|
key={type.id}
|
|
className="form-check d-flex align-items-center gap-2 p-0 m-0"
|
|
>
|
|
<input
|
|
type="radio"
|
|
id={`organizationType-${type.id}`}
|
|
value={type.id}
|
|
{...register("organizationTypeId")}
|
|
className="form-check-input m-0"
|
|
/>
|
|
<label
|
|
className="form-check-label m-0"
|
|
htmlFor={`organizationType-${type.id}`}
|
|
>
|
|
{type.name}
|
|
</label>
|
|
</div>
|
|
))}
|
|
</div>
|
|
{errors.organizationTypeId && (
|
|
<span className="text-danger">
|
|
{errors.organizationTypeId.message}
|
|
</span>
|
|
)}
|
|
</div>
|
|
|
|
{/* Services */}
|
|
<div className="mb-3">
|
|
<Label htmlFor="serviceIds" className="mb-3 fw-semibold" required>
|
|
Select Services
|
|
</Label>
|
|
{mergedServices?.map((service) => (
|
|
<div key={service.id} className="form-check mb-3">
|
|
<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: Always visible */}
|
|
<div className="d-flex justify-content-between mt-5">
|
|
<button
|
|
type="button"
|
|
className="btn btn-sm btn-outline-secondary"
|
|
onClick={handleBack}
|
|
disabled={isPending}
|
|
>
|
|
<i className="bx bx-chevron-left"></i>Back
|
|
</button>
|
|
<button
|
|
type="submit"
|
|
className="btn btn-sm btn-primary"
|
|
disabled={isPending}
|
|
>
|
|
{isPending
|
|
? "Please wait..."
|
|
: flowType === "default"
|
|
? "Assign to Organization"
|
|
: "Assign to Project"}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default AssignOrg;
|