feat(client): add client's page + CRUD operations modals

This commit is contained in:
2026-03-13 05:09:55 +08:00
parent 3948505a30
commit bbf7dfad2e
13 changed files with 588 additions and 14 deletions

63
src/api/clients.ts Normal file
View File

@@ -0,0 +1,63 @@
import { authFetch } from "./client";
import { type PaginatedClientList } from "../types/client";
export const getClients = async (workspaceId: string, search: string = "", ordering: string = "") => {
const queryParams = new URLSearchParams({ workspace: workspaceId });
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();
};
export const createClient = async (workspaceId: string, data: { name: string; notes: string }) => {
const response = await authFetch("/api/clients/", {
method: "POST",
body: JSON.stringify({
workspace_id: workspaceId,
...data,
}),
});
if (!response.ok) {
const errorData = await response.json().catch(() => null);
throw new Error(errorData?.detail || errorData?.message || "Failed to create client");
}
return response.json();
};
export const updateClient = async (id: string, data: { name?: string; notes?: string }) => {
const response = await authFetch(`/api/clients/${id}/`, {
method: "PATCH",
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();
};
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");
}
// DELETE requests often return 204 No Content, which throws an error on .json()
if (response.status === 204) {
return { success: true };
}
return response.json().catch(() => ({ success: true }));
};