diff --git a/src/events/components/Registrations/registration.tsx b/src/events/components/Registrations/registration.tsx new file mode 100644 index 00000000..0c54d985 --- /dev/null +++ b/src/events/components/Registrations/registration.tsx @@ -0,0 +1,155 @@ +import React, { FC, useEffect, useState } from 'react'; + +import { listEvents } from '../../api/events'; +import { IEvent } from '../../models/Event'; + +import { faCalendarAlt, faUser } from '@fortawesome/free-regular-svg-icons/'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { DateTime } from 'luxon'; + +import { getEventUrl } from 'core/appUrls'; +import { Link } from 'core/components/Router'; +import { getEventColor } from 'events/models/Event'; + +import style from './styles.less'; + +interface IProps { + event: IEvent; +} + +function timeLeftUntilRegistrationStart(date: string) { + const start = DateTime.fromISO(date); + const now = DateTime.local(); + const diff = start.diff(now, ['days', 'hours', 'minutes']); + + if (diff.days < 0) { + return `i dag ${start.toFormat('HH:mm')}`; + } + + const days = ['man', 'tir', 'ons', 'tor', 'fre', 'lør', 'søn'][start.weekday - 1]; + + return `${days} ${start.toFormat('HH:mm')}`; +} + +function timeLeftUntilRegistrationEnd(date: string) { + const end = DateTime.fromISO(date); + const diff = end.diff(DateTime.local(), ['days', 'hours', 'minutes']); + + if (diff.days < 0) { + return `i dag ${end.toFormat('HH:mm')}`; + } + + const days = ['man', 'tir', 'ons', 'tor', 'fre', 'lør', 'søn'][end.weekday - 1]; + + return `${days} ${end.toFormat('HH:mm')}`; +} + +const Registration: FC = ({ event }) => { + const capacity = `${event.number_of_seats_taken}/${event.max_capacity}`; + const registrationStart = DateTime.fromISO(event.registration_start); + const now = DateTime.local(); + + const registrationText = + registrationStart > now + ? `Påmelding åpner ${timeLeftUntilRegistrationStart(event.registration_start)}` + : `Påmelding stenger ${timeLeftUntilRegistrationEnd(event.registration_end)}`; + + return ( + + +
+ +
+

{event.title}

+

+

+
+ +
+

{DateTime.fromISO(event.start_date).toFormat('dd.MM')}

+
+ +
+

{capacity}

+
+
+ + ); +}; + +export const Registrations: FC = () => { + const [events, setEvents] = useState([]); + + useEffect(() => { + async function fetchUpcomingRegistrations() { + const response = await listEvents({ + ordering: 'attendance_event__registration_end', + page_size: 10, + registration_end__gte: DateTime.local().toISODate(), + registration_start__lte: DateTime.local() + .plus({ days: 8 }) + .toISODate(), + }); + if (response.status === 'success') { + setEvents(response.data.results); + return; + } + + console.log(response.errors); + return []; + } + + fetchUpcomingRegistrations(); + }, []); + + function eventsWithOpenRegistration(events: IEvent[]) { + return events.filter((event) => { + return ( + DateTime.fromISO(event.registration_start) < DateTime.local() && + DateTime.fromISO(event.registration_end) > DateTime.local() + ); + }); + } + + function eventsWithRegistrationNotStarted(events: IEvent[]) { + return events.filter((event) => { + return DateTime.fromISO(event.registration_start) > DateTime.local(); + }); + } + + return ( +
+

Påmeldinger

+
+
+ {eventsWithOpenRegistration(events).length > 0 ? ( +
+

Åpne

+
+ {eventsWithOpenRegistration(events).map((event) => ( + + ))} +
+
+ ) : ( +
Ingen åpne påmeldinger
+ )} +
+
+ {eventsWithRegistrationNotStarted(events).length > 0 ? ( +
+

Åpner snart

+ {eventsWithRegistrationNotStarted(events).map((event) => ( + + ))} +
+ ) : ( +
Ingen kommende påmeldinger neste uke
+ )} +
+
+
+ ); +}; + +export default Registrations; diff --git a/src/events/components/Registrations/styles.less b/src/events/components/Registrations/styles.less new file mode 100644 index 00000000..6ebb776b --- /dev/null +++ b/src/events/components/Registrations/styles.less @@ -0,0 +1,62 @@ +@import '~common/less/constants.less'; +@import '~common/less/mixins.less'; + +@edge-height: 20px; +@colorIndicatorSize: 0.5rem; + +.registrationContainer { + display: flex; + flex-direction: row; + + > div { + flex: 1; + } +} + +.small > span { + margin-right: @colorIndicatorSize / 2; +} + +@media (max-width: @owTabletBreakpoint) { + .registrationContainer { + flex-direction: column; + } +} + +.eventColumn { + display: flex; + flex-direction: column; + + > a { + &:not(:last-child) { + border-bottom: 1px solid @lightGray; + } + &:hover { + outline: 1px solid @blue; + } + } +} + +.small { + display: grid; + grid-template-columns: @colorIndicatorSize * 3 / 2 1fr 1.5rem 2.5rem 1.5rem 3.5rem; + min-height: 4rem; + padding: 0.5rem; + box-sizing: border-box; + grid-gap: 0.25rem; + + > p { + align-self: center; + text-align: left; + color: initial; + } +} + +.icon { + align-self: center; + text-align: right; +} + +.suppText { + width: 40px; +} diff --git a/src/events/models/Event.ts b/src/events/models/Event.ts index c0816bef..5b3243aa 100644 --- a/src/events/models/Event.ts +++ b/src/events/models/Event.ts @@ -108,6 +108,8 @@ export interface AttendeeInfo { export interface IEvent { id: number; title: string; + registration_start: string; + registration_end: string; slug: string; ingress: string; ingress_short: string; diff --git a/src/frontpage/index.tsx b/src/frontpage/index.tsx index ff78afba..49c6804e 100644 --- a/src/frontpage/index.tsx +++ b/src/frontpage/index.tsx @@ -1,4 +1,5 @@ import EventsContainer from 'events/components/EventsContainer'; +import Registrations from 'events/components/Registrations/registration'; import React, { FC } from 'react'; import Articles from './components/Articles'; import ForCompanies from './components/ForCompanies'; @@ -14,6 +15,7 @@ const Frontpage: FC = ({ offlines }) => ( <> +