-
-
+
+
-
-
{name}
-
{position}
-
+
+
{name}
+
{position}
+
+
+
-
+
diff --git a/src/components/council/CouncilCardPopUp.svelte b/src/components/council/CouncilCardPopUp.svelte
index e3e9c31..a3b53fc 100644
--- a/src/components/council/CouncilCardPopUp.svelte
+++ b/src/components/council/CouncilCardPopUp.svelte
@@ -1,42 +1,78 @@
-
-
-
-

+
+
+
+
+
+
+
+

+
+
{yearProgram}
-
{yearProgram}
-
-
-
-
-
-
-
- -
-
{positionDescription}
-
- -
-
-
- Email: {email}
-
-
-
+
+
+
+
+
+
+
+
+ {#if positionDescription}
+
+
+ {positionDescription}
+
+
+ {/if}
+ {#if email}
+
+ {/if}
+
diff --git a/src/components/layout/Section.svelte b/src/components/layout/Section.svelte
index 33e95e6..e18c128 100644
--- a/src/components/layout/Section.svelte
+++ b/src/components/layout/Section.svelte
@@ -11,20 +11,23 @@
to = '',
via = '',
direction = 'to-b', // to bottom
- black = false
+ black = false,
+ contentStart = false
} = $props();
const base =
- 'mx-auto flex min-h-[90vh] flex-col items-center justify-center gap-4 p-4 text-center text-ecsess-100';
+ 'mx-auto flex min-h-[90vh] flex-col items-center gap-4 p-4 text-center text-ecsess-100';
+ const justifyClass = contentStart ? 'justify-start' : 'justify-center';
// Compute classes: prefer gradient when from/to provided; otherwise fallback to previous behavior
let tailwindClasses = $state(base);
$effect(() => {
+ const withJustify = `${base} ${justifyClass}`;
if (from && to) {
- tailwindClasses = `${base} bg-gradient-${direction} ${from} ${to} ${via}`;
+ tailwindClasses = `${withJustify} bg-gradient-${direction} ${from} ${to} ${via}`;
} else {
- tailwindClasses = base + (black ? ' bg-ecsess-black' : ' bg-ecsess-800');
+ tailwindClasses = withJustify + (black ? ' bg-ecsess-black' : ' bg-ecsess-800');
}
});
diff --git a/src/routes/council/+page.svelte b/src/routes/council/+page.svelte
index 6b40c85..9755582 100644
--- a/src/routes/council/+page.svelte
+++ b/src/routes/council/+page.svelte
@@ -4,39 +4,69 @@
import CardCouncil from 'components/council/CouncilCard.svelte';
import type { CouncilMember } from '$lib/schemas';
import { fly } from 'svelte/transition';
- import Button from 'components/Button.svelte';
import SeoMetaTags from 'components/layout/SeoMetaTags.svelte';
+ import { onMount } from 'svelte';
+ import { tick } from 'svelte';
let { data } = $props();
- // Get members by 3 main categories:
- // - Preseident
- // - VPs + Equity and Mental Health Officer
- // - UReps
- let president: CouncilMember = data.members.filter((member: CouncilMember) =>
- member.position.includes('President')
- )[0];
+ const years = ['U4', 'U3', 'U2', 'U1', 'U0'];
- let vps: CouncilMember[] = data.members.filter(
- (member: CouncilMember) => member.position.includes('VP') || member.position.includes('Equity')
+ // Get members by 3 main categories (reactive from data)
+ let president = $derived(
+ data.members.filter((member: CouncilMember) => member.position.includes('President'))[0]
);
-
- let ureps: CouncilMember[] = data.members.filter((member: CouncilMember) =>
- member.position.includes('Representative')
+ let vps = $derived(
+ data.members.filter(
+ (member: CouncilMember) =>
+ member.position.includes('VP') || member.position.includes('Equity')
+ )
+ );
+ let ureps = $derived(
+ (() => {
+ const list = data.members.filter((member: CouncilMember) =>
+ member.position.includes('Representative')
+ );
+ return [...list].sort((a, b) => {
+ const aYear = years.findIndex((year) => a.position.includes(year));
+ const bYear = years.findIndex((year) => b.position.includes(year));
+ return aYear - bYear;
+ });
+ })()
);
-
- let years = ['U4', 'U3', 'U2', 'U1', 'U0'];
-
- ureps.sort((a, b) => {
- const aYear = years.findIndex((year) => a.position.includes(year));
- const bYear = years.findIndex((year) => b.position.includes(year));
- return aYear - bYear;
- });
let selectedMember = $state
(null);
+ let modalRef = $state(null);
+
function handleViewProfile(member: CouncilMember) {
selectedMember = member;
}
+ function closeModal() {
+ selectedMember = null;
+ }
+ function onBackdropKeydown(e: KeyboardEvent) {
+ if (e.key === 'Escape') closeModal();
+ }
+
+ onMount(() => {
+ function onKeyDown(e: KeyboardEvent) {
+ if (e.key === 'Escape') closeModal();
+ }
+ window.addEventListener('keydown', onKeyDown);
+ return () => window.removeEventListener('keydown', onKeyDown);
+ });
+
+ $effect(() => {
+ if (selectedMember) {
+ document.body.style.overflow = 'hidden';
+ tick().then(() => modalRef?.focus());
+ } else {
+ document.body.style.overflow = '';
+ }
+ return () => {
+ document.body.style.overflow = '';
+ };
+ });
-
-
-
Meet the council!
-
+
+
+
Meet the council!
- Our Student Council!
+
+ Our Student Council
+
-
- handleViewProfile(president!)}
- />
-
+ {#if president}
+
+ handleViewProfile(president)}
+ />
+
+ {/if}
-
+
Vice Presidents
-
+
{#each vps as vp}
- Year Representative
+ Year Representatives
-
+
{#each ureps as urep}
+
{#if selectedMember}
-
-
-
-
+
+
e.target === e.currentTarget && closeModal()}
+ onkeydown={onBackdropKeydown}
+ >
+
+
{/if}