Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .claude/settings.local.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"permissions": {
"allow": [
"Bash(Remove-Item \"C:\\Users\\iaramako\\Documents\\GitHub\\rainbow-engineering\\src\\app\\(frontend)\\components\\HomePageSection.tsx\")"
],
"deny": [],
"ask": []
}
}
102 changes: 102 additions & 0 deletions src/app/(frontend)/components/AboutUsSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
"use client";
import Image from "next/image";
import { useEffect, useState } from "react";

type AboutUsType = {
Title: string;
Image: { url: string; alt?: string };
"About Us Description": string;
"Bullet Points Description": string;
"Bullet Points"?: { Point: string }[];
};

interface AboutUsSectionProps {
aboutus: AboutUsType;
}

export default function AboutUsSection({ aboutus }: AboutUsSectionProps) {
const [isDark, setIsDark] = useState(false);

useEffect(() => {
const saved = localStorage.getItem("darkMode") === "true";
setIsDark(saved);

const onThemeChange = (e: Event) => {
const { isDark } = (e as CustomEvent).detail ?? {};
if (typeof isDark === "boolean") setIsDark(isDark);
};
window.addEventListener("themechange", onThemeChange);

const onStorage = (e: StorageEvent) => {
if (e.key === "darkMode" && e.newValue != null) {
setIsDark(e.newValue === "true");
}
};
window.addEventListener("storage", onStorage);

return () => {
window.removeEventListener("themechange", onThemeChange);
window.removeEventListener("storage", onStorage);
};
}, []);

const sectionBg = isDark ? "#2A2342" : "#E2D6F6";
const titleColor = isDark ? "#F4EFFF" : "#5f249f";
const textColor = isDark ? "#B8ADDA" : "#334155";

return (
<div
className="mt-22 w-full py-6 px-4 sm:px-16 rounded-2xl"
style={{ backgroundColor: sectionBg }}
>
{/* background coloured block */}

<h2
className="text-3xl sm:text-5xl font-bold font-[Montserrat] mb-3 text-center p-4 sm:p-6"
style={{ color: titleColor }}
>
{aboutus.Title}
</h2>
<div className="flex flex-col sm:flex-row items-center gap-6 sm:gap-8 mb-8">
{/* code for about us image */}
<div className="relative flex flex-col items-center text-center w-full sm:w-[1200px] h-[400px] overflow-hidden rounded-xl">
<Image
src={aboutus.Image.url}
alt={aboutus.Image?.alt ?? "About Us Image"}
fill
className="object-cover"
/>
</div>

{/* code for about us text */}
<div className="flex flex-col justify-center items-center text-center w-full sm:w-500 p-4 rounded">
<p
className="text-base sm:text-lg font-[Montserrat] px-2 sm:px-7"
style={{ color: textColor }}
>
{aboutus["About Us Description"]}
<br />
<br />
{aboutus["Bullet Points Description"]}
</p>
<ul
className="list-disc text-base sm:text-lg font-[Montserrat] px-8 text-left mt-4"
style={{ color: textColor }}
>
{
aboutus["Bullet Points"]?.map(
(
item, index) => (
<li key={index}>
{item.Point}
</li>
)

)
}
</ul>
</div>
</div>
</div>
);
}
46 changes: 44 additions & 2 deletions src/app/(frontend)/components/Banner.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,56 @@
"use client";

import { useEffect, useState } from "react";
import BannerAnimation from "./BannerAnimation";

interface BannerProps {
title: string;
}

