Compare commits
13 Commits
main
...
Kartik_Bug
Author | SHA1 | Date | |
---|---|---|---|
55ff4d5d29 | |||
97cb357a3c | |||
9592108472 | |||
3b032b7b07 | |||
b8891d403f | |||
01568db61c | |||
80a974e3be | |||
f3e05a11d6 | |||
222e6495a8 | |||
18a3b8a85b | |||
d75296ffe8 | |||
6649cab6a2 | |||
eab23389ed |
@ -280,3 +280,7 @@
|
||||
.w-8-xl{ width: 2rem; }
|
||||
.w-10-xl{ width: 2.5rem; }
|
||||
}
|
||||
|
||||
.cursor-not-allowed{
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ const Attendance = ({ getRole, handleModalData, searchTerm, projectId, organizat
|
||||
checked={ShowPending}
|
||||
onChange={(e) => setShowPending(e.target.checked)}
|
||||
/>
|
||||
<label className="form-check-label ms-0">Show Pending</label>
|
||||
<label className="form-check-label ms-0">Pending Attendance</label>
|
||||
</div>
|
||||
</div>
|
||||
{attLoading ? (
|
||||
|
@ -190,7 +190,7 @@ useEffect(() => {
|
||||
checked={showPending}
|
||||
onChange={(e) => setShowPending(e.target.checked)}
|
||||
/>
|
||||
<label className="form-check-label ms-0">Show Pending</label>
|
||||
<label className="form-check-label ms-0">Pending Attendance</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -23,7 +23,7 @@ const HorizontalBarChart = ({
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="w-full h-[380px] flex items-center justify-center bg-gray-100 rounded-xl">
|
||||
<span className="text-gray-500 text-sm">Loading chart...</span>
|
||||
<span className="text-gray-500">Loading chart...</span>
|
||||
{/* Replace this with a skeleton or spinner if you prefer */}
|
||||
</div>
|
||||
);
|
||||
|
@ -3,7 +3,8 @@ import HorizontalBarChart from "../Charts/HorizontalBarChart";
|
||||
import { useProjects } from "../../hooks/useProjects";
|
||||
|
||||
const ProjectCompletionChart = () => {
|
||||
const { projects, loading } = useProjects();
|
||||
const { data: projects = [], isLoading: loading, isError, error } = useProjects();
|
||||
|
||||
|
||||
// Bar chart logic
|
||||
const projectNames = projects?.map((p) => p.name) || [];
|
||||
@ -11,7 +12,7 @@ const ProjectCompletionChart = () => {
|
||||
projects?.map((p) => {
|
||||
const completed = p.completedWork || 0;
|
||||
const planned = p.plannedWork || 1;
|
||||
const percent = (completed / planned) * 100;
|
||||
const percent = planned ? (completed / planned) * 100 : 0;
|
||||
return Math.min(Math.round(percent), 100);
|
||||
}) || [];
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useState } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useDocumentFilterEntities } from "../../hooks/useDocument";
|
||||
import { FormProvider, useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
@ -9,9 +9,11 @@ import {
|
||||
import { DateRangePicker1 } from "../common/DateRangePicker";
|
||||
import SelectMultiple from "../common/SelectMultiple";
|
||||
import moment from "moment";
|
||||
import { useLocation } from "react-router-dom";
|
||||
|
||||
const DocumentFilterPanel = ({ entityTypeId, onApply }) => {
|
||||
const [resetKey, setResetKey] = useState(0);
|
||||
const location = useLocation();
|
||||
|
||||
const { data, isError, isLoading, error } =
|
||||
useDocumentFilterEntities(entityTypeId);
|
||||
@ -52,6 +54,13 @@ const DocumentFilterPanel = ({ entityTypeId, onApply }) => {
|
||||
closePanel();
|
||||
};
|
||||
|
||||
// Close popup when navigating to another component
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
closePanel();
|
||||
};
|
||||
}, []);
|
||||
|
||||
if (isLoading) return <div>Loading...</div>;
|
||||
if (isError)
|
||||
return <div>Error: {error?.message || "Something went wrong!"}</div>;
|
||||
@ -63,6 +72,8 @@ const DocumentFilterPanel = ({ entityTypeId, onApply }) => {
|
||||
documentTag = [],
|
||||
} = data?.data || {};
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<FormProvider {...methods}>
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
@ -73,18 +84,16 @@ const DocumentFilterPanel = ({ entityTypeId, onApply }) => {
|
||||
<div className="d-inline-flex border rounded-pill overflow-hidden shadow-none">
|
||||
<button
|
||||
type="button"
|
||||
className={`btn px-2 py-1 rounded-0 text-tiny ${
|
||||
isUploadedAt ? "active btn-secondary text-white" : ""
|
||||
}`}
|
||||
className={`btn px-2 py-1 rounded-0 text-tiny ${isUploadedAt ? "active btn-secondary text-white" : ""
|
||||
}`}
|
||||
onClick={() => setValue("isUploadedAt", true)}
|
||||
>
|
||||
Uploaded On
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={`btn px-2 py-1 rounded-0 text-tiny ${
|
||||
!isUploadedAt ? "active btn-secondary text-white" : ""
|
||||
}`}
|
||||
className={`btn px-2 py-1 rounded-0 text-tiny ${!isUploadedAt ? "active btn-secondary text-white" : ""
|
||||
}`}
|
||||
onClick={() => setValue("isUploadedAt", false)}
|
||||
>
|
||||
Updated On
|
||||
|
@ -144,12 +144,12 @@ const Documents = ({ Document_Entity, Entity }) => {
|
||||
<span className="switch-off"></span>
|
||||
</span>
|
||||
<span className="switch-label">
|
||||
{isActive ? "Active" : "In-Active"}
|
||||
{isActive ? "Active Document" : "In-Active Document"}
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="col-6 col-md-6 col-lg-8 text-end">
|
||||
<div className="col-12 col-md-6 col-lg-8 text-end">
|
||||
{(isSelf || canUploadDocument) && (
|
||||
<button
|
||||
className="btn btn-sm btn-primary me-3"
|
||||
|
@ -51,7 +51,6 @@ const EmpAttendance = () => {
|
||||
new Date(b?.checkInTime).getTime() - new Date(a?.checkInTime).getTime()
|
||||
);
|
||||
|
||||
console.log(sorted);
|
||||
|
||||
const { currentPage, totalPages, currentItems, paginate } = usePagination(
|
||||
sorted,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useEffect } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { FormProvider, useForm } from "react-hook-form";
|
||||
import {
|
||||
useCreateOrganization,
|
||||
@ -14,6 +14,7 @@ import Label from "../common/Label";
|
||||
import { useGlobalServices } from "../../hooks/masterHook/useMaster";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import SelectMultiple from "../common/SelectMultiple";
|
||||
import { LogoUpload } from "../Tenant/LogoUpload";
|
||||
|
||||
const ManagOrg = () => {
|
||||
const { data: service, isLoading } = useGlobalServices();
|
||||
@ -31,10 +32,14 @@ const ManagOrg = () => {
|
||||
defaultValues: defaultOrganizationValues,
|
||||
});
|
||||
|
||||
const [logoPreview, setLogoPreview] = useState(null);
|
||||
const [logoName, setLogoName] = useState("");
|
||||
|
||||
const {
|
||||
handleSubmit,
|
||||
register,
|
||||
reset,
|
||||
getValues,
|
||||
formState: { errors },
|
||||
} = method;
|
||||
|
||||
@ -62,6 +67,7 @@ const ManagOrg = () => {
|
||||
email: organization.email || "",
|
||||
serviceIds: organization.services?.map((s) => s.id) || [],
|
||||
address: organization.address || "",
|
||||
logoImage: organization.logoImage || "",
|
||||
});
|
||||
}
|
||||
}, [organization, reset, service?.data]);
|
||||
@ -93,6 +99,14 @@ const ManagOrg = () => {
|
||||
}
|
||||
onOpen({ startStep: 2 });
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const logoImage = getValues("logoImage");
|
||||
if (logoImage) {
|
||||
setLogoPreview(logoImage);
|
||||
setLogoName("Uploaded Logo");
|
||||
}
|
||||
}, [getValues]);
|
||||
return (
|
||||
<FormProvider {...method}>
|
||||
<form className="form" onSubmit={handleSubmit(onSubmit)}>
|
||||
@ -176,6 +190,17 @@ const ManagOrg = () => {
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="col-sm-12 text-start mt-2">
|
||||
<Label htmlFor="logoImage" required>Logo Image</Label>
|
||||
|
||||
<LogoUpload
|
||||
preview={logoPreview}
|
||||
setPreview={setLogoPreview}
|
||||
fileName={logoName}
|
||||
setFileName={setLogoName}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="d-flex justify-content-between gap-2 my-2">
|
||||
<button
|
||||
type="button"
|
||||
@ -199,8 +224,8 @@ const ManagOrg = () => {
|
||||
{isCreating || isUpdating
|
||||
? "Please Wait..."
|
||||
: orgData
|
||||
? "Update"
|
||||
: "Submit"}
|
||||
? "Update"
|
||||
: "Submit"}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -13,6 +13,7 @@ export const organizationSchema = z.object({
|
||||
.regex(phoneRegex, { message: "Invalid phone number" }),
|
||||
contactPerson: z.string().min(1, { message: "Person name required" }),
|
||||
address: z.string().min(1, { message: "Address is required!" }),
|
||||
logoImage: z.string().min(1, { message: "Logo is required!" }),
|
||||
email: z
|
||||
.string().trim()
|
||||
.min(1, { message: "Email is required" })
|
||||
@ -28,6 +29,7 @@ export const defaultOrganizationValues = {
|
||||
contactPerson: "",
|
||||
address: "",
|
||||
email: "",
|
||||
logoImage:"",
|
||||
serviceIds: [],
|
||||
};
|
||||
|
||||
@ -54,4 +56,4 @@ export const spridSchema = z.object({
|
||||
spridSearchText: z
|
||||
.string()
|
||||
.regex(/^\d{4}$/, { message: "SPRID must be exactly 4 digits" }),
|
||||
});
|
||||
});
|
@ -131,7 +131,7 @@ const OrganizationsList = ({searchText}) => {
|
||||
<div className="d-flex justify-content-center gap-2">
|
||||
<i className="bx bx-show text-primary cursor-pointer" onClick={()=>onOpen({startStep:5,orgData:org.id,flowType:"view"})}></i>
|
||||
<i className="bx bx-edit text-secondary cursor-pointer" onClick={()=>onOpen({startStep:4,orgData:org,flowType:"edit"})}></i>
|
||||
<i className="bx bx-trash text-danger cursor-pointer"></i>
|
||||
<i className="bx bx-trash text-danger cursor-not-allowed"></i>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -22,9 +22,8 @@ const VieworgDataanization = ({ orgId }) => {
|
||||
</div>
|
||||
<div className="text-end">
|
||||
<span
|
||||
className={`badge bg-label-${
|
||||
data?.isActive ? "primary" : "secondary"
|
||||
} `}
|
||||
className={`badge bg-label-${data?.isActive ? "primary" : "secondary"
|
||||
} `}
|
||||
>
|
||||
{data?.isActive ? "Active" : "In-Active"}{" "}
|
||||
</span>
|
||||
@ -105,9 +104,101 @@ const VieworgDataanization = ({ orgId }) => {
|
||||
<div className="text-muted text-start">{data?.address}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="d-flex text-secondary mb-2">
|
||||
{" "}
|
||||
<i className="bx bx-sm bx-briefcase me-1" /> Projects And Services
|
||||
<div className="col-12 mb-3">
|
||||
<div
|
||||
className="d-flex justify-content-between align-items-center text-secondary mb-2 cursor-pointer"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#collapse-projects-services"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<div>
|
||||
<i className="bx bx-sm bx-briefcase me-1" /> Projects
|
||||
</div>
|
||||
<i className="bx bx-chevron-down me-2"></i>
|
||||
</div>
|
||||
|
||||
{/* remove "show" from className */}
|
||||
<div id="collapse-projects-services" className="collapse">
|
||||
{data?.projects && data.projects.length > 0 ? (
|
||||
data.projects
|
||||
.reduce((acc, curr) => {
|
||||
const projectId = curr.project.id;
|
||||
if (!acc.find((p) => p.id === projectId)) {
|
||||
acc.push(curr.project);
|
||||
}
|
||||
return acc;
|
||||
}, [])
|
||||
.map((project) => (
|
||||
<div key={project.id} className="mb-2 rounded p-2">
|
||||
<div
|
||||
className="d-flex justify-content-between align-items-center cursor-pointer"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target={`#collapse-${project.id}`}
|
||||
aria-expanded="false"
|
||||
>
|
||||
<label className="form-label fw-semibold">
|
||||
<i className="bx bx-buildings me-2"></i>
|
||||
{project.name}
|
||||
</label>
|
||||
<i className="bx bx-chevron-down"></i>
|
||||
</div>
|
||||
|
||||
<div id={`collapse-${project.id}`} className="collapse mt-2 ps-5">
|
||||
{data.projects
|
||||
.filter((p) => p.project.id === project.id)
|
||||
.map((p) => (
|
||||
<div key={p.service.id} className="mb-1 text-muted">
|
||||
<i className="bx bx-wrench me-2"></i>
|
||||
{p.service.name}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className="text-muted fst-italic ps-2">No projects available</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Services Section */}
|
||||
<div className="col-12 mb-3">
|
||||
<div
|
||||
className="d-flex justify-content-between align-items-center text-secondary mb-2 cursor-pointer"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#collapse-services"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<div>
|
||||
<i className="bx bx-sm bx-cog me-1" /> Services
|
||||
</div>
|
||||
<i className="bx bx-chevron-down me-2"></i>
|
||||
</div>
|
||||
|
||||
{/* collapse is closed initially */}
|
||||
<div id="collapse-services" className="collapse">
|
||||
{data?.services && data.services.length > 0 ? (
|
||||
<div className="row">
|
||||
{data.services.map((service) => (
|
||||
<div key={service.id} className="col-md-12 mb-3">
|
||||
<div className="card h-100 shadow-sm border-0">
|
||||
<div className="card-body">
|
||||
<h6 className="fw-semibold mb-1">
|
||||
<i className="bx bx-wrench me-1"></i>
|
||||
{service.name}
|
||||
</h6>
|
||||
<p className="text-muted small mb-0">
|
||||
{service.description || "No description available."}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-muted fst-italic ps-2">No services available</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -201,7 +201,7 @@ const Teams = () => {
|
||||
className="form-check-label ms-2"
|
||||
htmlFor="activeEmployeeSwitch"
|
||||
>
|
||||
{activeEmployee ? "Active Employees" : "Include Inactive Employees"}
|
||||
{activeEmployee ? "Active Employees" : "In-active Employees"}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -45,7 +45,7 @@ export const LogoUpload = ({ preview, setPreview, fileName, setFileName }) => {
|
||||
return (
|
||||
<div className="col-sm-12 mb-3">
|
||||
<div
|
||||
className="border border-secondary border-dashed rounded p-2 text-center position-relative"
|
||||
className="border border-secondary text-black border-dashed rounded p-2 text-center position-relative"
|
||||
style={{ cursor: "pointer" }}
|
||||
onClick={() => document.getElementById("logoImageInput")?.click()}
|
||||
>
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import React from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import { FormProvider, useForm } from "react-hook-form";
|
||||
import {
|
||||
contactsFilter,
|
||||
@ -8,11 +8,14 @@ import {
|
||||
import { useContactFilter } from "../../hooks/useDirectory";
|
||||
import { ExpenseFilterSkeleton } from "../../components/Expenses/ExpenseSkeleton";
|
||||
import SelectMultiple from "../../components/common/SelectMultiple";
|
||||
import { useLocation } from "react-router-dom";
|
||||
|
||||
const ContactFilterPanel = ({ onApply, clearFilter }) => {
|
||||
const { data, isError, isLoading, error, isFetched, isFetching } =
|
||||
useContactFilter();
|
||||
|
||||
const location = useLocation();
|
||||
|
||||
const methods = useForm({
|
||||
resolver: zodResolver(contactsFilter),
|
||||
defaultValues: defaultContactFilter,
|
||||
@ -30,14 +33,24 @@ const ContactFilterPanel = ({ onApply, clearFilter }) => {
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
reset(defaultContactFilter);
|
||||
onApply(defaultContactFilter);
|
||||
reset(defaultContactFilter);
|
||||
onApply(defaultContactFilter);
|
||||
closePanel();
|
||||
};
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
closePanel();
|
||||
};
|
||||
}, []);
|
||||
|
||||
if (isLoading || isFetching) return <ExpenseFilterSkeleton />;
|
||||
if (isError && isFetched)
|
||||
return <div>Something went wrong Here- {error.message} </div>;
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<FormProvider {...methods}>
|
||||
<form onSubmit={handleSubmit(onSubmit)} className="p-2 text-start">
|
||||
|
@ -139,9 +139,8 @@ export default function DirectoryPage({ IsPage = true, projectId = null }) {
|
||||
<ul className="nav nav-tabs">
|
||||
<li className="nav-item cursor-pointer">
|
||||
<a
|
||||
className={`nav-link ${
|
||||
activeTab === "notes" ? "active" : ""
|
||||
} fs-6`}
|
||||
className={`nav-link ${activeTab === "notes" ? "active" : ""
|
||||
} fs-6`}
|
||||
onClick={(e) => handleTabClick("notes", e)}
|
||||
>
|
||||
<i className="bx bx-notepad bx-sm me-1_5"></i>
|
||||
@ -150,9 +149,8 @@ export default function DirectoryPage({ IsPage = true, projectId = null }) {
|
||||
</li>
|
||||
<li className="nav-item cursor-pointer">
|
||||
<a
|
||||
className={`nav-link ${
|
||||
activeTab === "contacts" ? "active" : ""
|
||||
} fs-6`}
|
||||
className={`nav-link ${activeTab === "contacts" ? "active" : ""
|
||||
} fs-6`}
|
||||
onClick={(e) => handleTabClick("contacts", e)}
|
||||
>
|
||||
<i className="bx bxs-contact bx-sm me-1_5"></i>
|
||||
@ -168,105 +166,84 @@ export default function DirectoryPage({ IsPage = true, projectId = null }) {
|
||||
{activeTab === "notes" && (
|
||||
<div className="col-8 col-md-3">
|
||||
<input
|
||||
type="search"
|
||||
className="form-control form-control-sm"
|
||||
placeholder="Search notes..."
|
||||
value={searchNote}
|
||||
onChange={(e) => setSearchNote(e.target.value)}
|
||||
/>
|
||||
type="search"
|
||||
className="form-control form-control-sm"
|
||||
placeholder="Search notes..."
|
||||
value={searchNote}
|
||||
onChange={(e) => setSearchNote(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{activeTab === "contacts" && (
|
||||
<div className="d-flex align-items-center gap-3">
|
||||
<div className="col-12 col-md-8 d-flex flex-row gap-2">
|
||||
<div className="col-7 col-md-4">
|
||||
<input
|
||||
type="search"
|
||||
className="form-control form-control-sm"
|
||||
placeholder="Search contacts..."
|
||||
value={searchContact}
|
||||
onChange={(e) => setsearchContact(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
className={`btn btn-sm p-1 ${
|
||||
!gridView ? "btn-primary" : "btn-outline-primary"
|
||||
}`}
|
||||
onClick={() => setGridView(false)}
|
||||
>
|
||||
<i className="bx bx-list-ul"></i>
|
||||
</button>
|
||||
|
||||
<button
|
||||
className={`btn btn-sm p-1 ${
|
||||
gridView ? " btn-primary" : " btn-outline-primary"
|
||||
}`}
|
||||
<div className="col-7 col-md-4">
|
||||
<input
|
||||
type="search"
|
||||
className="form-control form-control-sm"
|
||||
placeholder="Search contacts..."
|
||||
value={searchContact}
|
||||
onChange={(e) => setsearchContact(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
className={`btn btn-sm p-1 ${gridView ? " btn-primary" : " btn-outline-primary"
|
||||
}`}
|
||||
onClick={() => setGridView(true)}
|
||||
>
|
||||
<i className="bx bx-grid-alt"></i>
|
||||
</button>
|
||||
<div className="form-check form-switch d-flex align-items-center d-none d-md-flex">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="form-check-input"
|
||||
role="switch"
|
||||
id="inactiveEmployeesCheckbox"
|
||||
checked={showActive}
|
||||
onChange={(e) => setShowActive(e.target.checked)}
|
||||
/>
|
||||
<label
|
||||
className="form-check-label ms-2"
|
||||
htmlFor="inactiveEmployeesCheckbox"
|
||||
<button
|
||||
className={`btn btn-sm p-1 ${!gridView ? "btn-primary" : "btn-outline-primary"
|
||||
}`}
|
||||
onClick={() => setGridView(false)}
|
||||
>
|
||||
{showActive ? "Active" : "Inactive"} Contacts
|
||||
</label>
|
||||
<i className="bx bx-list-ul"></i>
|
||||
</button>
|
||||
|
||||
<div className="form-check form-switch d-flex align-items-end d-none d-md-flex">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="form-check-input"
|
||||
role="switch"
|
||||
id="inactiveEmployeesCheckbox"
|
||||
checked={showActive}
|
||||
onChange={(e) => setShowActive(e.target.checked)}
|
||||
/>
|
||||
<label
|
||||
className="form-check-label ms-2"
|
||||
htmlFor="inactiveEmployeesCheckbox"
|
||||
>
|
||||
{showActive ? "Active" : "In-active"} Contacts
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="col-12 col-md-2 d-flex justify-content-end align-items-center gap-2">
|
||||
<div className={`form-check form-switch d-flex align-items-center ${activeTab === "contacts" ? " d-flex d-md-none m-0":"d-none" }`}>
|
||||
<input
|
||||
type="checkbox"
|
||||
className="form-check-input"
|
||||
role="switch"
|
||||
id="inactiveEmployeesCheckbox"
|
||||
checked={showActive}
|
||||
onChange={(e) => setShowActive(e.target.checked)}
|
||||
/>
|
||||
<label
|
||||
className="form-check-label ms-2"
|
||||
htmlFor="inactiveEmployeesCheckbox"
|
||||
<div className="col-12 col-md-2 d-flex justify-content-end align-items-center gap-2">
|
||||
<div className=" btn-group">
|
||||
<button
|
||||
className="btn btn-sm btn-label-secondary dropdown-toggle"
|
||||
type="button"
|
||||
data-bs-toggle="dropdown"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<i className="bx bx-export me-2 bx-sm"></i>Export
|
||||
</button>
|
||||
<ul className="dropdown-menu">
|
||||
<li>
|
||||
<a
|
||||
className="dropdown-item cursor-pointer"
|
||||
onClick={() => handleExport("csv")}
|
||||
>
|
||||
{showActive ? "Active" : "Inactive"} Contacts
|
||||
</label>
|
||||
</div>
|
||||
<div className=" btn-group">
|
||||
<button
|
||||
className="btn btn-sm btn-label-secondary dropdown-toggle"
|
||||
type="button"
|
||||
data-bs-toggle="dropdown"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<i className="bx bx-export me-2 bx-sm"></i>Export
|
||||
</button>
|
||||
<ul className="dropdown-menu">
|
||||
<li>
|
||||
<a
|
||||
className="dropdown-item cursor-pointer"
|
||||
onClick={() => handleExport("csv")}
|
||||
>
|
||||
<i className="bx bx-file me-1"></i> CSV
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<i className="bx bx-file me-1"></i> CSV
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import React from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import { FormProvider, useForm } from "react-hook-form";
|
||||
import {
|
||||
defaultNotesFilter,
|
||||
@ -8,11 +8,18 @@ import {
|
||||
import { useContactFilter, useNoteFilter } from "../../hooks/useDirectory";
|
||||
import { ExpenseFilterSkeleton } from "../../components/Expenses/ExpenseSkeleton";
|
||||
import SelectMultiple from "../../components/common/SelectMultiple";
|
||||
import { useLocation } from "react-router-dom";
|
||||
|
||||
const NoteFilterPanel = ({ onApply, clearFilter }) => {
|
||||
const { data, isError, isLoading, error, isFetched, isFetching } =
|
||||
useNoteFilter();
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
closePanel();
|
||||
};
|
||||
}, []);
|
||||
|
||||
const methods = useForm({
|
||||
resolver: zodResolver(notesFilter),
|
||||
defaultValues: defaultNotesFilter,
|
||||
@ -31,7 +38,7 @@ const NoteFilterPanel = ({ onApply, clearFilter }) => {
|
||||
|
||||
const handleClose = () => {
|
||||
reset(defaultNotesFilter);
|
||||
onApply(defaultNotesFilter);
|
||||
onApply(defaultNotesFilter);
|
||||
closePanel();
|
||||
};
|
||||
|
||||
|
@ -176,12 +176,10 @@ const EmployeeList = () => {
|
||||
useEffect(() => {
|
||||
if (!loading && Array.isArray(employees)) {
|
||||
const sorted = [...employees].sort((a, b) => {
|
||||
const nameA = `${a.firstName || ""}${a.middleName || ""}${
|
||||
a.lastName || ""
|
||||
}`.toLowerCase();
|
||||
const nameB = `${b.firstName || ""}${b.middleName || ""}${
|
||||
b.lastName || ""
|
||||
}`.toLowerCase();
|
||||
const nameA = `${a.firstName || ""}${a.middleName || ""}${a.lastName || ""
|
||||
}`.toLowerCase();
|
||||
const nameB = `${b.firstName || ""}${b.middleName || ""}${b.lastName || ""
|
||||
}`.toLowerCase();
|
||||
return nameA?.localeCompare(nameB);
|
||||
});
|
||||
|
||||
@ -258,9 +256,8 @@ const EmployeeList = () => {
|
||||
? "Suspend Employee"
|
||||
: "Reactivate Employee"
|
||||
}
|
||||
message={`Are you sure you want to ${
|
||||
selectedEmpFordelete?.isActive ? "suspend" : "reactivate"
|
||||
} this employee?`}
|
||||
message={`Are you sure you want to ${selectedEmpFordelete?.isActive ? "suspend" : "reactivate"
|
||||
} this employee?`}
|
||||
onSubmit={(id) =>
|
||||
suspendEmployee({
|
||||
employeeId: id,
|
||||
@ -309,7 +306,7 @@ const EmployeeList = () => {
|
||||
className="form-check-label ms-0"
|
||||
htmlFor="inactiveEmployeesCheckbox"
|
||||
>
|
||||
Show Inactive Employees
|
||||
In-active Employees
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@ -471,9 +468,8 @@ const EmployeeList = () => {
|
||||
Status
|
||||
</th>
|
||||
<th
|
||||
className={`sorting_disabled ${
|
||||
!Manage_Employee && "d-none"
|
||||
}`}
|
||||
className={`sorting_disabled ${!Manage_Employee && "d-none"
|
||||
}`}
|
||||
rowSpan="1"
|
||||
colSpan="1"
|
||||
style={{ width: "50px" }}
|
||||
@ -493,20 +489,20 @@ const EmployeeList = () => {
|
||||
)}
|
||||
|
||||
{!loading &&
|
||||
displayData?.length === 0 &&
|
||||
(!searchText ) ? (
|
||||
displayData?.length === 0 &&
|
||||
(!searchText) ? (
|
||||
<tr>
|
||||
<td colSpan={8} className="border-0 py-3">
|
||||
<div className="py-4">
|
||||
<div className="py-4">
|
||||
No Data Found
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
) : null}
|
||||
|
||||
{!loading &&
|
||||
displayData?.length === 0 &&
|
||||
(searchText ) ? (
|
||||
{!loading &&
|
||||
displayData?.length === 0 &&
|
||||
(searchText) ? (
|
||||
<tr>
|
||||
<td colSpan={8} className="border-0 py-3">
|
||||
<div className="py-4">
|
||||
@ -542,18 +538,17 @@ const EmployeeList = () => {
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td className="text-start d-none d-sm-table-cell">
|
||||
<td className="text-start d-none d-sm-table-cell">
|
||||
{item.email ? (
|
||||
<span className="text-truncate">
|
||||
<i className="bx bxs-envelope text-primary me-2"></i>
|
||||
{item.email}
|
||||
</span>
|
||||
) : (
|
||||
<span className="text-truncate text-italic">
|
||||
-
|
||||
</span>
|
||||
<span className="d-block text-start text-muted fst-italic">NA</span>
|
||||
)}
|
||||
</td>
|
||||
|
||||
<td className="text-start d-none d-sm-table-cell">
|
||||
<span className="text-truncate">
|
||||
<i className="bx bxs-phone-call text-primary me-2"></i>
|
||||
@ -567,9 +562,14 @@ const EmployeeList = () => {
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<td className=" d-none d-md-table-cell">
|
||||
{moment(item.joiningDate)?.format("DD-MMM-YYYY")}
|
||||
<td className="d-none d-md-table-cell">
|
||||
{item.joiningDate ? (
|
||||
moment(item.joiningDate).format("DD-MMM-YYYY")
|
||||
) : (
|
||||
<span className="d-block text-center text-muted fst-italic">NA</span>
|
||||
)}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
{showInactive ? (
|
||||
<span
|
||||
|
@ -77,7 +77,7 @@ const ProjectDetails = () => {
|
||||
<AboutProject />
|
||||
<ProjectOverview project={projectId} />
|
||||
</div>
|
||||
<div className="col-lg-8 col-md-7 mt-5">
|
||||
<div className="col-lg-8 col-md-7 mt-2">
|
||||
<ProjectProgressChart ShowAllProject="false" DefaultRange="1M" />
|
||||
<div className="mt-5">
|
||||
<AttendanceOverview />
|
||||
|
Loading…
x
Reference in New Issue
Block a user