Skip to content

Commit 87d45b1

Browse files
committed
refactor: reduce code duplication
1 parent 164dc4c commit 87d45b1

File tree

5 files changed

+288
-2
lines changed

5 files changed

+288
-2
lines changed

src/App.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ import About from "./views/About/About";
6969
import Travel from "./views/Travel/Travel";
7070
import NotFoundError from "./components/NotFoundError/NotFoundError";
7171
import { Home2023Wrapper } from "./2023/Home/Home2023Wrapper";
72-
import Speakers2023 from "./2023/Speakers/Speakers2023";
72+
import Speakers2023 from "./components/YearSpecific/Speakers/Speakers2023";
7373
import SpeakerDetailContainer2023 from "./2023/SpeakerDetail/SpeakerDetailContainer2023";
7474
import Talks2023 from "./2023/Talks/Talks2023";
7575
import TalkDetailContainer2023 from "./2023/TalkDetail/TalkDetailContainer2023";
@@ -92,7 +92,7 @@ import Diversity from "./views/Diversity/Diversity";
9292
import LiveView from "./views/Talks/LiveView";
9393
import JobOffers from "./views/JobOffers/JobOffers";
9494
import { HomeWrapper2024 } from "./2024/HomeWrapper2024";
95-
import Speakers2024 from "./2024/Speakers/Speakers2024";
95+
import Speakers2024 from "./components/YearSpecific/Speakers/Speakers2024";
9696
import Talks2024 from "./2024/Talks/Talks2024";
9797
import TalkDetailContainer from "./views/MeetingDetail/TalkDetailContainer";
9898
import SpeakerDetailContainer2024 from "./2024/SpeakerDetail/SpeakerDetailContainer2024";
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import styled from "styled-components";
2+
import {motion} from "framer-motion";
3+
import {BIG_BREAKPOINT, TABLET_BREAKPOINT} from "../../../constants/BreakPoints";
4+
import {Color} from "../../../styles/colors";
5+
6+
export const StyledSpeakersSection = styled.section`
7+
display: flex;
8+
flex-direction: column;
9+
justify-content: center;
10+
align-items: center;
11+
padding: 0 2rem;
12+
@media (min-width: ${TABLET_BREAKPOINT}px) {
13+
padding: 0 5rem;
14+
}
15+
@media (min-width: ${BIG_BREAKPOINT}px) {
16+
padding: 0 10rem;
17+
}
18+
`;
19+
export const StyledLessIcon = styled.img`
20+
position: absolute;
21+
left: -1rem;
22+
top: 2rem;
23+
height: 5rem;
24+
25+
@media (min-width: ${BIG_BREAKPOINT}px) {
26+
height: 10rem;
27+
}
28+
`;
29+
export const StyledMoreIcon = styled.img`
30+
position: absolute;
31+
right: -1rem;
32+
top: 2rem;
33+
height: 5rem;
34+
35+
@media (min-width: ${BIG_BREAKPOINT}px) {
36+
height: 10rem;
37+
}
38+
`;
39+
export const StyledContainerLeftSlash = styled(motion.div)<{
40+
positionPercentage: string;
41+
}>`
42+
position: absolute;
43+
top: ${({positionPercentage}) => {
44+
return positionPercentage;
45+
}};
46+
left: 0;
47+
height: 2rem;
48+
width: 50%;
49+
opacity: 0.2;
50+
`;
51+
export const StyledContainerRightSlash = styled(motion.div)<{
52+
positionPercentage: string;
53+
}>`
54+
position: absolute;
55+
top: ${({positionPercentage}) => {
56+
return positionPercentage;
57+
}};
58+
right: 0;
59+
height: 2rem;
60+
width: 50%;
61+
opacity: 0.2;
62+
`;
63+
export const StyledSlash = styled(motion.p)<{ color: string }>`
64+
font-family: "Square 721 Regular", sans-serif;
65+
color: ${({color}) => {
66+
return color;
67+
}};
68+
font-size: 2rem;
69+
overflow-y: hidden;
70+
height: 100%;
71+
`;
72+
export const StyledWaveContainer = styled.div`
73+
background: ${Color.WHITE};
74+
overflow-y: hidden;
75+
height: 8rem;
76+
width: 100%;
77+
@media (min-width: ${TABLET_BREAKPOINT}px) {
78+
height: 16rem;
79+
}
80+
`;
81+
export const SpeakersCardsContainer = styled.div`
82+
display: flex;
83+
flex-direction: row;
84+
flex-wrap: wrap;
85+
padding: 3rem 0;
86+
justify-content: center;
87+
z-index: 1;
88+
@media (min-width: ${TABLET_BREAKPOINT}px) {
89+
padding: 5rem 0;
90+
}
91+
`;
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
import { MOBILE_BREAKPOINT } from "../../../constants/BreakPoints";
2+
import { Color } from "../../../styles/colors";
3+
import React, { FC, useCallback, useEffect } from "react";
4+
import LessThanBlueIcon from "../../../assets/images/LessThanBlueIcon.svg";
5+
import MoreThanBlueIcon from "../../../assets/images/MoreThanBlueIcon.svg";
6+
import SectionWrapper from "../../../components/SectionWrapper/SectionWrapper";
7+
import TitleSection from "../../../components/SectionTitle/TitleSection";
8+
import { useWindowSize } from "react-use";
9+
import {
10+
SpeakersCardsContainer,
11+
StyledContainerLeftSlash,
12+
StyledContainerRightSlash,
13+
StyledLessIcon,
14+
StyledMoreIcon,
15+
StyledSlash,
16+
StyledSpeakersSection,
17+
StyledWaveContainer,
18+
} from "./Speakers.style";
19+
import Button from "../../../components/UI/Button";
20+
import { gaEventTracker } from "../../../components/analytics/Analytics";
21+
import { useFetchSpeakers } from "../../../hooks/useFetchSpeakers";
22+
import { ISpeaker } from "../../../types/speakers";
23+
import { SpeakerCard } from "../../../views/Speakers/components/SpeakersCard";
24+
import { useSentryErrorReport } from "../../../hooks/useSentryErrorReport";
25+
26+
const LessThanGreaterThan = () => (
27+
<>
28+
<StyledLessIcon src={LessThanBlueIcon} />
29+
<StyledMoreIcon src={MoreThanBlueIcon} />
30+
</>
31+
);
32+
33+
interface SpeakersProps {
34+
year: string;
35+
webData: any;
36+
}
37+
38+
const Speakers: FC<SpeakersProps> = ({ year, webData }) => {
39+
const { width } = useWindowSize();
40+
const today = new Date();
41+
const isBetween = (startDay: Date, endDay: Date): boolean =>
42+
startDay < new Date() && endDay > today;
43+
44+
const { error, data, isLoading } = useFetchSpeakers(year);
45+
46+
useSentryErrorReport(error);
47+
48+
const trackCFP = useCallback(() => {
49+
gaEventTracker("CFP", "CFP");
50+
}, []);
51+
52+
useEffect(() => {
53+
document.title = `Speakers — ${webData.title}${webData.edition}`;
54+
}, [webData.title, webData.edition]);
55+
56+
const CFPStartDay = new Date(webData.cfp.startDay);
57+
const CFPEndDay = new Date(webData.cfp.endDay);
58+
return (
59+
<>
60+
<SectionWrapper color={Color.DARK_BLUE} marginTop={5}>
61+
<StyledSpeakersSection>
62+
<TitleSection
63+
title="SPEAKERS"
64+
subtitle="Speakers coming from all corners of the world join us to
65+
share their experience in various technologies and to
66+
invite everyone to participate in Open Source
67+
Technologies and in the JCP."
68+
color={Color.WHITE}
69+
/>
70+
{width > MOBILE_BREAKPOINT && <LessThanGreaterThan/>}
71+
<SpeakersCardsContainer>
72+
{isLoading && <p>Loading...</p>}
73+
{isBetween(CFPStartDay, CFPEndDay) && (
74+
<div
75+
style={{
76+
width: "100%",
77+
textAlign: "center",
78+
padding: "20px 30%",
79+
}}
80+
>
81+
<Button
82+
onClick={trackCFP}
83+
text="📢 Apply to be a Speaker"
84+
link={webData.cfp.link}
85+
/>
86+
</div>
87+
)}
88+
{webData.hideSpeakers ? (
89+
<p style={{ color: Color.WHITE }}>
90+
No selected speakers yet. Keep in touch in our social media for
91+
upcoming announcements
92+
</p>
93+
) : data?.length === 0 ? (
94+
<p style={{ color: Color.WHITE }}>
95+
No selected speakers yet. Keep in touch in our social media for
96+
upcoming announcements
97+
</p>
98+
) : (
99+
data?.map((speaker: ISpeaker) => (
100+
<SpeakerCard
101+
key={speaker.id}
102+
year={webData.edition}
103+
speaker={speaker}
104+
/>
105+
))
106+
)}
107+
</SpeakersCardsContainer>
108+
<StyledContainerRightSlash
109+
initial={{ x: "100%" }}
110+
animate={{ x: 0 }}
111+
transition={{ duration: 4 }}
112+
positionPercentage="20%"
113+
>
114+
<StyledSlash color={Color.YELLOW}>
115+
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
116+
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
117+
/{" "}
118+
</StyledSlash>
119+
</StyledContainerRightSlash>
120+
121+
<StyledContainerLeftSlash
122+
initial={{ x: "-100%" }}
123+
animate={{ x: 0 }}
124+
transition={{ duration: 4 }}
125+
positionPercentage="40%"
126+
>
127+
<StyledSlash color={Color.DARK_BLUE}>
128+
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
129+
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
130+
/{" "}
131+
</StyledSlash>
132+
</StyledContainerLeftSlash>
133+
134+
<StyledContainerRightSlash
135+
initial={{ x: "100%" }}
136+
animate={{ x: 0 }}
137+
transition={{ duration: 4 }}
138+
positionPercentage="60%"
139+
>
140+
<StyledSlash color={Color.BLUE}>
141+
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
142+
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
143+
/{" "}
144+
</StyledSlash>
145+
</StyledContainerRightSlash>
146+
147+
<StyledContainerLeftSlash
148+
initial={{ x: "-100%" }}
149+
animate={{ x: 0 }}
150+
transition={{ duration: 4 }}
151+
positionPercentage="80%"
152+
>
153+
<StyledSlash color={Color.YELLOW}>
154+
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
155+
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
156+
/{" "}
157+
</StyledSlash>
158+
</StyledContainerLeftSlash>
159+
</StyledSpeakersSection>
160+
</SectionWrapper>
161+
<StyledWaveContainer>
162+
<svg
163+
viewBox="0 0 500 150"
164+
preserveAspectRatio="none"
165+
style={{ height: "100%", width: "100%" }}
166+
>
167+
<path
168+
d="M-8.17,75.50 C207.95,-129.75 329.85,202.80 500.27,5.45 L501.41,-5.41 L0.00,0.00 Z"
169+
style={{ stroke: "none", fill: "#002454" }}
170+
></path>
171+
</svg>
172+
</StyledWaveContainer>
173+
</>
174+
);
175+
};
176+
177+
export default Speakers;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import React, { FC } from "react";
2+
import Speakers from "./Speakers";
3+
import webData from "../../../data/2023.json";
4+
5+
const Speakers2023: FC<React.PropsWithChildren<unknown>> = () => {
6+
return <Speakers year="2023" webData={webData} />;
7+
};
8+
9+
export default Speakers2023;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import React, { FC } from "react";
2+
import Speakers from "./Speakers";
3+
import webData from "../../../data/2024.json";
4+
5+
const Speakers2024: FC<React.PropsWithChildren<unknown>> = () => {
6+
return <Speakers year="2024" webData={webData} />;
7+
};
8+
9+
export default Speakers2024;

0 commit comments

Comments
 (0)