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