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
15 changes: 11 additions & 4 deletions components/frontend/src/lib/components/hackathon/TeamCard.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,16 @@
</button>
{/if}

<!-- eslint-disable-next-line @typescript-eslint/no-explicit-any -- dynamic path from page data; resolve() is route-literal typed -->
<a href={resolve(moreInfoHref as any)} class="btn btn-sm btn-ghost">
More Information
</a>
<!-- Only a real in-app route can be resolved; a placeholder '#' or a
bare '#fragment' throws inside resolve(). Teams have no detail page
on this branch (main's teams/[teamId] was not carried over), so the
list passes a fragment and this used to error on click. Offer no
dead link until there is somewhere to point. -->
{#if moreInfoHref.startsWith('/')}
<!-- eslint-disable-next-line @typescript-eslint/no-explicit-any -- dynamic path from page data; resolve() is route-literal typed -->
<a href={resolve(moreInfoHref as any)} class="btn btn-sm btn-ghost">
More Information
</a>
{/if}
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,17 @@
</p>
{:else}
{#each pagedTeams as team (team.id)}
<!-- No moreInfoHref: teams have no detail page on this branch
(main's teams/[teamId] was not carried over), and the
placeholder "#team-{id}" this used to pass threw inside
TeamCard's resolve(). TeamCard hides the link without one. -->
<TeamCard
num={team.num}
title={team.title}
projectDescription={team.projectDescription}
imageUrl={team.imageUrl}
members={team.members}
isOwn={team.isOwn}
moreInfoHref="#team-{team.id}"
/>
{/each}
{/if}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,14 @@ export const actions: Actions = {
})
}
if (e instanceof ClientError && e.code === Status.FAILED_PRECONDITION) {
return bad(409, { message: "Voting is not open for this hackathon." })
// Surface the server's specific reason. SubmitVote answers
// FAILED_PRECONDITION for two distinct states — the votingEnabled
// master switch being off ("voting is closed") and the VOTE capability
// being closed by the current phase (capabilityClosedMessage) — and one
// hardcoded string cannot tell an organiser which of the two to fix.
return bad(409, {
message: e.details || "Voting is not open for this hackathon.",
})
}
return formError(e)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,16 @@
<!-- The rules of the vote. They were stored and never read on the
server, and never written from anywhere at all — an event could
not state its own rules. Prefilled, because SetVotingPolicy
replaces the whole record. -->
<form method="POST" action="?/setPolicy" use:enhance class="card flex flex-col gap-3 p-4">
replaces the whole record.

keepValues, not a bare use:enhance: checked={…} sets the
checkbox PROPERTY, never the defaultChecked attribute, so the
default form.reset() after a successful save reverts the boxes
to unchecked. ownTeamVoting defaults to checked and round-trips
to the same value, so Svelte's reactivity never re-asserts it —
the reset's uncheck sticks, and saving looks like it silently
turned the rule off. -->
<form method="POST" action="?/setPolicy" use:enhance={keepValues} class="card flex flex-col gap-3 p-4">
<h2 class="m-0 text-xl font-bold">Rules</h2>

<label class="flex items-start gap-2 text-sm">
Expand Down
Loading