gendesign/tradein-mvp/frontend/src/lib/useMe.ts
lekss361 95bada3855 feat(tradein): brand-by-account + result IA redesign (distinct asking/sale prices)
- Resolve brand from account: /me returns brand (praktika/kopylov->praktika);
  useBrand uses ?brand= param OR me.brand (param wins) -> praktika auto-branded
  on login (no manual ?brand= needed).
- Result IA (Brusnika-style): single «Ожидаемая цена сделки» headline (lower,
  -X% vs asking, 5-12% note); two DISTINCT reference figures (asking объявления
  vs ДКП Росреестр) + price bars; sources row; 3 always-on explainer cards
  (asking!=real, ремонт по состоянию, скрытые расходы <=15%).
- Defer commercial buyback value (Brusnika p.4): OfferCard stub + TODO, no
  invented numbers (pending Praktika commercial terms).
- tsc clean, ruff clean, 35 backend tests (7 new /me-brand).

Refs #657
2026-05-30 09:38:09 +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";
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;
},
});
}