Changed channel categories from DB-backed Category records to a backed PHP enum

This commit is contained in:
2026-05-18 06:55:03 +03:30
parent 295a408965
commit 59e4ae60da
20 changed files with 221 additions and 130 deletions

View File

@@ -150,7 +150,7 @@ export default function ChannelShow({
<LiveState channel={channel} />
{channel.category && (
<span className="rounded-md border px-2 py-1 text-xs">
{channel.category.name}
{channel.category.label}
</span>
)}
</div>

View File

@@ -38,7 +38,7 @@ import {
update as updateChannelRoute,
} from '@/routes/creator/channel';
import { rotate as rotateStreamKeyRoute } from '@/routes/creator/stream-key';
import type { BroadcastSummary, Category } from '@/types';
import type { BroadcastSummary, ChannelCategory } from '@/types';
type CreatorChannel = {
id: number;
@@ -51,7 +51,7 @@ type CreatorChannel = {
is_live: boolean;
viewer_count: number;
stream_key_last_used_at: string | null;
category_id: number | null;
category: string | null;
live_broadcast: BroadcastSummary | null;
};
@@ -63,7 +63,7 @@ type Props = {
ingestServer: string;
tokenizedPath: string | null;
};
categories: Category[];
categories: ChannelCategory[];
recentBroadcasts: BroadcastSummary[];
};
@@ -90,14 +90,14 @@ export default function Dashboard({
display_name: '',
slug: '',
description: '',
category_id: '',
category: '',
});
const channelForm = useForm({
_method: 'PATCH',
display_name: channel?.display_name ?? '',
slug: channel?.slug ?? '',
description: channel?.description ?? '',
category_id: channel?.category_id ? String(channel.category_id) : '',
category: channel?.category ?? '',
thumbnail: null as File | null,
});
const broadcastForm = useForm({
@@ -235,13 +235,16 @@ export default function Dashboard({
placeholder={t('nyone-live')}
/>
</Field>
<Field label="Category">
<Field
label="Category"
error={createForm.errors.category}
>
<CategorySelect
categories={categories}
value={createForm.data.category_id}
value={createForm.data.category}
onChange={(value) =>
createForm.setData(
'category_id',
'category',
value,
)
}
@@ -440,13 +443,16 @@ export default function Dashboard({
}
/>
</Field>
<Field label="Category">
<Field
label="Category"
error={channelForm.errors.category}
>
<CategorySelect
categories={categories}
value={channelForm.data.category_id}
value={channelForm.data.category}
onChange={(value) =>
channelForm.setData(
'category_id',
'category',
value,
)
}
@@ -763,7 +769,7 @@ function CategorySelect({
value,
onChange,
}: {
categories: Category[];
categories: ChannelCategory[];
value: string;
onChange: (value: string) => void;
}) {
@@ -777,8 +783,8 @@ function CategorySelect({
>
<option value="">{t('No category')}</option>
{categories.map((category) => (
<option key={category.id} value={category.id}>
{category.name}
<option key={category.value} value={category.value}>
{category.label}
</option>
))}
</select>

View File

@@ -19,12 +19,12 @@ import { cn } from '@/lib/utils';
import { dashboard, home, login, register } from '@/routes';
import { show as showChannel } from '@/routes/channels';
import { index as supportIndex } from '@/routes/support';
import type { Category, ChannelCard } from '@/types';
import type { ChannelCard, ChannelCategory } from '@/types';
type Props = {
canRegister: boolean;
liveChannels: ChannelCard[];
categories: Category[];
categories: ChannelCategory[];
};
export default function Welcome({
@@ -43,7 +43,7 @@ export default function Welcome({
return liveChannels.filter((channel) => {
const matchesCategory =
category === 'all' || channel.category?.slug === category;
category === 'all' || channel.category?.value === category;
const matchesQuery =
normalizedQuery === '' ||
channel.display_name.toLowerCase().includes(normalizedQuery) ||
@@ -175,7 +175,7 @@ export default function Welcome({
</span>
<span className="min-w-0 break-words">
{featuredChannel.category
?.name ??
?.label ??
t('Uncategorized')}
</span>
<span className="inline-flex items-center gap-1">
@@ -292,8 +292,11 @@ export default function Welcome({
{t('All categories')}
</option>
{categories.map((item) => (
<option key={item.id} value={item.slug}>
{item.name}
<option
key={item.value}
value={item.value}
>
{item.label}
</option>
))}
</select>
@@ -356,7 +359,7 @@ function StreamCard({ channel }: { channel: ChannelCard }) {
</div>
<div className="flex items-center justify-between gap-3 text-sm text-muted-foreground">
<span className="truncate">
{channel.category?.name ?? t('Uncategorized')}
{channel.category?.label ?? t('Uncategorized')}
</span>
<span className="shrink-0">
{t(':count viewers', {

View File

@@ -1,7 +1,6 @@
export type Category = {
id: number;
name: string;
slug: string;
export type ChannelCategory = {
value: string;
label: string;
};
export type ChannelCard = {
@@ -15,7 +14,7 @@ export type ChannelCard = {
banner_url: string | null;
viewer_count: number;
followers_count: number;
category: Category | null;
category: ChannelCategory | null;
broadcast: {
id: number;
title: string;
@@ -38,7 +37,7 @@ export type ChannelDetail = {
is_live: boolean;
viewer_count: number;
followers_count: number;
category: Category | null;
category: ChannelCategory | null;
owner: {
id: number;
name: string;