Merge branch 'Service_Project_Managment' of https://git.marcoaiot.com/admin/marco.pms.web into Service_Project_Managment
This commit is contained in:
commit
314dd67118
@ -22,7 +22,7 @@ const JobComments = ({ data }) => {
|
|||||||
formState: { errors },
|
formState: { errors },
|
||||||
} = useAppForm({
|
} = useAppForm({
|
||||||
resolver: zodResolver(JobCommentSchema),
|
resolver: zodResolver(JobCommentSchema),
|
||||||
default: { comment: "", attachments: [] },
|
defaultValues:{ comment: "", attachments: [] }
|
||||||
});
|
});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -94,6 +94,7 @@ const JobComments = ({ data }) => {
|
|||||||
const newFiles = files.filter((_, i) => i !== index);
|
const newFiles = files.filter((_, i) => i !== index);
|
||||||
setValue("attachments", newFiles, { shouldValidate: true });
|
setValue("attachments", newFiles, { shouldValidate: true });
|
||||||
};
|
};
|
||||||
|
console.log(watch("attachments"))
|
||||||
return (
|
return (
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="sticky-section bg-white p-3">
|
<div className="sticky-section bg-white p-3">
|
||||||
|
|||||||
@ -1,15 +1,20 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
import Avatar from "../common/Avatar";
|
||||||
|
|
||||||
const JobStatusLog = ({ data }) => {
|
const JobStatusLog = ({ data }) => {
|
||||||
|
console.log(data)
|
||||||
return (
|
return (
|
||||||
<div className="card shadow-none p-0">
|
<div className="card shadow-none p-0">
|
||||||
<div className="card-body p-0">
|
<div className="card-body p-0">
|
||||||
<div className="list-group">
|
<div className="list-group">
|
||||||
|
|
||||||
{data?.map((item) => (
|
{data?.map((item) => (
|
||||||
<div key={item.id} className="list-group-item border-0 border-bottom pb-3">
|
|
||||||
|
<div
|
||||||
<div className="d-flex justify-content-between">
|
key={item.id}
|
||||||
|
className="list-group-item border-0 border-bottom p-1"
|
||||||
|
>
|
||||||
|
<div className="d-flex justify-content-between">
|
||||||
<div>
|
<div>
|
||||||
<span className="fw-semibold">
|
<span className="fw-semibold">
|
||||||
{item.nextStatus?.displayName ?? item.status?.displayName ?? "Status"}
|
{item.nextStatus?.displayName ?? item.status?.displayName ?? "Status"}
|
||||||
@ -20,27 +25,30 @@ const JobStatusLog = ({ data }) => {
|
|||||||
Level {item.nextStatus?.level ?? item.status?.level}
|
Level {item.nextStatus?.level ?? item.status?.level}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="d-flex align-items-start mt-2 mx-0 px-0">
|
||||||
<p className="mb-1 mt-2 text-muted" style={{ fontSize: "0.9rem" }}>
|
<Avatar
|
||||||
{item.comment}
|
firstName={item.updatedBy?.firstName}
|
||||||
</p>
|
lastName={item.updatedBy?.lastName}
|
||||||
|
/>
|
||||||
<div className="d-flex align-items-center mt-2">
|
<div className="">
|
||||||
<div className="rounded-circle bg-light d-flex justify-content-center align-items-center"
|
<div className="d-flex flex-row gap-3">
|
||||||
style={{ width: 32, height: 32 }}>
|
<span className="fw-semibold">
|
||||||
<i className="bx bx-user"></i>
|
{item.updatedBy?.firstName} {item.updatedBy?.lastName}
|
||||||
</div>
|
</span>
|
||||||
<div className="ms-2">
|
<span className="text-secondary">
|
||||||
<div className="fw-semibold" style={{ fontSize: "0.85rem" }}>
|
{/* <em>{formatUTCToLocalTime(item?.createdAt, true)}</em> */}
|
||||||
{item.updatedBy?.firstName} {item.updatedBy?.lastName}
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-muted" style={{ fontSize: "0.75rem" }}>
|
<div className="text-muted text-secondary">
|
||||||
{item.updatedBy?.jobRoleName}
|
{item?.updatedBy?.jobRoleName}
|
||||||
|
</div>
|
||||||
|
<div className="text-wrap">
|
||||||
|
<p className="mb-1 mt-2 text-muted">{item.comment}</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
|
||||||
))}
|
))}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -75,9 +75,6 @@ const Jobs = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<GlobalModel>
|
|
||||||
<PreviewDocument />
|
|
||||||
</GlobalModel>
|
|
||||||
</JonContext.Provider>
|
</JonContext.Provider>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -17,12 +17,14 @@ const ManageJobTicket = ({ Job }) => {
|
|||||||
{
|
{
|
||||||
id: "comment",
|
id: "comment",
|
||||||
title: "Coments",
|
title: "Coments",
|
||||||
|
icon:"bx bx-comment me-2",
|
||||||
active: true,
|
active: true,
|
||||||
content: <JobComments data={data} />,
|
content: <JobComments data={data} />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "history",
|
id: "history",
|
||||||
title: "History",
|
title: "History",
|
||||||
|
icon:"bx bx-time me-2",
|
||||||
active: false,
|
active: false,
|
||||||
content: <JobStatusLog data={data?.updateLogs} />,
|
content: <JobStatusLog data={data?.updateLogs} />,
|
||||||
},
|
},
|
||||||
@ -50,17 +52,17 @@ const ManageJobTicket = ({ Job }) => {
|
|||||||
<div className="d-flex flex-wrap my-3">
|
<div className="d-flex flex-wrap my-3">
|
||||||
<p>{data?.description}</p>
|
<p>{data?.description}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="d-flex flex-row gap-3">
|
<div className="d-flex flex-row gap-5">
|
||||||
<span className="fw-medium">
|
<span className="fw-medium">
|
||||||
Start Date : {formatUTCToLocalTime(data?.startDate)}
|
<i className="bx bx-calendar"></i> Start Date : {formatUTCToLocalTime(data?.startDate)}
|
||||||
</span>{" "}
|
</span>{" "}
|
||||||
<i className="bx bx-right-arrow-alt"></i>{" "}
|
<i className="bx bx-right-arrow-alt"></i>{" "}
|
||||||
<span className="fw-medium">
|
<span className="fw-medium">
|
||||||
Due To : {formatUTCToLocalTime(data?.startDate)}
|
<i className="bx bx-calendar"></i> Due To : {formatUTCToLocalTime(data?.startDate)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="d-flex justify-content-between">
|
<div className="d-block mt-2">
|
||||||
<div className="d-flex align-items-center">
|
<div className="d-flex align-items-center mb-2">
|
||||||
<small className="fs-6 text-secondary fs-italic me-3 mt-2">
|
<small className="fs-6 text-secondary fs-italic me-3 mt-2">
|
||||||
<em>Created By</em>
|
<em>Created By</em>
|
||||||
</small>{" "}
|
</small>{" "}
|
||||||
@ -69,13 +71,26 @@ const ManageJobTicket = ({ Job }) => {
|
|||||||
firstName={data?.createdBy?.firstName}
|
firstName={data?.createdBy?.firstName}
|
||||||
lastName={data?.createdBy?.lastName}
|
lastName={data?.createdBy?.lastName}
|
||||||
/>{" "}
|
/>{" "}
|
||||||
<span className="fw-medium">{`${data?.createdBy?.firstName} ${data?.createdBy?.lastName}`}</span>
|
<div className="d-flex flex-column">
|
||||||
|
<p className="m-0">{`${data?.createdBy?.firstName} ${data?.createdBy?.lastName}`}</p>
|
||||||
|
<small className="text-secondary">{data?.createdBy?.jobRoleName}</small>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="d-flex align-items-center">
|
<div className="d-flex align-items-center">
|
||||||
<small className="fs-6 text-secondary fs-italic me-3 mt-2">
|
<small className="fs-6 text-secondary fs-italic me-3 mt-2">
|
||||||
<em>Assigned</em>
|
<em>Assigned</em>
|
||||||
</small>
|
</small>
|
||||||
<EmployeeAvatarGroup employees={data?.assignees} />
|
<div className="d-flex flex-row gap-3">
|
||||||
|
{data?.assignees?.map((emp)=>(
|
||||||
|
<div className="d-flex flex-row ">
|
||||||
|
<Avatar size="xs" firstName={emp.firstName} lastName={emp.lastName}/>
|
||||||
|
<div className="d-flex flex-column">
|
||||||
|
<p className="m-0">{`${emp.firstName} ${emp.lastName}`}</p>
|
||||||
|
<small className="text-secondary">{emp.jobRoleName}</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -91,7 +106,7 @@ const ManageJobTicket = ({ Job }) => {
|
|||||||
data-bs-target={`#tab-${tab.id}`}
|
data-bs-target={`#tab-${tab.id}`}
|
||||||
role="tab"
|
role="tab"
|
||||||
>
|
>
|
||||||
{tab.title}
|
<i className={tab.icon} /> {tab.title}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@ -59,21 +59,24 @@ const ALLOWED_TYPES = [
|
|||||||
];
|
];
|
||||||
export const JobCommentSchema = z.object({
|
export const JobCommentSchema = z.object({
|
||||||
comment: z.string().min(1, { message: "Please leave comment" }),
|
comment: z.string().min(1, { message: "Please leave comment" }),
|
||||||
attachments: z.array(
|
attachments: z
|
||||||
|
.array(
|
||||||
z.object({
|
z.object({
|
||||||
fileName: z.string().min(1, { message: "Filename is required" }),
|
fileName: z.string().min(1),
|
||||||
base64Data: z.string().nullable(),
|
base64Data: z.string().nullable(),
|
||||||
contentType: z.string().refine((val) => ALLOWED_TYPES.includes(val), {
|
contentType: z.string().refine((val) => ALLOWED_TYPES.includes(val), {
|
||||||
message: "Only PDF, PNG, JPG, or JPEG files are allowed",
|
message: "Only PDF, PNG, JPG, or JPEG files are allowed",
|
||||||
}),
|
}),
|
||||||
documentId: z.string().optional(),
|
documentId: z.string().optional(),
|
||||||
fileSize: z.number().max(MAX_FILE_SIZE, {
|
fileSize: z.number().max(MAX_FILE_SIZE),
|
||||||
message: "File size must be less than or equal to 5MB",
|
|
||||||
}),
|
|
||||||
description: z.string().optional(),
|
description: z.string().optional(),
|
||||||
isActive: z.boolean().default(true),
|
isActive: z.boolean().default(true),
|
||||||
})
|
})
|
||||||
),
|
)
|
||||||
|
.optional()
|
||||||
|
.default([]),
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
export const defaultJobValue = {
|
export const defaultJobValue = {
|
||||||
title: "",
|
title: "",
|
||||||
|
|||||||
@ -51,7 +51,7 @@ const DatePicker = ({
|
|||||||
<div className={`position-relative ${className} w-max `}>
|
<div className={`position-relative ${className} w-max `}>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
className="form-control form-control-sm"
|
className="form-control form-control"
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
value={displayValue}
|
value={displayValue}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
|||||||
@ -159,7 +159,7 @@ export const useAddCommentJob = (onSuccessCallback) => {
|
|||||||
queryKey: ["jobComments", variables?.jobTicketId],
|
queryKey: ["jobComments", variables?.jobTicketId],
|
||||||
});
|
});
|
||||||
if (onSuccessCallback) onSuccessCallback();
|
if (onSuccessCallback) onSuccessCallback();
|
||||||
showToast("Job Created successfully", "success");
|
showToast("Comment added successfully", "success");
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
showToast(
|
showToast(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user