Add giraugh tools and update dayjs instance on client when lang changes
This commit is contained in:
parent
3034605126
commit
6220e599cf
|
|
@ -11,6 +11,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@azure/msal-browser": "^2.37.0",
|
||||
"@giraugh/tools": "^1.5.0",
|
||||
"@microsoft/microsoft-graph-client": "^3.0.5",
|
||||
"accept-language": "^3.0.18",
|
||||
"dayjs": "^1.11.7",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { rotateArray } from '@giraugh/tools'
|
||||
import { Dayjs } from 'dayjs'
|
||||
import { ChevronLeft, ChevronRight } from 'lucide-react'
|
||||
|
||||
import Button from '/src/components/Button/Button'
|
||||
import dayjs from '/src/config/dayjs'
|
||||
import { useDayjs } from '/src/config/dayjs'
|
||||
import { useTranslation } from '/src/i18n/client'
|
||||
import { useStore } from '/src/stores'
|
||||
import useSettingsStore from '/src/stores/settingsStore'
|
||||
|
|
@ -10,10 +12,6 @@ import { makeClass } from '/src/utils'
|
|||
|
||||
import styles from './Month.module.scss'
|
||||
|
||||
// TODO: use from giraugh tools
|
||||
export const rotateArray = <T, >(arr: T[], amount = 1): T[] =>
|
||||
arr.map((_, i) => arr[((( -amount + i ) % arr.length) + arr.length) % arr.length])
|
||||
|
||||
interface MonthProps {
|
||||
/** Array of dates in `DDMMYYYY` format */
|
||||
value: string[]
|
||||
|
|
@ -22,6 +20,7 @@ interface MonthProps {
|
|||
|
||||
const Month = ({ value, onChange }: MonthProps) => {
|
||||
const { t } = useTranslation('home')
|
||||
const dayjs = useDayjs()
|
||||
|
||||
const weekStart = useStore(useSettingsStore, state => state.weekStart) ?? 0
|
||||
|
||||
|
|
@ -29,7 +28,7 @@ const Month = ({ value, onChange }: MonthProps) => {
|
|||
month: dayjs().month(),
|
||||
year: dayjs().year(),
|
||||
})
|
||||
const [dates, setDates] = useState(calculateMonth(page, weekStart))
|
||||
const [dates, setDates] = useState(calculateMonth(dayjs().month(page.month).year(page.year), weekStart))
|
||||
|
||||
// Ref and state required to rerender but also access static version in callbacks
|
||||
const selectingRef = useRef<string[]>([])
|
||||
|
|
@ -45,7 +44,7 @@ const Month = ({ value, onChange }: MonthProps) => {
|
|||
// Update month view
|
||||
useEffect(() => {
|
||||
dayjs.updateLocale(dayjs.locale(), { weekStart })
|
||||
setDates(calculateMonth(page, weekStart))
|
||||
setDates(calculateMonth(dayjs().month(page.month).year(page.year), weekStart))
|
||||
}, [weekStart, page])
|
||||
|
||||
const handleFinishSelection = useCallback(() => {
|
||||
|
|
@ -149,8 +148,7 @@ interface Date {
|
|||
}
|
||||
|
||||
/** Calculate the dates to show for the month in a 2d array */
|
||||
const calculateMonth = ({ month, year }: { month: number, year: number }, weekStart: 0 | 1) => {
|
||||
const date = dayjs().month(month).year(year)
|
||||
const calculateMonth = (date: Dayjs, weekStart: 0 | 1) => {
|
||||
const daysInMonth = date.daysInMonth()
|
||||
const daysBefore = date.date(1).day() - weekStart
|
||||
const daysAfter = 6 - date.date(daysInMonth).day() + weekStart
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { useCallback, useMemo, useRef, useState } from 'react'
|
||||
import { rotateArray } from '@giraugh/tools'
|
||||
|
||||
import dayjs from '/src/config/dayjs'
|
||||
import { useDayjs } from '/src/config/dayjs'
|
||||
import { useTranslation } from '/src/i18n/client'
|
||||
import { useStore } from '/src/stores'
|
||||
import useSettingsStore from '/src/stores/settingsStore'
|
||||
|
|
@ -9,10 +10,6 @@ import { makeClass } from '/src/utils'
|
|||
// Use styles from Month picker
|
||||
import styles from '../Month/Month.module.scss'
|
||||
|
||||
// TODO: use from giraugh tools
|
||||
export const rotateArray = <T, >(arr: T[], amount = 1): T[] =>
|
||||
arr.map((_, i) => arr[((( -amount + i ) % arr.length) + arr.length) % arr.length])
|
||||
|
||||
interface WeekdaysProps {
|
||||
/** Array of weekdays as numbers from 0-6 (as strings) */
|
||||
value: string[]
|
||||
|
|
@ -21,6 +18,7 @@ interface WeekdaysProps {
|
|||
|
||||
const Weekdays = ({ value, onChange }: WeekdaysProps) => {
|
||||
const { t } = useTranslation('home')
|
||||
const dayjs = useDayjs()
|
||||
|
||||
const weekStart = useStore(useSettingsStore, state => state.weekStart) ?? 0
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import SelectField from '/src/components/SelectField/SelectField'
|
|||
import TextField from '/src/components/TextField/TextField'
|
||||
import TimeRangeField from '/src/components/TimeRangeField/TimeRangeField'
|
||||
import { API_BASE } from '/src/config/api'
|
||||
import dayjs from '/src/config/dayjs'
|
||||
import { useDayjs } from '/src/config/dayjs'
|
||||
import { useTranslation } from '/src/i18n/client'
|
||||
import timezones from '/src/res/timezones.json'
|
||||
|
||||
|
|
@ -36,6 +36,7 @@ const defaultValues: Fields = {
|
|||
|
||||
const CreateForm = () => {
|
||||
const { t } = useTranslation('home')
|
||||
const dayjs = useDayjs()
|
||||
const { push } = useRouter()
|
||||
|
||||
const {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import Link from 'next/link'
|
|||
|
||||
import Content from '/src/components/Content/Content'
|
||||
import Section from '/src/components/Section/Section'
|
||||
import dayjs from '/src/config/dayjs'
|
||||
import { useDayjs } from '/src/config/dayjs'
|
||||
import { useTranslation } from '/src/i18n/client'
|
||||
import { useStore } from '/src/stores'
|
||||
import useRecentsStore from '/src/stores/recentsStore'
|
||||
|
|
@ -18,6 +18,7 @@ interface RecentsProps {
|
|||
const Recents = ({ target }: RecentsProps) => {
|
||||
const recents = useStore(useRecentsStore, state => state.recents)
|
||||
const { t } = useTranslation(['home', 'common'])
|
||||
const dayjs = useDayjs()
|
||||
|
||||
return recents?.length ? <Section id="recents">
|
||||
<Content>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import { Settings as SettingsIcon } from 'lucide-react'
|
|||
|
||||
import SelectField from '/src/components/SelectField/SelectField'
|
||||
import ToggleField from '/src/components/ToggleField/ToggleField'
|
||||
import dayjs from '/src/config/dayjs'
|
||||
import { useTranslation } from '/src/i18n/client'
|
||||
import { languageDetails } from '/src/i18n/options'
|
||||
import { useStore } from '/src/stores'
|
||||
|
|
@ -16,12 +15,6 @@ import { makeClass, unhyphenate } from '/src/utils'
|
|||
|
||||
import styles from './Settings.module.scss'
|
||||
|
||||
// TODO: add to giraugh tools
|
||||
const isKeyOfObject = <T extends object>(
|
||||
key: string | number | symbol,
|
||||
obj: T,
|
||||
): key is keyof T => key in obj
|
||||
|
||||
const Settings = () => {
|
||||
const { t, i18n } = useTranslation('common')
|
||||
const router = useRouter()
|
||||
|
|
@ -128,17 +121,7 @@ const Settings = () => {
|
|||
}}
|
||||
isSmall
|
||||
value={i18n.language}
|
||||
onChange={e => {
|
||||
if (isKeyOfObject(e.target.value, languageDetails)) {
|
||||
store?.setWeekStart(languageDetails[e.target.value].weekStart)
|
||||
store?.setTimeFormat(languageDetails[e.target.value].timeFormat)
|
||||
|
||||
languageDetails[e.target.value]?.import().then(() => {
|
||||
dayjs.locale(e.target.value)
|
||||
})
|
||||
}
|
||||
i18n.changeLanguage(e.target.value).then(() => router.refresh())
|
||||
}}
|
||||
onChange={e => i18n.changeLanguage(e.target.value).then(() => router.refresh())}
|
||||
/>
|
||||
</div>
|
||||
</dialog>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import { useCallback, useState } from 'react'
|
||||
import { isKeyOfObject } from '@giraugh/tools'
|
||||
import dayjs from 'dayjs'
|
||||
import customParseFormat from 'dayjs/plugin/customParseFormat'
|
||||
import isToday from 'dayjs/plugin/isToday'
|
||||
|
|
@ -7,6 +9,11 @@ import timezone from 'dayjs/plugin/timezone'
|
|||
import updateLocale from 'dayjs/plugin/updateLocale'
|
||||
import utc from 'dayjs/plugin/utc'
|
||||
|
||||
import { useTranslation } from '/src/i18n/client'
|
||||
import { languageDetails } from '/src/i18n/options'
|
||||
import { useStore } from '/src/stores'
|
||||
import useSettingsStore from '/src/stores/settingsStore'
|
||||
|
||||
dayjs.extend(customParseFormat)
|
||||
dayjs.extend(isToday)
|
||||
dayjs.extend(localeData)
|
||||
|
|
@ -15,4 +22,26 @@ dayjs.extend(timezone)
|
|||
dayjs.extend(updateLocale)
|
||||
dayjs.extend(utc)
|
||||
|
||||
export default dayjs
|
||||
export const useDayjs = () => {
|
||||
const { i18n } = useTranslation()
|
||||
const store = useStore(useSettingsStore, state => state)
|
||||
const [updateInstance, setUpdateInstance] = useState(0)
|
||||
|
||||
const instance = useCallback(dayjs, [updateInstance, dayjs])
|
||||
|
||||
const handleLanguageChange = useCallback((lng: string) => {
|
||||
if (isKeyOfObject(lng, languageDetails)) {
|
||||
store?.setWeekStart(languageDetails[lng].weekStart)
|
||||
store?.setTimeFormat(languageDetails[lng].timeFormat)
|
||||
|
||||
languageDetails[lng]?.import().then(() => {
|
||||
dayjs.locale(lng)
|
||||
setUpdateInstance(updateInstance + 1)
|
||||
})
|
||||
}
|
||||
}, [store])
|
||||
|
||||
i18n.on('languageChanged', handleLanguageChange)
|
||||
|
||||
return instance
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,12 +2,11 @@
|
|||
|
||||
import { initReactI18next, useTranslation as useTranslationHook } from 'react-i18next'
|
||||
import { cookies } from 'next/dist/client/components/headers' // risky disky (undocumented???)
|
||||
import dayjs from 'dayjs'
|
||||
import i18next from 'i18next'
|
||||
import LanguageDetector from 'i18next-browser-languagedetector'
|
||||
import resourcesToBackend from 'i18next-resources-to-backend'
|
||||
|
||||
import dayjs from '/src/config/dayjs'
|
||||
|
||||
import { cookieName, getOptions, languageDetails } from './options'
|
||||
|
||||
i18next
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import { cookies, headers } from 'next/headers'
|
||||
import acceptLanguage from 'accept-language'
|
||||
import dayjs from 'dayjs'
|
||||
import { createInstance } from 'i18next'
|
||||
import resourcesToBackend from 'i18next-resources-to-backend'
|
||||
|
||||
import dayjs from '/src/config/dayjs'
|
||||
|
||||
import { cookieName, fallbackLng, getOptions, languageDetails, languages } from './options'
|
||||
|
||||
type Mutable<T> = { -readonly [K in keyof T]: Mutable<T[K]> }
|
||||
|
|
|
|||
|
|
@ -65,6 +65,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.40.0.tgz#3ba73359e11f5a7bd3e407f70b3528abfae69cec"
|
||||
integrity sha512-ElyB54bJIhXQYVKjDSvCkPO1iU1tSAeVQJbllWJq1XQSmmA4dgFk8CbiBGpiOPxleE48vDogxCtmMYku4HSVLA==
|
||||
|
||||
"@giraugh/tools@^1.5.0":
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@giraugh/tools/-/tools-1.5.0.tgz#5c5cc8b248d1e04aebc46dcbeb7620c99f47d2ec"
|
||||
integrity sha512-DZTrxKU5Ul5+UnDUNja0Cp1HcMLPGF2fh7j4ICEzaNwvRMwcHRH241L/pfneuibZ22w1Ka4U7LVzOWL+SjLIjw==
|
||||
|
||||
"@humanwhocodes/config-array@^0.11.8":
|
||||
version "0.11.8"
|
||||
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz#03595ac2075a4dc0f191cc2131de14fbd7d410b9"
|
||||
|
|
|
|||
Loading…
Reference in a new issue