Skip to content

Commit

Permalink
new session logic wip
Browse files Browse the repository at this point in the history
  • Loading branch information
moostoet committed Jan 31, 2023
1 parent 7a87c2b commit 0e3c214
Show file tree
Hide file tree
Showing 10 changed files with 308 additions and 82 deletions.
85 changes: 85 additions & 0 deletions src/lib/ActiveSession.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<script lang="ts">
import { enhance } from '$app/forms';
import { onMount } from 'svelte';
import { now } from 'svelte/internal';
import type { Session } from '../types/session';
import { convertISODate } from '../use/time';
let currentTime: Date = new Date();
export let session: Session;
let startTimeDisplay: string;
let sessionStarted: boolean = false;
$: startTimeDisplay = session.startTime ? convertISODate(session.startTime) : 'Not yet started';
$: duration = session.startTime ? currentTime.getTime() - Date.parse(session.startTime) : 0;
$: totalMinutes = Math.floor(duration / (1000 * 60));
$: hours = Math.floor(totalMinutes / 60);
$: minutes = totalMinutes % 60;
$: seconds = Math.floor((duration / 1000) % 60);
$: formattedDuration = `${hours}h ${minutes}m ${seconds}s`;
onMount(() => {
let updateNowTimeout: NodeJS.Timeout;
const updateNow = () => {
currentTime = new Date();
updateNowTimeout = setTimeout(
updateNow,
1_000 - currentTime.getMilliseconds() // ms until next full second
);
};
updateNow();
return () => clearTimeout(updateNowTimeout);
});
</script>

<div>
<div class="p-8 flex flex-col gap-3">
<div class="p-8 bg-white rounded-md flex flex-col gap-3 shadow-sm">
<p class="text-xl font-semibold">
{session.name}
</p>
<div class="relative overflow-x-auto">
<table class="w-full text-sm text-left">
<thead class="text-sm uppercase bg-gray-100 border-l border-r border-t">
<tr>
<th scope="col" class="px-6 py-3"> Session state </th>
<th scope="col" class="px-6 py-3"> Session start </th>
<th scope="col" class="px-6 py-3"> Hourly rate </th>
<th scope="col" class="px-6 py-3"> Duration </th>
</tr>
</thead>
<tbody>
<tr class="bg-white border-l border-r border-b">
<th scope="row" class="px-6 py-4 font-medium text-gray-900">
{sessionStarted ? 'Started' : 'Not started'}
</th>
<td class="px-6 py-4">
{session.startTime && sessionStarted ? startTimeDisplay : 'Not yet started'}
</td>
<td class="px-6 py-4"> {session.hourlyRate} </td>
<td class="px-6 py-4">
{duration && sessionStarted && duration > 0 ? formattedDuration : '0h 0m 0s'}
</td>
</tr>
</tbody>
</table>
</div>
<div>
<form method="POST" action="?/startSession&id={session._id}" use:enhance>
<button
class="p-[10px] rounded-sm bg-blue-400 text-white font-semibold hover:bg-blue-500"
type="submit"
on:click={() => {
sessionStarted = true;
}}>Start Session</button
>
</form>
</div>
</div>
</div>
</div>
File renamed without changes.
42 changes: 42 additions & 0 deletions src/lib/NewSession.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<script lang="ts">
import { enhance } from '$app/forms';
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
const cancel = () => {
dispatch('cancel');
};
</script>

