Added columns in jobs list and implementing functionality for daysleft.

This commit is contained in:
Kartik Sharma 2025-11-15 15:06:44 +05:30 committed by pramod.mahajan
parent 852ebd7dd0
commit e47262123d
5 changed files with 70 additions and 47 deletions

View File

@ -1,5 +1,5 @@
import React, { useState } from "react";
import { getNextBadgeColor } from "../../utils/appUtils";
import { daysLeft, getNextBadgeColor } from "../../utils/appUtils";
import { useServiceProjectJobs } from "../../hooks/useServiceProject";
import { ITEMS_PER_PAGE } from "../../utils/constants";
import EmployeeAvatarGroup from "../common/EmployeeAvatarGroup";
@ -37,36 +37,51 @@ const JobList = ({ filterByProject }) => {
isAlwaysVisible: true,
className: "text-start",
},
{
key: "project",
label: "Project",
getValue: (e) => <div className="text-start ">{e?.project?.name}</div>,
isAlwaysVisible: true,
className: "text-start d-none d-sm-table-cell",
},
{
key: "employee",
label: "Team",
getValue: (e) => <EmployeeAvatarGroup employees={e.assignees} />,
isAlwaysVisible: true,
className: "text-start d-none d-sm-table-cell",
},
{
key: "startDate",
label: "Start Date",
getValue: (e) => formatUTCToLocalTime(e.startDate),
isAlwaysVisible: true,
className: "text-center d-none d-sm-table-cell ",
},
{
key: "dueDate",
label: "Due To",
label: "Due On",
getValue: (e) => formatUTCToLocalTime(e.startDate),
isAlwaysVisible: true,
className: "text-center d-none d-sm-table-cell",
className: "text-start d-none d-sm-table-cell",
},
{
key: "status",
label: "Status",
getValue: (e) => {
const statusName = e?.status?.displayName || "N/A";
const statusColorMap = {
Assigned: "label-primary",
Pending: "label-warning",
Completed: "label-success",
Cancelled: "label-danger",
};
const badgeColor = statusColorMap[statusName] || "label-secondary";
return (
<span className={`badge bg-${badgeColor}`} style={{ fontSize: "12px" }}>
{statusName}
</span>
);
},
isAlwaysVisible: true,
className: "text-start d-none d-sm-table-cell",
},
{
key: "daysLeft",
label: "Days Left",
getValue: (e) => {
const { days, color } = daysLeft(e.startDate, e.dueDate);
return (
<span className={`badge bg-${color}`} style={{ fontSize: "12px" }}>
{days !== null ? `${days} days` : "N/A"}
</span>
);
},
isAlwaysVisible: true,
className: "text-start d-none d-sm-table-cell"
}
];
return (

View File

@ -58,24 +58,7 @@ const Jobs = () => {
</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 ">
<div>
{" "}
<select
className="form-select form-select-sm"
value={selectedProject}
onChange={(e) => setSelectedProject(e.target.value)}
>
<option disabled selected>
Select Poject
</option>
{data?.data?.map((project) => (
<option key={project.id} value={project.id}>
{project.name}
</option>
))}
</select>
</div>
<div className="col-12 py-2 d-flex justify-content-end ">
<div className="px-2">
<button
className="btn btn-sm btn-primary"

View File

@ -134,7 +134,7 @@ const ManageJob = ({ Job }) => {
/>
</div>
<div className="col-12 col-md-6 mb-2 mb-md-4">
<Label required>End Date</Label>
<Label required>Select Employee</Label>
<PmsEmployeeInputTag
control={control}
name="assignees"

View File

@ -190,7 +190,7 @@ export const useJobComments = (jobId, pageSize, pageNumber) => {
return allPages.length + pageNumber;
},
});
};
};
export const useJobTags = () => {
return useQuery({
queryKey: ["Job_Tags"],
@ -238,7 +238,7 @@ export const useCreateServiceProjectJob = (onSuccessCallback) => {
return await ServiceProjectRepository.CreateJob(payload);
},
onSuccess: (data, variables) => {
queryClient.invalidateQueries({ queryKey: [""] });
queryClient.invalidateQueries({ queryKey: ["serviceProjectJobs"] });
if (onSuccessCallback) onSuccessCallback();
showToast("Job Created successfully", "success");

View File

@ -203,3 +203,28 @@ export function getNextBadgeColor(type = "label") {
colorIndex = (colorIndex + 1) % badgeColors.length;
return `rounded-pill text-bg-${color}`;
}
export function daysLeft(startDate, dueDate) {
if (!startDate || !dueDate) {
return { days: null, color: "label-secondary" };
}
const start = new Date(startDate);
const due = new Date(dueDate);
const today = new Date();
const diffTime = due.getTime() - today.getTime();
const days = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
let color = "label-primary"; // default
if (days < 0) {
color = "label-danger"; // overdue → red
} else if (days <= 15) {
color = "label-warning"; // near due → yellow
} else {
color = "label-primary"; // safe range
}
return { days, color };
}