Optimise month field
This commit is contained in:
parent
028d63992c
commit
25d029ba57
|
|
@ -4,13 +4,11 @@ import Header from '/src/components/Header/Header'
|
||||||
|
|
||||||
const Layout = async ({ children }: { children: React.ReactNode }) => <>
|
const Layout = async ({ children }: { children: React.ReactNode }) => <>
|
||||||
<Content>
|
<Content>
|
||||||
{/* @ts-expect-error Async Server Component */}
|
|
||||||
<Header />
|
<Header />
|
||||||
</Content>
|
</Content>
|
||||||
|
|
||||||
{children}
|
{children}
|
||||||
|
|
||||||
{/* @ts-expect-error Async Server Component */}
|
|
||||||
<Footer />
|
<Footer />
|
||||||
</>
|
</>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ export const metadata: Metadata = {
|
||||||
*/
|
*/
|
||||||
const Page = async () => <>
|
const Page = async () => <>
|
||||||
<Content isSlim>
|
<Content isSlim>
|
||||||
{/* @ts-expect-error Async Server Component */}
|
|
||||||
<Header isFull isSmall />
|
<Header isFull isSmall />
|
||||||
</Content>
|
</Content>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ const Page = async () => {
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
<Content>
|
<Content>
|
||||||
{/* @ts-expect-error Async Server Component */}
|
|
||||||
<Header />
|
<Header />
|
||||||
|
|
||||||
<h1>{t('help:name')}</h1>
|
<h1>{t('help:name')}</h1>
|
||||||
|
|
@ -82,7 +81,6 @@ const Page = async () => {
|
||||||
</Content>
|
</Content>
|
||||||
</Section>
|
</Section>
|
||||||
|
|
||||||
{/* @ts-expect-error Async Server Component */}
|
|
||||||
<Footer />
|
<Footer />
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ const Page = async () => {
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
<Content>
|
<Content>
|
||||||
{/* @ts-expect-error Async Server Component */}
|
|
||||||
<Header isFull />
|
<Header isFull />
|
||||||
</Content>
|
</Content>
|
||||||
|
|
||||||
|
|
@ -32,7 +31,6 @@ const Page = async () => {
|
||||||
<Content>
|
<Content>
|
||||||
<h2>{t('about.name')}</h2>
|
<h2>{t('about.name')}</h2>
|
||||||
|
|
||||||
{/* @ts-expect-error Async Server Component */}
|
|
||||||
<Stats />
|
<Stats />
|
||||||
|
|
||||||
<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>
|
||||||
|
|
@ -48,7 +46,6 @@ const Page = async () => {
|
||||||
</Content>
|
</Content>
|
||||||
</Section>
|
</Section>
|
||||||
|
|
||||||
{/* @ts-expect-error Async Server Component */}
|
|
||||||
<Footer />
|
<Footer />
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ const Page = async () => {
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
<Content>
|
<Content>
|
||||||
{/* @ts-expect-error Async Server Component */}
|
|
||||||
<Header />
|
<Header />
|
||||||
|
|
||||||
<h1>{t('privacy:name')}</h1>
|
<h1>{t('privacy:name')}</h1>
|
||||||
|
|
@ -86,7 +85,6 @@ const Page = async () => {
|
||||||
</Content>
|
</Content>
|
||||||
</Section>
|
</Section>
|
||||||
|
|
||||||
{/* @ts-expect-error Async Server Component */}
|
|
||||||
<Footer />
|
<Footer />
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ const Month = ({ value, onChange }: MonthProps) => {
|
||||||
const weekStart = useStore(useSettingsStore, state => state.weekStart) ?? 0
|
const weekStart = useStore(useSettingsStore, state => state.weekStart) ?? 0
|
||||||
|
|
||||||
const [page, setPage] = useState<Temporal.PlainYearMonth>(Temporal.Now.plainDateISO().toPlainYearMonth())
|
const [page, setPage] = useState<Temporal.PlainYearMonth>(Temporal.Now.plainDateISO().toPlainYearMonth())
|
||||||
const dates = useMemo(() => calculateMonth(page, weekStart), [page, weekStart])
|
const dates = useMemo(() => calculateMonth(page, weekStart, i18n.language), [page, weekStart, i18n.language])
|
||||||
|
|
||||||
// Ref and state required to rerender but also access static version in callbacks
|
// Ref and state required to rerender but also access static version in callbacks
|
||||||
const selectingRef = useRef<string[]>([])
|
const selectingRef = useRef<string[]>([])
|
||||||
|
|
@ -46,7 +46,7 @@ const Month = ({ value, onChange }: MonthProps) => {
|
||||||
}, [value])
|
}, [value])
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
<div className={styles.header}>
|
{useMemo(() => <div className={styles.header}>
|
||||||
<Button
|
<Button
|
||||||
title={t<string>('form.dates.tooltips.previous')}
|
title={t<string>('form.dates.tooltips.previous')}
|
||||||
onClick={() => setPage(page.subtract({ months: 1 }))}
|
onClick={() => setPage(page.subtract({ months: 1 }))}
|
||||||
|
|
@ -58,13 +58,13 @@ const Month = ({ value, onChange }: MonthProps) => {
|
||||||
onClick={() => setPage(page.add({ months: 1 }))}
|
onClick={() => setPage(page.add({ months: 1 }))}
|
||||||
icon={<ChevronRight />}
|
icon={<ChevronRight />}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>, [page, i18n.language])}
|
||||||
|
|
||||||
<div className={styles.dayLabels}>
|
{useMemo(() => <div className={styles.dayLabels}>
|
||||||
{(rotateArray(getWeekdayNames(i18n.language, 'short'), weekStart ? 0 : 1)).map(name =>
|
{(rotateArray(getWeekdayNames(i18n.language, 'short'), weekStart ? 0 : 1)).map(name =>
|
||||||
<label key={name}>{name}</label>
|
<label key={name}>{name}</label>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>, [i18n.language, weekStart])}
|
||||||
|
|
||||||
<div className={styles.grid}>
|
<div className={styles.grid}>
|
||||||
{dates.length > 0 && dates.map((dateRow, y) =>
|
{dates.length > 0 && dates.map((dateRow, y) =>
|
||||||
|
|
@ -73,27 +73,27 @@ const Month = ({ value, onChange }: MonthProps) => {
|
||||||
className={makeClass(
|
className={makeClass(
|
||||||
styles.date,
|
styles.date,
|
||||||
date.month !== page.month && styles.otherMonth,
|
date.month !== page.month && styles.otherMonth,
|
||||||
date.equals(Temporal.Now.plainDateISO()) && styles.today,
|
date.isToday && styles.today,
|
||||||
(
|
(
|
||||||
(!(mode.current === 'remove' && selecting.includes(date.toString())) && value.includes(date.toString()))
|
(!(mode.current === 'remove' && selecting.includes(date.string)) && value.includes(date.string))
|
||||||
|| (mode.current === 'add' && selecting.includes(date.toString()))
|
|| (mode.current === 'add' && selecting.includes(date.string))
|
||||||
) && styles.selected,
|
) && styles.selected,
|
||||||
)}
|
)}
|
||||||
key={date.toString()}
|
key={date.string}
|
||||||
title={`${date.toLocaleString(i18n.language, { day: 'numeric', month: 'long' })}${date.equals(Temporal.Now.plainDateISO()) ? ` (${t('form.dates.tooltips.today')})` : ''}`}
|
title={`${date.title}${date.isToday ? ` (${t('form.dates.tooltips.today')})` : ''}`}
|
||||||
onKeyDown={e => {
|
onKeyDown={e => {
|
||||||
if (e.key === ' ' || e.key === 'Enter') {
|
if (e.key === ' ' || e.key === 'Enter') {
|
||||||
if (value.includes(date.toString())) {
|
if (value.includes(date.string)) {
|
||||||
onChange(value.filter(d => d !== date.toString()))
|
onChange(value.filter(d => d !== date.string))
|
||||||
} else {
|
} else {
|
||||||
onChange([...value, date.toString()])
|
onChange([...value, date.string])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onPointerDown={e => {
|
onPointerDown={e => {
|
||||||
startPos.current = { x, y }
|
startPos.current = { x, y }
|
||||||
mode.current = value.includes(date.toString()) ? 'remove' : 'add'
|
mode.current = value.includes(date.string) ? 'remove' : 'add'
|
||||||
setSelecting([date.toString()])
|
setSelecting([date.string])
|
||||||
e.currentTarget.releasePointerCapture(e.pointerId)
|
e.currentTarget.releasePointerCapture(e.pointerId)
|
||||||
|
|
||||||
document.addEventListener('pointerup', handleFinishSelection, { once: true })
|
document.addEventListener('pointerup', handleFinishSelection, { once: true })
|
||||||
|
|
@ -106,10 +106,10 @@ const Month = ({ value, onChange }: MonthProps) => {
|
||||||
found.push({ y: cy, x: cx })
|
found.push({ y: cy, x: cx })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setSelecting(found.map(d => dates[d.y][d.x].toString()))
|
setSelecting(found.map(d => dates[d.y][d.x].string))
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>{date.toLocaleString(i18n.language, { day: 'numeric' })}</button>)
|
>{date.label}</button>)
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|
@ -117,18 +117,33 @@ const Month = ({ value, onChange }: MonthProps) => {
|
||||||
|
|
||||||
export default Month
|
export default Month
|
||||||
|
|
||||||
|
interface Day {
|
||||||
|
month: number
|
||||||
|
isToday: boolean
|
||||||
|
string: string
|
||||||
|
title: string
|
||||||
|
label: string
|
||||||
|
}
|
||||||
|
|
||||||
/** Calculate the dates to show for the month in a 2d array */
|
/** Calculate the dates to show for the month in a 2d array */
|
||||||
const calculateMonth = (month: Temporal.PlainYearMonth, weekStart: 0 | 1) => {
|
const calculateMonth = (month: Temporal.PlainYearMonth, weekStart: 0 | 1, locale: string) => {
|
||||||
|
const today = Temporal.Now.plainDateISO()
|
||||||
const daysBefore = month.toPlainDate({ day: 1 }).dayOfWeek - weekStart
|
const daysBefore = month.toPlainDate({ day: 1 }).dayOfWeek - weekStart
|
||||||
const daysAfter = 6 - month.toPlainDate({ day: month.daysInMonth }).dayOfWeek + weekStart
|
const daysAfter = 6 - month.toPlainDate({ day: month.daysInMonth }).dayOfWeek + weekStart
|
||||||
|
|
||||||
const dates: Temporal.PlainDate[][] = []
|
const dates: Day[][] = []
|
||||||
let curDate = month.toPlainDate({ day: 1 }).subtract({ days: daysBefore })
|
let curDate = month.toPlainDate({ day: 1 }).subtract({ days: daysBefore })
|
||||||
let y = 0
|
let y = 0
|
||||||
let x = 0
|
let x = 0
|
||||||
for (let i = 0; i < daysBefore + month.daysInMonth + daysAfter; i++) {
|
for (let i = 0; i < daysBefore + month.daysInMonth + daysAfter; i++) {
|
||||||
if (x === 0) dates[y] = []
|
if (x === 0) dates[y] = []
|
||||||
dates[y][x] = curDate
|
dates[y][x] = {
|
||||||
|
month: curDate.month,
|
||||||
|
isToday: curDate.equals(today),
|
||||||
|
string: curDate.toString(),
|
||||||
|
title: curDate.toLocaleString(locale, { day: 'numeric', month: 'long' }),
|
||||||
|
label: curDate.toLocaleString(locale, { day: 'numeric' }),
|
||||||
|
}
|
||||||
curDate = curDate.add({ days: 1 })
|
curDate = curDate.add({ days: 1 })
|
||||||
x++
|
x++
|
||||||
if (x > 6) {
|
if (x > 6) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue