-
+
+ {#if tag}
+
+ {tag}
+
+ {/if}
+ {#if image && !imageError}
+
+ {:else}
+
+ {/if}
-
-
{name}
-{position}
-
-
-
+
+
diff --git a/src/components/council/CouncilCardPopUp.svelte b/src/components/council/CouncilCardPopUp.svelte
index a3b53fc..c7ac114 100644
--- a/src/components/council/CouncilCardPopUp.svelte
+++ b/src/components/council/CouncilCardPopUp.svelte
@@ -1,4 +1,4 @@
-
+ {name} +
+{position}
+
-
-
-
+
+
-
-
-
+ {#if yearProgram}
+
+ {#if image && !imageError}
-
- {yearProgram}
+ {:else}
+
+ {/if}
+ {yearProgram} +
+ {/if} +
-
-
+
-
diff --git a/src/components/layout/Section.svelte b/src/components/layout/Section.svelte
index e18c128..89b37f2 100644
--- a/src/components/layout/Section.svelte
+++ b/src/components/layout/Section.svelte
@@ -17,12 +17,11 @@
const base =
'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 justifyClass = contentStart ? 'justify-start' : 'justify-center';
const withJustify = `${base} ${justifyClass}`;
if (from && to) {
tailwindClasses = `${withJustify} bg-gradient-${direction} ${from} ${to} ${via}`;
diff --git a/src/lib/format.ts b/src/lib/format.ts
new file mode 100644
index 0000000..78139bb
--- /dev/null
+++ b/src/lib/format.ts
@@ -0,0 +1,13 @@
+/**
+ * Get initials from a name (e.g. "Jane Doe" → "JD", "Mary Jane Watson" → "MJW").
+ * Uses first letter of up to 3 words. Safe for null/undefined/empty.
+ */
+export function getInitials(name: string | null | undefined): string {
+ if (name == null || typeof name !== 'string') return '';
+ const words = name.trim().split(/\s+/).filter(Boolean);
+ if (words.length === 0) return '';
+ return words
+ .slice(0, 3)
+ .map((w) => w.charAt(0).toUpperCase())
+ .join('');
+}
diff --git a/src/routes/council/+page.server.ts b/src/routes/council/+page.server.ts
index fa562b4..7530333 100644
--- a/src/routes/council/+page.server.ts
+++ b/src/routes/council/+page.server.ts
@@ -10,7 +10,7 @@ const councilQuery = `{
email,
position,
positionDescription,
- "image": image.asset->url+"?h=300&fm=webp",
+ "image": image.asset->url+"?h=360&fm=webp",
yearProgram
},
"councilGoofyPic": *[_type == "homepage"]{
@@ -18,7 +18,7 @@ const councilQuery = `{
}[0]
}`;
-export const load = async ({ url }) => {
+export const load = async ({ url }: { url: URL }) => {
const {
members,
councilGoofyPic
diff --git a/src/routes/council/+page.svelte b/src/routes/council/+page.svelte
index 9755582..6f20632 100644
--- a/src/routes/council/+page.svelte
+++ b/src/routes/council/+page.svelte
@@ -2,8 +2,8 @@
import CouncilCardPopUp from 'components/council/CouncilCardPopUp.svelte';
import Section from 'components/layout/Section.svelte';
import CardCouncil from 'components/council/CouncilCard.svelte';
+ import Link from 'components/Link.svelte';
import type { CouncilMember } from '$lib/schemas';
- import { fly } from 'svelte/transition';
import SeoMetaTags from 'components/layout/SeoMetaTags.svelte';
import { onMount } from 'svelte';
import { tick } from 'svelte';
@@ -12,7 +12,6 @@
const years = ['U4', 'U3', 'U2', 'U1', 'U0'];
- // Get members by 3 main categories (reactive from data)
let president = $derived(
data.members.filter((member: CouncilMember) => member.position.includes('President'))[0]
);
@@ -48,6 +47,11 @@
if (e.key === 'Escape') closeModal();
}
+ function getYearFromPosition(position: string): string | undefined {
+ const match = position.match(/\b(U[0-4])\b/);
+ return match?.[1];
+ }
+
onMount(() => {
function onKeyDown(e: KeyboardEvent) {
if (e.key === 'Escape') closeModal();
@@ -75,82 +79,126 @@
canonical={data.canonical}
/>
-{name}
-{position}
+ +
+
- -
{name}
+{position}
+ + {#if positionDescription} +
+
+ {/if}
- + {positionDescription} +
- -
- {#if positionDescription}
-
+ {/if}
-
- {/if}
- {#if email}
- - {positionDescription} -
-
-
-
- {email}
-
-
- {/if}
+ {#if email}
+
+
+
+ {email}
+
-
-
-
+Meet the council!
-
+
+
Meet the ECSESS Council
-- Our Student Council -
- - {#if president} -
- handleViewProfile(president)}
+
+
-
- {/if}
+
-
-
+
+ {/if}
+
+
+
+
+
+
+
+
+
+
+
+
{#if selectedMember}
-
- Vice Presidents -
-
- {#each vps as vp}
- handleViewProfile(vp)}
- />
- {/each}
-
- - Year Representatives -
-
- {#each ureps as urep}
- handleViewProfile(urep)}
- />
- {/each}
-
+
+ {#if president}
+
+
+
+ + President +
+ +
+ handleViewProfile(president)}
+ featured
+ />
+
+
+
+
+ + Vice Presidents +
+ +
+ {#each vps as vp}
+
+
+ handleViewProfile(vp)}
+ />
+
+ {/each}
+
+
+
+ + Year Representatives +
+ +
+ {#each ureps as urep}
+
+
+ handleViewProfile(urep)}
+ tag={getYearFromPosition(urep.position)}
+ />
+
+ {/each}
+ + Like what you see? + + Join ECSESS and be part of the fun → + +
+ e.target === e.currentTarget && closeModal()}
onkeydown={onBackdropKeydown}
>
-
+