From fe25ca9c5276bfd257c05b3047cf504e71ba13a4 Mon Sep 17 00:00:00 2001 From: Anyul Rivas Date: Wed, 14 May 2025 12:26:41 +0200 Subject: [PATCH 1/2] refactor: replace framer-motion with motion/react and update imports --- package-lock.json | 27 ++++++ package.json | 1 + src/2023/Home/components/Faqs/Faqs.style.ts | 6 +- src/2023/Home/components/Home/Style.Home.tsx | 6 +- .../SpeakersCarousel/SpeakerSwiper.tsx | 8 +- .../components/Sponsors/Sponsors.style.ts | 2 +- src/2023/SpeakerDetail/Speaker.style.ts | 6 +- src/2023/SpeakerDetail/SpeakerDetail.style.ts | 6 +- src/2023/Speakers/Speakers.style.ts | 6 +- src/2023/TalkDetail/Style.MeetingDetail.tsx | 6 +- src/2024/Home/Style.Home.tsx | 6 +- src/2024/Speakers/Speakers.style.ts | 6 +- src/2024/Sponsors/Sponsors.style.ts | 2 +- src/components/JobOffers/JobsCard.tsx | 8 +- .../LeftHashWithText/LeftHashWithText.tsx | 4 +- .../Navigation/Style.Navigation.tsx | 6 +- .../RightHashWithText/RightHashWithText.tsx | 4 +- src/components/Swiper/SpeakersCarousel.tsx | 4 +- .../YearSpecific/Speakers/Speakers.style.ts | 9 +- src/hooks/useFetchSpeakers.test.tsx | 95 +++++++++++++++++-- src/hooks/useFetchSpeakers.ts | 38 ++++---- src/hooks/useFetchTalks.test.tsx | 4 +- src/views/Home/HomeWrapper.tsx | 2 +- src/views/Home/components/Faqs/Faqs.style.ts | 8 +- src/views/Home/components/Home/Style.Home.tsx | 9 +- .../components/Sponsors/Sponsors.style.ts | 2 +- .../MeetingDetail/Style.MeetingDetail.tsx | 24 ++--- src/views/SpeakerDetail/Speaker.style.ts | 8 +- .../SpeakerDetail/SpeakerDetail.style.ts | 6 +- src/views/Speakers/Speakers.style.ts | 6 +- 30 files changed, 214 insertions(+), 111 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2d03cc923..cf53f6e68 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,6 +28,7 @@ "gsap": "^3.13.0", "lenis": "^1.3.1", "moment": "^2.30.1", + "motion": "^12.11.0", "primeicons": "^7.0.0", "primereact": "^10.9.1", "react": "^18.3.1", @@ -8135,6 +8136,32 @@ "node": "*" } }, + "node_modules/motion": { + "version": "12.11.0", + "resolved": "https://registry.npmjs.org/motion/-/motion-12.11.0.tgz", + "integrity": "sha512-1DIh+uBh2Ledv8VlJfveLuE+6tTAkLqRxhBHQSH6Ct8PxcZpUWY7z9E34L3LvnGbXp8u97hGSjeDsmvmVrjOeQ==", + "license": "MIT", + "dependencies": { + "framer-motion": "^12.11.0", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, "node_modules/motion-dom": { "version": "12.11.0", "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.11.0.tgz", diff --git a/package.json b/package.json index 681e1634b..7d615794e 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "gsap": "^3.13.0", "lenis": "^1.3.1", "moment": "^2.30.1", + "motion": "^12.11.0", "primeicons": "^7.0.0", "primereact": "^10.9.1", "react": "^18.3.1", diff --git a/src/2023/Home/components/Faqs/Faqs.style.ts b/src/2023/Home/components/Faqs/Faqs.style.ts index 21aae5b33..4f112d76d 100644 --- a/src/2023/Home/components/Faqs/Faqs.style.ts +++ b/src/2023/Home/components/Faqs/Faqs.style.ts @@ -1,7 +1,7 @@ import { styled } from "styled-components"; -import { Color } from "../../../../styles/colors"; -import { motion } from "framer-motion"; -import { BIG_BREAKPOINT } from "../../../../constants/BreakPoints"; +import { Color } from "@styles/colors"; +import { motion } from "motion/react"; +import { BIG_BREAKPOINT } from "@constants/BreakPoints"; export type FaqCardType = { faq: { diff --git a/src/2023/Home/components/Home/Style.Home.tsx b/src/2023/Home/components/Home/Style.Home.tsx index 1290b56f8..2aa93ad7a 100644 --- a/src/2023/Home/components/Home/Style.Home.tsx +++ b/src/2023/Home/components/Home/Style.Home.tsx @@ -1,7 +1,7 @@ import { styled } from "styled-components"; -import { Color } from "../../../../styles/colors"; -import { motion } from "framer-motion"; -import { BIG_BREAKPOINT } from "../../../../constants/BreakPoints"; +import { Color } from "@styles/colors"; +import { motion } from "motion/react"; +import { BIG_BREAKPOINT } from "@constants/BreakPoints"; export const StyledHomaImage = styled.div` padding: 70px 0 40px; diff --git a/src/2023/Home/components/SpeakersCarousel/SpeakerSwiper.tsx b/src/2023/Home/components/SpeakersCarousel/SpeakerSwiper.tsx index ce30b6a49..2466c9147 100644 --- a/src/2023/Home/components/SpeakersCarousel/SpeakerSwiper.tsx +++ b/src/2023/Home/components/SpeakersCarousel/SpeakerSwiper.tsx @@ -2,12 +2,12 @@ import { FC } from "react"; import { Autoplay, Parallax } from "swiper"; import { Swiper, SwiperSlide } from "swiper/react"; import { styled } from "styled-components"; -import { Color } from "../../../../styles/colors"; +import { Color } from "@styles/colors"; import "swiper/swiper-bundle.min.css"; import { Link } from "react-router"; -import { ROUTE_SPEAKER_DETAIL } from "../../../../constants/routes"; -import { useFetchSpeakers } from "../../../../hooks/useFetchSpeakers"; -import { useSentryErrorReport } from "../../../../hooks/useSentryErrorReport"; +import { ROUTE_SPEAKER_DETAIL } from "@constants/routes"; +import { useFetchSpeakers } from "@hooks/useFetchSpeakers"; +import { useSentryErrorReport } from "@hooks/useSentryErrorReport"; const StyledSlideImage = styled.img` display: block; diff --git a/src/2023/Home/components/Sponsors/Sponsors.style.ts b/src/2023/Home/components/Sponsors/Sponsors.style.ts index f18aadd36..caeb5ef27 100644 --- a/src/2023/Home/components/Sponsors/Sponsors.style.ts +++ b/src/2023/Home/components/Sponsors/Sponsors.style.ts @@ -1,6 +1,6 @@ import { styled } from "styled-components"; import { BIG_BREAKPOINT } from "@constants/BreakPoints"; -import { motion } from "framer-motion"; +import { motion } from "motion/react"; export const StyledSponsorsContainer = styled.div` position: relative; diff --git a/src/2023/SpeakerDetail/Speaker.style.ts b/src/2023/SpeakerDetail/Speaker.style.ts index 6c2ac2f96..4a5d2df16 100644 --- a/src/2023/SpeakerDetail/Speaker.style.ts +++ b/src/2023/SpeakerDetail/Speaker.style.ts @@ -1,11 +1,11 @@ import { styled } from "styled-components"; -import { Color } from "../../styles/colors"; +import { Color } from "@styles/colors"; import { BIG_BREAKPOINT, LARGE_BREAKPOINT, TABLET_BREAKPOINT, -} from "../../constants/BreakPoints"; -import { motion } from "framer-motion"; +} from "@constants/BreakPoints"; +import { motion } from "motion/react"; export const StyledContainer = styled.div` background-color: ${Color.BLUE}; diff --git a/src/2023/SpeakerDetail/SpeakerDetail.style.ts b/src/2023/SpeakerDetail/SpeakerDetail.style.ts index 1944c4f73..0813e39f3 100644 --- a/src/2023/SpeakerDetail/SpeakerDetail.style.ts +++ b/src/2023/SpeakerDetail/SpeakerDetail.style.ts @@ -1,7 +1,7 @@ import { styled } from "styled-components"; -import { motion } from "framer-motion"; -import { BIG_BREAKPOINT } from "../../constants/BreakPoints"; -import { Color } from "../../styles/colors"; +import { motion } from "motion/react"; +import { BIG_BREAKPOINT } from "@constants/BreakPoints"; +import { Color } from "@styles/colors"; import { Link } from "react-router"; /* eslint-disable @typescript-eslint/no-unused-expressions*/ export const StyledTalkDescription = styled(Link)` diff --git a/src/2023/Speakers/Speakers.style.ts b/src/2023/Speakers/Speakers.style.ts index b2d35531a..595e6db47 100644 --- a/src/2023/Speakers/Speakers.style.ts +++ b/src/2023/Speakers/Speakers.style.ts @@ -1,7 +1,7 @@ import { styled } from "styled-components"; -import { motion } from "framer-motion"; -import { BIG_BREAKPOINT, TABLET_BREAKPOINT } from "../../constants/BreakPoints"; -import { Color } from "../../styles/colors"; +import { motion } from "motion/react"; +import { BIG_BREAKPOINT, TABLET_BREAKPOINT } from "@constants/BreakPoints"; +import { Color } from "@styles/colors"; export const StyledSpeakersSection = styled.section` display: flex; diff --git a/src/2023/TalkDetail/Style.MeetingDetail.tsx b/src/2023/TalkDetail/Style.MeetingDetail.tsx index ada1e59da..f6931b09f 100644 --- a/src/2023/TalkDetail/Style.MeetingDetail.tsx +++ b/src/2023/TalkDetail/Style.MeetingDetail.tsx @@ -1,7 +1,7 @@ import { styled } from "styled-components"; -import { BIG_BREAKPOINT, LARGE_BREAKPOINT } from "../../constants/BreakPoints"; -import { motion } from "framer-motion"; -import { Color } from "../../styles/colors"; +import { BIG_BREAKPOINT, LARGE_BREAKPOINT } from "@constants/BreakPoints"; +import { motion } from "motion/react"; +import { Color } from "@styles/colors"; export const StyledContainer = styled.div` padding-top: 2rem; diff --git a/src/2024/Home/Style.Home.tsx b/src/2024/Home/Style.Home.tsx index eca587299..0f3488fea 100644 --- a/src/2024/Home/Style.Home.tsx +++ b/src/2024/Home/Style.Home.tsx @@ -1,7 +1,7 @@ import { styled } from "styled-components"; -import { motion } from "framer-motion"; -import { Color } from "../../styles/colors"; -import { BIG_BREAKPOINT, BIGGER_BREAKPOINT } from "../../constants/BreakPoints"; +import { motion } from "motion/react"; +import { Color } from "@styles/colors"; +import { BIG_BREAKPOINT, BIGGER_BREAKPOINT } from "@constants/BreakPoints"; export const StyledHomeImage = styled.div` padding: 70px 0 40px; diff --git a/src/2024/Speakers/Speakers.style.ts b/src/2024/Speakers/Speakers.style.ts index b2d35531a..595e6db47 100644 --- a/src/2024/Speakers/Speakers.style.ts +++ b/src/2024/Speakers/Speakers.style.ts @@ -1,7 +1,7 @@ import { styled } from "styled-components"; -import { motion } from "framer-motion"; -import { BIG_BREAKPOINT, TABLET_BREAKPOINT } from "../../constants/BreakPoints"; -import { Color } from "../../styles/colors"; +import { motion } from "motion/react"; +import { BIG_BREAKPOINT, TABLET_BREAKPOINT } from "@constants/BreakPoints"; +import { Color } from "@styles/colors"; export const StyledSpeakersSection = styled.section` display: flex; diff --git a/src/2024/Sponsors/Sponsors.style.ts b/src/2024/Sponsors/Sponsors.style.ts index 12465ca77..1bdd5f8d3 100644 --- a/src/2024/Sponsors/Sponsors.style.ts +++ b/src/2024/Sponsors/Sponsors.style.ts @@ -1,6 +1,6 @@ import { styled } from "styled-components"; import { BIG_BREAKPOINT } from "@constants/BreakPoints"; -import { motion } from "framer-motion"; +import { motion } from "motion/react"; export const StyledSponsorsContainer = styled.div` position: relative; diff --git a/src/components/JobOffers/JobsCard.tsx b/src/components/JobOffers/JobsCard.tsx index dbff1df43..05b258811 100644 --- a/src/components/JobOffers/JobsCard.tsx +++ b/src/components/JobOffers/JobsCard.tsx @@ -1,14 +1,14 @@ import { FC } from "react"; import { styled } from "styled-components"; -import { Color } from "../../styles/colors"; -import { motion } from "framer-motion"; +import { Color } from "@styles/colors"; +import { motion } from "motion/react"; import LocationIcon from "../../assets/images/LocationIcon.svg"; import { StyledFaqCard, StyledFaqText, StyledFaqTitle, -} from "../../views/Home/components/Faqs/Faqs.style"; -import { Offer } from "../../types/jobOffers"; +} from "@views/Home/components/Faqs/Faqs.style"; +import { Offer } from "@types/jobOffers"; export type IJobsCardProps = { offer: Offer; diff --git a/src/components/LeftHashWithText/LeftHashWithText.tsx b/src/components/LeftHashWithText/LeftHashWithText.tsx index 4dd04219c..1d24adf45 100644 --- a/src/components/LeftHashWithText/LeftHashWithText.tsx +++ b/src/components/LeftHashWithText/LeftHashWithText.tsx @@ -1,8 +1,8 @@ import { FC } from "react"; -import { motion } from "framer-motion"; +import { motion } from "motion/react"; import { styled } from "styled-components"; import { TLateralHashWithText } from "../RightHashWithText/RightHashWithText"; -import { MOBILE_BREAKPOINT } from "../../constants/BreakPoints"; +import { MOBILE_BREAKPOINT } from "@constants/BreakPoints"; const StyledLeftSlashWrapper = styled(motion.div)` display: flex; diff --git a/src/components/Navigation/Style.Navigation.tsx b/src/components/Navigation/Style.Navigation.tsx index 87c6424b5..ccd0dbc4f 100644 --- a/src/components/Navigation/Style.Navigation.tsx +++ b/src/components/Navigation/Style.Navigation.tsx @@ -1,8 +1,8 @@ import { styled } from "styled-components"; -import { motion } from "framer-motion"; -import { Color } from "../../styles/colors"; +import { motion } from "motion/react"; +import { Color } from "@styles/colors"; import { NavLink } from "react-router"; -import { MAX_WIDTH, MOBILE_BREAKPOINT } from "../../constants/BreakPoints"; +import { MAX_WIDTH, MOBILE_BREAKPOINT } from "@constants/BreakPoints"; export const StyledBlueHamburger = styled(motion.img)` height: 2.5rem; diff --git a/src/components/RightHashWithText/RightHashWithText.tsx b/src/components/RightHashWithText/RightHashWithText.tsx index b3a60a2e4..15207989d 100644 --- a/src/components/RightHashWithText/RightHashWithText.tsx +++ b/src/components/RightHashWithText/RightHashWithText.tsx @@ -1,7 +1,7 @@ import { FC } from "react"; -import { motion } from "framer-motion"; +import { motion } from "motion/react"; import { styled } from "styled-components"; -import { MOBILE_BREAKPOINT } from "../../constants/BreakPoints"; +import { MOBILE_BREAKPOINT } from "@constants/BreakPoints"; export type TLateralHashWithText = { color: string; diff --git a/src/components/Swiper/SpeakersCarousel.tsx b/src/components/Swiper/SpeakersCarousel.tsx index 10f60c8ef..572f419cb 100644 --- a/src/components/Swiper/SpeakersCarousel.tsx +++ b/src/components/Swiper/SpeakersCarousel.tsx @@ -1,7 +1,7 @@ import { FC } from "react"; import { Link } from "react-router"; -import LessThanBlueWhiteIcon from "../../assets/images/LessThanBlueIcon.svg"; -import { motion } from "framer-motion"; +import LessThanBlueWhiteIcon from "@assets/images/LessThanBlueIcon.svg"; +import { motion } from "motion/react"; import { styled } from "styled-components"; import SpeakerSwiper from "./SpeakerSwiper"; import { Color } from "@styles/colors"; diff --git a/src/components/YearSpecific/Speakers/Speakers.style.ts b/src/components/YearSpecific/Speakers/Speakers.style.ts index c236dffb8..595e6db47 100644 --- a/src/components/YearSpecific/Speakers/Speakers.style.ts +++ b/src/components/YearSpecific/Speakers/Speakers.style.ts @@ -1,10 +1,7 @@ import { styled } from "styled-components"; -import { motion } from "framer-motion"; -import { - BIG_BREAKPOINT, - TABLET_BREAKPOINT, -} from "../../../constants/BreakPoints"; -import { Color } from "../../../styles/colors"; +import { motion } from "motion/react"; +import { BIG_BREAKPOINT, TABLET_BREAKPOINT } from "@constants/BreakPoints"; +import { Color } from "@styles/colors"; export const StyledSpeakersSection = styled.section` display: flex; diff --git a/src/hooks/useFetchSpeakers.test.tsx b/src/hooks/useFetchSpeakers.test.tsx index cf269a0bd..0522d4d21 100644 --- a/src/hooks/useFetchSpeakers.test.tsx +++ b/src/hooks/useFetchSpeakers.test.tsx @@ -1,6 +1,7 @@ import { renderHook, waitFor } from "@testing-library/react"; import { useFetchSpeakers } from "./useFetchSpeakers"; import axios from "axios"; +import * as Sentry from "@sentry/react"; import { speakerAdapter } from "../services/speakerAdapter"; import { IResponse } from "../types/speakers"; import { @@ -9,9 +10,12 @@ import { getQueryClientWrapper, SPEAKER_URLS, } from "../utils/testing/testUtils"; +import { vi } from "vitest"; vi.mock("axios"); +vi.mock("@sentry/react"); const mockedAxios = axios as jest.Mocked; +const mockedSentry = vi.mocked(Sentry); // Create mock speakers const mockSpeaker1 = createMockSpeaker(); @@ -40,9 +44,6 @@ const mockSpeaker2 = createMockSpeaker({ const payload = createMockAxiosResponse([mockSpeaker1, mockSpeaker2]); describe("fetch speaker hook and speaker adapter", () => { - beforeAll(() => { - vi.mock("axios"); - }); beforeEach(() => { vi.clearAllMocks(); }); @@ -56,7 +57,10 @@ describe("fetch speaker hook and speaker adapter", () => { }); await waitFor(() => result.current.isSuccess, {}); await waitFor(() => !result.current.isLoading, {}); - expect(mockedAxios.get).toHaveBeenCalledWith(SPEAKER_URLS.DEFAULT); + + expect(mockedAxios.get).toHaveBeenCalledWith(SPEAKER_URLS.DEFAULT, { + headers: { Accept: "application/json; charset=utf-8" }, + }); expect(result.current.isLoading).toEqual(false); expect(result.current.error).toEqual(null); expect(result.current.data).toEqual(speakerAdapter(payload.data)); @@ -75,7 +79,9 @@ describe("fetch speaker hook and speaker adapter", () => { await waitFor(() => result.current.isSuccess); await waitFor(() => !result.current.isLoading, {}); //then - expect(mockedAxios.get).toHaveBeenCalledWith(SPEAKER_URLS.DEFAULT); + expect(mockedAxios.get).toHaveBeenCalledWith(SPEAKER_URLS.DEFAULT, { + headers: { Accept: "application/json; charset=utf-8" }, + }); expect(result.current.data).toEqual(speakerAdapter(expectedPayload)); }); @@ -88,7 +94,10 @@ describe("fetch speaker hook and speaker adapter", () => { }); await waitFor(() => result.current.isSuccess, {}); await waitFor(() => !result.current.isLoading, {}); - expect(mockedAxios.get).toHaveBeenCalledWith(SPEAKER_URLS["2023"]); + + expect(mockedAxios.get).toHaveBeenCalledWith(SPEAKER_URLS["2023"], { + headers: { Accept: "application/json; charset=utf-8" }, + }); expect(result.current.isLoading).toEqual(false); expect(result.current.error).toEqual(null); expect(result.current.data).toEqual(speakerAdapter(payload.data)); @@ -103,7 +112,10 @@ describe("fetch speaker hook and speaker adapter", () => { }); await waitFor(() => result.current.isSuccess, {}); await waitFor(() => !result.current.isLoading, {}); - expect(mockedAxios.get).toHaveBeenCalledWith(SPEAKER_URLS["2024"]); + + expect(mockedAxios.get).toHaveBeenCalledWith(SPEAKER_URLS["2024"], { + headers: { Accept: "application/json; charset=utf-8" }, + }); expect(result.current.isLoading).toEqual(false); expect(result.current.error).toEqual(null); expect(result.current.data).toEqual(speakerAdapter(payload.data)); @@ -119,7 +131,10 @@ describe("fetch speaker hook and speaker adapter", () => { }); await waitFor(() => result.current.isSuccess, {}); await waitFor(() => !result.current.isLoading, {}); - expect(mockedAxios.get).toHaveBeenCalledWith(customUrl); + + expect(mockedAxios.get).toHaveBeenCalledWith(customUrl, { + headers: { Accept: "application/json; charset=utf-8" }, + }); expect(result.current.isLoading).toEqual(false); expect(result.current.error).toEqual(null); expect(result.current.data).toEqual(speakerAdapter(payload.data)); @@ -139,7 +154,69 @@ describe("fetch speaker hook and speaker adapter", () => { await waitFor(() => result.current.isSuccess); await waitFor(() => !result.current.isLoading, {}); //then - expect(mockedAxios.get).toHaveBeenCalledWith(customUrl); + expect(mockedAxios.get).toHaveBeenCalledWith(customUrl, { + headers: { Accept: "application/json; charset=utf-8" }, + }); expect(result.current.data).toEqual(speakerAdapter(expectedPayload)); }); + + it("should handle network errors and report to Sentry", async () => { + // Given + const { wrapper } = getQueryClientWrapper(); + const networkError = new Error("Network Error"); + mockedAxios.get.mockRejectedValueOnce(networkError); + + // When + const { result } = renderHook(() => useFetchSpeakers(), { + wrapper, + }); + await waitFor(() => result.current.isSuccess); + + // Then + expect(mockedAxios.get).toHaveBeenCalledWith(SPEAKER_URLS.DEFAULT, { + headers: { Accept: "application/json; charset=utf-8" }, + }); + expect(mockedSentry.captureException).toHaveBeenCalledWith(networkError); + expect(result.current.data).toEqual({}); + }); + + it("should handle CORS errors with proper headers", async () => { + // Given + const { wrapper } = getQueryClientWrapper(); + const corsError = new Error("Failed to fetch"); + corsError.name = "TypeError"; + mockedAxios.get.mockRejectedValueOnce(corsError); + + // When + const { result } = renderHook(() => useFetchSpeakers(), { + wrapper, + }); + await waitFor(() => result.current.isSuccess); + + // Then + expect(mockedAxios.get).toHaveBeenCalledWith(SPEAKER_URLS.DEFAULT, { + headers: { Accept: "application/json; charset=utf-8" }, + }); + expect(mockedSentry.captureException).toHaveBeenCalledWith(corsError); + expect(result.current.data).toEqual({}); + }); + + it("should handle empty responses", async () => { + // Given + const { wrapper } = getQueryClientWrapper(); + const emptyPayload = createMockAxiosResponse([]); + mockedAxios.get.mockResolvedValueOnce(emptyPayload); + + // When + const { result } = renderHook(() => useFetchSpeakers(), { + wrapper, + }); + await waitFor(() => result.current.isSuccess); + + // Then + expect(mockedAxios.get).toHaveBeenCalledWith(SPEAKER_URLS.DEFAULT, { + headers: { Accept: "application/json; charset=utf-8" }, + }); + expect(result.current.data).toEqual(speakerAdapter([])); + }); }); diff --git a/src/hooks/useFetchSpeakers.ts b/src/hooks/useFetchSpeakers.ts index 4d980f8f9..d4aa30c34 100644 --- a/src/hooks/useFetchSpeakers.ts +++ b/src/hooks/useFetchSpeakers.ts @@ -1,6 +1,7 @@ import { useQuery, UseQueryResult } from "react-query"; import axios from "axios"; import { speakerAdapter } from "@services/speakerAdapter"; +import * as Sentry from "@sentry/react"; // @ts-expect-error some weird error when importing types import { IResponse, ISpeaker } from "@types/speakers"; @@ -14,36 +15,37 @@ export const useFetchSpeakers = ( yearOrUrl?: string, id?: string, ): UseQueryResult => { - // Determine if the first parameter is a URL or an ID let url = URLS.default; let speakerId = id; if (yearOrUrl) { - // If urlOrId starts with http, it's a URL if (yearOrUrl.startsWith("http")) { url = yearOrUrl; - } - // If urlOrId is a year key in URLS, use that URL - else if (yearOrUrl in URLS) { + } else if (yearOrUrl in URLS) { url = URLS[yearOrUrl as keyof typeof URLS]; - } - // Otherwise, it's an ID - else { + } else { speakerId = yearOrUrl; } } return useQuery("api-speakers", async () => { - const serverResponse = await axios.get(url); - let returnData: IResponse[]; - if (speakerId !== undefined) { - returnData = serverResponse.data.filter( - (speaker: { id: string }) => speaker.id === speakerId, - ); - } else { - returnData = serverResponse.data; - } + try { + const serverResponse = await axios.get(url, { + headers: { Accept: "application/json; charset=utf-8" }, + }); + let returnData: IResponse[]; + if (speakerId !== undefined) { + returnData = serverResponse.data.filter( + (speaker: { id: string }) => speaker.id === speakerId, + ); + } else { + returnData = serverResponse.data; + } - return speakerAdapter(returnData); + return speakerAdapter(returnData); + } catch (e) { + Sentry.captureException(e); + return {}; + } }); }; diff --git a/src/hooks/useFetchTalks.test.tsx b/src/hooks/useFetchTalks.test.tsx index 99df8d0ae..2b9f4babf 100644 --- a/src/hooks/useFetchTalks.test.tsx +++ b/src/hooks/useFetchTalks.test.tsx @@ -15,10 +15,10 @@ import { getQueryClientWrapper, SESSION_URLS, } from "../utils/testing/testUtils"; -import { vi } from "vitest"; +import { type MockedFunction, vi } from "vitest"; vi.mock("axios"); -const mockedAxios = axios as jest.Mocked; +const mockedAxios = axios as unknown as MockedFunction; describe("useFetchTalks", () => { beforeEach(() => { diff --git a/src/views/Home/HomeWrapper.tsx b/src/views/Home/HomeWrapper.tsx index d980e3a8b..685a0a2c9 100644 --- a/src/views/Home/HomeWrapper.tsx +++ b/src/views/Home/HomeWrapper.tsx @@ -36,7 +36,7 @@ const HomeWrapper: FC> = () => { {conferenceData?.carrousel.enabled && ( diff --git a/src/views/Home/components/Faqs/Faqs.style.ts b/src/views/Home/components/Faqs/Faqs.style.ts index 5e0514429..ac43aa68c 100644 --- a/src/views/Home/components/Faqs/Faqs.style.ts +++ b/src/views/Home/components/Faqs/Faqs.style.ts @@ -1,7 +1,7 @@ -import { styled, keyframes } from "styled-components"; -import { Color } from "../../../../styles/colors"; -import { motion } from "framer-motion"; -import { BIG_BREAKPOINT } from "../../../../constants/BreakPoints"; +import { keyframes, styled } from "styled-components"; +import { Color } from "@styles/colors"; +import { motion } from "motion/react"; +import { BIG_BREAKPOINT } from "@constants/BreakPoints"; const revealAnimation = keyframes` from { diff --git a/src/views/Home/components/Home/Style.Home.tsx b/src/views/Home/components/Home/Style.Home.tsx index a3779c703..d3451cd83 100644 --- a/src/views/Home/components/Home/Style.Home.tsx +++ b/src/views/Home/components/Home/Style.Home.tsx @@ -1,10 +1,7 @@ import { styled } from "styled-components"; -import { Color } from "../../../../styles/colors"; -import { motion } from "framer-motion"; -import { - BIG_BREAKPOINT, - BIGGER_BREAKPOINT, -} from "../../../../constants/BreakPoints"; +import { Color } from "@styles/colors"; +import { motion } from "motion/react"; +import { BIG_BREAKPOINT, BIGGER_BREAKPOINT } from "@constants/BreakPoints"; export const StyledHomeImage = styled.div` padding: 70px 0 40px; diff --git a/src/views/Home/components/Sponsors/Sponsors.style.ts b/src/views/Home/components/Sponsors/Sponsors.style.ts index ba7d093af..1a18abd4f 100644 --- a/src/views/Home/components/Sponsors/Sponsors.style.ts +++ b/src/views/Home/components/Sponsors/Sponsors.style.ts @@ -1,6 +1,6 @@ import { styled } from "styled-components"; import { BIG_BREAKPOINT, LARGE_BREAKPOINT } from "@constants/BreakPoints"; -import { motion } from "framer-motion"; +import { motion } from "motion/react"; const SponsorMargin = 11; const sponsorMarginDesktop = 11; diff --git a/src/views/MeetingDetail/Style.MeetingDetail.tsx b/src/views/MeetingDetail/Style.MeetingDetail.tsx index 890a7f799..ef401711f 100644 --- a/src/views/MeetingDetail/Style.MeetingDetail.tsx +++ b/src/views/MeetingDetail/Style.MeetingDetail.tsx @@ -1,7 +1,7 @@ import { styled } from "styled-components"; -import { BIG_BREAKPOINT, LARGE_BREAKPOINT } from "../../constants/BreakPoints"; -import { motion } from "framer-motion"; -import { Color } from "../../styles/colors"; +import { BIG_BREAKPOINT, LARGE_BREAKPOINT } from "@constants/BreakPoints"; +import { motion } from "motion/react"; +import { Color } from "@styles/colors"; export const StyledContainer = styled.div` padding-top: 2rem; @@ -51,10 +51,11 @@ export const StyledDescription = styled.p` `; export const StyledExtraInfo = styled.p` - { - margin-top: 10px; - color: ${Color.LIGHT_BLUE}; - } +{ + margin-top: 10px; + color: ${Color.LIGHT_BLUE}; +} + & strong { color: ${Color.DARK_BLUE}; } @@ -153,10 +154,11 @@ export const StyledRightContainer = styled.div` `; export const StyledNameContainer = styled.div` - { - width: 50%; - text-align: center; - } +{ + width: 50%; + text-align: center; +} + & a { text-decoration: none; color: ${Color.LIGHT_BLUE}; diff --git a/src/views/SpeakerDetail/Speaker.style.ts b/src/views/SpeakerDetail/Speaker.style.ts index 7201f2607..a4c54fb55 100644 --- a/src/views/SpeakerDetail/Speaker.style.ts +++ b/src/views/SpeakerDetail/Speaker.style.ts @@ -1,11 +1,11 @@ -import { styled, keyframes } from "styled-components"; -import { Color } from "../../styles/colors"; +import { keyframes, styled } from "styled-components"; +import { Color } from "@styles/colors"; import { BIG_BREAKPOINT, LARGE_BREAKPOINT, TABLET_BREAKPOINT, -} from "../../constants/BreakPoints"; -import { motion } from "framer-motion"; +} from "@constants/BreakPoints"; +import { motion } from "motion/react"; const revealAnimation = keyframes` from { diff --git a/src/views/SpeakerDetail/SpeakerDetail.style.ts b/src/views/SpeakerDetail/SpeakerDetail.style.ts index aa8535fbb..fbced34ec 100644 --- a/src/views/SpeakerDetail/SpeakerDetail.style.ts +++ b/src/views/SpeakerDetail/SpeakerDetail.style.ts @@ -1,7 +1,7 @@ import { styled } from "styled-components"; -import { motion } from "framer-motion"; -import { BIG_BREAKPOINT } from "../../constants/BreakPoints"; -import { Color } from "../../styles/colors"; +import { motion } from "motion/react"; +import { BIG_BREAKPOINT } from "@constants/BreakPoints"; +import { Color } from "@styles/colors"; import { Link } from "react-router"; /* eslint-disable @typescript-eslint/no-unused-expressions*/ diff --git a/src/views/Speakers/Speakers.style.ts b/src/views/Speakers/Speakers.style.ts index b2d35531a..595e6db47 100644 --- a/src/views/Speakers/Speakers.style.ts +++ b/src/views/Speakers/Speakers.style.ts @@ -1,7 +1,7 @@ import { styled } from "styled-components"; -import { motion } from "framer-motion"; -import { BIG_BREAKPOINT, TABLET_BREAKPOINT } from "../../constants/BreakPoints"; -import { Color } from "../../styles/colors"; +import { motion } from "motion/react"; +import { BIG_BREAKPOINT, TABLET_BREAKPOINT } from "@constants/BreakPoints"; +import { Color } from "@styles/colors"; export const StyledSpeakersSection = styled.section` display: flex; From bb9add7ea658674f7100b68ee4c497e05991832a Mon Sep 17 00:00:00 2001 From: Anyul Rivas Date: Wed, 14 May 2025 12:45:37 +0200 Subject: [PATCH 2/2] refactor: return empty array instead of object in useFetchSpeakers and remove unused styles --- src/2023/TalkDetail/Style.MeetingDetail.tsx | 108 +------------------- src/hooks/useFetchSpeakers.test.tsx | 4 +- src/hooks/useFetchSpeakers.ts | 2 +- 3 files changed, 4 insertions(+), 110 deletions(-) diff --git a/src/2023/TalkDetail/Style.MeetingDetail.tsx b/src/2023/TalkDetail/Style.MeetingDetail.tsx index f6931b09f..1ec1deaa3 100644 --- a/src/2023/TalkDetail/Style.MeetingDetail.tsx +++ b/src/2023/TalkDetail/Style.MeetingDetail.tsx @@ -1,5 +1,5 @@ import { styled } from "styled-components"; -import { BIG_BREAKPOINT, LARGE_BREAKPOINT } from "@constants/BreakPoints"; +import { BIG_BREAKPOINT } from "@constants/BreakPoints"; import { motion } from "motion/react"; import { Color } from "@styles/colors"; @@ -51,10 +51,8 @@ export const StyledDescription = styled.p` `; export const StyledExtraInfo = styled.p` -{ margin-top: 10px; color: ${Color.LIGHT_BLUE}; -} & strong { color: ${Color.DARK_BLUE}; @@ -134,18 +132,6 @@ export const StyledDetailsContainer = styled.div` padding: 3rem 0 4rem 3rem; } `; - -export const StyledImageContainer = styled.div` - flex-direction: column; - width: 25%; - padding: 0 1rem; - display: none; - - @media only screen and (min-width: ${BIG_BREAKPOINT}px) { - display: flex; - } -`; - export const StyledRightContainer = styled.div` display: flex; flex-direction: row; @@ -154,10 +140,8 @@ export const StyledRightContainer = styled.div` `; export const StyledNameContainer = styled.div` -{ width: 50%; text-align: center; -} & a { text-decoration: none; @@ -179,93 +163,3 @@ export const StyledName = styled.h3` margin-bottom: 0; } `; - -export const StyledSpeakerImgBorder = styled.div` - width: 100%; - height: 300px; - margin-bottom: 0.75rem; - padding: 0.3rem; - border: 1px solid ${Color.YELLOW}; - - @media only screen and (min-width: ${BIG_BREAKPOINT}px) { - padding: 0.2rem; - height: 200px; - } - - @media only screen and (min-width: ${LARGE_BREAKPOINT}px) { - padding: 0.2rem; - height: 275px; - } -`; - -export const StyledSpeakerImg = styled.div<{ photo: string }>` - width: 100%; - height: 100%; - background-image: url(${({ photo }) => photo}); - background-repeat: no-repeat; - background-position: center; - background-size: cover; -`; - -export const StyledSlashes = styled.img` - width: 80%; - margin-bottom: 0.75rem; - - @media only screen and (min-width: ${BIG_BREAKPOINT}px) { - margin-bottom: 0; - width: 75%; - } -`; - -export const StyledSpeakerTitle = styled.h4` - font-size: 1.15rem; - margin-bottom: 1rem; - - @media only screen and (min-width: ${BIG_BREAKPOINT}px) { - text-align: left; - } -`; - -export const StyledSocialMediaContainer = styled.div` - display: flex; - width: 100%; - justify-content: center; - margin-bottom: 0.75rem; -`; - -export const StyledSpeakerDescription = styled.p` - text-align: justify; - - @media only screen and (min-width: ${BIG_BREAKPOINT}px) { - padding-right: 4rem; - } -`; - -export const StyledLink = styled.a` - text-decoration: none; - color: ${Color.WHITE}; - cursor: pointer; - display: flex; - align-items: center; -`; - -export const StyledSocialMediaIcon = styled.img<{ noMargin?: boolean }>` - height: 1.5rem; - margin-right: ${({ noMargin }) => (noMargin ? "0" : "0.75rem")}; - - @media only screen and (min-width: ${BIG_BREAKPOINT}px) { - margin-right: ${({ noMargin }) => (noMargin ? "0" : "0.5rem")}; - } -`; - -export const StyledAbsoluteSlashes = styled.div` - position: absolute; - display: flex; - align-items: center; - color: ${Color.DARK_BLUE}; - font-size: 2rem; - height: 2rem; - font-weight: 900; - bottom: -0.65rem; - left: 0; -`; diff --git a/src/hooks/useFetchSpeakers.test.tsx b/src/hooks/useFetchSpeakers.test.tsx index 0522d4d21..d15ca353e 100644 --- a/src/hooks/useFetchSpeakers.test.tsx +++ b/src/hooks/useFetchSpeakers.test.tsx @@ -177,7 +177,7 @@ describe("fetch speaker hook and speaker adapter", () => { headers: { Accept: "application/json; charset=utf-8" }, }); expect(mockedSentry.captureException).toHaveBeenCalledWith(networkError); - expect(result.current.data).toEqual({}); + expect(result.current.data).toEqual([]); }); it("should handle CORS errors with proper headers", async () => { @@ -198,7 +198,7 @@ describe("fetch speaker hook and speaker adapter", () => { headers: { Accept: "application/json; charset=utf-8" }, }); expect(mockedSentry.captureException).toHaveBeenCalledWith(corsError); - expect(result.current.data).toEqual({}); + expect(result.current.data).toEqual([]); }); it("should handle empty responses", async () => { diff --git a/src/hooks/useFetchSpeakers.ts b/src/hooks/useFetchSpeakers.ts index d4aa30c34..b83bcd363 100644 --- a/src/hooks/useFetchSpeakers.ts +++ b/src/hooks/useFetchSpeakers.ts @@ -45,7 +45,7 @@ export const useFetchSpeakers = ( return speakerAdapter(returnData); } catch (e) { Sentry.captureException(e); - return {}; + return []; } }); };