]> git.localhorst.tv Git - alttp.git/blobdiff - resources/js/pages/Events.js
events overview
[alttp.git] / resources / js / pages / Events.js
diff --git a/resources/js/pages/Events.js b/resources/js/pages/Events.js
new file mode 100644 (file)
index 0000000..dd24865
--- /dev/null
@@ -0,0 +1,94 @@
+import axios from 'axios';
+import React from 'react';
+import { Container } from 'react-bootstrap';
+import { Helmet } from 'react-helmet';
+import { useTranslation } from 'react-i18next';
+
+import CanonicalLinks from '../components/common/CanonicalLinks';
+import ErrorBoundary from '../components/common/ErrorBoundary';
+import ErrorMessage from '../components/common/ErrorMessage';
+import Loading from '../components/common/Loading';
+import List from '../components/events/List';
+
+const Events = () => {
+       const { t } = useTranslation();
+
+       const [error, setError] = React.useState(null);
+       const [loading, setLoading] = React.useState(true);
+       const [events, setEvents] = React.useState([]);
+
+       const fetchEvents = React.useCallback(async (controller) => {
+               const params = {
+                       order: 'recency',
+                       with: ['description'],
+               };
+               try {
+                       const response = await axios.get(`/api/events`, {
+                               signal: controller.signal,
+                               params,
+                       });
+                       return response.data || [];
+               } catch (error) {
+                       if (!axios.isCancel(error)) {
+                               throw error;
+                       }
+                       return [];
+               }
+       }, []);
+
+       React.useEffect(() => {
+               const controller = new AbortController();
+               setLoading(true);
+               fetchEvents(controller)
+                       .then(events => {
+                               setError(null);
+                               setLoading(false);
+                               setEvents(events);
+                       })
+                       .catch(error => {
+                               setError(error);
+                               setLoading(false);
+                               setEvents([]);
+                       });
+               return () => {
+                       controller.abort();
+               };
+       }, [fetchEvents]);
+
+       const evergreen = React.useMemo(() =>
+               events.filter(event => !event.start)
+       , [events]);
+       const ongoing = React.useMemo(() =>
+               events.filter(event => event.start && !event.end)
+       , [events]);
+       const past = React.useMemo(() =>
+               events.filter(event => event.end)
+       , [events]);
+
+       if (loading) {
+               return <Loading />;
+       }
+
+       if (error) {
+               return <ErrorMessage error={error} />;
+       }
+
+       return <ErrorBoundary>
+               <Helmet>
+                       <title>
+                               {t('events.heading')}
+                       </title>
+               </Helmet>
+               <CanonicalLinks base={`/events`} />
+               <Container>
+                       <h1>{t('events.ongoing')}</h1>
+                       <List events={ongoing} />
+                       <h1>{t('events.evergreen')}</h1>
+                       <List events={evergreen} />
+                       <h1>{t('events.past')}</h1>
+                       <List events={past} />
+               </Container>
+       </ErrorBoundary>;
+};
+
+export default Events;