Skip to content
Open
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
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@
"typescript.tsdk": "${workspaceFolder}/client/node_modules/typescript/lib",
"shellcheck.ignorePatterns": {
"**/.env*": true
}
},
"python-envs.defaultEnvManager": "ms-python.python:system"
}
39 changes: 39 additions & 0 deletions client/src/components/ui/TeamMemberCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/* ---------------------------------- */
/* Team member card + section */
/* ---------------------------------- */
import Image from "next/image";

interface TeamMemberCardProps {
name: string;
role: string;
bio: string;
email: string;
image: string;
}

export default function TeamMemberCard({
name,
role,
bio,
email,
image,
}: TeamMemberCardProps) {
return (
<div className="flex w-72 flex-col overflow-hidden rounded-2xl bg-white shadow-sm">
<div className="relative mb-2 h-48 w-full bg-gray-400">
<Image src={image} alt={name} fill className="object-cover" />
</div>

<div className="flex flex-col gap-2 p-4">
<h3 className="text-lg font-bold">{name}</h3>
<p className="border-b border-[#F5D76E] pb-2 text-sm text-gray-500">
{role}
</p>
<p className="text-sm">{bio}</p>
<a href={`mailto:${email}`} className="text-sm text-gray-500">
{email}
</a>
</div>
</div>
);
}
42 changes: 42 additions & 0 deletions client/src/components/ui/TeamSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import TeamMemberCard from "@/components/ui//TeamMemberCard";

const members = [
// TODO: replace with real people + real images in public/images/
{
name: "John Smith",
role: "Director",
bio: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
email: "johnsmith@email.com",
image: "/images/john-smith.png",
},
{
name: "John Smith",
role: "Director",
bio: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
email: "johnsmith2@email.com",
image: "/images/john-smith.png",
},
{
name: "John Smith",
role: "Director",
bio: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
email: "johnsmith3@email.com",
image: "/images/john-smith.png",
},
];

export default function TeamSection() {
return (
<section className="bg-[#FAF5E4] px-8 py-16">
<div className="mx-auto flex max-w-7xl flex-col items-center">
<h2 className="mb-2 text-center text-3xl font-bold">Meet the Team</h2>
<div className="mx-auto mb-10 w-28 border-b-2 border-[#F5D76E]" />
<div className="grid w-full grid-cols-1 justify-items-center gap-8 md:grid-cols-3">
{members.map((member, index) => (
<TeamMemberCard key={`${member.email}-${index}`} {...member} />
))}
</div>
</div>
</section>
);
}
168 changes: 168 additions & 0 deletions client/src/components/ui/footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
"use client";

import { ChevronsUp } from "lucide-react";
import { Inter } from "next/font/google";
import Image from "next/image";
import * as React from "react";
import { BsFacebook,BsInstagram, BsLinkedin } from "react-icons/bs";

import { Button } from "./button";

const inter = Inter({ subsets: ["latin"] });

// ---------------------------------------------------------------------------
// Site map data
// ---------------------------------------------------------------------------
const siteMapLinks = [
{ label: "home", href: "/" },
{ label: "about us", href: "/about" },
{ label: "news", href: "/news" },
{ label: "events", href: "/events" },
{ label: "wa savings", href: "/wa-savings" },
{ label: "resources", href: "/resources" },
{ label: "contact", href: "/contact" },
] as const;

const socialLinks = [
{ label: "Instagram", href: "https://instagram.com", Icon: BsInstagram },
{ label: "LinkedIn", href: "https://linkedin.com", Icon: BsLinkedin },
{ label: "Facebook", href: "https://facebook.com", Icon: BsFacebook },
] as const;

export default function Footer() {
const scrollToTop = () => {
window.scrollTo({ top: 0, behavior: "smooth" });
};

return (
<footer
className={`relative overflow-hidden bg-[#ededed] text-black ${inter.className}`}
>
{/* faint house + plug watermark, matches the background graphic in the design */}
<HouseWatermark />

<div className="relative w-full px-6 py-16 sm:px-10">
<div className="flex flex-col gap-12 sm:flex-row sm:items-start sm:justify-between">
{/* ---------------------------------------------------------------- */}
{/* Left column: logo, blurb, socials, back-to-top, charity badge */}
{/* ---------------------------------------------------------------- */}
<div className="max-w-sm">
<div className="mb-4 flex items-center gap-2">
<Image
src="/eewa-black.png"
alt="Electrify Everything WA logo"
width={40}
height={40}
className="h-10 w-auto"
/>
<h2 className="text-xl font-bold text-black">
Electrify Everything WA
</h2>
</div>

<p className="mb-6 text-sm leading-relaxed text-gray-700">
Advocating for the switch from fossil-fuel based electricity
reliance to renewable sources in Western Australia.
</p>

{/* socials */}
<div className="mb-6 flex items-center gap-3">
{socialLinks.map(({ label, href, Icon }) => (
<a
key={label}
href={href}
target="_blank"
rel="noopener noreferrer"
aria-label={label}
className="text-black transition hover:text-gray-600"
>
<Icon className="h-4 w-4" />
</a>
))}
</div>

{/* back to top + charity badge */}
<div className="flex flex-wrap items-center gap-4">
<Button
variant="outline"
size="sm"
onClick={scrollToTop}
className="gap-2 border-gray-400 bg-transparent text-xs font-thin uppercase tracking-wide text-black hover:border-black hover:bg-transparent hover:text-black"
>
<ChevronsUp className="h-4 w-4" />
Back to top
</Button>

<CharityBadge />
</div>
</div>

{/* ---------------------------------------------------------------- */}
{/* Right column: site map */}
{/* ---------------------------------------------------------------- */}
<nav aria-label="Site map" className="text-right">
<h3 className="mb-4 text-sm font-bold lowercase tracking-wide text-black">
site map
</h3>
<ul className="space-y-2">
{siteMapLinks.map((link) => (
<li key={link.href}>
<a
href={link.href}
className="text-sm text-gray-700 transition hover:text-black"
>
{link.label}
</a>
</li>
))}
</ul>
</nav>
</div>
</div>

{/* copyright bar */}
<div className="relative border-t border-gray-200 bg-gray-50 py-4">
<p className="text-center text-xs text-gray-500">
Copyright © {new Date().getFullYear()}, electrifyeverythingwa.org,
All Rights Reserved.
</p>
</div>
</footer>
);
}

