added offcanavs for create and update
This commit is contained in:
parent
dab3c5fe52
commit
7190a3c190
@ -94,7 +94,6 @@ const JobComments = ({ data }) => {
|
||||
const newFiles = files.filter((_, i) => i !== index);
|
||||
setValue("attachments", newFiles, { shouldValidate: true });
|
||||
};
|
||||
console.log(watch("attachments"))
|
||||
return (
|
||||
<div className="row">
|
||||
<div className="sticky-section bg-white p-3">
|
||||
|
||||
@ -9,9 +9,8 @@ import { useParams } from "react-router-dom";
|
||||
import ProjectPage from "../../pages/project/ProjectPage";
|
||||
import { useServiceProjectJobContext } from "./Jobs";
|
||||
|
||||
|
||||
const JobList = ({ filterByProject }) => {
|
||||
const {setSelectedJob} = useServiceProjectJobContext()
|
||||
const { setSelectedJob, setManageJob } = useServiceProjectJobContext();
|
||||
const { id } = useParams();
|
||||
const { data, isLoading, isError, error } = useServiceProjectJobs(
|
||||
ITEMS_PER_PAGE,
|
||||
@ -112,12 +111,22 @@ const JobList = ({ filterByProject }) => {
|
||||
</button>
|
||||
<div className="dropdown-menu dropdown-menu-end">
|
||||
{/* View always visible */}
|
||||
<button className="dropdown-item py-1" onClick={()=>setSelectedJob({showCanvas:true,job:row?.id})}>
|
||||
<button
|
||||
className="dropdown-item py-1"
|
||||
onClick={() =>
|
||||
setSelectedJob({ showCanvas: true, job: row?.id })
|
||||
}
|
||||
>
|
||||
<i className="bx bx-detail bx-sm"></i> View
|
||||
</button>
|
||||
|
||||
<>
|
||||
<button className="dropdown-item py-1">
|
||||
<button
|
||||
className="dropdown-item py-1"
|
||||
onClick={() =>
|
||||
setManageJob({ isOpen: true, jobId: row?.id })
|
||||
}
|
||||
>
|
||||
<i className="bx bx-edit bx-sm"></i> Edit
|
||||
</button>
|
||||
</>
|
||||
|
||||
@ -20,15 +20,21 @@ export const useServiceProjectJobContext = () => {
|
||||
return context;
|
||||
};
|
||||
const Jobs = () => {
|
||||
const [manageJob, setManageJob] = useState({ isOpen: false, jobId: null });
|
||||
const [showCanvas, setShowCanvas] = useState(false);
|
||||
const [selectedProject, setSelectedProject] = useState(null);
|
||||
const [selectJob,setSelectedJob] = useState({showCanvas:false,job:null})
|
||||
const [selectJob, setSelectedJob] = useState({
|
||||
showCanvas: false,
|
||||
job: null,
|
||||
});
|
||||
const navigate = useNavigate();
|
||||
const { data } = useServiceProjects(ITEMS_PER_PAGE, 1);
|
||||
|
||||
const contextProvider = {
|
||||
setSelectedJob
|
||||
}
|
||||
setSelectedJob,
|
||||
setSelectedProject,
|
||||
setManageJob,
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<JonContext.Provider value={contextProvider}>
|
||||
@ -41,6 +47,15 @@ const Jobs = () => {
|
||||
>
|
||||
<ManageJobTicket Job={selectJob} />
|
||||
</OffcanvasComponent>
|
||||
<OffcanvasComponent
|
||||
id="customCanvas1"
|
||||
title={`${manageJob.jobId ? "Update a Job" : "Create a new Job"} `}
|
||||
placement="end"
|
||||
show={manageJob.isOpen}
|
||||
onClose={() => setManageJob({ isOpen: false, jobId: null })}
|
||||
>
|
||||
<ManageJob Job={manageJob.jobId} />
|
||||
</OffcanvasComponent>
|
||||
<div className="card page-min-h my-2 px-4">
|
||||
<div className="row">
|
||||
<div className="col-12 py-2 d-flex justify-content-between ">
|
||||
@ -64,7 +79,7 @@ const Jobs = () => {
|
||||
<div className="px-2">
|
||||
<button
|
||||
className="btn btn-sm btn-primary"
|
||||
onClick={() => navigate("/service/job")}
|
||||
onClick={() => setManageJob({ isOpen: true, jobId: null })}
|
||||
>
|
||||
<i className="bx bx-plus-circle bx-md me-2"></i>New Job
|
||||
</button>
|
||||
@ -74,7 +89,6 @@ const Jobs = () => {
|
||||
<JobList filterByProject={selectedProject} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</JonContext.Provider>
|
||||
</>
|
||||
);
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
import React from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import Breadcrumb from "../common/Breadcrumb";
|
||||
import Label from "../common/Label";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { defaultJobValue, jobSchema } from "./ServiceProjectSchema";
|
||||
import {
|
||||
useCreateServiceProjectJob,
|
||||
useJobTags,
|
||||
useServiceProjectJobDetails,
|
||||
useServiceProjects,
|
||||
} from "../../hooks/useServiceProject";
|
||||
import { ITEMS_PER_PAGE } from "../../utils/constants";
|
||||
@ -19,7 +21,7 @@ import {
|
||||
useAppForm,
|
||||
} from "../../hooks/appHooks/useAppForm";
|
||||
|
||||
const ManageJob = () => {
|
||||
const ManageJob = ({ Job }) => {
|
||||
const methods = useAppForm({
|
||||
resolver: zodResolver(jobSchema),
|
||||
defaultValues: defaultJobValue,
|
||||
@ -40,10 +42,23 @@ const ManageJob = () => {
|
||||
isError: isProjectError,
|
||||
error,
|
||||
} = useServiceProjects(ITEMS_PER_PAGE, 1);
|
||||
const {
|
||||
data: JobTags,
|
||||
isLoading: isTagLoading,
|
||||
isError: isTagError,
|
||||
error: tagError,
|
||||
} = useJobTags();
|
||||
const {
|
||||
data: JobData,
|
||||
isLoading: isJobLoading,
|
||||
isError: isJobError,
|
||||
error: jobError,
|
||||
} = useServiceProjectJobDetails(Job);
|
||||
|
||||
const { mutate: CreateJob, isPending } = useCreateServiceProjectJob(() => {
|
||||
reset();
|
||||
});
|
||||
|
||||
const onSubmit = (formData) => {
|
||||
formData.assignees = formData.assignees.map((emp) => ({
|
||||
employeeId: emp,
|
||||
@ -52,27 +67,27 @@ const ManageJob = () => {
|
||||
|
||||
formData.startDate = localToUtc(formData.startDate);
|
||||
formData.dueDate = localToUtc(formData.dueDate);
|
||||
// CreateJob(formData);
|
||||
console.log(formData);
|
||||
CreateJob(formData)
|
||||
};
|
||||
console.log(errors);
|
||||
|
||||
useEffect(() => {
|
||||
if (!JobData || !Job) return;
|
||||
const assignedEmployees = (JobData.assignees || []).map((e) => e.id);
|
||||
reset({
|
||||
title: JobData.title ?? "",
|
||||
description: JobData.description ?? "",
|
||||
projectId: JobData.project.id ?? "",
|
||||
assignees: assignedEmployees,
|
||||
startDate: JobData.startDate ?? null,
|
||||
dueDate: JobData.dueDate ?? null,
|
||||
tags: [],
|
||||
});
|
||||
}, [JobData]);
|
||||
|
||||
return (
|
||||
<div className="container-fluid">
|
||||
<Breadcrumb
|
||||
data={[
|
||||
{ label: "Home", link: "/dashboard" },
|
||||
{ label: "Sevice Projects", link: "/projects" },
|
||||
{ label: "" || "Jobs", link: null },
|
||||
]}
|
||||
/>
|
||||
<div className="card m-auto page-min-h">
|
||||
<div className="col-md-4 col-12 p-3"></div>
|
||||
<div className="col-md-8 p-3">
|
||||
<div className="container">
|
||||
<AppFormProvider {...methods}>
|
||||
<form className="row text-start" onSubmit={handleSubmit(onSubmit)}>
|
||||
<div>
|
||||
<p className="fs-5 fw-medium">Create Job</p>
|
||||
</div>
|
||||
<div className="col-12 col-md-6 mb-2 ">
|
||||
<Label required>Title</Label>
|
||||
<input
|
||||
@ -127,7 +142,12 @@ const ManageJob = () => {
|
||||
/>
|
||||
</div>
|
||||
<div className="col-12 col-md-6 mb-2 mb-md-4">
|
||||
<TagInput name="tags" label="Tag" required />
|
||||
<TagInput
|
||||
options={JobTags?.data}
|
||||
name="tags"
|
||||
label="Tag"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="col-12">
|
||||
<Label required>Description</Label>
|
||||
@ -137,7 +157,7 @@ const ManageJob = () => {
|
||||
rows={3}
|
||||
/>
|
||||
</div>
|
||||
<div className="d-flex flex-row-reverse my-2">
|
||||
<div className="d-flex flex-row-reverse my-4">
|
||||
<button
|
||||
type="submit"
|
||||
className="btn btn-sm btn-primary"
|
||||
@ -149,8 +169,6 @@ const ManageJob = () => {
|
||||
</form>
|
||||
</AppFormProvider>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
import React from "react";
|
||||
|
||||
const ServiceProjectNav = ({ onPillClick, activePill }) => {
|
||||
const ProjectTab = [
|
||||
@ -16,8 +16,6 @@ const ServiceProjectNav = ({ onPillClick, activePill }) => {
|
||||
icon: "bx bxs-contact",
|
||||
label: "Directory",
|
||||
},
|
||||
|
||||
|
||||
];
|
||||
return (
|
||||
<div className="table-responsive">
|
||||
@ -26,8 +24,8 @@ const ServiceProjectNav = ({ onPillClick, activePill }) => {
|
||||
{ProjectTab?.filter((tab) => !tab.hidden)?.map((tab) => (
|
||||
<li key={tab.key} className="nav-item cursor-pointer">
|
||||
<a
|
||||
|
||||
className={`nav-link ${activePill === tab.key ? "active cursor-pointer" : ""
|
||||
className={`nav-link ${
|
||||
activePill === tab.key ? "active cursor-pointer" : ""
|
||||
} fs-6`}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
@ -42,7 +40,7 @@ const ServiceProjectNav = ({ onPillClick, activePill }) => {
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default ServiceProjectNav
|
||||
export default ServiceProjectNav;
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { z } from "zod";
|
||||
|
||||
//#region Service Project
|
||||
export const projectSchema = z.object({
|
||||
name: z.string().min(1, "Name is required"),
|
||||
shortName: z.string().min(1, "Short name is required"),
|
||||
@ -31,12 +32,15 @@ export const defaultProjectValues = {
|
||||
contactEmail: "",
|
||||
};
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region JobSchema
|
||||
|
||||
export const TagSchema = z.object({
|
||||
name: z.string().min(1, "Tag name is required"),
|
||||
isActive: z.boolean().default(true),
|
||||
});
|
||||
|
||||
export const jobSchema = z.object({
|
||||
title: z.string().min(1, "Title is required"),
|
||||
description: z.string().min(1, "Description is required"),
|
||||
@ -57,6 +61,7 @@ const ALLOWED_TYPES = [
|
||||
"image/jpg",
|
||||
"image/jpeg",
|
||||
];
|
||||
|
||||
export const JobCommentSchema = z.object({
|
||||
comment: z.string().min(1, { message: "Please leave comment" }),
|
||||
attachments: z
|
||||
@ -75,9 +80,8 @@ export const JobCommentSchema = z.object({
|
||||
)
|
||||
.optional()
|
||||
.default([]),
|
||||
|
||||
|
||||
});
|
||||
|
||||
export const defaultJobValue = {
|
||||
title: "",
|
||||
description: "",
|
||||
|
||||
@ -1,4 +1,9 @@
|
||||
import { useInfiniteQuery, useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import {
|
||||
useInfiniteQuery,
|
||||
useMutation,
|
||||
useQuery,
|
||||
useQueryClient,
|
||||
} from "@tanstack/react-query";
|
||||
import { ServiceProjectRepository } from "../repositories/ServiceProjectRepository";
|
||||
import showToast from "../services/toastService";
|
||||
|
||||
@ -126,7 +131,11 @@ export const useJobComments = (jobId, pageSize, pageNumber ) => {
|
||||
queryKey: ["jobComments", jobId, pageSize],
|
||||
|
||||
queryFn: async ({ pageParam = pageNumber }) => {
|
||||
const resp = await ServiceProjectRepository.GetJobComment(jobId, pageSize, pageParam);
|
||||
const resp = await ServiceProjectRepository.GetJobComment(
|
||||
jobId,
|
||||
pageSize,
|
||||
pageParam
|
||||
);
|
||||
return resp.data;
|
||||
},
|
||||
|
||||
@ -139,6 +148,12 @@ export const useJobComments = (jobId, pageSize, pageNumber ) => {
|
||||
},
|
||||
});
|
||||
};
|
||||
export const useJobTags = () => {
|
||||
return useQuery({
|
||||
queryKey: ["Job_Tags"],
|
||||
queryFn: async () => await ServiceProjectRepository.GetJobTags(),
|
||||
});
|
||||
};
|
||||
|
||||
export const useServiceProjectJobDetails = (job) => {
|
||||
return useQuery({
|
||||
|
||||
@ -25,4 +25,5 @@ export const ServiceProjectRepository = {
|
||||
api.get(
|
||||
`/api/ServiceProject/job/comment/list?jobTicketId=${jobTicketId}&pageSize=${pageSize}&pageNumber=${pageNumber}`
|
||||
),
|
||||
GetJobTags: () => api.get(`/api/ServiceProject/job/tag/list`),
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user