Files
jobtrackingapp/job-tracker-ui/src/hooks/useCompanies.ts
T
2026-08-24 20:21:09 +02:00

90 lines
2.3 KiB
TypeScript

import { useEffect, useState } from "react";
import { api } from "../api";
import { AUTH_USER_CHANGED_EVENT, getAuthUserKey } from "../auth";
import { Company } from "../types";
import { useViewResource, ViewResourceError } from "./useViewResource";
let cachedCompanies: Company[] | null = null;
let inflight: Promise<Company[]> | null = null;
let cacheOwner = "";
function resetForOwner(owner: string) {
if (cacheOwner === owner) return;
cacheOwner = owner;
cachedCompanies = null;
inflight = null;
}
function cachedForCurrentOwner() {
const owner = getAuthUserKey();
resetForOwner(owner);
return cachedCompanies;
}
async function fetchCompanies(): Promise<Company[]> {
const owner = getAuthUserKey();
resetForOwner(owner);
if (cachedCompanies) return cachedCompanies;
if (inflight) return inflight;
const request = api
.get<Company[]>('/companies')
.then((r) => {
if (cacheOwner === owner && getAuthUserKey() === owner) cachedCompanies = r.data;
return r.data;
})
.finally(() => {
if (inflight === request) inflight = null;
});
inflight = request;
return inflight;
}
export function invalidateCompaniesCache() {
cachedCompanies = null;
inflight = null;
}
export function useCompanies(): {
companies: Company[];
loading: boolean;
refreshing: boolean;
error: ViewResourceError | null;
reload: () => Promise<void>;
} {
const [cacheBust, setCacheBust] = useState(0);
const resource = useViewResource(fetchCompanies, {
initialData: cachedForCurrentOwner() ?? [],
errorMessage: 'Unable to load companies right now.',
deps: [cacheBust],
});
useEffect(() => {
if (!resource.error) {
cachedCompanies = resource.data;
}
}, [resource.data, resource.error]);
useEffect(() => {
const reloadForAccount = () => {
resetForOwner(getAuthUserKey());
setCacheBust((value) => value + 1);
};
window.addEventListener(AUTH_USER_CHANGED_EVENT, reloadForAccount);
return () => window.removeEventListener(AUTH_USER_CHANGED_EVENT, reloadForAccount);
}, []);
return {
companies: resource.data,
loading: resource.loading,
refreshing: resource.refreshing,
error: resource.error,
reload: async () => {
invalidateCompaniesCache();
setCacheBust((value) => value + 1);
},
};
}