Migrate AvailabilityEditor
This commit is contained in:
parent
1a6d34ac59
commit
5abba62c66
11 changed files with 277 additions and 219 deletions
|
|
@ -1,23 +1,31 @@
|
|||
'use client'
|
||||
|
||||
import { useMemo, useState } from 'react'
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { Trans } from 'react-i18next/TransWithoutContext'
|
||||
|
||||
import AvailabilityEditor from '/src/components/AvailabilityEditor/AvailabilityEditor'
|
||||
import AvailabilityViewer from '/src/components/AvailabilityViewer/AvailabilityViewer'
|
||||
import Content from '/src/components/Content/Content'
|
||||
import Login from '/src/components/Login/Login'
|
||||
import Section from '/src/components/Section/Section'
|
||||
import SelectField from '/src/components/SelectField/SelectField'
|
||||
import { EventResponse, PersonResponse } from '/src/config/api'
|
||||
import { EventResponse, getPeople, PersonResponse, updatePerson } from '/src/config/api'
|
||||
import { useTranslation } from '/src/i18n/client'
|
||||
import timezones from '/src/res/timezones.json'
|
||||
import useRecentsStore from '/src/stores/recentsStore'
|
||||
import { expandTimes, makeClass } from '/src/utils'
|
||||
|
||||
import styles from './page.module.scss'
|
||||
|
||||
const EventAvailabilities = ({ event, people }: { event: EventResponse, people: PersonResponse[] }) => {
|
||||
interface EventAvailabilitiesProps {
|
||||
event: EventResponse
|
||||
people: PersonResponse[]
|
||||
}
|
||||
|
||||
const EventAvailabilities = ({ event, ...data }: EventAvailabilitiesProps) => {
|
||||
const { t, i18n } = useTranslation('event')
|
||||
|
||||
const [people, setPeople] = useState(data.people)
|
||||
const expandedTimes = useMemo(() => expandTimes(event.times), [event.times])
|
||||
|
||||
const [user, setUser] = useState<PersonResponse>()
|
||||
|
|
@ -26,12 +34,32 @@ const EventAvailabilities = ({ event, people }: { event: EventResponse, people:
|
|||
const [tab, setTab] = useState<'group' | 'you'>('group')
|
||||
const [timezone, setTimezone] = useState(Intl.DateTimeFormat().resolvedOptions().timeZone)
|
||||
|
||||
// Add this event to recents
|
||||
const addRecent = useRecentsStore(state => state.addRecent)
|
||||
useEffect(() => {
|
||||
addRecent({
|
||||
id: event.id,
|
||||
name: event.name,
|
||||
created_at: event.created_at,
|
||||
})
|
||||
}, [addRecent])
|
||||
|
||||
// Refetch availabilities
|
||||
useEffect(() => {
|
||||
if (tab === 'group') {
|
||||
getPeople(event.id)
|
||||
.then(setPeople)
|
||||
.catch(console.warn)
|
||||
}
|
||||
}, [tab])
|
||||
|
||||
return <>
|
||||
<Section id="login">
|
||||
<Content>
|
||||
<Login eventId={event.id} user={user} onChange={(u, p) => {
|
||||
setUser(u)
|
||||
setPassword(p)
|
||||
setTab(u ? 'you' : 'group')
|
||||
}} />
|
||||
|
||||
<SelectField
|
||||
|
|
@ -107,10 +135,23 @@ const EventAvailabilities = ({ event, people }: { event: EventResponse, people:
|
|||
</div>
|
||||
</Content>
|
||||
|
||||
{tab === 'group' && <AvailabilityViewer
|
||||
{tab === 'group' ? <AvailabilityViewer
|
||||
times={expandedTimes}
|
||||
people={people}
|
||||
timezone={timezone}
|
||||
/> : user && <AvailabilityEditor
|
||||
times={expandedTimes}
|
||||
timezone={timezone}
|
||||
value={user.availability}
|
||||
onChange={availability => {
|
||||
const oldAvailability = [...user.availability]
|
||||
setUser({ ...user, availability })
|
||||
updatePerson(event.id, user.name, { availability }, password)
|
||||
.catch(e => {
|
||||
console.warn(e)
|
||||
setUser({ ...user, availability: oldAvailability })
|
||||
})
|
||||
}}
|
||||
/>}
|
||||
</>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,22 @@
|
|||
'use client'
|
||||
|
||||
import { useEffect } from 'react'
|
||||
|
||||
import Content from '/src/components/Content/Content'
|
||||
import { useTranslation } from '/src/i18n/server'
|
||||
import { useTranslation } from '/src/i18n/client'
|
||||
import useRecentsStore from '/src/stores/recentsStore'
|
||||
|
||||
import styles from './page.module.scss'
|
||||
|
||||
const NotFound = async () => {
|
||||
const { t } = await useTranslation('event')
|
||||
const NotFound = () => {
|
||||
const { t } = useTranslation('event')
|
||||
|
||||
// Remove this event from recents if it was in there
|
||||
const removeRecent = useRecentsStore(state => state.removeRecent)
|
||||
useEffect(() => {
|
||||
// Note: Next.js doesn't expose path params to the 404 page
|
||||
removeRecent(window.location.pathname.replace('/', ''))
|
||||
}, [removeRecent])
|
||||
|
||||
return <Content>
|
||||
<div style={{ marginBlock: 100 }}>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { Trans } from 'react-i18next/TransWithoutContext'
|
||||
import { Metadata } from 'next'
|
||||
import { notFound } from 'next/navigation'
|
||||
import { Temporal } from '@js-temporal/polyfill'
|
||||
|
||||
|
|
@ -11,7 +12,21 @@ import { makeClass, relativeTimeFormat } from '/src/utils'
|
|||
import EventAvailabilities from './EventAvailabilities'
|
||||
import styles from './page.module.scss'
|
||||
|
||||
const Page = async ({ params }: { params: { id: string } }) => {
|
||||
interface PageProps {
|
||||
params: { id: string }
|
||||
}
|
||||
|
||||
export const generateMetadata = async ({ params }: PageProps): Promise<Metadata> => {
|
||||
const event = await getEvent(params.id).catch(() => undefined)
|
||||
const { t } = await useTranslation('event')
|
||||
|
||||
// TODO: More metadata
|
||||
return {
|
||||
title: event?.name ?? t('error.title'),
|
||||
}
|
||||
}
|
||||
|
||||
const Page = async ({ params }: PageProps) => {
|
||||
const event = await getEvent(params.id).catch(() => undefined)
|
||||
const people = await getPeople(params.id).catch(() => undefined)
|
||||
if (!event || !people) notFound()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue