import { useState } from 'react'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router'; import { createGuild, fetchGuildTemplates, guildTemplatesQueryKey } from '@/api/guilds'; import { instanceQueryKey } from '@/api/instance'; import { myGuildsQueryKey } from '@/api/users'; import { ErrorNotice } from '@/components/ui/ErrorNotice'; import { Field } from '@/components/ui/Field'; import { Modal } from '@/components/ui/Modal'; import { Button } from '@/components/ui/primitives'; import { useInstance } from '@/lib/hooks'; import { useSessionStore } from '@/stores/session'; import { useUiStore } from '@/stores/ui'; /** * Единственное модальное окно создания сервера (`POST /guilds {name}`). * Открывается из рейки и с пустого экрана «У вас пока нет серверов», * поэтому смонтировано в `AppLayout`, а состояние — в `ui`-сторе. */ export function CreateGuildModal() { const { t } = useTranslation(); const navigate = useNavigate(); const queryClient = useQueryClient(); const instance = useInstance(); const open = useUiStore((state) => state.guildCreateOpen); const close = useUiStore((state) => state.closeGuildCreate); const guilds = useSessionStore((state) => state.guilds); const upsertGuild = useSessionStore((state) => state.upsertGuild); const [name, setName] = useState(''); const [templateId, setTemplateId] = useState('empty'); // Шаблоны структуры: список небольшой и статический, кэшируется на сессию. const templates = useQuery({ queryKey: guildTemplatesQueryKey, queryFn: ({ signal }) => fetchGuildTemplates(signal), enabled: open, staleTime: 300_000, retry: 0, }); const create = useMutation({ mutationFn: (guildName: string) => createGuild(guildName, templateId), onSuccess: (guild) => { close(); setName(''); upsertGuild(guild); void queryClient.invalidateQueries({ queryKey: myGuildsQueryKey }); void queryClient.invalidateQueries({ queryKey: instanceQueryKey }); void navigate(`/app/${guild.id}`); }, }); const limitReached = instance.data !== undefined && guilds.length >= instance.data.max_guilds_per_user; return ( } >
{ event.preventDefault(); if (name.trim() !== '') { create.mutate(name.trim()); } }} > setName(event.target.value)} maxLength={64} hint={t('guilds.create.hint')} /> {/* Шаблон задаёт структуру комнат и ролей (AGENT.md 7.3). */}
{t('guilds.create.template')} {(templates.data ?? []).map((template) => ( ))} {templates.isError ? ( void templates.refetch()} /> ) : null}
{instance.data === undefined ? null : (

{t('guilds.create.limit', { count: instance.data.max_guilds_per_user })}

)} {limitReached && !create.isError ? (

{t('guilds.create.limitReached')}

) : null} {create.isError ? : null}
); }