7475d4fd37
- Neue Spalte Kategorie (SET stern/sonne) in objekte-Tabelle - ObjektSelector zeigt je nach ArtFuehrung nur passende Objekte - SonnenFührung: Sonne fest vorausgewählt, zusätzliche Sonne-Objekte wählbar - Bestehende Objekte erhalten Kategorie automatisch beim Speichern - Admin: Kategorie editierbar (stern / sonne / stern,sonne) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
186 lines
4.9 KiB
TypeScript
186 lines
4.9 KiB
TypeScript
import type { BeoOption, LogbuchEintrag, ObjektOption, SelectedObjekt, Wetter } from '@/types/logbuch';
|
|
|
|
const PHP_DB_URL = process.env.PHP_DB_URL ?? 'http://localhost:8080/DB4js_all.php';
|
|
|
|
async function call<T>(cmd: string, params: object = {}): Promise<T> {
|
|
const res = await fetch(PHP_DB_URL, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ cmd, ...params }),
|
|
cache: 'no-store',
|
|
});
|
|
if (!res.ok) {
|
|
let detail = '';
|
|
try { detail = await res.text(); } catch { /* ignore */ }
|
|
throw new Error(`DB4js ${cmd} HTTP ${res.status}: ${detail}`);
|
|
}
|
|
const json: unknown = await res.json();
|
|
if (json && typeof json === 'object' && 'error' in json) {
|
|
throw new Error(`DB4js ${cmd}: ${(json as { error: string }).error}`);
|
|
}
|
|
return json as T;
|
|
}
|
|
|
|
// ---- Auth / Benutzer ----
|
|
|
|
export interface Beo {
|
|
id: number;
|
|
name: string;
|
|
vorname: string | null;
|
|
'kürzel': string | null;
|
|
pw: string | null;
|
|
MustChangePassword: number;
|
|
role: string | null;
|
|
}
|
|
|
|
export interface BeoUser {
|
|
id: number;
|
|
'kürzel': string | null;
|
|
name: string;
|
|
vorname: string | null;
|
|
role: string | null;
|
|
hasPw: boolean;
|
|
}
|
|
|
|
export async function getBeoByKuerzel(kuerzel: string): Promise<Beo | null> {
|
|
const r = await call<{ beo: Beo | null }>('LB_AUTH_KUERZEL', { kuerzel });
|
|
return r.beo;
|
|
}
|
|
|
|
export async function getBeoByName(name: string): Promise<Beo | null> {
|
|
const r = await call<{ beo: Beo | null }>('LB_AUTH_NAME', { name });
|
|
return r.beo;
|
|
}
|
|
|
|
export async function updateBeoPassword(id: number, pwHash: string): Promise<void> {
|
|
await call('LB_UPDATE_PW', { id, pw: pwHash });
|
|
}
|
|
|
|
export async function resetBeoPassword(id: number): Promise<void> {
|
|
await call('LB_RESET_PW', { id });
|
|
}
|
|
|
|
export async function listUsers(): Promise<BeoUser[]> {
|
|
return call<BeoUser[]>('LB_LIST_USERS');
|
|
}
|
|
|
|
// ---- Logbuch ----
|
|
|
|
export interface ListLogbuchParams {
|
|
kuppel?: string;
|
|
limit?: number;
|
|
offset?: number;
|
|
month?: string;
|
|
search?: string;
|
|
order?: string;
|
|
}
|
|
|
|
export async function listLogbuch(
|
|
params: ListLogbuchParams
|
|
): Promise<{ entries: LogbuchEintrag[]; total: number }> {
|
|
return call('LB_LIST_LOGBUCH', params);
|
|
}
|
|
|
|
export interface CreateLogbuchData {
|
|
Kuppel: string;
|
|
ArtFuehrung: string;
|
|
SonderName?: string | null;
|
|
Beginn: string;
|
|
Ende: string;
|
|
Besucher?: number;
|
|
beoIds?: number[];
|
|
objekte?: SelectedObjekt[];
|
|
Bemerkungen?: string | null;
|
|
Wetter?: Partial<Wetter> | null;
|
|
created_by: number;
|
|
}
|
|
|
|
export async function createLogbuch(data: CreateLogbuchData): Promise<{ id: number }> {
|
|
return call('LB_CREATE_LOGBUCH', data);
|
|
}
|
|
|
|
export async function updateLogbuch(
|
|
id: number,
|
|
userId: number,
|
|
userRole: string,
|
|
data: Omit<CreateLogbuchData, 'created_by'>
|
|
): Promise<void> {
|
|
await call('LB_UPDATE_LOGBUCH', { id, user_id: userId, user_role: userRole, ...data });
|
|
}
|
|
|
|
export async function deleteLogbuch(
|
|
id: number,
|
|
userId: number,
|
|
userRole: string
|
|
): Promise<void> {
|
|
await call('LB_DELETE_LOGBUCH', { id, user_id: userId, user_role: userRole });
|
|
}
|
|
|
|
// ---- BEOs & Objekte ----
|
|
|
|
export async function getBeos(): Promise<BeoOption[]> {
|
|
return call('LB_GET_BEOS');
|
|
}
|
|
|
|
export async function getObjekte(kategorie: 'stern' | 'sonne' = 'stern'): Promise<ObjektOption[]> {
|
|
return call('LB_GET_OBJEKTE', { kategorie });
|
|
}
|
|
|
|
export async function createObjekt(name: string, kategorie: string = 'stern'): Promise<ObjektOption> {
|
|
return call('LB_CREATE_OBJEKT', { name, kategorie });
|
|
}
|
|
|
|
export async function updateObjekt(id: number, name: string, kategorie?: string): Promise<ObjektOption> {
|
|
return call('LB_UPDATE_OBJEKT', { id, name, ...(kategorie ? { kategorie } : {}) });
|
|
}
|
|
|
|
export async function deleteObjekt(id: number): Promise<void> {
|
|
await call('LB_DELETE_OBJEKT', { id });
|
|
}
|
|
|
|
export async function listObjekteAdmin(): Promise<{ ID: number; Name: string; LastUsed: string | null; Kategorie: string }[]> {
|
|
return call('LB_LIST_OBJEKTE_ADMIN');
|
|
}
|
|
|
|
// ---- Auswertungen ----
|
|
|
|
export interface FahrkostenRow {
|
|
ID: number;
|
|
Kuerzel: string;
|
|
Name: string;
|
|
Anzahl: number;
|
|
}
|
|
|
|
export async function getFahrkosten(ab: string): Promise<FahrkostenRow[]> {
|
|
return call('LB_FAHRKOSTEN', { ab });
|
|
}
|
|
|
|
export interface StatistikResult {
|
|
monthly: {
|
|
monat: number;
|
|
tageFuehrungen: number; tageBeob: number; tageTD: number;
|
|
tageSonst: number; tageBEOS: number; tagesToT: number; tageGesamt: number;
|
|
besucherRF: number; besucherSF: number; besucherSonF: number;
|
|
besucherPrF: number; besucherToT: number; besucherGesamt: number;
|
|
}[];
|
|
cumulative: number;
|
|
tage: number;
|
|
year: number;
|
|
}
|
|
|
|
export async function getStatistik(year: number): Promise<StatistikResult> {
|
|
return call('LB_STATISTIK', { year });
|
|
}
|
|
|
|
// ---- Backup ----
|
|
|
|
export interface BackupTable {
|
|
name: string;
|
|
createSql: string;
|
|
rows: Record<string, string | number | null>[];
|
|
}
|
|
|
|
export async function getBackupData(): Promise<{ tables: BackupTable[] }> {
|
|
return call('LB_BACKUP_DATA');
|
|
}
|