Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 20 additions & 20 deletions src/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,27 @@
@custom-variant dark (&:where(.dark, .dark *));

@theme {
--color-primary-50: #fff5f2;
--color-primary-100: #fff1ee;
--color-primary-200: #ffe4de;
--color-primary-300: #ffd5cc;
--color-primary-400: #ffbcad;
--color-primary-500: #fe795d;
--color-primary-600: #ef562f;
--color-primary-700: #eb4f27;
--color-primary-800: #cc4522;
--color-primary-900: #a5371b;
--color-primary-50: #f0f9ff;
--color-primary-100: #e0f2fe;
--color-primary-200: #bae6fd;
--color-primary-300: #7dd3fc;
--color-primary-400: #38bdf8;
--color-primary-500: #0ea5e9;
--color-primary-600: #0284c7;
--color-primary-700: #0369a1;
--color-primary-800: #075985;
--color-primary-900: #0c4a6e;

--color-secondary-50: #f0f9ff;
--color-secondary-100: #e0f2fe;
--color-secondary-200: #bae6fd;
--color-secondary-300: #7dd3fc;
--color-secondary-400: #38bdf8;
--color-secondary-500: #0ea5e9;
--color-secondary-600: #0284c7;
--color-secondary-700: #0369a1;
--color-secondary-800: #075985;
--color-secondary-900: #0c4a6e;
--color-secondary-50: #fff5f2;
--color-secondary-100: #fff1ee;
--color-secondary-200: #ffe4de;
--color-secondary-300: #ffd5cc;
--color-secondary-400: #ffbcad;
--color-secondary-500: #fe795d;
--color-secondary-600: #ef562f;
--color-secondary-700: #eb4f27;
--color-secondary-800: #cc4522;
--color-secondary-900: #a5371b;
}

@source '../node_modules/flowbite-svelte/dist';
Expand Down
8 changes: 4 additions & 4 deletions src/lib/components/EventForm.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
let newDish = $state('');
let votingSystem: string = $state(votingSystems[0].id);

const isFormValid = $derived(eventName.trim() !== '' && dishes.length > 0);
const isFormValid = $derived(eventName.trim() !== '' && dishes.length > 1);

