Skip to content

Commit

Permalink
Merge pull request #8 from esc-chula/techmonth
Browse files Browse the repository at this point in the history
Techmonth
  • Loading branch information
ebonian authored Oct 16, 2024
2 parents 7895355 + c1e5ce1 commit 59496d0
Show file tree
Hide file tree
Showing 14 changed files with 569 additions and 19 deletions.
48 changes: 41 additions & 7 deletions src/app/techmonth/_components/section-schedule.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,50 @@
export default function ScheduleSection(): JSX.Element {
import { getEvents } from "@/server/actions/techmonth";

export default async function ScheduleSection(): Promise<JSX.Element> {
const events = await getEvents();

return (
<div
id="schedule"
className="min-h-96 w-full max-w-screen-xl px-8 py-16 font-tiny5 md:px-16 xl:px-4"
className="min-h-screen w-full max-w-screen-xl space-y-8 px-8 py-28 font-tiny5 md:px-16 xl:px-4"
>
<h2 className="text-center text-3xl uppercase md:text-5xl lg:text-left lg:text-6xl">
<h2 className="text-center text-3xl uppercase md:text-5xl lg:text-left lg:text-8xl">
Sche
<span className="text-techmonth-green">dule</span>
<span className="text-techmonth-magenta">dule</span>
</h2>
<p className="grid w-full place-items-center text-xl uppercase md:text-3xl lg:text-4xl">
Coming Soon...
</p>
<div className="flex w-full flex-col gap-4">
{events.map((event, index) => (
<div
key={index}
className="flex w-full items-center justify-between border-4 border-techmonth-white bg-techmonth-white/10 p-5"
>
<div>
<h3 className="text-5xl">{event.name}</h3>
<p className="font-ibm-plex-sans-thai">
Powered by {event.club || "TECH ESC"}
</p>
</div>
<div className="text-right">
<p className="font-press-start-2p text-lg">
{/* Monday, 1st November 2021 */}
{new Date(event.date).toLocaleDateString("en-US", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric",
})}
</p>
<p className="font-press-start-2p">
{/* 10:00 - 12:00 */}
{new Date(event.date).toLocaleTimeString("en-US", {
hour: "numeric",
minute: "2-digit",
})}{" "}
</p>
</div>
</div>
))}
</div>
</div>
);
}
2 changes: 1 addition & 1 deletion src/app/techmonth/_components/section-techmonth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export default function TechMonthSection(): JSX.Element {
return (
<div
id="techmonth"
className="flex min-h-screen w-full max-w-screen-xl flex-col gap-40 px-8 pt-16 md:px-16 xl:px-4"
className="flex min-h-screen w-full max-w-screen-xl flex-col gap-40 px-8 py-28 md:px-16 xl:px-4"
>
<article>
<h2 className="max-w-4xl text-center font-ibm-plex-sans-thai text-5xl leading-normal md:text-7xl lg:text-left lg:text-8xl">
Expand Down
56 changes: 47 additions & 9 deletions src/app/techmonth/login/page.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,64 @@
"use client";

import { login } from "@/server/actions/techmonth";
import { useRouter, useSearchParams } from "next/navigation";
import { useState } from "react";

export default function LoginPage() {
const router = useRouter();
const searchParams = useSearchParams();

const callbackUrl = searchParams.get("callbackUrl");

const [loading, setLoading] = useState(false);

const formHandler = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();

const formData = new FormData(e.target as HTMLFormElement);
const studentId = formData.get("studentId");
if (!studentId) {

const regex = /^6\d{7}21$/;

if (!regex.test(studentId as string)) {
alert("Invalid student ID");
return;
}
setLoading(true);

await login(studentId as string);
if (callbackUrl) {
router.push(callbackUrl);
} else {
router.push("/techmonth/stamps");
}
};

return (
<form onSubmit={formHandler}>
<input
name="studentId"
placeholder="Fill your student ID"
className="text-black"
/>
<button type="submit">login</button>
</form>
<main className="flex w-full flex-col items-center">
<div className="flex min-h-screen w-full max-w-screen-xl flex-col justify-center space-y-8 px-8 py-28 font-tiny5 md:px-16 xl:px-4">
<h2 className="text-left text-6xl uppercase md:text-5xl lg:text-8xl">
<span className="text-techmonth-green">LOG</span>
IN
</h2>
<form
onSubmit={formHandler}
className="flex flex-col items-start justify-between"
>
<input
name="studentId"
placeholder="Fill your student ID"
className="h-16 w-full border-4 border-techmonth-white bg-transparent p-4 text-2xl text-techmonth-white outline-none placeholder:text-techmonth-white lg:w-1/2"
/>
<button
type="submit"
className="mt-40 bg-techmonth-yellow px-6 py-2 text-3xl text-techmonth-black duration-200 hover:translate-x-3"
disabled={loading}
>
{loading ? `LOADING...` : `GO gO Go ->`}
</button>
</form>
</div>
</main>
);
}
110 changes: 110 additions & 0 deletions src/app/techmonth/stamps/_components/add_modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
"use client";

import { addStamp } from "@/server/actions/techmonth";
import { useRouter } from "next/navigation";
import { createContext, useContext, useState } from "react";

interface ModalContextProps {
open: boolean;
setOpen: (open: boolean) => void;
}

const ModalContext = createContext<ModalContextProps>({
open: false,
setOpen: () => null,
});

export function Modal({ children }: { children: React.ReactNode }) {
const [open, setOpen] = useState(false);

return (
<ModalContext.Provider
value={{
open,
setOpen,
}}
>
{children}
</ModalContext.Provider>
);
}

interface TriggerModalProps
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
children: React.ReactNode;
}

export function TriggerModal(props: TriggerModalProps) {
const { setOpen } = useContext(ModalContext);

return (
<button type="button" onClick={() => setOpen(true)} {...props}>
{props.children}
</button>
);
}

export function ModalContent(): JSX.Element {
const router = useRouter();
const { open, setOpen } = useContext(ModalContext);
const [loading, setLoading] = useState(false);

const formHandler = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();

const formData = new FormData(e.target as HTMLFormElement);
const eventId = formData.get("eventId");

if (!eventId) {
alert("Invalid event ID");
return;
}

setLoading(true);

await addStamp(eventId as string)
.then(() => {
router.refresh();
setOpen(false);
setLoading(false);
})
.catch((err) => {
alert(err);
setLoading(false);
});
};

return (
<div
className={`fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50`}
style={{
display: open ? "flex" : "none",
}}
onClick={() => setOpen(false)}
>
<div
className={`flex h-80 w-full max-w-screen-sm flex-col gap-16 bg-techmonth-black px-4 pt-10 font-tiny5`}
onClick={(e) => e.stopPropagation()}
>
<h3 className="text-center text-5xl">ADD STAMP</h3>
<form
onSubmit={formHandler}
className="flex items-center justify-center gap-4"
>
<input
name="eventId"
placeholder="Fill in the event ID"
className="h-16 w-full border-4 border-techmonth-white bg-transparent p-4 text-2xl text-techmonth-white outline-none placeholder:text-techmonth-white lg:w-1/2"
/>
<button
type="submit"
disabled={loading}
className="bg-techmonth-yellow px-6 py-2 text-3xl text-techmonth-black duration-200 hover:translate-x-3"
>
{loading ? "loaAding..." : "ADD"}
</button>
</form>
</div>
</div>
);
}
18 changes: 18 additions & 0 deletions src/app/techmonth/stamps/_components/header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"use client";

import { logout } from "@/server/actions/techmonth";

export default function Header({ studentId }: { studentId: string }) {
return (
<div className="flex w-full items-center justify-between text-2xl lg:text-3xl">
<p>{studentId}</p>
<button
onClick={() => {
logout().catch(console.error);
}}
>
logout
</button>
</div>
);
}
31 changes: 31 additions & 0 deletions src/app/techmonth/stamps/_components/stamp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import Image from "next/image";
import type { Event } from "@/types/techmonth";

export default function Stamp({
stamp,
}: {
stamp: {
event: Event | undefined;
id: number;
studentId: string;
eventId: string;
};
}) {
return (
<div className="h-full w-full -rotate-[20deg] rounded-full bg-[#474747] pt-3 text-center">
<div className="relative h-3/4 w-full">
<Image
src={
stamp.event?.club
? `/techmonth/clubs/${stamp.event?.club}.png`
: "/techmonth/tech_logo.svg"
}
alt={stamp.eventId}
fill
className="object-contain"
/>
</div>
<div className="h-20">{`<${stamp.eventId}>`}</div>
</div>
);
}
Loading

0 comments on commit 59496d0

Please sign in to comment.