]> git.localhorst.tv Git - alttp.git/blob - resources/js/pages/Events.js
tracker descriptions
[alttp.git] / resources / js / pages / Events.js
1 import axios from 'axios';
2 import React from 'react';
3 import { Container } from 'react-bootstrap';
4 import { Helmet } from 'react-helmet';
5 import { useTranslation } from 'react-i18next';
6
7 import CanonicalLinks from '../components/common/CanonicalLinks';
8 import ErrorBoundary from '../components/common/ErrorBoundary';
9 import ErrorMessage from '../components/common/ErrorMessage';
10 import Loading from '../components/common/Loading';
11 import List from '../components/events/List';
12
13 export const Component = () => {
14         const { t } = useTranslation();
15
16         const [error, setError] = React.useState(null);
17         const [loading, setLoading] = React.useState(true);
18         const [events, setEvents] = React.useState([]);
19
20         const fetchEvents = React.useCallback(async (controller) => {
21                 const params = {
22                         order: 'recency',
23                         with: ['description'],
24                 };
25                 try {
26                         const response = await axios.get(`/api/events`, {
27                                 signal: controller.signal,
28                                 params,
29                         });
30                         return response.data || [];
31                 } catch (error) {
32                         if (!axios.isCancel(error)) {
33                                 throw error;
34                         }
35                         return [];
36                 }
37         }, []);
38
39         React.useEffect(() => {
40                 const controller = new AbortController();
41                 setLoading(true);
42                 fetchEvents(controller)
43                         .then(events => {
44                                 setError(null);
45                                 setLoading(false);
46                                 setEvents(events);
47                         })
48                         .catch(error => {
49                                 setError(error);
50                                 setLoading(false);
51                                 setEvents([]);
52                         });
53                 return () => {
54                         controller.abort();
55                 };
56         }, [fetchEvents]);
57
58         const evergreen = React.useMemo(() =>
59                 events.filter(event => !event.start)
60         , [events]);
61         const ongoing = React.useMemo(() =>
62                 events.filter(event => event.start && !event.end)
63         , [events]);
64         const past = React.useMemo(() =>
65                 events.filter(event => event.end)
66         , [events]);
67
68         if (loading) {
69                 return <Loading />;
70         }
71
72         if (error) {
73                 return <ErrorMessage error={error} />;
74         }
75
76         return <ErrorBoundary>
77                 <Helmet>
78                         <title>
79                                 {t('events.heading')}
80                         </title>
81                 </Helmet>
82                 <CanonicalLinks base={`/events`} />
83                 <Container>
84                         <h1>{t('events.ongoing')}</h1>
85                         <List events={ongoing} />
86                         <h1>{t('events.evergreen')}</h1>
87                         <List events={evergreen} />
88                         <h1>{t('events.past')}</h1>
89                         <List events={past} />
90                 </Container>
91         </ErrorBoundary>;
92 };