Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 57 additions & 22 deletions src/components/BMDashboard/BMTimeLogger/BMTimeLogCard.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
background-color: #2e5061;
}

@media (width >= 650px) {
@media (width >=650px) {
.bmDashboard_button.btn.btnSecondary {
padding-left: 0;
padding-right: 0;
Expand Down Expand Up @@ -47,10 +47,9 @@
}

.memberStopwatch {
background-color: #4b5055 !important;
background-color: #3f444a !important;
border-radius: 15px !important;
height: 3rem;
font-size: 1.5rem !important;
font-size: 1.7rem !important;
text-align: center;
color: white;
white-space: nowrap;
Expand All @@ -59,33 +58,25 @@
display: inline-block;
}

.fontColorGray {
.fontColorGray {
color: #4b5055;
}

.memberStart {
background-color: #01987a !important;
border-radius: 10px !important;
width: 5rem;
background-color: #01987a !important;
}

.memberPause {
background-color: #168dc0 !important;
border-radius: 10px !important;
width: 5rem;
background-color: #168dc0 !important;
}


.memberStop {
background-color: #980101 !important;
border-radius: 10px !important;
width: 5rem;
background-color: #980101 !important;
}

.memberClear {
background-color: #a9b7be !important;
border-radius: 10px !important;
width: 5rem;
background-color: #a9b7be !important;
}

/* project summaries */
Expand All @@ -94,7 +85,7 @@
list-style-type: none;
max-height: 80vh;
overflow: hidden auto;
padding:0;
padding: 0;
}

.projectSummary {
Expand Down Expand Up @@ -197,19 +188,63 @@
color: red;
}

@media screen and (width <= 800px) {
@media screen and (width <=800px) {
.invFormPageContainer {
width: 95%;
}
}

@media screen and (width <= 480px) {
@media screen and (width <=480px) {
.invFormPageContainer h2 {
font-size: 1.7rem;
}
}

.formFooter {
font-size: 0.875em;
margin-top:3px;
font-size: 0.875em;
margin-top: 3px;
}

.memberStart,
.memberStop,
.memberClear,
.memberPause {
min-width: 110px;
font-weight: 500 !important;
border-radius: 10px !important;
}

:global(body.dark-mode:not(.no-global-theme)) .stopwatchContainer,
:global(body.bm-dashboard-dark:not(.no-global-theme)) .stopwatchContainer {
background: none;
}

:global(.dark-mode) .stopwatchContainer :global(.btn.btn-secondary).memberStart {
background-color: #01987a !important;
border-color: #01987a !important;
}


:global(.dark-mode) .stopwatchContainer :global(.btn.btn-secondary).memberStop,
:global(.dark-mode) .stopwatchContainer :global(.btn.btn-secondary).memberStop:hover {
background-color: #980101 !important;
border-color: #980101 !important;
}

:global(.dark-mode) .stopwatchContainer :global(.btn.btn-secondary).memberStopwatch,
:global(.dark-mode) .stopwatchContainer :global(.btn.btn-secondary).memberStopwatch:hover {
background: none !important
}

:global(.dark-mode) .fontColorGray {
color: #fff;
}

:global(.dark-mode) .stopwatchContainer :global(.btn.btn-secondary).memberClear,
:global(.dark-mode) .stopwatchContainer :global(.btn.btn-secondary).memberClear:hover {
background-color: #a9b7be !important;
}

:global(.btn:disabled) {
cursor: not-allowed;
}
108 changes: 85 additions & 23 deletions src/components/BMDashboard/BMTimeLogger/BMTimeLogStopWatch.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,14 @@
const [currentTime, setCurrentTime] = useState('');
const [startButtonText, setStartButtonText] = useState('START');
const [isStarted, setIsStarted] = useState(false);
const [feedbackMessage, setFeedbackMessage] = useState('');
const [enableStop, setEnableStop] = useState(true);
const intervalRef = useRef(null);
const isStartingNewLogRef = useRef(false);
const justPausedTimeRef = useRef(null);
const resumingFromTimeRef = useRef(null);
const justStoppedTimeRef = useRef(null);
const isTimerRunning = currentTimeLog?.status === 'ongoing';

const formatTime = useCallback(totalSeconds => {
const hrs = Math.floor(totalSeconds / 3600);
Expand Down Expand Up @@ -186,6 +189,7 @@

// Start/Pause Handler
const startStop = () => {
setEnableStop(false);
if (!currentTime) {
setCurrentTime(moment().format('hh:mm:ss A'));
}
Expand All @@ -197,13 +201,18 @@
dispatch(pauseTimeLog(projectId, currentTimeLog._id, memberId))
.then(() => {
// UI will be updated by the sync useEffect when the paused log comes back
setFeedbackMessage('Timer paused successfully');
setTimeout(() => {
setFeedbackMessage('');
}, 3000);
})
.catch(() => {
// On error, ensure UI still shows the correct time
justPausedTimeRef.current = null;
setTime(currentElapsedTime);
setStartButtonText('START');
setIsStarted(false);
setFeedbackMessage('Failed to pause timer');
});
} else {
// Start or resume time log
Expand All @@ -222,13 +231,19 @@
setCurrentTime(moment().format('hh:mm:ss A'));
dispatch(startTimeLog(projectId, memberId, 'Default Task'));
}
setFeedbackMessage('Timer started');

setTimeout(() => {
setFeedbackMessage('');
}, 3000);
setStartButtonText('PAUSE');
setIsStarted(true);
}
};

// Stop Handler
const stop = () => {
setEnableStop(true);
if (currentTimeLog) {
// Store the current time before stopping so it remains visible
const finalTime = time;
Expand All @@ -242,61 +257,108 @@
// Don't clear currentTime - keep the start time visible

// Then dispatch the stop action
dispatch(stopTimeLog(projectId, currentTimeLog._id, memberId)).catch(() => {
// On error, still show the time
justStoppedTimeRef.current = null;
setTime(finalTime);
});
dispatch(stopTimeLog(projectId, currentTimeLog._id, memberId))
.then(() => {
setFeedbackMessage('Time logged successfully');

setTimeout(() => {
setFeedbackMessage('');
}, 3000);
})
.catch(() => {
// On error, still show the time
justStoppedTimeRef.current = null;
setTime(finalTime);
setFeedbackMessage('Failed to stop timer');
});
} else {
// No active log, just reset
setTime(0);
setCurrentTime('');
setStartButtonText('START');
setIsStarted(false);
initialElapsedTimeRef.current = 0;
clear();
}
};

// Clear Handler
const clear = () => {
stop();
setTime(0);
setCurrentTime('');
setStartButtonText('START');
setIsStarted(false);
setEnableStop(true);
initialElapsedTimeRef.current = 0;
//stop();

Check warning on line 288 in src/components/BMDashboard/BMTimeLogger/BMTimeLogStopWatch.jsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this commented out code.

See more on https://sonarcloud.io/project/issues?id=OneCommunityGlobal_HighestGoodNetworkApp&issues=AZ6L4skQjzFPwmpx3NFa&open=AZ6L4skQjzFPwmpx3NFa&pullRequest=5319
setFeedbackMessage('Timer cleared');
setTimeout(() => {
setFeedbackMessage('');
}, 3000);
};

const { hr, min, sec } = formatTime(time);
console.log('Current Time', currentTimeLog);

return (
<CardBody style={{ width: '100%' }}>
<Container className={`${styles.stopwatchContainer}`}>
<Row className="justify-content-center">
{feedbackMessage && (
<Row className="justify-content-center gap-2 mb-3">
<span className="text-info fw-semibold">{feedbackMessage}</span>
</Row>
)}
<Row className="justify-content-center align-items-center">
<Col xs="auto">
<span
className={isTimerRunning ? 'text-success fw-semibold' : 'text-secondary fw-semibold'}
>
● {isTimerRunning ? 'Running' : 'Stopped'}
</span>
</Col>

<Col xs="auto">
<Button className={`${styles.memberStopwatch} mb-2 px-3`}>
<Button
className={`${styles.memberStopwatch} px-4 align-items-center justify-content-center`}
>
{hr.toString().padStart(2, '0')}:{min.toString().padStart(2, '0')}:
{sec.toString().padStart(2, '0')}
</Button>
</Col>
</Row>

<Row className="justify-content-between mb-2">
<Button className={isStarted ? 'member-pause' : 'member-start mb-1'} onClick={startStop}>
<b>{startButtonText}</b>
</Button>

<Button className={`${styles.memberStop}`} onClick={stop}>
<b>STOP</b>
</Button>
<Row className="justify-content-center gap-3">
<Col>
<Button
className={`px-0 ${isStarted ? styles.memberPause : styles.memberStart}`}
onClick={startStop}
>
<b>{startButtonText}</b>
</Button>
</Col>
<Col>
<Button className={`${styles.memberStop} px-0`} onClick={stop} disabled={enableStop}>
<b>STOP</b>
</Button>
</Col>
</Row>
<Row className="justify-content-center mb-1">
<Row className="justify-content-center align-items-center m-2">
Start at:
<Col>
<b className={`${styles.fontColorGray}`}>{currentTime}</b>
</Col>
</Row>
{/* <Row className="mb-2">Task: </Row> */}
<Row className="justify-content-center">
<Button className={`${styles.memberClear}`} onClick={clear}>
<Button
className={`${styles.memberClear} px-2 py-2`}
onClick={clear}
disabled={isStarted}
>
<b>CLEAR</b>
</Button>
</Row>

<Row className="mt-3 text-center">
<small className="text-muted">
Start begins time tracking. Stop saves the session. Clear resets the timer display.
</small>
</Row>
</Container>
</CardBody>
);
Expand Down
Loading