Skip to content

Commit c033382

Browse files
authored
Display ghost contests (#544)
* Display ghost contests * Fix svelte check error
1 parent bfa0e96 commit c033382

File tree

7 files changed

+82
-59
lines changed

7 files changed

+82
-59
lines changed

src/components/stats/contests/participation.svelte

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import type { StrippedContestParticipationDto } from '$lib/api';
33
import * as Popover from '$ui/popover';
44
import CircleAlert from '@lucide/svelte/icons/circle-alert';
5+
import Ghost from '@lucide/svelte/icons/ghost';
56
67
interface Props {
78
entry: StrippedContestParticipationDto;
@@ -28,12 +29,24 @@
2829
<span class="xs:text-md text-sm sm:text-xl md:text-2xl">???</span>
2930
{/if}
3031
</p>
32+
{#if entry.medal === 'ghost'}
33+
<Popover.Mobile>
34+
{#snippet trigger()}
35+
<Ghost class="text-muted-foreground" />
36+
{/snippet}
37+
<div>
38+
<p class="text-lg font-semibold">Ghost Contest</p>
39+
<p class="max-w-xs break-words whitespace-normal">
40+
This participation is a "ghost" entry and is not claimable. This player claimed a different
41+
crop during the contest.
42+
</p>
43+
</div>
44+
</Popover.Mobile>
45+
{/if}
3146
{#if entry.removed}
3247
<Popover.Mobile>
3348
{#snippet trigger()}
34-
<div class="mt-2">
35-
<CircleAlert class="text-destructive" size={24} />
36-
</div>
49+
<CircleAlert class="text-destructive mt-0.5" />
3750
{/snippet}
3851
<div>
3952
<p class="text-lg font-semibold">This participation no longer exists!</p>
@@ -54,7 +67,7 @@
5467
<div class="xs:text-xl font-mono text-sm sm:text-2xl">
5568
{entry.collected?.toLocaleString()}
5669
</div>
57-
{#if entry.medal && entry.medal !== 'none'}
70+
{#if entry.medal && entry.medal !== 'none' && entry.medal !== 'ghost'}
5871
<img
5972
class="pixelated inline-block h-6 w-6"
6073
src="/images/medals/{entry.medal}.webp"

src/components/stats/jacob/contest-list.svelte

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,16 @@
77
88
interface Props {
99
contests: NonNullable<JacobDataDto['contests']>;
10+
showGhosts: boolean;
1011
remaining?: number;
1112
}
1213
13-
let { contests, remaining = 0 }: Props = $props();
14+
let { contests, remaining = 0, showGhosts = false }: Props = $props();
1415
</script>
1516

1617
<ScrollArea orientation="vertical" class="h-96">
1718
<div class="flex flex-wrap items-center justify-center gap-2 px-3">
18-
{#each contests as contest (`${contest.crop}${contest.timestamp}`)}
19+
{#each contests.filter((contest) => showGhosts || contest.medal !== 'ghost') as contest (`${contest.crop}${contest.timestamp}`)}
1920
<Contest {contest} class="" />
2021
{/each}
2122
</div>

src/components/stats/jacob/contest.svelte

Lines changed: 53 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,36 @@
1+
<script lang="ts" module>
2+
const borderColors: Record<string, string> = {
3+
Cactus: 'border-cactus',
4+
Carrot: 'border-carrot',
5+
'Cocoa Beans': 'border-cocoa',
6+
Melon: 'border-melon',
7+
Mushroom: 'border-mushroom',
8+
'Nether Wart': 'border-netherwart',
9+
Potato: 'border-potato',
10+
Pumpkin: 'border-pumpkin',
11+
'Sugar Cane': 'border-sugarcane',
12+
Wheat: 'border-wheat',
13+
};
14+
15+
const ghostColors: Record<string, string> = {
16+
Cactus: 'border-cactus/50',
17+
Carrot: 'border-carrot/50',
18+
'Cocoa Beans': 'border-cocoa/50',
19+
Melon: 'border-melon/50',
20+
Mushroom: 'border-mushroom/50',
21+
'Nether Wart': 'border-netherwart/50',
22+
Potato: 'border-potato/50',
23+
Pumpkin: 'border-pumpkin/50',
24+
'Sugar Cane': 'border-sugarcane/50',
25+
Wheat: 'border-wheat/50',
26+
};
27+
</script>
28+
129
<script lang="ts">
230
import type { ContestParticipationDto } from '$lib/api';
331
import { getReadableSkyblockDate } from '$lib/format';
432
import { cn } from '$lib/utils';
33+
import Ghost from '@lucide/svelte/icons/ghost';
534
635
interface Props {
736
contest: ContestParticipationDto;
@@ -15,80 +44,53 @@
1544
1645
let cropName = $derived(crop ?? 'Not Found');
1746
let ranking = $derived((position ?? 0) > -1);
47+
let ghost = $derived(medal === 'ghost');
48+
let borderColor = $derived(
49+
(ghost ? ghostColors[crop ?? 'Wheat'] : borderColors[crop ?? 'Wheat']) || 'var(--color-border)'
50+
);
1851
</script>
1952

2053
<a
2154
href="/contest/{timestamp}"
2255
data-sveltekit-preload-data="off"
2356
class={cn(
24-
`bg-card hover:bg-muted flex min-w-52 flex-col gap-1 rounded-md border-l-4 p-2 hover:shadow-lg ${crop?.replace(
25-
' ',
26-
''
27-
)}`,
57+
`bg-card hover:bg-muted flex min-w-52 flex-col gap-1 rounded-md border-l-4 p-2 hover:shadow-lg ${borderColor}`,
2858
classes
2959
)}
3060
>
3161
<p class="text-sm first-letter:uppercase">
3262
<span class="bg-card rounded-md p-0.5 px-1.5">{cropName}</span>
33-
<span class="text-sm font-semibold">{ranking ? `#${(position ?? -2) + 1}` : 'Unclaimed'}</span>
34-
<span class="text-xs">{ranking ? `/ ${participants}` : ''}</span>
63+
{#if ghost}
64+
<span class="text-sm font-semibold">Not Claimable</span>
65+
{:else}
66+
<span class="text-sm font-semibold">{ranking ? `#${(position ?? -2) + 1}` : 'Unclaimed'}</span>
67+
<span class="text-xs">{ranking ? `/ ${participants}` : ''}</span>
68+
{/if}
3569
</p>
3670
<p class="flex flex-row items-center gap-1 text-lg font-semibold">
3771
{#if medal && medal !== 'none'}
38-
<img class="pixelated inline-block h-6 w-6 p-0.5" src="/images/medals/{medal}.webp" alt="Earned Medal" />
72+
{#if ghost}
73+
<Ghost class="text-muted-foreground p-0.5" />
74+
{:else}
75+
<img
76+
class="pixelated inline-block h-6 w-6 p-0.5"
77+
src="/images/medals/{medal}.webp"
78+
alt="Earned Medal"
79+
/>
80+
{/if}
3981
{/if}
4082
<span>{(collected ?? 0).toLocaleString()}</span>
4183
</p>
4284
{#if irlTime}
43-
<span class="font-mono text-xs font-semibold">
85+
<span class="font-mono text-xs font-semibold {irlTime ? 'block' : 'hidden'}">
4486
{new Date(Number(timestamp ?? 0) * 1000).toLocaleString(undefined, {
4587
timeStyle: 'short',
4688
dateStyle: 'medium',
4789
})}
4890
</span>
4991
{:else}
50-
<span class="font-mono text-xs font-semibold">{getReadableSkyblockDate(timestamp ?? 0)}</span>
92+
<span class="font-mono text-xs font-semibold {irlTime ? 'hidden' : 'block'}"
93+
>{getReadableSkyblockDate(timestamp ?? 0)}</span
94+
>
5195
{/if}
5296
</a>
53-
54-
<style lang="postcss">
55-
.Cactus {
56-
border-color: var(--color-cactus);
57-
}
58-
59-
.Carrot {
60-
border-color: var(--color-carrot);
61-
}
62-
63-
.CocoaBeans {
64-
border-color: var(--color-cocoa);
65-
}
66-
67-
.Melon {
68-
border-color: var(--color-melon);
69-
}
70-
71-
.Mushroom {
72-
border-color: var(--color-mushroom);
73-
}
74-
75-
.NetherWart {
76-
border-color: var(--color-netherwart);
77-
}
78-
79-
.Potato {
80-
border-color: var(--color-potato);
81-
}
82-
83-
.Pumpkin {
84-
border-color: var(--color-pumpkin);
85-
}
86-
87-
.SugarCane {
88-
border-color: var(--color-sugarcane);
89-
}
90-
91-
.Wheat {
92-
border-color: var(--color-wheat);
93-
}
94-
</style>

src/components/stats/jacob/crop-stats.svelte

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,10 @@
158158
]}
159159
/>
160160
</div>
161-
<ContestList contests={recentContests} remaining={Math.max(0, contests.length - recentContests.length)} />
161+
<ContestList
162+
contests={recentContests}
163+
remaining={Math.max(0, contests.length - recentContests.length)}
164+
showGhosts={false}
165+
/>
162166
</div>
163167
</div>

src/components/stats/jacob/recent-contests.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
{#if recentContests.length > 0}
2525
<div class="flex flex-col items-center gap-2">
26-
<ContestList contests={recentContests} />
26+
<ContestList contests={recentContests} showGhosts={false} />
2727
<Button
2828
href={page.url.pathname + '/contests'}
2929
data-sveltekit-preload-data="off"

src/lib/api/client/EliteAPI.zod.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7553,6 +7553,7 @@ export const zodGetProfileResponse = zod.object({
75537553
zod.literal(3),
75547554
zod.literal(4),
75557555
zod.literal(5),
7556+
zod.literal(-1),
75567557
])
75577558
),
75587559
personalBests: zod.record(zod.string(), zod.number()),
@@ -8177,6 +8178,7 @@ export const zodGetSelectedProfileResponse = zod.object({
81778178
zod.literal(3),
81788179
zod.literal(4),
81798180
zod.literal(5),
8181+
zod.literal(-1),
81808182
])
81818183
),
81828184
personalBests: zod.record(zod.string(), zod.number()),

src/lib/api/schemas/ContestMedal.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@ export const ContestMedal = {
1818
Gold: 3,
1919
Platinum: 4,
2020
Diamond: 5,
21+
Unclaimable: -1,
2122
} as const;

0 commit comments

Comments
 (0)