-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
20 changed files
with
1,754 additions
and
2,824 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
"use client"; // Mark this component as a Client Component | ||
|
||
import { Provider } from 'react-redux'; | ||
import { store } from '../redux/stores/store'; // Adjust the path as necessary | ||
import '../styles/globals.css'; // Import your global styles | ||
import type { AppProps } from 'next/app'; // Import AppProps from next/app | ||
|
||
export default function App({ Component, pageProps }: AppProps) { // Use AppProps for typing | ||
return ( | ||
<Provider store={store}> | ||
<Component {...pageProps} /> | ||
</Provider> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,74 +1,30 @@ | ||
"use client"; | ||
|
||
import { UnknownAction } from "@reduxjs/toolkit"; | ||
import { useEffect, useState } from "react"; | ||
// import Conditional from "../shared_components/Conditional"; | ||
import ExecProfiles from "./ExecProfiles"; | ||
import { useAppDispatch, useAppSelector } from "../../redux/hooks/hooks"; | ||
import { AddExecProfile, ExecProfileObject, selectProfile } from "../../redux/slices/execProfileSlice"; | ||
// import { SetCurrentPage } from "../../redux/slices/pageSlice"; | ||
import { AppDispatch } from "../../redux/stores/store"; | ||
import { loadProfilesAsync } from "../../redux/thunks/ProfileThunks"; | ||
|
||
interface AboutPageProps | ||
{} | ||
interface AboutPageProps { } | ||
|
||
export default function AboutPage({} : AboutPageProps) | ||
{ | ||
// const execProfiles = useAppSelector(selectProfile); | ||
export default function AboutPage({ }: AboutPageProps) { | ||
|
||
// const mainDispatch = useAppDispatch(); | ||
|
||
// const [loading, setLoading] = useState(true); | ||
|
||
// mainDispatch(SetCurrentPage("/about")); | ||
|
||
// fetch the profiles if not done already | ||
// useEffect(() => { | ||
// (async () => { | ||
// if (execProfiles.length < 1) | ||
// { | ||
// const promise: UnknownAction = mainDispatch(loadProfilesAsync() as AppDispatch); | ||
|
||
// ((await promise) as unknown as any[]).forEach((element) => { | ||
// mainDispatch(AddExecProfile({ ...element} as ExecProfileObject)); | ||
// }); | ||
// } | ||
|
||
// setLoading(false); | ||
// })(); | ||
// }, [execProfiles.length]); | ||
|
||
return ( | ||
<div className={"flex flex-col gap-5 bg-body-gray grow pl-5"}> | ||
<div className={"flex flex-col gap-5 grow pl-5"}> | ||
|
||
<div className={"flex flex-col gap-3 mt-10"}> | ||
<div className={"text-[36px] font-semibold text-start"}> | ||
About us: | ||
</div> | ||
<div className={"text-lg max-[600px]:text-s font-light items-center"}> | ||
<p>{"The Langara Computer Science Club is a student-led club dedicated to providing a space for students interested in computer science. We provide a space to learn, create, network, and to have fun! We hold workshops, programming competitions, and other meetups."}</p> | ||
<br></br> | ||
<p> | ||
{"The Langara Computer Science club is run by a team of dedicated Langara students. We strive to create awesome opportunities and events and to represent the interests of the diverse student body."} | ||
</p> | ||
</div> | ||
|
||
</div> | ||
<h1 className="text-3xl font-semibold">About us:</h1> | ||
|
||
<br></br> | ||
|
||
<p>{"The Langara Computer Science Club is a student-led club dedicated to providing a space for students interested in computer science. We provide a space to learn, create, network, and to have fun. We hold workshops, programming competitions, and other meetups."}</p> | ||
<p>{"The Langara Computer Science club is run by a team of dedicated Langara students. We strive to create awesome opportunities and events and to represent the interests of the diverse student body."}</p> | ||
{/* <p>{"We hire for new executives at the start of every month. If you are interested in joining our executive team, please follow our discord and instagram channels for updates."}</p> */} | ||
|
||
<br></br> | ||
|
||
<div className={"flex flex-col profileContainer mb-3 items-center gap-5"}> | ||
<h3 className="text-3xl font-semibold">Our Executives:</h3> | ||
|
||
<div className={"flex flex-col max-[600px]:mx-0 gap-3 items-center"}> | ||
{/* TODO: don't assume API always works. */} | ||
{/* <Conditional Condition={loading}>Loading</Conditional> */} | ||
<ExecProfiles/> | ||
</div> | ||
<h3 className="text-3xl font-semibold">Our Executives:</h3> | ||
|
||
</div> | ||
<div className={"flex flex-col max-[600px]:mx-0 gap-3 items-center"}> | ||
{/* TODO: don't assume API always works. */} | ||
{/* <Conditional Condition={loading}>Loading</Conditional> */} | ||
<ExecProfiles /> | ||
</div> | ||
); | ||
|
||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,56 +1,104 @@ | ||
import { useEffect, useState } from 'react'; | ||
import ExecProfile from './ExecProfile'; | ||
import { useAppSelector, useAppDispatch } from '../../redux/hooks/hooks'; | ||
import { selectProfile } from '../../redux/slices/execProfileSlice'; | ||
import { loadProfilesAsync } from '../../redux/thunks/ProfileThunks'; | ||
|
||
export default function ExecProfiles() { | ||
const dispatch = useAppDispatch(); | ||
const profiles = useAppSelector(selectProfile); | ||
const [loading, setLoading] = useState(true); | ||
const [hasFetched, setHasFetched] = useState(false); // Prevents multiple fetches | ||
|
||
useEffect(() => { | ||
const fetchProfiles = async () => { | ||
if (!hasFetched) { | ||
setHasFetched(true); // Set flag to true to prevent re-fetching | ||
// console.log("Fetching profiles..."); | ||
const resultAction = await dispatch(loadProfilesAsync()); | ||
|
||
if (loadProfilesAsync.fulfilled.match(resultAction)) { | ||
// console.log("Profiles fetched:", resultAction.payload); | ||
} else { | ||
// console.error("Failed to fetch profiles"); | ||
} | ||
setLoading(false); | ||
} | ||
}; | ||
|
||
fetchProfiles(); | ||
}, [dispatch, hasFetched]); | ||
|
||
if (loading) { | ||
return <div>Loading...</div>; | ||
} | ||
|
||
// console.log("Profiles to display:", profiles); | ||
|
||
interface Executive { | ||
student_id: string; | ||
roles: string[]; | ||
name: string; | ||
profile_picture: string | null; | ||
current_status: string; | ||
bio: string; | ||
last_term: string; | ||
} | ||
|
||
async function getExecutives() { | ||
const res = await fetch('https://api3.langaracs.ca/executives/all'); | ||
const executives = await res.json(); | ||
return executives; | ||
} | ||
|
||
export default async function ExecProfiles() { | ||
const executives: Executive[] = await getExecutives(); | ||
|
||
// Separate executives into current and retired | ||
const currentExecutives = executives.filter(exec => exec.current_status !== 'Retired'); | ||
const retiredExecutives = executives.filter(exec => exec.current_status === 'Retired'); | ||
|
||
// Group current executives by year | ||
const groupedCurrentExecutives = currentExecutives.reduce((acc: Record<string, Executive[]>, exec) => { | ||
const year = exec.last_term ? exec.last_term.split(' ')[0] : 'Unknown'; | ||
if (!acc[year]) { | ||
acc[year] = []; | ||
} | ||
acc[year].push(exec); | ||
return acc; | ||
}, {}); | ||
|
||
// Group retired executives by year | ||
const groupedRetiredExecutives = retiredExecutives.reduce((acc: Record<string, Executive[]>, exec) => { | ||
const year = exec.last_term ? exec.last_term.split(' ')[0] : 'Unknown'; | ||
if (!acc[year]) { | ||
acc[year] = []; | ||
} | ||
acc[year].push(exec); | ||
return acc; | ||
}, {}); | ||
|
||
// Sort years for retired executives | ||
const sortedRetiredYears = Object.keys(groupedRetiredExecutives).sort((a, b) => { | ||
if (a === 'current') return -1; | ||
if (b === 'current') return 1; | ||
return Number(b) - Number(a); | ||
}); | ||
|
||
return ( | ||
<div className="flex flex-wrap gap-20 justify-center"> | ||
{profiles.map((profile: { ID: string; Position: string[]; Name: string; ImageBuffer?: string; Description: string; }) => ( | ||
<ExecProfile | ||
key={profile.ID} | ||
Position={profile.Position} | ||
ID={profile.ID} | ||
Name={profile.Name} | ||
ImageBuffer={ | ||
profile.ImageBuffer | ||
? `https://api3.langaracs.ca/executives/image/${profile.ImageBuffer}` | ||
: 'https://via.placeholder.com/200x200' | ||
} | ||
Description={profile.Description} | ||
/> | ||
<div className="flex flex-wrap flex-row gap-20 justify-center"> | ||
{/* Block for current executives grouped by year */} | ||
{Object.keys(groupedCurrentExecutives).map(year => ( | ||
<div key={year} className="flex-row gap-5"> | ||
{/* <h2 className="text-2xl font-semibold pb-5">Current Executives</h2> */} | ||
<div className=" flex flex-wrap flex-row gap-5"> | ||
{groupedCurrentExecutives[year].map((exec) => ( | ||
<ExecProfile | ||
key={exec.student_id} | ||
ID={exec.student_id} | ||
Position={exec.roles} | ||
Name={exec.name} | ||
ImageBuffer={ | ||
exec.profile_picture | ||
? `https://${exec.profile_picture}` | ||
: 'https://via.placeholder.com/200x200' | ||
} | ||
Description={exec.bio || ''} | ||
/> | ||
))} | ||
</div> | ||
</div> | ||
))} | ||
|
||
{/* Block for retired executives grouped by year */} | ||
{sortedRetiredYears.map(year => ( | ||
<div key={year} className="mt-10"> | ||
<h2 className="text-2xl font-semibold pb-5">Retired Executives - {year}</h2> | ||
<div className=" flex flex-wrap flex-row gap-5"> | ||
{groupedRetiredExecutives[year].map((exec) => ( | ||
<ExecProfile | ||
key={exec.student_id} | ||
ID={exec.student_id} | ||
Position={exec.roles} | ||
Name={exec.name} | ||
ImageBuffer={ | ||
exec.profile_picture | ||
? `https://${exec.profile_picture}` | ||
: 'https://via.placeholder.com/200x200' | ||
} | ||
Description={exec.bio || ''} | ||
/> | ||
))} | ||
</div> | ||
</div> | ||
))} | ||
<br></br> | ||
</div> | ||
); | ||
} |
Oops, something went wrong.