<div class="p-8 flex flex-col gap-3">
<div class="p-8 bg-white rounded-md flex flex-col gap-3 shadow-sm">
<form class="flex flex-col gap-3" action="?/sessions" method="POST" use:enhance>
<label class="text-md font-semibold" for="sessionName">Session name</label>
<input
name="sessionName"
type="text"
class="border p-2 rounded-sm bg-gray-100 focus:outline-1 outline-blue-300"
/>
<label class="text-md font-semibold" for="hourlyRate">Hourly rate</label>
<input
name="hourlyRate"
type="number"
class="border p-2 rounded-sm bg-gray-100 focus:outline-1 outline-blue-300"
/>
<div class="flex flex-row">
<button
class="p-[10px] bg-blue-400 hover:bg-blue-500 transition text-white font-semibold rounded-sm"
>Create session</button
>
<button
type="button"
on:click|preventDefault={() => {
cancel();
}}
class="ml-auto p-[10px] bg-red-500 hover:bg-red-600 transition text-white font-semibold rounded-sm"
>Cancel</button
>
</div>
</form>
</div>
</div>
64 changes: 64 additions & 0 deletions src/lib/Sessions.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<script lang="ts">
import type { Session } from '../types/session';
import { convertISODate } from '../use/time';
import { calculateHours } from '../use/time';
import DeleteButton from '../lib/DeleteButton.svelte';
export let sessions: Session[];
// $: startTimesFormatted = sessions.map((session) =>
// 'startTime' in session ? convertISODate(session.startTime) : undefined
// );
// $: endTimesFormatted = sessions.map((session) =>
// 'endTime' in session ? convertISODate(session.endTime) : undefined
// );
// $: totalHours = sessions.map((session) =>
// 'startTime' in session && 'endTime' in session
// ? calculateHours(session.startTime, session.endTime)
// : undefined
// );
$: startTimesFormatted = sessions.map((session) => convertISODate(session.startTime!));
$: endTimesFormatted = sessions.map((session) => convertISODate(session.endTime!));
$: totalHours = sessions.map((session) => calculateHours(session.startTime!, session.endTime!));
const handleDelete = (event: CustomEvent<{ id: string }>) => {
sessions = sessions.filter((session) => session._id !== event.detail.id);
};
</script>

<div class="p-8 flex flex-col gap-3">
{#if sessions.length === 0}
<div class="text-xl font-semibold">No sessions found</div>
{:else}
{#each sessions as session, i}
<div class="p-8 bg-white rounded-md flex flex-col gap-3 shadow-sm">
<p class="text-xl font-semibold">
{session.name}
</p>
<div class="relative overflow-x-auto">
<table class="w-full text-sm text-left">
<thead class="text-sm uppercase bg-gray-100 border-l border-r border-t">
<tr>
<th scope="col" class="px-6 py-3"> Session start </th>
<th scope="col" class="px-6 py-3"> Session end </th>
<th scope="col" class="px-6 py-3"> Hourly rate </th>
<th scope="col" class="px-6 py-3"> Total hours </th>
</tr>
</thead>
<tbody>
<tr class="bg-white border-l border-r border-b">
<th scope="row" class="px-6 py-4 font-medium text-gray-900">
{startTimesFormatted[i]}
</th>
<td class="px-6 py-4"> {endTimesFormatted[i]} </td>
<td class="px-6 py-4"> {session.hourlyRate} </td>
<td class="px-6 py-4"> {totalHours[i]} </td>
</tr>
</tbody>
</table>
</div>
<DeleteButton on:delete={handleDelete} {session} />
</div>
{/each}
{/if}
</div>
45 changes: 44 additions & 1 deletion src/routes/+page.server.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,54 @@
import type { PageServerLoad } from './$types';
import type { Session } from '../types/session';
import type { Actions } from '@sveltejs/kit';
// import { useQuery } from '@sveltestack/svelte-query'
import { fetchData } from '../use/fetch';
export const load = (async () => {
return { sessions: await fetchData<Session[]>('http://localhost:8000/sessions')}
return { sessions: await fetchData<Session[]>('http://localhost:8000/sessions') };
}) satisfies PageServerLoad;

export const actions: Actions = {
sessions: async ({ request }) => {
const data = await request.formData();
const name = data.get('sessionName');
const hourlyRate = data.get('hourlyRate');
const session = { name, hourlyRate };
const response = await fetch('http://localhost:8000/sessions', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(session)
});
return {
status: response.status
};
},
startSession: async ({ url }) => {
const id = url.searchParams.get('id');
const res = await fetch(`http://localhost:8000/sessions/${id}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
});
const session: Session = await res.json();
session.startTime = new Date().toISOString();

const response = await fetch(`http://localhost:8000/sessions/${id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(session)
});

return {
status: response.status
};
}
};

