This commit is contained in:
Tomas Dvorak
2025-10-29 21:20:16 +01:00
parent 823fabee02
commit 16e4533202
61 changed files with 2308 additions and 942 deletions
+28 -8
View File
@@ -178,7 +178,7 @@ const AdminVideosPage: React.FC = () => {
setSelectedIds((prev) => ({ ...prev, [id]: !prev[id] }));
};
const importSelected = () => {
const importSelected = async () => {
const selected = ytVideos.filter((v) => selectedIds[v.video_id]);
if (selected.length === 0) {
toast({ status: 'info', title: 'Nic k importu', description: 'Vyberte alespoň jedno video.' });
@@ -203,10 +203,30 @@ const AdminVideosPage: React.FC = () => {
}
return merged;
});
// If currently in auto mode, switch to manual so the preview reflects newly added items
if (videosSource !== 'manual') {
setVideosSource('manual');
try {
await updateAdminSettings({ videos_source: 'manual' });
toast({ status: 'info', title: 'Přepnuto na ruční správu', description: 'Nově přidaná videa se budou používat. Nezapomeňte uložit seznam.', duration: 3500 });
} catch {
// ignore
}
}
toast({ status: 'success', title: 'Videa přidána', description: `${selected.length} videí bylo přidáno do seznamu.` });
};
const addItem = () => setItems((prev) => [...prev, { ...emptyItem }]);
const addItem = async () => {
setItems((prev) => [...prev, { ...emptyItem }]);
if (videosSource !== 'manual') {
setVideosSource('manual');
try {
await updateAdminSettings({ videos_source: 'manual' });
} catch {
// ignore
}
}
};
const removeItem = (idx: number) => setItems((prev) => prev.filter((_, i) => i !== idx));
const updateField = (idx: number, key: keyof AdminVideoItem, val: string) => {
setItems((prev) => prev.map((it, i) => i === idx ? { ...it, [key]: val } : it));
@@ -341,13 +361,13 @@ const AdminVideosPage: React.FC = () => {
Použijte Scraper API. Zadejte handle (např. <code>@FotbalKunovice</code>) nebo URL kanálu a načtěte videa z karty Videa.
Služba: <Link href="https://youtube.tdvorak.dev/" isExternal color="blue.500">https://youtube.tdvorak.dev/</Link>
</Text>
<HStack align="start" spacing={3}>
<HStack align="start" spacing={3} flexWrap="wrap">
<FormControl maxW={{ base: '100%', md: '400px' }}>
<FormLabel>Kanál (handle nebo URL)</FormLabel>
<Input id="admin-videos-channel-input" placeholder="@FCBizoniUH nebo https://www.youtube.com/@FCBizoniUH/videos" value={channelInput} onChange={(e) => setChannelInput(e.target.value)} />
</FormControl>
<Button onClick={fetchChannelVideos} isLoading={ytLoading} variant="outline">Načíst videa</Button>
<Button colorScheme="green" onClick={importSelected} isDisabled={ytVideos.length === 0}>Přidat vybraná</Button>
<Button onClick={fetchChannelVideos} isLoading={ytLoading} variant="outline" flexShrink={0} minW="max-content">Načíst videa</Button>
<Button colorScheme="green" onClick={importSelected} isDisabled={ytVideos.length === 0} flexShrink={0} minW="max-content">Přidat vybraná</Button>
</HStack>
{ytError && (
<Alert status="error" mt={3} borderRadius="md">
@@ -387,9 +407,9 @@ const AdminVideosPage: React.FC = () => {
<HStack justify="space-between" align="center" mb={2} flexWrap="wrap">
<Heading size="sm">Náhled: všechna videa (aktivní zdroj)</Heading>
{videosSource === 'auto' && (
<HStack spacing={2}>
<Input size="sm" placeholder="Filtrovat podle názvu" value={filter} onChange={(e) => setFilter(e.target.value)} />
<Button size="sm" onClick={refreshAuto} isLoading={autoLoading} variant="outline">Aktualizovat cache</Button>
<HStack spacing={2} flexWrap="wrap">
<Input size="sm" placeholder="Filtrovat podle názvu" value={filter} onChange={(e) => setFilter(e.target.value)} width={{ base: '100%', md: '260px' }} />
<Button size="sm" onClick={refreshAuto} isLoading={autoLoading} variant="outline" flexShrink={0} minW="max-content">Aktualizovat cache</Button>
</HStack>
)}
</HStack>