Save timer variables on database

This commit is contained in:
Santiago Lo Coco 2024-05-18 16:32:22 +02:00
parent 204f2d89d7
commit c51ad6a41e
6 changed files with 230 additions and 88 deletions

View File

@ -1,22 +1,38 @@
generator client {
provider = "prisma-client-js"
binaryTargets = ["native", "rhel-openssl-1.0.x"]
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
username String @unique
passwordHash String
userAuthToken String @unique
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("user")
}
generator client {
provider = "prisma-client-js"
binaryTargets = ["native", "rhel-openssl-1.0.x"]
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
username String @unique
passwordHash String
userAuthToken String @unique
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
Timer Timer?
@@map("user")
}
model Timer {
id Int @id @default(autoincrement())
user_id Int @unique
breakInterval Int @default(20)
miniBreakDuration Int @default(20)
longBreakDuration Int @default(5)
soundEnabled Boolean @default(true)
notificationsEnabled Boolean @default(true)
user User @relation(references: [id], fields: [user_id], onDelete: Cascade)
@@index([user_id])
@@map("Timer")
}

View File

@ -10,12 +10,13 @@ export const handle: Handle = async ({ event, resolve }) => {
const user = await db.user.findUnique({
where: { userAuthToken: session },
select: { username: true },
select: { username: true, id: true },
})
if (user) {
event.locals.user = {
name: user.username,
id: user.id,
}
}

View File

@ -1,5 +1,6 @@
export type User = {
username: string
id: number
}
export const themes = ["light", "dark"] as const

13
src/lib/server/timer.ts Normal file
View File

@ -0,0 +1,13 @@
export const updateTimer = async ({ user, breakInterval, miniBreakDuration, longBreakDuration, soundEnabled, notificationsEnabled }) => {
await db.timer.update({
where: { user_id: user.id },
data: {
breakInterval,
miniBreakDuration,
longBreakDuration,
soundEnabled,
notificationsEnabled,
},
})
}

View File

@ -0,0 +1,52 @@
import { redirect, type ServerLoadEvent } from "@sveltejs/kit"
import type { PageServerLoad } from "./$types"
import { db } from "$lib/server/database"
import type { User } from "$lib/index"
export const load: PageServerLoad = async (event) => {
if (!event.locals.user) {
return
}
let timer = await fetchTimer(event.locals.user)
return { timer }
}
async function fetchTimer(user: User) {
let timer = await db.timer.findUnique({ where: { user_id: user.id } })
if (!timer) {
await db.timer.create({
data: {
user_id: user.id,
},
})
}
return await db.timer.findUnique({ where: { user_id: user.id } })
}
export const actions = {
updateTimer: async ({ request, locals }) => {
const user = locals.user
const data = await request.formData()
console.log(data)
const breakInterval = parseInt(data.get("break-interval"))
const miniBreakDuration = parseInt(data.get("mini-break-duration"))
const longBreakDuration = parseInt(data.get("long-break-duration"))
const soundEnabled = data.get("sound-enabled") === "true"
const notificationsEnabled = data.get("notifications-enabled") === "true"
await db.timer.update({
where: { user_id: user.id },
data: {
breakInterval,
miniBreakDuration,
longBreakDuration,
soundEnabled,
notificationsEnabled,
},
})
}
}

View File

@ -1,24 +1,41 @@
<script lang="ts">
import { onDestroy, onMount } from "svelte"
import { browser } from "$app/environment"
import { enhance } from "$app/forms"
let BREAK_INTERVAL_STORE = $state(
browser ? localStorage.getItem("breakInterval") || 20 : 20
)
let MINI_BREAK_DURATION_STORE = $state(
browser ? localStorage.getItem("miniBreakDuration") || 20 : 20
)
let LONG_BREAK_DURATION_STORE = $state(
browser ? localStorage.getItem("longBreakDuration") || 5 : 5
)
let SOUND_ENABLED = $state(
browser ? (localStorage.getItem("soundEnabled") || "true") === "true" : true
)
let NOTIFICATIONS_ENABLED = $state(
browser
? (localStorage.getItem("notificationsEnabled") || "true") === "true"
: true
)
let { data } = $props()
let BREAK_INTERVAL_STORE: any = $state(20)
let MINI_BREAK_DURATION_STORE: any = $state(20)
let LONG_BREAK_DURATION_STORE: any = $state(5)
let SOUND_ENABLED: any = $state(true)
let NOTIFICATIONS_ENABLED: any = $state(true)
$effect(() => {
if (!data.user || !data.timer) {
BREAK_INTERVAL_STORE = browser
? localStorage.getItem("breakInterval") || 20
: 20
MINI_BREAK_DURATION_STORE = browser
? localStorage.getItem("miniBreakDuration") || 20
: 20
LONG_BREAK_DURATION_STORE = browser
? localStorage.getItem("longBreakDuration") || 5
: 5
SOUND_ENABLED = browser
? (localStorage.getItem("soundEnabled") || "true") === "true"
: true
NOTIFICATIONS_ENABLED = browser
? (localStorage.getItem("notificationsEnabled") || "true") === "true"
: true
} else {
BREAK_INTERVAL_STORE = data.timer.breakInterval
MINI_BREAK_DURATION_STORE = data.timer.miniBreakDuration
LONG_BREAK_DURATION_STORE = data.timer.longBreakDuration
SOUND_ENABLED = data.timer.soundEnabled
NOTIFICATIONS_ENABLED = data.timer.notificationsEnabled
}
})
let BREAK_INTERVAL: number
let MINI_BREAK_DURATION: number
@ -30,29 +47,53 @@
let timeLeftDisplay = $state("")
let timeLeft = $state(0)
const updateTimer = () => {
if (!data.user) {
return
}
const formData = new FormData()
formData.append("user", data.user)
formData.append("break-interval", BREAK_INTERVAL_STORE)
formData.append("mini-break-duration", MINI_BREAK_DURATION_STORE)
formData.append("long-break-duration", LONG_BREAK_DURATION_STORE)
formData.append("sound-enabled", SOUND_ENABLED)
formData.append("notifications-enabled", NOTIFICATIONS_ENABLED)
fetch("?/updateTimer", {
method: "POST",
body: formData,
})
}
$effect(() => {
BREAK_INTERVAL = BREAK_INTERVAL_STORE * 60 * 1000
timeLeft = BREAK_INTERVAL
timeLeftDisplay = formatTime(BREAK_INTERVAL)
localStorage.setItem("breakInterval", BREAK_INTERVAL_STORE)
updateTimer()
})
$effect(() => {
console.log(MINI_BREAK_DURATION_STORE)
MINI_BREAK_DURATION = MINI_BREAK_DURATION_STORE * 1000
localStorage.setItem("miniBreakDuration", MINI_BREAK_DURATION_STORE)
updateTimer()
})
$effect(() => {
LONG_BREAK_DURATION = LONG_BREAK_DURATION_STORE * 60 * 1000
localStorage.setItem("longBreakDuration", LONG_BREAK_DURATION_STORE)
updateTimer()
})
$effect(() => {
localStorage.setItem("soundEnabled", SOUND_ENABLED)
updateTimer()
})
$effect(() => {
localStorage.setItem("notificationsEnabled", NOTIFICATIONS_ENABLED)
updateTimer()
})
let miniBreakCount = 0
@ -159,58 +200,76 @@
{:else}
<div class="container">
<div class="settings">
<div class="setting">
<label for="break-interval"
>Break interval: {BREAK_INTERVAL_STORE} minutes</label
>
<input
type="range"
min="1"
max="60"
step="1"
bind:value={BREAK_INTERVAL_STORE}
/>
</div>
<form method="POST" action="?/updateTimer" use:enhance>
<div class="setting">
<label for="break-interval"
>Break interval: {BREAK_INTERVAL_STORE} minutes</label
>
<input
type="range"
id="break-interval"
name="break-interval"
min="1"
max="60"
step="1"
bind:value={BREAK_INTERVAL_STORE}
/>
</div>
<div class="setting">
<label for="mini-break-duration"
>Mini break duration: {MINI_BREAK_DURATION_STORE} seconds</label
>
<input
type="range"
min="5"
max="60"
step="1"
bind:value={MINI_BREAK_DURATION_STORE}
/>
</div>
<div class="setting">
<label for="mini-break-duration"
>Mini break duration: {MINI_BREAK_DURATION_STORE} seconds</label
>
<input
id="mini-break-duration"
name="mini-break-duration"
type="range"
min="5"
max="60"
step="1"
bind:value={MINI_BREAK_DURATION_STORE}
/>
</div>
<div class="setting">
<label for="long-break-duration"
>Long break duration: {LONG_BREAK_DURATION_STORE} minutes</label
>
<input
type="range"
min="1"
max="30"
step="1"
bind:value={LONG_BREAK_DURATION_STORE}
/>
</div>
<div class="setting">
<label for="long-break-duration"
>Long break duration: {LONG_BREAK_DURATION_STORE} minutes</label
>
<input
id="long-break-duration"
name="long-break-duration"
type="range"
min="1"
max="30"
step="1"
bind:value={LONG_BREAK_DURATION_STORE}
/>
</div>
<div class="setting">
<label>
<input type="checkbox" bind:checked={SOUND_ENABLED} />
Sound
</label>
</div>
<div class="setting">
<label>
<input
id="sound-enabled"
name="sound-enabled"
type="checkbox"
bind:checked={SOUND_ENABLED}
/>
Sound
</label>
</div>
<div class="setting">
<label>
<input type="checkbox" bind:checked={NOTIFICATIONS_ENABLED} />
Notifications
</label>
</div>
<div class="setting">
<label>
<input
id="notifications-enabled"
name="notifications-enabled"
type="checkbox"
bind:checked={NOTIFICATIONS_ENABLED}
/>
Notifications
</label>
</div>
</form>
</div>
</div>