Lead Radar: исходный код

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
yuriandClaude Opus 5.5 committed 2026-10-25 23:11:04 +04:00
commit 9749da5ae7
201 files changed
+97685

No files matched your search

+44
View File
@@ -0,0 +1,44 @@
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { useEffect, useState } from 'react';
import { api, ApiError, type Me } from './api.ts';
export const ME_KEY = ['me'] as const;
/** Текущий пользователь; null — не вошёл. */
export function useMe() {
return useQuery({
queryKey: ME_KEY,
queryFn: async (): Promise<Me | null> => {
try {
return await api<Me>('/me');
} catch (e) {
if (e instanceof ApiError && e.status === 401) return null;
throw e;
}
},
});
}
/** Мутация, после которой перечитываются указанные запросы (по умолчанию — все). */
export function useAction<TArgs = void, TResult = unknown>(
fn: (args: TArgs) => Promise<TResult>,
invalidate?: readonly unknown[],
) {
const qc = useQueryClient();
return useMutation({
mutationFn: fn,
onSuccess: () => qc.invalidateQueries(invalidate ? { queryKey: invalidate } : undefined),
});
}
export type Theme = 'dark' | 'light';
export function useTheme(): [Theme, () => void] {
const [theme, setTheme] = useState<Theme>(() => (localStorage.getItem('lr_theme') === 'light' ? 'light' : 'dark'));
useEffect(() => {
document.documentElement.dataset.theme = theme;
localStorage.setItem('lr_theme', theme);
document.querySelector('meta[name="theme-color"]')?.setAttribute('content', theme === 'light' ? '#f6f8fb' : '#020617');
}, [theme]);
return [theme, () => setTheme((v) => (v === 'dark' ? 'light' : 'dark'))];
}