Compare commits
No commits in common. "f3e60bf8bcfb15ce56f1b034e28a72a8be851f57" and "9112f9f673d13ad3a46e65456778c09cdd8c33f1" have entirely different histories.
f3e60bf8bc
...
9112f9f673
@ -162,7 +162,7 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
if (isInitialLoading) return <ExpenseTableSkeleton />;
|
if (isInitialLoading) return <ExpenseTableSkeleton />;
|
||||||
if (isError) return <div>{error.message}</div>;
|
if (isError) return <div>{error}</div>;
|
||||||
|
|
||||||
const grouped = groupBy
|
const grouped = groupBy
|
||||||
? groupByField(data?.data ?? [], groupBy)
|
? groupByField(data?.data ?? [], groupBy)
|
||||||
|
|||||||
@ -1,19 +1,14 @@
|
|||||||
import { useState,useMemo } from "react";
|
import { useState } from "react";
|
||||||
import Avatar from "../common/Avatar";
|
import Avatar from "../common/Avatar";
|
||||||
import { formatUTCToLocalTime } from "../../utils/dateUtils";
|
import { formatUTCToLocalTime } from "../../utils/dateUtils";
|
||||||
|
|
||||||
|
|
||||||
const ExpenseStatusLogs = ({ data }) => {
|
const ExpenseStatusLogs = ({ data }) => {
|
||||||
const [visibleCount, setVisibleCount] = useState(4);
|
const [visibleCount, setVisibleCount] = useState(4);
|
||||||
|
|
||||||
const sortedLogs = useMemo(() => {
|
const logsToShow = [...(data?.expenseLogs || [])]
|
||||||
if (!data?.expenseLogs) return [];
|
.sort((a, b) => new Date(b.updateAt) - new Date(a.updateAt))
|
||||||
return [...data.expenseLogs].sort(
|
.slice(0, visibleCount);
|
||||||
(a, b) => new Date(b.updateAt) - new Date(a.updateAt)
|
|
||||||
);
|
|
||||||
}, [data?.expenseLogs]);
|
|
||||||
|
|
||||||
const logsToShow = sortedLogs.slice(0, visibleCount);
|
|
||||||
|
|
||||||
const handleShowMore = () => {
|
const handleShowMore = () => {
|
||||||
setVisibleCount((prev) => prev + 4);
|
setVisibleCount((prev) => prev + 4);
|
||||||
@ -22,8 +17,11 @@ const ExpenseStatusLogs = ({ data }) => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="row g-2">
|
<div className="row g-2">
|
||||||
{logsToShow.map((log) => (
|
{logsToShow.map((log, index) => (
|
||||||
<div key={log.id} className="col-12 d-flex align-items-start mb-1">
|
<div
|
||||||
|
key={log.id}
|
||||||
|
className="col-12 d-flex align-items-start mb-1"
|
||||||
|
>
|
||||||
<Avatar
|
<Avatar
|
||||||
size="xs"
|
size="xs"
|
||||||
firstName={log.updatedBy.firstName}
|
firstName={log.updatedBy.firstName}
|
||||||
@ -31,18 +29,20 @@ const ExpenseStatusLogs = ({ data }) => {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="flex-grow-1">
|
<div className="flex-grow-1">
|
||||||
<div className="text-start">
|
<div className="d-flex justify-content-start">
|
||||||
<div className="flex">
|
<div className="text-start">
|
||||||
<span>{`${log.updatedBy.firstName} ${log.updatedBy.lastName}`}</span>
|
<div >
|
||||||
<small className="text-secondary text-tiny ms-2">
|
<div className="flex">
|
||||||
<em>{log.action}</em>
|
<span>{`${log.updatedBy.firstName} ${log.updatedBy.lastName}`}</span>
|
||||||
</small>
|
<small className="text-secondary text-tiny ms-2">
|
||||||
<span className="text-tiny text-secondary d-block" >
|
<em>{log.action}</em>
|
||||||
{formatUTCToLocalTime(log.updateAt,true)}
|
</small>
|
||||||
</span>
|
<span className="text-tiny text-secondary d-block small">{formatUTCToLocalTime(log?.updateAt)}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="d-flex align-items-center text-muted small mt-1">
|
</div>
|
||||||
<span>{log.comment}</span>
|
<div className="d-flex align-items-center text-muted small mt-1">
|
||||||
|
<span className="small">{log.comment}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -50,7 +50,7 @@ const ExpenseStatusLogs = ({ data }) => {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{sortedLogs.length > visibleCount && (
|
{data?.expenseLogs?.length > visibleCount && (
|
||||||
<div className="text-center my-1">
|
<div className="text-center my-1">
|
||||||
<button
|
<button
|
||||||
className="btn btn-xs btn-outline-primary"
|
className="btn btn-xs btn-outline-primary"
|
||||||
@ -64,5 +64,4 @@ const ExpenseStatusLogs = ({ data }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export default ExpenseStatusLogs;
|
export default ExpenseStatusLogs;
|
||||||
|
|||||||
@ -548,7 +548,7 @@ const ManageExpense = ({ closeModal, expenseToEdit = null }) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="d-flex justify-content-center gap-3">
|
<div className="d-flex justify-content-center gap-2">
|
||||||
{" "}
|
{" "}
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
|
|||||||
@ -177,19 +177,20 @@ const ViewExpense = ({ ExpenseId }) => {
|
|||||||
<div className="text-muted">{data?.paymentMode?.name}</div>
|
<div className="text-muted">{data?.paymentMode?.name}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{data?.gstNumber && (
|
<div className="col-md-6 mb-3">
|
||||||
<div className="col-md-6 mb-3">
|
<div className="d-flex">
|
||||||
<div className="d-flex">
|
<label
|
||||||
<label
|
className="form-label me-2 mb-0 fw-semibold text-start"
|
||||||
className="form-label me-2 mb-0 fw-semibold text-start"
|
style={{ minWidth: "130px" }}
|
||||||
style={{ minWidth: "130px" }}
|
>
|
||||||
>
|
GST Number :
|
||||||
GST Number :
|
</label>
|
||||||
</label>
|
<div className="text-muted">
|
||||||
<div className="text-muted">{data?.gstNumber}</div>
|
{data?.gstNumber}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
</div>
|
||||||
|
|
||||||
|
|
||||||
{/* Row 4 */}
|
{/* Row 4 */}
|
||||||
<div className="col-md-6 mb-3">
|
<div className="col-md-6 mb-3">
|
||||||
@ -256,7 +257,7 @@ const ViewExpense = ({ ExpenseId }) => {
|
|||||||
>
|
>
|
||||||
Created By :
|
Created By :
|
||||||
</label>
|
</label>
|
||||||
<div className="d-flex align-items-center">
|
<div className="d-flex align-items-center gap-1">
|
||||||
<Avatar
|
<Avatar
|
||||||
size="xs"
|
size="xs"
|
||||||
classAvatar="m-0"
|
classAvatar="m-0"
|
||||||
@ -272,26 +273,16 @@ const ViewExpense = ({ ExpenseId }) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="col-md-6 text-start">
|
<div className="col-md-6 mb-3">
|
||||||
<div className="d-flex align-items-center">
|
<div className="d-flex">
|
||||||
<label
|
<label
|
||||||
className="form-label me-2 mb-0 fw-semibold"
|
className="form-label me-2 mb-0 fw-semibold text-start"
|
||||||
style={{ minWidth: "130px" }}
|
style={{ minWidth: "130px" }}
|
||||||
>
|
>
|
||||||
Paid By:
|
Paid By :
|
||||||
</label>
|
</label>
|
||||||
<div className="d-flex align-items-center ">
|
<div className="text-muted">
|
||||||
<Avatar
|
{data?.paidBy?.firstName} {data?.paidBy?.lastName}
|
||||||
size="xs"
|
|
||||||
classAvatar="m-0"
|
|
||||||
firstName={data.paidBy?.firstName}
|
|
||||||
lastName={data.paidBy?.lastName}
|
|
||||||
/>
|
|
||||||
<span className="text-muted">
|
|
||||||
{`${data.paidBy?.firstName ?? ""} ${
|
|
||||||
data.paidBy?.lastName ?? ""
|
|
||||||
}`.trim() || "N/A"}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -372,7 +363,7 @@ const ViewExpense = ({ ExpenseId }) => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<hr className="divider my-1 border-2 divider-primary my-2" />
|
<hr className="divider my-1 border-2 divider-primary my-2"/>
|
||||||
|
|
||||||
{Array.isArray(data?.nextStatus) && data.nextStatus.length > 0 && (
|
{Array.isArray(data?.nextStatus) && data.nextStatus.length > 0 && (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@ -30,8 +30,8 @@ const DatePicker = ({
|
|||||||
? flatpickr.parseDate(value, "Y-m-d")
|
? flatpickr.parseDate(value, "Y-m-d")
|
||||||
: null,
|
: null,
|
||||||
maxDate:maxDate,
|
maxDate:maxDate,
|
||||||
minDate:new Date(minDate?.split("T")[0]) ?? null,
|
minDate:new Date(minDate?.split("T")[0]) ?? undefined,
|
||||||
onChange: (selectedDates, dateStr) => {
|
onChange: function (selectedDates, dateStr) {
|
||||||
onChange(dateStr);
|
onChange(dateStr);
|
||||||
},
|
},
|
||||||
...rest
|
...rest
|
||||||
|
|||||||
@ -1,27 +1,20 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import showToast from '../services/toastService';
|
import showToast from '../services/toastService';
|
||||||
|
|
||||||
let hasShownLocationErrorToast = false; // global flag
|
|
||||||
|
|
||||||
export const usePositionTracker = () => {
|
export const usePositionTracker = () => {
|
||||||
const [coords, setCoords] = useState({ latitude: 0, longitude: 0 });
|
const [coords, setCoords] = useState({ latitude: 0, longitude: 0 });
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const locationID = navigator.geolocation.watchPosition(
|
const locationID = navigator.geolocation.watchPosition(
|
||||||
({ coords }) => {
|
({ coords }) => {
|
||||||
setCoords(coords);
|
setCoords(coords);
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
if (!hasShownLocationErrorToast) {
|
showToast("Please Allow Location","warn");
|
||||||
showToast("Please Allow Location", "warn");
|
},
|
||||||
hasShownLocationErrorToast = true;
|
{ enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 }
|
||||||
}
|
);
|
||||||
},
|
return () => navigator.geolocation.clearWatch(locationID);
|
||||||
{ enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 }
|
}, []);
|
||||||
);
|
return coords;
|
||||||
|
};
|
||||||
return () => navigator.geolocation.clearWatch(locationID);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return coords;
|
|
||||||
};
|
|
||||||
@ -27,7 +27,7 @@ const AttendancePage = () => {
|
|||||||
const [ShowPending, setShowPending] = useState(false);
|
const [ShowPending, setShowPending] = useState(false);
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const loginUser = getCachedProfileData();
|
const loginUser = getCachedProfileData();
|
||||||
const selectedProject = useSelector((store) => store.localVariables.projectId);
|
var selectedProject = useSelector((store) => store.localVariables.projectId);
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
const [attendances, setAttendances] = useState();
|
const [attendances, setAttendances] = useState();
|
||||||
@ -155,32 +155,28 @@ const AttendancePage = () => {
|
|||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div className="tab-content attedanceTabs py-0 px-1 px-sm-3">
|
<div className="tab-content attedanceTabs py-0 px-1 px-sm-3" >
|
||||||
{selectedProject ? (
|
{activeTab === "all" && (
|
||||||
<>
|
<div className="tab-pane fade show active py-0">
|
||||||
{activeTab === "all" && (
|
<Attendance
|
||||||
<div className="tab-pane fade show active py-0">
|
handleModalData={handleModalData}
|
||||||
<Attendance handleModalData={handleModalData} getRole={getRole} />
|
getRole={getRole}
|
||||||
</div>
|
/>
|
||||||
)}
|
</div>
|
||||||
{activeTab === "logs" && (
|
)}
|
||||||
<div className="tab-pane fade show active py-0">
|
{activeTab === "logs" && (
|
||||||
<AttendanceLog handleModalData={handleModalData} />
|
<div className="tab-pane fade show active py-0">
|
||||||
</div>
|
<AttendanceLog
|
||||||
)}
|
handleModalData={handleModalData}
|
||||||
{activeTab === "regularization" && DoRegularized && (
|
/>
|
||||||
<div className="tab-pane fade show active py-0">
|
</div>
|
||||||
<Regularization />
|
)}
|
||||||
</div>
|
{activeTab === "regularization" && DoRegularized && (
|
||||||
)}
|
<div className="tab-pane fade show active py-0">
|
||||||
</>
|
<Regularization />
|
||||||
) : (
|
</div>
|
||||||
<div className="py-2">
|
)}
|
||||||
<small className="py-2">Please Select Project!</small>
|
</div>
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user