Fix company and fiscal year sync issues

- Remove duplicate sync logic from CompanySwitcher (CompanyGuard handles it)
- Validate persisted activeCompany against API response in CompanyGuard
- Reset fiscal year state when switching companies in FiscalYearSelector
- Validate currentFiscalYear belongs to current company's data

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Nicolaj Hartmann 2026-01-30 22:47:05 +01:00
parent 7d819ace28
commit de235a3da7
3 changed files with 42 additions and 51 deletions

View file

@ -31,30 +31,20 @@ export default function CompanyGuard({ children }: CompanyGuardProps) {
// Sync companies to store when loaded // Sync companies to store when loaded
useEffect(() => { useEffect(() => {
if (companies) { if (companies && companies.length > 0) {
setCompanies(companies); setCompanies(companies);
// Set active company if not already set // Validate that activeCompany exists in API response
if (companies.length > 0 && !activeCompany) { const validCompany = activeCompany
// Try to restore from localStorage ? companies.find((c) => c.id === activeCompany.id)
const stored = localStorage.getItem('books-company-storage'); : null;
if (stored) {
try { if (!validCompany) {
const parsed = JSON.parse(stored); // Persisted company doesn't exist - set to first
const storedCompany = parsed.state?.activeCompany;
if (storedCompany) {
const found = companies.find((c) => c.id === storedCompany.id);
if (found) {
setActiveCompany(found);
return;
}
}
} catch {
// Ignore parse errors
}
}
// Default to first company
setActiveCompany(companies[0]); setActiveCompany(companies[0]);
} else if (JSON.stringify(validCompany) !== JSON.stringify(activeCompany)) {
// Update with fresh data from API
setActiveCompany(validCompany);
} }
} }
}, [companies, activeCompany, setCompanies, setActiveCompany]); }, [companies, activeCompany, setCompanies, setActiveCompany]);

View file

@ -1,8 +1,6 @@
import { useEffect } from 'react';
import { Select, Space, Typography, Tag, Skeleton } from 'antd'; import { Select, Space, Typography, Tag, Skeleton } from 'antd';
import { ShopOutlined } from '@ant-design/icons'; import { ShopOutlined } from '@ant-design/icons';
import { useCompanyStore } from '@/stores/companyStore'; import { useCompanyStore } from '@/stores/companyStore';
import { useMyCompanies } from '@/api/queries/companyQueries';
import { formatCVR } from '@/lib/formatters'; import { formatCVR } from '@/lib/formatters';
import type { Company } from '@/types/accounting'; import type { Company } from '@/types/accounting';
@ -13,18 +11,8 @@ interface CompanySwitcherProps {
} }
export default function CompanySwitcher({ compact = false }: CompanySwitcherProps) { export default function CompanySwitcher({ compact = false }: CompanySwitcherProps) {
const { data: companies = [], isLoading } = useMyCompanies(); const { activeCompany, setActiveCompany } = useCompanyStore();
const { activeCompany, setActiveCompany, setCompanies } = useCompanyStore(); const companies = useCompanyStore((state) => state.companies);
// Sync companies with store when data changes
useEffect(() => {
if (companies.length > 0) {
setCompanies(companies);
if (!activeCompany) {
setActiveCompany(companies[0]);
}
}
}, [companies, activeCompany, setActiveCompany, setCompanies]);
const handleCompanyChange = (companyId: string) => { const handleCompanyChange = (companyId: string) => {
const company = companies.find((c) => c.id === companyId); const company = companies.find((c) => c.id === companyId);
@ -33,12 +21,8 @@ export default function CompanySwitcher({ compact = false }: CompanySwitcherProp
} }
}; };
if (isLoading) {
return <Skeleton.Input style={{ width: 200 }} active />;
}
if (companies.length === 0) { if (companies.length === 0) {
return null; return <Skeleton.Input style={{ width: 200 }} active />;
} }
return ( return (

View file

@ -1,6 +1,6 @@
// FiscalYearSelector - Dropdown for selecting active fiscal year (regnskabsar) // FiscalYearSelector - Dropdown for selecting active fiscal year (regnskabsar)
import { useState, useEffect } from 'react'; import { useState, useEffect, useRef } from 'react';
import { Select, Space, Typography, Tag, Divider, Button, Skeleton } from 'antd'; import { Select, Space, Typography, Tag, Divider, Button, Skeleton } from 'antd';
import { import {
CalendarOutlined, CalendarOutlined,
@ -62,21 +62,38 @@ export default function FiscalYearSelector({ onCreateNew, onManage }: FiscalYear
const [createModalOpen, setCreateModalOpen] = useState(false); const [createModalOpen, setCreateModalOpen] = useState(false);
// Sync fiscal years with store when data changes // Track company changes
const prevCompanyIdRef = useRef<string | undefined>(activeCompany?.id);
// Reset fiscal year state when company changes
useEffect(() => {
if (activeCompany?.id !== prevCompanyIdRef.current) {
const isInitialMount = prevCompanyIdRef.current === undefined;
prevCompanyIdRef.current = activeCompany?.id;
if (!isInitialMount) {
// Company changed - reset fiscal year state
setFiscalYears([]);
setCurrentFiscalYear(null);
}
}
}, [activeCompany?.id, setFiscalYears, setCurrentFiscalYear]);
// Sync fiscal years from API to store
useEffect(() => { useEffect(() => {
if (fiscalYearsData.length > 0) { if (fiscalYearsData.length > 0) {
setFiscalYears(fiscalYearsData); setFiscalYears(fiscalYearsData);
}
}, [fiscalYearsData, setFiscalYears]);
// Set default fiscal year if none selected // Validate currentFiscalYear belongs to this company's data
useEffect(() => { const isValid = currentFiscalYear &&
if (fiscalYears.length > 0 && !currentFiscalYear) { fiscalYearsData.some(fy => fy.id === currentFiscalYear.id);
// Default to most recent open year, or first year
const openYear = fiscalYears.find(y => y.status === 'open'); if (!isValid) {
setCurrentFiscalYear(openYear || fiscalYears[0]); const openYear = fiscalYearsData.find(y => y.status === 'open');
setCurrentFiscalYear(openYear || fiscalYearsData[0]);
}
} }
}, [fiscalYears, currentFiscalYear, setCurrentFiscalYear]); }, [fiscalYearsData, currentFiscalYear, setFiscalYears, setCurrentFiscalYear]);
const handleFiscalYearChange = (yearId: string) => { const handleFiscalYearChange = (yearId: string) => {
const year = fiscalYears.find((y) => y.id === yearId); const year = fiscalYears.find((y) => y.id === yearId);