Add media and channel management routes: introduce new routes for admin channels, media, and shows in the routing structure. Update navigation in the admin layout to include links for these new sections. Enhance type definitions for media assets and shows in the API types. Integrate HLS.js for improved streaming support.

This commit is contained in:
Leonid Pershin
2026-07-24 16:18:54 +03:00
parent 1bbfd15907
commit a2685fb602
24 changed files with 2050 additions and 42 deletions
+22 -1
View File
@@ -14,7 +14,28 @@ function AdminLayout() {
return (
<div className="flex flex-col gap-6">
<h1 className="crt-glow text-2xl font-bold">{t('nav.admin')}</h1>
<nav className="flex gap-4 border-b border-border text-sm">
<nav className="flex flex-wrap gap-4 border-b border-border text-sm">
<Link
to="/admin/media"
className={cn('pb-2 uppercase tracking-wide text-muted-foreground hover:text-foreground')}
activeProps={{ className: 'border-b-2 border-primary text-primary' }}
>
{t('admin.media.title')}
</Link>
<Link
to="/admin/shows"
className={cn('pb-2 uppercase tracking-wide text-muted-foreground hover:text-foreground')}
activeProps={{ className: 'border-b-2 border-primary text-primary' }}
>
{t('admin.shows.title')}
</Link>
<Link
to="/admin/channels"
className={cn('pb-2 uppercase tracking-wide text-muted-foreground hover:text-foreground')}
activeProps={{ className: 'border-b-2 border-primary text-primary' }}
>
{t('admin.channels.title')}
</Link>
<Link
to="/admin/roles"
className={cn('pb-2 uppercase tracking-wide text-muted-foreground hover:text-foreground')}
@@ -0,0 +1,9 @@
import { createFileRoute } from '@tanstack/react-router'
import { ChannelDetail } from '@/features/admin/channels/ChannelDetail'
export const Route = createFileRoute('/admin/channels/$channelId')({ component: ChannelDetailRoute })
function ChannelDetailRoute() {
const { channelId } = Route.useParams()
return <ChannelDetail channelId={channelId} />
}
+4
View File
@@ -0,0 +1,4 @@
import { createFileRoute } from '@tanstack/react-router'
import { ChannelsPanel } from '@/features/admin/channels/ChannelsPanel'
export const Route = createFileRoute('/admin/channels')({ component: ChannelsPanel })
+1 -1
View File
@@ -1,5 +1,5 @@
import { createFileRoute, Navigate } from '@tanstack/react-router'
export const Route = createFileRoute('/admin/')({
component: () => <Navigate to="/admin/users" />,
component: () => <Navigate to="/admin/media" />,
})
+4
View File
@@ -0,0 +1,4 @@
import { createFileRoute } from '@tanstack/react-router'
import { MediaPanel } from '@/features/admin/media/MediaPanel'
export const Route = createFileRoute('/admin/media')({ component: MediaPanel })
@@ -0,0 +1,9 @@
import { createFileRoute } from '@tanstack/react-router'
import { ShowDetail } from '@/features/admin/shows/ShowDetail'
export const Route = createFileRoute('/admin/shows/$showId')({ component: ShowDetailRoute })
function ShowDetailRoute() {
const { showId } = Route.useParams()
return <ShowDetail showId={showId} />
}
+4
View File
@@ -0,0 +1,4 @@
import { createFileRoute } from '@tanstack/react-router'
import { ShowsPanel } from '@/features/admin/shows/ShowsPanel'
export const Route = createFileRoute('/admin/shows')({ component: ShowsPanel })
+4 -29
View File
@@ -1,38 +1,13 @@
import { createFileRoute } from '@tanstack/react-router'
import { useTranslation } from 'react-i18next'
import { Tv } from 'lucide-react'
import { useRequireAuth } from '@/features/auth/guards'
import { Badge } from '@/shared/ui/badge'
import { Card, CardContent, CardHeader, CardTitle } from '@/shared/ui/card'
import { AirPage } from '@/features/streaming/AirPage'
export const Route = createFileRoute('/dashboard')({ component: DashboardPage })
function DashboardPage() {
const { t } = useTranslation()
const { user, isReady } = useRequireAuth()
const { isReady } = useRequireAuth()
if (!isReady || !user) return null
if (!isReady) return null
return (
<div className="flex flex-col gap-6">
<div className="flex flex-wrap items-center justify-between gap-2">
<h1 className="crt-glow text-2xl font-bold">{t('dashboard.welcome', { userName: user.userName })}</h1>
<Badge>
{t('dashboard.role')}: {user.role}
</Badge>
</div>
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Tv className="h-5 w-5" />
{t('nav.dashboard')}
</CardTitle>
</CardHeader>
<CardContent>
<p className="text-muted-foreground">{t('dashboard.placeholder')}</p>
</CardContent>
</Card>
</div>
)
return <AirPage />
}