Skip to content

Commit

Permalink
Merge branch 'nwhacks2025_dev' into desktop-projects
Browse files Browse the repository at this point in the history
  • Loading branch information
martincai8 authored Nov 18, 2024
2 parents 6d7fc71 + 98d79fc commit 23f53d1
Show file tree
Hide file tree
Showing 3 changed files with 241 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/sections/Projects.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@ const Projects = () => {
<img src={leftArrow} alt="Carousel Left Arrow" />
</LeftButton>
<RightButton onClick={handleRightClick}>
<img src={rightArrow} alt="Carousel Right Arrow" />
<img src={rightArrow} alt="Carousel Left Arrow" />
</RightButton>
<DotsContainer>
{projects.map((_, index) => (
Expand Down
237 changes: 230 additions & 7 deletions src/sections/Testimonials.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import React, { useState } from 'react';
import React, { useState, useRef } from 'react'
import styled from 'styled-components';

import QaziImage from '@assets/images/testimonials/qazi.png';
import VaibhavImage from '@assets/images/testimonials/vaibhav.png';
import PascaleImage from '@assets/images/testimonials/pascale.png';

import leftArrow from '@assets/images/carouselLeft.svg'
import rightArrow from '@assets/images/carouselRight.svg'

const TestimonialsContainer = styled.div`
aspect-ratio: 1280/832;
height: 100%;
Expand All @@ -17,6 +20,7 @@ const TestimonialsContainer = styled.div`
${p => p.theme.mediaQueries.tablet} {
position: relative;
aspect-ratio: 834 / 1149;
display: block;
}
${p => p.theme.mediaQueries.mobile} {
Expand Down Expand Up @@ -51,6 +55,12 @@ const TestimonialLeft = styled.div`
width: 27.5%;
padding: 40px;
height: 100%;
${p => p.theme.mediaQueries.tablet} {
display: block;
width: 100%;
height: 30%;
padding: 40px 0;
}
`;

const TestimonialRight = styled.div`
Expand All @@ -61,17 +71,31 @@ const TestimonialRight = styled.div`
justify-content: space-between;
align-items: center;
height: 80%;
${p => p.theme.mediaQueries.tablet} {
display: block;
width: 100%;
height: 70%;
}
`;

const Title = styled.h1`
font-size: calc(100vw * (40 / 1280));
font-weight: bold;
color: white;
${p => p.theme.mediaQueries.tablet} {
font-size: calc(100vw * (100 / 1280));
text-align: center;
margin-top: 20px;
}
`;

const Description = styled.p`
font-size: 1.2rem;
color: white;
${p => p.theme.mediaQueries.tablet} {
font-size: 14px;
text-align: center;
}
`;

const HackerList = styled.ul`
Expand All @@ -80,6 +104,10 @@ const HackerList = styled.ul`
margin-top: 75%;
width: 95%;
margin-left: 5px;
${p => p.theme.mediaQueries.tablet} {
display: none;
}
`;

const Hacker = styled.li`
Expand All @@ -99,24 +127,40 @@ const Number = styled.span`
font-size: 2.2em;
margin-right: 20px;
color: white;
${p => p.theme.mediaQueries.tablet} {
position: absolute;
}
`;

const Name = styled.span`
font-size: 1.5rem;
color: white;
${p => p.theme.mediaQueries.tablet} {
text-align: left;
font-size: 1.3rem;
margin-left: 40px;
}
`;

const Role = styled.span`
font-size: 1rem;
color: white;
display: block;
${p => p.theme.mediaQueries.tablet} {
text-align: left;
margin-left: 40px;
}
`;

const HackerImageContainer = styled.div`
width: 25%;
height: 200px;
top: -110px;
position: relative;
${p => p.theme.mediaQueries.mobile} {
display: none;
}
`;

const HackerImage = styled.img`
Expand All @@ -126,6 +170,22 @@ const HackerImage = styled.img`
display: block;
position: relative;
`;
const MobileImageContainer = styled.div`
display: none;
${p => p.theme.mediaQueries.mobile} {
display: block;
margin: 0 auto;
position: absolute;
left: 0;
width: 100vw;
height: 200px;
top: calc(100vh * (860 / 1280));
}
`;
const MobileHackerImage = styled.img`
width: auto;
height: 125px;
`;

const HackerInfo = styled.div`
display: flex;
Expand All @@ -137,22 +197,46 @@ const HackerInfo = styled.div`
justify-content: flex-start;
align-items: flex-start;
color: #FFECD6;
${p => p.theme.mediaQueries.mobile} {
width: 100%;
padding: 0px 0%;
padding-left: 0%;
padding-right: 0%;
text-align: center;
}
`;

const HackerName = styled.h2`
font-size: 1.8rem;
font-weight: bold;
${p => p.theme.mediaQueries.mobile} {
font-size: 1.2rem;
text-align: center;
width: 100%;
}
`;

const HackerHeading = styled.h3`
font-size: 1.2rem;
margin-bottom: 40px;
${p => p.theme.mediaQueries.mobile} {
font-size: 14px;
width: 100%;
}
`;

const HackerDescription = styled.p`
font-size: 1.1rem;
display: block;
margin-bottom: 40px;
${p => p.theme.mediaQueries.mobile} {
font-size: 14px;
width: 100%;
height: 220px;
overflow-y: scroll;
}
`;

const ProfileURL = styled.a`
Expand All @@ -172,7 +256,69 @@ const FAQTitle = styled.p`
${p => p.theme.mediaQueries.tablet} {
display: none;
}
`;

const Carousel = styled.div`
display: none;
${p => p.theme.mediaQueries.tablet} {
display: flex;
width: 100vw;
transition: transform 0.5s ease-in-out;
transform: translateX(${({ currentIndex }) => `-${currentIndex * 100}%`});
}
`;

const HackerCarousel = styled.div`
width: 100vw;
position: relative;
left: 0;
flex-shrink: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
overflow: hidden;
`;
const HackerInfoMobile = styled.div`
display: flex;
width: 75%;
padding: 30px 0%;
padding-left: 10%;
padding-right: 10%;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
color: #FFECD6;
`;
const NavigationButton = styled.button`
display: none;
position: absolute;
top: calc(100vh * (200 / 1280));
transform: translateY(-50%);
background: transparent;
border: none;
color: white;
transform: scale(0.75);
cursor: pointer;
z-index: 2;
&:hover {
color: #ffc633;
}
${p => p.theme.mediaQueries.tablet} {
display: block;
}
`;

const LeftButton = styled(NavigationButton)`
left: 20px;
`;

const RightButton = styled(NavigationButton)`
right: 20px;
`;

const hackerData = [
Expand Down Expand Up @@ -217,6 +363,52 @@ const hackerData = [

const Testimonials = () => {
const [selectedHacker, setSelectedHacker] = useState(hackerData[0]);
const [currentIndex, setCurrentIndex] = useState(0);

const touchStartX = useRef(0);
const touchEndX = useRef(0);

const handleTouchStart = (e) => {
touchStartX.current = e.touches[0].clientX;
};

const handleTouchMove = (e) => {
touchEndX.current = e.touches[0].clientX;
};

const handleTouchEnd = () => {
const swipeDistance = touchEndX.current - touchStartX.current;

if (swipeDistance > 50) {
setCurrentIndex((prevIndex) => {
const newIndex = prevIndex > 0 ? prevIndex - 1 : hackerData.length - 1;
setSelectedHacker(hackerData[newIndex]);
return newIndex;
});
} else if (swipeDistance < -50) {
setCurrentIndex((prevIndex) => {
const newIndex = prevIndex < hackerData.length - 1 ? prevIndex + 1 : 0;
setSelectedHacker(hackerData[newIndex]);
return newIndex;
});
}
};

const handleLeftClick = () => {
setCurrentIndex((prev) => {
const newIndex = prev > 0 ? prev - 1 : hackerData.length - 1;
setSelectedHacker(hackerData[newIndex]); // Ensure `selectedHacker` updates synchronously with `currentIndex`
return newIndex;
});
};

const handleRightClick = () => {
setCurrentIndex((prev) => {
const newIndex = prev < hackerData.length - 1 ? prev + 1 : 0;
setSelectedHacker(hackerData[newIndex]); // Ensure `selectedHacker` updates synchronously with `currentIndex`
return newIndex;
});
};

const handleHackerClick = (hacker) => {
setSelectedHacker(hacker);
Expand All @@ -226,7 +418,11 @@ const Testimonials = () => {
<TestimonialsContainer id="testimonials">
<TestimonialsBackground />
<TestimonialLeft>
<Title>Testimonials</Title>
<Title>Testimonials&nbsp;&nbsp;
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M17.1548 3.62016L17.8456 17.396M17.8456 17.396L4.05247 17.3799M17.8456 17.396L1.55119 1.88007" stroke="white" strokeWidth="4" />
</svg>
</Title>
<Description>Here’s what previous nwHacks attendees have to say!</Description>
<HackerList>
{hackerData.map((hacker) => (
Expand All @@ -238,7 +434,29 @@ const Testimonials = () => {
))}
</HackerList>

<FAQTitle>FAQ</FAQTitle>
<Carousel currentIndex={currentIndex} onTouchStart={handleTouchStart} onTouchMove={handleTouchMove} onTouchEnd={handleTouchEnd}>
{hackerData.map((hacker) => (
<HackerCarousel key={hacker.id} selected={selectedHacker.id === hacker.id}>
<HackerInfoMobile>
<Number>{hacker.id}</Number>
<Name>{hacker.name}</Name>
<Role>{hacker.role}</Role>
</HackerInfoMobile>
</HackerCarousel>
))}
</Carousel>
<LeftButton onClick={handleLeftClick}>
<img src={leftArrow} alt="Carousel Left Arrow" />
</LeftButton>
<RightButton onClick={handleRightClick}>
<img src={rightArrow} alt="Carousel Right Arrow" />
</RightButton>

<FAQTitle>FAQ&nbsp;&nbsp;
<svg width="23" height="26" viewBox="0 0 23 26" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M21.2244 12.75L11.7244 22.75M11.7244 22.75L2.22437 12.75M11.7244 22.75L11.7244 0.25" stroke="white" strokeWidth="4" />
</svg>
</FAQTitle>
</TestimonialLeft>
<TestimonialRight>
{/* Left - Hacker Image */}
Expand All @@ -249,10 +467,15 @@ const Testimonials = () => {
<HackerInfo>
<HackerName>{selectedHacker.name} ({selectedHacker.pronouns})</HackerName>
<HackerHeading>{selectedHacker.heading}</HackerHeading>
<HackerDescription>{selectedHacker.description}</HackerDescription>
{selectedHacker.links.map((link) => (
<ProfileURL href={link.URL} target="_blank">{link.Label}</ProfileURL>
))}
<HackerDescription>{selectedHacker.description}<br /><br />
{selectedHacker.links.map((link) => (
<ProfileURL href={link.URL} target="_blank">{link.Label}</ProfileURL>
))}
</HackerDescription>

<MobileImageContainer>
<MobileHackerImage src={selectedHacker.imageUrl} alt={selectedHacker.name} />
</MobileImageContainer>
</HackerInfo>
</TestimonialRight>
</TestimonialsContainer>
Expand Down
Loading

0 comments on commit 23f53d1

Please sign in to comment.