Redesign some components of the council page

This commit is contained in:
2026-02-03 10:17:54 -05:00
parent a3908745d7
commit 7ad2bfba10
5 changed files with 186 additions and 95 deletions

View File

@@ -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<CouncilMember | null>(null);
let modalRef = $state<HTMLDivElement | null>(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 = '';
};
});
</script>
<SeoMetaTags
@@ -45,36 +75,41 @@
canonical={data.canonical}
/>
<Section from="from-ecsess-black" to="to-ecsess-black" via="via-ecsess-800" direction="to-b">
<div class="flex flex-col place-items-center">
<p class="page-title">Meet the council!</p>
<Section from="from-ecsess-black" to="to-ecsess-black" via="via-ecsess-800" direction="to-b" contentStart>
<div class="flex w-full max-w-4xl flex-col items-center gap-6 py-6 text-left lg:max-w-6xl">
<p class="page-title text-balance">Meet the council!</p>
<img
src={data.councilGoofyPic.url}
alt="ECSESS Council, but we are goofy"
class="ring-ecsess-400 shadow-ecsess-black hover:ring-ecsess-300 mb-8 rounded-md shadow-2xl ring-4 transition-all lg:w-[90%]"
class="mb-8 rounded-xl shadow-2xl ring-2 ring-ecsess-400/50 shadow-black/40 transition-all hover:ring-ecsess-300/60 hover:shadow-ecsess-900/30 lg:w-[90%]"
transition:fly
/>
</div>
<h1 class="border-b-ecsess-300 w-full border-b-2 lg:w-1/2">Our Student Council!</h1>
<h1 class="border-b-ecsess-300/80 w-full max-w-6xl border-b-2 pb-3 text-center font-semibold tracking-tight">
Our Student Council
</h1>
<div>
<CardCouncil
name={president.name}
position={president.position}
image={president.image}
onViewProfile={() => handleViewProfile(president!)}
/>
</div>
{#if president}
<div class="w-full max-w-2xl lg:max-w-3xl">
<CardCouncil
name={president.name}
position={president.position}
image={president.image}
onViewProfile={() => handleViewProfile(president)}
/>
</div>
{/if}
<div class="grid place-items-center">
<div class="grid w-full max-w-6xl place-items-center gap-6">
<h2
class="border-b-ecsess-300 w-full place-self-center-safe border-b-2 border-dashed md:w-1/2 lg:w-1/3"
class="border-b-ecsess-300/70 w-full border-b-2 border-dashed pb-2 text-center text-lg font-semibold tracking-tight"
>
Vice Presidents
</h2>
<div class="grid gap-2 py-8 md:grid-cols-2 lg:grid-cols-3">
<div
class="grid w-full grid-cols-1 gap-5 py-4 sm:gap-6 md:grid-cols-2 md:gap-6 lg:gap-8 xl:gap-10"
>
{#each vps as vp}
<CardCouncil
name={vp.name}
@@ -85,11 +120,13 @@
{/each}
</div>
<h2
class="border-b-ecsess-300 w-full place-self-center-safe border-b-2 border-dashed md:w-1/2 lg:w-1/3"
class="border-b-ecsess-300/70 w-full border-b-2 border-dashed pb-2 text-center text-lg font-semibold tracking-tight"
>
Year Representative
Year Representatives
</h2>
<div class="grid gap-2 py-8 md:grid-cols-2 lg:grid-cols-3">
<div
class="grid w-full grid-cols-1 gap-5 py-4 sm:gap-6 md:grid-cols-2 md:gap-6 lg:gap-8 xl:gap-10"
>
{#each ureps as urep}
<CardCouncil
name={urep.name}
@@ -100,18 +137,30 @@
{/each}
</div>
</div>
{#if selectedMember}
<div class="fixed inset-0 z-10 flex flex-col items-center justify-center bg-black/70">
<CouncilCardPopUp
name={selectedMember.name}
position={selectedMember.position}
email={selectedMember.email}
positionDescription={selectedMember.positionDescription}
yearProgram={selectedMember.yearProgram}
image={selectedMember.image}
/>
<div transition:fly>
<Button onclick={() => (selectedMember = null)}>Close</Button>
<!-- Modal: backdrop with blur, click-outside and Escape to close -->
<div
bind:this={modalRef}
tabindex="-1"
class="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/60 backdrop-blur-sm outline-none overflow-y-auto"
role="dialog"
aria-modal="true"
aria-labelledby="popup-title"
onclick={(e) => e.target === e.currentTarget && closeModal()}
onkeydown={onBackdropKeydown}
>
<div class="relative flex max-h-[90vh] w-full max-w-4xl flex-col items-center justify-center overflow-hidden">
<CouncilCardPopUp
id="popup-title"
name={selectedMember.name}
position={selectedMember.position}
email={selectedMember.email}
positionDescription={selectedMember.positionDescription}
yearProgram={selectedMember.yearProgram}
image={selectedMember.image}
onClose={closeModal}
/>
</div>
</div>
{/if}