// export const load = (() => {
// const queryResult = useQuery('sessions', () => {
// return fetch('http://localhost:8000/sessions').then(res => res.json())
Expand Down
69 changes: 21 additions & 48 deletions src/routes/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,61 +1,34 @@
<script lang="ts">
import type { PageServerData } from './$types';
import { convertISODate, calculateHours } from '../use/time';
import DeleteButton from '../components/DeleteButton.svelte';
import Sessions from '../lib/Sessions.svelte';
import NewSession from '../lib/NewSession.svelte';
import ActiveSession from '../lib/ActiveSession.svelte';
export let data: PageServerData;
let newSession: boolean = false;
$: startTimesFormatted = data.sessions.map((session) => convertISODate(session.startTime));
$: endTimesFormatted = data.sessions.map((session) => convertISODate(session.endTime));
$: totalHours = data.sessions.map((session) =>
calculateHours(session.startTime, session.endTime)
);
const handleDelete = (event: CustomEvent<{id: string}>) => {
data.sessions = data.sessions.filter((session) => session._id !== event.detail.id);
};
$: completedSessions = data.sessions.filter((session) => 'hours' in session);
$: activeSession = data.sessions.find((session) => !('hours' in session));
</script>

<main class="p-4">
<div class="px-8">
<button
class="p-[10px] rounded-sm bg-blue-400 text-white font-semibold hover:bg-blue-500 transition"
on:click={() => {
newSession = true;
}}
class="p-[10px] rounded-sm bg-blue-400 text-white font-semibold hover:bg-blue-500"
>New Session</button
>
</div>
<div class="p-8 flex flex-col gap-3">
{#if data.sessions.length === 0}
<div class="text-xl font-semibold">No sessions found</div>
{:else}
{#each data.sessions as session, i}
<div class="p-8 bg-white rounded-md flex flex-col gap-3 shadow-sm">
<div class="text-xl font-semibold">
{session.name}
</div>
<div class="relative overflow-x-auto">
<table class="w-full text-sm text-left">
<thead class="text-sm uppercase bg-gray-100 border-l border-r border-t">
<tr>
<th scope="col" class="px-6 py-3"> Session start </th>
<th scope="col" class="px-6 py-3"> Session end </th>
<th scope="col" class="px-6 py-3"> Hourly rate </th>
<th scope="col" class="px-6 py-3"> Total hours </th>
</tr>
</thead>
<tbody>
<tr class="bg-white border-l border-r border-b">
<th scope="row" class="px-6 py-4 font-medium text-gray-900">
{startTimesFormatted[i]}
</th>
<td class="px-6 py-4"> {endTimesFormatted[i]} </td>
<td class="px-6 py-4"> {session.hourlyRate} </td>
<td class="px-6 py-4"> {totalHours[i]} </td>
</tr>
</tbody>
</table>
</div>
<DeleteButton on:delete={handleDelete} session={session}/>
</div>
{/each}
{/if}
</div>
{#if newSession}
<NewSession
on:cancel={() => {
newSession = false;
}}
/>
{/if}
{#if activeSession}
<ActiveSession session={activeSession} />
{/if}
<Sessions sessions={completedSessions} />
</main>
32 changes: 25 additions & 7 deletions src/types/session.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,26 @@
// export type Session = {
// _id: string
// name: string
// hourlyRate: number
// } | {
// _id: string
// name: string
// hourlyRate: number
// startTime: Date
// } | {
// _id: string
// name: string
// hourlyRate: number
// startTime: Date
// endTime: Date
// hours: number
// }

export interface Session {
_id: string
name: string
hours: number
startTime: Date
endTime: Date
hourlyRate?: number
}
_id: string;
name: string;
hourlyRate: number;
startTime?: string;
endTime?: string;
hours?: number;
}
6 changes: 0 additions & 6 deletions src/typings/additional-svelte-typings.d.ts

This file was deleted.

4 changes: 2 additions & 2 deletions src/use/time.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const convertISODate = (timestamp: Date): string => {
export const convertISODate = (timestamp: string): string => {
const date = new Date(timestamp);

const month = (date.getMonth() + 1).toString().padStart(2, '0')
Expand All @@ -11,7 +11,7 @@ export const convertISODate = (timestamp: Date): string => {
return `${month}/${day}/${year} ${hours}:${minutes} ${AMorPM}`
}

export const calculateHours = (startTimestamp: Date, endTimestamp: Date): string => {
export const calculateHours = (startTimestamp: string, endTimestamp: string): string => {
const start = new Date(startTimestamp);
const end = new Date(endTimestamp);
const diff = end.getTime() - start.getTime();
Expand Down
Loading

0 comments on commit 0e3c214

Please sign in to comment.