export default function Banner({ title }: BannerProps) {
//this part tracks whether dark mode is currently active
const [isDark, setIsDark] = useState(false);

useEffect(() => {
//checks what NAvbar has saved for dark mode preference
const saved = localStorage.getItem("darkMode") === "true";
setIsDark(saved);

const onThemeChange = (e: Event) => {
const { isDark } = (e as CustomEvent).detail ?? {};
if (typeof isDark === "boolean") setIsDark(isDark);
};
window.addEventListener("themechange", onThemeChange);

//in case dark mode changes in another browser/tab
const onStorage = (e: StorageEvent) => {
if (e.key === "darkMode" && e.newValue != null) {
setIsDark(e.newValue === "true");
}
};
window.addEventListener("storage", onStorage);

return () => {
window.removeEventListener("themechange", onThemeChange);
window.removeEventListener("storage", onStorage);
};
}, []);

//dark and light mode colours
const bannerBg = isDark ? "#121022" : "#F1EAFB";
const bannerText = isDark ? "#F4EFFF" : "#5f249f";

return (
<>
<div id="banner" className="bg-[#F1EAFB] w-full px-4 py-10 relative -z-10">
<h1 className="text-5xl md:text-6xl text-[#5f249f] font-bold font-[Montserrat] py-12 lg:py-10 z-10">
<div
id="banner"
className="w-full px-4 py-10 relative -z-10"
style={{ background: bannerBg }}
>
<h1
className="text-5xl md:text-6xl font-bold font-[Montserrat] py-12 lg:py-10 z-10"
style={{ color: bannerText }}
>
{title}
</h1>
</div>
Expand Down
39 changes: 39 additions & 0 deletions src/app/(frontend)/components/DarkThemeBoxes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
'use client';

import { useEffect, useState } from 'react'
export default function DarkThemeBoxes({
children,
}: {
children: React.ReactNode;
}) {
const [isDark, setIsDark] = useState(false);

useEffect(() => {
const saved = localStorage.getItem('darkMode') === 'true';
setIsDark(saved);

const onThemeChange = (e: Event) => {
const { isDark } = (e as CustomEvent).detail ?? {};
if (typeof isDark === 'boolean') setIsDark(isDark);
};

window.addEventListener('themechange', onThemeChange as EventListener);
return () =>
window.removeEventListener('themechange', onThemeChange as EventListener);
}, []);

//colours for light and darkmode
const bgColour = isDark ? '#796299' : '#E9D5FF';
const textColour = isDark ? '#E9D5FF' : '#5f249f';


//this is for the sponsors page information
return (
<div
className="mt-6 mb-20 font-[Montserrat] p-6 rounded-xl max-w-full mx-auto text-center transition-colors duration-300"
style={{ backgroundColor: bgColour, color: textColour }}
>
{children}
</div>
);
}
31 changes: 28 additions & 3 deletions src/app/(frontend)/components/EventDropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client'

import { useState } from 'react'
import { useEffect, useState } from 'react'
import Image from 'next/image'

interface EventDropdownProps {
Expand All @@ -19,9 +19,32 @@ const EventDropdown: React.FC<EventDropdownProps> = ({
signupUrl
}) => {
const [open, setOpen] = useState(false)
const [isDark, setIsDark] = useState(false)




useEffect(() => {
const saved = localStorage.getItem('darkMode') === 'true'
setIsDark(saved)

const onThemeChange = (e: Event) => {
const { isDark } = (e as CustomEvent).detail ?? {}
if (typeof isDark === 'boolean') setIsDark(isDark)
}
window.addEventListener('themechange', onThemeChange)
return () => {
window.removeEventListener('themechange', onThemeChange)
}
}, [])

const bgColour = isDark ? '#796299' : '#E9D5FF'
const text = isDark ? "#E9D5FF" : "#5f249f";
const desc = isDark ? "#E9D5FF" : "#334155";

return (
<div className="bg-purple-200 rounded-xl p-4 my-2 text-purple-800">
<div className="rounded-xl p-4 my-2"
style = {{ background: bgColour, color: text}}>
<button
onClick={() => setOpen(!open)}
className="w-full flex items-center justify-between text-left"
Expand All @@ -37,7 +60,9 @@ const EventDropdown: React.FC<EventDropdownProps> = ({

{open && (
<div className="mt-4 flex flex-col md:flex-row gap-4">
<div className="md:basis-3/5 text-lg text-slate-700 font-[Montserrat]">{description}</div>
<div className="md:basis-3/5 text-lg font-[Montserrat]"
style={{ color: desc}}
>{description}</div>
<div className="md:basis-2/5 flex flex-col gap-2">
<div className="relative w-full min-h-48 h-full">
<Image
Expand Down
40 changes: 36 additions & 4 deletions src/app/(frontend)/components/ExecCard.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// components/ExecCard.tsx
"use client";
import Image from "next/image";
import { useEffect, useState } from "react";

interface ExecCardProps {
name: string;
Expand All @@ -9,18 +11,48 @@ interface ExecCardProps {
}

export default function ExecCard({ name, role, imageSrc, description }: ExecCardProps) {
const [isDark, setIsDark] = useState(false);

useEffect(() => {
const saved = localStorage.getItem("darkMode") === "true";
setIsDark(saved);

const onThemeChange = (e: Event) => {
const { isDark } = (e as CustomEvent).detail ?? {};
if (typeof isDark === "boolean") setIsDark(isDark);
};
window.addEventListener("themechange", onThemeChange);

const onStorage = (e: StorageEvent) => {
if (e.key === "darkMode" && e.newValue != null) {
setIsDark(e.newValue === "true");
}
};
window.addEventListener("storage", onStorage);

return () => {
window.removeEventListener("themechange", onThemeChange);
window.removeEventListener("storage", onStorage);
};
}, []);

const cardBg = isDark ? "#2A2342" : "#E2D6F6";
const nameColor = isDark ? "#F4EFFF" : "#1f2937";
const roleColor = isDark ? "#CFC6E9" : "#4b5563";
const descColor = isDark ? "#B8ADDA" : "#334155";

return (
<div className="flex flex-col items-center text-center bg-[#E2D6F6] p-6 rounded-2xl">
<div className="flex flex-col items-center text-center p-6 rounded-2xl" style={{ backgroundColor: cardBg }}>
<Image
src={imageSrc}
alt={name}
width={160} // same as w-40
height={160} // same as h-40
className="mb-2 rounded-full"
/>
<p className="text-sm md:text-base font-semibold font-[Montserrat]">{name}</p>
<p className="text-xs md:text-sm text-black-600 font-semibold font-[Montserrat] mb-1">{role}</p>
<p className="text-xs md:text-sm text-slate-700 font-[Montserrat]">{description}</p>
<p className="text-sm md:text-base font-semibold font-[Montserrat]" style={{ color: nameColor }}>{name}</p>
<p className="text-xs md:text-sm font-semibold font-[Montserrat] mb-1" style={{ color: roleColor }}>{role}</p>
<p className="text-xs md:text-sm font-[Montserrat]" style={{ color: descColor }}>{description}</p>
</div>
);
}
40 changes: 40 additions & 0 deletions src/app/(frontend)/components/ExecsHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"use client";
import { useEffect, useState } from "react";

export default function ExecsHeader() {
const [isDark, setIsDark] = useState(false);

useEffect(() => {
const saved = localStorage.getItem("darkMode") === "true";
setIsDark(saved);

const onThemeChange = (e: Event) => {
const { isDark } = (e as CustomEvent).detail ?? {};
if (typeof isDark === "boolean") setIsDark(isDark);
};
window.addEventListener("themechange", onThemeChange);

const onStorage = (e: StorageEvent) => {
if (e.key === "darkMode" && e.newValue != null) {
setIsDark(e.newValue === "true");
}
};
window.addEventListener("storage", onStorage);

return () => {
window.removeEventListener("themechange", onThemeChange);
window.removeEventListener("storage", onStorage);
};
}, []);

const textColor = isDark ? "#F4EFFF" : "#5f249f";

return (
<h2
className="mt-22 text-3xl md:text-5xl font-bold font-[Montserrat] mb-3 text-center p-6"
style={{ color: textColor }}
>
Meet the Exec Team!
</h2>
);
}
Loading