From ea6d47b1a1fc89687d4317cc565440c5bda844f9 Mon Sep 17 00:00:00 2001 From: altaf-creator Date: Sun, 30 Nov 2025 19:11:28 +0700 Subject: finish timer --- backend/main.py | 7 +++++-- frontend/main.js | 23 +++++++++++++++++++++-- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/backend/main.py b/backend/main.py index 491ffb3..351d427 100644 --- a/backend/main.py +++ b/backend/main.py @@ -76,6 +76,7 @@ class RequestData(BaseModel): class BlockRequestData(BaseModel): block: int + class FinishRequestData(BaseModel): id: int @@ -125,7 +126,7 @@ def restart_terminated_schedules(): def reminder_timer_finished(timer_id): print("timer almost finished", timer_id) - end_date = datetime.datetime.now() + datetime.timedelta(seconds=5) + end_date = datetime.datetime.now() + datetime.timedelta(minutes=5) scheduler.add_job(final_timer_finished, 'date', run_date=end_date, id=str(timer_id), args=[timer_id]) notification = Notification(app_id=ONESIGNAL_APP_ID, included_segments=['All'], contents={'en':'get ready to get your bloody laundry'}, headings={'en':'laundry almost finished'}) @@ -278,7 +279,7 @@ def get_laundry_info(response: fastapi.Response, session_key: Annotated[str | No # --- finish one's laundry -@app.post("/finish") +@app.post("/finish", response_class=PlainTextResponse) def finish_laundry(data: FinishRequestData, response: fastapi.Response, session_key: Annotated[str | None, fastapi.Cookie()] = None): if session_key: cursor.execute(f"SELECT * FROM timers WHERE id = '{data.id}'") @@ -291,6 +292,8 @@ def finish_laundry(data: FinishRequestData, response: fastapi.Response, session_ cursor.execute(f"DELETE FROM timers WHERE timer_id = {row[0]}") conn.commit() + return "laundry finished" + if session_key != row[1]: response.status_code = fastapi.status.HTTP_401_UNAUTHORIZED return "session key mismatch with timer id, dubious and hence unauthorised." diff --git a/frontend/main.js b/frontend/main.js index 7ed3b9c..1e1c8f9 100644 --- a/frontend/main.js +++ b/frontend/main.js @@ -151,7 +151,7 @@ async function startLoadTimers() { for (let i = 0; i < timers.length; i++) { container.innerHTML += ` -
+

Timer #${(i + 1).toString()}

@@ -177,13 +177,15 @@ async function startLoadTimers() {
- +
` textList.push(`timer-txt-${i}`); progList.push(`timer-prog-${i}`); endTimestamps.push(Date.parse(timers[i]["start_time"]) + timers[i]["duration"] * 60000); + + document.getElementById(`timer-btn-${i}`).addEventListener("click", finishLaundryTimer, timers[i]["id"]); } console.log(textList); @@ -203,6 +205,11 @@ async function startLoadTimers() { const prog = document.getElementById(progList[i]); prog.style.width = ((timeRemaining / (timers[i]["duration"] * 60)) * 100).toString() + "%"; + + if (timeRemaining <= 0) { + alert(`timer ${i} finished`); + document.getElementById(`timer-btn-${i}`).disabled = false; + } } await delay(1000); } @@ -216,6 +223,18 @@ async function fetchTimers() { return [response.status, await response.json()]; } +// --- finish / collect timer / laundry +async function finishLaundryTimer(timerId) { + const response = await fetch(`${API_URL}/finish`, { + method: "POST", + credentials: "include", + body: JSON.stringify({id: timerId}), + }); + if (await response.text() == "laundry finished") { + document.getElementById(`timer-${timerId}`).remove(); + } +} + const delay = (durationMs) => { return new Promise(resolve => setTimeout(resolve, durationMs)); } -- cgit v1.2.3