Skip to content

Commit

Permalink
Merge pull request #9 from rushlow-development/feature/time-tracking
Browse files Browse the repository at this point in the history
add ability to run timers
  • Loading branch information
jrushlow committed Mar 19, 2024
2 parents 6bf6c6d + a2191c7 commit 27b1531
Show file tree
Hide file tree
Showing 24 changed files with 1,261 additions and 333 deletions.
151 changes: 151 additions & 0 deletions assets/controllers/timer_controller.js
@@ -0,0 +1,151 @@
import { Controller } from '@hotwired/stimulus';
import { useDebounce } from 'stimulus-use';
import axios from 'axios';
import { DateTime, Duration } from 'luxon';

/* stimulusFetch: 'lazy */
export default class extends Controller {
#intervalId;
#startIcon;
#stopIcon;

static debounces = ['runTimer', 'startTimer', 'stopTimer']

static values = {
timerId: String,
timerRunning: Boolean,
timerStartTime: Number,
timerAccumulatedTime: Number,
}

static targets = [
'timerDurationCounter',
'timerStartButton',
'timerStopButton',
]

connect() {
useDebounce(this);

this.setButtonVisibility();
this.#startIcon = this.timerStartButtonTarget.innerHTML;
this.#stopIcon = this.timerStopButtonTarget.innerHTML;

if (this.timerRunningValue) {
this.initTimer();
}
}

setButtonVisibility() {
if (this.timerRunningValue) {
this.timerStartButtonTarget.classList.toggle('hidden', true);
this.timerStopButtonTarget.classList.toggle('hidden', false);

return;
}

this.timerStartButtonTarget.classList.toggle('hidden', false);
this.timerStopButtonTarget.classList.toggle('hidden', true);
}

// Called when page is first loaded to start any timers that are already running.
initTimer() {
let startedAt = DateTime.fromSeconds(this.timerStartTimeValue);

// Negate the diff, otherwise we'll get a negative int.
let diff = startedAt.diffNow(['seconds']).negate();

this.runTimer(diff);
}

// Called when starting a timer AFTER the initial page load
runTimer(diff) {
// let totalTime = Duration.fromObject({seconds: this.timerAccumulatedTimeValue});
let totalTime = diff.plus({seconds: this.timerAccumulatedTimeValue});

this.#intervalId = setInterval(() => {
totalTime = totalTime.plus({seconds: 1});

this.timerDurationCounterTarget.innerHTML = totalTime.toFormat('h:mm:ss');
}, 1000);
}

startTimer() {
this.timerStartButtonTarget.innerHTML = '~';

this.restartTimer();

let diff = Duration.fromObject({seconds: 0})

this.runTimer(diff);
}

stopTimer() {
this.timerStopButtonTarget.innerHTML = '~';

clearInterval(this.#intervalId);

this.timerRunningValue = false;

this.persistTimer();
}

async restartTimer() {
let response = await axios
.post(`/timer/start/${this.timerIdValue}`)
.then((response) => {
return response.data;
})
.catch(function (error) {
console.log(error);

return false;
})
;

if (response === false) {
// @todo do something
this.timerStartButtonTarget.innerHTML = 'Oops';

clearInterval(this.#intervalId);

return;
}

this.timerAccumulatedTimeValue = response.accumulatedSeconds;
this.timerStartTimeValue = response.restartedAt;

this.timerStartButtonTarget.classList.toggle('hidden', true);
this.timerStopButtonTarget.classList.toggle('hidden', false);
this.timerStartButtonTarget.innerHTML = this.#startIcon;
}

async persistTimer() {
let response = await axios
.post(`/timer/pause/${this.timerIdValue}`)
.then((response) => {
return response.data.accumulatedSeconds;
})
.catch(function (error) {
console.log(error);

return false;
})
;

if (response === false) {
// @todo do something
this.timerStopButtonTarget.innerHTML = 'Oops';

this.runTimer();

return;
}

this.timerAccumulatedTimeValue = response;

this.timerStartButtonTarget.classList.toggle('hidden', false);
this.timerStopButtonTarget.classList.toggle('hidden', true);
this.timerStopButtonTarget.innerHTML = this.#stopIcon;
}
}
44 changes: 44 additions & 0 deletions assets/controllers/timer_dashboard_controller.js
@@ -0,0 +1,44 @@
import { Controller } from '@hotwired/stimulus';
import axios from 'axios';

/* stimulusFetch: 'lazy */
export default class extends Controller {
static values = {
// todoListId: String,
}

static targets = [
'timerList',
]

async startTimer() {
let response = await axios
.post('/timer/create')
.then((response) => {
if (response.status !== 200) {
// @TODO Show an alert of something...

return false;
}

return response.data;
})
;

if (response === false) {
// @TODO Show an alert of something...

console.log('Ooops, something went wrong....');

return;
}

// console.log(response.html.content);

const div = document.createElement('div');
div.classList.add('row');
div.innerHTML = response.html.content;

this.timerListTarget.prepend(div);
}
}
4 changes: 4 additions & 0 deletions assets/styles/app.css
@@ -1,2 +1,6 @@
:root {
}

.hidden {
display: none;
}
2 changes: 2 additions & 0 deletions composer.json
Expand Up @@ -14,6 +14,7 @@
"doctrine/doctrine-migrations-bundle": "^3.3",
"doctrine/orm": "^3.0",
"league/commonmark": "^2.4",
"nesbot/carbon": "^3.1",
"phpdocumentor/reflection-docblock": "^5.3",
"phpstan/phpdoc-parser": "^1.25",
"rushlow-development/serialize-type-bundle": "dev-main",
Expand Down Expand Up @@ -44,6 +45,7 @@
"symfony/twig-bundle": "7.0.*",
"symfony/uid": "7.0.*",
"symfony/ux-turbo": "^2.14",
"symfony/ux-twig-component": "^2.16",
"symfony/validator": "7.0.*",
"symfony/web-link": "7.0.*",
"symfony/yaml": "7.0.*",
Expand Down

0 comments on commit 27b1531

Please sign in to comment.