// ---------------------------------------------------------------------------
// Charity badge
// ---------------------------------------------------------------------------
function CharityBadge() {
return (
<a
href="https://www.acnc.gov.au/charity/charities/YOUR-ABN-OR-CHARITY-ID/profile"
target="_blank"
rel="noopener noreferrer"
aria-label="View our registration on the ACNC Charity Register"
>
<Image
src="/registered-charity-icon.png"
alt="ACNC Registered Charity Tick"
width={170}
height={170}
/>
</a>
);
}

// Faint background

function HouseWatermark() {
return (
<Image
src="/eewa-black.png"
alt=""
aria-hidden="true"
width={800}
height={800}
className="pointer-events-none absolute left-[60%] top-1/2 h-[130%] w-auto -translate-x-1/2 -translate-y-1/2 opacity-40"
/>
);
}
120 changes: 120 additions & 0 deletions client/src/pages/AboutPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import Image from "next/image";

import TeamSection from "@/components/ui/TeamSection";

/* ---------------------------------- */
/* Intro text (top of page) */
/* ---------------------------------- */

function AboutIntro() {
return (
<div className="relative mx-auto max-w-3xl items-center space-y-6 px-8 pt-16 text-center">
<p>
Electrify Everything WA is a volunteer-run, non-aligned, not-for-profit,
incorporated organisation representing community groups across WA.
</p>
<div className="mx-auto mb-8 w-40 border-b-2 border-[#FBBF3B]" />
<p>
We aim to accelerate the electrification of households and communities,
replacing fossil fuels with efficient electric technologies powered by
renewable energy. We advocate for a fair and equitable transition to an
all-electric future.
</p>
</div>
);
}

/* ---------------------------------- */
/* Vision / Values / Mission cards */
/* ---------------------------------- */

interface InfoCardProps {
title: string;
description: string;
}

function InfoCard({ title, description }: InfoCardProps) {
return (
<div className="w-full max-w-4xl rounded-2xl bg-[#F5D76E] px-8 py-10 text-center">
<h3 className="mb-3 font-bold uppercase tracking-widest">{title}</h3>
<p>{description}</p>
</div>
);
}

const cards: InfoCardProps[] = [
{
title: "VISION",
description:
"Widespread and just electrification of households, businesses, and transport throughout our communities to reduce energy costs, carbon emissions and build a safer future.",
},
{
title: "VALUES",
description:
"Collaboration, respect, optimism, positive action, and inclusivity.",
},
{
title: "MISSION",
description:
"To advocate, promote and celebrate the just electrification of Western Australia.",
},
];

function InfoCards() {
return (
<div className="flex flex-col items-center gap-6 px-8">
{cards.map((card) => (
<InfoCard
key={card.title}
title={card.title}
description={card.description}
/>
))}
</div>
);
}

/* ---------------------------------- */
/* Our History (dark image section) */
/* ---------------------------------- */

function HistorySection() {
return (
<section className="relative px-8 py-20">
{/* Background image — add solar-panels.jpg to public/images/ */}
<div
className="absolute inset-0 bg-cover bg-center"
style={{ backgroundImage: "url('/images/solar-panels.jpg')" }}
/>
{/* Dark overlay so text stays readable */}
<div className="absolute inset-0 bg-black/60" />

<div className="relative mx-auto flex max-w-3xl flex-col items-center text-white">
<h2 className="mb-2 text-3xl font-bold">Our History</h2>
<div className="mb-8 w-20 border-b-2 border-[#F5D76E]" />
<p className="text-center">
{/* TODO: replace with real history copy */}
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
</p>
</div>
</section>
);
}

export default function AboutPage() {
return (
<main>
{/* Cream → yellow gradient wraps intro + cards, like the mockup */}
<div className="bg-gradient-to-b from-[#FCE49C] via-[#FFFDF4] to-[#FFFDF4] pb-24">
<AboutIntro />
<div className="mt-12">
<InfoCards />
</div>
</div>

<HistorySection />
<TeamSection />
</main>
);
}
Loading