Skip to content

Commit

Permalink
Gabe - "Who We Are" and "Our Mission" Sections (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielsessions authored Jan 10, 2025
1 parent 463babf commit f8a201b
Show file tree
Hide file tree
Showing 14 changed files with 356 additions and 0 deletions.
15 changes: 15 additions & 0 deletions app/dev/who-we-are/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import OurMission from "@/components/OurMission";
import WhoWeAre from "@/components/WhoWeAre";


export default function WhoWeArePage() {

return (
<>
<div className="font-inter">
<WhoWeAre />
<OurMission />
</div>
</>
)
}
11 changes: 11 additions & 0 deletions app/globals.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&display=swap");

@tailwind base;
@tailwind components;
@tailwind utilities;

.hide-scrollbar::-webkit-scrollbar {
display: none;
}

.hide-scrollbar {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
6 changes: 6 additions & 0 deletions app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import Button from "@/components/button";
import Hero from "@/components/hero";
import OurMission from "@/components/OurMission";
import WhoWeAre from "@/components/WhoWeAre";


export default function HomePage() {
return (
Expand All @@ -18,6 +21,9 @@ export default function HomePage() {
</>
}
/>

<WhoWeAre />
<OurMission />
</div>
);
}
65 changes: 65 additions & 0 deletions components/FeaturedStatistics.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* @fileoverview A section that displays a set of large statistics
* and statistic descriptions.
*
* @file FeaturedStatistics.tsx
* @date January 5th, 2023
* @author Gabriel Sessions
*
*/

import clsx from "clsx"

interface FeaturedStatisticsProps {
statistics: Array<Statistic>,
className?: string
}

/**
* Displays a set of statistics in a row (or column depending on screen size)
*
* @param props - An array of statistics to be fed into DisplayStatistic
*/
export default function FeaturedStatistics(props: FeaturedStatisticsProps) {
return (
<div className={
clsx(
"block sm:flex justify-center sm:space-x-6 lg:space-x-16 flex-wrap space-y-8 sm:space-y-0 text-center",
props.className
)
}>
{
props.statistics.map((stat, idx) =>
<div key={idx}>
<DisplayStatistic
key={idx}
{...stat}
/>
</div>
)
}
</div>
)
}

interface Statistic {
statistic: string,
label: string
}

/**
* Displays a bold statistic (e.g. number)
* and a short description of the statistic
*
* @param props - A statistic and a descriptor (label)
*/
function DisplayStatistic(props: Statistic) {
return (
<>
<div className="text-white">
<h2 className="font-semibold text-2xl md:text-3xl lg:text-5xl mb-2">{props.statistic}</h2>
<h3 className="font-normal text-md md:text-lg lg:text-xl">{props.label}</h3>
</div>
</>
)
}
31 changes: 31 additions & 0 deletions components/FeaturedTextBlock.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* @fileoverview A simple section with a small title and a block of bolded text
*
* @file FeaturedTextBlock.tsx
* @date January 5th, 2025
* @author Gabriel Sessions
*
*/

import { ReactNode } from "react"

interface FeaturedTextBlockProps {
title: ReactNode,
featuredText: ReactNode
}

/**
* Displays a header and descriptor text below the header.
*
* @param Takes in a title (header) and featured text (descriptor)
*/
export default function FeaturedTextBlock(props: FeaturedTextBlockProps) {
return (
<>
<div className="flex py-10 md:py-10 lg:py-24 flex-col justify-center items-start gap-2">
<h2 className="text-lg md:text-xl text-white opacity-60 font-bold">{props.title}</h2>
<h3 className="text-2xl md:text-4xl lg:text-5xl text-white font-semibold lg:leading-[56px]">{props.featuredText}</h3>
</div>
</>
)
}
120 changes: 120 additions & 0 deletions components/ImageCarousel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/**
* @fileoverview A scrollable image carousel which shows a preview of the
* next/previous images.
*
* @file ImageCarousel.tsx
* @date January 5th, 2023
* @author Gabriel Sessions
*
* @todo Remove hardcoded width/height values if this component is reused
* with different image dimensions.
*/

"use client"

import { clsx } from 'clsx';
import Image from "next/image";
import { useEffect, useRef, useState } from "react";

const IMG_HEIGHT = 389;
const IMG_WIDTH = 665;

/**
* @param path - Local or absolute path to an image asset
* @param altText - A text descriptor of the image
* @param className - Optional field to add CSS styles
*/
interface ImageProps {
path: string,
altText: string,
className?: string
}

/**
* @param images - An array of objects to be fed into the Image component
* @param className - Optional field to add CSS styles
*/
interface ImageCarouselProps {
images: Array<ImageProps>,
className?: string
}

/**
* An Image Carousel with basic scrolling functionality
*
* @param props - An array of images
* @todo Adjust the useEffect scrolling logic to display an even number
* of images properly.
*/
export default function ImageCarousel(props: ImageCarouselProps) {
const scrollContainerRef = useRef<HTMLDivElement>(null);

// The carousel is hidden from the user while it loads and waits for the
// useEffect to scroll the carousel
const [isVisible, setIsVisible] = useState(false);

// Scrolls the carousel to the center when the page loads
useEffect(() => {
if (scrollContainerRef.current) {
const scrollContainer = scrollContainerRef.current;
const centerPosition = (scrollContainer.scrollWidth - scrollContainer.clientWidth) / 2;
scrollContainer.scrollLeft = centerPosition;
setIsVisible(true);
}
}, []);

return (
<div
className={
clsx(
"relative transition-opacity duration-300",
isVisible ? 'opacity-100' : 'opacity-0',
props.className
)
}
>
<div
className="relative flex overflow-x-auto hide-scrollbar space-x-6 xl:-mx-32"
ref={scrollContainerRef}
>
{props.images.map((image, idx) => (
<ImageContainer
key={idx}
path={image.path}
altText={image.altText}
className="scroll-snap-center"
/>
))}
</div>
</div>
)
}


/**
* An image container generator. Creates a responsive, rounded box
* for images with a max width of 600px.
*
* @param props - Image path, alt text. Width and height are defined globally.
* @returns A React component
*
* @todo Change width/height to props values if the component needs to be reused
* with new image dimensions.
*/
function ImageContainer(props: ImageProps) {
return (
<Image
src={props.path}
alt={props.altText}
width={IMG_WIDTH}
height={IMG_HEIGHT}
className={
`border-transparent rounded-xl scroll-snap-center
w-[300px] h-auto
md:w-[450px]
xl:w-[600px] ${props.className}`
}
/>
)
}

26 changes: 26 additions & 0 deletions components/OurMission.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* @fileoverview The "Our Mission" section on the JumboCode homepage
*
* @file OurMission.tsx
* @date January 5th, 2025
* @author Gabriel Sessions
*/

import FeaturedTextBlock from "./FeaturedTextBlock"

const ourMissionText = {
title: "Our mission",
featuredText:
<>
To <span className="text-brand">strengthen communities</span> by developing custom software solutions that promote change and <span className="text-brand">foster student growth</span>.
</>
}

export default function OurMission() {

return (
<>
<FeaturedTextBlock {...ourMissionText} />
</>
)
}
77 changes: 77 additions & 0 deletions components/WhoWeAre.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/**
* @fileoverview The "Who We Are" section of the JumboCode homepage.
*
* @file WhoWeAre.tsx
* @date January 5th, 2025
* @author Gabriel Sessions
*/

import FeaturedStatistics from "./FeaturedStatistics";
import FeaturedTextBlock from "./FeaturedTextBlock";
import ImageCarousel from "./ImageCarousel";

const whoWeAreText = {
title: "Who we are",
featuredText:
<>
JumboCode is a <span className="text-brand">student-run digital agency</span> at Tufts University that provides custom and high-quality <span className="text-brand">software to nonprofits</span> through year-long pro bono projects.
</>
}

const whoWeAreImages = [
{
path: "/homepage/who-we-are-4.png",
altText: "Project presentation"
},
{
path: "/homepage/who-we-are-1.png",
altText: "A live demo at JumboCode final presentations"
},
{
path: "/homepage/who-we-are-2.png",
altText: "JumboCode Team Photo"
},
{
path: "/homepage/who-we-are-3.png",
altText: "A team having fun at a JumboCode hack night"
},
{
path: "/homepage/who-we-are-5.png",
altText: "JumboHack programmers working on their projects"
}
];

const featuredStatistics = [
{
statistic: "170+",
label: "Annual Members"
},
{
statistic: "80K+",
label: "Hours Volunteered"
},
{
statistic: "75+",
label: "Shipped Apps"
}
]

export default function WhoWeAre() {
return (
<>
<div>
<FeaturedTextBlock {...whoWeAreText} />
<ImageCarousel
images={whoWeAreImages}
className="py-8 md:pb-8 lg:py-20"
/>
<FeaturedStatistics
statistics={featuredStatistics}
className={"py-8 md:mt-8 lg:py-12 lg:pb-20"}
/>

</div>
</>
)
}

Binary file added public/homepage/who-we-are-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/homepage/who-we-are-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/homepage/who-we-are-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/homepage/who-we-are-4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/homepage/who-we-are-5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions tailwind.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,14 @@ const config: Config = {
],
theme: {
extend: {
fontFamily: {
inter: ['Inter', 'sans-serif']
},
colors: {
gray: colors.zinc,
brand: "#32C89E",
background: "#171719",
subtext: "#A1A1A1"
},
},
},
Expand Down

0 comments on commit f8a201b

Please sign in to comment.