Add settings endpoints and registration status check: implement new API endpoints for settings management, including registration status retrieval, and update the registration command handler to enforce registration rules based on site settings.

This commit is contained in:
Leonid Pershin
2026-07-25 07:48:17 +03:00
parent 1bdc3323ab
commit c53848477f
33 changed files with 1289 additions and 17 deletions
+7
View File
@@ -57,6 +57,13 @@ function AdminLayout() {
>
{t('admin.maintenance.title')}
</Link>
<Link
to="/admin/settings"
className={cn('pb-2 uppercase tracking-wide text-muted-foreground hover:text-foreground')}
activeProps={{ className: 'border-b-2 border-primary text-primary' }}
>
{t('admin.settings.title')}
</Link>
</nav>
<Outlet />
</div>
+4
View File
@@ -0,0 +1,4 @@
import { createFileRoute } from '@tanstack/react-router'
import { SettingsPanel } from '@/features/admin/settings/SettingsPanel'
export const Route = createFileRoute('/admin/settings')({ component: SettingsPanel })
+15 -6
View File
@@ -1,6 +1,8 @@
import { createFileRoute, Link, useNavigate } from '@tanstack/react-router'
import { useQuery } from '@tanstack/react-query'
import { useTranslation } from 'react-i18next'
import { LoginForm } from '@/features/auth/LoginForm'
import { fetchRegistrationStatus } from '@/features/auth/api'
import { useRequireGuest } from '@/features/auth/guards'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/shared/ui/card'
@@ -11,6 +13,11 @@ function LoginPage() {
const { t } = useTranslation()
const navigate = useNavigate()
const { data: registration } = useQuery({
queryKey: ['auth', 'registration'],
queryFn: fetchRegistrationStatus,
})
return (
<div className="mx-auto max-w-sm py-8">
<Card>
@@ -20,12 +27,14 @@ function LoginPage() {
</CardHeader>
<CardContent>
<LoginForm onSuccess={() => void navigate({ to: '/dashboard' })} />
<p className="mt-4 text-center text-sm text-muted-foreground">
{t('auth.noAccount')}{' '}
<Link to="/register" className="text-primary hover:underline">
{t('nav.register')}
</Link>
</p>
{registration?.enabled && (
<p className="mt-4 text-center text-sm text-muted-foreground">
{t('auth.noAccount')}{' '}
<Link to="/register" className="text-primary hover:underline">
{t('nav.register')}
</Link>
</p>
)}
</CardContent>
</Card>
</div>
+30 -8
View File
@@ -1,6 +1,8 @@
import { createFileRoute, Link, useNavigate } from '@tanstack/react-router'
import { useQuery } from '@tanstack/react-query'
import { useTranslation } from 'react-i18next'
import { RegisterForm } from '@/features/auth/RegisterForm'
import { fetchRegistrationStatus } from '@/features/auth/api'
import { useRequireGuest } from '@/features/auth/guards'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/shared/ui/card'
@@ -11,21 +13,41 @@ function RegisterPage() {
const { t } = useTranslation()
const navigate = useNavigate()
const { data: registration, isLoading } = useQuery({
queryKey: ['auth', 'registration'],
queryFn: fetchRegistrationStatus,
})
const disabled = !isLoading && registration?.enabled === false
return (
<div className="mx-auto max-w-sm py-8">
<Card>
<CardHeader>
<CardTitle>{t('auth.registerTitle')}</CardTitle>
<CardDescription>{t('auth.registerSubtitle')}</CardDescription>
<CardDescription>
{disabled ? t('auth.registrationClosed') : t('auth.registerSubtitle')}
</CardDescription>
</CardHeader>
<CardContent>
<RegisterForm onSuccess={() => void navigate({ to: '/dashboard' })} />
<p className="mt-4 text-center text-sm text-muted-foreground">
{t('auth.haveAccount')}{' '}
<Link to="/login" className="text-primary hover:underline">
{t('nav.login')}
</Link>
</p>
{disabled ? (
<p className="text-center text-sm text-muted-foreground">
{t('auth.registrationClosedHint')}{' '}
<Link to="/login" className="text-primary hover:underline">
{t('nav.login')}
</Link>
</p>
) : (
<>
<RegisterForm onSuccess={() => void navigate({ to: '/dashboard' })} />
<p className="mt-4 text-center text-sm text-muted-foreground">
{t('auth.haveAccount')}{' '}
<Link to="/login" className="text-primary hover:underline">
{t('nav.login')}
</Link>
</p>
</>
)}
</CardContent>
</Card>
</div>