diff --git a/src/lib/ActiveSession.svelte b/src/lib/ActiveSession.svelte new file mode 100644 index 0000000..88f97e0 --- /dev/null +++ b/src/lib/ActiveSession.svelte @@ -0,0 +1,85 @@ + + +
+
+
+

+ {session.name} +

+
+ + + + + + + + + + + + + + + + + +
Session state Session start Hourly rate Duration
+ {sessionStarted ? 'Started' : 'Not started'} + + {session.startTime && sessionStarted ? startTimeDisplay : 'Not yet started'} + {session.hourlyRate} + {duration && sessionStarted && duration > 0 ? formattedDuration : '0h 0m 0s'} +
+
+
+
+ +
+
+
+
+
diff --git a/src/components/DeleteButton.svelte b/src/lib/DeleteButton.svelte similarity index 100% rename from src/components/DeleteButton.svelte rename to src/lib/DeleteButton.svelte diff --git a/src/lib/NewSession.svelte b/src/lib/NewSession.svelte new file mode 100644 index 0000000..bc73736 --- /dev/null +++ b/src/lib/NewSession.svelte @@ -0,0 +1,42 @@ + + +
+
+
+ + + + +
+ + +
+
+
+
diff --git a/src/lib/Sessions.svelte b/src/lib/Sessions.svelte new file mode 100644 index 0000000..3f693af --- /dev/null +++ b/src/lib/Sessions.svelte @@ -0,0 +1,64 @@ + + +
+ {#if sessions.length === 0} +
No sessions found
+ {:else} + {#each sessions as session, i} +
+

+ {session.name} +

+
+ + + + + + + + + + + + + + + + + +
Session start Session end Hourly rate Total hours
+ {startTimesFormatted[i]} + {endTimesFormatted[i]} {session.hourlyRate} {totalHours[i]}
+
+ +
+ {/each} + {/if} +
diff --git a/src/routes/+page.server.ts b/src/routes/+page.server.ts index e1c877d..a7afcbb 100644 --- a/src/routes/+page.server.ts +++ b/src/routes/+page.server.ts @@ -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('http://localhost:8000/sessions')} + return { sessions: await fetchData('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()) diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 3bb618b..9d36bcc 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,61 +1,34 @@
-
- {#if data.sessions.length === 0} -
No sessions found
- {:else} - {#each data.sessions as session, i} -
-
- {session.name} -
-
- - - - - - - - - - - - - - - - - -
Session start Session end Hourly rate Total hours
- {startTimesFormatted[i]} - {endTimesFormatted[i]} {session.hourlyRate} {totalHours[i]}
-
- -
- {/each} - {/if} -
+ {#if newSession} + { + newSession = false; + }} + /> + {/if} + {#if activeSession} + + {/if} +
diff --git a/src/types/session.ts b/src/types/session.ts index 4dc78a3..1c7d01d 100644 --- a/src/types/session.ts +++ b/src/types/session.ts @@ -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 - } \ No newline at end of file + _id: string; + name: string; + hourlyRate: number; + startTime?: string; + endTime?: string; + hours?: number; +} \ No newline at end of file diff --git a/src/typings/additional-svelte-typings.d.ts b/src/typings/additional-svelte-typings.d.ts deleted file mode 100644 index 0b961a0..0000000 --- a/src/typings/additional-svelte-typings.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -declare namespace svelteHTML { - // enhance attributes - interface HTMLAttributes { - 'on:click_outside'?: () => void; - } -} \ No newline at end of file diff --git a/src/use/time.ts b/src/use/time.ts index ce13b25..5e3bbe2 100644 --- a/src/use/time.ts +++ b/src/use/time.ts @@ -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') @@ -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(); diff --git a/src/utils/clickOutside.ts b/src/utils/clickOutside.ts index e15d7e9..d497431 100644 --- a/src/utils/clickOutside.ts +++ b/src/utils/clickOutside.ts @@ -1,20 +1,27 @@ -export function clickOutside(node: T) { - const handleClick = (event: MouseEvent) => { - if ( - node && - event.target instanceof Element && - !node.contains(event.target) && - !event.defaultPrevented - ) { - node.dispatchEvent(new CustomEvent('click_outside', { detail: node })) - } - } +import type { Action } from 'svelte/action'; - document.addEventListener('click', handleClick, true) +export const clickOutside: Action< + HTMLElement, + undefined, + { 'on:click_outside': (e: CustomEvent<{ detail: HTMLElement }>) => void } +> = (node) => { + const handleClick = (event: MouseEvent) => { + console.log(event); + if ( + node && + event.target instanceof Element && + !node.contains(event.target) && + !event.defaultPrevented + ) { + node.dispatchEvent(new CustomEvent('click_outside', { detail: node })); + } + }; - return { - destroy() { - document.removeEventListener('click', handleClick, true) - } - } -} \ No newline at end of file + document.addEventListener('click', handleClick, true); + + return { + destroy() { + document.removeEventListener('click', handleClick, true); + } + }; +};