Files
ForbiddenStarsApp/frontend/src/api/queryKeys.ts
T
NotBigGhostandClaude Opus 5 d31e998f87 Объявления: окно у игрока и редактор в админке
Окно — вариант E из макетов: заголовок в плашке-шапке, текст, точки очереди
и «Понятно», крестика нет. Очередь идёт от старого к новому; закрытое сразу
уходит из кэша, следующее открывается без ожидания сети. У повторно
показанного объявления под заголовком — красная пометка «обновлено».
AppShell показывает окно на любой странице и только когда пароль задан:
обязательное окно пароля всегда первое. Новые и изменённые объявления
приходят SSE-событием announcements, отложенное начало показа — перезапросом
раз в 5 минут.

Админка — вкладка «Объявления» с редактором R1: contenteditable и панель
(жирный, курсив, золотой и красный акцент, эмодзи, снятие оформления),
вставка и перетаскивание только простым текстом, счётчик символов, период
показа по МСК, переключатели «показывать новым игрокам» и «показать заново».
Предпросмотр — тем же окном, что у игрока. Список со статусом, счётчиком
«закрыли N из M» и действиями: изменить, снять с показа, дублировать,
удалить. Выделение текста в форме — полупрозрачный оранжевый вместо синего.

schema.d.ts пересобран из OpenAPI. #84

Перенесено в main без рейтинга из ab1fc3f; schema.d.ts сверен с OpenAPI этой ветки.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 21:59:32 +03:00

45 lines
2.0 KiB
TypeScript

export const qk = {
me: ["me"] as const,
adminMe: ["adminMe"] as const,
home: ["home"] as const,
leaderboard: ["leaderboard"] as const,
expansions: ["expansions"] as const,
factions: ["factions"] as const,
myStats: ["myStats"] as const,
publicProfile: (id: number) => ["publicProfile", id] as const,
userMatches: (id: number) => ["userMatches", id] as const,
userSearch: (q: string, limit: number) => ["userSearch", q, limit] as const,
groups: ["groups"] as const,
group: (id: number) => ["group", id] as const,
groupFactions: (id: number) => ["group", id, "factions"] as const,
groupMembers: (id: number) => ["group", id, "members"] as const,
groupMatches: (id: number) => ["group", id, "matches"] as const,
groupStats: (id: number) => ["group", id, "stats"] as const,
match: (id: number) => ["match", id] as const,
authConfig: ["authConfig"] as const,
invitations: ["invitations"] as const,
notifications: ["notifications"] as const,
announcements: ["announcements"] as const,
devUsers: ["devUsers"] as const,
adminUsers: ["adminUsers"] as const,
adminGroups: ["adminGroups"] as const,
adminMatches: ["adminMatches"] as const,
adminLogs: ["adminLogs"] as const,
adminAchievements: ["adminAchievements"] as const,
adminAnnouncements: ["adminAnnouncements"] as const,
};
/**
* Ключи, которые протухают от любой партии: конкретных участников мы не знаем
* (событие приходит на всю группу), поэтому инвалидируем по префиксу. Один
* список на SSE-обработчик и на завершение партии — иначе переименование ключа
* в этом файле тихо разойдётся с местами, где он написан строкой.
*/
export const matchAffectedKeys = [
qk.home,
qk.leaderboard,
qk.myStats,
["userMatches"],
["publicProfile"],
] as const;