114 lines
3.1 KiB
TypeScript
114 lines
3.1 KiB
TypeScript
import type {
|
|
Campaign,
|
|
Character,
|
|
Gear,
|
|
Talent,
|
|
GameItem,
|
|
GameTalent,
|
|
RollResult,
|
|
} from "./types";
|
|
|
|
const BASE = "/api";
|
|
|
|
async function request<T>(path: string, options?: RequestInit): Promise<T> {
|
|
const res = await fetch(`${BASE}${path}`, {
|
|
headers: { "Content-Type": "application/json" },
|
|
...options,
|
|
});
|
|
if (!res.ok) {
|
|
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
throw new Error(err.error || res.statusText);
|
|
}
|
|
if (res.status === 204) return undefined as T;
|
|
return res.json();
|
|
}
|
|
|
|
// Campaigns
|
|
export const getCampaigns = () => request<Campaign[]>("/campaigns");
|
|
export const createCampaign = (name: string) =>
|
|
request<Campaign>("/campaigns", {
|
|
method: "POST",
|
|
body: JSON.stringify({ name }),
|
|
});
|
|
export const deleteCampaign = (id: number) =>
|
|
request<void>(`/campaigns/${id}`, { method: "DELETE" });
|
|
|
|
// Characters
|
|
export const getCharacters = (campaignId: number) =>
|
|
request<Character[]>(`/campaigns/${campaignId}/characters`);
|
|
export const createCharacter = (
|
|
campaignId: number,
|
|
data: { name: string; class?: string; ancestry?: string; hp_max?: number },
|
|
) =>
|
|
request<Character>(`/campaigns/${campaignId}/characters`, {
|
|
method: "POST",
|
|
body: JSON.stringify(data),
|
|
});
|
|
export const updateCharacter = (id: number, data: Partial<Character>) =>
|
|
request<Character>(`/characters/${id}`, {
|
|
method: "PATCH",
|
|
body: JSON.stringify(data),
|
|
});
|
|
export const deleteCharacter = (id: number) =>
|
|
request<void>(`/characters/${id}`, { method: "DELETE" });
|
|
|
|
// Stats
|
|
export const updateStat = (
|
|
characterId: number,
|
|
statName: string,
|
|
value: number,
|
|
) =>
|
|
request<{ characterId: number; statName: string; value: number }>(
|
|
`/characters/${characterId}/stats/${statName}`,
|
|
{ method: "PATCH", body: JSON.stringify({ value }) },
|
|
);
|
|
|
|
// Gear
|
|
export const addGear = (
|
|
characterId: number,
|
|
data: {
|
|
name: string;
|
|
type?: string;
|
|
slot_count?: number;
|
|
properties?: Record<string, unknown>;
|
|
effects?: Record<string, unknown>;
|
|
game_item_id?: number | null;
|
|
},
|
|
) =>
|
|
request<Gear>(`/characters/${characterId}/gear`, {
|
|
method: "POST",
|
|
body: JSON.stringify(data),
|
|
});
|
|
export const removeGear = (characterId: number, gearId: number) =>
|
|
request<void>(`/characters/${characterId}/gear/${gearId}`, {
|
|
method: "DELETE",
|
|
});
|
|
|
|
// Talents
|
|
export const addTalent = (
|
|
characterId: number,
|
|
data: {
|
|
name: string;
|
|
description?: string;
|
|
effect?: Record<string, unknown>;
|
|
game_talent_id?: number | null;
|
|
},
|
|
) =>
|
|
request<Talent>(`/characters/${characterId}/talents`, {
|
|
method: "POST",
|
|
body: JSON.stringify(data),
|
|
});
|
|
export const removeTalent = (characterId: number, talentId: number) =>
|
|
request<void>(`/characters/${characterId}/talents/${talentId}`, {
|
|
method: "DELETE",
|
|
});
|
|
|
|
// Game Items
|
|
export const getGameItems = () => request<GameItem[]>("/game-items");
|
|
|
|
// Game Talents
|
|
export const getGameTalents = () => request<GameTalent[]>("/game-talents");
|
|
|
|
// Rolls
|
|
export const getRolls = (campaignId: number) =>
|
|
request<RollResult[]>(`/campaigns/${campaignId}/rolls`);
|