From 1d5eafbbd0f8988a980517ddb305bf7f9f9917a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Faleiros?= Date: Fri, 4 Sep 2026 14:16:02 -0300 Subject: [PATCH] feat: simplify instructor video uploads --- pages/ManageCourses.tsx | 79 +++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 47 deletions(-) diff --git a/pages/ManageCourses.tsx b/pages/ManageCourses.tsx index 99b6b7a..0a2eba6 100644 --- a/pages/ManageCourses.tsx +++ b/pages/ManageCourses.tsx @@ -23,8 +23,12 @@ import { Lock, Unlock, Globe, - Download - ,Copy, ChevronUp, ChevronDown, ChevronLeft, ChevronRight + Download, + Copy, + ChevronUp, + ChevronDown, + ChevronLeft, + ChevronRight, } from 'lucide-react'; import { Course, Comment, Attachment, Lesson, AttachmentType, LessonMedia } from '../types'; import { useToast } from '../context/ToastContext'; @@ -57,8 +61,6 @@ const CourseModal: React.FC<{ // New Lesson State const [newLessonTitle, setNewLessonTitle] = useState(''); const [newLessonDuration, setNewLessonDuration] = useState(''); - const [newLessonVideoUrl, setNewLessonVideoUrl] = useState(''); - const [newLessonProvider, setNewLessonProvider] = useState('external'); const [newLessonMedia, setNewLessonMedia] = useState(null); const [newLessonIsFree, setNewLessonIsFree] = useState(false); const [bunnyConfigured, setBunnyConfigured] = useState(null); @@ -136,12 +138,12 @@ const CourseModal: React.FC<{ return; } if (!bunnyConfigured) { - alert('A integração com Bunny Stream ainda não foi configurada pelo administrador.'); + alert('O envio de vídeos ainda não está disponível. Tente novamente mais tarde ou entre em contato com o administrador.'); return; } setBunnyUploadState('uploading'); - setBunnyUploadMessage(`Enviando ${file.name} para Bunny Stream...`); + setBunnyUploadMessage(`Enviando ${file.name}...`); try { const created = await instructorApi.createBunnyVideo(newLessonTitle.trim()); const uploaded = await instructorApi.uploadBunnyVideo(created.data.id, file); @@ -154,10 +156,10 @@ const CourseModal: React.FC<{ setBunnyUploadState('uploaded'); setBunnyUploadMessage(uploaded.data.status === 'ready' ? 'Vídeo pronto para ser adicionado à aula.' - : 'Upload concluído. Bunny Stream está processando o vídeo; você já pode salvar a aula.'); + : 'Upload concluído. O vídeo está sendo processado; você já pode salvar a aula.'); } catch (error) { setBunnyUploadState('error'); - setBunnyUploadMessage(error instanceof Error ? error.message : 'Não foi possível enviar o vídeo para Bunny Stream.'); + setBunnyUploadMessage('Não foi possível enviar o vídeo. Tente novamente.'); } }; @@ -238,8 +240,8 @@ const CourseModal: React.FC<{ alert("Digite um título para a aula."); return; } - if (!newLessonMedia && !newLessonVideoUrl.trim()) { - alert('Envie um vídeo para Bunny Stream ou informe uma URL de vídeo hospedado.'); + if (!newLessonMedia) { + alert('Envie o vídeo da aula antes de adicioná-la.'); return; } @@ -247,9 +249,9 @@ const CourseModal: React.FC<{ id: `lesson-${Date.now()}`, title: newLessonTitle, duration: newLessonDuration || '15m', - videoUrl: newLessonMedia?.playbackUrl || newLessonVideoUrl, - mediaProvider: newLessonMedia?.provider || newLessonProvider || 'external', - media: newLessonMedia ? [newLessonMedia] : undefined, + videoUrl: newLessonMedia.playbackUrl || '', + mediaProvider: newLessonMedia.provider, + media: [newLessonMedia], isFree: newLessonIsFree, description: '' }; @@ -258,8 +260,6 @@ const CourseModal: React.FC<{ setNewLessonTitle(''); setNewLessonDuration(''); - setNewLessonVideoUrl(''); - setNewLessonProvider('external'); setNewLessonMedia(null); setNewLessonIsFree(false); setBunnyUploadState('idle'); @@ -431,7 +431,7 @@ const CourseModal: React.FC<{ disabled={!coverConfigured || isCoverUploading} onChange={handleCoverUpload} /> -

{coverUploadMessage || (coverConfigured ? 'JPG, PNG ou WebP. Tamanho máximo: 10 MB.' : 'O upload de capas será habilitado após configurar Bunny Storage no servidor.')}

+

{coverUploadMessage || (coverConfigured ? 'JPG, PNG ou WebP. Tamanho máximo: 10 MB.' : 'O envio de imagens estará disponível assim que o armazenamento de mídia for configurado.')}

@@ -441,7 +441,7 @@ const CourseModal: React.FC<{ type="text" value={title} onChange={(e) => setTitle(e.target.value)} - placeholder="Ex: Masterclass: Escala de Tráfego Pago" + placeholder="Ex.: Estratégias de tráfego pago para e-commerce" className="w-full bg-black/50 text-white text-base font-bold border border-white/10 rounded-xl px-4 py-3 focus:outline-none focus:border-orange-500/50" required /> @@ -477,7 +477,7 @@ const CourseModal: React.FC<{ value={description} onChange={(e) => setDescription(e.target.value)} rows={3} - placeholder="O que os alunos vão aprender e dominar neste curso?" + placeholder="Descreva os tópicos, as competências e os resultados esperados para os alunos." className="w-full bg-black/50 text-white border border-white/10 rounded-xl px-4 py-2.5 text-xs focus:outline-none focus:border-orange-500/50 resize-none leading-relaxed" />
@@ -504,7 +504,7 @@ const CourseModal: React.FC<{ type="text" value={newAttName} onChange={(e) => setNewAttName(e.target.value)} - placeholder="Nome do arquivo (ex: Planilha_ROAS.xlsx)" + placeholder="Ex.: Planilha de acompanhamento de campanhas" className="col-span-2 bg-white/5 border border-white/10 rounded-lg px-2.5 py-1.5 text-xs text-white focus:outline-none focus:border-orange-500/50" /> setNewAttDesc(e.target.value)} - placeholder="Breve descrição do material..." + placeholder="Explique como este material apoia o aprendizado." className="flex-1 bg-white/5 border border-white/10 rounded-lg px-2.5 py-1.5 text-xs text-white focus:outline-none" /> )} -
- setNewLessonProvider(event.target.value)} - placeholder="Provider externo" - className="w-40 bg-white/5 border border-white/10 rounded-xl px-3 py-2 text-xs text-white focus:outline-none" - /> - setNewLessonVideoUrl(event.target.value)} - placeholder="Ou cole uma URL externa de vídeo" - className="flex-1 bg-white/5 border border-white/10 rounded-xl px-3 py-2 text-xs text-white focus:outline-none" - /> - +