Adding Dropdown in Employee.
This commit is contained in:
parent
dbf4f5e9c8
commit
0e75a3e1c9
@ -17,6 +17,8 @@ import {
|
||||
import showToast from "../../services/toastService";
|
||||
import { useDocumentContext } from "./Documents";
|
||||
import { isPending } from "@reduxjs/toolkit";
|
||||
import { AppFormController, AppFormProvider } from "../../hooks/appHooks/useAppForm";
|
||||
import SelectField from "../common/Forms/SelectField";
|
||||
|
||||
const toBase64 = (file) =>
|
||||
new Promise((resolve, reject) => {
|
||||
@ -72,9 +74,12 @@ const ManageDocument = ({ closeModal, Document_Entity, Entity }) => {
|
||||
handleSubmit,
|
||||
watch,
|
||||
setValue,
|
||||
control,
|
||||
reset,
|
||||
formState: { errors },
|
||||
} = methods;
|
||||
|
||||
|
||||
const { mutate: UploadDocument, isPending: isUploading } = useUploadDocument(
|
||||
() => {
|
||||
showToast("Document Uploaded Successfully", "success");
|
||||
@ -88,33 +93,33 @@ const ManageDocument = ({ closeModal, Document_Entity, Entity }) => {
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
|
||||
const onSubmit = (data) => {
|
||||
const normalizeAttachment = (attachment) => {
|
||||
if (!attachment) return null;
|
||||
return {
|
||||
...attachment,
|
||||
fileSize: Math.ceil(attachment.fileSize / 1024),
|
||||
const normalizeAttachment = (attachment) => {
|
||||
if (!attachment) return null;
|
||||
return {
|
||||
...attachment,
|
||||
fileSize: Math.ceil(attachment.fileSize / 1024),
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
const payload = {
|
||||
...data,
|
||||
attachment: normalizeAttachment(data.attachment),
|
||||
};
|
||||
|
||||
if (ManageDoc?.document) {
|
||||
const DocumentPayload = {
|
||||
...payload,
|
||||
id: DocData.id,
|
||||
tags: MergedTagsWithExistenStatus(data?.tags, DocData?.tags),
|
||||
const payload = {
|
||||
...data,
|
||||
attachment: normalizeAttachment(data.attachment),
|
||||
};
|
||||
UpdateDocument({ documentId: DocData?.id, DocumentPayload });
|
||||
} else {
|
||||
const DocumentPayload = { ...payload, entityId: Entity };
|
||||
UploadDocument(DocumentPayload);
|
||||
}
|
||||
};
|
||||
|
||||
if (ManageDoc?.document) {
|
||||
const DocumentPayload = {
|
||||
...payload,
|
||||
id: DocData.id,
|
||||
tags: MergedTagsWithExistenStatus(data?.tags, DocData?.tags),
|
||||
};
|
||||
UpdateDocument({ documentId: DocData?.id, DocumentPayload });
|
||||
} else {
|
||||
const DocumentPayload = { ...payload, entityId: Entity };
|
||||
UploadDocument(DocumentPayload);
|
||||
}
|
||||
};
|
||||
|
||||
const {
|
||||
data: DocData,
|
||||
@ -134,7 +139,7 @@ const ManageDocument = ({ closeModal, Document_Entity, Entity }) => {
|
||||
const { DocumentTypes, isLoading: isTypeLoading } = useDocumentTypes(
|
||||
categoryId || null
|
||||
);
|
||||
const {data:DocumentTags} = useDocumentTags()
|
||||
const { data: DocumentTags } = useDocumentTags()
|
||||
|
||||
// Update schema whenever document type changes
|
||||
useEffect(() => {
|
||||
@ -144,7 +149,7 @@ const ManageDocument = ({ closeModal, Document_Entity, Entity }) => {
|
||||
(t) => String(t.id) === String(documentTypeId)
|
||||
);
|
||||
if (!type) return;
|
||||
setSelectedType(type)
|
||||
setSelectedType(type)
|
||||
const newSchema = DocumentPayloadSchema({
|
||||
isMandatory: type.isMandatory ?? false,
|
||||
regexExpression: type.regexExpression ?? null,
|
||||
@ -200,10 +205,10 @@ const ManageDocument = ({ closeModal, Document_Entity, Entity }) => {
|
||||
t === "application/pdf"
|
||||
? ".pdf"
|
||||
: t === "image/jpeg"
|
||||
? ".jpg,.jpeg"
|
||||
: t === "image/png"
|
||||
? ".png"
|
||||
: ""
|
||||
? ".jpg,.jpeg"
|
||||
: t === "image/png"
|
||||
? ".png"
|
||||
: ""
|
||||
)
|
||||
.join(",") || "";
|
||||
|
||||
@ -231,200 +236,209 @@ const ManageDocument = ({ closeModal, Document_Entity, Entity }) => {
|
||||
|
||||
const isPending = isUploading || isUpdating;
|
||||
return (
|
||||
<div className="p-2">
|
||||
<p className="fw-bold fs-6">Upload New Document</p>
|
||||
<FormProvider key={documentTypeId} {...methods}>
|
||||
<form onSubmit={handleSubmit(onSubmit)} className="text-start">
|
||||
{/* Category */}
|
||||
<div className="mb-2">
|
||||
<Label htmlFor="documentCategoryId" required>Document Category</Label>
|
||||
<select
|
||||
{...register("documentCategoryId")}
|
||||
className="form-select form-select-sm"
|
||||
>
|
||||
{isLoading && (
|
||||
<option disabled value="">
|
||||
Loading...
|
||||
</option>
|
||||
)}
|
||||
{!isLoading && <option value="">Select Category</option>}
|
||||
{DocumentCategories?.map((type) => (
|
||||
<option key={type.id} value={type.id}>
|
||||
{type.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
{errors.documentCategoryId && (
|
||||
<div className="danger-text">
|
||||
{errors.documentCategoryId.message}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Type */}
|
||||
{categoryId && (
|
||||
<div className="mb-2">
|
||||
<Label htmlFor="documentTypeId" required>Document Type</Label>
|
||||
<select
|
||||
{...register("documentTypeId")}
|
||||
className="form-select form-select-sm"
|
||||
>
|
||||
{isTypeLoading && (
|
||||
<option disabled value="">
|
||||
Loading...
|
||||
</option>
|
||||
<AppFormProvider {...methods}>
|
||||
<div className="p-2">
|
||||
<h5 className="">Upload New Document</h5>
|
||||
<FormProvider key={documentTypeId} {...methods}>
|
||||
<form onSubmit={handleSubmit(onSubmit)} className="text-start">
|
||||
{/* Category */}
|
||||
<div className="col-12 col-md-12 mb-2 mb-md-4">
|
||||
<AppFormController
|
||||
name="documentCategoryId"
|
||||
control={control}
|
||||
render={({ field }) => (
|
||||
<SelectField
|
||||
label="Document Category"
|
||||
options={DocumentCategories ?? []}
|
||||
placeholder="Select Category"
|
||||
required
|
||||
labelKeyKey="name"
|
||||
valueKeyKey="id"
|
||||
value={field.value}
|
||||
onChange={field.onChange}
|
||||
isLoading={isLoading}
|
||||
className="m-0"
|
||||
/>
|
||||
)}
|
||||
{DocumentTypes?.map((type) => (
|
||||
<option key={type.id} value={type.id}>
|
||||
{type.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
{errors.documentTypeId && (
|
||||
<div className="danger-text">
|
||||
{errors.documentTypeId.message}
|
||||
</div>
|
||||
/>
|
||||
|
||||
{errors.documentCategoryId && (
|
||||
<small className="danger-text">
|
||||
{errors.documentCategoryId.message}
|
||||
</small>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
{/* Document ID */}
|
||||
<div className="mb-2">
|
||||
<label
|
||||
htmlFor="documentId"
|
||||
required={selectedType?.isMandatory ?? false}
|
||||
>
|
||||
Document ID
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control form-control-sm"
|
||||
{...register("documentId")}
|
||||
/>
|
||||
{errors.documentId && (
|
||||
<div className="danger-text">{errors.documentId.message}</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Document Name */}
|
||||
<div className="mb-2">
|
||||
<Label htmlFor="name" required>
|
||||
Document Name
|
||||
</Label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control form-control-sm"
|
||||
{...register("name")}
|
||||
/>
|
||||
{errors.name && (
|
||||
<div className="danger-text">{errors.name.message}</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
{/* Upload */}
|
||||
<div className="row my-2">
|
||||
<div className="col-md-12">
|
||||
<Label htmlFor="attachment" required>Upload Document</Label>
|
||||
|
||||
<div
|
||||
className="border border-secondary border-dashed rounded p-4 text-center bg-textMuted position-relative"
|
||||
style={{ cursor: "pointer" }}
|
||||
onClick={() => document.getElementById("attachment").click()}
|
||||
>
|
||||
<i className="bx bx-cloud-upload d-block bx-lg"></i>
|
||||
<span className="text-muted d-block">
|
||||
Click to select or click here to browse
|
||||
</span>
|
||||
<small className="text-muted">
|
||||
({selectedType?.allowedContentType || "PDF/JPG/PNG"}, max{" "}
|
||||
{selectedType?.maxSizeAllowedInMB ?? 25}MB)
|
||||
</small>
|
||||
|
||||
<input
|
||||
type="file"
|
||||
id="attachment"
|
||||
accept={selectedType?.allowedContentType}
|
||||
style={{ display: "none" }}
|
||||
onChange={(e) => {
|
||||
onFileChange(e);
|
||||
e.target.value = ""; // reset input
|
||||
}}
|
||||
{/* Type */}
|
||||
{categoryId && (
|
||||
<div className="col-12 col-md-12 mb-2 mb-md-4">
|
||||
<AppFormController
|
||||
name="documentTypeId"
|
||||
control={control}
|
||||
render={({ field }) => (
|
||||
<SelectField
|
||||
label="Document Type"
|
||||
options={DocumentTypes ?? []}
|
||||
placeholder="Select Document Type"
|
||||
required
|
||||
labelKeyKey="name"
|
||||
valueKeyKey="id"
|
||||
value={field.value}
|
||||
onChange={field.onChange}
|
||||
isLoading={isTypeLoading}
|
||||
className="m-0"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
{errors.documentTypeId && (
|
||||
<small className="danger-text">
|
||||
{errors.documentTypeId.message}
|
||||
</small>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{errors.attachment && (
|
||||
<small className="danger-text">
|
||||
{errors.attachment.message
|
||||
? errors.attachment.message
|
||||
: errors.attachment.fileName?.message ||
|
||||
)}
|
||||
|
||||
|
||||
{/* Document ID */}
|
||||
<div className="mb-4">
|
||||
<label
|
||||
htmlFor="documentId"
|
||||
required={selectedType?.isMandatory ?? false}
|
||||
>
|
||||
Document ID
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control "
|
||||
{...register("documentId")}
|
||||
/>
|
||||
{errors.documentId && (
|
||||
<div className="danger-text">{errors.documentId.message}</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Document Name */}
|
||||
<div className="mb-2">
|
||||
<Label htmlFor="name" required>
|
||||
Document Name
|
||||
</Label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control "
|
||||
{...register("name")}
|
||||
/>
|
||||
{errors.name && (
|
||||
<div className="danger-text">{errors.name.message}</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
{/* Upload */}
|
||||
<div className="row my-4">
|
||||
<div className="col-md-12">
|
||||
<Label htmlFor="attachment" required>Upload Document</Label>
|
||||
|
||||
<div
|
||||
className="border border-secondary border-dashed rounded p-4 text-center bg-textMuted position-relative"
|
||||
style={{ cursor: "pointer" }}
|
||||
onClick={() => document.getElementById("attachment").click()}
|
||||
>
|
||||
<i className="bx bx-cloud-upload d-block bx-lg"></i>
|
||||
<span className="text-muted d-block">
|
||||
Click to select or click here to browse
|
||||
</span>
|
||||
<small className="text-muted">
|
||||
({selectedType?.allowedContentType || "PDF/JPG/PNG"}, max{" "}
|
||||
{selectedType?.maxSizeAllowedInMB ?? 25}MB)
|
||||
</small>
|
||||
|
||||
<input
|
||||
type="file"
|
||||
id="attachment"
|
||||
accept={selectedType?.allowedContentType}
|
||||
style={{ display: "none" }}
|
||||
onChange={(e) => {
|
||||
onFileChange(e);
|
||||
e.target.value = ""; // reset input
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{errors.attachment && (
|
||||
<small className="danger-text">
|
||||
{errors.attachment.message
|
||||
? errors.attachment.message
|
||||
: errors.attachment.fileName?.message ||
|
||||
errors.attachment.base64Data?.message ||
|
||||
errors.attachment.contentType?.message ||
|
||||
errors.attachment.fileSize?.message}
|
||||
</small>
|
||||
)}
|
||||
</small>
|
||||
)}
|
||||
|
||||
{file?.base64Data && (
|
||||
<div className="d-flex justify-content-between text-start p-1 mt-2">
|
||||
<div>
|
||||
<span className="mb-0 text-secondary small d-block">
|
||||
{file.fileName}
|
||||
</span>
|
||||
<span className="text-body-secondary small d-block">
|
||||
{(file.fileSize / 1024).toFixed(1)} KB
|
||||
</span>
|
||||
{file?.base64Data && (
|
||||
<div className="d-flex justify-content-between text-start p-1 mt-2">
|
||||
<div>
|
||||
<span className="mb-0 text-secondary small d-block">
|
||||
{file.fileName}
|
||||
</span>
|
||||
<span className="text-body-secondary small d-block">
|
||||
{(file.fileSize / 1024).toFixed(1)} KB
|
||||
</span>
|
||||
</div>
|
||||
<i
|
||||
className="bx bx-trash bx-sm cursor-pointer text-danger"
|
||||
onClick={removeFile}
|
||||
></i>
|
||||
</div>
|
||||
<i
|
||||
className="bx bx-trash bx-sm cursor-pointer text-danger"
|
||||
onClick={removeFile}
|
||||
></i>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mb-4">
|
||||
<TagInput name="tags" label="Tags" placeholder="Tags.." options={DocumentTags} />
|
||||
{errors.tags && (
|
||||
<small className="danger-text">{errors.tags.message}</small>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mb-2">
|
||||
<TagInput name="tags" label="Tags" placeholder="Tags.." options={DocumentTags} />
|
||||
{errors.tags && (
|
||||
<small className="danger-text">{errors.tags.message}</small>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Description */}
|
||||
<div className="mb-2">
|
||||
<Label htmlFor="description" required>Description</Label>
|
||||
<textarea
|
||||
rows="2"
|
||||
className="form-control"
|
||||
{...register("description")}
|
||||
></textarea>
|
||||
{errors.description && (
|
||||
<div className="danger-text">{errors.description.message}</div>
|
||||
)}
|
||||
</div>
|
||||
{/* Description */}
|
||||
<div className="mb-4">
|
||||
<Label htmlFor="description" required>Description</Label>
|
||||
<textarea
|
||||
rows="2"
|
||||
className="form-control"
|
||||
{...register("description")}
|
||||
></textarea>
|
||||
{errors.description && (
|
||||
<div className="danger-text">{errors.description.message}</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Buttons */}
|
||||
<div className="d-flex justify-content-end gap-3 mt-4">
|
||||
<button
|
||||
type="reset"
|
||||
className="btn btn-label-secondary btn-sm"
|
||||
disabled={isPending}
|
||||
onClick={closeModal}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
className="btn btn-primary btn-sm"
|
||||
disabled={isPending}
|
||||
>
|
||||
{isPending ? "Please Wait..." : " Submit"}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</FormProvider>
|
||||
</div>
|
||||
{/* Buttons */}
|
||||
<div className="d-flex justify-content-end gap-3 mt-4">
|
||||
<button
|
||||
type="reset"
|
||||
className="btn btn-label-secondary btn-sm"
|
||||
disabled={isPending}
|
||||
onClick={closeModal}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
className="btn btn-primary btn-sm"
|
||||
disabled={isPending}
|
||||
>
|
||||
{isPending ? "Please Wait..." : " Submit"}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</FormProvider>
|
||||
</div>
|
||||
</AppFormProvider>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -517,39 +517,35 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
|
||||
</div>
|
||||
</div>
|
||||
<div className="row mb-3">
|
||||
<div className="col-sm-4">
|
||||
<Label className="form-text text-start" required>
|
||||
Official Designation
|
||||
</Label>
|
||||
<div className="input-group">
|
||||
<select
|
||||
className="form-select"
|
||||
{...register("jobRoleId")}
|
||||
id="jobRoleId"
|
||||
aria-label=""
|
||||
>
|
||||
<option disabled value="">
|
||||
Select Role
|
||||
</option>
|
||||
{[...job_role]
|
||||
.sort((a, b) => a?.name?.localeCompare(b.name))
|
||||
.map((item) => (
|
||||
<option value={item?.id} key={item.id}>
|
||||
{item?.name}{" "}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div className="col-sm-4 text-start">
|
||||
<AppFormController
|
||||
name="jobRoleId"
|
||||
control={control}
|
||||
render={({ field }) => (
|
||||
<SelectField
|
||||
label="Official Designation"
|
||||
required
|
||||
options={[...job_role].sort((a, b) =>
|
||||
a?.name?.localeCompare(b?.name)
|
||||
)}
|
||||
placeholder="Select Role"
|
||||
labelKeyKey="name"
|
||||
valueKeyKey="id"
|
||||
value={field.value}
|
||||
onChange={field.onChange}
|
||||
className="m-0"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
{errors.jobRoleId && (
|
||||
<div
|
||||
className="danger-text text-start"
|
||||
style={{ fontSize: "12px" }}
|
||||
>
|
||||
<div className="danger-text text-start" style={{ fontSize: "12px" }}>
|
||||
{errors.jobRoleId.message}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="col-sm-4">
|
||||
|
||||
<div className="col-sm-4 mt-n1">
|
||||
<Label className="form-text text-start" required>
|
||||
Emergency Contact Person
|
||||
</Label>
|
||||
@ -570,7 +566,7 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="col-sm-4">
|
||||
<div className="col-sm-4 mt-n1">
|
||||
<Label className="form-text text-start" required>
|
||||
Emergency Phone Number
|
||||
</Label>
|
||||
|
||||
@ -10,6 +10,8 @@ import { useForm, Controller } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { z } from "zod";
|
||||
import showToast from "../../services/toastService";
|
||||
import { AppFormController } from "../../hooks/appHooks/useAppForm";
|
||||
import SelectField from "../common/Forms/SelectField";
|
||||
|
||||
export const ProjectPermissionSchema = z.object({
|
||||
employeeId: z.string().min(1, "Employee is required"),
|
||||
@ -46,26 +48,26 @@ const ProjectPermission = () => {
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!selectedEmployee) return;
|
||||
if (!selectedEmployee) return;
|
||||
|
||||
const enabledPerms =
|
||||
const enabledPerms =
|
||||
selectedEmpPermissions?.permissions
|
||||
?.filter((perm) => perm.isEnabled)
|
||||
?.map((perm) => perm.id) || [];
|
||||
|
||||
setValue("selectedPermissions", enabledPerms, { shouldValidate: true });
|
||||
}, [selectedEmpPermissions, setValue, selectedEmployee]);
|
||||
|
||||
const selectedPermissions = watch("selectedPermissions") || [];
|
||||
|
||||
const existingEnabledIds =
|
||||
selectedEmpPermissions?.permissions
|
||||
?.filter((perm) => perm.isEnabled)
|
||||
?.map((perm) => perm.id) || [];
|
||||
?.filter((p) => p.isEnabled)
|
||||
?.map((p) => p.id) || [];
|
||||
|
||||
setValue("selectedPermissions", enabledPerms, { shouldValidate: true });
|
||||
}, [selectedEmpPermissions, setValue, selectedEmployee]);
|
||||
|
||||
const selectedPermissions = watch("selectedPermissions") || [];
|
||||
|
||||
const existingEnabledIds =
|
||||
selectedEmpPermissions?.permissions
|
||||
?.filter((p) => p.isEnabled)
|
||||
?.map((p) => p.id) || [];
|
||||
|
||||
const hasChanges =
|
||||
selectedPermissions.length !== existingEnabledIds.length ||
|
||||
selectedPermissions.some((id) => !existingEnabledIds.includes(id));
|
||||
const hasChanges =
|
||||
selectedPermissions.length !== existingEnabledIds.length ||
|
||||
selectedPermissions.some((id) => !existingEnabledIds.includes(id));
|
||||
|
||||
const { mutate: updatePermission, isPending } =
|
||||
useUpdateProjectLevelEmployeePermission();
|
||||
@ -115,35 +117,42 @@ const hasChanges =
|
||||
<form className="row" onSubmit={handleSubmit(onSubmit)}>
|
||||
<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="d-block">
|
||||
{/* <div className="d-block">
|
||||
<label className="form-label">Select Employee</label>
|
||||
</div>
|
||||
<div className="d-block">
|
||||
{" "}
|
||||
<select
|
||||
className="form-select form-select-sm"
|
||||
{...register("employeeId")}
|
||||
disabled={isPending}
|
||||
>
|
||||
{loading ? (
|
||||
<option value="">Loading...</option>
|
||||
) : (
|
||||
<>
|
||||
<option value="">-- Select Employee --</option>
|
||||
{[...employees]
|
||||
?.sort((a, b) =>
|
||||
`${a?.firstName} ${a?.firstName}`?.localeCompare(
|
||||
`${b?.firstName} ${b?.lastName}`
|
||||
</div> */}
|
||||
|
||||
<div className="d-block flex-grow-1">
|
||||
<AppFormController
|
||||
name="employeeId"
|
||||
control={control}
|
||||
render={({ field }) => (
|
||||
<SelectField
|
||||
label="Select Employee"
|
||||
options={
|
||||
employees
|
||||
?.sort((a, b) =>
|
||||
`${a?.firstName} ${a?.lastName}`.localeCompare(
|
||||
`${b?.firstName} ${b?.lastName}`
|
||||
)
|
||||
)
|
||||
)
|
||||
?.map((emp) => (
|
||||
<option key={emp.id} value={emp.id}>
|
||||
{emp.firstName} {emp.lastName}
|
||||
</option>
|
||||
))}
|
||||
</>
|
||||
?.map((emp) => ({
|
||||
id: emp.id,
|
||||
name: `${emp.firstName} ${emp.lastName}`,
|
||||
})) ?? []
|
||||
}
|
||||
placeholder="-- Select Employee --"
|
||||
required
|
||||
labelKeyKey="name"
|
||||
valueKeyKey="id"
|
||||
value={field.value}
|
||||
onChange={field.onChange}
|
||||
isLoading={loading}
|
||||
disabled={isPending}
|
||||
className="m-0"
|
||||
/>
|
||||
)}
|
||||
</select>
|
||||
/>
|
||||
|
||||
{errors.employeeId && (
|
||||
<div className="d-block text-danger small">
|
||||
{errors.employeeId.message}
|
||||
@ -152,6 +161,7 @@ const hasChanges =
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="mt-3 text-end">
|
||||
{hasChanges && (
|
||||
<button
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user