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:
@@ -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>
|
||||
|
||||
@@ -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 })
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user