feat: Initialize frontend and backend structure with essential configurations
Some checks failed
Backend CI / lint-and-test (push) Failing after 2m15s
Frontend CI / lint-and-build (push) Successful in 1m1s

- Added TypeScript build info for frontend.
- Created Vite configuration for React application.
- Implemented pre-commit hook to run checks before commits.
- Set up PostgreSQL Dockerfile with PostGIS support and initialization scripts.
- Added database creation script for PostgreSQL with necessary extensions.
- Established Python project configuration with dependencies and development tools.
- Developed pre-commit script to enforce code quality checks for backend and frontend.
- Created PowerShell script to set up Git hooks path.
This commit is contained in:
2025-10-11 15:25:32 +02:00
commit fc1e874309
74 changed files with 9477 additions and 0 deletions

View File

@@ -0,0 +1,84 @@
import type { AuthResponse, LoginPayload, RegisterPayload } from '../types/auth';
import type { Station, Track, Train } from '../types/domain';
export class ApiError extends Error {
readonly status: number;
constructor(message: string, status: number) {
super(message);
this.name = 'ApiError';
this.status = status;
}
}
export interface NetworkSnapshot {
readonly stations: Station[];
readonly tracks: Track[];
readonly trains: Train[];
}
const JSON_HEADERS = {
accept: 'application/json',
'content-type': 'application/json',
};
export async function login(credentials: LoginPayload): Promise<AuthResponse> {
const response = await fetch('/api/auth/login', {
method: 'POST',
headers: JSON_HEADERS,
body: JSON.stringify(credentials),
});
if (!response.ok) {
throw new ApiError('Invalid username or password', response.status);
}
return (await response.json()) as AuthResponse;
}
export async function register(credentials: RegisterPayload): Promise<AuthResponse> {
const response = await fetch('/api/auth/register', {
method: 'POST',
headers: JSON_HEADERS,
body: JSON.stringify(credentials),
});
if (!response.ok) {
const message =
response.status === 409
? 'Username already exists'
: 'Registration failed. Please try again.';
throw new ApiError(message, response.status);
}
return (await response.json()) as AuthResponse;
}
export async function fetchNetworkSnapshot(
token: string,
signal?: AbortSignal
): Promise<NetworkSnapshot> {
const response = await fetch('/api/network', {
method: 'GET',
headers: {
accept: 'application/json',
Authorization: `Bearer ${token}`,
},
signal,
});
if (!response.ok) {
const message =
response.status === 401
? 'Authorization required. Please sign in again.'
: `Failed to fetch network snapshot (status ${response.status})`;
throw new ApiError(message, response.status);
}
const data = (await response.json()) as NetworkSnapshot;
return {
stations: data.stations ?? [],
tracks: data.tracks ?? [],
trains: data.trains ?? [],
};
}