Skip to content
Snippets Groups Projects
Commit 07f195c7 authored by YAHYAOUI Firas's avatar YAHYAOUI Firas
Browse files

add: events page with infinite scrolling

parent 1873aa28
No related branches found
No related tags found
1 merge request!13add home page and first edition of events page
Pipeline #20193 passed
......@@ -16,6 +16,7 @@
"react": "^18.2.0",
"react-bootstrap": "^2.9.2",
"react-dom": "^18.2.0",
"react-intersection-observer": "^9.5.3",
"react-redux": "^9.1.0",
"react-router-dom": "^6.21.3"
},
......@@ -6173,6 +6174,14 @@
"react": "^18.2.0"
}
},
"node_modules/react-intersection-observer": {
"version": "9.5.3",
"resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-9.5.3.tgz",
"integrity": "sha512-NJzagSdUPS5rPhaLsHXYeJbsvdpbJwL6yCHtMk91hc0ufQ2BnXis+0QQ9NBh6n9n+Q3OyjR6OQLShYbaNBkThQ==",
"peerDependencies": {
"react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
......
......@@ -19,6 +19,7 @@
"react": "^18.2.0",
"react-bootstrap": "^2.9.2",
"react-dom": "^18.2.0",
"react-intersection-observer": "^9.5.3",
"react-redux": "^9.1.0",
"react-router-dom": "^6.21.3"
},
......
import { Button, Card } from "react-bootstrap";
import { Event } from "../models/Event.model";
type EventCardProps = {
event: Event;
};
export default function EventCard({ event }: EventCardProps) {
return (
<Card>
<Card.Img variant="top" src={event.media_url} />
<Card.Body>
<Card.Title>{event.nom}</Card.Title>
<Card.Subtitle className="mb-2 text-muted">{event.rubrique}</Card.Subtitle>
<Card.Subtitle className="mb-2 text-muted">{event.date}</Card.Subtitle>
<Button variant="primary">Voir l'évènement</Button>
</Card.Body>
</Card>
);
}
import { Col, Row } from "react-bootstrap";
import EventCard from "./EventCard";
import { Event } from "../models/Event.model";
type EventsListProps = {
events: Event[];
};
export default function EventsList({ events }: EventsListProps) {
return (
<Row>
{events.map((event) => {
return (
<Col sm={4}>
<EventCard key={event.id_manif} event={event} />
</Col>
);
})}
{/* <Col sm={4}>
<EventCard />
</Col>
<Col sm={4}>
<EventCard />
</Col> */}
</Row>
);
}
import EventsList from "./EventsList";
import { useInView } from "react-intersection-observer";
import { Button } from "react-bootstrap";
import { useEffect } from "react";
import { useGetInfiniteEvents } from "../hooks/useGetInfiniteEventsHook";
export default function EventsPage() {
const [ref, inView] = useInView();
const { data, fetchNextPage, hasNextPage, isFetchingNextPage } = useGetInfiniteEvents();
useEffect(() => {
if (inView) fetchNextPage();
}, [fetchNextPage, inView]);
return (
<>
{data && (
<>
<h1>Evènements</h1>
<EventsList events={data.pages.map((data) => data.events).flat()} />
<Button
ref={ref}
onClick={() => fetchNextPage()}
disabled={!hasNextPage || isFetchingNextPage}
/>
</>
)}
</>
);
}
import { useInfiniteQuery } from "@tanstack/react-query";
import { getEvents } from "../utils";
export const useGetInfiniteEvents = () => {
return useInfiniteQuery({
queryKey: ["events", "infinite"],
queryFn: async ({ pageParam }) => await getEvents(12, pageParam),
initialPageParam: 1,
getNextPageParam: (lastPage) => lastPage.nextPage,
getPreviousPageParam: (firstPage) => firstPage.previousPage,
});
}
\ No newline at end of file
......@@ -5,6 +5,7 @@ import { Provider } from "react-redux";
import { store } from "./store.ts";
import { RouterProvider, createBrowserRouter } from "react-router-dom";
import Accueil from "./components/Accueil.tsx";
import EventsPage from "./components/EventsPage.tsx";
const router = createBrowserRouter([
{
......@@ -25,11 +26,7 @@ const router = createBrowserRouter([
},
{
path: "/events",
element: (
<>
<h1>Evènements</h1>
</>
),
element: <EventsPage />,
},
{
path: "/login",
......
export type Event = {
id_manif: string;
nom: string;
description: string;
libelle_festival: string | null;
emetteur: string;
rubrique: string;
categorie_1: string;
categorie_2: string | null;
categorie_3: string | null;
categorie_4: string | null;
categorie_5: string | null;
precisions_public: string;
accueil_enfant: 'oui' | 'non';
date: string;
heure_debut: string;
heure_fin: string | null;
complet: 'oui' | 'non';
annule: 'oui' | 'non';
reporte: 'oui' | 'non';
date_report: string | null;
organisateurs: string | null;
lieu: string;
adresse: string;
ville: string;
code_postal: string;
lieu_quartier: string;
lieu_siteweb: string | null;
lieu_tel: string | null;
lieu_email: string | null;
gratuit: 'oui' | 'non';
precisions_tarifs: string | null;
carte_blanche: 'oui' | 'non';
info_suppl: string | null;
h_auditif: 'oui' | 'non';
h_hyperacousie: 'oui' | 'non';
h_intellectuel: 'oui' | 'non';
h_lsf: 'oui' | 'non';
h_moteur: 'oui' | 'non';
h_psychique: 'oui' | 'non';
h_visuel: 'oui' | 'non';
lien_agenda: string;
latitude: number;
longitude: number;
location: string;
type: string;
courriel: string | null;
libelle_courriel: string | null;
libelle_site: string | null;
libelle_telephone: string | null;
media_url: string;
telephone: string | null;
url_site: string | null;
location_latlong: {
lon: number;
lat: number;
};
location_lieu: {
lon: number;
lat: number;
};
}
export type EventsResponse = {
total_count: number,
results: Event[]
}
\ No newline at end of file
......@@ -2,9 +2,21 @@ import axios from "axios";
import { Arret } from "./models/Arret.model";
import { Horaire } from "./models/Horaire.model";
import { RemainingTime } from "./models/RemainingTime.model";
import { EventsResponse } from "./models/Event.model";
const URL = `https://hackathon-login.osc-fr1.scalingo.io`;
export const getEvents = async (limit: number, page: number) => {
const offset = (page-1) * limit;
const result = await axios.get<EventsResponse>(`https://data.nantesmetropole.fr/api/explore/v2.1/catalog/datasets/244400404_agenda-evenements-nantes-nantes-metropole/records?limit=${limit}&offset=${offset}`);
const hasNext = offset + limit < result.data.total_count;
return {
nextPage: hasNext ? page + 1 : undefined,
previousPage: page > 1 ? page : undefined,
events: result.data.results
}
}
export const getPaginated = (data: Array<object>, page: number) => {
const hasNext = page * 10 < data.length;
const startIndex = (page - 1) * 10;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment