deploying

This commit is contained in:
2026-06-13 18:12:53 +03:00
parent 0d98a060e7
commit 4a3db42971
171 changed files with 13003 additions and 810 deletions
+25
View File
@@ -0,0 +1,25 @@
import {apiRequest, clearRequestSecurity} from "#/api/client";
import type {AuthUser, LoginRequest, RegisterRequest} from "#/types/auth";
export function getCurrentUser(signal?: AbortSignal) {
return apiRequest<AuthUser>("/auth/me", {signal});
}
export function login(request: LoginRequest) {
return apiRequest<AuthUser>("/auth/login", {
method: "POST",
body: request,
});
}
export function register(request: RegisterRequest) {
return apiRequest<AuthUser>("/auth/register", {
method: "POST",
body: request,
});
}
export async function logout() {
await apiRequest<void>("/auth/logout", {method: "POST"});
clearRequestSecurity();
}
+51 -3
View File
@@ -3,6 +3,9 @@ import type {ApiErrorResponse} from "#/types/api";
const API_BASE_URL =
import.meta.env.VITE_API_BASE_URL ?? "http://localhost:8080/api";
let csrfToken: string | null = null;
let csrfHeaderName = "X-XSRF-TOKEN";
export class ApiError extends Error {
status: number;
code: string;
@@ -23,14 +26,46 @@ type RequestOptions = {
signal?: AbortSignal;
};
type CsrfResponse = {
headerName: string;
parameterName: string;
token: string;
};
async function loadCsrfToken() {
const response = await fetch(`${API_BASE_URL}/auth/csrf`, {
credentials: "include",
});
if (!response.ok) {
throw new Error("Could not initialize request security");
}
const data = (await response.json()) as CsrfResponse;
csrfToken = data.token;
csrfHeaderName = data.headerName;
}
function isMutating(method: string) {
return method !== "GET";
}
export async function apiRequest<T>(
path: string,
options: RequestOptions = {},
): Promise<T> {
const method = options.method ?? "GET";
if (isMutating(method) && !csrfToken) {
await loadCsrfToken();
}
const response = await fetch(`${API_BASE_URL}${path}`, {
method: options.method ?? "GET",
method,
credentials: "include",
headers: {
"Content-Type": "application/json",
...(isMutating(method) && csrfToken ? {[csrfHeaderName]: csrfToken} : {}),
},
body: options.body ? JSON.stringify(options.body) : undefined,
signal: options.signal,
@@ -58,5 +93,18 @@ export async function apiRequest<T>(
return undefined as T;
}
return response.json() as Promise<T>;
}
const text = await response.text();
if (!text) {
return undefined as T;
}
return JSON.parse(text) as T;
}
export function clearRequestSecurity() {
csrfToken = null;
}
export async function initializeRequestSecurity() {
await loadCsrfToken();
}
+23 -2
View File
@@ -1,6 +1,13 @@
import {apiRequest} from "#/api/client";
import type {PageResponse} from "#/types/api";
import type {CancelOrderResponse, Order, OrderFilters, OrderSummary,} from "#/types/order";
import type {
CancelOrderResponse,
CreateOrderRequest,
Order,
OrderFilters,
OrderStatus,
OrderSummary,
} from "#/types/order";
export function getOrders(
filters: OrderFilters,
@@ -34,8 +41,22 @@ export function getOrder(id: string, signal?: AbortSignal) {
return apiRequest<Order>(`/orders/${id}`, {signal});
}
export function createOrder(request: CreateOrderRequest) {
return apiRequest<Order>("/orders", {
method: "POST",
body: request,
});
}
export function cancelOrder(id: string) {
return apiRequest<CancelOrderResponse>(`/orders/${id}`, {
method: "DELETE",
});
}
}
export function updateOrderStatus(id: string, status: OrderStatus) {
return apiRequest<Order>(`/orders/${id}/status`, {
method: "PATCH",
body: {status},
});
}
+28
View File
@@ -0,0 +1,28 @@
import {apiRequest} from "#/api/client";
import type {Product, ProductRequest} from "#/types/product";
export function getProducts(signal?: AbortSignal) {
return apiRequest<Product[]>("/products", {signal});
}
export function getProduct(id: string, signal?: AbortSignal) {
return apiRequest<Product>(`/products/${id}`, {signal});
}
export function createProduct(request: ProductRequest) {
return apiRequest<Product>("/products", {
method: "POST",
body: request,
});
}
export function updateProduct(id: string, request: ProductRequest) {
return apiRequest<Product>(`/products/${id}`, {
method: "PUT",
body: request,
});
}
export function deactivateProduct(id: string) {
return apiRequest<Product>(`/products/${id}`, {method: "DELETE"});
}
+32
View File
@@ -0,0 +1,32 @@
import {apiRequest} from "#/api/client";
import type {CreateRideRequest, Ride, RideStatus} from "#/types/ride";
export function getRides(signal?: AbortSignal) {
return apiRequest<Ride[]>("/rides", {signal});
}
export function requestRide(request: CreateRideRequest) {
return apiRequest<Ride>("/rides", {
method: "POST",
body: request,
});
}
export function acceptRide(id: string) {
return apiRequest<Ride>(`/rides/${id}/accept`, {method: "POST"});
}
export function completeRide(id: string) {
return apiRequest<Ride>(`/rides/${id}/complete`, {method: "POST"});
}
export function cancelRide(id: string) {
return apiRequest<Ride>(`/rides/${id}`, {method: "DELETE"});
}
export function updateRideStatus(id: string, status: RideStatus) {
return apiRequest<Ride>(`/rides/${id}/status`, {
method: "PATCH",
body: {status},
});
}
+32
View File
@@ -0,0 +1,32 @@
import {apiRequest} from "#/api/client";
import type {AdminUserRequest, UserSummary} from "#/types/user";
export function getUsers(signal?: AbortSignal) {
return apiRequest<UserSummary[]>("/users", {signal});
}
export function getCustomers(signal?: AbortSignal) {
return apiRequest<UserSummary[]>("/users/customers", {signal});
}
export function getDrivers(signal?: AbortSignal) {
return apiRequest<UserSummary[]>("/users/drivers", {signal});
}
export function createUser(request: AdminUserRequest) {
return apiRequest<UserSummary>("/users", {
method: "POST",
body: request,
});
}
export function updateUser(id: string, request: AdminUserRequest) {
return apiRequest<UserSummary>(`/users/${id}`, {
method: "PUT",
body: request,
});
}
export function disableUser(id: string) {
return apiRequest<UserSummary>(`/users/${id}`, {method: "DELETE"});
}