Merge pull request 'HotChanges_06-10-25 : Image Gallery and Attendanc CheckIn check-Out' (#459) from HotChanges_06-10-25 into main
Reviewed-on: #459 Merged
This commit is contained in:
commit
5e27ed36fa
@ -12,7 +12,7 @@ import { useQueryClient } from "@tanstack/react-query";
|
|||||||
import eventBus from "../../services/eventBus";
|
import eventBus from "../../services/eventBus";
|
||||||
import { useSelectedProject } from "../../slices/apiDataManager";
|
import { useSelectedProject } from "../../slices/apiDataManager";
|
||||||
|
|
||||||
const Attendance = ({ getRole, handleModalData, searchTerm, projectId, organizationId, includeInactive, date }) => {
|
const Attendance = ({ getRole, handleModalData, searchTerm, projectId, organizationId, }) => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@ -24,7 +24,7 @@ const Attendance = ({ getRole, handleModalData, searchTerm, projectId, organizat
|
|||||||
loading: attLoading,
|
loading: attLoading,
|
||||||
recall: attrecall,
|
recall: attrecall,
|
||||||
isFetching
|
isFetching
|
||||||
} = useAttendance(selectedProject, organizationId, includeInactive, date);
|
} = useAttendance(selectedProject, organizationId);
|
||||||
const filteredAttendance = ShowPending
|
const filteredAttendance = ShowPending
|
||||||
? attendance?.filter(
|
? attendance?.filter(
|
||||||
(att) => att?.checkInTime !== null && att?.checkOutTime === null
|
(att) => att?.checkInTime !== null && att?.checkOutTime === null
|
||||||
|
@ -5,7 +5,11 @@ import { convertShortTime } from "../../utils/dateUtils";
|
|||||||
import RenderAttendanceStatus from "./RenderAttendanceStatus";
|
import RenderAttendanceStatus from "./RenderAttendanceStatus";
|
||||||
import { useSelector, useDispatch } from "react-redux";
|
import { useSelector, useDispatch } from "react-redux";
|
||||||
import DateRangePicker from "../common/DateRangePicker";
|
import DateRangePicker from "../common/DateRangePicker";
|
||||||
import { clearCacheKey, getCachedData, useSelectedProject } from "../../slices/apiDataManager";
|
import {
|
||||||
|
clearCacheKey,
|
||||||
|
getCachedData,
|
||||||
|
useSelectedProject,
|
||||||
|
} from "../../slices/apiDataManager";
|
||||||
import eventBus from "../../services/eventBus";
|
import eventBus from "../../services/eventBus";
|
||||||
import AttendanceRepository from "../../repositories/AttendanceRepository";
|
import AttendanceRepository from "../../repositories/AttendanceRepository";
|
||||||
import { useAttendancesLogs } from "../../hooks/useAttendance";
|
import { useAttendancesLogs } from "../../hooks/useAttendance";
|
||||||
@ -33,7 +37,7 @@ const usePagination = (data, itemsPerPage) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const AttendanceLog = ({ handleModalData, searchTerm ,organizationId}) => {
|
const AttendanceLog = ({ handleModalData, searchTerm, organizationId }) => {
|
||||||
// const selectedProject = useSelector(
|
// const selectedProject = useSelector(
|
||||||
// (store) => store.localVariables.projectId
|
// (store) => store.localVariables.projectId
|
||||||
// );
|
// );
|
||||||
@ -41,7 +45,7 @@ const AttendanceLog = ({ handleModalData, searchTerm ,organizationId}) => {
|
|||||||
const [dateRange, setDateRange] = useState({ startDate: "", endDate: "" });
|
const [dateRange, setDateRange] = useState({ startDate: "", endDate: "" });
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [showPending, setShowPending] = useState(false)
|
const [showPending, setShowPending] = useState(false);
|
||||||
|
|
||||||
const [isRefreshing, setIsRefreshing] = useState(false);
|
const [isRefreshing, setIsRefreshing] = useState(false);
|
||||||
const [processedData, setProcessedData] = useState([]);
|
const [processedData, setProcessedData] = useState([]);
|
||||||
@ -151,33 +155,6 @@ const AttendanceLog = ({ handleModalData, searchTerm ,organizationId}) => {
|
|||||||
});
|
});
|
||||||
}, [processedData, searchTerm]);
|
}, [processedData, searchTerm]);
|
||||||
|
|
||||||
// const filteredSearchData = useMemo(() => {
|
|
||||||
// let tempData = processedData;
|
|
||||||
|
|
||||||
// if (searchTerm) {
|
|
||||||
// const lowercasedSearchTerm = searchTerm.toLowerCase();
|
|
||||||
// tempData = tempData.filter((item) => {
|
|
||||||
// const fullName = `${item.firstName} ${item.lastName}`.toLowerCase();
|
|
||||||
// return fullName.includes(lowercasedSearchTerm);
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (filters?.selectedOrganization) {
|
|
||||||
// tempData = tempData.filter(
|
|
||||||
// (item) => item.organization?.name === filters.selectedOrganization
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (filters?.selectedServices?.length > 0) {
|
|
||||||
// tempData = tempData.filter((item) =>
|
|
||||||
// filters.selectedServices.includes(item.service?.name)
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return tempData;
|
|
||||||
// }, [processedData, searchTerm, filters]);
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
currentPage,
|
currentPage,
|
||||||
totalPages,
|
totalPages,
|
||||||
@ -235,7 +212,7 @@ const AttendanceLog = ({ handleModalData, searchTerm ,organizationId}) => {
|
|||||||
// })
|
// })
|
||||||
// );
|
// );
|
||||||
|
|
||||||
refetch()
|
refetch();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[selectedProject, dateRange, data, refetch]
|
[selectedProject, dateRange, data, refetch]
|
||||||
@ -270,11 +247,16 @@ const AttendanceLog = ({ handleModalData, searchTerm ,organizationId}) => {
|
|||||||
<label className="form-check-label ms-0">Show Pending</label>
|
<label className="form-check-label ms-0">Show Pending</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div className="table-responsive text-nowrap" style={{ minHeight: "200px" }}>
|
<div
|
||||||
|
className="table-responsive text-nowrap"
|
||||||
|
style={{ minHeight: "200px" }}
|
||||||
|
>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<div className="d-flex justify-content-center align-items-center" style={{ height: "200px" }}>
|
<div
|
||||||
|
className="d-flex justify-content-center align-items-center"
|
||||||
|
style={{ height: "200px" }}
|
||||||
|
>
|
||||||
<p className="text-secondary">Loading...</p>
|
<p className="text-secondary">Loading...</p>
|
||||||
</div>
|
</div>
|
||||||
) : filteredSearchData?.length > 0 ? (
|
) : filteredSearchData?.length > 0 ? (
|
||||||
@ -287,7 +269,8 @@ const AttendanceLog = ({ handleModalData, searchTerm ,organizationId}) => {
|
|||||||
<th className="border-top-1">Date</th>
|
<th className="border-top-1">Date</th>
|
||||||
<th>Organization</th>
|
<th>Organization</th>
|
||||||
<th>
|
<th>
|
||||||
<i className="bx bxs-down-arrow-alt text-success"></i> Check-In
|
<i className="bx bxs-down-arrow-alt text-success"></i>{" "}
|
||||||
|
Check-In
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<i className="bx bxs-up-arrow-alt text-danger"></i> Check-Out
|
<i className="bx bxs-up-arrow-alt text-danger"></i> Check-Out
|
||||||
@ -303,9 +286,9 @@ const AttendanceLog = ({ handleModalData, searchTerm ,organizationId}) => {
|
|||||||
const previousAttendance = arr[index - 1];
|
const previousAttendance = arr[index - 1];
|
||||||
const previousDate = previousAttendance
|
const previousDate = previousAttendance
|
||||||
? moment(
|
? moment(
|
||||||
previousAttendance.checkInTime ||
|
previousAttendance.checkInTime ||
|
||||||
previousAttendance.checkOutTime
|
previousAttendance.checkOutTime
|
||||||
).format("YYYY-MM-DD")
|
).format("YYYY-MM-DD")
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
if (!previousDate || currentDate !== previousDate) {
|
if (!previousDate || currentDate !== previousDate) {
|
||||||
@ -344,7 +327,7 @@ const AttendanceLog = ({ handleModalData, searchTerm ,organizationId}) => {
|
|||||||
attendance.checkInTime || attendance.checkOutTime
|
attendance.checkInTime || attendance.checkOutTime
|
||||||
).format("DD-MMM-YYYY")}
|
).format("DD-MMM-YYYY")}
|
||||||
</td>
|
</td>
|
||||||
<td>{attendance.organizationName || "--"}</td>
|
<td>{attendance.organizationName || "--"}</td>
|
||||||
<td>{convertShortTime(attendance.checkInTime)}</td>
|
<td>{convertShortTime(attendance.checkInTime)}</td>
|
||||||
<td>
|
<td>
|
||||||
{attendance.checkOutTime
|
{attendance.checkOutTime
|
||||||
@ -366,7 +349,12 @@ const AttendanceLog = ({ handleModalData, searchTerm ,organizationId}) => {
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
) : (
|
) : (
|
||||||
<div className="my-12"><span className="text-secondary">No data available for the selected date range. Please Select another date.</span></div>
|
<div className="my-12">
|
||||||
|
<span className="text-secondary">
|
||||||
|
No data available for the selected date range. Please Select
|
||||||
|
another date.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{paginatedAttendances?.length == 0 && filteredSearchData?.length > 0 && (
|
{paginatedAttendances?.length == 0 && filteredSearchData?.length > 0 && (
|
||||||
@ -392,8 +380,9 @@ const AttendanceLog = ({ handleModalData, searchTerm ,organizationId}) => {
|
|||||||
(pageNumber) => (
|
(pageNumber) => (
|
||||||
<li
|
<li
|
||||||
key={pageNumber}
|
key={pageNumber}
|
||||||
className={`page-item ${currentPage === pageNumber ? "active" : ""
|
className={`page-item ${
|
||||||
}`}
|
currentPage === pageNumber ? "active" : ""
|
||||||
|
}`}
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
className="page-link"
|
className="page-link"
|
||||||
@ -405,8 +394,9 @@ const AttendanceLog = ({ handleModalData, searchTerm ,organizationId}) => {
|
|||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
<li
|
<li
|
||||||
className={`page-item ${currentPage === totalPages ? "disabled" : ""
|
className={`page-item ${
|
||||||
}`}
|
currentPage === totalPages ? "disabled" : ""
|
||||||
|
}`}
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
className="page-link"
|
className="page-link"
|
||||||
|
@ -96,12 +96,12 @@ const CheckInCheckOut = ({ modeldata, closeModal, handleSubmitForm }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form className="row g-2" onSubmit={handleSubmit(onSubmit)}>
|
<form className="row p-2" onSubmit={handleSubmit(onSubmit)}>
|
||||||
<div className="col-12 d-flex justify-content-center">
|
<div className="col-12 d-flex justify-content-center mb-4">
|
||||||
<label className="fs-5 text-dark text-center">
|
<label className="fs-5 tex-semibold text-center">
|
||||||
{modeldata?.checkInTime && !modeldata?.checkOutTime
|
{modeldata?.checkInTime && !modeldata?.checkOutTime
|
||||||
? "Check-out :"
|
? "Check-Out "
|
||||||
: "Check-in :"}
|
: "Check-In "}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -120,7 +120,7 @@ const CheckInCheckOut = ({ modeldata, closeModal, handleSubmitForm }) => {
|
|||||||
modeldata?.checkInTime && !modeldata?.checkOutTime
|
modeldata?.checkInTime && !modeldata?.checkOutTime
|
||||||
? formatDate(modeldata?.checkInTime?.split("T")[0]) || ""
|
? formatDate(modeldata?.checkInTime?.split("T")[0]) || ""
|
||||||
: formatDate(today)
|
: formatDate(today)
|
||||||
}
|
}
|
||||||
disabled
|
disabled
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import React, { useEffect, useRef } from "react";
|
import React, { useEffect, useRef } from "react";
|
||||||
import { useController, useFormContext, useWatch } from "react-hook-form";
|
import { useController, useFormContext, useWatch } from "react-hook-form";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
|
|
||||||
const DateRangePicker = ({
|
const DateRangePicker = ({
|
||||||
md,
|
md,
|
||||||
sm,
|
sm,
|
||||||
@ -9,19 +11,29 @@ const DateRangePicker = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const inputRef = useRef(null);
|
const inputRef = useRef(null);
|
||||||
|
|
||||||
|
const persistedRange = useSelector(
|
||||||
|
(store) => store.localVariables.attendance.defaultDateRange
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const endDate = new Date();
|
let startDate, endDate;
|
||||||
if (endDateMode === "yesterday") {
|
|
||||||
endDate.setDate(endDate.getDate() - 1);
|
if (persistedRange?.startDate && persistedRange?.endDate) {
|
||||||
|
startDate = new Date(persistedRange.startDate);
|
||||||
|
endDate = new Date(persistedRange.endDate);
|
||||||
|
} else {
|
||||||
|
endDate = new Date();
|
||||||
|
if (endDateMode === "yesterday") {
|
||||||
|
endDate.setDate(endDate.getDate() - 1);
|
||||||
|
}
|
||||||
|
endDate.setHours(0, 0, 0, 0);
|
||||||
|
|
||||||
|
startDate = new Date(endDate);
|
||||||
|
startDate.setDate(endDate.getDate() - (DateDifference - 1));
|
||||||
|
startDate.setHours(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
endDate.setHours(0, 0, 0, 0);
|
const fp = flatpickr(inputRef.current, {
|
||||||
|
|
||||||
const startDate = new Date(endDate);
|
|
||||||
startDate.setDate(endDate.getDate() - (DateDifference - 1));
|
|
||||||
startDate.setHours(0, 0, 0, 0);
|
|
||||||
|
|
||||||
const fp = flatpickr(inputRef.current, {
|
|
||||||
mode: "range",
|
mode: "range",
|
||||||
dateFormat: "Y-m-d",
|
dateFormat: "Y-m-d",
|
||||||
altInput: true,
|
altInput: true,
|
||||||
@ -41,14 +53,12 @@ const DateRangePicker = ({
|
|||||||
endDate: endDate.toLocaleDateString("en-CA"),
|
endDate: endDate.toLocaleDateString("en-CA"),
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => {
|
return () => fp.destroy();
|
||||||
fp.destroy();
|
}, [onRangeChange, DateDifference, endDateMode, persistedRange]);
|
||||||
};
|
|
||||||
}, [onRangeChange, DateDifference, endDateMode]);
|
|
||||||
|
|
||||||
const handleIconClick = () => {
|
const handleIconClick = () => {
|
||||||
if (inputRef.current) {
|
if (inputRef.current?._flatpickr) {
|
||||||
inputRef.current._flatpickr.open(); // directly opens flatpickr
|
inputRef.current._flatpickr.open();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -63,9 +73,10 @@ const DateRangePicker = ({
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<i
|
<i
|
||||||
className="bx bx-calendar calendar-icon cursor-pointer position-relative top-50 translate-middle-y " onClick={handleIconClick}
|
className="bx bx-calendar calendar-icon cursor-pointer position-relative top-50 translate-middle-y"
|
||||||
|
onClick={handleIconClick}
|
||||||
style={{ right: "22px", bottom: "-8px" }}
|
style={{ right: "22px", bottom: "-8px" }}
|
||||||
></i>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -76,6 +87,7 @@ export default DateRangePicker;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const DateRangePicker1 = ({
|
export const DateRangePicker1 = ({
|
||||||
startField = "startDate",
|
startField = "startDate",
|
||||||
endField = "endDate",
|
endField = "endDate",
|
||||||
|
128
src/components/gallary/GalleryFilterPanel.jsx
Normal file
128
src/components/gallary/GalleryFilterPanel.jsx
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import { useImageGalleryFilter } from "../../hooks/useImageGallery";
|
||||||
|
import { useSelectedProject } from "../../slices/apiDataManager";
|
||||||
|
import { FormProvider, useForm } from "react-hook-form";
|
||||||
|
import Label from "../common/Label";
|
||||||
|
import { DateRangePicker1 } from "../common/DateRangePicker";
|
||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import { defaultGalleryFilterValue, gallerySchema } from "./GallerySchema";
|
||||||
|
import SelectMultiple from "../common/SelectMultiple";
|
||||||
|
|
||||||
|
const GalleryFilterPanel = () => {
|
||||||
|
const selectedProject = useSelectedProject();
|
||||||
|
const [resetKey, setResetKey] = useState(0);
|
||||||
|
const { data, isLoading, isError, error } =
|
||||||
|
useImageGalleryFilter(selectedProject);
|
||||||
|
|
||||||
|
const methods = useForm({
|
||||||
|
resolver: zodResolver(gallerySchema),
|
||||||
|
defaultValues: defaultGalleryFilterValue,
|
||||||
|
});
|
||||||
|
|
||||||
|
const {
|
||||||
|
handleSubmit,
|
||||||
|
register,
|
||||||
|
setValue,
|
||||||
|
formState: { errors },
|
||||||
|
} = methods;
|
||||||
|
|
||||||
|
const onSubmit = (formData) => {
|
||||||
|
console.log(formData);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isLoading) return <div>Loading....</div>;
|
||||||
|
if (isError) return <div>{error.message}</div>;
|
||||||
|
return (
|
||||||
|
<div className="d-block text-start">
|
||||||
|
<FormProvider {...methods}>
|
||||||
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
|
<div className="mb-2">
|
||||||
|
<Label>Select Date:</Label>
|
||||||
|
<DateRangePicker1
|
||||||
|
placeholder="DD-MM-YYYY To DD-MM-YYYY"
|
||||||
|
startField="startDate"
|
||||||
|
endField="endDate"
|
||||||
|
resetSignal={resetKey}
|
||||||
|
defaultRange={false}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mb-2">
|
||||||
|
<SelectMultiple
|
||||||
|
name="buildingIds"
|
||||||
|
label="Select building:"
|
||||||
|
options={data?.buildings}
|
||||||
|
labelKey="name"
|
||||||
|
valueKey="id"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mb-2">
|
||||||
|
<SelectMultiple
|
||||||
|
name="floorIds"
|
||||||
|
label="Select Floor:"
|
||||||
|
options={data?.floors}
|
||||||
|
labelKey="name"
|
||||||
|
valueKey="id"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mb-2">
|
||||||
|
<SelectMultiple
|
||||||
|
name="workAreaIds"
|
||||||
|
label="Select Work Area:"
|
||||||
|
options={data?.workAreas}
|
||||||
|
labelKey="name"
|
||||||
|
valueKey="id"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mb-2">
|
||||||
|
<SelectMultiple
|
||||||
|
name="workCategoryIds"
|
||||||
|
label="Select Work Category:"
|
||||||
|
options={data?.workCategories}
|
||||||
|
labelKey="name"
|
||||||
|
valueKey="id"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mb-2">
|
||||||
|
<SelectMultiple
|
||||||
|
name="activityIds"
|
||||||
|
label="Select Activity:"
|
||||||
|
|
||||||
|
|
||||||
|
options={data?.activities}
|
||||||
|
labelKey="name"
|
||||||
|
valueKey="id"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mb-2">
|
||||||
|
<SelectMultiple
|
||||||
|
name="uploadedByIds"
|
||||||
|
label="Select Uploaded By:"
|
||||||
|
options={data?.UploadedBys}
|
||||||
|
labelKey="name"
|
||||||
|
valueKey="id"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mb-2">
|
||||||
|
<SelectMultiple
|
||||||
|
name="serviceIds"
|
||||||
|
label="Select Service:"
|
||||||
|
options={data?.services}
|
||||||
|
labelKey="name"
|
||||||
|
valueKey="id"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="d-flex flex-row gap-3 justify-content-end">
|
||||||
|
<button className="btn btn-sm btn-label-secondary">Cancel</button>
|
||||||
|
<button type="submit" className="btn btn-sm btn-primary">
|
||||||
|
Apply
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</FormProvider>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GalleryFilterPanel;
|
25
src/components/gallary/GallerySchema.jsx
Normal file
25
src/components/gallary/GallerySchema.jsx
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
export const gallerySchema = z.object({
|
||||||
|
buildingIds: z.array(z.string()).optional(),
|
||||||
|
floorIds: z.array(z.string()).optional(),
|
||||||
|
workAreaIds: z.array(z.string()).optional(),
|
||||||
|
activityIds: z.array(z.string()).optional(),
|
||||||
|
workCategoryIds: z.array(z.string()).optional(),
|
||||||
|
startDate: z.string().optional(),
|
||||||
|
endDate: z.string().optional(),
|
||||||
|
uploadedByIds: z.array(z.string()).optional(),
|
||||||
|
serviceIds: z.array(z.string()).optional(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const defaultGalleryFilterValue = {
|
||||||
|
buildingIds: [],
|
||||||
|
floorIds: [],
|
||||||
|
workAreaIds: [],
|
||||||
|
activityIds: [],
|
||||||
|
workCategoryIds:[],
|
||||||
|
startDate: null,
|
||||||
|
endDate: null,
|
||||||
|
uploadedByIds:[],
|
||||||
|
serviceIds: [],
|
||||||
|
};
|
169
src/components/gallary/ImageGalleryListView.jsx
Normal file
169
src/components/gallary/ImageGalleryListView.jsx
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
import React, { useRef, useState, useCallback, useEffect } from "react";
|
||||||
|
import moment from "moment";
|
||||||
|
import Avatar from "../../components/common/Avatar";
|
||||||
|
import { useGalleryContext } from "../../pages/Gallary/ImageGallaryPage";
|
||||||
|
import useImageGallery from "../../hooks/useImageGallery";
|
||||||
|
import { useSelectedProject } from "../../slices/apiDataManager";
|
||||||
|
import { ITEMS_PER_PAGE } from "../../utils/constants";
|
||||||
|
import Pagination from "../common/Pagination";
|
||||||
|
import { formatUTCToLocalTime } from "../../utils/dateUtils";
|
||||||
|
import Loader from "../common/Loader";
|
||||||
|
|
||||||
|
const ImageGalleryListView = () => {
|
||||||
|
const [hoveredImage, setHoveredImage] = useState(null);
|
||||||
|
const selectedProject = useSelectedProject();
|
||||||
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
|
const { setOpenGallery } = useGalleryContext();
|
||||||
|
|
||||||
|
const { data, isLoading, isError, error } = useImageGallery(
|
||||||
|
selectedProject,
|
||||||
|
currentPage,
|
||||||
|
10,
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
|
||||||
|
const paginate = (page) => {
|
||||||
|
if (page >= 1 && page <= (data?.totalPages ?? 1)) {
|
||||||
|
setCurrentPage(page);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!data?.data?.length && !isLoading) {
|
||||||
|
return (
|
||||||
|
<p className="text-center text-muted mt-5">
|
||||||
|
{selectedProject ? " No images match the selected filters.":"Please Select Project!"}
|
||||||
|
</p>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return (
|
||||||
|
<div className="page-min-h d-flex justify-content-center align-items-center">
|
||||||
|
<Loader />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="main-content">
|
||||||
|
<div className="activity-section">
|
||||||
|
{data?.data?.map((batch) => {
|
||||||
|
if (!batch.documents?.length) return null;
|
||||||
|
|
||||||
|
const doc = batch.documents[0];
|
||||||
|
const userName = `${doc.uploadedBy?.firstName || ""} ${
|
||||||
|
doc.uploadedBy?.lastName || ""
|
||||||
|
}`.trim();
|
||||||
|
const date = formatUTCToLocalTime(doc.uploadedAt);
|
||||||
|
// const hasArrows = batch.documents.length > scrollThreshold;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div key={batch.batchId} className="grouped-section">
|
||||||
|
<div className="group-heading">
|
||||||
|
<div className="d-flex align-items-center mb-1">
|
||||||
|
<Avatar
|
||||||
|
size="xs"
|
||||||
|
firstName={doc.uploadedBy?.firstName}
|
||||||
|
lastName={doc.uploadedBy?.lastName}
|
||||||
|
className="me-2"
|
||||||
|
/>
|
||||||
|
<div className="d-flex flex-column align-items-start">
|
||||||
|
<strong className="user-name-text">{userName}</strong>
|
||||||
|
<span className="text-muted small">{date}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="location-line text-secondary">
|
||||||
|
<div className="d-flex align-items-center flex-wrap gap-1 text-secondary">
|
||||||
|
<span className="d-flex align-items-center">
|
||||||
|
<span>{batch.buildingName}</span>
|
||||||
|
<i className="bx bx-chevron-right " />
|
||||||
|
</span>
|
||||||
|
<span className="d-flex align-items-center">
|
||||||
|
<span>{batch.floorName}</span>
|
||||||
|
<i className="bx bx-chevron-right m" />
|
||||||
|
</span>
|
||||||
|
<span className="d-flex align-items-center ">
|
||||||
|
<span>{batch.workAreaName || "Unknown"}</span>
|
||||||
|
<i className="bx bx-chevron-right " />
|
||||||
|
<span>{batch.activityName}</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{batch.workCategoryName && (
|
||||||
|
<span className="badge bg-label-primary ms-2">
|
||||||
|
{batch.workCategoryName}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="image-group-wrapper">
|
||||||
|
{/* {hasArrows && (
|
||||||
|
<button className="scroll-arrow left-arrow" onClick={() => scrollLeft(batch.batchId)}>
|
||||||
|
‹
|
||||||
|
</button>
|
||||||
|
)} */}
|
||||||
|
<div
|
||||||
|
className="image-group-horizontal"
|
||||||
|
// ref={(el) => (imageGroupRefs.current[batch.batchId] = el)}
|
||||||
|
>
|
||||||
|
{batch.documents.map((d, i) => {
|
||||||
|
const hoverDate = moment().format("DD MMMM, YYYY");
|
||||||
|
const hoverTime = moment(d.uploadedAt).format("hh:mm A");
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={d.id}
|
||||||
|
className="image-card"
|
||||||
|
onMouseEnter={() => setHoveredImage(d)}
|
||||||
|
onMouseLeave={() => setHoveredImage(null)}
|
||||||
|
onClick={() =>
|
||||||
|
setOpenGallery({
|
||||||
|
isOpen: true,
|
||||||
|
data: { data: batch, index: i },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className="image-wrapper">
|
||||||
|
<img src={d.url} alt={`Image ${i + 1}`} />
|
||||||
|
</div>
|
||||||
|
{hoveredImage === d && (
|
||||||
|
<div className="image-hover-description">
|
||||||
|
<p>
|
||||||
|
<strong>Date:</strong> {hoverDate}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>Time:</strong> {hoverTime}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>Activity:</strong> {batch.activityName}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
{/* {hasArrows && (
|
||||||
|
<button className="scroll-arrow right-arrow" onClick={() => scrollRight(batch.batchId)}>
|
||||||
|
‹
|
||||||
|
</button>
|
||||||
|
)} */}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{data?.data?.length > 0 && (
|
||||||
|
<Pagination
|
||||||
|
currentPage={currentPage}
|
||||||
|
totalPages={data?.totalPages}
|
||||||
|
onPageChange={paginate}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ImageGalleryListView;
|
111
src/components/gallary/ViewGallery.jsx
Normal file
111
src/components/gallary/ViewGallery.jsx
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import { formatUTCToLocalTime } from "../../utils/dateUtils";
|
||||||
|
|
||||||
|
const ViewGallery = ({ batch, index }) => {
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [currentIndex, setCurrentIndex] = useState(index);
|
||||||
|
console.log(batch);
|
||||||
|
useEffect(() => {
|
||||||
|
setCurrentIndex(index);
|
||||||
|
}, [index, batch]);
|
||||||
|
|
||||||
|
if (!batch || !batch.documents || batch.documents.length === 0) return null;
|
||||||
|
|
||||||
|
const image = batch.documents[currentIndex];
|
||||||
|
if (!image) return null;
|
||||||
|
|
||||||
|
const fullName = `${image.uploadedBy?.firstName || ""} ${
|
||||||
|
image.uploadedBy?.lastName || ""
|
||||||
|
}`.trim();
|
||||||
|
const date = formatUTCToLocalTime(image.uploadedAt);
|
||||||
|
|
||||||
|
const buildingName = batch.buildingName;
|
||||||
|
const floorName = batch.floorName;
|
||||||
|
const workAreaName = batch.workAreaName;
|
||||||
|
const activityName = batch.activityName;
|
||||||
|
const batchComment = batch.comment;
|
||||||
|
|
||||||
|
const handlePrev = () => {
|
||||||
|
setCurrentIndex((prevIndex) => Math.max(0, prevIndex - 1));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleNext = () => {
|
||||||
|
setCurrentIndex((prevIndex) =>
|
||||||
|
Math.min(batch.documents.length - 1, prevIndex + 1)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const hasPrev = currentIndex > 0;
|
||||||
|
const hasNext = currentIndex < batch.documents.length - 1;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
|
||||||
|
{loading && <p>Loading...</p>}
|
||||||
|
<div className="position-relative d-flex justify-content-center align-items-center">
|
||||||
|
{hasPrev && (
|
||||||
|
<button
|
||||||
|
className="btn btn-icon btn-outline-primary rounded-circle position-absolute start-0 top-50 translate-middle-y shadow"
|
||||||
|
onClick={handlePrev}
|
||||||
|
>
|
||||||
|
<i className="bx bx-chevron-left fs-4"></i>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<img
|
||||||
|
src={image.url}
|
||||||
|
alt="Preview"
|
||||||
|
className="img-fluid rounded"
|
||||||
|
style={{
|
||||||
|
maxHeight: "500px",
|
||||||
|
width: "100%",
|
||||||
|
objectFit: "contain",
|
||||||
|
}}
|
||||||
|
onLoad={() => setLoading(false)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{hasNext && (
|
||||||
|
<button
|
||||||
|
className="btn btn-icon btn-outline-primary position-absolute end-0 top-50 translate-middle-y rounded-circle shadow"
|
||||||
|
onClick={handleNext}
|
||||||
|
>
|
||||||
|
<i className="bx bx-chevron-right fs-4"></i>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Details */}
|
||||||
|
<div className="mt-3 text-start small">
|
||||||
|
<p className="mb-1">
|
||||||
|
<i className="bx bxs-user me-2"></i>
|
||||||
|
<span className="text-muted">Uploaded By: </span>
|
||||||
|
<span className="fw-semibold">{fullName}</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p className="mb-1">
|
||||||
|
<i className="bx bxs-calendar me-2"></i>
|
||||||
|
<span className="text-muted">Date: </span>
|
||||||
|
<span className="fw-semibold">{date}</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p className="mb-1">
|
||||||
|
<i className="bx bx-map me-2"></i>
|
||||||
|
<span className="text-muted">Location: </span>
|
||||||
|
<span className="fw-semibold">
|
||||||
|
{buildingName} <i className="bx bx-chevron-right"></i> {floorName}{" "}
|
||||||
|
<i className="bx bx-chevron-right"></i> {workAreaName || "Unknown"}{" "}
|
||||||
|
<i className="bx bx-chevron-right"></i> {activityName}
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p className="mb-0">
|
||||||
|
<i className="bx bx-comment-dots me-2"></i>
|
||||||
|
<span className="text-muted">Comment: </span>
|
||||||
|
<span className="fw-semibold">{batchComment}</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ViewGallery;
|
@ -1,5 +1,9 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { cacheData, getCachedData, useSelectedProject } from "../slices/apiDataManager";
|
import {
|
||||||
|
cacheData,
|
||||||
|
getCachedData,
|
||||||
|
useSelectedProject,
|
||||||
|
} from "../slices/apiDataManager";
|
||||||
import AttendanceRepository from "../repositories/AttendanceRepository";
|
import AttendanceRepository from "../repositories/AttendanceRepository";
|
||||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||||
import showToast from "../services/toastService";
|
import showToast from "../services/toastService";
|
||||||
@ -7,11 +11,8 @@ import { useDispatch, useSelector } from "react-redux";
|
|||||||
import { store } from "../store/store";
|
import { store } from "../store/store";
|
||||||
import { setDefaultDateRange } from "../slices/localVariablesSlice";
|
import { setDefaultDateRange } from "../slices/localVariablesSlice";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------Query-----------------------------
|
// ----------------------------Query-----------------------------
|
||||||
|
|
||||||
|
|
||||||
// export const useAttendance = (projectId) => {
|
// export const useAttendance = (projectId) => {
|
||||||
// const dispatch = useDispatch()
|
// const dispatch = useDispatch()
|
||||||
// const {
|
// const {
|
||||||
@ -41,7 +42,10 @@ import { setDefaultDateRange } from "../slices/localVariablesSlice";
|
|||||||
// };
|
// };
|
||||||
// };
|
// };
|
||||||
|
|
||||||
export const useAttendance = (projectId, organizationId, includeInactive = false, date = null) => {
|
export const useAttendance = (
|
||||||
|
projectId,
|
||||||
|
organizationId,
|
||||||
|
) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -51,13 +55,11 @@ export const useAttendance = (projectId, organizationId, includeInactive = false
|
|||||||
refetch: recall,
|
refetch: recall,
|
||||||
isFetching,
|
isFetching,
|
||||||
} = useQuery({
|
} = useQuery({
|
||||||
queryKey: ["attendance", projectId, organizationId, includeInactive, date], // include filters in cache key
|
queryKey: ["attendance", projectId, organizationId], // include filters in cache key
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const response = await AttendanceRepository.getAttendance(
|
const response = await AttendanceRepository.getAttendance(
|
||||||
projectId,
|
projectId,
|
||||||
organizationId,
|
organizationId,
|
||||||
includeInactive,
|
|
||||||
date
|
|
||||||
);
|
);
|
||||||
return response.data;
|
return response.data;
|
||||||
},
|
},
|
||||||
@ -70,12 +72,17 @@ export const useAttendance = (projectId, organizationId, includeInactive = false
|
|||||||
return { attendance, loading, error, recall, isFetching };
|
return { attendance, loading, error, recall, isFetching };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useAttendancesLogs = (projectId, fromDate, toDate,organizationId) => {
|
export const useAttendancesLogs = (
|
||||||
|
projectId,
|
||||||
|
fromDate,
|
||||||
|
toDate,
|
||||||
|
organizationId
|
||||||
|
) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const enabled = !!projectId && !!fromDate && !!toDate;
|
const enabled = !!projectId && !!fromDate && !!toDate;
|
||||||
|
|
||||||
const query = useQuery({
|
const query = useQuery({
|
||||||
queryKey: ['attendanceLogs', projectId, fromDate, toDate,organizationId],
|
queryKey: ["attendanceLogs", projectId, fromDate, toDate, organizationId],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const res = await AttendanceRepository.getAttendanceFilteredByDate(
|
const res = await AttendanceRepository.getAttendanceFilteredByDate(
|
||||||
projectId,
|
projectId,
|
||||||
@ -87,7 +94,7 @@ export const useAttendancesLogs = (projectId, fromDate, toDate,organizationId) =
|
|||||||
},
|
},
|
||||||
enabled,
|
enabled,
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (query.data && fromDate && toDate) {
|
if (query.data && fromDate && toDate) {
|
||||||
dispatch(
|
dispatch(
|
||||||
@ -101,8 +108,6 @@ export const useAttendancesLogs = (projectId, fromDate, toDate,organizationId) =
|
|||||||
return query;
|
return query;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const useEmployeeAttendacesLog = (id) => {
|
export const useEmployeeAttendacesLog = (id) => {
|
||||||
const {
|
const {
|
||||||
data: logs = [],
|
data: logs = [],
|
||||||
@ -117,7 +122,10 @@ export const useEmployeeAttendacesLog = (id) => {
|
|||||||
},
|
},
|
||||||
enabled: !!id,
|
enabled: !!id,
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
showToast(error.message || "Error while fetching Attendance Logs", "error");
|
showToast(
|
||||||
|
error.message || "Error while fetching Attendance Logs",
|
||||||
|
"error"
|
||||||
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -135,16 +143,22 @@ export const useAttendanceByEmployee = (employeeId, fromDate, toDate) => {
|
|||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: ["employeeAttendance", employeeId, fromDate, toDate],
|
queryKey: ["employeeAttendance", employeeId, fromDate, toDate],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const res = await AttendanceRepository.getAttendanceByEmployee(employeeId, fromDate, toDate);
|
const res = await AttendanceRepository.getAttendanceByEmployee(
|
||||||
|
employeeId,
|
||||||
|
fromDate,
|
||||||
|
toDate
|
||||||
|
);
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
enabled
|
enabled,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useRegularizationRequests = (
|
||||||
|
projectId,
|
||||||
export const useRegularizationRequests = (projectId, organizationId, IncludeInActive = false) => {
|
organizationId,
|
||||||
|
IncludeInActive = false
|
||||||
|
) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -159,7 +173,7 @@ export const useRegularizationRequests = (projectId, organizationId, IncludeInAc
|
|||||||
const response = await AttendanceRepository.getRegularizeList(
|
const response = await AttendanceRepository.getRegularizeList(
|
||||||
projectId,
|
projectId,
|
||||||
organizationId,
|
organizationId,
|
||||||
IncludeInActive,
|
IncludeInActive
|
||||||
);
|
);
|
||||||
return response.data;
|
return response.data;
|
||||||
},
|
},
|
||||||
@ -172,48 +186,61 @@ export const useRegularizationRequests = (projectId, organizationId, IncludeInAc
|
|||||||
return { regularizes, loading, error, recall, isFetching };
|
return { regularizes, loading, error, recall, isFetching };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// -------------------Mutation--------------------------------------
|
// -------------------Mutation--------------------------------------
|
||||||
|
|
||||||
export const useMarkAttendance = () => {
|
export const useMarkAttendance = () => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const selectedProject = useSelectedProject();
|
const selectedProject = useSelectedProject();
|
||||||
const selectedDateRange = useSelector((store)=>store.localVariables.defaultDateRange)
|
const selectedDateRange = useSelector(
|
||||||
|
(store) => store.localVariables.attendance.defaultDateRange
|
||||||
|
);
|
||||||
|
const selectedOrganization = useSelector(
|
||||||
|
(store) => store.localVariables.attendance.SelectedOrg
|
||||||
|
);
|
||||||
|
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: async ({payload,forWhichTab}) => {
|
mutationFn: async ({ payload, forWhichTab }) => {
|
||||||
const res = await AttendanceRepository.markAttendance(payload);
|
const res = await AttendanceRepository.markAttendance(payload);
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
|
|
||||||
onSuccess: (data,variables) => {
|
onSuccess: (data, variables) => {
|
||||||
if(variables.forWhichTab == 1){
|
if (variables.forWhichTab == 1) {
|
||||||
queryClient.setQueryData(["attendance",selectedProject], (oldData) => {
|
queryClient.setQueryData(["attendance", selectedProject,selectedOrganization], (oldData) => {
|
||||||
if (!oldData) return oldData;
|
|
||||||
return oldData.map((emp) =>
|
|
||||||
emp.employeeId === data.employeeId ? { ...emp, ...data } : emp
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}else if(variables.forWhichTab == 2){
|
|
||||||
// queryClient.invalidateQueries({
|
|
||||||
// queryKey: ["attendanceLogs"],
|
|
||||||
// });
|
|
||||||
queryClient.setQueryData(["attendanceLogs",selectedProject,selectedDateRange.startDate,selectedDateRange.endDate], (oldData) => {
|
|
||||||
if (!oldData) return oldData;
|
|
||||||
return oldData.map((record) =>
|
|
||||||
record.id === data.id ? { ...record, ...data } : record
|
|
||||||
);
|
|
||||||
});
|
|
||||||
queryClient.invalidateQueries({queryKey:["regularizedList"]})
|
|
||||||
}else(
|
|
||||||
queryClient.setQueryData(["regularizedList",selectedProject], (oldData) => {
|
|
||||||
if (!oldData) return oldData;
|
|
||||||
return oldData.filter((record) => record.id !== data.id)
|
|
||||||
}),
|
|
||||||
queryClient.invalidateQueries({queryKey:["attendanceLogs"]})
|
|
||||||
)
|
|
||||||
|
|
||||||
if(variables.forWhichTab !== 3) showToast("Attendance marked successfully", "success");
|
if (!oldData) return oldData;
|
||||||
|
return oldData.map((emp) =>
|
||||||
|
emp.employeeId === data.employeeId ? { ...emp, ...data } : emp
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else if (variables.forWhichTab == 2) {
|
||||||
|
queryClient.setQueryData(
|
||||||
|
[
|
||||||
|
"attendanceLogs",
|
||||||
|
selectedProject,
|
||||||
|
selectedDateRange.startDate,
|
||||||
|
selectedDateRange.endDate,selectedOrganization
|
||||||
|
],
|
||||||
|
(oldData) => {
|
||||||
|
if (!oldData) return oldData;
|
||||||
|
return oldData.map((record) =>
|
||||||
|
record.id === data.id ? { ...record, ...data } : record
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["regularizedList"] });
|
||||||
|
} else
|
||||||
|
queryClient.setQueryData(
|
||||||
|
["regularizedList", selectedProject],
|
||||||
|
(oldData) => {
|
||||||
|
if (!oldData) return oldData;
|
||||||
|
return oldData.filter((record) => record.id !== data.id);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["attendanceLogs"] });
|
||||||
|
|
||||||
|
if (variables.forWhichTab !== 3)
|
||||||
|
showToast("Attendance marked successfully", "success");
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
showToast(error.message || "Failed to mark attendance", "error");
|
showToast(error.message || "Failed to mark attendance", "error");
|
||||||
|
@ -1,116 +1,45 @@
|
|||||||
import { useState, useCallback } from "react";
|
import { useState, useCallback } from "react";
|
||||||
// import { ImageGalleryAPI } from "../repositories/ImageGalleyRepository";
|
// import { ImageGalleryAPI } from "../repositories/ImageGalleyRepository";
|
||||||
import { ImageGalleryAPI } from "../repositories/ImageGalleryAPI";
|
import { ImageGalleryRepository } from "../repositories/ImageGalleryAPI";
|
||||||
|
|
||||||
// const PAGE_SIZE = 10;
|
|
||||||
|
|
||||||
// const useImageGallery = (selectedProjectId) => {
|
import { useInfiniteQuery, useQuery } from "@tanstack/react-query";
|
||||||
// const [images, setImages] = useState([]);
|
|
||||||
// const [allImagesData, setAllImagesData] = useState([]);
|
|
||||||
// const [pageNumber, setPageNumber] = useState(1);
|
|
||||||
// const [hasMore, setHasMore] = useState(true);
|
|
||||||
// const [loading, setLoading] = useState(false);
|
|
||||||
// const [loadingMore, setLoadingMore] = useState(false);
|
|
||||||
|
|
||||||
// const fetchImages = useCallback(async (page = 1, filters = {}, reset = false) => {
|
|
||||||
// if (!selectedProjectId) return;
|
|
||||||
|
|
||||||
// try {
|
|
||||||
// if (page === 1) {
|
|
||||||
// setLoading(true);
|
|
||||||
// } else {
|
|
||||||
// setLoadingMore(true);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const res = await ImageGalleryAPI.ImagesGet(
|
|
||||||
// selectedProjectId,
|
|
||||||
// filters,
|
|
||||||
// page,
|
|
||||||
// PAGE_SIZE
|
|
||||||
// );
|
|
||||||
|
|
||||||
// const newBatches = res.data || [];
|
|
||||||
// const receivedCount = newBatches.length;
|
|
||||||
|
|
||||||
// setImages((prev) => {
|
|
||||||
// if (page === 1 || reset) return newBatches;
|
|
||||||
// const uniqueNew = newBatches.filter(
|
|
||||||
// (batch) => !prev.some((b) => b.batchId === batch.batchId)
|
|
||||||
// );
|
|
||||||
// return [...prev, ...uniqueNew];
|
|
||||||
// });
|
|
||||||
|
|
||||||
// setAllImagesData((prev) => {
|
|
||||||
// if (page === 1 || reset) return newBatches;
|
|
||||||
// const uniqueAll = newBatches.filter(
|
|
||||||
// (batch) => !prev.some((b) => b.batchId === batch.batchId)
|
|
||||||
// );
|
|
||||||
// return [...prev, ...uniqueAll];
|
|
||||||
// });
|
|
||||||
|
|
||||||
// setHasMore(receivedCount === PAGE_SIZE);
|
|
||||||
// } catch (error) {
|
|
||||||
// console.error("Error fetching images:", error);
|
|
||||||
// if (page === 1) {
|
|
||||||
// setImages([]);
|
|
||||||
// setAllImagesData([]);
|
|
||||||
// }
|
|
||||||
// setHasMore(false);
|
|
||||||
// } finally {
|
|
||||||
// setLoading(false);
|
|
||||||
// setLoadingMore(false);
|
|
||||||
// }
|
|
||||||
// }, [selectedProjectId]);
|
|
||||||
|
|
||||||
// const resetGallery = useCallback(() => {
|
|
||||||
// setImages([]);
|
|
||||||
// setAllImagesData([]);
|
|
||||||
// setPageNumber(1);
|
|
||||||
// setHasMore(true);
|
|
||||||
// }, []);
|
|
||||||
|
|
||||||
// return {
|
|
||||||
// images,
|
|
||||||
// allImagesData,
|
|
||||||
// pageNumber,
|
|
||||||
// setPageNumber,
|
|
||||||
// hasMore,
|
|
||||||
// loading,
|
|
||||||
// loadingMore,
|
|
||||||
// fetchImages,
|
|
||||||
// resetGallery,
|
|
||||||
// };
|
|
||||||
// };
|
|
||||||
|
|
||||||
// export default useImageGallery;
|
|
||||||
import { useInfiniteQuery } from "@tanstack/react-query";
|
|
||||||
|
|
||||||
|
|
||||||
const PAGE_SIZE = 10;
|
const PAGE_SIZE = 10;
|
||||||
|
|
||||||
const useImageGallery = (selectedProjectId, filters) => {
|
const useImageGallery = (selectedProjectId,pageNumber, pageSize, filters) => {
|
||||||
const hasFilters = filters && Object.values(filters).some(
|
const hasFilters = filters && Object.values(filters).some(
|
||||||
value => Array.isArray(value) ? value.length > 0 : value !== null && value !== ""
|
value => Array.isArray(value) ? value.length > 0 : value !== null && value !== ""
|
||||||
);
|
);
|
||||||
|
|
||||||
return useInfiniteQuery({
|
return useQuery({
|
||||||
queryKey: ["imageGallery", selectedProjectId, hasFilters ? filters : null],
|
queryKey: ["imageGallery", selectedProjectId, pageNumber, pageSize, hasFilters ? filters : null],
|
||||||
enabled: !!selectedProjectId,
|
enabled: !!selectedProjectId,
|
||||||
getNextPageParam: (lastPage, allPages) => {
|
|
||||||
if (!lastPage?.data?.length) return undefined;
|
queryFn: async () => {
|
||||||
return allPages.length + 1;
|
const res = await ImageGalleryRepository.ImagesGet(
|
||||||
},
|
|
||||||
queryFn: async ({ pageParam = 1 }) => {
|
|
||||||
const res = await ImageGalleryAPI.ImagesGet(
|
|
||||||
selectedProjectId,
|
selectedProjectId,
|
||||||
|
pageNumber,
|
||||||
|
pageSize,
|
||||||
hasFilters ? filters : undefined,
|
hasFilters ? filters : undefined,
|
||||||
pageParam,
|
|
||||||
PAGE_SIZE
|
|
||||||
);
|
);
|
||||||
return res;
|
return res.data;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useImageGallery;
|
export default useImageGallery;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const useImageGalleryFilter = (project)=>{
|
||||||
|
return useQuery({
|
||||||
|
queryKey:["imageGalleryFlter",project],
|
||||||
|
queryFn:async() => {
|
||||||
|
const response = await ImageGalleryRepository.getImageGalleryFilter(project);
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,10 @@ import { setProjectId } from "../../slices/localVariablesSlice";
|
|||||||
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
|
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
|
||||||
import { REGULARIZE_ATTENDANCE } from "../../utils/constants";
|
import { REGULARIZE_ATTENDANCE } from "../../utils/constants";
|
||||||
import eventBus from "../../services/eventBus";
|
import eventBus from "../../services/eventBus";
|
||||||
import { useProjectAssignedOrganizations, useProjectName } from "../../hooks/useProjects";
|
import {
|
||||||
|
useProjectAssignedOrganizations,
|
||||||
|
useProjectName,
|
||||||
|
} from "../../hooks/useProjects";
|
||||||
import GlobalModel from "../../components/common/GlobalModel";
|
import GlobalModel from "../../components/common/GlobalModel";
|
||||||
import CheckCheckOutmodel from "../../components/Activities/CheckCheckOutForm";
|
import CheckCheckOutmodel from "../../components/Activities/CheckCheckOutForm";
|
||||||
import AttendLogs from "../../components/Activities/AttendLogs";
|
import AttendLogs from "../../components/Activities/AttendLogs";
|
||||||
@ -101,11 +104,11 @@ const AttendancePage = () => {
|
|||||||
{(modelConfig?.action === 0 ||
|
{(modelConfig?.action === 0 ||
|
||||||
modelConfig?.action === 1 ||
|
modelConfig?.action === 1 ||
|
||||||
modelConfig?.action === 2) && (
|
modelConfig?.action === 2) && (
|
||||||
<CheckCheckOutmodel
|
<CheckCheckOutmodel
|
||||||
modeldata={modelConfig}
|
modeldata={modelConfig}
|
||||||
closeModal={closeModal}
|
closeModal={closeModal}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{/* For view logs */}
|
{/* For view logs */}
|
||||||
{modelConfig?.action === 6 && (
|
{modelConfig?.action === 6 && (
|
||||||
<AttendLogs Id={modelConfig?.id} closeModal={closeModal} />
|
<AttendLogs Id={modelConfig?.id} closeModal={closeModal} />
|
||||||
@ -134,8 +137,9 @@ const AttendancePage = () => {
|
|||||||
<li className="nav-item">
|
<li className="nav-item">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className={`nav-link ${activeTab === "all" ? "active" : ""
|
className={`nav-link ${
|
||||||
} fs-6`}
|
activeTab === "all" ? "active" : ""
|
||||||
|
} fs-6`}
|
||||||
onClick={() => handleTabChange("all")}
|
onClick={() => handleTabChange("all")}
|
||||||
data-bs-toggle="tab"
|
data-bs-toggle="tab"
|
||||||
data-bs-target="#navs-top-home"
|
data-bs-target="#navs-top-home"
|
||||||
@ -146,8 +150,9 @@ const AttendancePage = () => {
|
|||||||
<li className="nav-item">
|
<li className="nav-item">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className={`nav-link ${activeTab === "logs" ? "active" : ""
|
className={`nav-link ${
|
||||||
} fs-6`}
|
activeTab === "logs" ? "active" : ""
|
||||||
|
} fs-6`}
|
||||||
onClick={() => handleTabChange("logs")}
|
onClick={() => handleTabChange("logs")}
|
||||||
data-bs-toggle="tab"
|
data-bs-toggle="tab"
|
||||||
data-bs-target="#navs-top-profile"
|
data-bs-target="#navs-top-profile"
|
||||||
@ -159,8 +164,9 @@ const AttendancePage = () => {
|
|||||||
<li className={`nav-item ${!DoRegularized ? "d-none" : ""}`}>
|
<li className={`nav-item ${!DoRegularized ? "d-none" : ""}`}>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className={`nav-link ${activeTab === "regularization" ? "active" : ""
|
className={`nav-link ${
|
||||||
} fs-6`}
|
activeTab === "regularization" ? "active" : ""
|
||||||
|
} fs-6`}
|
||||||
onClick={() => handleTabChange("regularization")}
|
onClick={() => handleTabChange("regularization")}
|
||||||
data-bs-toggle="tab"
|
data-bs-toggle="tab"
|
||||||
data-bs-target="#navs-top-messages"
|
data-bs-target="#navs-top-messages"
|
||||||
@ -187,8 +193,8 @@ const AttendancePage = () => {
|
|||||||
disabled={orgLoading}
|
disabled={orgLoading}
|
||||||
>
|
>
|
||||||
<option value="">All Organizations</option>
|
<option value="">All Organizations</option>
|
||||||
{organizations?.map((org) => (
|
{organizations?.map((org, ind) => (
|
||||||
<option key={org.id} value={org.id}>
|
<option key={`${org.id}-${ind}`} value={org.id}>
|
||||||
{org.name}
|
{org.name}
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
@ -204,8 +210,6 @@ const AttendancePage = () => {
|
|||||||
style={{ minWidth: "200px" }}
|
style={{ minWidth: "200px" }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { useState, useEffect, useRef, useCallback } from "react";
|
import React, { useState, useEffect, useRef, useCallback } from "react";
|
||||||
import "./ImageGallery.css";
|
// import "./ImageGallery.css";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { useModal } from "./ModalContext";
|
import { useModal } from "./ModalContext";
|
||||||
|
124
src/pages/Gallary/ImageGallaryPage.jsx
Normal file
124
src/pages/Gallary/ImageGallaryPage.jsx
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
import React, {
|
||||||
|
useState,
|
||||||
|
useEffect,
|
||||||
|
useRef,
|
||||||
|
useContext,
|
||||||
|
createContext,
|
||||||
|
} from "react";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
import moment from "moment";
|
||||||
|
import eventBus from "../../services/eventBus";
|
||||||
|
import Breadcrumb from "../../components/common/Breadcrumb";
|
||||||
|
import { formatUTCToLocalTime } from "../../utils/dateUtils";
|
||||||
|
import useImageGallery from "../../hooks/useImageGallery";
|
||||||
|
import {
|
||||||
|
useProjectAssignedServices,
|
||||||
|
useProjectName,
|
||||||
|
} from "../../hooks/useProjects";
|
||||||
|
import { setProjectId } from "../../slices/localVariablesSlice";
|
||||||
|
import ImageGalleryListView from "../../components/gallary/ImageGalleryListView";
|
||||||
|
import "../../components/gallary/ImageGallery.css";
|
||||||
|
import { useSelectedProject } from "../../slices/apiDataManager";
|
||||||
|
import GlobalModel from "../../components/common/GlobalModel";
|
||||||
|
import ViewGallery from "../../components/gallary/ViewGallery";
|
||||||
|
import { useFab } from "../../Context/FabContext";
|
||||||
|
import GalleryFilterPanel from "../../components/gallary/GalleryFilterPanel";
|
||||||
|
|
||||||
|
const GalleryContext = createContext();
|
||||||
|
|
||||||
|
export const useGalleryContext = () => {
|
||||||
|
let context = useContext(GalleryContext);
|
||||||
|
|
||||||
|
if (!context) {
|
||||||
|
throw new Error("Error");
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ImageGalleryPage = () => {
|
||||||
|
const selectedProjectId = useSelectedProject();
|
||||||
|
const { projectNames } = useProjectName();
|
||||||
|
|
||||||
|
const [openGallery, setOpenGallery] = useState({ isOpen: false, data: null });
|
||||||
|
|
||||||
|
const { data: assignedServices = [], isLoading } =
|
||||||
|
useProjectAssignedServices(selectedProjectId);
|
||||||
|
|
||||||
|
const [selectedService, setSelectedService] = useState("");
|
||||||
|
|
||||||
|
const handleServiceChange = (e) => {
|
||||||
|
setSelectedService(e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const contextMessager = {
|
||||||
|
setOpenGallery,
|
||||||
|
};
|
||||||
|
|
||||||
|
const { setOffcanvasContent, setShowTrigger } = useFab();
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
setShowTrigger(true);
|
||||||
|
setOffcanvasContent("Gallery Filter",<GalleryFilterPanel/>);
|
||||||
|
|
||||||
|
return ()=>{
|
||||||
|
setOffcanvasContent("",null)
|
||||||
|
setShowTrigger(false);
|
||||||
|
}
|
||||||
|
},[])
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<GalleryContext.Provider value={contextMessager}>
|
||||||
|
<div className="container-fluid">
|
||||||
|
<Breadcrumb
|
||||||
|
data={[{ label: "Home", link: "/" }, { label: "Gallery" }]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="card page-min-h p-2">
|
||||||
|
{selectedProjectId && (
|
||||||
|
<div className="d-flex flex-row w-20 pb-2">
|
||||||
|
{!isLoading && assignedServices?.length === 0 ? (
|
||||||
|
<span className="badge bg-label-secondary">
|
||||||
|
Not service assiged yet
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<select className="form-select form-select-sm">
|
||||||
|
<option>Select Service</option>
|
||||||
|
{isLoading ? (
|
||||||
|
<option>Loading...</option>
|
||||||
|
) : assignedServices.length === 1 ? (
|
||||||
|
<span className="badge bg-label-secondary">
|
||||||
|
{assignedServices[0].name}
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
assignedServices?.map((service) => (
|
||||||
|
<option key={service.id} value={service?.id}>
|
||||||
|
{service?.name}
|
||||||
|
</option>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</select>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<ImageGalleryListView />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{openGallery?.isOpen && (
|
||||||
|
<GlobalModel
|
||||||
|
isOpen={openGallery?.isOpen}
|
||||||
|
closeModal={() => setOpenGallery({ isOpen: false, data: null })}
|
||||||
|
>
|
||||||
|
<ViewGallery
|
||||||
|
batch={openGallery?.data?.data}
|
||||||
|
index={openGallery?.data?.index}
|
||||||
|
/>
|
||||||
|
</GlobalModel>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</GalleryContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ImageGalleryPage;
|
@ -1,8 +1,12 @@
|
|||||||
import { api } from "../utils/axiosClient";
|
import { api } from "../utils/axiosClient";
|
||||||
|
|
||||||
export const ImageGalleryAPI = {
|
export const ImageGalleryRepository = {
|
||||||
ImagesGet: (projectId, filter, pageNumber, pageSize) => {
|
ImagesGet: (projectId, pageNumber, pageSize,filter) => {
|
||||||
const payloadJsonString = JSON.stringify(filter);
|
const payloadJsonString = JSON.stringify(filter);
|
||||||
return api.get(`/api/image/images/${projectId}?filter=${payloadJsonString}&pageNumber=${pageNumber}&pageSize=${pageSize}`);
|
return api.get(`/api/image/images/${projectId}?pageNumber=${pageNumber}&pageSize=${pageSize}&filter=${payloadJsonString}`);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
getImageGalleryFilter:(projectId)=>api.get(`/api/Image/filter/${projectId}`)
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -53,6 +53,7 @@ import TenantSelectionPage from "../pages/authentication/TenantSelectionPage";
|
|||||||
import DailyProgrssReport from "../pages/DailyProgressReport/DailyProgrssReport";
|
import DailyProgrssReport from "../pages/DailyProgressReport/DailyProgrssReport";
|
||||||
import ProjectPage from "../pages/project/ProjectPage";
|
import ProjectPage from "../pages/project/ProjectPage";
|
||||||
import { ComingSoonPage } from "../pages/Misc/ComingSoonPage";
|
import { ComingSoonPage } from "../pages/Misc/ComingSoonPage";
|
||||||
|
import ImageGalleryPage from "../pages/Gallary/ImageGallaryPage";
|
||||||
const router = createBrowserRouter(
|
const router = createBrowserRouter(
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@ -93,7 +94,7 @@ const router = createBrowserRouter(
|
|||||||
{ path: "/activities/records/:projectId?", element: <DailyProgrssReport /> },
|
{ path: "/activities/records/:projectId?", element: <DailyProgrssReport /> },
|
||||||
{ path: "/activities/task", element: <TaskPlannng /> },
|
{ path: "/activities/task", element: <TaskPlannng /> },
|
||||||
{ path: "/activities/reports", element: <Reports /> },
|
{ path: "/activities/reports", element: <Reports /> },
|
||||||
{ path: "/gallary", element: <ComingSoonPage /> },
|
{ path: "/gallary", element: <ImageGalleryPage /> },
|
||||||
{ path: "/expenses", element: <ExpensePage /> },
|
{ path: "/expenses", element: <ExpensePage /> },
|
||||||
{ path: "/masters", element: <MasterPage /> },
|
{ path: "/masters", element: <MasterPage /> },
|
||||||
{ path: "/tenants", element: <TenantPage /> },
|
{ path: "/tenants", element: <TenantPage /> },
|
||||||
|
@ -4,10 +4,11 @@ const localVariablesSlice = createSlice({
|
|||||||
name: "localVariables",
|
name: "localVariables",
|
||||||
initialState: {
|
initialState: {
|
||||||
selectedMaster: "Application Role",
|
selectedMaster: "Application Role",
|
||||||
regularizationCount: 0,
|
// Attendances
|
||||||
defaultDateRange: {
|
attendance: {
|
||||||
startDate: null,
|
regularizationCount: 0,
|
||||||
endDate: null,
|
defaultDateRange: { startDate: null, endDate: null },
|
||||||
|
SelectedOrg:null,
|
||||||
},
|
},
|
||||||
projectId: null,
|
projectId: null,
|
||||||
reload: false,
|
reload: false,
|
||||||
@ -28,9 +29,20 @@ const localVariablesSlice = createSlice({
|
|||||||
changeMaster: (state, action) => {
|
changeMaster: (state, action) => {
|
||||||
state.selectedMaster = action.payload;
|
state.selectedMaster = action.payload;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
// ─── ATTENDANCE ─────────────────────────
|
||||||
updateRegularizationCount: (state, action) => {
|
updateRegularizationCount: (state, action) => {
|
||||||
state.regularizationCount = action.payload;
|
state.attendance.regularizationCount = action.payload;
|
||||||
},
|
},
|
||||||
|
setDefaultDateRange: (state, action) => {
|
||||||
|
state.attendance.defaultDateRange = action.payload;
|
||||||
|
},
|
||||||
|
setOrganization:(state,action)=>{
|
||||||
|
state.attendance.SelectedOrg = action.payload;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
setProjectId: (state, action) => {
|
setProjectId: (state, action) => {
|
||||||
localStorage.setItem("project", null);
|
localStorage.setItem("project", null);
|
||||||
state.projectId = action.payload;
|
state.projectId = action.payload;
|
||||||
@ -39,10 +51,6 @@ const localVariablesSlice = createSlice({
|
|||||||
refreshData: (state, action) => {
|
refreshData: (state, action) => {
|
||||||
state.reload = action.payload;
|
state.reload = action.payload;
|
||||||
},
|
},
|
||||||
setDefaultDateRange: (state, action) => {
|
|
||||||
state.defaultDateRange = action.payload;
|
|
||||||
},
|
|
||||||
|
|
||||||
openOrgModal: (state, action) => {
|
openOrgModal: (state, action) => {
|
||||||
state.OrganizationModal.isOpen = true;
|
state.OrganizationModal.isOpen = true;
|
||||||
state.OrganizationModal.orgData = action.payload?.orgData || null;
|
state.OrganizationModal.orgData = action.payload?.orgData || null;
|
||||||
@ -83,6 +91,6 @@ export const {
|
|||||||
closeOrgModal,
|
closeOrgModal,
|
||||||
toggleOrgModal,
|
toggleOrgModal,
|
||||||
openAuthModal,
|
openAuthModal,
|
||||||
closeAuthModal,
|
closeAuthModal,setOrganization
|
||||||
} = localVariablesSlice.actions;
|
} = localVariablesSlice.actions;
|
||||||
export default localVariablesSlice.reducer;
|
export default localVariablesSlice.reducer;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user