Files
k-tv/k-tv-frontend/app/(main)/dashboard/components/channel-card.tsx
Gabriel Kaszewski 477de2c49d feat: add schedule sheet and tag input components
- Implemented ScheduleSheet component to display channel schedules with a timeline view.
- Added DayRow subcomponent for rendering daily schedule slots with color coding.
- Integrated ScheduleSheet into the DashboardPage for viewing schedules of selected channels.
- Created TagInput component for managing tags with add and remove functionality.
- Updated package dependencies to include zod version 4.3.6.
2026-03-11 21:14:42 +01:00

106 lines
3.0 KiB
TypeScript

import Link from "next/link";
import { Pencil, Trash2, RefreshCw, Tv2, CalendarDays } from "lucide-react";
import { Button } from "@/components/ui/button";
import type { ChannelResponse } from "@/lib/types";
interface ChannelCardProps {
channel: ChannelResponse;
isGenerating: boolean;
onEdit: () => void;
onDelete: () => void;
onGenerateSchedule: () => void;
onViewSchedule: () => void;
}
export function ChannelCard({
channel,
isGenerating,
onEdit,
onDelete,
onGenerateSchedule,
onViewSchedule,
}: ChannelCardProps) {
const blockCount = channel.schedule_config.blocks.length;
return (
<div className="flex flex-col gap-4 rounded-xl border border-zinc-800 bg-zinc-900 p-5 transition-colors hover:border-zinc-700">
{/* Top row */}
<div className="flex items-start justify-between gap-3">
<div className="min-w-0 space-y-1">
<h2 className="truncate text-base font-semibold text-zinc-100">
{channel.name}
</h2>
{channel.description && (
<p className="line-clamp-2 text-sm text-zinc-500">
{channel.description}
</p>
)}
</div>
<div className="flex shrink-0 items-center gap-1">
<Button
variant="ghost"
size="icon-sm"
onClick={onEdit}
title="Edit channel"
>
<Pencil className="size-3.5" />
</Button>
<Button
variant="ghost"
size="icon-sm"
onClick={onDelete}
title="Delete channel"
className="text-zinc-600 hover:text-red-400"
>
<Trash2 className="size-3.5" />
</Button>
</div>
</div>
{/* Meta */}
<div className="flex flex-wrap gap-x-4 gap-y-1 text-xs text-zinc-500">
<span>
<span className="text-zinc-400">{channel.timezone}</span>
</span>
<span>
{blockCount} {blockCount === 1 ? "block" : "blocks"}
</span>
</div>
{/* Actions */}
<div className="flex gap-2">
<Button
size="sm"
onClick={onGenerateSchedule}
disabled={isGenerating}
className="flex-1"
>
<RefreshCw className={`size-3.5 ${isGenerating ? "animate-spin" : ""}`} />
{isGenerating ? "Generating…" : "Generate schedule"}
</Button>
<Button
variant="outline"
size="icon-sm"
onClick={onViewSchedule}
title="View schedule"
className="border-zinc-700 text-zinc-400 hover:text-zinc-100"
>
<CalendarDays className="size-3.5" />
</Button>
<Button
variant="outline"
size="icon-sm"
asChild
title="Watch on TV"
className="border-zinc-700 text-zinc-400 hover:text-zinc-100"
>
<Link href="/tv">
<Tv2 className="size-3.5" />
</Link>
</Button>
</div>
</div>
);
}