Initial commit — Умный Байт landing
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
const API_BASE = import.meta.env.VITE_API_URL || '';
|
||||
|
||||
export interface Product {
|
||||
id: number;
|
||||
slug: string;
|
||||
title: string;
|
||||
subtitle: string | null;
|
||||
description: string;
|
||||
status: 'production' | 'development' | 'planned';
|
||||
audience: 'B2B' | 'B2C' | 'global' | null;
|
||||
icon_key: string | null;
|
||||
tags: string[];
|
||||
sort_order: number;
|
||||
}
|
||||
|
||||
export interface ApproachItem {
|
||||
id: number;
|
||||
title: string;
|
||||
description: string;
|
||||
icon_key: string | null;
|
||||
sort_order: number;
|
||||
}
|
||||
|
||||
export interface LandingContent {
|
||||
sections: Record<string, Record<string, unknown>>;
|
||||
products: Product[];
|
||||
approach: ApproachItem[];
|
||||
settings: Record<string, string>;
|
||||
}
|
||||
|
||||
async function request<T>(
|
||||
path: string,
|
||||
options: RequestInit = {}
|
||||
): Promise<T> {
|
||||
const res = await fetch(`${API_BASE}${path}`, {
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...(options.headers || {}),
|
||||
},
|
||||
...options,
|
||||
});
|
||||
if (!res.ok) {
|
||||
const err = await res.json().catch(() => ({}));
|
||||
throw new Error(err.error || `request_failed_${res.status}`);
|
||||
}
|
||||
return res.json();
|
||||
}
|
||||
|
||||
export const api = {
|
||||
getContent: () => request<LandingContent>('/api/content'),
|
||||
|
||||
login: (login: string, password: string) =>
|
||||
request<{ ok: true; login: string }>('/api/admin/login', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ login, password }),
|
||||
}),
|
||||
logout: () =>
|
||||
request<{ ok: true }>('/api/admin/logout', { method: 'POST' }),
|
||||
me: () => request<{ admin: { id: number; login: string } }>('/api/admin/me'),
|
||||
|
||||
listProducts: () =>
|
||||
request<{ products: Product[] }>('/api/admin/products'),
|
||||
updateProduct: (id: number, data: Partial<Product>) =>
|
||||
request<{ product: Product }>(`/api/admin/products/${id}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(data),
|
||||
}),
|
||||
createProduct: (data: Omit<Product, 'id'>) =>
|
||||
request<{ product: Product }>('/api/admin/products', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
}),
|
||||
deleteProduct: (id: number) =>
|
||||
request<{ ok: true }>(`/api/admin/products/${id}`, {
|
||||
method: 'DELETE',
|
||||
}),
|
||||
|
||||
listSections: () => request<{ sections: unknown[] }>('/api/admin/sections'),
|
||||
updateSection: (key: string, data: { content_json?: unknown; title?: string }) =>
|
||||
request<{ section: unknown }>(`/api/admin/sections/${key}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(data),
|
||||
}),
|
||||
|
||||
listApproach: () => request<{ items: ApproachItem[] }>('/api/admin/approach'),
|
||||
updateApproach: (id: number, data: Partial<ApproachItem>) =>
|
||||
request<{ item: ApproachItem }>(`/api/admin/approach/${id}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(data),
|
||||
}),
|
||||
|
||||
listSettings: () =>
|
||||
request<{ settings: Record<string, string> }>('/api/admin/settings'),
|
||||
updateSetting: (key: string, value: string) =>
|
||||
request<{ ok: true }>(`/api/admin/settings/${key}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify({ value }),
|
||||
}),
|
||||
};
|
||||
Reference in New Issue
Block a user