v0.1 - макет интерфейса, аутентификация через логин, аккаунт админа, создание партии в 2 этапа, базовые настройки профиля и группы, переключение между группами, статистика

This commit is contained in:
2026-06-16 17:41:06 +03:00
parent 6ab74f01aa
commit 56b5d09a4d
123 changed files with 13572 additions and 21 deletions
+101
View File
@@ -0,0 +1,101 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { api, unwrap } from "../api/client";
import { qk } from "../api/queryKeys";
import type { AuthConfig, Me } from "../domain/types";
export function useMe() {
return useQuery({
queryKey: qk.me,
queryFn: async (): Promise<Me | null> => {
const r = await api.GET("/api/users/me");
if (r.response.status === 401) return null;
return unwrap(r);
},
});
}
export function useAuthConfig() {
return useQuery({
queryKey: qk.authConfig,
queryFn: async (): Promise<AuthConfig> => unwrap(await api.GET("/api/auth/config")),
});
}
export function useDevUsers(enabled: boolean) {
return useQuery({
queryKey: qk.devUsers,
enabled,
queryFn: async () => unwrap(await api.GET("/api/auth/dev/users")),
});
}
// DEV-вход по нику (только в деве; в прод-бэкенде эндпоинта нет).
export function useStubLogin() {
const qc = useQueryClient();
return useMutation({
mutationFn: async (nickname: string) =>
unwrap(await api.POST("/api/auth/dev/login", { body: { nickname } })),
onSuccess: (me) => {
qc.setQueryData(qk.me, me);
qc.invalidateQueries();
},
});
}
// Вход через Telegram Login Widget: payload виджета проверяется на сервере по HMAC.
export function useTelegramLogin() {
const qc = useQueryClient();
return useMutation({
mutationFn: async (payload: Record<string, unknown>) =>
unwrap(await api.POST("/api/auth/telegram", { body: payload as never })),
onSuccess: (me) => {
qc.setQueryData(qk.me, me);
qc.invalidateQueries();
},
});
}
export function useCreateDevUser() {
const qc = useQueryClient();
return useMutation({
mutationFn: async (nickname: string) =>
unwrap(await api.POST("/api/auth/dev/users", { body: { nickname } })),
onSuccess: () => qc.invalidateQueries({ queryKey: qk.devUsers }),
});
}
export function useLogout() {
const qc = useQueryClient();
return useMutation({
mutationFn: async () => unwrap(await api.POST("/api/auth/logout")),
onSuccess: () => {
qc.setQueryData(qk.me, null);
qc.clear();
},
});
}
export function useUpdateNickname() {
const qc = useQueryClient();
return useMutation({
mutationFn: async (nickname: string) =>
unwrap(await api.PATCH("/api/users/me", { body: { nickname } })),
onSuccess: () => {
qc.invalidateQueries({ queryKey: qk.me });
qc.invalidateQueries({ queryKey: qk.home });
},
});
}
export function useSetActiveGroup() {
const qc = useQueryClient();
return useMutation({
mutationFn: async (group_id: number | null) =>
unwrap(await api.PUT("/api/users/me/active-group", { body: { group_id } })),
onSuccess: (me) => {
qc.setQueryData(qk.me, me);
qc.invalidateQueries({ queryKey: qk.home });
},
});
}