const addDish = () => {
if (newDish.trim()) {
Expand Down Expand Up @@ -49,7 +49,7 @@
};
</script>

<Heading tag="h2" class="mb-4">Create an Event</Heading>
<Heading tag="h2" class="mb-4">Host an Event</Heading>

<form class="space-y-6" onsubmit={handleSubmit}>
<div>
Expand All @@ -67,7 +67,7 @@
onkeydown={handleKeyPressOnDishInput}
/>
<div>
<Button color="blue" onclick={addDish}>Add</Button>
<Button color="secondary" onclick={addDish}>Add</Button>
</div>
</div>
{#if dishes.length > 0}
Expand All @@ -93,5 +93,5 @@
{/each}
</Select>
</div>
<Button type="submit" class="flex-1" color="blue" disabled={!isFormValid}>Create Event</Button>
<Button type="submit" class="flex-1" disabled={!isFormValid}>Create Event</Button>
</form>
74 changes: 74 additions & 0 deletions src/lib/components/SavedBallotList.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<script lang="ts">
import type { APIError } from '$lib/api/base';
import { EventsAPI } from '$lib/api/events';
import { getStorageContext } from '$lib/storage/storage';
import { Heading, Listgroup, ListgroupItem, P } from 'flowbite-svelte';
import { onMount } from 'svelte';

type BallotItem = {
eventName: string;
eventID: number;
state: 'closed' | 'open';
id: number;
};

let ballots: BallotItem[] = $state([]);
let closedBallots: BallotItem[] = $derived(ballots.filter((ballot) => ballot.state === 'closed'));
let openBallots: BallotItem[] = $derived(ballots.filter((ballot) => ballot.state === 'open'));

const storage = getStorageContext();

onMount(async () => {
const eventApi = new EventsAPI();
const localBallots = storage.data.ballots;

for (const key in localBallots) {
const keyAsNumber = Number(key);
try {
const response = await eventApi.getEvent(
localBallots[keyAsNumber].eventID,
localBallots[keyAsNumber].token
);
ballots.push({
eventName: response.name,
eventID: localBallots[keyAsNumber].eventID,
id: keyAsNumber,
state: response.status == 'CL' ? 'closed' : 'open'
});
} catch (e) {
const status = (e as APIError).status;
if (status == 404 || status == 403) storage.deleteBallot(keyAsNumber);
}
}
});
</script>

{#snippet ballotItem(ballot: BallotItem)}
<ListgroupItem
class="flex flex-row items-center justify-between px-4 py-3"
href={`/event/${ballot.eventID}/ballot/${ballot.id}`}
>
{ballot.eventName}
</ListgroupItem>
{/snippet}

{#if ballots.length === 0}
<P class="mb-4">No past ballots found.</P>
{:else}
{#if openBallots.length}
<Listgroup active class="mb-4 ">
<Heading tag="h4" class="p-4 text-lg">Open</Heading>
{#each openBallots as ballot (ballot.id)}
{@render ballotItem(ballot)}
{/each}
</Listgroup>
{/if}
{#if closedBallots.length}
<Listgroup active class="mb-4">
<Heading tag="h4" class="p-4 text-lg">Closed</Heading>
{#each closedBallots.slice(0, 5) as ballot (ballot.id)}
{@render ballotItem(ballot)}
{/each}
</Listgroup>
{/if}
{/if}
79 changes: 79 additions & 0 deletions src/lib/components/SavedEventList.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<script lang="ts">
import type { APIError } from '$lib/api/base';
import { EventsAPI } from '$lib/api/events';
import { getStorageContext } from '$lib/storage/storage';
import { Heading, Listgroup, ListgroupItem, P } from 'flowbite-svelte';
import { onMount } from 'svelte';

type EventItem = {
name: string;
state: 'closed' | 'open' | 'missing';
id: number;
};

let events: EventItem[] = $state([]);

let closedEvents: EventItem[] = $derived(events.filter((event) => event.state === 'closed'));
let openEvents: EventItem[] = $derived(events.filter((event) => event.state === 'open'));

const storage = getStorageContext();

onMount(async () => {
const eventApi = new EventsAPI();

const localEvents = storage.data.events;

for (const key in localEvents) {
const keyAsNumber = Number(key);

try {
const event = await eventApi.getEvent(keyAsNumber, localEvents[keyAsNumber].token);
events.push({
name: localEvents[keyAsNumber].name,
id: keyAsNumber,
state: event.status === 'CL' ? 'closed' : 'open'
});
} catch (e) {
const status = (e as APIError).status;
if (status == 404 || status == 403) {
events.push({
name: localEvents[keyAsNumber].name,
id: keyAsNumber,
state: 'missing'
});
storage.deleteEvent(keyAsNumber);
}
}
}
});
</script>

{#snippet eventItem(event: EventItem)}
<ListgroupItem
class="flex flex-row items-center justify-between px-4 py-3"
href={`/event/${event.id}`}
>
{event.name}
</ListgroupItem>
{/snippet}

{#if events.length === 0}
<P class="mb-4">No past events found.</P>
{:else}
{#if openEvents.length}
<Listgroup active class="mb-4 ">
<Heading tag="h4" class="p-4 text-lg">Open</Heading>
{#each openEvents as event (event.id)}
{@render eventItem(event)}
{/each}
</Listgroup>
{/if}
{#if closedEvents.length}
<Listgroup active class="mb-4">
<Heading tag="h4" class="p-4 text-lg">Closed</Heading>
{#each closedEvents.slice(0, 5) as event (event.id)}
{@render eventItem(event)}
{/each}
</Listgroup>
{/if}
{/if}
18 changes: 18 additions & 0 deletions src/lib/storage/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ export class StorageManager {
this.data = await this.loadStorage();
};

hasBallots() {
return !!this.data.ballots;
}

hasEvents() {
return !!this.data.events;
}

getBallot(ballotID: number) {
if (!this.data.ballots) throw new ErrorBallotNotFound(ballotID);
if (ballotID in this.data.ballots) return this.data.ballots[ballotID];
Expand Down Expand Up @@ -66,6 +74,11 @@ export class StorageManager {
this.saveStorage(this.data);
}

deleteBallot(ballotID: number) {
if (this.data.ballots) delete this.data.ballots[ballotID];
this.saveStorage(this.data);
}

saveEvent(eventID: number, name: string, token: string) {
if (!this.data.events) {
this.data.events = {};
Expand All @@ -74,6 +87,11 @@ export class StorageManager {
this.saveStorage(this.data);
}

deleteEvent(eventID: number) {
if (this.data.events) delete this.data.events[eventID];
this.saveStorage(this.data);
}

async migrate<T = unknown>(data: StorageData<T>): Promise<StorageData<CurrentStorageSchema>> {
let migratedData: StorageData<unknown> = { ...data };

Expand Down
11 changes: 10 additions & 1 deletion src/routes/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
<script lang="ts">
import EventForm from '$lib/components/EventForm.svelte';
import { Heading, P, Hr } from 'flowbite-svelte';
import { getStorageContext } from '$lib/storage/storage';
import { Heading, P, Hr, Button } from 'flowbite-svelte';

const storage = getStorageContext();
</script>

<div class="p-4">
Expand All @@ -14,5 +17,11 @@

<Hr />

{#if storage.hasEvents() || storage.hasEvents()}
<Button href="/user/dashboard" class="w-full">See past events</Button>

<Hr>or</Hr>
{/if}

<EventForm />
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,6 @@
{/if}
</div>

<Button size="xl" color="blue" class="w-full" disabled={ballotCount < 2} onclick={startVoting}>
<Button size="xl" class="w-full" disabled={ballotCount < 2} onclick={startVoting}>
Begin Voting
</Button>
2 changes: 1 addition & 1 deletion src/routes/event/[id=eventID]/components/voting.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,5 @@
<!-- <Button size="sm" outline color="red" class="grow" onclick={openRegistration}>
Temporarily Open Registration
</Button> -->
<Button size="xl" color="blue" class="grow" onclick={closeVoting}>Close Voting</Button>
<Button size="xl" class="grow" onclick={closeVoting}>Close Voting</Button>
</div>
2 changes: 1 addition & 1 deletion src/routes/register/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
</div>

<div class="flex gap-4">
<Button type="submit" class="flex-1 cursor-pointer" color="blue" disabled={!isFormValid}>
<Button type="submit" class="flex-1 cursor-pointer" disabled={!isFormValid}>
Start Voting!
</Button>
</div>
Expand Down
20 changes: 20 additions & 0 deletions src/routes/user/dashboard/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<script lang="ts">
import SavedBallotList from '$lib/components/SavedBallotList.svelte';
import SavedEventList from '$lib/components/SavedEventList.svelte';
import { Button, Heading } from 'flowbite-svelte';
</script>

<div class="p-4">
<Heading tag="h2" class="mb-6">Your Dashboard</Heading>

<div class="mb-8">
<Heading tag="h3" class="mb-4">Events</Heading>
<SavedEventList />
</div>
<div>
<Heading tag="h3" class="mb-4">Ballots</Heading>
<SavedBallotList />
</div>

<Button href="/" class="w-full">Back to Home</Button>
</div>
Loading