{/* Sidebar */}
{/* Main Content */}
diff --git a/src/ui/pages/Dashboard.tsx b/src/ui/pages/Dashboard.tsx
index d90aacd..0c9d455 100644
--- a/src/ui/pages/Dashboard.tsx
+++ b/src/ui/pages/Dashboard.tsx
@@ -2,6 +2,10 @@ import React, { useEffect, useRef, useState } from "react";
import { Clock, TrendingUp, Play, Square, ProjectorIcon, Pause } from "lucide-react";
import { useOutletContext } from "react-router-dom";
import NoData from "./NoData";
+import { useDispatch, useSelector } from "react-redux";
+import { initializeProjectTracking, setProjectsDataSlice, setProjectSummarySlice, setSelectedProjectSlice, updateProjectTracking } from "../store/projectSlice";
+import { setError, setLoading, setProfile } from "../store/profileSlice";
+import { getFormattedRemainingTime, isProjectLimitReached } from '../utils/projectLimits';
// Updated Project interface to match JSON structure
interface Project {
@@ -11,6 +15,7 @@ interface Project {
totalWorkTime: string;
totalWorkMs: number;
totalLogs: number;
+ status: string
}
interface ProjectTrackingData {
@@ -23,7 +28,7 @@ interface ProjectTrackingData {
interface TrackingState {
selectedProject: Project | null;
- projectTrackingMap: Map
;
+ // projectTrackingMap: Map;
isTracking: boolean;
isPaused: boolean;
elapsedTime: number;
@@ -34,6 +39,8 @@ interface TrackingState {
handleStopTracking: () => void;
handleProjectSelect: (projectId: string) => void;
projectsData: Project[];
+ loadingStart: boolean,
+ loadingStop: boolean
}
// Helper function
@@ -41,8 +48,8 @@ const formatTime = (seconds: number) => {
const hrs = Math.floor(seconds / 3600);
const mins = Math.floor((seconds % 3600) / 60);
const secs = seconds % 60;
- // return `${hrs}h ${mins}m ${secs}s`;
- return `${hrs}h ${mins}m `;
+ return `${hrs}h ${mins}m ${secs}s`;
+ // return `${hrs}h ${mins}m `;
};
// Widget Component
@@ -79,8 +86,8 @@ const Widget: React.FC<{
// Dashboard Component
const Dashboard: React.FC = () => {
const {
- selectedProject,
- projectTrackingMap,
+ // selectedProject,
+ // projectTrackingMap,
isTracking,
isPaused,
elapsedTime,
@@ -89,7 +96,9 @@ const Dashboard: React.FC = () => {
handlePauseResume,
handleStopTracking,
handleProjectSelect,
- projectsData,
+ // projectsData,
+ loadingStart,
+ loadingStop
} = useOutletContext();
// interface AppsListInt {
@@ -100,10 +109,112 @@ const Dashboard: React.FC = () => {
// const [runningApps, setRunningApps] = useState([]);
+ const projectsData = useSelector((state: any) => state.projects.projectsData);
+ const selectedProject = useSelector((state: any) => state.projects.selectedProject);
+ const projectSummary = useSelector((state: any) => state.projects.projectSummary);
+ const projectTrackingMap = useSelector((state: any) => state.projects.projectTrackingMap);
+
+
+ console.log("Line 111", projectsData, selectedProject, projectTrackingMap)
+
+
+ const dispatch = useDispatch();
+
+
+ const fetchProfile = async () => {
+ try {
+ dispatch(setLoading(true));
+ const res = await window.electron.getProfile();
+ console.log("Profile", res)
+ if (res.success && res.data) {
+ dispatch(setProfile(res.data));
+ } else {
+ dispatch(setError("Failed to fetch profile"));
+ }
+ } catch (err: any) {
+ dispatch(setError(err.message));
+ } finally {
+ dispatch(setLoading(false));
+ }
+ };
+
+ useEffect(() => {
+ const fetchProjects = async () => {
+ try {
+ console.log("π‘ Fetching projects...Dashboard");
+ const res = await window.electron.getProjectList();
+ console.log(" Project list response in dashboard:", res);
+
+ if (res?.success && Array.isArray(res.data)) {
+ // Store project list
+ // setProjectsData(res.data);
+
+ // Store project summary info
+ // setProjectSummary({
+ // totalProjects: res.totalProjects || 0,
+ // activeProjects: res.activeProjects || 0,
+ // awayProjects: res.awayProjects || 0,
+ // totalWorkTime: res.totalWorkTime || "0h 0m 0s",
+ // totalWorkMs: res.totalWorkMs || 0,
+ // vaName: res.vaName || "",
+ // vaId: res.vaId || "",
+ // });
+
+ // Store data redux store
+ dispatch(setProjectsDataSlice(res.data));
+
+ dispatch(
+ setProjectSummarySlice({
+ totalProjects: res.totalProjects || 0,
+ activeProjects: res.activeProjects || 0,
+ awayProjects: res.awayProjects || 0,
+ totalWorkTime: res.totalWorkTime || "0h 0m 0s",
+ totalWorkMs: res.totalWorkMs || 0,
+ vaName: res.vaName || "",
+ vaId: res.vaId || "",
+ })
+ );
+
+ // Auto-select first project
+ if (res.data.length > 0 && !selectedProject) {
+ const firstProject = res.data[0];
+
+ // Select the project
+ dispatch(setSelectedProjectSlice(firstProject));
+
+ // Convert total work ms β seconds
+ const initialElapsed = Math.floor((firstProject.totalWorkMs || 0) / 1000);
+
+ // Initialize tracking data for first project (your slice matches this)
+ dispatch(
+ initializeProjectTracking({
+ projectId: firstProject.projectId,
+ initialTime: initialElapsed,
+ })
+ );
+ }
+
+ fetchProfile()
+
+ } else {
+ console.warn("β οΈ Unexpected response:", res);
+ // if (res?.status) {
+ // // handleLogout()
+ // }
+ }
+ } catch (err) {
+ console.error("β Error fetching projects:", err);
+ }
+ };
+
+ fetchProjects();
+ }, []);
+
const selectedData = selectedProject
- ? projectTrackingMap.get(selectedProject.projectId)
+ ? projectTrackingMap[selectedProject.projectId]
: null;
+
const formatWorkTime = (time: string) => {
if (!time) return "0h 0m";
@@ -115,49 +226,40 @@ const Dashboard: React.FC = () => {
};
+ const handleProjectSelectLocal = (projectId: string) => {
+
+ const project = projectsData.find((p: any) => p.projectId === projectId);
+ if (!project) return;
+
+ dispatch(setSelectedProjectSlice(project));
+
+ const existingData = projectTrackingMap[projectId];
+
+ if (!existingData) {
+ const initialElapsed = Math.floor((project.totalWorkMs || 0) / 1000);
+
+ dispatch(initializeProjectTracking({
+ projectId,
+ initialTime: initialElapsed
+ }));
+ } else {
+ // Restore saved tracking state
+ dispatch(updateProjectTracking({
+ projectId,
+ data: existingData
+ }));
+ }
+ };
+
+
return (
{/* Header */}
Dashboard
- {/* */}
-
- {/* Widgets */}
- {/*
- }
- color="primary"
- />
- }
- color="success"
- />
- }
- color="warning"
- />
-
*/}
-
{/* Tracking Section */}
- {/*
- Tracking
-
*/}
-
{selectedProject ? (
@@ -183,60 +285,33 @@ const Dashboard: React.FC = () => {
) : (
)}
+
-
- {/*
-
- Status:{" "}
-
- {selectedProject.activityStatus}
-
-
-
- Tracking:{" "}
-
- {selectedData?.isPaused
- ? "Paused"
- : selectedData?.isTracking
- ? "Active"
- : "Ready"}
-
-
-
- Start:{" "}
-
- {selectedData?.startTime
- ? selectedData.startTime.toLocaleTimeString()
- : "β"}
-
-
-
*/}
>
) : (
@@ -257,7 +332,7 @@ const Dashboard: React.FC = () => {
{/* πΉ Table or Empty State */}
{projectsData.length > 0 ? (
{
| # |
Name |
- {/* Logs Hours | */}
+ Logs Hours |
Action |
- {projectsData.map((project, index) => {
+ {projectsData.map((project: any, index: any) => {
const isCurrentlySelected =
selectedProject?.projectId === project.projectId;
const isDisabled = isTracking && !isCurrentlySelected;
+ const limitReached = isProjectLimitReached(project);
+ const remainingTime = getFormattedRemainingTime(project);
return (
-
+
| {index + 1} |
- {project.projectName} |
- {/*
- {formatWorkTime(project.totalWorkTime)}
- | */}
+
+ {project.projectName}
+ {limitReached && (
+ Daily limit reached
+ )}
+ |
+
+
+
+ {formatWorkTime(project.totalWorkTime)}
+
+ {/*
+ of {project.dedicatedHours}
+ */}
+
+ |
-
+
+
+ {/* {!limitReached && (
+
+ {remainingTime} left
+
+ )} */}
+
|
);
diff --git a/src/ui/pages/LeaveAndAdjustments/LeaveAndAdjustments.tsx b/src/ui/pages/LeaveAndAdjustments/LeaveAndAdjustments.tsx
index a342136..6bf360f 100644
--- a/src/ui/pages/LeaveAndAdjustments/LeaveAndAdjustments.tsx
+++ b/src/ui/pages/LeaveAndAdjustments/LeaveAndAdjustments.tsx
@@ -535,7 +535,7 @@ const LeaveAndAdjustments: React.FC = () => {
{/* Header */}
-
Adjust Timesheet
+ Leave & Adjust Timesheet
{/* General Error Alert */}
@@ -545,6 +545,9 @@ const LeaveAndAdjustments: React.FC = () => {
)}
+
+
+
{/* Main Container */}
{/* Tabs Navigation */}
diff --git a/src/ui/pages/Login.tsx b/src/ui/pages/Login.tsx
index 3f0f16f..138c08f 100644
--- a/src/ui/pages/Login.tsx
+++ b/src/ui/pages/Login.tsx
@@ -5,6 +5,7 @@ import { setUserSlice } from '../store/userSlice';
import DocVaLogoLight from '../../assets/logo-colored-vertical.svg'
import DocVaLogoDark from '../../assets/logo-white-vertical.svg'
import { ThemeToggle } from '../helper/ThemeToggle';
+import { KeyRound, Mail } from 'lucide-react';
const Login = () => {
const theme = ThemeToggle();
@@ -41,7 +42,8 @@ const Login = () => {
email: response.user.email,
}));
navigate("/")
- } else if (response.success == false) {
+ }
+ else if (response.success == false) {
console.log(response.error.message)
setErrorMessage(response.error.message)
}
@@ -112,15 +114,8 @@ const Login = () => {
-