diff --git a/package.json b/package.json index 9c034f39..212fdc2e 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ }, "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e", "dependencies": { + "dayjs": "^1.11.13", "@apollo/client": "^3.10.8" } } diff --git a/web/__test__/components/UpcomingEventHomeCard.test.tsx b/web/__test__/components/UpcomingEventHomeCard.test.tsx new file mode 100644 index 00000000..62619525 --- /dev/null +++ b/web/__test__/components/UpcomingEventHomeCard.test.tsx @@ -0,0 +1,33 @@ +import { describe, expect, it } from "vitest"; +import { render, screen } from "@testing-library/react"; +import UpcomingEventHomeCard from "../../src/components/UpcomingEventHomeCard"; +import React from "react"; + +const mockEvents = { + Events: [ + { + id: 1, + title: "Test event", + description: "Test description", + subtitle: "Test subtitle", + location: "Test location", + locationLink: "Test link", + eventDateStart: "25 December", + eventDateEnd: "26 December", + isLive: false, + termsAndConditions: "Test terms and conditions", + eventCapacityRemaining: 12, + image: "/uploads/john_doe.jpg", + }, + ], +}; + +describe("UpcomingEventHomeCard", () => { + it("renders the event card", () => { + render(); + expect(screen.getByText("25 December")).toBeInTheDocument(); + expect(screen.getByText("Test event")).toBeInTheDocument(); + const partnerImage = screen.getByAltText("Event Image"); + expect(partnerImage).toHaveAttribute("src", mockEvents.image); + }); +}); diff --git a/web/package.json b/web/package.json index f682ca5f..5d0c2d5c 100644 --- a/web/package.json +++ b/web/package.json @@ -18,6 +18,7 @@ "@types/react-router-dom": "^5.3.3", "@types/react-slick": "^0.23.13", "axios": "^1.6.7", + "dayjs": "^1.11.13", "graphql": "^16.8.2", "react": "^18.2.0", "react-cookies": "^0.1.1", diff --git a/web/src/components/UpcomingEventHomeCard.tsx b/web/src/components/UpcomingEventHomeCard.tsx new file mode 100644 index 00000000..f97107be --- /dev/null +++ b/web/src/components/UpcomingEventHomeCard.tsx @@ -0,0 +1,38 @@ +import { Event } from "../types/types"; + +interface UpcomingEventCardProps { + upcomingEvent: Event; +} + +export default function UpcomingEventHomeCard({ + upcomingEvent, +}: UpcomingEventCardProps) { + const formattedDate = new Date( + upcomingEvent.eventDateStart + ).toLocaleDateString("en-NZ", { + day: "numeric", + month: "long", + }); + + return ( +
+
+ Event Image +

+ {upcomingEvent.title} +

+
+
+
+
+ {formattedDate} +
+
+
+
+ ); +} diff --git a/web/src/components/UpcomingEventHomeSlider.tsx b/web/src/components/UpcomingEventHomeSlider.tsx new file mode 100644 index 00000000..18d2db7a --- /dev/null +++ b/web/src/components/UpcomingEventHomeSlider.tsx @@ -0,0 +1,109 @@ +import Slider from "react-slick"; +import "slick-carousel/slick/slick.css"; +import "slick-carousel/slick/slick-theme.css"; +import { + IoArrowBackCircleOutline, + IoArrowForwardCircleOutline, +} from "react-icons/io5"; +import { useRef } from "react"; +import LoadingSpinner from "./LoadingSpinner"; +import { useQuery, gql } from "@apollo/client"; +import UpcomingEventHomeCard from "./UpcomingEventHomeCard"; +import { GET_EVENTS } from "../graphql/queries"; +import dayjs from "dayjs"; +import { Mapper } from "../utils/Mapper"; +import type { Event } from "../types/types"; + +export default function UpcomingEventHomeSlider() { + const sliderRef = useRef(null); + + const { + loading: eventsLoading, + error: eventsError, + data: eventsData, + } = useQuery(GET_EVENTS); + + if (eventsLoading) { + return ; + } + + if (eventsError) { + return
CMS Offline
; + } + + if (!eventsData) { + return
No data available
; + } + + const events = Mapper.mapToEvents(eventsData); + + const now = dayjs(); // current date and time + const upcomingEvents = events + .filter((event) => dayjs(event.eventDateStart).isAfter(now)) // only future events + .sort((a, b) => dayjs(a.eventDateStart).diff(dayjs(b.eventDateStart))); // sort by start date + + const settings = { + dots: true, + infinite: false, + speed: 500, + slidesToShow: 3, + slidesToScroll: 1, + arrows: false, + responsive: [ + { + breakpoint: 1080, + settings: { + slidesToShow: 2, + }, + }, + { + breakpoint: 800, + settings: { + slidesToShow: 1, + }, + }, + ], + }; + + const next = () => { + sliderRef.current?.slickNext(); + }; + + const previous = () => { + sliderRef.current?.slickPrev(); + }; + + function SliderNoArrow() { + return ( +
+ + {upcomingEvents.map((event) => ( +
+ +
+ ))} +
+
+ ); + } + + return ( +
+
+ +
+
+ +
+
+ +
+
+ ); +} diff --git a/web/src/components/UpcomingEvents.tsx b/web/src/components/UpcomingEvents.tsx index d3c0014b..f8c7b58c 100644 --- a/web/src/components/UpcomingEvents.tsx +++ b/web/src/components/UpcomingEvents.tsx @@ -1,4 +1,4 @@ -import SimpleSlider from "./SimpleSlider"; +import UpcomingEventHomeSlider from "./UpcomingEventHomeSlider"; function UpcomingEvents() { return ( @@ -8,7 +8,7 @@ function UpcomingEvents() { Our Upcoming Events!
- +
diff --git a/yarn.lock b/yarn.lock index dd816149..a98e7ce8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -132,6 +132,11 @@ date-fns@^2.30.0: dependencies: "@babel/runtime" "^7.21.0" +dayjs@^1.11.13: + version "1.11.13" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" + integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"