first commit

This commit is contained in:
Alexej Wolff
2026-02-11 00:15:59 +01:00
commit cc003ffbd5
39 changed files with 12170 additions and 0 deletions
+302
View File
@@ -0,0 +1,302 @@
// API сервис для работы с бэкендом
const API_URL = import.meta.env.VITE_API_URL || "http://localhost:3001";
// ============ AUTH ============
export interface User {
id: string;
discordId: string;
username: string;
email: string;
avatar: string | null;
}
export function getDiscordLoginUrl(): string {
return `${API_URL}/auth/discord`;
}
export async function getCurrentUser(): Promise<User | null> {
try {
const response = await fetch(`${API_URL}/auth/me`, {
credentials: "include",
});
const data = await response.json();
return data.user;
} catch (error) {
console.error("Failed to get current user:", error);
return null;
}
}
export async function logout(): Promise<boolean> {
try {
const response = await fetch(`${API_URL}/auth/logout`, {
method: "POST",
credentials: "include",
});
return response.ok;
} catch (error) {
console.error("Failed to logout:", error);
return false;
}
}
export function getDiscordAvatarUrl(user: User): string {
if (user.avatar) {
return `https://cdn.discordapp.com/avatars/${user.discordId}/${user.avatar}.png`;
}
// Default Discord avatar
const defaultAvatarIndex = parseInt(user.discordId) % 5;
return `https://cdn.discordapp.com/embed/avatars/${defaultAvatarIndex}.png`;
}
// ============ STORIES ============
import type { Story } from "../types";
export async function getStories(): Promise<Story[]> {
try {
const response = await fetch(`${API_URL}/api/stories`, {
credentials: "include",
});
if (response.status === 401) {
return [];
}
if (!response.ok) {
throw new Error("Failed to fetch stories");
}
return await response.json();
} catch (error) {
console.error("Failed to get stories:", error);
return [];
}
}
export async function getStory(id: string): Promise<Story | null> {
try {
const response = await fetch(`${API_URL}/api/stories/${id}`, {
credentials: "include",
});
if (!response.ok) {
return null;
}
return await response.json();
} catch (error) {
console.error("Failed to get story:", error);
return null;
}
}
export async function createStory(
story: Omit<Story, "id" | "createdAt" | "updatedAt">,
): Promise<Story | null> {
try {
const response = await fetch(`${API_URL}/api/stories`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
credentials: "include",
body: JSON.stringify(story),
});
if (!response.ok) {
throw new Error("Failed to create story");
}
const data = await response.json();
return { ...data, id: data._id };
} catch (error) {
console.error("Failed to create story:", error);
return null;
}
}
export async function updateStory(
id: string,
story: Partial<Story>,
): Promise<boolean> {
try {
const response = await fetch(`${API_URL}/api/stories/${id}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
credentials: "include",
body: JSON.stringify(story),
});
return response.ok;
} catch (error) {
console.error("Failed to update story:", error);
return false;
}
}
export async function deleteStory(id: string): Promise<boolean> {
try {
const response = await fetch(`${API_URL}/api/stories/${id}`, {
method: "DELETE",
credentials: "include",
});
return response.ok;
} catch (error) {
console.error("Failed to delete story:", error);
return false;
}
}
// ============ GAME SESSIONS ============
import type { GameSession } from "../types";
export async function getSession(storyId: string): Promise<GameSession | null> {
try {
const response = await fetch(`${API_URL}/api/sessions/${storyId}`, {
credentials: "include",
});
if (!response.ok) {
return null;
}
return await response.json();
} catch (error) {
console.error("Failed to get session:", error);
return null;
}
}
export async function saveSession(
storyId: string,
session: Omit<GameSession, "storyId">,
): Promise<boolean> {
try {
const response = await fetch(`${API_URL}/api/sessions/${storyId}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
credentials: "include",
body: JSON.stringify(session),
});
return response.ok;
} catch (error) {
console.error("Failed to save session:", error);
return false;
}
}
// ============ PLAYER CHARACTERS ============
import type { PlayerCharacter } from "../types";
export async function getPlayerCharacters(): Promise<PlayerCharacter[]> {
try {
const response = await fetch(`${API_URL}/api/characters`, {
credentials: "include",
});
if (response.status === 401) {
return [];
}
if (!response.ok) {
throw new Error("Failed to fetch characters");
}
const data = await response.json();
return data.map((c: any) => ({ ...c, id: c._id || c.id }));
} catch (error) {
console.error("Failed to get characters:", error);
return [];
}
}
export async function getPlayerCharacter(
id: string,
): Promise<PlayerCharacter | null> {
try {
const response = await fetch(`${API_URL}/api/characters/${id}`, {
credentials: "include",
});
if (!response.ok) {
return null;
}
const data = await response.json();
return { ...data, id: data._id || data.id };
} catch (error) {
console.error("Failed to get character:", error);
return null;
}
}
export async function createPlayerCharacter(
character: Omit<PlayerCharacter, "id" | "userId" | "createdAt" | "updatedAt">,
): Promise<PlayerCharacter | null> {
try {
const response = await fetch(`${API_URL}/api/characters`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
credentials: "include",
body: JSON.stringify(character),
});
if (!response.ok) {
throw new Error("Failed to create character");
}
const data = await response.json();
return { ...data, id: data._id };
} catch (error) {
console.error("Failed to create character:", error);
return null;
}
}
export async function updatePlayerCharacter(
id: string,
character: Partial<PlayerCharacter>,
): Promise<boolean> {
try {
const response = await fetch(`${API_URL}/api/characters/${id}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
credentials: "include",
body: JSON.stringify(character),
});
return response.ok;
} catch (error) {
console.error("Failed to update character:", error);
return false;
}
}
export async function deletePlayerCharacter(id: string): Promise<boolean> {
try {
const response = await fetch(`${API_URL}/api/characters/${id}`, {
method: "DELETE",
credentials: "include",
});
return response.ok;
} catch (error) {
console.error("Failed to delete character:", error);
return false;
}
}