feat(cache): add stale get caching for report filters and summaries

This commit is contained in:
2026-04-30 16:13:35 +03:30
parent 0e8d43f1ea
commit a5a7a01da0
8 changed files with 356 additions and 131 deletions

View File

@@ -1,12 +1,26 @@
import { authFetch } from "./client";
export const getClients = async (
workspaceId: string,
search: string = "",
ordering: string = "",
limit: number = 10,
offset: number = 0
) => {
import { authFetch } from "./client";
import { cachedGetJson, invalidateApiCache } from "./cache";
export interface Client {
id: string
name: string
notes?: string
}
interface PaginatedResponse<T> {
count: number
next: string | null
previous: string | null
results: T[]
}
export const getClients = async (
workspaceId: string,
search: string = "",
ordering: string = "",
limit: number = 10,
offset: number = 0
): Promise<PaginatedResponse<Client>> => {
const queryParams = new URLSearchParams({
workspace: workspaceId,
limit: limit.toString(),
@@ -16,12 +30,11 @@ export const getClients = async (
if (search) queryParams.append("search", search);
if (ordering) queryParams.append("ordering", ordering);
const response = await authFetch(`/api/clients/?${queryParams.toString()}`);
if (!response.ok) {
throw new Error("Failed to fetch clients");
}
return response.json();
};
return cachedGetJson<PaginatedResponse<Client>>(`/api/clients/?${queryParams.toString()}`, {
ttlMs: 5 * 60 * 1000,
namespaces: ["clients"],
});
};
export const createClient = async (workspaceId: string, data: { name: string; notes: string }) => {
const response = await authFetch("/api/clients/", {
@@ -32,12 +45,14 @@ export const createClient = async (workspaceId: string, data: { name: string; no
}),
});
if (!response.ok) {
const errorData = await response.json().catch(() => null);
throw new Error(errorData?.detail || errorData?.message || "Failed to create client");
}
return response.json();
};
if (!response.ok) {
const errorData = await response.json().catch(() => null);
throw new Error(errorData?.detail || errorData?.message || "Failed to create client");
}
const payload = await response.json();
invalidateApiCache(["clients", "reports"]);
return payload;
};
export const updateClient = async (id: string, data: { name?: string; notes?: string }) => {
const response = await authFetch(`/api/clients/${id}/`, {
@@ -45,25 +60,28 @@ export const updateClient = async (id: string, data: { name?: string; notes?: st
body: JSON.stringify(data),
});
if (!response.ok) {
const errorData = await response.json().catch(() => null);
throw new Error(errorData?.detail || errorData?.message || "Failed to update client");
}
return response.json();
};
if (!response.ok) {
const errorData = await response.json().catch(() => null);
throw new Error(errorData?.detail || errorData?.message || "Failed to update client");
}
const payload = await response.json();
invalidateApiCache(["clients", "reports"]);
return payload;
};
export const deleteClient = async (id: string) => {
const response = await authFetch(`/api/clients/${id}/`, {
method: "DELETE",
});
if (!response.ok) {
const errorData = await response.json().catch(() => null);
throw new Error(errorData?.detail || errorData?.message || "Failed to delete client");
}
if (response.status === 204) {
return { success: true };
if (!response.ok) {
const errorData = await response.json().catch(() => null);
throw new Error(errorData?.detail || errorData?.message || "Failed to delete client");
}
invalidateApiCache(["clients", "reports"]);
if (response.status === 204) {
return { success: true };
}
return response.json().catch(() => ({ success: true }));