Skip to content

Commit 5eaf594

Browse files
JoshXL23Joshua Gonsalvescybercoder-naj
authored
feat(landing): schedule component (#126)
Co-authored-by: Joshua Gonsalves <[email protected]> Co-authored-by: Nishant Aanjaney Jalan <[email protected]>
1 parent 2cf2031 commit 5eaf594

38 files changed

+1184
-24
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ You should create a PR **as soon as** you create a branch.
8282
#### Code contributors
8383

8484
- [@Harini-Sritharar](https://github.com/Harini-Sritharar)
85+
- [@JoshXL23 | Joshua Gonsalves](https://github.com/JoshXL23)
8586

8687
## License
8788

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { Result } from 'typescript-result';
2+
import type { Event as ICEvent } from '~~/shared/types';
3+
4+
export default function () {
5+
const client = useHttpClient();
6+
7+
const getEvents = async (): Promise<Result<ICEvent[], Error>> => {
8+
return Result.try(async () => {
9+
const res = await client.event.$get();
10+
if (!res.ok) {
11+
const message = await res.text();
12+
throw new Error('Server errored when fetching events:' + message);
13+
}
14+
15+
const eventsJson = await res.json();
16+
return eventsJson.map(event => {
17+
return {
18+
...event,
19+
startsAt: new Date(event.startsAt),
20+
endsAt: event.endsAt ? new Date(event.endsAt) : undefined
21+
};
22+
});
23+
});
24+
};
25+
26+
return {
27+
getEvents
28+
};
29+
}
Lines changed: 12 additions & 0 deletions
Loading

packages/ui25/components/IC/NavBar.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<template>
2-
<nav class="relative flex justify-between px-5 lg:overflow-hidden">
2+
<nav
3+
class="sticky top-0 z-50 flex justify-between bg-black px-5 lg:overflow-hidden">
34
<img src="@ui25/assets/logo-white.svg" class="my-2" />
45

56
<ICHamburger

packages/www/assets/svgs/clock.svg

Lines changed: 27 additions & 0 deletions
Loading
Lines changed: 19 additions & 0 deletions
Loading
Lines changed: 21 additions & 0 deletions
Loading

packages/www/components/Section/About.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66

77
<div class="max-w-[512px]">
88
<ICWindow name="about.txt" background="bg-cream-ic">
9-
<div class="flex gap-4 text-black">
9+
<div class="relative flex gap-4 text-black">
1010
<div
1111
class="[&_span]:text-blue-ic flex self-start text-lg [&_span]:font-bold">
12-
<img src="@ui25/assets/alien.svg" class="absolute" />
12+
<img src="@ui25/assets/alien.svg" class="absolute left-0 top-0" />
1313
<div
1414
v-for="col in ['bg-blue-ic', 'bg-yellow-ic', 'bg-red-ic']"
1515
class="ml-1 w-8"
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
<template>
2+
<section
3+
id="schedule"
4+
class="relative mx-auto flex max-w-[80%] flex-col justify-center px-5 sm:flex-row">
5+
<div class="absolute top-0">
6+
<div id="schedule-1"></div>
7+
<div id="schedule-2"></div>
8+
</div>
9+
<div
10+
class="font-ichack sticky top-[60px] z-10 ml-6 w-full self-start bg-black/50 backdrop-blur-sm sm:top-[80px] sm:ml-0 sm:w-auto">
11+
<h1 class="text-4xl uppercase">Schedule</h1>
12+
<div class="mt-2 flex gap-4 sm:justify-end">
13+
<a
14+
href="#schedule-1"
15+
:class="`font-ichack z-20 px-1 py-2 text-xl uppercase leading-9 sm:text-2xl ${day == 1 ? 'bg-blue-ic' : ''}`"
16+
@click="() => (day = 1)">
17+
1st
18+
</a>
19+
<a
20+
href="#schedule-2"
21+
:class="`font-ichack px-1 py-2 text-xl uppercase leading-9 sm:text-2xl ${day == 2 ? 'bg-red-ic' : ''}`"
22+
@click="() => (day = 2)">
23+
2nd
24+
</a>
25+
</div>
26+
</div>
27+
<div
28+
class="relative hidden w-8 bg-[url(~/assets/svgs/line-divider.svg)] bg-center bg-repeat-y p-8 sm:block"></div>
29+
<div
30+
class="absolute left-0 h-full w-6 bg-[url(~/assets/svgs/line-divider.svg)] bg-center bg-repeat-y sm:hidden"></div>
31+
<!-- RHS details -->
32+
33+
<div
34+
class="relative ml-6 inline-block max-lg:mt-8 max-sm:z-0 lg:ml-7 lg:w-1/2">
35+
<div
36+
v-for="(event, index) in schedule"
37+
:key="event.title"
38+
class="mb-16 flex flex-col items-start gap-4 sm:mb-32"
39+
ref="refs">
40+
<h2 :class="`font-ichack ${nextTxtColor(index)} text-4xl sm:text-6xl`">
41+
{{ format(event.startsAt, 'HH:mm') }}
42+
<!-- prettier-ignore -->
43+
<span v-if="event.endsAt"> - {{ format(event.endsAt, 'HH:mm') }}</span>
44+
</h2>
45+
<h2 class="text-xl font-extrabold capitalize text-white sm:text-4xl">
46+
{{ event.title }}
47+
</h2>
48+
<p class="text-2xl font-normal lowercase leading-snug text-white">
49+
{{ event.description }}
50+
</p>
51+
<div
52+
v-for="(loc, loc_index) in event?.locations ?? []"
53+
:key="loc"
54+
:class="`flex ${nextColor(index + loc_index)} w-full items-center justify-start sm:w-[80%]`">
55+
<img
56+
src="@ui25/assets/location-sign.svg"
57+
alt="location"
58+
class="m-4" />
59+
<p
60+
class="pr-4 text-lg font-extrabold leading-[15px] text-white sm:text-2xl">
61+
{{ locationToFullName[loc] }}
62+
</p>
63+
</div>
64+
<img
65+
:src="getImage(event)"
66+
:alt="event.locations[0]"
67+
class="sm:w-[80%]" />
68+
</div>
69+
</div>
70+
</section>
71+
</template>
72+
73+
<script setup lang="ts">
74+
import type { EventLocation, Event as ICEvent } from '#shared/types';
75+
import { filename } from 'pathe/utils';
76+
import { format } from 'date-fns';
77+
78+
type Schedule = [ICEvent[], ICEvent[]];
79+
80+
const glob = import.meta.glob('~/public/locations/*.jpeg', {
81+
eager: true
82+
});
83+
84+
const images = Object.fromEntries(
85+
Object.entries(glob).map(([key, value]) => [
86+
filename(key),
87+
// @ts-ignore - default is not in the type
88+
value.default
89+
])
90+
) as Record<EventLocation, string>;
91+
92+
const { getEvents } = useEvents();
93+
const { data: schedules } = useAsyncData<Schedule>('get_schedule', async () => {
94+
const eventRes = await getEvents();
95+
const events: ICEvent[] = eventRes.getOrThrow();
96+
return [
97+
events.filter(e => e.startsAt.getUTCDate() === 1),
98+
events.filter(e => e.startsAt.getUTCDate() === 2)
99+
];
100+
});
101+
102+
const day = ref<1 | 2>(1);
103+
const schedule = computed<ICEvent[]>(() => {
104+
if (!schedules.value) return [];
105+
return day.value === 1 ? schedules.value[0] : schedules.value[1];
106+
});
107+
108+
function nextTxtColor(index: number) {
109+
switch (index % 3) {
110+
case 0:
111+
return 'text-blue-ic';
112+
case 1:
113+
return 'text-red-ic';
114+
case 2:
115+
return 'text-yellow-ic';
116+
default:
117+
throw new Error('Invalid index');
118+
}
119+
}
120+
121+
function nextColor(index: number) {
122+
switch (index % 3) {
123+
case 0:
124+
return 'bg-blue-ic';
125+
case 1:
126+
return 'bg-red-ic';
127+
case 2:
128+
return 'bg-yellow-ic';
129+
default:
130+
throw new Error('Invalid index');
131+
}
132+
}
133+
134+
function getImage(event: ICEvent) {
135+
const loc = !event.locations.length ? 'HXLY' : event.locations[0]!;
136+
return images[loc];
137+
}
138+
139+
const locationToFullName: Record<EventLocation, string> = {
140+
HXLY: 'HUXLEY BUILDING',
141+
JCR: 'JUNIOR COMMON ROOM',
142+
SCR: 'SENIOR COMMON ROOM',
143+
QTR: "QUEEN'S TOWER ROOMS",
144+
QLWN: "QUEEN'S LAWN",
145+
HBAR: 'ħ-bar',
146+
ICME: 'IMPERIAL COLLEGE MAIN ENTRANCE',
147+
GRHL: 'GREAT HALL',
148+
SF: 'SHERFIELD BUILDING',
149+
CLR: 'HUXLEY CLORE THEATRE',
150+
H308: 'HUXLEY LECTURE THEATRE 308',
151+
H311: 'HUXLEY LECTURE THEATRE 311',
152+
H340: 'HUXLEY LECTURE THEATRE 340',
153+
HF: 'HUXLEY FOYER'
154+
};
155+
</script>

packages/www/nuxt.config.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ export default defineNuxtConfig({
22
app: {
33
rootAttrs: {
44
id: 'app',
5-
style:
6-
'overflow-x: hidden; min-height: 100svh; background: black; color: white;'
5+
style: `overflow-x: hidden; height: 100svh; background: black; color: white;
6+
position: relative; width: 100vw; scroll-padding-top: 1.5rem; overflow-x: hidden;
7+
overflow-y: visible; scroll-behavior: smooth;`
78
},
89
head: {
910
titleTemplate: '%s'

packages/www/pages/index.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
<DividerOne />
88
<SectionAbout class="py-16" />
99
<SectionTicket class="py-16" />
10+
<SectionSchedule class="py-8" />
1011
<SectionSponsors class="py-16" />
1112
<SectionTeam class="py-16" />
1213
<SectionFAQ class="py-16" />
140 KB
Loading
178 KB
Loading
162 KB
Loading
162 KB
Loading
133 KB
Loading
72.3 KB
Loading

packages/www/public/locations/HF.jpeg

143 KB
Loading
188 KB
Loading
113 KB
Loading
124 KB
Loading
220 KB
Loading

packages/www/public/locations/MB.jpeg

128 KB
Loading
182 KB
Loading
114 KB
Loading
123 KB
Loading

packages/www/public/locations/SF.jpeg

92.4 KB
Loading

schemas/0000_init.sql

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ CREATE TYPE "public"."user_roles" AS ENUM('god', 'admin', 'hacker', 'volunteer')
33
CREATE TYPE "public"."gender_types" AS ENUM('Male', 'Female', 'Non-binary', 'Other', 'N/A');--> statement-breakpoint
44
CREATE TYPE "public"."t_shirt_sizes" AS ENUM('S', 'M', 'L', 'XL', '2XL');--> statement-breakpoint
55
CREATE TYPE "public"."year_of_study" AS ENUM('Undergraduate Year 1', 'Undergraduate Year 2', 'Undergraduate Year 3', 'Undergraduate Year 4', 'Undergraduate Year 5', 'Undergraduate Year 6', 'Graduated', 'Postgraduate');--> statement-breakpoint
6+
CREATE TYPE "public"."location_enum" AS ENUM('HXLY', 'JCR', 'SCR', 'QTR', 'QLWN', 'HBAR', 'ICME', 'GRHL', 'SF', 'HF', 'H308', 'H311', 'H340', 'CLR');--> statement-breakpoint
67
CREATE TABLE "announcements" (
78
"id" serial PRIMARY KEY NOT NULL,
89
"title" text NOT NULL,
@@ -67,7 +68,8 @@ CREATE TABLE "events" (
6768
"description" text NOT NULL,
6869
"starts_at" timestamp NOT NULL,
6970
"ends_at" timestamp,
70-
"public" boolean NOT NULL
71+
"public" boolean NOT NULL,
72+
"locations" "location_enum"[] NOT NULL
7173
);
7274
--> statement-breakpoint
7375
CREATE TABLE "profiles" (

schemas/0001_schedule.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
CREATE TYPE "public"."location_enum" AS ENUM('HXLY', 'JCR', 'SCR', 'QTR', 'QLWN', 'HBAR', 'ICME', 'GRHL', 'SF', 'HF', 'H308', 'H311', 'H340', 'CLR');--> statement-breakpoint
2+
ALTER TABLE "events" ADD COLUMN "locations" "location_enum"[] NOT NULL;

0 commit comments

Comments
 (0)