gendesign/tradein-mvp/frontend/src/lib/useMe.ts
bot-backend 703e411a17
All checks were successful
CI / changes (pull_request) Successful in 6s
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
feat(tradein/auth): expire praktika trial access + trial-ended screen (contact Artem)
praktika pilot→expired role in roles.yaml (paths:[], deny:/**); RouteGuard
short-circuits on role=expired with a dedicated trial-ended screen (not the
generic path-deny path). NoAccessScreen gains variant="trial" with title
«Пробный доступ закончился» and a Telegram link to @ArtemKopylov87. Backend
Role Literal and frontend Role type extended to include "expired". kopylov
(pilot) unaffected.
2026-06-27 13:30:28 +03:00

52 lines
1.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
/**
* MIRROR of main frontend `frontend/src/lib/useMe.ts` — keep in sync manually.
*
* Tradein-mvp — отдельный Next.js bundle с basePath=/trade-in. `apiFetch`
* автоматически префиксит `API_BASE_URL` (= `/trade-in` в проде, "" в dev),
* поэтому путь `/api/v1/me` в проде превращается в `/trade-in/api/v1/me` →
* Caddy `uri strip_prefix /trade-in` → tradein-backend `/api/v1/me`.
* Tradein-backend имеет mirror endpoint `/me` (см. `tradein-mvp/backend/app/api/v1/me.py`).
*/
import { useQuery } from "@tanstack/react-query";
import { apiFetchWithStatus, HTTPError } from "@/lib/api";
export type Role = "admin" | "pilot" | "expired";
export interface UserScope {
username: string;
role: Role;
allowed_paths: string[];
deny_paths: string[];
// #657 brand-by-account: slug бренда, привязанный к аккаунту (praktika→"praktika").
// null/undefined = generic UI. useBrand применяет его автоматически на login.
brand?: string | null;
}
export const ME_QUERY_KEY = ["auth", "me"] as const;
async function fetchMe(): Promise<UserScope> {
const { body } = await apiFetchWithStatus<UserScope>("/api/v1/me");
return body;
}
export function useMe() {
return useQuery<UserScope, Error>({
queryKey: ME_QUERY_KEY,
queryFn: fetchMe,
staleTime: Infinity,
gcTime: Infinity,
refetchOnWindowFocus: false,
refetchOnReconnect: false,
refetchOnMount: false,
retry: (failureCount, error) => {
if (error instanceof HTTPError && (error.status === 401 || error.status === 403)) {
return false;
}
return failureCount < 2;
},
});
}