feat(admin): add announcement placeholder

This commit is contained in:
saltbo
2026-04-27 21:15:41 -04:00
parent bf7c3389ea
commit ec9cc0b5e0
5 changed files with 75 additions and 0 deletions
+2
View File
@@ -6,6 +6,7 @@ import {
KeyRound,
LayoutDashboard,
Mail,
Megaphone,
Settings,
ShieldCheck,
Users,
@@ -32,6 +33,7 @@ const adminNavItems = [
{ titleKey: 'admin.nav.auth', url: '/admin/settings/oauth', icon: KeyRound },
{ titleKey: 'admin.nav.email', url: '/admin/settings/email', icon: Mail },
{ titleKey: 'admin.nav.settings', url: '/admin/settings', icon: Settings },
{ titleKey: 'admin.nav.announcement', url: '/admin/announcement', icon: Megaphone },
{ titleKey: 'admin.nav.audit', url: '/admin/audit', icon: ShieldCheck },
{ titleKey: 'admin.nav.licensing', url: '/admin/licensing', icon: BadgeCheck },
]
+5
View File
@@ -109,6 +109,7 @@
"admin.nav.management": "Management",
"admin.nav.overview": "Overview",
"admin.nav.storages": "Storages",
"admin.nav.announcement": "Announcement",
"admin.nav.audit": "Audit Logs",
"admin.nav.users": "Users",
"admin.nav.settings": "Settings",
@@ -164,6 +165,10 @@
"admin.audit.proTooltip": "Audit Logs are available with ZPan Pro.",
"admin.audit.placeholderTitle": "Audit Logs Coming Soon",
"admin.audit.placeholderDescription": "This page is reserved for the future audit log experience.",
"admin.announcement.title": "Site Announcement",
"admin.announcement.description": "Manage the announcement area shown to users across the site.",
"admin.announcement.placeholderTitle": "Site Announcement Coming Soon",
"admin.announcement.placeholderDescription": "This page is reserved for the future announcement management experience.",
"admin.users.resendInvite": "Resend Invite",
"admin.users.revokeInvite": "Revoke Invite",
"admin.users.inviteStatus.pending": "Pending",
+5
View File
@@ -109,6 +109,7 @@
"admin.nav.management": "管理",
"admin.nav.overview": "概览",
"admin.nav.storages": "存储",
"admin.nav.announcement": "站点公告",
"admin.nav.audit": "审计日志",
"admin.nav.users": "用户",
"admin.nav.settings": "设置",
@@ -164,6 +165,10 @@
"admin.audit.proTooltip": "审计日志仅在 ZPan Pro 中可用。",
"admin.audit.placeholderTitle": "审计日志即将推出",
"admin.audit.placeholderDescription": "此页面已预留给未来的审计日志体验。",
"admin.announcement.title": "站点公告",
"admin.announcement.description": "管理面向站点用户展示的公告区域。",
"admin.announcement.placeholderTitle": "站点公告即将推出",
"admin.announcement.placeholderDescription": "此页面已预留给未来的公告管理体验。",
"admin.users.resendInvite": "重新发送邀请",
"admin.users.revokeInvite": "撤销邀请",
"admin.users.inviteStatus.pending": "待使用",
+22
View File
@@ -34,6 +34,7 @@ import { Route as AuthenticatedSettingsIhostRouteImport } from './routes/_authen
import { Route as AuthenticatedSettingsAppearanceRouteImport } from './routes/_authenticated/settings/appearance'
import { Route as AuthenticatedAdminLicensingRouteImport } from './routes/_authenticated/admin/licensing'
import { Route as AuthenticatedAdminAuditRouteImport } from './routes/_authenticated/admin/audit'
import { Route as AuthenticatedAdminAnnouncementRouteImport } from './routes/_authenticated/admin/announcement'
import { Route as AuthenticatedTeamsTeamIdRouteRouteImport } from './routes/_authenticated/teams/$teamId/route'
import { Route as AuthenticatedTeamsTeamIdIndexRouteImport } from './routes/_authenticated/teams/$teamId/index'
import { Route as AuthenticatedAdminUsersIndexRouteImport } from './routes/_authenticated/admin/users/index'
@@ -180,6 +181,12 @@ const AuthenticatedAdminAuditRoute = AuthenticatedAdminAuditRouteImport.update({
path: '/audit',
getParentRoute: () => AuthenticatedAdminRouteRoute,
} as any)
const AuthenticatedAdminAnnouncementRoute =
AuthenticatedAdminAnnouncementRouteImport.update({
id: '/announcement',
path: '/announcement',
getParentRoute: () => AuthenticatedAdminRouteRoute,
} as any)
const AuthenticatedTeamsTeamIdRouteRoute =
AuthenticatedTeamsTeamIdRouteRouteImport.update({
id: '/teams/$teamId',
@@ -251,6 +258,7 @@ export interface FileRoutesByFullPath {
'/s/$token': typeof STokenRoute
'/u/$username': typeof UUsernameRoute
'/teams/$teamId': typeof AuthenticatedTeamsTeamIdRouteRouteWithChildren
'/admin/announcement': typeof AuthenticatedAdminAnnouncementRoute
'/admin/audit': typeof AuthenticatedAdminAuditRoute
'/admin/licensing': typeof AuthenticatedAdminLicensingRoute
'/settings/appearance': typeof AuthenticatedSettingsAppearanceRoute
@@ -284,6 +292,7 @@ export interface FileRoutesByTo {
'/s/$token': typeof STokenRoute
'/u/$username': typeof UUsernameRoute
'/': typeof AuthenticatedIndexRoute
'/admin/announcement': typeof AuthenticatedAdminAnnouncementRoute
'/admin/audit': typeof AuthenticatedAdminAuditRoute
'/admin/licensing': typeof AuthenticatedAdminLicensingRoute
'/settings/appearance': typeof AuthenticatedSettingsAppearanceRoute
@@ -322,6 +331,7 @@ export interface FileRoutesById {
'/u/$username': typeof UUsernameRoute
'/_authenticated/': typeof AuthenticatedIndexRoute
'/_authenticated/teams/$teamId': typeof AuthenticatedTeamsTeamIdRouteRouteWithChildren
'/_authenticated/admin/announcement': typeof AuthenticatedAdminAnnouncementRoute
'/_authenticated/admin/audit': typeof AuthenticatedAdminAuditRoute
'/_authenticated/admin/licensing': typeof AuthenticatedAdminLicensingRoute
'/_authenticated/settings/appearance': typeof AuthenticatedSettingsAppearanceRoute
@@ -360,6 +370,7 @@ export interface FileRouteTypes {
| '/s/$token'
| '/u/$username'
| '/teams/$teamId'
| '/admin/announcement'
| '/admin/audit'
| '/admin/licensing'
| '/settings/appearance'
@@ -393,6 +404,7 @@ export interface FileRouteTypes {
| '/s/$token'
| '/u/$username'
| '/'
| '/admin/announcement'
| '/admin/audit'
| '/admin/licensing'
| '/settings/appearance'
@@ -430,6 +442,7 @@ export interface FileRouteTypes {
| '/u/$username'
| '/_authenticated/'
| '/_authenticated/teams/$teamId'
| '/_authenticated/admin/announcement'
| '/_authenticated/admin/audit'
| '/_authenticated/admin/licensing'
| '/_authenticated/settings/appearance'
@@ -642,6 +655,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof AuthenticatedAdminAuditRouteImport
parentRoute: typeof AuthenticatedAdminRouteRoute
}
'/_authenticated/admin/announcement': {
id: '/_authenticated/admin/announcement'
path: '/announcement'
fullPath: '/admin/announcement'
preLoaderRoute: typeof AuthenticatedAdminAnnouncementRouteImport
parentRoute: typeof AuthenticatedAdminRouteRoute
}
'/_authenticated/teams/$teamId': {
id: '/_authenticated/teams/$teamId'
path: '/teams/$teamId'
@@ -716,6 +736,7 @@ declare module '@tanstack/react-router' {
}
interface AuthenticatedAdminRouteRouteChildren {
AuthenticatedAdminAnnouncementRoute: typeof AuthenticatedAdminAnnouncementRoute
AuthenticatedAdminAuditRoute: typeof AuthenticatedAdminAuditRoute
AuthenticatedAdminLicensingRoute: typeof AuthenticatedAdminLicensingRoute
AuthenticatedAdminIndexRoute: typeof AuthenticatedAdminIndexRoute
@@ -728,6 +749,7 @@ interface AuthenticatedAdminRouteRouteChildren {
const AuthenticatedAdminRouteRouteChildren: AuthenticatedAdminRouteRouteChildren =
{
AuthenticatedAdminAnnouncementRoute: AuthenticatedAdminAnnouncementRoute,
AuthenticatedAdminAuditRoute: AuthenticatedAdminAuditRoute,
AuthenticatedAdminLicensingRoute: AuthenticatedAdminLicensingRoute,
AuthenticatedAdminIndexRoute: AuthenticatedAdminIndexRoute,
@@ -0,0 +1,41 @@
import { createFileRoute } from '@tanstack/react-router'
import { Megaphone } from 'lucide-react'
import { useTranslation } from 'react-i18next'
import { ProBadge } from '@/components/ProBadge'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
export const Route = createFileRoute('/_authenticated/admin/announcement')({
component: AnnouncementPage,
})
function AnnouncementPage() {
const { t } = useTranslation()
return (
<div className="space-y-6">
<div className="flex items-center gap-2">
<h2 className="text-xl font-semibold">{t('admin.announcement.title')}</h2>
<ProBadge />
</div>
<p className="text-sm text-muted-foreground">{t('admin.announcement.description')}</p>
<Card className="border-dashed">
<CardHeader>
<div className="flex items-center gap-3">
<div className="rounded-2xl border border-border/60 bg-primary/10 p-2 text-primary">
<Megaphone className="h-5 w-5" />
</div>
<div>
<CardTitle>{t('admin.announcement.placeholderTitle')}</CardTitle>
<CardDescription>{t('admin.announcement.placeholderDescription')}</CardDescription>
</div>
</div>
</CardHeader>
<CardContent className="text-sm text-muted-foreground">
Site Announcement UI placeholder only. No publishing workflow is wired yet.
</CardContent>
</Card>
</div>
)
}