diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index 9412a8f4..dac2f324 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -1,6 +1,19 @@ import { Routes } from '@angular/router'; import { HomeComponent } from 'pages/home/home.component'; +export enum SiteRoute { + ReadMe = '/readme', + Officers = '/officers', + Committees = '/committees', + Affiliates = '/affiliates', + CommonRoom = '/common-room', + Events = '/events', + EventsArchives = '/events/archives', + Elections = '/elections', + ElectionsSchedule = '/elections/schedule', + ElectionsSpeeches = '/elections/speeches' +} + /** * Formats the title on the web browser's tab/window. * @param pageTitle - Title of the page @@ -66,7 +79,7 @@ export const routes: Routes = [ } }, { - path: 'event-archives', + path: 'events/archives', loadComponent: () => import('pages/event-archives/event-archives.component').then(m => m.EventArchivesComponent), title: makeTitle('Event Archives'), @@ -84,6 +97,28 @@ export const routes: Routes = [ description: 'Learn about the responsibilities of our executives and how you can become one.' } }, + { + path: 'elections/schedule', + loadComponent: () => + import('pages/elections/upcoming/elections-schedule.component').then( + m => m.ElectionsScheduleComponent + ), + title: makeTitle('Elections'), + data: { + description: 'View upcoming, current, and past elections.' + } + }, + { + path: 'elections/speeches', + loadComponent: () => + import('./pages/elections/election-speeches/election-speeches.component').then( + m => m.ElectionSpeechesComponent + ), + title: makeTitle('Elections'), + data: { + description: 'Learn more about the candidates who want to make our society a better place.' + } + }, { path: '', component: HomeComponent, title: 'Computing Science Student Society' }, // 404 will go down there { diff --git a/src/app/components/nav-bar/nav-bar.component.html b/src/app/components/nav-bar/nav-bar.component.html index dcda2676..0ef44516 100644 --- a/src/app/components/nav-bar/nav-bar.component.html +++ b/src/app/components/nav-bar/nav-bar.component.html @@ -37,17 +37,18 @@

SFU CSSS

[routerLinkActiveOptions]="{ exact: true }" > @if (subItem.route) { + {{ subItem.label }} } @else { + {{ subItem.label }} diff --git a/src/app/components/nav-bar/nav-entries.ts b/src/app/components/nav-bar/nav-entries.ts index ae930274..80be0d08 100644 --- a/src/app/components/nav-bar/nav-entries.ts +++ b/src/app/components/nav-bar/nav-entries.ts @@ -4,9 +4,9 @@ import { faBook, faChevronRight, faFile, - faRoadBarrier, faUpRightFromSquare } from '@fortawesome/free-solid-svg-icons'; +import { SiteRoute } from 'app/app.routes'; import { EXTERNAL_LINKS } from 'components/url/links.data'; export interface NavItem extends CodeListItem { @@ -27,31 +27,31 @@ export const NAVBAR_ENTRIES: NavItem[] = [ key: 'readme', label: 'README', icon: faFile, - route: '/readme' + route: SiteRoute.ReadMe }, { key: 'officers', label: 'Officers', icon: faFile, - route: '/officers' + route: SiteRoute.Officers }, { key: 'committees', label: 'Committees', icon: faFile, - route: '/committees' + route: SiteRoute.Committees }, { key: 'common-room', label: 'Common Room', icon: faFile, - route: '/common-room' + route: SiteRoute.CommonRoom }, { key: 'affiliates', label: 'Affiliates', icon: faFile, - route: '/affiliates' + route: SiteRoute.Affiliates } ] }, @@ -65,7 +65,7 @@ export const NAVBAR_ENTRIES: NavItem[] = [ key: 'events.about', label: 'About', icon: faFile, - route: '/events' + route: SiteRoute.Events }, { key: 'events.tech-fair', @@ -95,7 +95,7 @@ export const NAVBAR_ENTRIES: NavItem[] = [ key: 'events.archives', label: 'Archives', icon: faBook, - route: '/event-archives' + route: SiteRoute.EventsArchives } ] }, @@ -109,21 +109,19 @@ export const NAVBAR_ENTRIES: NavItem[] = [ key: 'elections.about', label: 'About', icon: faFile, - route: '/elections' + route: SiteRoute.Elections }, { - key: 'elections.upcoming', - label: 'Upcoming', - icon: faRoadBarrier, - route: '/upcoming-elections', - isDisabled: true + key: 'elections.schedule', + label: 'Schedule', + icon: faFile, + route: SiteRoute.ElectionsSchedule }, { key: 'elections.speeches', label: 'Speeches', - icon: faRoadBarrier, - route: '/speeches', - isDisabled: true + icon: faFile, + route: SiteRoute.ElectionsSpeeches } ] }, diff --git a/src/app/pages/elections/election-speeches/election-speeches.component.html b/src/app/pages/elections/election-speeches/election-speeches.component.html new file mode 100644 index 00000000..95d8c9db --- /dev/null +++ b/src/app/pages/elections/election-speeches/election-speeches.component.html @@ -0,0 +1,15 @@ + +
+

Nominees

+

Learn more about our candidates and what they will do for our society.

+
+

Director of Multi-Media

+ @for (nominee of nominees; track $index) { +
+

> {{ nominee.name }}

+

{{ nominee.speech }}

+
+ } +
+
+
diff --git a/src/app/pages/elections/election-speeches/election-speeches.component.scss b/src/app/pages/elections/election-speeches/election-speeches.component.scss new file mode 100644 index 00000000..0c45809a --- /dev/null +++ b/src/app/pages/elections/election-speeches/election-speeches.component.scss @@ -0,0 +1,22 @@ +@use 'globals' as g; + +.nominees { + display: flex; + flex-direction: column; + gap: 2rem; +} + +.nominee { + border: 1px black solid; + padding: 1rem; + box-shadow: 10px 10px 5px black; + + &__name { + margin: 0; + color: g.$accent2; + } + + &__speech { + white-space: pre-line; + } +} diff --git a/src/app/pages/elections/election-speeches/election-speeches.component.spec.ts b/src/app/pages/elections/election-speeches/election-speeches.component.spec.ts new file mode 100644 index 00000000..534b56db --- /dev/null +++ b/src/app/pages/elections/election-speeches/election-speeches.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ElectionSpeechesComponent } from './election-speeches.component'; + +describe('ElectionSpeechesComponent', () => { + let component: ElectionSpeechesComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ElectionSpeechesComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ElectionSpeechesComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/pages/elections/election-speeches/election-speeches.component.ts b/src/app/pages/elections/election-speeches/election-speeches.component.ts new file mode 100644 index 00000000..28b67d0c --- /dev/null +++ b/src/app/pages/elections/election-speeches/election-speeches.component.ts @@ -0,0 +1,46 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { ArticleComponent } from '@csss-code/article/article.component'; + +interface Nominee { + name: string; + speech: string; +} + +@Component({ + selector: 'cs-election-speeches', + imports: [ArticleComponent], + templateUrl: './election-speeches.component.html', + styleUrl: './election-speeches.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ElectionSpeechesComponent { + // FIXME: This was hardcoded because Jon had to get this page up ASAP + nominees: Nominee[] = [ + { + name: 'Sia Garg', + speech: `I’ve already been helping out with CSSS this term — I made two of our Instagram posts for past events, I’ve sat in on multiple meetings, and I’ve been happy to jump in whenever help was needed. Doing that has shown me how much work goes on behind the scenes, and it made me want to be even more involved. + +I’m running because I care about making our events look good, feel inviting, and reach more people. Good visuals and clear posts really do make a difference, and I want to help us be more consistent and creative with the way we present the CSSS. + +If I get this role, I’ll keep doing what I’ve been doing: showing up, helping out, and making content that they're happy to put out there. Thanks for considering me!` + }, + { + name: 'Heather Nguyen', + speech: `Hello all! My name is Heather and I'm a 3rd year majoring in Interactive Arts and Technology. My interests lie in the creation of fun and exciting, colorful designs in everyday life tech products, hence my concentration of Visual, UX/UI and Product Design. + +In SIAT, we value the significance of creativity and innovation through our thoughtfully crafted designs. I think I similarly share these objectives with the CS student community, and I want to become part of our creation process for new ideas and projects. I have strong experience in creating posters/graphic assets or illustration from multiple design coordinator/director positions in the past, so I'm confident I would make a unique contribution to the community. + +To tell a little more about myself: I watch anime, am proficient in drawing cute girls and have a newfound passion for getting myself stuck in the mines (in Minecraft) :D` + }, + { + name: 'Amelia Shen', + speech: `Hi, : D My name is Amelia Shen, and I am a second-year student in the SFU-ZJU DDP for Computing Science and Finance. I can create designs and drawings using tools such as Procreate, Figma, Canva, Affinity Design, and PixelStudio. + +I was a part of the Visual Design team for Try/CATCH 2025, a tech conference for high school girls and non-binary students by WiCS. I designed a sponsorship package, logos, merchandise (tote bags, mugs, and pens), as well as Instagram and LinkedIn posts using Figma, Procreate, and PixelStudio. I also help the Developers and Systems Club as an Assistant Director of Multimedia by designing Instagram posts for events such as the CMPT 125 Final Exam Review Session and the Recruiter Rewind. + +I have a lot of experience creating media for clubs, as I was the Marketing Director for three clubs in high school: a science demonstration club, the student press club, and the business club. I would manage the Instagram accounts by uploading designed posts for events, writing captions, and posting stories. As the Marketing Director of the science demo club, I would also use a camera to film and take pictures. For the student press club, I would work with editors and authors to make posts that introduced short stories, editorials, articles, etc. For the business club, I made posts for events like case competitions and infographics on business topics. + +In the past, I had a lot of fun designing posts for these clubs. My position as Marketing Director allowed me to take a break from schoolwork and spend time drawing and designing media. There was always a new theme to plan and work on. I could add my unique style and creativity to the CSSS Instagram. Drawing has also been a favourite hobby of mine since middle school.` + } + ]; +} diff --git a/src/app/pages/elections/upcoming/elections-schedule.component.html b/src/app/pages/elections/upcoming/elections-schedule.component.html new file mode 100644 index 00000000..7c684f64 --- /dev/null +++ b/src/app/pages/elections/upcoming/elections-schedule.component.html @@ -0,0 +1,26 @@ + +
+

Elections Schedule

+

+ Tune in here to see upcoming or past elections (Soon ™)
+ * each date shown has a deadline of 11:59PM PT, unless otherwise stated +

+
+

Scheduled

+
+

Director of Multi-Media

+
+

Nominations End: December 7th, 2025

+

Election Day: December 13th, 2025

+

Duties

+
    +
  • + Create and procure media such as advertisements, promotional material, artwork, + photographs, etc., at the request of the Executive. +
  • +
  • Sit on committees as necessary, or upon request.
  • +
+
+
+
+
diff --git a/src/app/pages/elections/upcoming/elections-schedule.component.scss b/src/app/pages/elections/upcoming/elections-schedule.component.scss new file mode 100644 index 00000000..78ecf259 --- /dev/null +++ b/src/app/pages/elections/upcoming/elections-schedule.component.scss @@ -0,0 +1,14 @@ +.post { + border: 1px black solid; + padding: 1rem; + box-shadow: 10px 10px 5px black; + + &__title { + margin: 0; + } + + &__list { + list-style-position: inside; + list-style-type: circle; + } +} diff --git a/src/app/pages/elections/upcoming/elections-schedule.component.spec.ts b/src/app/pages/elections/upcoming/elections-schedule.component.spec.ts new file mode 100644 index 00000000..35825e1d --- /dev/null +++ b/src/app/pages/elections/upcoming/elections-schedule.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ElectionsScheduleComponent } from './elections-schedule.component'; + +describe('UpcomingComponent', () => { + let component: ElectionsScheduleComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ElectionsScheduleComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ElectionsScheduleComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/pages/elections/upcoming/elections-schedule.component.ts b/src/app/pages/elections/upcoming/elections-schedule.component.ts new file mode 100644 index 00000000..611ce462 --- /dev/null +++ b/src/app/pages/elections/upcoming/elections-schedule.component.ts @@ -0,0 +1,13 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { ArticleComponent } from '@csss-code/article/article.component'; + +@Component({ + selector: 'cs-upcoming', + imports: [ArticleComponent], + templateUrl: './elections-schedule.component.html', + styleUrl: './elections-schedule.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush +}) +// FIXME: Make this dynamic +// eslint-disable-next-line @typescript-eslint/no-extraneous-class +export class ElectionsScheduleComponent {} diff --git a/src/app/services/application/applications.ts b/src/app/services/application/applications.ts index ece7f86f..9106c109 100644 --- a/src/app/services/application/applications.ts +++ b/src/app/services/application/applications.ts @@ -1,3 +1,5 @@ +import { SiteRoute } from 'app/app.routes'; + /** * Interface representing an Application that is registered to run. * Each application will be run in an activity. @@ -23,14 +25,14 @@ export interface AppInfo { /** * The key of the application. * This should be unique to each activity. - * Routes should be in the form `//` or `/` to successfully launch apps. */ key: string; /** * Route to access the application. + * Routes should be in the form `//` or `/` to successfully launch apps. */ - route: string; + route: SiteRoute; } /** @@ -44,7 +46,7 @@ export const routeApplicationMap: Map = new Map([ label: 'README', activityKey: '', key: 'readme', - route: '/readme' + route: SiteRoute.ReadMe } ], [ @@ -54,7 +56,7 @@ export const routeApplicationMap: Map = new Map([ label: 'Officers', activityKey: '', key: 'officers', - route: '/officers' + route: SiteRoute.Officers } ], [ @@ -64,7 +66,7 @@ export const routeApplicationMap: Map = new Map([ label: 'Committees', activityKey: '', key: 'committees', - route: '/committees' + route: SiteRoute.Committees } ], [ @@ -74,7 +76,7 @@ export const routeApplicationMap: Map = new Map([ label: 'Affiliates', activityKey: '', key: 'affiliates', - route: '/affiliates' + route: SiteRoute.Affiliates } ], [ @@ -84,7 +86,7 @@ export const routeApplicationMap: Map = new Map([ label: 'Common Room', activityKey: '', key: 'common-room', - route: '/common-room' + route: SiteRoute.CommonRoom } ], [ @@ -94,17 +96,17 @@ export const routeApplicationMap: Map = new Map([ label: 'Events', activityKey: '', key: 'events', - route: '/events' + route: SiteRoute.Events } ], [ 6, { id: 6, - label: 'Event Archives', + label: 'Events Archives', activityKey: '', key: 'event-archives', - route: '/event-archives' + route: SiteRoute.EventsArchives } ], [ @@ -114,7 +116,27 @@ export const routeApplicationMap: Map = new Map([ label: 'Elections', activityKey: '', key: 'elections', - route: '/elections' + route: SiteRoute.Elections + } + ], + [ + 8, + { + id: 8, + label: 'Upcoming', + activityKey: '', + key: 'elections-upcoming', + route: SiteRoute.ElectionsSchedule + } + ], + [ + 9, + { + id: 9, + label: 'Speeches', + activityKey: '', + key: 'elections-speeches', + route: SiteRoute.ElectionsSpeeches } ] ]);