fixed Modal provider component and setup organization creation

This commit is contained in:
pramod mahajan 2025-09-17 19:45:42 +05:30
parent 78a0ecebf1
commit a48fc1d989
8 changed files with 145 additions and 48 deletions

View File

@ -1,14 +1,12 @@
import React from 'react' import React from 'react'
import Modal from './components/common/Modal'
import ManageOrganization from './components/Organization/ManageOrganization' import ManageOrganization from './components/Organization/ManageOrganization'
import { useOrganizationModal } from './hooks/useOrganization';
const ModalProvider = () => { const ModalProvider = () => {
return ( const { isOpen } = useOrganizationModal();
<>
return <>{isOpen && <ManageOrganization />}</>;
};
<ManageOrganization/>
</>
)
}
export default ModalProvider export default ModalProvider

View File

@ -6,77 +6,135 @@ import {
organizationSchema, organizationSchema,
} from "./OrganizationSchema"; } from "./OrganizationSchema";
import Modal from "../common/Modal"; import Modal from "../common/Modal";
import { useOrganization } from "../../hooks/useDirectory"; import { useCreateOrganization, useOrganizationModal } from "../../hooks/useOrganization";
import { useOrganizationModal } from "../../hooks/useOrganization";
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";
const ManageOrganization = () => { const ManageOrganization = () => {
const orgModal = useOrganizationModal(); const orgModal = useOrganizationModal();
const { data: services,isLoading } = useServices();
const method = useForm({ const method = useForm({
resolver: zodResolver(organizationSchema), resolver: zodResolver(organizationSchema),
defaultValues: defaultOrganizationValues, defaultValues: defaultOrganizationValues,
}); });
const { handleSubmit, watch, register } = method; const {
handleSubmit,
register,
formState: { errors },
} = method;
const onSubmit = () => {}; const {mutate:CreateOrganization,isPending} = useCreateOrganization(()=>{})
const onSubmit = (OrgPayload) => {
CreateOrganization()
};
console.log(services)
const contentBody = ( const contentBody = (
<FormProvider {...method}> <FormProvider {...method}>
<form className="form" onSubmit={handleSubmit(onSubmit)}> <form className="form" onSubmit={handleSubmit(onSubmit)}>
<div className="mb-1 text-start"> <div className="mb-1 text-start">
<Label htmlFor="organization" required> <Label htmlFor="name" required>
Organization Name Organization Name
</Label> </Label>
<input className="form-control form-control-sm" /> <input
className="form-control form-control-sm"
{...register("name")}
/>
{errors.name && (
<span className="danger-text">{errors.name.message}</span>
)}
</div> </div>
<div className="mb-1 text-start"> <div className="mb-1 text-start">
<Label htmlFor="organization" required> <Label htmlFor="contactPerson" required>
Contact Person Contact Person
</Label> </Label>
<input className="form-control form-control-sm" /> <input
className="form-control form-control-sm"
{...register("contactPerson")}
/>
{errors.contactPerson && (
<span className="danger-text">{errors.contactPerson.message}</span>
)}
</div> </div>
<div className="mb-1 text-start"> <div className="mb-1 text-start">
<Label htmlFor="organization" required> <Label htmlFor="contactNumber" required>
Contact Number Contact Number
</Label> </Label>
<input className="form-control form-control-sm" /> <input
className="form-control form-control-sm"
{...register("contactNumber")}
/>
{errors.contactNumber && (
<span className="danger-text">{errors.contactNumber.message}</span>
)}
</div> </div>
<div className="mb-1 text-start"> <div className="mb-1 text-start">
<Label htmlFor="organization" required> <Label htmlFor="email" required>
Email Address Email Address
</Label> </Label>
<input className="form-control form-control-sm" /> <input
className="form-control form-control-sm"
{...register("email")}
/>
{errors.email && (
<span className="danger-text">{errors.email.message}</span>
)}
</div> </div>
<div className="mb-1 text-start"> <div className="mb-1 text-start">
<SelectMultiple <SelectMultiple
name="serviceIds" name="serviceIds"
label="Services" label="Services"
required={true} required={true}
valueKey="id" valueKey="id"
options={services?.data || []}
/> />
{errors.serviceIds && (
<span className="danger-text">{errors.serviceIds.message}</span>
)}
</div> </div>
<div className="mb-1 text-start"> <div className="mb-1 text-start">
<Label htmlFor="organization" required> <Label htmlFor="address" required>
Address Address
</Label> </Label>
<textarea className="form-control form-control-sm" rows={2} /> <textarea
className="form-control form-control-sm"
{...register("address")}
rows={2}
/>
{errors.address && (
<span className="danger-text">{errors.address.message}</span>
)}
</div> </div>
<div className="d-flex justify-content-end gap-2 my-2"> <div className="d-flex justify-content-end gap-2 my-2">
<button className="btn btn-sm btn-secondary">Cancel</button> <button
<button className="btn btn-sm btn-primary">Submit</button> type="button"
className="btn btn-sm btn-secondary"
onClick={orgModal.onClose} disabled={isPending || isLoading}
>
Cancel
</button>
<button type="submit" className="btn btn-sm btn-primary" disabled={isPending || isLoading}>
{isPending ? "Please Wait...":"Submit"}
</button>
</div> </div>
</form> </form>
</FormProvider> </FormProvider>
); );
return ( return (
<Modal <Modal
isOpen={orgModal.isOpen} isOpen={orgModal.isOpen}
onClose={orgModal.onClose} onClose={orgModal.onClose}
onSubmit={onSubmit} title="Manage Organization"
title={"Manage Organization"}
actionLabel={"Submit"}
body={contentBody} body={contentBody}
/> />
); );

View File

@ -3,12 +3,13 @@ import { array, z } from "zod";
const phoneRegex = /^\+?[1-9]\d{6,14}$/; const phoneRegex = /^\+?[1-9]\d{6,14}$/;
export const organizationSchema = z.object({ export const organizationSchema = z.object({
organizationName: z.string().min(1, { message: "Name is required" }), name: z.string().min(1, { message: "Name is required" }),
contactPhone: z contactNumber: z
.string() .string()
.trim() .trim()
.min(7) .min(7, { message: "Contact number must be at least 7 digits" })
.max(20) .max(20, { message: "Contact number cannot exceed 12 digits" })
.regex(phoneRegex, { message: "Invalid phone number" }), .regex(phoneRegex, { message: "Invalid phone number" }),
contactPerson: z.string().min(1, { message: "Person name required" }), contactPerson: z.string().min(1, { message: "Person name required" }),
address: z.string().min(1, { message: "Address is required!" }), address: z.string().min(1, { message: "Address is required!" }),
@ -16,17 +17,16 @@ export const organizationSchema = z.object({
.string() .string()
.min(1, { message: "Email is required" }) .min(1, { message: "Email is required" })
.email("Invalid email address"), .email("Invalid email address"),
listOfServiceId: z serviceIds: z
.array(z.string()) .array(z.string())
.min(1, { message: "Please insert service id" }), .min(1, { message: "Please insert service id" }),
}); });
export const defaultOrganizationValues = { export const defaultOrganizationValues = {
organizationSchema:"", name: "",
contactPhone:"", contactNumber: "",
contactPerson:"", contactPerson: "",
address:"", address: "",
email:"", email: "",
listOfServiceId:[] serviceIds: [],
} };

View File

@ -12,7 +12,6 @@ const SelectMultiple = ({
valueKey = "id", valueKey = "id",
placeholder = "Please select...", placeholder = "Please select...",
IsLoading = false, IsLoading = false,
required = false,
}) => { }) => {
const { setValue, watch } = useFormContext(); const { setValue, watch } = useFormContext();
const selectedValues = watch(name) || []; const selectedValues = watch(name) || [];
@ -147,9 +146,7 @@ const SelectMultiple = ({
className="multi-select-dropdown-container" className="multi-select-dropdown-container"
style={{ position: "relative" }} style={{ position: "relative" }}
> >
<Label htmlFor={name} required={required}> <label>{label}</label>
{label}
</Label>
<div <div
className="multi-select-dropdown-header" className="multi-select-dropdown-header"

View File

@ -9,7 +9,12 @@ import showToast from "../../services/toastService";
export const useServices = ()=>{
return useQuery({
queryKey:["services"],
queryFn:async()=> await MasterRespository.getServices()
})
}
export const useMasterMenu = ()=>{ export const useMasterMenu = ()=>{
return useQuery({ return useQuery({

View File

@ -1,16 +1,42 @@
import { useSelector, useDispatch } from "react-redux"; import { useSelector, useDispatch } from "react-redux";
import { toggleOrgModal,openOrgModal,closeOrgModal } from "../slices/localVariablesSlice"; import {
toggleOrgModal,
openOrgModal,
closeOrgModal,
} from "../slices/localVariablesSlice";
import { useMutation } from "@tanstack/react-query";
import OrganizationRepository from "../repositories/OrganizationRespository";
import showToast from "../services/toastService";
export const useOrganizationModal = () => { export const useOrganizationModal = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const isOpen = useSelector((state) => state.localVariables.OrganizationModal.isOpen); const isOpen = useSelector(
(state) => state.localVariables.OrganizationModal.isOpen
);
return { return {
isOpen, isOpen,
onOpen: () => dispatch(openOrgModal()), onOpen: () => dispatch(openOrgModal()),
onClose: () => dispatch(closeOrgModal()), onClose: () => dispatch(closeOrgModal()),
Togggle:()=> dispatch(toggleOrgModal(isOpen)) Togggle: () => dispatch(toggleOrgModal(isOpen)),
}; };
}; };
export const useCreateOrganization = (onSuccessCallback) => {
return useMutation({
mutationFn: async (OrgPayload) =>
await OrganizationRepository.createOrganization(OrgPayload),
onSuccess: (_, variables) => {
showToast("Organization created successfully", "success");
if (onSuccessCallback) onSuccessCallback();
},
onError: (error) => {
showToast(
error.response.data.message ||
error.message ||
"Something went wrong please try again !",
"error"
);
},
});
};

View File

@ -106,4 +106,8 @@ export const MasterRespository = {
createDocumentType: (data) => api.post(`/api/Master/document-type`, data), createDocumentType: (data) => api.post(`/api/Master/document-type`, data),
updateDocumentType: (id, data) => updateDocumentType: (id, data) =>
api.put(`/api/Master/document-type/edit/${id}`, data), api.put(`/api/Master/document-type/edit/${id}`, data),
getServices:()=>api.get("/api/Master/global-service/list")
}; };

View File

@ -0,0 +1,9 @@
import { api } from "../utils/axiosClient";
const OrganizationRepository = {
createOrganization:(data)=>api.post('/api/Organization/create',data)
}
export default OrganizationRepository;