Adding Dropdown in Employee.

This commit is contained in:
Kartik Sharma 2025-12-06 10:11:58 +05:30
parent dbf4f5e9c8
commit 0e75a3e1c9
3 changed files with 298 additions and 278 deletions

View File

@ -17,6 +17,8 @@ import {
import showToast from "../../services/toastService"; import showToast from "../../services/toastService";
import { useDocumentContext } from "./Documents"; import { useDocumentContext } from "./Documents";
import { isPending } from "@reduxjs/toolkit"; import { isPending } from "@reduxjs/toolkit";
import { AppFormController, AppFormProvider } from "../../hooks/appHooks/useAppForm";
import SelectField from "../common/Forms/SelectField";
const toBase64 = (file) => const toBase64 = (file) =>
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
@ -72,9 +74,12 @@ const ManageDocument = ({ closeModal, Document_Entity, Entity }) => {
handleSubmit, handleSubmit,
watch, watch,
setValue, setValue,
control,
reset, reset,
formState: { errors }, formState: { errors },
} = methods; } = methods;
const { mutate: UploadDocument, isPending: isUploading } = useUploadDocument( const { mutate: UploadDocument, isPending: isUploading } = useUploadDocument(
() => { () => {
showToast("Document Uploaded Successfully", "success"); showToast("Document Uploaded Successfully", "success");
@ -114,7 +119,7 @@ const ManageDocument = ({ closeModal, Document_Entity, Entity }) => {
const DocumentPayload = { ...payload, entityId: Entity }; const DocumentPayload = { ...payload, entityId: Entity };
UploadDocument(DocumentPayload); UploadDocument(DocumentPayload);
} }
}; };
const { const {
data: DocData, data: DocData,
@ -134,7 +139,7 @@ const ManageDocument = ({ closeModal, Document_Entity, Entity }) => {
const { DocumentTypes, isLoading: isTypeLoading } = useDocumentTypes( const { DocumentTypes, isLoading: isTypeLoading } = useDocumentTypes(
categoryId || null categoryId || null
); );
const {data:DocumentTags} = useDocumentTags() const { data: DocumentTags } = useDocumentTags()
// Update schema whenever document type changes // Update schema whenever document type changes
useEffect(() => { useEffect(() => {
@ -231,66 +236,74 @@ const ManageDocument = ({ closeModal, Document_Entity, Entity }) => {
const isPending = isUploading || isUpdating; const isPending = isUploading || isUpdating;
return ( return (
<AppFormProvider {...methods}>
<div className="p-2"> <div className="p-2">
<p className="fw-bold fs-6">Upload New Document</p> <h5 className="">Upload New Document</h5>
<FormProvider key={documentTypeId} {...methods}> <FormProvider key={documentTypeId} {...methods}>
<form onSubmit={handleSubmit(onSubmit)} className="text-start"> <form onSubmit={handleSubmit(onSubmit)} className="text-start">
{/* Category */} {/* Category */}
<div className="mb-2"> <div className="col-12 col-md-12 mb-2 mb-md-4">
<Label htmlFor="documentCategoryId" required>Document Category</Label> <AppFormController
<select name="documentCategoryId"
{...register("documentCategoryId")} control={control}
className="form-select form-select-sm" render={({ field }) => (
> <SelectField
{isLoading && ( label="Document Category"
<option disabled value=""> options={DocumentCategories ?? []}
Loading... placeholder="Select Category"
</option> required
labelKeyKey="name"
valueKeyKey="id"
value={field.value}
onChange={field.onChange}
isLoading={isLoading}
className="m-0"
/>
)} )}
{!isLoading && <option value="">Select Category</option>} />
{DocumentCategories?.map((type) => (
<option key={type.id} value={type.id}>
{type.name}
</option>
))}
</select>
{errors.documentCategoryId && ( {errors.documentCategoryId && (
<div className="danger-text"> <small className="danger-text">
{errors.documentCategoryId.message} {errors.documentCategoryId.message}
</div> </small>
)} )}
</div> </div>
{/* Type */} {/* Type */}
{categoryId && ( {categoryId && (
<div className="mb-2"> <div className="col-12 col-md-12 mb-2 mb-md-4">
<Label htmlFor="documentTypeId" required>Document Type</Label> <AppFormController
<select name="documentTypeId"
{...register("documentTypeId")} control={control}
className="form-select form-select-sm" render={({ field }) => (
> <SelectField
{isTypeLoading && ( label="Document Type"
<option disabled value=""> options={DocumentTypes ?? []}
Loading... placeholder="Select Document Type"
</option> required
labelKeyKey="name"
valueKeyKey="id"
value={field.value}
onChange={field.onChange}
isLoading={isTypeLoading}
className="m-0"
/>
)} )}
{DocumentTypes?.map((type) => ( />
<option key={type.id} value={type.id}>
{type.name}
</option>
))}
</select>
{errors.documentTypeId && ( {errors.documentTypeId && (
<div className="danger-text"> <small className="danger-text">
{errors.documentTypeId.message} {errors.documentTypeId.message}
</div> </small>
)} )}
</div> </div>
)} )}
{/* Document ID */} {/* Document ID */}
<div className="mb-2"> <div className="mb-4">
<label <label
htmlFor="documentId" htmlFor="documentId"
required={selectedType?.isMandatory ?? false} required={selectedType?.isMandatory ?? false}
@ -299,7 +312,7 @@ const ManageDocument = ({ closeModal, Document_Entity, Entity }) => {
</label> </label>
<input <input
type="text" type="text"
className="form-control form-control-sm" className="form-control "
{...register("documentId")} {...register("documentId")}
/> />
{errors.documentId && ( {errors.documentId && (
@ -314,7 +327,7 @@ const ManageDocument = ({ closeModal, Document_Entity, Entity }) => {
</Label> </Label>
<input <input
type="text" type="text"
className="form-control form-control-sm" className="form-control "
{...register("name")} {...register("name")}
/> />
{errors.name && ( {errors.name && (
@ -325,7 +338,7 @@ const ManageDocument = ({ closeModal, Document_Entity, Entity }) => {
{/* Upload */} {/* Upload */}
<div className="row my-2"> <div className="row my-4">
<div className="col-md-12"> <div className="col-md-12">
<Label htmlFor="attachment" required>Upload Document</Label> <Label htmlFor="attachment" required>Upload Document</Label>
@ -384,7 +397,7 @@ const ManageDocument = ({ closeModal, Document_Entity, Entity }) => {
)} )}
</div> </div>
</div> </div>
<div className="mb-2"> <div className="mb-4">
<TagInput name="tags" label="Tags" placeholder="Tags.." options={DocumentTags} /> <TagInput name="tags" label="Tags" placeholder="Tags.." options={DocumentTags} />
{errors.tags && ( {errors.tags && (
<small className="danger-text">{errors.tags.message}</small> <small className="danger-text">{errors.tags.message}</small>
@ -392,7 +405,7 @@ const ManageDocument = ({ closeModal, Document_Entity, Entity }) => {
</div> </div>
{/* Description */} {/* Description */}
<div className="mb-2"> <div className="mb-4">
<Label htmlFor="description" required>Description</Label> <Label htmlFor="description" required>Description</Label>
<textarea <textarea
rows="2" rows="2"
@ -425,6 +438,7 @@ const ManageDocument = ({ closeModal, Document_Entity, Entity }) => {
</form> </form>
</FormProvider> </FormProvider>
</div> </div>
</AppFormProvider>
); );
}; };

View File

@ -517,39 +517,35 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
</div> </div>
</div> </div>
<div className="row mb-3"> <div className="row mb-3">
<div className="col-sm-4"> <div className="col-sm-4 text-start">
<Label className="form-text text-start" required> <AppFormController
Official Designation name="jobRoleId"
</Label> control={control}
<div className="input-group"> render={({ field }) => (
<select <SelectField
className="form-select" label="Official Designation"
{...register("jobRoleId")} required
id="jobRoleId" options={[...job_role].sort((a, b) =>
aria-label="" a?.name?.localeCompare(b?.name)
> )}
<option disabled value=""> placeholder="Select Role"
Select Role labelKeyKey="name"
</option> valueKeyKey="id"
{[...job_role] value={field.value}
.sort((a, b) => a?.name?.localeCompare(b.name)) onChange={field.onChange}
.map((item) => ( className="m-0"
<option value={item?.id} key={item.id}> />
{item?.name}{" "} )}
</option> />
))}
</select>
</div>
{errors.jobRoleId && ( {errors.jobRoleId && (
<div <div className="danger-text text-start" style={{ fontSize: "12px" }}>
className="danger-text text-start"
style={{ fontSize: "12px" }}
>
{errors.jobRoleId.message} {errors.jobRoleId.message}
</div> </div>
)} )}
</div> </div>
<div className="col-sm-4">
<div className="col-sm-4 mt-n1">
<Label className="form-text text-start" required> <Label className="form-text text-start" required>
Emergency Contact Person Emergency Contact Person
</Label> </Label>
@ -570,7 +566,7 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
</div> </div>
)} )}
</div> </div>
<div className="col-sm-4"> <div className="col-sm-4 mt-n1">
<Label className="form-text text-start" required> <Label className="form-text text-start" required>
Emergency Phone Number Emergency Phone Number
</Label> </Label>

View File

@ -10,6 +10,8 @@ import { useForm, Controller } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod"; import { z } from "zod";
import showToast from "../../services/toastService"; import showToast from "../../services/toastService";
import { AppFormController } from "../../hooks/appHooks/useAppForm";
import SelectField from "../common/Forms/SelectField";
export const ProjectPermissionSchema = z.object({ export const ProjectPermissionSchema = z.object({
employeeId: z.string().min(1, "Employee is required"), employeeId: z.string().min(1, "Employee is required"),
@ -54,16 +56,16 @@ const ProjectPermission = () => {
?.map((perm) => perm.id) || []; ?.map((perm) => perm.id) || [];
setValue("selectedPermissions", enabledPerms, { shouldValidate: true }); setValue("selectedPermissions", enabledPerms, { shouldValidate: true });
}, [selectedEmpPermissions, setValue, selectedEmployee]); }, [selectedEmpPermissions, setValue, selectedEmployee]);
const selectedPermissions = watch("selectedPermissions") || []; const selectedPermissions = watch("selectedPermissions") || [];
const existingEnabledIds = const existingEnabledIds =
selectedEmpPermissions?.permissions selectedEmpPermissions?.permissions
?.filter((p) => p.isEnabled) ?.filter((p) => p.isEnabled)
?.map((p) => p.id) || []; ?.map((p) => p.id) || [];
const hasChanges = const hasChanges =
selectedPermissions.length !== existingEnabledIds.length || selectedPermissions.length !== existingEnabledIds.length ||
selectedPermissions.some((id) => !existingEnabledIds.includes(id)); selectedPermissions.some((id) => !existingEnabledIds.includes(id));
@ -115,35 +117,42 @@ const hasChanges =
<form className="row" onSubmit={handleSubmit(onSubmit)}> <form className="row" onSubmit={handleSubmit(onSubmit)}>
<div className="d-flex justify-content-between align-items-end gap-2 mb-3"> <div className="d-flex justify-content-between align-items-end gap-2 mb-3">
<div className="text-start d-flex align-items-center gap-2"> <div className="text-start d-flex align-items-center gap-2">
<div className="d-block"> {/* <div className="d-block">
<label className="form-label">Select Employee</label> <label className="form-label">Select Employee</label>
</div> </div> */}
<div className="d-block">
{" "} <div className="d-block flex-grow-1">
<select <AppFormController
className="form-select form-select-sm" name="employeeId"
{...register("employeeId")} control={control}
disabled={isPending} render={({ field }) => (
> <SelectField
{loading ? ( label="Select Employee"
<option value="">Loading...</option> options={
) : ( employees
<>
<option value="">-- Select Employee --</option>
{[...employees]
?.sort((a, b) => ?.sort((a, b) =>
`${a?.firstName} ${a?.firstName}`?.localeCompare( `${a?.firstName} ${a?.lastName}`.localeCompare(
`${b?.firstName} ${b?.lastName}` `${b?.firstName} ${b?.lastName}`
) )
) )
?.map((emp) => ( ?.map((emp) => ({
<option key={emp.id} value={emp.id}> id: emp.id,
{emp.firstName} {emp.lastName} name: `${emp.firstName} ${emp.lastName}`,
</option> })) ?? []
))} }
</> placeholder="-- Select Employee --"
required
labelKeyKey="name"
valueKeyKey="id"
value={field.value}
onChange={field.onChange}
isLoading={loading}
disabled={isPending}
className="m-0"
/>
)} )}
</select> />
{errors.employeeId && ( {errors.employeeId && (
<div className="d-block text-danger small"> <div className="d-block text-danger small">
{errors.employeeId.message} {errors.employeeId.message}
@ -152,6 +161,7 @@ const hasChanges =
</div> </div>
</div> </div>
<div className="mt-3 text-end"> <div className="mt-3 text-end">
{hasChanges && ( {hasChanges && (
<button <button