Add missing frontend/src/lib files (api.ts, utils.ts)

This commit is contained in:
XPS\Micro 2026-01-30 22:00:55 +01:00
parent 68e1320d20
commit e17231eb75
3 changed files with 113 additions and 0 deletions

1
.gitignore vendored
View File

@ -25,6 +25,7 @@ downloads/
eggs/
.eggs/
lib/
!frontend/src/lib/
lib64/
parts/
sdist/

106
frontend/src/lib/api.ts Normal file
View File

@ -0,0 +1,106 @@
const API_BASE = process.env.NEXT_PUBLIC_API_URL || "";
interface ApiResponse<T> {
data?: T;
error?: string;
}
async function fetchApi<T>(
endpoint: string,
options: RequestInit = {}
): Promise<ApiResponse<T>> {
const token =
typeof window !== "undefined" ? localStorage.getItem("token") : null;
const headers: HeadersInit = {
"Content-Type": "application/json",
...options.headers,
};
if (token) {
(headers as Record<string, string>)["Authorization"] = `Bearer ${token}`;
}
try {
const response = await fetch(`${API_BASE}${endpoint}`, {
...options,
headers,
});
const data = await response.json();
if (!response.ok) {
return { error: data.error || "Ein Fehler ist aufgetreten" };
}
return { data };
} catch (error) {
return { error: "Netzwerkfehler - Server nicht erreichbar" };
}
}
export interface LoginResponse {
access_token: string;
token_type: string;
expires_in: number;
user: {
id: number;
username: string;
email: string;
};
}
export interface UserResponse {
user: {
id: number;
username: string;
email: string;
created_at: string | null;
};
container: {
id: string | null;
port: number | null;
status: string;
service_url: string;
};
}
export interface ContainerStatusResponse {
container_id: string | null;
status: string;
}
export interface ContainerRestartResponse {
message: string;
container_id: string;
status: string;
}
export const api = {
login: (username: string, password: string) =>
fetchApi<LoginResponse>("/api/auth/login", {
method: "POST",
body: JSON.stringify({ username, password }),
}),
signup: (username: string, email: string, password: string) =>
fetchApi<LoginResponse>("/api/auth/signup", {
method: "POST",
body: JSON.stringify({ username, email, password }),
}),
logout: () =>
fetchApi<{ message: string }>("/api/auth/logout", {
method: "POST",
}),
getUser: () => fetchApi<UserResponse>("/api/user/me"),
getContainerStatus: () =>
fetchApi<ContainerStatusResponse>("/api/container/status"),
restartContainer: () =>
fetchApi<ContainerRestartResponse>("/api/container/restart", {
method: "POST",
}),
};

View File

@ -0,0 +1,6 @@
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}