Bug/gh issues fiz (#1103)

* refactor: optimize page loading and data fetching

* fix: resolve recurring production runtime errors

* feat: add MCP company and customer updates

* fix: handle year-end tax adjustments

* feat: harden annual report compliance

* fix: expand invoice logo and font support

* fix: sanitize API route error responses

* fix: sanitize user-facing error messages

* feat: persist onboarding and tax assessment notices

* fix: reduce cloud backup audit churn

* feat: refine invoice editor layout

* fix: show saved tax adjustments in INK2

* fix: complete annual report API mappings

* docs: record operational safeguards and decisions

* fix: harden annual report review findings

* fix: adjust column span for description based on VAT registration

* New css class name
This commit is contained in:
Mattsson
2026-07-21 23:00:15 +02:00
committed by GitHub
parent 702512437a
commit e11f70b347
467 changed files with 17569 additions and 2221 deletions
+31 -17
View File
@@ -51,6 +51,16 @@ interface Props {
*/
onReady?: () => void
className?: string
/** Server-loaded periods for the first render, scoped to initialCompanyId. */
initialPeriods?: FiscalPeriod[]
initialCompanyId?: string | null
}
function preparePeriods(periods: FiscalPeriod[], hideFuturePeriods: boolean): FiscalPeriod[] {
const today = new Date().toISOString().split('T')[0]
return periods
.filter((period) => !hideFuturePeriods || period.period_start <= today)
.sort((a, b) => b.period_start.localeCompare(a.period_start))
}
/**
@@ -71,11 +81,16 @@ export function FiscalYearSelector({
hideFuturePeriods = false,
onReady,
className,
initialPeriods,
initialCompanyId,
}: Props) {
const { company } = useCompany()
const t = useTranslations('fiscal_year')
const [periods, setPeriods] = useState<FiscalPeriod[]>([])
const [loaded, setLoaded] = useState(false)
const canUseInitialPeriods = initialCompanyId === company?.id && initialPeriods !== undefined
const [periods, setPeriods] = useState<FiscalPeriod[]>(() =>
canUseInitialPeriods ? preparePeriods(initialPeriods, hideFuturePeriods) : [],
)
const [loaded, setLoaded] = useState(canUseInitialPeriods)
const effectiveLabel = label === null ? null : (label ?? t('label'))
useEffect(() => {
@@ -87,24 +102,23 @@ export function FiscalYearSelector({
}
let cancelled = false
;(async () => {
const res = await fetch('/api/bookkeeping/fiscal-periods')
if (!res.ok) {
if (!cancelled) {
setLoaded(true)
onReady?.()
let fetched: FiscalPeriod[]
if (initialCompanyId === company.id && initialPeriods !== undefined) {
fetched = preparePeriods(initialPeriods, hideFuturePeriods)
} else {
const res = await fetch('/api/bookkeeping/fiscal-periods')
if (!res.ok) {
if (!cancelled) {
setLoaded(true)
onReady?.()
}
return
}
return
const { data } = await res.json()
fetched = preparePeriods(data || [], hideFuturePeriods)
}
const { data } = await res.json()
if (cancelled) return
let fetched: FiscalPeriod[] = data || []
if (hideFuturePeriods) {
const today = new Date().toISOString().split('T')[0]
fetched = fetched.filter((p) => p.period_start <= today)
}
// Newest first: most migrations list recent years at the top
fetched.sort((a, b) => b.period_start.localeCompare(a.period_start))
setPeriods(fetched)
setLoaded(true)
@@ -131,7 +145,7 @@ export function FiscalYearSelector({
// onReady is intentionally excluded from deps: it's a lifecycle callback that
// should fire once per load, not re-trigger if the parent re-creates it.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [company?.id, hideFuturePeriods, includeAllOption])
}, [company?.id, hideFuturePeriods, includeAllOption, initialCompanyId, initialPeriods])
const handleChange = (next: string) => {
const nextPeriodId = next === ALL_YEARS_VALUE ? null : next