Merge pull request #279 from GRA0007/refactor/optimisations

Loading optimisations
This commit is contained in:
Benji Grant 2023-06-18 18:23:24 +10:00 committed by GitHub
commit f95e794cb7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 311 additions and 239 deletions

View file

@ -19,16 +19,16 @@
"accept-language": "^3.0.18", "accept-language": "^3.0.18",
"chroma.ts": "^1.0.10", "chroma.ts": "^1.0.10",
"hue-map": "^1.0.0", "hue-map": "^1.0.0",
"i18next": "^22.5.1", "i18next": "^23.1.0",
"i18next-browser-languagedetector": "^7.0.2", "i18next-browser-languagedetector": "^7.0.2",
"i18next-http-backend": "^2.2.1", "i18next-http-backend": "^2.2.1",
"i18next-resources-to-backend": "^1.1.4", "i18next-resources-to-backend": "^1.1.4",
"lucide-react": "^0.241.0", "lucide-react": "^0.244.0",
"next": "^13.4.4", "next": "^13.4.6",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-hook-form": "^7.44.3", "react-hook-form": "^7.44.3",
"react-i18next": "^12.3.1", "react-i18next": "^13.0.0",
"zod": "^3.21.4", "zod": "^3.21.4",
"zustand": "^4.3.8" "zustand": "^4.3.8"
}, },
@ -36,15 +36,15 @@
"@types/gapi": "^0.0.44", "@types/gapi": "^0.0.44",
"@types/gapi.calendar": "^3.0.6", "@types/gapi.calendar": "^3.0.6",
"@types/google.accounts": "^0.0.7", "@types/google.accounts": "^0.0.7",
"@types/node": "^20.2.5", "@types/node": "^20.3.1",
"@types/react": "^18.2.9", "@types/react": "^18.2.12",
"@types/react-dom": "^18.2.4", "@types/react-dom": "^18.2.5",
"@typescript-eslint/eslint-plugin": "^5.59.9", "@typescript-eslint/eslint-plugin": "^5.59.11",
"@typescript-eslint/parser": "^5.59.9", "@typescript-eslint/parser": "^5.59.11",
"eslint": "^8.42.0", "eslint": "^8.43.0",
"eslint-config-next": "^13.4.4", "eslint-config-next": "^13.4.6",
"eslint-plugin-simple-import-sort": "^10.0.0", "eslint-plugin-simple-import-sort": "^10.0.0",
"sass": "^1.63.2", "sass": "^1.63.4",
"typescript": "^5.1.3", "typescript": "^5.1.3",
"typescript-plugin-css-modules": "^5.0.1" "typescript-plugin-css-modules": "^5.0.1"
} }

View file

