From ebe10fe4b30c42ab0d80037af88e7858a21f5815 Mon Sep 17 00:00:00 2001 From: The game fire Date: Tue, 16 Sep 2025 22:18:43 +0200 Subject: [PATCH 1/4] Created Achievement Page for Mobile --- ui/src/lib/components/CheckedLabel.svelte | 19 ++++++++ ui/src/lib/components/Navbar.svelte | 14 +++++- .../achievements/Achievement.svelte | 30 ++++++++++++ .../achievements/AchievementDisplay.svelte | 23 +++++++++ .../AchievementServiceGroup.svelte | 47 +++++++++++++++++++ .../components/icons/AchievementIcon.svelte | 24 ++++++++++ .../components/icons/ArrowNoBaseIcon.svelte | 4 ++ ui/src/lib/components/icons/CheckIcon.svelte | 6 +++ ui/src/lib/components/icons/CrossIcon.svelte | 6 +++ ui/src/lib/globalFunctions-Types.ts | 29 ++++++++++++ ui/src/routes/+page.svelte | 2 +- ui/src/routes/achievements/+page.svelte | 34 ++++++++++++++ ui/src/routes/profile/[username]/+page.svelte | 2 +- 13 files changed, 236 insertions(+), 4 deletions(-) create mode 100644 ui/src/lib/components/CheckedLabel.svelte create mode 100644 ui/src/lib/components/achievements/Achievement.svelte create mode 100644 ui/src/lib/components/achievements/AchievementDisplay.svelte create mode 100644 ui/src/lib/components/achievements/AchievementServiceGroup.svelte create mode 100644 ui/src/lib/components/icons/AchievementIcon.svelte create mode 100644 ui/src/lib/components/icons/ArrowNoBaseIcon.svelte create mode 100644 ui/src/lib/components/icons/CheckIcon.svelte create mode 100644 ui/src/lib/components/icons/CrossIcon.svelte create mode 100644 ui/src/routes/achievements/+page.svelte diff --git a/ui/src/lib/components/CheckedLabel.svelte b/ui/src/lib/components/CheckedLabel.svelte new file mode 100644 index 0000000..ab3ee77 --- /dev/null +++ b/ui/src/lib/components/CheckedLabel.svelte @@ -0,0 +1,19 @@ + + + + {#if checked} + + + + {:else} + + + + {/if} + {@render children()} + \ No newline at end of file diff --git a/ui/src/lib/components/Navbar.svelte b/ui/src/lib/components/Navbar.svelte index a3f2da8..13d791f 100644 --- a/ui/src/lib/components/Navbar.svelte +++ b/ui/src/lib/components/Navbar.svelte @@ -1,7 +1,8 @@ + +
+ {#if achievementUnlocked()} + achievement + {:else} + achievement + {/if} +
+ {achievement.name} +
+ {#each achievement.goals as goal, i} + {goal.description} + {/each} +
+
+
\ No newline at end of file diff --git a/ui/src/lib/components/achievements/AchievementDisplay.svelte b/ui/src/lib/components/achievements/AchievementDisplay.svelte new file mode 100644 index 0000000..68ce020 --- /dev/null +++ b/ui/src/lib/components/achievements/AchievementDisplay.svelte @@ -0,0 +1,23 @@ + + +{#if $query.isSuccess} +
+ {#each $query.data as service} + + {/each} +
+{/if} \ No newline at end of file diff --git a/ui/src/lib/components/achievements/AchievementServiceGroup.svelte b/ui/src/lib/components/achievements/AchievementServiceGroup.svelte new file mode 100644 index 0000000..eb60949 --- /dev/null +++ b/ui/src/lib/components/achievements/AchievementServiceGroup.svelte @@ -0,0 +1,47 @@ + + +{#if $query.isSuccess} +
+ + + {#if isOpen} +
+ {#each $query.data as achievement } + + {/each} +
+ {/if} +
+{/if} diff --git a/ui/src/lib/components/icons/AchievementIcon.svelte b/ui/src/lib/components/icons/AchievementIcon.svelte new file mode 100644 index 0000000..8d3056a --- /dev/null +++ b/ui/src/lib/components/icons/AchievementIcon.svelte @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ui/src/lib/components/icons/ArrowNoBaseIcon.svelte b/ui/src/lib/components/icons/ArrowNoBaseIcon.svelte new file mode 100644 index 0000000..81e7f95 --- /dev/null +++ b/ui/src/lib/components/icons/ArrowNoBaseIcon.svelte @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/ui/src/lib/components/icons/CheckIcon.svelte b/ui/src/lib/components/icons/CheckIcon.svelte new file mode 100644 index 0000000..5f6c943 --- /dev/null +++ b/ui/src/lib/components/icons/CheckIcon.svelte @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/ui/src/lib/components/icons/CrossIcon.svelte b/ui/src/lib/components/icons/CrossIcon.svelte new file mode 100644 index 0000000..37700b1 --- /dev/null +++ b/ui/src/lib/components/icons/CrossIcon.svelte @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/ui/src/lib/globalFunctions-Types.ts b/ui/src/lib/globalFunctions-Types.ts index f3f63d7..0c15336 100644 --- a/ui/src/lib/globalFunctions-Types.ts +++ b/ui/src/lib/globalFunctions-Types.ts @@ -17,6 +17,23 @@ export type CurrentUser = { username: string; }; +export type AchievementService = { + id: number; + name: string; +}; + +export type Achievement = { + id: number; + name: string; + goals: Goal[]; +}; + +export type Goal = { + id: number; + description: string; + sequence: number; +}; + export function toTitleCase(str: string) { if (!str) { return ''; @@ -60,3 +77,15 @@ export async function submitAbout(userId: number, about: string): Promise { + return fetch(`${BACKEND_URL}/api/services`, { + credentials: 'include' + }).then((r) => r.json()); +} + +export async function getAchievementsFromService(serviceId: number): Promise { + return fetch(`${BACKEND_URL}/api/services/${serviceId}/achievements`, { + credentials: 'include' + }).then((r) => r.json()); +} diff --git a/ui/src/routes/+page.svelte b/ui/src/routes/+page.svelte index 00651f5..67064bb 100644 --- a/ui/src/routes/+page.svelte +++ b/ui/src/routes/+page.svelte @@ -12,7 +12,7 @@ } ); -
+
{#if $query.isSuccess} diff --git a/ui/src/routes/achievements/+page.svelte b/ui/src/routes/achievements/+page.svelte new file mode 100644 index 0000000..491fd31 --- /dev/null +++ b/ui/src/routes/achievements/+page.svelte @@ -0,0 +1,34 @@ + +
+ + {#if $query.isSuccess} + +
+ {:else if $query.isLoading} +

+ Hold on, we're checking if you're logged in... +

+ {:else} +

+ Something went wrong, couldn't reach backend +

+ {/if} +
+
+
+
+
+
diff --git a/ui/src/routes/profile/[username]/+page.svelte b/ui/src/routes/profile/[username]/+page.svelte index a5f7591..e6ee0a9 100644 --- a/ui/src/routes/profile/[username]/+page.svelte +++ b/ui/src/routes/profile/[username]/+page.svelte @@ -17,7 +17,7 @@ -
+
{#if $query.isSuccess} From 59a24c080cadd2789a287530166d0b1859c1a6b5 Mon Sep 17 00:00:00 2001 From: The game fire Date: Tue, 16 Sep 2025 23:24:41 +0200 Subject: [PATCH 2/4] Made Achievement Page Look Better on Desktop --- .../achievements/Achievement.svelte | 20 ++++++++++++++----- .../AchievementServiceGroup.svelte | 2 +- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/ui/src/lib/components/achievements/Achievement.svelte b/ui/src/lib/components/achievements/Achievement.svelte index 85e9bc0..9396782 100644 --- a/ui/src/lib/components/achievements/Achievement.svelte +++ b/ui/src/lib/components/achievements/Achievement.svelte @@ -11,20 +11,30 @@ let imgSrc = 'https://cdn.fastly.steamstatic.com/steamcommunity/public/images/apps/1903340/893a5719f74928a4706ad295b4ab42cf0a2ffacb.jpg'; const achievementUnlocked = () => goalsUnlocked.every(g => g); + + const progressBarStyle = `width: ${goalsUnlocked.filter(g => g).length * 100 / goalsUnlocked.length}%`; + -
+
{#if achievementUnlocked()} achievement {:else} achievement {/if} -
- {achievement.name} -
+
+ {achievement.name} +
{#each achievement.goals as goal, i} - {goal.description} +
+ {goal.description} +
{/each}
+ + +
\ No newline at end of file diff --git a/ui/src/lib/components/achievements/AchievementServiceGroup.svelte b/ui/src/lib/components/achievements/AchievementServiceGroup.svelte index eb60949..b34e0dc 100644 --- a/ui/src/lib/components/achievements/AchievementServiceGroup.svelte +++ b/ui/src/lib/components/achievements/AchievementServiceGroup.svelte @@ -24,7 +24,7 @@ {#if $query.isSuccess}
+
{#each $query.data as service} - + {/each}
-{/if} \ No newline at end of file + + {#if editAllowed} + + {/if} +{/if} + diff --git a/ui/src/lib/components/achievements/AchievementEditModal.svelte b/ui/src/lib/components/achievements/AchievementEditModal.svelte new file mode 100644 index 0000000..fb5615d --- /dev/null +++ b/ui/src/lib/components/achievements/AchievementEditModal.svelte @@ -0,0 +1,74 @@ + +
+ + + + + +
+
+ +
+

Edit Service

+
+ // Middle Content +
+ +
+ + +
+
+
+
+
+
+
+ diff --git a/ui/src/lib/components/achievements/AchievementServiceGroup.svelte b/ui/src/lib/components/achievements/AchievementServiceGroup.svelte index b34e0dc..5a7d989 100644 --- a/ui/src/lib/components/achievements/AchievementServiceGroup.svelte +++ b/ui/src/lib/components/achievements/AchievementServiceGroup.svelte @@ -5,8 +5,9 @@ import Achievement from '$lib/components/achievements/Achievement.svelte'; import { createQuery, type CreateQueryResult } from '@tanstack/svelte-query'; import { slide } from 'svelte/transition'; + import PencilIcon from '$lib/components/icons/PencilIcon.svelte'; - let { service } = $props(); + let { service, editAllowed, editModal } = $props(); let isOpen = $state(false); @@ -19,22 +20,46 @@ queryFn: async () => getAchievementsFromService(service.id), retry: false }); + + function keyClickHandler(event: any, clickFn: Function) { + if (event.key === 'Enter' || event.key === ' ') { + event.preventDefault(); + clickFn(); + } + } + + function openEdit() { + toggle(); + editModal.open(); + } {#if $query.isSuccess} -
- + {/if} + - +
{#if isOpen}
From 5407a3fd4d3c63d1cdfd55fa62d153ca56593c34 Mon Sep 17 00:00:00 2001 From: The game fire Date: Thu, 18 Sep 2025 02:23:08 +0200 Subject: [PATCH 4/4] Made Achievement Edit Only Available for Admins --- .../components/achievements/AchievementDisplay.svelte | 11 +++++------ ui/src/lib/globalFunctions-Types.ts | 1 + ui/src/routes/achievements/+page.svelte | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ui/src/lib/components/achievements/AchievementDisplay.svelte b/ui/src/lib/components/achievements/AchievementDisplay.svelte index 2491f5b..74dab60 100644 --- a/ui/src/lib/components/achievements/AchievementDisplay.svelte +++ b/ui/src/lib/components/achievements/AchievementDisplay.svelte @@ -4,7 +4,7 @@ import { type AchievementService, getAchievementServices } from '$lib/globalFunctions-Types'; import AchievementEditModal from '$lib/components/achievements/AchievementEditModal.svelte'; - const services = ['tap', 'zodom', 'ledstrip']; + let { admin } = $props(); let query: CreateQueryResult = createQuery({ queryKey: [`achievement-services`], @@ -13,9 +13,8 @@ } ); - const editAllowed = true; - let editModal: AchievementEditModal; + let editModal: AchievementEditModal | undefined = $state(); @@ -23,17 +22,17 @@
{#each $query.data as service} - + {/each}
- {#if editAllowed} + {#if admin} {/if} {/if} diff --git a/ui/src/lib/globalFunctions-Types.ts b/ui/src/lib/globalFunctions-Types.ts index 0c15336..7555c6d 100644 --- a/ui/src/lib/globalFunctions-Types.ts +++ b/ui/src/lib/globalFunctions-Types.ts @@ -15,6 +15,7 @@ export type ProfileData = { export type CurrentUser = { id: number; username: string; + admin: boolean; }; export type AchievementService = { diff --git a/ui/src/routes/achievements/+page.svelte b/ui/src/routes/achievements/+page.svelte index 491fd31..2b6948c 100644 --- a/ui/src/routes/achievements/+page.svelte +++ b/ui/src/routes/achievements/+page.svelte @@ -15,7 +15,7 @@
{#if $query.isSuccess} - +
{:else if $query.isLoading}