Профиль: блок истории игр с переключателями режима и подробности
В «Аккаунте» появился блок «История игр» с двумя тумблерами — «Только лучшая партия» и «Подробные карточки»; выбор уходит в профиль, поэтому переживает перезаход и другое устройство. Новый компонент MatchHistory: подробный режим переиспользует список партий группы (MatchListView со всеми участниками), компактный рисует строку с результатом самого игрока — место, фракция, дата и длительность. Публичный профиль показывает ту же историю в режиме владельца и без контролов: страница намеренно read-only. schema.d.ts пересобран с живого бэкенда (npm run gen:api). #1 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -137,6 +137,23 @@ export function useUpdateFavoriteFaction() {
|
||||
});
|
||||
}
|
||||
|
||||
// Витрина истории партий: режим (all/best) и подробность (compact/full).
|
||||
// Шлём только изменившееся поле — роутер обновляет лишь пришедшие.
|
||||
export function useUpdateHistoryPrefs() {
|
||||
const qc = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: async (prefs: {
|
||||
history_mode?: string;
|
||||
history_detail?: string;
|
||||
}): Promise<Me> => unwrap(await api.PATCH("/api/users/me/profile", { body: prefs })),
|
||||
onSuccess: (me) => {
|
||||
qc.setQueryData(qk.me, me);
|
||||
// Список истории приходит вместе с режимом — перезапрашиваем его целиком.
|
||||
qc.invalidateQueries({ queryKey: qk.userMatches(me.id) });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Аватар. Картинку уменьшаем на клиенте (≤512px) и грузим multipart'ом отдельным
|
||||
// fetch (openapi-fetch неудобен для файлов); CSRF-токен из cookie ставим вручную.
|
||||
function readCsrfToken(): string | null {
|
||||
|
||||
@@ -15,6 +15,21 @@ function useDebounced<T>(value: T, ms = 100): T {
|
||||
return debounced;
|
||||
}
|
||||
|
||||
/** История партий игрока. Режим и подробность приходят вместе со списком:
|
||||
* это витрина ВЛАДЕЛЬЦА профиля, её видят и гости. */
|
||||
export function useUserMatches(userId: number | null) {
|
||||
return useQuery({
|
||||
queryKey: userId ? qk.userMatches(userId) : ["userMatches", "none"],
|
||||
enabled: userId != null,
|
||||
queryFn: async () =>
|
||||
unwrap(
|
||||
await api.GET("/api/users/{user_id}/matches", {
|
||||
params: { path: { user_id: userId as number } },
|
||||
}),
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
/** Подсказки по нику среди всех активных игроков (GET /api/users/search). */
|
||||
export function useUserSearch(q: string, limit = 3) {
|
||||
const dq = useDebounced(q.trim());
|
||||
|
||||
Reference in New Issue
Block a user