diff --git a/src/components/Dashboard/Dashboard.jsx b/src/components/Dashboard/Dashboard.jsx
index ad5ead8c..e5ed7edc 100644
--- a/src/components/Dashboard/Dashboard.jsx
+++ b/src/components/Dashboard/Dashboard.jsx
@@ -17,12 +17,19 @@ import ExpenseAnalysis from "./ExpenseAnalysis";
import ExpenseStatus from "./ExpenseStatus";
import ExpenseByProject from "./ExpenseByProject";
import ProjectStatistics from "../Project/ProjectStatistics";
+import ServiceJobs from "./ServiceJobs";
+import { useHasUserPermission } from "../../hooks/useHasUserPermission";
+import { REGULARIZE_ATTENDANCE, SELF_ATTENDANCE, TEAM_ATTENDANCE } from "../../utils/constants";
const Dashboard = () => {
// Get the selected project ID from Redux store
const projectId = useSelector((store) => store.localVariables.projectId);
const isAllProjectsSelected = projectId === null;
+ const canRegularize = useHasUserPermission(REGULARIZE_ATTENDANCE);
+ const canTeamAttendance = useHasUserPermission(TEAM_ATTENDANCE);
+ const canSelfAttendance = useHasUserPermission(SELF_ATTENDANCE);
+
return (
@@ -49,7 +56,7 @@ const Dashboard = () => {
- {!isAllProjectsSelected && (
+ {!isAllProjectsSelected && (canRegularize || canTeamAttendance || canSelfAttendance) && (
@@ -57,7 +64,9 @@ const Dashboard = () => {
{!isAllProjectsSelected && (
)}
@@ -74,6 +83,9 @@ const Dashboard = () => {
+ {/*
+
+
*/}
);
diff --git a/src/components/Dashboard/ServiceJobs.jsx b/src/components/Dashboard/ServiceJobs.jsx
new file mode 100644
index 00000000..987addda
--- /dev/null
+++ b/src/components/Dashboard/ServiceJobs.jsx
@@ -0,0 +1,237 @@
+import React from "react";
+
+const ServiceJobs = () => {
+ return (
+
+
+
+
+
Service Jobs
+
All Projects
+
+
+
+
+
+
+ {/* Tabs */}
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ {/* Tab Content */}
+
+
+ {/* ---------------------- NEW TAB ---------------------- */}
+
+ {/* Entry 1 */}
+
+ -
+
+
+
+
+
+ Sender
+
+
Myrtle Ullrich
+
101 Boulder, California(CA), 95959
+
+
+ -
+
+
+
+
+
+ Receiver
+
+
Barry Schowalter
+
939 Orange, California(CA), 92118
+
+
+
+
+
+
+ {/* Entry 2 */}
+
+ -
+
+
+
+
+
+ Sender
+
+
Veronica Herman
+
162 Windsor, California(CA), 95492
+
+
+ -
+
+
+
+
+
+ Receiver
+
+
Helen Jacobs
+
487 Sunset, California(CA), 94043
+
+
+
+
+
+ {/* ---------------------- PREPARING TAB ---------------------- */}
+
+
+ {/* Entry 1 */}
+
+ -
+
+
+
+
+
+ Sender
+
+
Oliver Grant
+
220 Pine St, California(CA), 95765
+
+
+
+ -
+
+
+
+
+
+ Receiver
+
+
Samantha Lee
+
744 Bay Area, California(CA), 94016
+
+
+
+
+
+
+ {/* Entry 2 */}
+
+ -
+
+
+
+
+
+ Sender
+
+
Marcus Howard
+
58 Avenue, California(CA), 95376
+
+
+
+ -
+
+
+
+
+
+ Receiver
+
+
Daniel Foster
+
312 Marina, California(CA), 94109
+
+
+
+
+
+ {/* ---------------------- SHIPPING TAB ---------------------- */}
+
+
+ {/* Entry 1 */}
+
+ -
+
+
+
+
+
+ Sender
+
+
James Carter
+
441 Market St, California(CA), 94111
+
+
+
+ -
+
+
+
+
+
+ Receiver
+
+
Linda Moore
+
990 Willow Road, California(CA), 94025
+
+
+
+
+
+
+ {/* Entry 2 */}
+
+ -
+
+
+
+
+
+ Sender
+
+
Sarah Bennett
+
882 Canyon Rd, California(CA), 94704
+
+
+
+ -
+
+
+
+
+
+ Receiver
+
+
George Simmons
+
19 Palm St, California(CA), 93001
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default ServiceJobs;
diff --git a/src/components/Project/ProjectStatistics.jsx b/src/components/Project/ProjectStatistics.jsx
index 7ec5dbd3..ac7a8f2a 100644
--- a/src/components/Project/ProjectStatistics.jsx
+++ b/src/components/Project/ProjectStatistics.jsx
@@ -165,7 +165,7 @@ const ProjectStatistics = ({ project }) => {
}, [selectedProject]);
return (
-
+ <>
{" "}
@@ -242,8 +242,8 @@ const ProjectStatistics = ({ project }) => {
+ >
-
);
};
diff --git a/src/components/RecurringExpense/ManageRecurringExpense.jsx b/src/components/RecurringExpense/ManageRecurringExpense.jsx
index a399867d..2d29400a 100644
--- a/src/components/RecurringExpense/ManageRecurringExpense.jsx
+++ b/src/components/RecurringExpense/ManageRecurringExpense.jsx
@@ -252,16 +252,15 @@ const ManageRecurringExpense = ({ closeModal, requestToEdit = null }) => {
-
- Choose whether the payment amount varies or remains fixed
- each cycle.
-
- Is Variable: Amount changes per cycle.
-
- Fixed: Amount stays constant.
-
+
+ Choose whether the payment amount varies or remains fixed
+ each cycle.
+
+ Is Variable: Amount changes per cycle.
+
+ Fixed: Amount stays constant.
}
>
@@ -476,10 +475,10 @@ const ManageRecurringExpense = ({ closeModal, requestToEdit = null }) => {
title="Payment Buffer Days"
id="payment_buffer_days"
content={
-
+
Number of extra days allowed after the due date before
payment is considered late.
-
+
}
>
@@ -511,10 +510,11 @@ const ManageRecurringExpense = ({ closeModal, requestToEdit = null }) => {
+
The date when the last payment in the recurrence occurs.
-
+
}
>
@@ -592,8 +592,8 @@ const ManageRecurringExpense = ({ closeModal, requestToEdit = null }) => {
{createPending || isPending
? "Please wait...."
: requestToEdit
- ? "Update"
- : "Save as Draft"}
+ ? "Update"
+ : "Save as Draft"}
diff --git a/src/components/common/HoverPopup.jsx b/src/components/common/HoverPopup.jsx
index 1063745b..232ced5d 100644
--- a/src/components/common/HoverPopup.jsx
+++ b/src/components/common/HoverPopup.jsx
@@ -58,139 +58,66 @@ const HoverPopup = ({
return () => document.removeEventListener("click", handler);
}, [Mode, visible, dispatch, id]);
- // Positioning effect: respects align prop and stays inside boundary (drawer)
useEffect(() => {
if (!visible || !popupRef.current || !triggerRef.current) return;
- // run in next frame so DOM/layout settles
requestAnimationFrame(() => {
const popup = popupRef.current;
-
- // choose boundary: provided boundaryRef or nearest positioned parent (popup.parentElement)
- const boundaryEl =
- (boundaryRef && boundaryRef.current) || popup.parentElement;
+ const boundaryEl = (boundaryRef && boundaryRef.current) || popup.parentElement;
if (!boundaryEl) return;
const boundaryRect = boundaryEl.getBoundingClientRect();
const triggerRect = triggerRef.current.getBoundingClientRect();
-
- // reset styles first
popup.style.left = "";
popup.style.right = "";
popup.style.transform = "";
popup.style.top = "";
const popupRect = popup.getBoundingClientRect();
- const parentRect = boundaryRect; // alias
+ const triggerCenterX = triggerRect.left + triggerRect.width / 2 - boundaryRect.left;
+ let left = triggerCenterX - popupRect.width / 2;
- // Convert trigger center to parent coordinates
- const triggerCenterX =
- triggerRect.left + triggerRect.width / 2 - parentRect.left;
-
- // preferred left so popup center aligns to trigger center:
- const preferredLeft = triggerCenterX - popupRect.width / 2;
-
- // Helpers to set styles in parent's coordinate system:
- const setLeft = (leftPx) => {
- popup.style.left = `${leftPx}px`;
- popup.style.right = "auto";
- popup.style.transform = "none";
- };
- const setRight = (rightPx) => {
- popup.style.left = "auto";
- popup.style.right = `${rightPx}px`;
- popup.style.transform = "none";
- };
-
- // If user forced align:
- if (align === "left") {
- // align popup's left to parent's left (0)
- setLeft(0);
- return;
- }
- if (align === "right") {
- // align popup's right to parent's right (0)
- setRight(0);
- return;
- }
- if (align === "center") {
- popup.style.left = "50%";
- popup.style.right = "auto";
- popup.style.transform = "translateX(-50%)";
- return;
- }
-
- // align === "auto": try preferred centered position, but flip fully if overflow
- // clamp preferredLeft to boundaries so it doesn't render partially outside
- const leftIfCentered = Math.max(
- 0,
- Math.min(preferredLeft, parentRect.width - popupRect.width)
- );
-
- // if centered fits, use it
- if (leftIfCentered === preferredLeft) {
- setLeft(leftIfCentered);
- return;
- }
-
- // if centering would overflow right -> stick popup fully to left (left=0)
- if (preferredLeft > parentRect.width - popupRect.width) {
- // place popup so its right aligns to parent's right
- // i.e., left = parent width - popup width
- setLeft(parentRect.width - popupRect.width);
- return;
- }
-
- // if centering would overflow left -> stick popup fully to left=0
- if (preferredLeft < 0) {
- setLeft(0);
- return;
- }
-
- // fallback center
- setLeft(leftIfCentered);
+ // Clamp to boundaries
+ left = Math.max(0, Math.min(left, boundaryRect.width - popupRect.width));
+ popup.style.left = `${left}px`;
});
}, [visible, align, boundaryRef]);
- return (
-