Redesign the setup flow and consolidate the CSS into one primitives layer
Onboarding asks explicitly for one or two parents and shows one card per parent for balances; the balance form is per parent with inline validation; the partner can be filled from the FK deduction or added from it. Settings and Dashboard reuse the same form. CSS: bare buttons carry no colour any more; buttons, cards, choice cards, fields, alerts, badges, eyebrow and modal chrome are defined once in primitives.css. Media queries live only in responsive.css. A style guard test blocks hex, !important and stray media queries. Bilingual fixes: calendar selects size by content, header no longer wraps. Vitest is capped at four workers. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import * as api from '@/services/api'
|
||||
import { useLatestRequest } from './useLatestRequest'
|
||||
import type { ParentBalanceInitial } from '@/components/modals/ParentBalanceForm'
|
||||
|
||||
interface UseLatestBalanceResult {
|
||||
initial: ParentBalanceInitial | undefined
|
||||
isLoading: boolean
|
||||
error: string | null
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a parent's latest saved parental-leave balance so `ParentBalanceForm`
|
||||
* can be reopened pre-filled with the real figures instead of always
|
||||
* falling back to its 195/45/60 preset. Shared by `Settings` ("Dagar kvar")
|
||||
* and `Dashboard` ("Ange manuellt") so a saved balance shows the same way
|
||||
* from either entry point.
|
||||
*
|
||||
* Imported directly from this file (not the `@/hooks` barrel) by both pages
|
||||
* — same escape hatch `VacationDaysList` uses for `useVacationDays` — so
|
||||
* their tests can drive it through a mocked `api.getParentalLeave` instead
|
||||
* of mocking the hook itself, while the rest of `@/hooks` stays blanket-
|
||||
* mocked.
|
||||
*
|
||||
* `personalDataUuid`/`childId` are null when no balance form is open — the
|
||||
* hook then no-ops and reports no saved balance, rather than fetching.
|
||||
*/
|
||||
export function useLatestBalance(
|
||||
personalDataUuid: string | null,
|
||||
childId: string | null,
|
||||
): UseLatestBalanceResult {
|
||||
const [initial, setInitial] = useState<ParentBalanceInitial | undefined>(undefined)
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
const { start, isCurrent } = useLatestRequest()
|
||||
|
||||
const fetch = useCallback(async () => {
|
||||
const requestId = start()
|
||||
if (!personalDataUuid || !childId) {
|
||||
setInitial(undefined)
|
||||
setError(null)
|
||||
return
|
||||
}
|
||||
setIsLoading(true)
|
||||
setError(null)
|
||||
try {
|
||||
const response = await api.getParentalLeave(personalDataUuid, childId)
|
||||
if (!isCurrent(requestId)) return
|
||||
// `null` means nothing has been saved for this parent/child yet (a
|
||||
// brand-new partner, or self before any fetch) — not an error, so the
|
||||
// form is left to fall back to its own preset.
|
||||
setInitial(
|
||||
response
|
||||
? {
|
||||
sjukpenningLeft: response.tierData.sjukpenningLeft,
|
||||
lagstaNivaLeft: response.tierData.lagstaNivaLeft,
|
||||
dubbeldagarLeft: response.dubbeldagarLeft,
|
||||
reservedDaysLeft: response.reservedDaysLeft,
|
||||
}
|
||||
: undefined,
|
||||
)
|
||||
} catch (err) {
|
||||
if (!isCurrent(requestId)) return
|
||||
setError(err instanceof Error ? err.message : 'Failed to load parental leave balance')
|
||||
setInitial(undefined)
|
||||
} finally {
|
||||
if (isCurrent(requestId)) setIsLoading(false)
|
||||
}
|
||||
}, [personalDataUuid, childId, start, isCurrent])
|
||||
|
||||
useEffect(() => {
|
||||
void fetch()
|
||||
}, [fetch])
|
||||
|
||||
return { initial, isLoading, error }
|
||||
}
|
||||
Reference in New Issue
Block a user