@ -1,6 +1,6 @@
'use client' 'use client'
import { useEffect, useMemo, useState } from 'react' import { useEffect, useMemo, useRef, useState } from 'react'
import { Trans } from 'react-i18next/TransWithoutContext' import { Trans } from 'react-i18next/TransWithoutContext'
import AvailabilityEditor from '/src/components/AvailabilityEditor/AvailabilityEditor' import AvailabilityEditor from '/src/components/AvailabilityEditor/AvailabilityEditor'
@ -20,17 +20,16 @@ import { calculateTable, expandTimes, makeClass } from '/src/utils'
import styles from './page.module.scss' import styles from './page.module.scss'
interface EventAvailabilitiesProps { interface EventAvailabilitiesProps {
event: EventResponse event?: EventResponse
people: PersonResponse[]
} }
const EventAvailabilities = ({ event, ...data }: EventAvailabilitiesProps) => { const EventAvailabilities = ({ event }: EventAvailabilitiesProps) => {
const { t, i18n } = useTranslation('event') const { t, i18n } = useTranslation('event')
const timeFormat = useStore(useSettingsStore, state => state.timeFormat) ?? '12h' const timeFormat = useStore(useSettingsStore, state => state.timeFormat) ?? '12h'
const [people, setPeople] = useState(data.people) const [people, setPeople] = useState<PersonResponse[]>([])
const expandedTimes = useMemo(() => expandTimes(event.times), [event.times]) const expandedTimes = useMemo(() => expandTimes(event?.times ?? []), [event?.times])
const [user, setUser] = useState<PersonResponse>() const [user, setUser] = useState<PersonResponse>()
const [password, setPassword] = useState<string>() const [password, setPassword] = useState<string>()
@ -39,40 +38,42 @@ const EventAvailabilities = ({ event, ...data }: EventAvailabilitiesProps) => {
const [timezone, setTimezone] = useState(Intl.DateTimeFormat().resolvedOptions().timeZone) const [timezone, setTimezone] = useState(Intl.DateTimeFormat().resolvedOptions().timeZone)
// Web worker for calculating the heatmap table // Web worker for calculating the heatmap table
const tableWorker = useMemo(() => (typeof window !== undefined && window.Worker) ? new Worker(new URL('/src/workers/calculateTable', import.meta.url)) : undefined, []) const tableWorker = useRef<Worker>()
// Calculate table (using a web worker if available) // Calculate table (using a web worker if available)
const [table, setTable] = useState<ReturnType<typeof calculateTable>>() const [table, setTable] = useState<ReturnType<typeof calculateTable>>()
useEffect(() => { useEffect(() => {
const args = { times: expandedTimes, locale: i18n.language, timeFormat, timezone } if (event && expandTimes.length > 0) {
if (tableWorker) { if (!tableWorker.current) {
tableWorker.postMessage(args) tableWorker.current = window.Worker ? new Worker(new URL('/src/workers/calculateTable', import.meta.url)) : undefined
setTable(undefined) }
} else { const args = { times: expandedTimes, locale: i18n.language, timeFormat, timezone }
setTable(calculateTable(args)) if (tableWorker.current) {
tableWorker.current.onmessage = (e: MessageEvent<ReturnType<typeof calculateTable>>) => setTable(e.data)
tableWorker.current.postMessage(args)
setTable(undefined)
} else {
setTable(calculateTable(args))
}
} }
}, [tableWorker, expandedTimes, i18n.language, timeFormat, timezone]) }, [expandedTimes, i18n.language, timeFormat, timezone])
useEffect(() => {
if (tableWorker) {
tableWorker.onmessage = (e: MessageEvent<ReturnType<typeof calculateTable>>) => setTable(e.data)
}
}, [tableWorker])
// Add this event to recents // Add this event to recents
const addRecent = useRecentsStore(state => state.addRecent) const addRecent = useRecentsStore(state => state.addRecent)
useEffect(() => { useEffect(() => {
addRecent({ if (event) {
id: event.id, addRecent({
name: event.name, id: event.id,
created_at: event.created_at, name: event.name,
}) created_at: event.created_at,
})
}
}, [addRecent]) }, [addRecent])
// Refetch availabilities // Refetch availabilities
useEffect(() => { useEffect(() => {
if (tab === 'group') { if (tab === 'group' && event) {
getPeople(event.id) getPeople(event.id)
.then(setPeople) .then(setPeople)
.catch(console.warn) .catch(console.warn)
@ -82,7 +83,7 @@ const EventAvailabilities = ({ event, ...data }: EventAvailabilitiesProps) => {
return <> return <>
<Section id="login"> <Section id="login">
<Content> <Content>
<Login eventId={event.id} user={user} onChange={(u, p) => { <Login eventId={event?.id} user={user} onChange={(u, p) => {
setUser(u) setUser(u)
setPassword(p) setPassword(p)
setTab(u ? 'you' : 'group') setTab(u ? 'you' : 'group')
@ -148,7 +149,7 @@ const EventAvailabilities = ({ event, ...data }: EventAvailabilitiesProps) => {
document.dispatchEvent(new CustomEvent('focusName')) document.dispatchEvent(new CustomEvent('focusName'))
} }
}} }}
title={user ? '' : t<string>('tabs.you_tooltip')} title={user ? '' : t('tabs.you_tooltip')}
>{t('tabs.you')}</button> >{t('tabs.you')}</button>
<button <button
className={makeClass( className={makeClass(
@ -170,6 +171,7 @@ const EventAvailabilities = ({ event, ...data }: EventAvailabilitiesProps) => {
timezone={timezone} timezone={timezone}
value={user.availability} value={user.availability}
onChange={availability => { onChange={availability => {
if (!event) return
const oldAvailability = [...user.availability] const oldAvailability = [...user.availability]
setUser({ ...user, availability }) setUser({ ...user, availability })
updatePerson(event.id, user.name, { availability }, password) updatePerson(event.id, user.name, { availability }, password)

View file

@ -0,0 +1,17 @@
import EventAvailabilities from '/src/app/[id]/EventAvailabilities'
import Content from '/src/components/Content/Content'
import styles from './page.module.scss'
const Loading = async () => <>
<Content>
<h1 className={styles.name}><span className={styles.bone} /></h1>
<div className={styles.date}><span className={styles.bone} /></div>
<div className={styles.info}><span className={styles.bone} style={{ width: '20em' }} /></div>
<div className={styles.info}><span className={styles.bone} style={{ width: '20em' }} /></div>
</Content>
<EventAvailabilities />
</>
export default Loading

View file

@ -69,3 +69,12 @@
opacity: .5; opacity: .5;
cursor: not-allowed; cursor: not-allowed;
} }
.bone {
width: 12em;
max-width: 100%;
background-color: var(--loading);
border-radius: 3px;
height: 1em;
display: inline-block;
}

View file

@ -1,3 +1,4 @@
import { Suspense } from 'react'
import { Trans } from 'react-i18next/TransWithoutContext' import { Trans } from 'react-i18next/TransWithoutContext'
import { Metadata } from 'next' import { Metadata } from 'next'
import { notFound } from 'next/navigation' import { notFound } from 'next/navigation'
@ -5,7 +6,7 @@ import { Temporal } from '@js-temporal/polyfill'
import Content from '/src/components/Content/Content' import Content from '/src/components/Content/Content'
import Copyable from '/src/components/Copyable/Copyable' import Copyable from '/src/components/Copyable/Copyable'
import { getEvent, getPeople } from '/src/config/api' import { getEvent } from '/src/config/api'
import { useTranslation } from '/src/i18n/server' import { useTranslation } from '/src/i18n/server'
import { makeClass, relativeTimeFormat } from '/src/utils' import { makeClass, relativeTimeFormat } from '/src/utils'
@ -27,12 +28,19 @@ export const generateMetadata = async ({ params }: PageProps): Promise<Metadata>
const Page = async ({ params }: PageProps) => { const Page = async ({ params }: PageProps) => {
const event = await getEvent(params.id).catch(() => undefined) const event = await getEvent(params.id).catch(() => undefined)
const people = await getPeople(params.id).catch(() => undefined) if (!event) notFound()
if (!event || !people) notFound()
const { t, i18n } = await useTranslation(['common', 'event']) const { t, i18n } = await useTranslation(['common', 'event'])
return <> return <>
<Suspense
fallback={<Content>
<h1 className={styles.name}><span className={styles.bone} /></h1>
<div className={styles.date}><span className={styles.bone} /></div>
<div className={styles.info}><span className={styles.bone} style={{ width: '20em' }} /></div>
<div className={styles.info}><span className={styles.bone} style={{ width: '20em' }} /></div>
</Content>}
>
<Content> <Content>
<h1 className={styles.name}>{event.name}</h1> <h1 className={styles.name}>{event.name}</h1>
<span <span
@ -44,11 +52,12 @@ const Page = async ({ params }: PageProps) => {
{`https://crab.fit/${event.id}`} {`https://crab.fit/${event.id}`}
</Copyable> </Copyable>
<p className={makeClass(styles.info, styles.noPrint)}> <p className={makeClass(styles.info, styles.noPrint)}>
<Trans i18nKey="event:nav.shareinfo" t={t} i18n={i18n}>_<a href={`mailto:?subject=${encodeURIComponent(t<string>('event:nav.email_subject', { event_name: event.name }))}&body=${encodeURIComponent(`${t('event:nav.email_body')} https://crab.fit/${event.id}`)}`}>_</a>_</Trans> <Trans i18nKey="event:nav.shareinfo" t={t} i18n={i18n}>_<a href={`mailto:?subject=${encodeURIComponent(t('event:nav.email_subject', { event_name: event.name }))}&body=${encodeURIComponent(`${t('event:nav.email_body')} https://crab.fit/${event.id}`)}`}>_</a>_</Trans>
</p> </p>
</Content> </Content>
</Suspense>
<EventAvailabilities event={event} people={people} /> <EventAvailabilities event={event} />
</> </>
} }

View file

@ -1,3 +1,4 @@
import { Suspense } from 'react'
import { Trans } from 'react-i18next/TransWithoutContext' import { Trans } from 'react-i18next/TransWithoutContext'
import Link from 'next/link' import Link from 'next/link'
@ -31,7 +32,9 @@ const Page = async () => {
<Content> <Content>
<h2>{t('about.name')}</h2> <h2>{t('about.name')}</h2>
<Stats /> <Suspense>
<Stats />
</Suspense>
<P><Trans i18nKey="about.content.p1" t={t} i18n={i18n}>_<br /><Link href="/how-to" rel="help">_</Link>_</Trans></P> <P><Trans i18nKey="about.content.p1" t={t} i18n={i18n}>_<br /><Link href="/how-to" rel="help">_</Link>_</Trans></P>

View file

@ -65,7 +65,7 @@ const AvailabilityEditor = ({ times, timezone, value = [], onChange, table }: Av
<Button isSmall onClick={selectInvert} title="Ctrl + I (⌘ I)">{t('you.select_invert')}</Button> <Button isSmall onClick={selectInvert} title="Ctrl + I (⌘ I)">{t('you.select_invert')}</Button>
</div> </div>
</Content> </Content>
{times[0].length === 13 && <Content> {times[0]?.length === 13 && <Content>
<div style={{ display: 'flex', flexWrap: 'wrap', alignItems: 'center', justifyContent: 'center', gap: 12 }}> <div style={{ display: 'flex', flexWrap: 'wrap', alignItems: 'center', justifyContent: 'center', gap: 12 }}>
<GoogleCalendar <GoogleCalendar
timezone={timezone} timezone={timezone}
@ -106,7 +106,7 @@ const AvailabilityEditor = ({ times, timezone, value = [], onChange, table }: Av
if (!cell) return <div if (!cell) return <div
className={makeClass(viewerStyles.timeSpace, viewerStyles.grey)} className={makeClass(viewerStyles.timeSpace, viewerStyles.grey)}
key={y} key={y}
title={t<string>('greyed_times')} title={t('greyed_times')}
/> />
const isSelected = ( const isSelected = (
@ -162,7 +162,7 @@ const AvailabilityEditor = ({ times, timezone, value = [], onChange, table }: Av
})} })}
</div> </div>
</div> : <div className={viewerStyles.columnSpacer} />} </div> : <div className={viewerStyles.columnSpacer} />}
</Fragment>) ?? <Skeleton isSpecificDates={times[0].length === 13} />} </Fragment>) ?? <Skeleton isSpecificDates={times[0]?.length === 13} />}
</div> </div>
</div> </div>
</div> </div>

View file

@ -70,7 +70,7 @@ const AvailabilityViewer = ({ times, people, table }: AvailabilityViewerProps) =
if (!cell) return <div if (!cell) return <div
className={makeClass(styles.timeSpace, styles.grey)} className={makeClass(styles.timeSpace, styles.grey)}
key={y} key={y}
title={t<string>('greyed_times')} title={t('greyed_times')}
/> />
let peopleHere = availabilities.find(a => a.date === cell.serialized)?.people ?? [] let peopleHere = availabilities.find(a => a.date === cell.serialized)?.people ?? []
@ -106,7 +106,7 @@ const AvailabilityViewer = ({ times, people, table }: AvailabilityViewerProps) =
})} })}
</div> </div>
</div> : <div className={styles.columnSpacer} />} </div> : <div className={styles.columnSpacer} />}
</Fragment>) ?? <Skeleton isSpecificDates={times[0].length === 13} />, [ </Fragment>) ?? <Skeleton isSpecificDates={times[0]?.length === 13} />, [
availabilities, availabilities,
table?.columns, table?.columns,
highlight, highlight,

View file

@ -55,13 +55,13 @@ const Month = ({ value, onChange }: MonthProps) => {
return <> return <>
{useMemo(() => <div className={styles.header}> {useMemo(() => <div className={styles.header}>
<Button <Button
title={t<string>('form.dates.tooltips.previous')} title={t('form.dates.tooltips.previous')}
onClick={() => setPage(page.subtract({ months: 1 }))} onClick={() => setPage(page.subtract({ months: 1 }))}
icon={<ChevronLeft />} icon={<ChevronLeft />}
/> />
<span>{page.toPlainDate({ day: 1 }).toLocaleString(i18n.language, { month: 'long', year: 'numeric' })}</span> <span>{page.toPlainDate({ day: 1 }).toLocaleString(i18n.language, { month: 'long', year: 'numeric' })}</span>
<Button <Button
title={t<string>('form.dates.tooltips.next')} title={t('form.dates.tooltips.next')}
onClick={() => setPage(page.add({ months: 1 }))} onClick={() => setPage(page.add({ months: 1 }))}
icon={<ChevronRight />} icon={<ChevronRight />}
/> />

View file

@ -56,7 +56,7 @@ const Weekdays = ({ value, onChange }: WeekdaysProps) => {
) && styles.selected, ) && styles.selected,
)} )}
key={day.toString()} key={day.toString()}
title={day.equals(Temporal.Now.plainDateISO()) ? t<string>('form.dates.tooltips.today') : undefined} title={day.equals(Temporal.Now.plainDateISO()) ? t('form.dates.tooltips.today') : undefined}
onKeyDown={e => { onKeyDown={e => {
if (e.key === ' ' || e.key === 'Enter') { if (e.key === ' ' || e.key === 'Enter') {
if (value.includes(day.dayOfWeek.toString())) { if (value.includes(day.dayOfWeek.toString())) {

View file

@ -1,6 +1,6 @@
'use client' 'use client'
import { useState } from 'react' import { useEffect, useState } from 'react'
import { useTranslation } from '/src/i18n/client' import { useTranslation } from '/src/i18n/client'
import { makeClass } from '/src/utils' import { makeClass } from '/src/utils'
@ -16,6 +16,9 @@ const Copyable = ({ children, className, ...props }: CopyableProps) => {
const [copied, setCopied] = useState<React.ReactNode>() const [copied, setCopied] = useState<React.ReactNode>()
const [canCopy, setCanCopy] = useState(false)
useEffect(() => { setCanCopy('clipboard' in navigator) }, [])
return <p return <p
onClick={() => navigator.clipboard?.writeText(children) onClick={() => navigator.clipboard?.writeText(children)
.then(() => { .then(() => {
@ -24,8 +27,8 @@ const Copyable = ({ children, className, ...props }: CopyableProps) => {
}) })
.catch(e => console.error('Failed to copy', e)) .catch(e => console.error('Failed to copy', e))
} }
title={'clipboard' in navigator ? t<string>('nav.title') : undefined} title={canCopy ? t('nav.title') : undefined}
className={makeClass(className, 'clipboard' in navigator && styles.copyable)} className={makeClass(className, canCopy && styles.copyable)}
{...props} {...props}
>{copied ?? children}</p> >{copied ?? children}</p>
} }

View file

@ -19,7 +19,7 @@ const EventInfo = ({ event }: EventInfoProps) => {
{`https://crab.fit/${event.id}`} {`https://crab.fit/${event.id}`}
</Copyable> </Copyable>
<p className={styles.info}> <p className={styles.info}>
<Trans i18nKey="event:nav.shareinfo_alt" t={t} i18n={i18n}>_<a href={`mailto:?subject=${encodeURIComponent(t<string>('nav.email_subject', { event_name: event.name }))}&body=${encodeURIComponent(`${t('nav.email_body')} https://crab.fit/${event.id}`)}`} target="_blank">_</a>_</Trans> <Trans i18nKey="event:nav.shareinfo_alt" t={t} i18n={i18n}>_<a href={`mailto:?subject=${encodeURIComponent(t('nav.email_subject', { event_name: event.name }))}&body=${encodeURIComponent(`${t('nav.email_body')} https://crab.fit/${event.id}`)}`} target="_blank">_</a>_</Trans>
</p> </p>
</div> </div>
} }

View file

@ -39,4 +39,10 @@
justify-content: center; justify-content: center;
margin-left: 16px; margin-left: 16px;
padding: 0; padding: 0;
border-radius: .2em;
&:focus-visible {
outline: 2px solid currentColor;
outline-offset: 2px;
}
} }

View file

@ -23,7 +23,7 @@ const Footer = async ({ isSmall }: FooterProps) => {
<span>{t('donate.info')}</span> <span>{t('donate.info')}</span>
<Button <Button
isSmall isSmall
title={t<string>('donate.title')} title={t('donate.title')}
href="https://ko-fi.com/A06841WZ" href="https://ko-fi.com/A06841WZ"
target="_blank" target="_blank"
rel="noreferrer noopener payment" rel="noreferrer noopener payment"

View file

@ -24,7 +24,7 @@ const Legend = ({ min, max, total, palette, onSegmentFocus }: LegendProps) => {
className={styles.bar} className={styles.bar}
onMouseOut={() => onSegmentFocus(undefined)} onMouseOut={() => onSegmentFocus(undefined)}
onClick={() => setHighlight?.(!highlight)} onClick={() => setHighlight?.(!highlight)}
title={t<string>('group.legend_tooltip')} title={t('group.legend_tooltip')}
> >
{[...Array(max + 1 - min).keys()].map(i => i + min).map((i, j) => {[...Array(max + 1 - min).keys()].map(i => i + min).map((i, j) =>
<div <div

View file

@ -5,13 +5,10 @@
grid-gap: 18px; grid-gap: 18px;
@media (max-width: 500px) { @media (max-width: 500px) {
grid-template-columns: 1fr 1fr;
}
@media (max-width: 400px) {
grid-template-columns: 1fr; grid-template-columns: 1fr;
& div:last-child { & div:last-child {
--btn-width: 100%; width: 100%;
} }
} }
} }

View file

@ -15,7 +15,7 @@ const defaultValues = {
} }
interface LoginProps { interface LoginProps {
eventId: string eventId?: string
user: PersonResponse | undefined user: PersonResponse | undefined
onChange: (user: PersonResponse | undefined, password?: string) => void onChange: (user: PersonResponse | undefined, password?: string) => void
} }
@ -50,6 +50,8 @@ const Login = ({ eventId, user, onChange }: LoginProps) => {
setError(undefined) setError(undefined)
try { try {
if (!eventId) throw 'Event ID not set'
const resUser = await getPerson(eventId, username, password || undefined) const resUser = await getPerson(eventId, username, password || undefined)
onChange(resUser, password || undefined) onChange(resUser, password || undefined)
reset() reset()
@ -76,6 +78,7 @@ const Login = ({ eventId, user, onChange }: LoginProps) => {
type="text" type="text"
isInline isInline
required required
disabled={!eventId}
{...register('username')} {...register('username')}
/> />
@ -83,13 +86,14 @@ const Login = ({ eventId, user, onChange }: LoginProps) => {
label={t('form.password')} label={t('form.password')}
type="password" type="password"
isInline isInline
disabled={!eventId}
{...register('password')} {...register('password')}
/> />
<Button <Button
type="submit" type="submit"
isLoading={isLoading} isLoading={isLoading}
disabled={isLoading} disabled={isLoading || !eventId}
>{t('form.button')}</Button> >{t('form.button')}</Button>
</form> </form>
<Error onClose={() => setError(undefined)}>{error}</Error> <Error onClose={() => setError(undefined)}>{error}</Error>

View file

@ -56,7 +56,7 @@ const Settings = () => {
type="button" type="button"
className={makeClass(styles.openButton, isOpen && styles.open)} className={makeClass(styles.openButton, isOpen && styles.open)}
onClick={() => setIsOpen(!isOpen)} onClick={() => setIsOpen(!isOpen)}
title={t<string>('options.name')} title={t('options.name')}
><SettingsIcon /></button> ><SettingsIcon /></button>
<dialog <dialog

View file

@ -17,7 +17,7 @@ const Video = () => {
width="560" width="560"
height="315" height="315"
src="https://www.youtube.com/embed/yXGd4VXZzcY?modestbranding=1&rel=0&autoplay=1" src="https://www.youtube.com/embed/yXGd4VXZzcY?modestbranding=1&rel=0&autoplay=1"
title={t<string>('video.title')} title={t('video.title')}
frameBorder="0" frameBorder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen allowFullScreen
@ -34,7 +34,7 @@ const Video = () => {
setIsPlaying(true) setIsPlaying(true)
}} }}
> >
<img src={video_thumb.src} alt={t<string>('video.button')} /> <img src={video_thumb.src} alt={t('video.button')} />
<span>{t('video.button')}</span> <span>{t('video.button')}</span>
</a> </a>
) )

View file

@ -43,11 +43,12 @@ export const StatsResponse = z.object({
}) })
export type StatsResponse = z.infer<typeof StatsResponse> export type StatsResponse = z.infer<typeof StatsResponse>
const get = async <S extends z.Schema>(url: string, schema: S, auth?: string): Promise<ReturnType<S['parse']>> => { const get = async <S extends z.Schema>(url: string, schema: S, auth?: string, nextOptions?: NextFetchRequestConfig): Promise<ReturnType<S['parse']>> => {
const res = await fetch(new URL(url, API_BASE), { const res = await fetch(new URL(url, API_BASE), {
headers: { headers: {
...auth && { Authorization: `Bearer ${auth}` }, ...auth && { Authorization: `Bearer ${auth}` },
} },
next: nextOptions,
}) })
.catch(console.warn) .catch(console.warn)
if (!res?.ok) throw res if (!res?.ok) throw res
@ -69,7 +70,7 @@ const post = async <S extends z.Schema>(url: string, schema: S, input: unknown,
} }
// Get // Get
export const getStats = () => get('/stats', StatsResponse) export const getStats = () => get('/stats', StatsResponse, undefined, { revalidate: 60 })
export const getEvent = (eventId: string) => get(`/event/${eventId}`, EventResponse) export const getEvent = (eventId: string) => get(`/event/${eventId}`, EventResponse)
export const getPeople = (eventId: string) => get(`/event/${eventId}/people`, PersonResponse.array()) export const getPeople = (eventId: string) => get(`/event/${eventId}/people`, PersonResponse.array())
export const getPerson = (eventId: string, personName: string, password?: string) => get(`/event/${eventId}/people/${personName}`, PersonResponse, password && btoa(password)) export const getPerson = (eventId: string, personName: string, password?: string) => get(`/event/${eventId}/people/${personName}`, PersonResponse, password && btoa(password))

View file

@ -23,8 +23,8 @@ interface AvailabilityInfo {
* group availability for each date passed in. * group availability for each date passed in.
*/ */
export const calculateAvailability = (dates: string[], people: Person[]): AvailabilityInfo => { export const calculateAvailability = (dates: string[], people: Person[]): AvailabilityInfo => {
let min = Infinity let min = 0
let max = -Infinity let max = people.length
const availabilities: Availability[] = dates.map(date => { const availabilities: Availability[] = dates.map(date => {
const names = people.flatMap(p => p.availability.some(d => d === date) ? [p.name] : []) const names = people.flatMap(p => p.availability.some(d => d === date) ? [p.name] : [])

View file

@ -26,7 +26,7 @@ export const calculateTable = ({
const columns = calculateColumns(dates) const columns = calculateColumns(dates)
// Is specific dates or just days of the week // Is specific dates or just days of the week
const isSpecificDates = times[0].length === 13 const isSpecificDates = times[0]?.length === 13
return { return {
rows: rows.map(row => row && row.minute === 0 ? { rows: rows.map(row => row && row.minute === 0 ? {

View file

@ -6,7 +6,7 @@ import { Temporal } from '@js-temporal/polyfill'
* @param timezone The target timezone * @param timezone The target timezone
*/ */
export const convertTimesToDates = (times: string[], timezone: string): Temporal.ZonedDateTime[] => { export const convertTimesToDates = (times: string[], timezone: string): Temporal.ZonedDateTime[] => {
const isSpecificDates = times[0].length === 13 const isSpecificDates = times[0]?.length === 13
return times.map(time => isSpecificDates ? return times.map(time => isSpecificDates ?
parseSpecificDate(time).withTimeZone(timezone) parseSpecificDate(time).withTimeZone(timezone)

View file

@ -26,13 +26,20 @@
dependencies: dependencies:
regenerator-runtime "^0.13.4" regenerator-runtime "^0.13.4"
"@babel/runtime@^7.19.4", "@babel/runtime@^7.20.6", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.5": "@babel/runtime@^7.19.4", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.5":
version "7.21.5" version "7.21.5"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.5.tgz#8492dddda9644ae3bda3b45eabe87382caee7200" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.5.tgz#8492dddda9644ae3bda3b45eabe87382caee7200"
integrity sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q== integrity sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q==
dependencies: dependencies:
regenerator-runtime "^0.13.11" regenerator-runtime "^0.13.11"
"@babel/runtime@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.5.tgz#8564dd588182ce0047d55d7a75e93921107b57ec"
integrity sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==
dependencies:
regenerator-runtime "^0.13.11"
"@eslint-community/eslint-utils@^4.2.0": "@eslint-community/eslint-utils@^4.2.0":
version "4.4.0" version "4.4.0"
resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59"
@ -60,10 +67,10 @@
minimatch "^3.1.2" minimatch "^3.1.2"
strip-json-comments "^3.1.1" strip-json-comments "^3.1.1"
"@eslint/js@8.42.0": "@eslint/js@8.43.0":
version "8.42.0" version "8.43.0"
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.42.0.tgz#484a1d638de2911e6f5a30c12f49c7e4a3270fb6" resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.43.0.tgz#559ca3d9ddbd6bf907ad524320a0d14b85586af0"
integrity sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw== integrity sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg==
"@floating-ui/core@^1.3.0": "@floating-ui/core@^1.3.0":
version "1.3.0" version "1.3.0"
@ -124,62 +131,62 @@
"@babel/runtime" "^7.12.5" "@babel/runtime" "^7.12.5"
tslib "^2.2.0" tslib "^2.2.0"
"@next/env@13.4.4": "@next/env@13.4.6":
version "13.4.4" version "13.4.6"
resolved "https://registry.yarnpkg.com/@next/env/-/env-13.4.4.tgz#46b620f6bef97fe67a1566bf570dbb791d40c50a" resolved "https://registry.yarnpkg.com/@next/env/-/env-13.4.6.tgz#3f2041c7758660d7255707ae4cb9166519113dea"
integrity sha512-q/y7VZj/9YpgzDe64Zi6rY1xPizx80JjlU2BTevlajtaE3w1LqweH1gGgxou2N7hdFosXHjGrI4OUvtFXXhGLg== integrity sha512-nqUxEtvDqFhmV1/awSg0K2XHNwkftNaiUqCYO9e6+MYmqNObpKVl7OgMkGaQ2SZnFx5YqF0t60ZJTlyJIDAijg==
"@next/eslint-plugin-next@13.4.4": "@next/eslint-plugin-next@13.4.6":
version "13.4.4" version "13.4.6"
resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-13.4.4.tgz#0df2f699e61b97c65035f87f54795f799e12fead" resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-13.4.6.tgz#6a291305226b3f762fdbc01e123efadeb63e5aaf"
integrity sha512-5jnh7q6I15efnjR/rR+/TGTc9hn53g3JTbEjAMjmeQiExKqEUgIXqrHI5zlTNlNyzCPkBB860/ctxXheZaF2Vw== integrity sha512-bPigeu0RI7bgy1ucBA2Yqcfg539y0Lzo38P2hIkrRB1GNvFSbYg6RTu8n6tGqPVrH3TTlPTNKLXG01wc+5NuwQ==
dependencies: dependencies:
glob "7.1.7" glob "7.1.7"
"@next/swc-darwin-arm64@13.4.4": "@next/swc-darwin-arm64@13.4.6":
version "13.4.4" version "13.4.6"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.4.tgz#8c14083c2478e2a9a8d140cce5900f76b75667ff" resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.6.tgz#47485f3deaee6681b4a4036c74bb9c4b728d5ddd"
integrity sha512-xfjgXvp4KalNUKZMHmsFxr1Ug+aGmmO6NWP0uoh4G3WFqP/mJ1xxfww0gMOeMeSq/Jyr5k7DvoZ2Pv+XOITTtw== integrity sha512-ahi6VP98o4HV19rkOXPSUu+ovfHfUxbJQ7VVJ7gL2FnZRr7onEFC1oGQ6NQHpm8CxpIzSSBW79kumlFMOmZVjg==
"@next/swc-darwin-x64@13.4.4": "@next/swc-darwin-x64@13.4.6":
version "13.4.4" version "13.4.6"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.4.tgz#5fe01c65c80fcb833c8789fd70f074ea99893864" resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.6.tgz#a6a5b232ec0f2079224fb8ed6bf11dc479af1acf"
integrity sha512-ZY9Ti1hkIwJsxGus3nlubIkvYyB0gNOYxKrfsOrLEqD0I2iCX8D7w8v6QQZ2H+dDl6UT29oeEUdDUNGk4UEpfg== integrity sha512-13cXxKFsPJIJKzUqrU5XB1mc0xbUgYsRcdH6/rB8c4NMEbWGdtD4QoK9ShN31TZdePpD4k416Ur7p+deMIxnnA==
"@next/swc-linux-arm64-gnu@13.4.4": "@next/swc-linux-arm64-gnu@13.4.6":
version "13.4.4" version "13.4.6"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.4.tgz#f2e071f38e8a6cdadf507cc5d28956f73360d064" resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.6.tgz#2a67144e863d9c45fdbd13c7827370e7f2a28405"
integrity sha512-+KZnDeMShYkpkqAvGCEDeqYTRADJXc6SY1jWXz+Uo6qWQO/Jd9CoyhTJwRSxvQA16MoYzvILkGaDqirkRNctyA== integrity sha512-Ti+NMHEjTNktCVxNjeWbYgmZvA2AqMMI2AMlzkXsU7W4pXCMhrryAmAIoo+7YdJbsx01JQWYVxGe62G6DoCLaA==
"@next/swc-linux-arm64-musl@13.4.4": "@next/swc-linux-arm64-musl@13.4.6":
version "13.4.4" version "13.4.6"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.4.tgz#23bf75c544e54562bc24ec1be036e4bd9cf89e2c" resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.6.tgz#5a191ac3575a70598e9e9c6e7264fc0b8a90b2db"
integrity sha512-evC1twrny2XDT4uOftoubZvW3EG0zs0ZxMwEtu/dDGVRO5n5pT48S8qqEIBGBUZYu/Xx4zzpOkIxx1vpWdE+9A== integrity sha512-OHoC6gO7XfjstgwR+z6UHKlvhqJfyMtNaJidjx3sEcfaDwS7R2lqR5AABi8PuilGgi0BO0O0sCXqLlpp3a0emQ==
"@next/swc-linux-x64-gnu@13.4.4": "@next/swc-linux-x64-gnu@13.4.6":
version "13.4.4" version "13.4.6"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.4.tgz#bd42590950a01957952206f89cf5622e7c9e4196" resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.6.tgz#d38adf842a8b8f9de492454328fd32a2c53350f3"
integrity sha512-PX706XcCHr2FfkyhP2lpf+pX/tUvq6/ke7JYnnr0ykNdEMo+sb7cC/o91gnURh4sPYSiZJhsF2gbIqg9rciOHQ== integrity sha512-zHZxPGkUlpfNJCboUrFqwlwEX5vI9LSN70b8XEb0DYzzlrZyCyOi7hwDp/+3Urm9AB7YCAJkgR5Sp1XBVjHdfQ==
"@next/swc-linux-x64-musl@13.4.4": "@next/swc-linux-x64-musl@13.4.6":
version "13.4.4" version "13.4.6"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.4.tgz#907d81feb1abec3daec0ecb61e3f39b56e7aeafe" resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.6.tgz#74c745774358b78be7f958e7a8b7d93936cd6ebc"
integrity sha512-TKUUx3Ftd95JlHV6XagEnqpT204Y+IsEa3awaYIjayn0MOGjgKZMZibqarK3B1FsMSPaieJf2FEAcu9z0yT5aA== integrity sha512-K/Y8lYGTwTpv5ME8PSJxwxLolaDRdVy+lOd9yMRMiQE0BLUhtxtCWC9ypV42uh9WpLjoaD0joOsB9Q6mbrSGJg==
"@next/swc-win32-arm64-msvc@13.4.4": "@next/swc-win32-arm64-msvc@13.4.6":
version "13.4.4" version "13.4.6"
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.4.tgz#1d754d2bb10bdf9907c0acc83711438697c3b5fe" resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.6.tgz#1e1e02c175573e64808fc1a7e8650e3e217f1edc"
integrity sha512-FP8AadgSq4+HPtim7WBkCMGbhr5vh9FePXiWx9+YOdjwdQocwoCK5ZVC3OW8oh3TWth6iJ0AXJ/yQ1q1cwSZ3A== integrity sha512-U6LtxEUrjBL2tpW+Kr1nHCSJWNeIed7U7l5o7FiKGGwGgIlFi4UHDiLI6TQ2lxi20fAU33CsruV3U0GuzMlXIw==
"@next/swc-win32-ia32-msvc@13.4.4": "@next/swc-win32-ia32-msvc@13.4.6":
version "13.4.4" version "13.4.6"
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.4.tgz#77b2c7f7534b675d46e46301869e08d504d23956" resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.6.tgz#2b528ae3ec7f6e727f4f0d81a1015f63da55c7a6"
integrity sha512-3WekVmtuA2MCdcAOrgrI+PuFiFURtSyyrN1I3UPtS0ckR2HtLqyqmS334Eulf15g1/bdwMteePdK363X/Y9JMg== integrity sha512-eEBeAqpCfhdPSlCZCayjCiyIllVqy4tcqvm1xmg3BgJG0G5ITiMM4Cw2WVeRSgWDJqQGRyyb+q8Y2ltzhXOWsQ==
"@next/swc-win32-x64-msvc@13.4.4": "@next/swc-win32-x64-msvc@13.4.6":
version "13.4.4" version "13.4.6"
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.4.tgz#faab69239f8a9d0be7cd473e65f5a07735ef7b0e" resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.6.tgz#38620bd68267ff13e50ecd432f1822eac51382a8"
integrity sha512-AHRITu/CrlQ+qzoqQtEMfaTu7GHaQ6bziQln/pVWpOYC1wU+Mq6VQQFlsDtMCnDztPZtppAXdvvbNS7pcfRzlw== integrity sha512-OrZs94AuO3ZS5tnqlyPRNgfWvboXaDQCi5aXGve3o3C+Sj0ctMUV9+Do+0zMvvLRumR8E0PTWKvtz9n5vzIsWw==
"@nodelib/fs.scandir@2.1.5": "@nodelib/fs.scandir@2.1.5":
version "2.1.5" version "2.1.5"
@ -253,10 +260,10 @@
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
"@types/node@^20.2.5": "@types/node@^20.3.1":
version "20.2.5" version "20.3.1"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.2.5.tgz#26d295f3570323b2837d322180dfbf1ba156fefb" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.3.1.tgz#e8a83f1aa8b649377bb1fb5d7bac5cb90e784dfe"
integrity sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ== integrity sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg==
"@types/postcss-modules-local-by-default@^4.0.0": "@types/postcss-modules-local-by-default@^4.0.0":
version "4.0.0" version "4.0.0"
@ -277,10 +284,10 @@
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf"
integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==
"@types/react-dom@^18.2.4": "@types/react-dom@^18.2.5":
version "18.2.4" version "18.2.5"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.4.tgz#13f25bfbf4e404d26f62ac6e406591451acba9e0" resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.5.tgz#5c5f13548bda23cd98f50ca4a59107238bfe18f3"
integrity sha512-G2mHoTMTL4yoydITgOGwWdWMVd8sNgyEP85xVmMKAPUBwQWm9wBPQUmvbeF4V3WBY1P7mmL4BkjQ0SqUpf1snw== integrity sha512-sRQsOS/sCLnpQhR4DSKGTtWFE3FZjpQa86KPVbhUqdYMRZ9FEFcfAytKhR/vUG2rH1oFbOOej6cuD7MFSobDRQ==
dependencies: dependencies:
"@types/react" "*" "@types/react" "*"
@ -293,10 +300,10 @@
"@types/scheduler" "*" "@types/scheduler" "*"
csstype "^3.0.2" csstype "^3.0.2"
"@types/react@^18.2.9": "@types/react@^18.2.12":
version "18.2.9" version "18.2.12"
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.9.tgz#9207f8571afdc59a9c9c30df50e8ad2591ecefaf" resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.12.tgz#95d584338610b78bb9ba0415e3180fb03debdf97"
integrity sha512-pL3JAesUkF7PEQGxh5XOwdXGV907te6m1/Qe1ERJLgomojS6Ne790QiA7GUl434JEkFA2aAaB6qJ5z4e1zJn/w== integrity sha512-ndmBMLCgn38v3SntMeoJaIrO6tGHYKMEBohCUmw8HoLLQdRMOIGXfeYaBTLe2lsFaSB3MOK1VXscYFnmLtTSmw==
dependencies: dependencies:
"@types/prop-types" "*" "@types/prop-types" "*"
"@types/scheduler" "*" "@types/scheduler" "*"
@ -312,15 +319,15 @@
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.0.tgz#591c1ce3a702c45ee15f47a42ade72c2fd78978a" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.0.tgz#591c1ce3a702c45ee15f47a42ade72c2fd78978a"
integrity sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw== integrity sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==
"@typescript-eslint/eslint-plugin@^5.59.9": "@typescript-eslint/eslint-plugin@^5.59.11":
version "5.59.9" version "5.59.11"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.9.tgz#2604cfaf2b306e120044f901e20c8ed926debf15" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.11.tgz#8d466aa21abea4c3f37129997b198d141f09e76f"
integrity sha512-4uQIBq1ffXd2YvF7MAvehWKW3zVv/w+mSfRAu+8cKbfj3nwzyqJLNcZJpQ/WZ1HLbJDiowwmQ6NO+63nCA+fqA== integrity sha512-XxuOfTkCUiOSyBWIvHlUraLw/JT/6Io1365RO6ZuI88STKMavJZPNMU0lFcUTeQXEhHiv64CbxYxBNoDVSmghg==
dependencies: dependencies:
"@eslint-community/regexpp" "^4.4.0" "@eslint-community/regexpp" "^4.4.0"
"@typescript-eslint/scope-manager" "5.59.9" "@typescript-eslint/scope-manager" "5.59.11"
"@typescript-eslint/type-utils" "5.59.9" "@typescript-eslint/type-utils" "5.59.11"
"@typescript-eslint/utils" "5.59.9" "@typescript-eslint/utils" "5.59.11"
debug "^4.3.4" debug "^4.3.4"
grapheme-splitter "^1.0.4" grapheme-splitter "^1.0.4"
ignore "^5.2.0" ignore "^5.2.0"
@ -338,16 +345,24 @@
"@typescript-eslint/typescript-estree" "5.59.6" "@typescript-eslint/typescript-estree" "5.59.6"
debug "^4.3.4" debug "^4.3.4"
"@typescript-eslint/parser@^5.59.9": "@typescript-eslint/parser@^5.59.11":
version "5.59.9" version "5.59.11"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.59.9.tgz#a85c47ccdd7e285697463da15200f9a8561dd5fa" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.59.11.tgz#af7d4b7110e3068ce0b97550736de455e4250103"
integrity sha512-FsPkRvBtcLQ/eVK1ivDiNYBjn3TGJdXy2fhXX+rc7czWl4ARwnpArwbihSOHI2Peg9WbtGHrbThfBUkZZGTtvQ== integrity sha512-s9ZF3M+Nym6CAZEkJJeO2TFHHDsKAM3ecNkLuH4i4s8/RCPnF5JRip2GyviYkeEAcwGMJxkqG9h2dAsnA1nZpA==
dependencies: dependencies:
"@typescript-eslint/scope-manager" "5.59.9" "@typescript-eslint/scope-manager" "5.59.11"
"@typescript-eslint/types" "5.59.9" "@typescript-eslint/types" "5.59.11"
"@typescript-eslint/typescript-estree" "5.59.9" "@typescript-eslint/typescript-estree" "5.59.11"
debug "^4.3.4" debug "^4.3.4"
"@typescript-eslint/scope-manager@5.59.11":
version "5.59.11"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.59.11.tgz#5d131a67a19189c42598af9fb2ea1165252001ce"
integrity sha512-dHFOsxoLFtrIcSj5h0QoBT/89hxQONwmn3FOQ0GOQcLOOXm+MIrS8zEAhs4tWl5MraxCY3ZJpaXQQdFMc2Tu+Q==
dependencies:
"@typescript-eslint/types" "5.59.11"
"@typescript-eslint/visitor-keys" "5.59.11"
"@typescript-eslint/scope-manager@5.59.6": "@typescript-eslint/scope-manager@5.59.6":
version "5.59.6" version "5.59.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.59.6.tgz#d43a3687aa4433868527cfe797eb267c6be35f19" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.59.6.tgz#d43a3687aa4433868527cfe797eb267c6be35f19"
@ -356,33 +371,38 @@
"@typescript-eslint/types" "5.59.6" "@typescript-eslint/types" "5.59.6"
"@typescript-eslint/visitor-keys" "5.59.6" "@typescript-eslint/visitor-keys" "5.59.6"
"@typescript-eslint/scope-manager@5.59.9": "@typescript-eslint/type-utils@5.59.11":
version "5.59.9" version "5.59.11"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.59.9.tgz#eadce1f2733389cdb58c49770192c0f95470d2f4" resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.59.11.tgz#5eb67121808a84cb57d65a15f48f5bdda25f2346"
integrity sha512-8RA+E+w78z1+2dzvK/tGZ2cpGigBZ58VMEHDZtpE1v+LLjzrYGc8mMaTONSxKyEkz3IuXFM0IqYiGHlCsmlZxQ== integrity sha512-LZqVY8hMiVRF2a7/swmkStMYSoXMFlzL6sXV6U/2gL5cwnLWQgLEG8tjWPpaE4rMIdZ6VKWwcffPlo1jPfk43g==
dependencies: dependencies:
"@typescript-eslint/types" "5.59.9" "@typescript-eslint/typescript-estree" "5.59.11"
"@typescript-eslint/visitor-keys" "5.59.9" "@typescript-eslint/utils" "5.59.11"
"@typescript-eslint/type-utils@5.59.9":
version "5.59.9"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.59.9.tgz#53bfaae2e901e6ac637ab0536d1754dfef4dafc2"
integrity sha512-ksEsT0/mEHg9e3qZu98AlSrONAQtrSTljL3ow9CGej8eRo7pe+yaC/mvTjptp23Xo/xIf2mLZKC6KPv4Sji26Q==
dependencies:
"@typescript-eslint/typescript-estree" "5.59.9"
"@typescript-eslint/utils" "5.59.9"
debug "^4.3.4" debug "^4.3.4"
tsutils "^3.21.0" tsutils "^3.21.0"
"@typescript-eslint/types@5.59.11":
version "5.59.11"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.59.11.tgz#1a9018fe3c565ba6969561f2a49f330cf1fe8db1"
integrity sha512-epoN6R6tkvBYSc+cllrz+c2sOFWkbisJZWkOE+y3xHtvYaOE6Wk6B8e114McRJwFRjGvYdJwLXQH5c9osME/AA==
"@typescript-eslint/types@5.59.6": "@typescript-eslint/types@5.59.6":
version "5.59.6" version "5.59.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.59.6.tgz#5a6557a772af044afe890d77c6a07e8c23c2460b" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.59.6.tgz#5a6557a772af044afe890d77c6a07e8c23c2460b"
integrity sha512-tH5lBXZI7T2MOUgOWFdVNUILsI02shyQvfzG9EJkoONWugCG77NDDa1EeDGw7oJ5IvsTAAGVV8I3Tk2PNu9QfA== integrity sha512-tH5lBXZI7T2MOUgOWFdVNUILsI02shyQvfzG9EJkoONWugCG77NDDa1EeDGw7oJ5IvsTAAGVV8I3Tk2PNu9QfA==
"@typescript-eslint/types@5.59.9": "@typescript-eslint/typescript-estree@5.59.11":
version "5.59.9" version "5.59.11"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.59.9.tgz#3b4e7ae63718ce1b966e0ae620adc4099a6dcc52" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.11.tgz#b2caaa31725e17c33970c1197bcd54e3c5f42b9f"
integrity sha512-uW8H5NRgTVneSVTfiCVffBb8AbwWSKg7qcA4Ot3JI3MPCJGsB4Db4BhvAODIIYE5mNj7Q+VJkK7JxmRhk2Lyjw== integrity sha512-YupOpot5hJO0maupJXixi6l5ETdrITxeo5eBOeuV7RSKgYdU3G5cxO49/9WRnJq9EMrB7AuTSLH/bqOsXi7wPA==
dependencies:
"@typescript-eslint/types" "5.59.11"
"@typescript-eslint/visitor-keys" "5.59.11"
debug "^4.3.4"
globby "^11.1.0"
is-glob "^4.0.3"
semver "^7.3.7"
tsutils "^3.21.0"
"@typescript-eslint/typescript-estree@5.59.6": "@typescript-eslint/typescript-estree@5.59.6":
version "5.59.6" version "5.59.6"
@ -397,33 +417,28 @@
semver "^7.3.7" semver "^7.3.7"
tsutils "^3.21.0" tsutils "^3.21.0"
"@typescript-eslint/typescript-estree@5.59.9": "@typescript-eslint/utils@5.59.11":
version "5.59.9" version "5.59.11"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.9.tgz#6bfea844e468427b5e72034d33c9fffc9557392b" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.59.11.tgz#9dbff49dc80bfdd9289f9f33548f2e8db3c59ba1"
integrity sha512-pmM0/VQ7kUhd1QyIxgS+aRvMgw+ZljB3eDb+jYyp6d2bC0mQWLzUDF+DLwCTkQ3tlNyVsvZRXjFyV0LkU/aXjA== integrity sha512-didu2rHSOMUdJThLk4aZ1Or8IcO3HzCw/ZvEjTTIfjIrcdd5cvSIwwDy2AOlE7htSNp7QIZ10fLMyRCveesMLg==
dependencies:
"@typescript-eslint/types" "5.59.9"
"@typescript-eslint/visitor-keys" "5.59.9"
debug "^4.3.4"
globby "^11.1.0"
is-glob "^4.0.3"
semver "^7.3.7"
tsutils "^3.21.0"
"@typescript-eslint/utils@5.59.9":
version "5.59.9"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.59.9.tgz#adee890107b5ffe02cd46fdaa6c2125fb3c6c7c4"
integrity sha512-1PuMYsju/38I5Ggblaeb98TOoUvjhRvLpLa1DoTOFaLWqaXl/1iQ1eGurTXgBY58NUdtfTXKP5xBq7q9NDaLKg==
dependencies: dependencies:
"@eslint-community/eslint-utils" "^4.2.0" "@eslint-community/eslint-utils" "^4.2.0"
"@types/json-schema" "^7.0.9" "@types/json-schema" "^7.0.9"
"@types/semver" "^7.3.12" "@types/semver" "^7.3.12"
"@typescript-eslint/scope-manager" "5.59.9" "@typescript-eslint/scope-manager" "5.59.11"
"@typescript-eslint/types" "5.59.9" "@typescript-eslint/types" "5.59.11"
"@typescript-eslint/typescript-estree" "5.59.9" "@typescript-eslint/typescript-estree" "5.59.11"
eslint-scope "^5.1.1" eslint-scope "^5.1.1"
semver "^7.3.7" semver "^7.3.7"
"@typescript-eslint/visitor-keys@5.59.11":
version "5.59.11"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.11.tgz#dca561ddad169dc27d62396d64f45b2d2c3ecc56"
integrity sha512-KGYniTGG3AMTuKF9QBD7EIrvufkB6O6uX3knP73xbKLMpH+QRPcgnCxjWXSHjMRuOxFLovljqQgQpR0c7GvjoA==
dependencies:
"@typescript-eslint/types" "5.59.11"
eslint-visitor-keys "^3.3.0"
"@typescript-eslint/visitor-keys@5.59.6": "@typescript-eslint/visitor-keys@5.59.6":
version "5.59.6" version "5.59.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.6.tgz#673fccabf28943847d0c8e9e8d008e3ada7be6bb" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.6.tgz#673fccabf28943847d0c8e9e8d008e3ada7be6bb"
@ -432,14 +447,6 @@
"@typescript-eslint/types" "5.59.6" "@typescript-eslint/types" "5.59.6"
eslint-visitor-keys "^3.3.0" eslint-visitor-keys "^3.3.0"
"@typescript-eslint/visitor-keys@5.59.9":
version "5.59.9"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.9.tgz#9f86ef8e95aca30fb5a705bb7430f95fc58b146d"
integrity sha512-bT7s0td97KMaLwpEBckbzj/YohnvXtqbe2XgqNvTl6RJVakY5mvENOTPvw5u66nljfZxthESpDozs86U+oLY8Q==
dependencies:
"@typescript-eslint/types" "5.59.9"
eslint-visitor-keys "^3.3.0"
"@vercel/analytics@^1.0.1": "@vercel/analytics@^1.0.1":
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/@vercel/analytics/-/analytics-1.0.1.tgz#38308a626c91866cb00a249c08bf65251e9b9d81" resolved "https://registry.yarnpkg.com/@vercel/analytics/-/analytics-1.0.1.tgz#38308a626c91866cb00a249c08bf65251e9b9d81"
@ -949,12 +956,12 @@ escape-string-regexp@^4.0.0:
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
eslint-config-next@^13.4.4: eslint-config-next@^13.4.6:
version "13.4.4" version "13.4.6"
resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-13.4.4.tgz#95356e96f3796ad0587fa2aaa51ec4a81e71cedc" resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-13.4.6.tgz#ccccf5dad45b23a56418d66caad5339116297308"
integrity sha512-z/PMbm6L0iC/fwISULxe8IVy4DtNqZk2wQY711o35klenq70O6ns82A8yuMVCFjHC0DIyB2lyugesRtuk9u8dQ== integrity sha512-nlv4FYish1RYYHILbQwM5/rD37cOvEqtMfDjtQCYbXdE2O3MggqHu2q6IDeLE2Z6u8ZJyNPgWOA6OimWcxj3qw==
dependencies: dependencies:
"@next/eslint-plugin-next" "13.4.4" "@next/eslint-plugin-next" "13.4.6"
"@rushstack/eslint-patch" "^1.1.3" "@rushstack/eslint-patch" "^1.1.3"
"@typescript-eslint/parser" "^5.42.0" "@typescript-eslint/parser" "^5.42.0"
eslint-import-resolver-node "^0.3.6" eslint-import-resolver-node "^0.3.6"
@ -1089,15 +1096,15 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994"
integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA== integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==
eslint@^8.42.0: eslint@^8.43.0:
version "8.42.0" version "8.43.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.42.0.tgz#7bebdc3a55f9ed7167251fe7259f75219cade291" resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.43.0.tgz#3e8c6066a57097adfd9d390b8fc93075f257a094"
integrity sha512-ulg9Ms6E1WPf67PHaEY4/6E2tEn5/f7FXGzr3t9cBMugOmf1INYvuUwwh1aXQN4MfJ6a5K2iNwP3w4AColvI9A== integrity sha512-aaCpf2JqqKesMFGgmRPessmVKjcGXqdlAYLLC3THM8t5nBRZRQ+st5WM/hoJXkdioEXLLbXgclUpM0TXo5HX5Q==
dependencies: dependencies:
"@eslint-community/eslint-utils" "^4.2.0" "@eslint-community/eslint-utils" "^4.2.0"
"@eslint-community/regexpp" "^4.4.0" "@eslint-community/regexpp" "^4.4.0"
"@eslint/eslintrc" "^2.0.3" "@eslint/eslintrc" "^2.0.3"
"@eslint/js" "8.42.0" "@eslint/js" "8.43.0"
"@humanwhocodes/config-array" "^0.11.10" "@humanwhocodes/config-array" "^0.11.10"
"@humanwhocodes/module-importer" "^1.0.1" "@humanwhocodes/module-importer" "^1.0.1"
"@nodelib/fs.walk" "^1.2.8" "@nodelib/fs.walk" "^1.2.8"
@ -1349,6 +1356,11 @@ glob-parent@^6.0.2:
dependencies: dependencies:
is-glob "^4.0.3" is-glob "^4.0.3"
glob-to-regexp@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
glob@7.1.7: glob@7.1.7:
version "7.1.7" version "7.1.7"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90"
@ -1516,12 +1528,12 @@ i18next-resources-to-backend@^1.1.4:
dependencies: dependencies:
"@babel/runtime" "^7.21.5" "@babel/runtime" "^7.21.5"
i18next@^22.5.1: i18next@^23.1.0:
version "22.5.1" version "23.1.0"
resolved "https://registry.yarnpkg.com/i18next/-/i18next-22.5.1.tgz#99df0b318741a506000c243429a7352e5f44d424" resolved "https://registry.yarnpkg.com/i18next/-/i18next-23.1.0.tgz#d0c4222b38a3007e6070d43d40fe59ca57d6bbaa"
integrity sha512-8TGPgM3pAD+VRsMtUMNknRz3kzqwp/gPALrWMsDnmC1mKqJwpWyooQRLMcbTwq8z8YwSmuj+ZYvc+xCuEpkssA== integrity sha512-CObNPofJpw7zGVGYLd58mtMZUF+NZQl9czYMihbJkStjX+Nlu9kC3PHiC6uE1niP3qxP/3ocLXIBc2zqbAb1dg==
dependencies: dependencies:
"@babel/runtime" "^7.20.6" "@babel/runtime" "^7.22.5"
iconv-lite@^0.6.3: iconv-lite@^0.6.3:
version "0.6.3" version "0.6.3"
@ -1916,10 +1928,10 @@ lru-cache@^6.0.0:
dependencies: dependencies:
yallist "^4.0.0" yallist "^4.0.0"
lucide-react@^0.241.0: lucide-react@^0.244.0:
version "0.241.0" version "0.244.0"
resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.241.0.tgz#e5116bb66e64e8c1742bd063a96248f54b527a8e" resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.244.0.tgz#9626f44881830280012dad23afda7ddbcffff24b"
integrity sha512-g22ci6iHuNc2hUwjiFz0D3jQQfQYrZBZesXG6+AX5rOV68Epttkt/nF6dMdz6reKJjtpoNzu+LKeKHGu/qjOgQ== integrity sha512-PeDVbx5PlIRrVvdxiuSxPfBo7sK5qrL3LbvvRoGVNiHYRAkBm/48lKqoioxcmp0bgsyJs9lMw7CdtGFvnMJbVg==
make-dir@^2.1.0: make-dir@^2.1.0:
version "2.1.0" version "2.1.0"
@ -2013,28 +2025,29 @@ needle@^3.1.0:
iconv-lite "^0.6.3" iconv-lite "^0.6.3"
sax "^1.2.4" sax "^1.2.4"
next@^13.4.4: next@^13.4.6:
version "13.4.4" version "13.4.6"
resolved "https://registry.yarnpkg.com/next/-/next-13.4.4.tgz#d1027c8d77f4c51be0b39f671b4820db03c93e60" resolved "https://registry.yarnpkg.com/next/-/next-13.4.6.tgz#ebe52f5c74d60176d45b45e73f25a51103713ea4"
integrity sha512-C5S0ysM0Ily9McL4Jb48nOQHT1BukOWI59uC3X/xCMlYIh9rJZCv7nzG92J6e1cOBqQbKovlpgvHWFmz4eKKEA== integrity sha512-sjVqjxU+U2aXZnYt4Ud6CTLNNwWjdSfMgemGpIQJcN3Z7Jni9xRWbR0ie5fQzCg87aLqQVhKA2ud2gPoqJ9lGw==
dependencies: dependencies:
"@next/env" "13.4.4" "@next/env" "13.4.6"
"@swc/helpers" "0.5.1" "@swc/helpers" "0.5.1"
busboy "1.6.0" busboy "1.6.0"
caniuse-lite "^1.0.30001406" caniuse-lite "^1.0.30001406"
postcss "8.4.14" postcss "8.4.14"
styled-jsx "5.1.1" styled-jsx "5.1.1"
watchpack "2.4.0"
zod "3.21.4" zod "3.21.4"
optionalDependencies: optionalDependencies:
"@next/swc-darwin-arm64" "13.4.4" "@next/swc-darwin-arm64" "13.4.6"
"@next/swc-darwin-x64" "13.4.4" "@next/swc-darwin-x64" "13.4.6"
"@next/swc-linux-arm64-gnu" "13.4.4" "@next/swc-linux-arm64-gnu" "13.4.6"
"@next/swc-linux-arm64-musl" "13.4.4" "@next/swc-linux-arm64-musl" "13.4.6"
"@next/swc-linux-x64-gnu" "13.4.4" "@next/swc-linux-x64-gnu" "13.4.6"
"@next/swc-linux-x64-musl" "13.4.4" "@next/swc-linux-x64-musl" "13.4.6"
"@next/swc-win32-arm64-msvc" "13.4.4" "@next/swc-win32-arm64-msvc" "13.4.6"
"@next/swc-win32-ia32-msvc" "13.4.4" "@next/swc-win32-ia32-msvc" "13.4.6"
"@next/swc-win32-x64-msvc" "13.4.4" "@next/swc-win32-x64-msvc" "13.4.6"
node-fetch@^2.6.11: node-fetch@^2.6.11:
version "2.6.11" version "2.6.11"
@ -2346,12 +2359,12 @@ react-hook-form@^7.44.3:
resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.44.3.tgz#a99e560c6ef2b668db1daaebc4f98267331b6828" resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.44.3.tgz#a99e560c6ef2b668db1daaebc4f98267331b6828"
integrity sha512-/tHId6p2ViAka1wECMw8FEPn/oz/w226zehHrJyQ1oIzCBNMIJCaj6ZkQcv+MjDxYh9MWR7RQic7Qqwe4a5nkw== integrity sha512-/tHId6p2ViAka1wECMw8FEPn/oz/w226zehHrJyQ1oIzCBNMIJCaj6ZkQcv+MjDxYh9MWR7RQic7Qqwe4a5nkw==
react-i18next@^12.3.1: react-i18next@^13.0.0:
version "12.3.1" version "13.0.0"
resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-12.3.1.tgz#30134a41a2a71c61dc69c6383504929aed1c99e7" resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-13.0.0.tgz#358a3ed93206fd2d5b78507bccce89a6f7d73e17"
integrity sha512-5v8E2XjZDFzK7K87eSwC7AJcAkcLt5xYZ4+yTPDAW1i7C93oOY1dnr4BaQM7un4Hm+GmghuiPvevWwlca5PwDA== integrity sha512-qRFbrSgynsBSjfnSTb/Um3mw9uPjOfDi4Iq2rMCuzfsRsYGdkEdyCr0i+T0bR0bG6xwULvK4k1oRVLLd7ZDBVw==
dependencies: dependencies:
"@babel/runtime" "^7.20.6" "@babel/runtime" "^7.22.5"
html-parse-stringify "^3.0.1" html-parse-stringify "^3.0.1"
react-is@^16.13.1: react-is@^16.13.1:
@ -2469,10 +2482,10 @@ sass@^1.58.3:
immutable "^4.0.0" immutable "^4.0.0"
source-map-js ">=0.6.2 <2.0.0" source-map-js ">=0.6.2 <2.0.0"
sass@^1.63.2: sass@^1.63.4:
version "1.63.2" version "1.63.4"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.63.2.tgz#75f7d9a8e67d1d5b98a989507f4d98b6067b1f75" resolved "https://registry.yarnpkg.com/sass/-/sass-1.63.4.tgz#caf60643321044c61f6a0fe638a07abbd31cfb5d"
integrity sha512-u56TU0AIFqMtauKl/OJ1AeFsXqRHkgO7nCWmHaDwfxDo9GUMSqBA4NEh6GMuh1CYVM7zuROYtZrHzPc2ixK+ww== integrity sha512-Sx/+weUmK+oiIlI+9sdD0wZHsqpbgQg8wSwSnGBjwb5GwqFhYNwwnI+UWZtLjKvKyFlKkatRK235qQ3mokyPoQ==
dependencies: dependencies:
chokidar ">=3.0.0 <4.0.0" chokidar ">=3.0.0 <4.0.0"
immutable "^4.0.0" immutable "^4.0.0"
@ -2839,6 +2852,14 @@ void-elements@3.1.0:
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09" resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09"
integrity sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w== integrity sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==
watchpack@2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d"
integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==
dependencies:
glob-to-regexp "^0.4.1"
graceful-fs "^4.1.2"
webidl-conversions@^3.0.0: webidl-conversions@^3.0.0:
version "3.0.1" version "3.0.1"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"