From 70953ab57a381b9dd76f6646530db3e15d0440c2 Mon Sep 17 00:00:00 2001 From: Lucas Santana Date: Fri, 20 Dec 2024 10:25:21 -0300 Subject: [PATCH] =?UTF-8?q?feat:=20adiciona=20RootLayout=20e=20atualiza=20?= =?UTF-8?q?rotas=20da=20aplica=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Cria componente RootLayout como container principal - Atualiza router para usar RootLayout como elemento raiz - Organiza rotas aninhadas com Outlet do React Router - Adiciona rota para visualização de histórias individuais --- src/components/layout/RootLayout.tsx | 10 ++ src/components/story/AudioRecorder.tsx | 2 +- src/pages/story/StoryPage.tsx | 162 ++++++++++++++++++++++--- src/routes/index.tsx | 8 +- src/types/database.ts | 2 + 5 files changed, 164 insertions(+), 20 deletions(-) create mode 100644 src/components/layout/RootLayout.tsx diff --git a/src/components/layout/RootLayout.tsx b/src/components/layout/RootLayout.tsx new file mode 100644 index 0000000..b61ad74 --- /dev/null +++ b/src/components/layout/RootLayout.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import { Outlet } from 'react-router-dom'; + +export function RootLayout(): JSX.Element { + return ( +
+ +
+ ); +} \ No newline at end of file diff --git a/src/components/story/AudioRecorder.tsx b/src/components/story/AudioRecorder.tsx index d3d706c..5a33819 100644 --- a/src/components/story/AudioRecorder.tsx +++ b/src/components/story/AudioRecorder.tsx @@ -1,6 +1,6 @@ import React, { useState, useRef } from 'react'; import { Mic, Square, Loader, Play, Upload } from 'lucide-react'; -import { supabase } from '@/lib/supabase'; +import { supabase } from '../../lib/supabase'; interface AudioRecorderProps { storyId: string; diff --git a/src/pages/story/StoryPage.tsx b/src/pages/story/StoryPage.tsx index d9aaa05..2f2ef9a 100644 --- a/src/pages/story/StoryPage.tsx +++ b/src/pages/story/StoryPage.tsx @@ -1,40 +1,166 @@ -import { AudioRecorder } from '../../components/story/AudioRecorder'; +import React, { useEffect, useState } from 'react'; +import { useParams } from 'react-router-dom'; import { supabase } from '../../lib/supabase'; +import { Story } from '../../types/database'; +import { AudioRecorder } from '../../components/story/AudioRecorder'; +import { Loader2 } from 'lucide-react'; -export function StoryPage() { - // ... outros códigos ... +interface StoryPageProps { + demo?: boolean; +} + +export function StoryPage({ demo = false }: StoryPageProps): JSX.Element { + const { storyId } = useParams(); + const [story, setStory] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + const [currentPage, setCurrentPage] = useState(0); + + useEffect(() => { + const fetchStory = async () => { + try { + if (!storyId && !demo) { + throw new Error('ID da história não fornecido'); + } + + if (demo) { + setStory({ + id: 'demo', + student_id: 'demo', + class_id: 'demo', + school_id: 'demo', + title: 'Uma Aventura Educacional', + theme: 'Demo', + content: { + pages: [ + { + text: 'Bem-vindo à demonstração do Histórias Mágicas! Aqui você pode ver como funciona nossa plataforma...', + image: 'https://images.unsplash.com/photo-1472162072942-cd5147eb3902?auto=format&fit=crop&q=80&w=800&h=600', + }, + { + text: 'Com histórias interativas e educativas, seus alunos aprenderão de forma divertida e envolvente...', + image: 'https://images.unsplash.com/photo-1519681393784-d120267933ba?auto=format&fit=crop&q=80&w=800&h=600', + } + ], + currentPage: 0 + }, + status: 'published', + created_at: new Date().toISOString(), + updated_at: new Date().toISOString() + }); + setLoading(false); + return; + } + + const { data, error } = await supabase + .from('stories') + .select('*') + .eq('id', storyId) + .single(); + + if (error) throw error; + setStory(data); + } catch (err) { + console.error('Erro ao buscar história:', err); + setError(err instanceof Error ? err.message : 'Erro ao carregar história'); + } finally { + setLoading(false); + } + }; + + fetchStory(); + }, [storyId, demo]); const handleAudioUploaded = async (audioUrl: string) => { try { - // Salvar referência do áudio no banco de dados + if (demo) return; // Não salva gravações no modo demo + + const { data: { session } } = await supabase.auth.getSession(); + if (!session?.user?.id) throw new Error('Usuário não autenticado'); + const { error } = await supabase .from('story_recordings') .insert({ story_id: storyId, - student_id: studentId, + student_id: session.user.id, audio_url: audioUrl, - status: 'pending_analysis' // será analisado pela IA posteriormente + status: 'pending_analysis' }); if (error) throw error; - - // Aqui você pode adicionar a lógica para enviar o áudio para análise da IA - // Por exemplo, chamar uma função que envia o áudio para um endpoint de IA - } catch (err) { console.error('Erro ao salvar gravação:', err); + setError('Erro ao salvar gravação de áudio'); } }; + if (loading) { + return ( +
+ +
+ ); + } + + if (error || !story) { + return ( +
+
+

Ops!

+

{error || 'História não encontrada'}

+
+
+ ); + } + return ( -
- {/* ... outros elementos da página ... */} - - +
+
+

+ {story.title} +

+ +
+ {story.content.pages[currentPage].image && ( + {`Ilustração + )} + +
+

+ {story.content.pages[currentPage].text} +

+ + + +
+ + +
+
+
+
); } \ No newline at end of file diff --git a/src/routes/index.tsx b/src/routes/index.tsx index d72fed7..3958248 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -1,4 +1,5 @@ import { createBrowserRouter } from 'react-router-dom'; +import { RootLayout } from '../components/layout/RootLayout'; import { HomePage } from '../components/home/HomePage'; import { LoginForm } from '../components/auth/LoginForm'; import { SchoolRegistrationForm } from '../components/auth/SchoolRegistrationForm'; @@ -14,6 +15,7 @@ import { InviteTeacherPage } from '../pages/dashboard/teachers/InviteTeacherPage import { StudentsPage } from '../pages/dashboard/students/StudentsPage'; import { AddStudentPage } from '../pages/dashboard/students/AddStudentPage'; import { DemoPage } from '../pages/demo/DemoPage'; +import { StoryPage } from '../pages/story/StoryPage'; import React from 'react'; export const router = createBrowserRouter([ @@ -27,7 +29,7 @@ export const router = createBrowserRouter([ }, { path: 'demo', - element: , + element: }, { path: '/login', @@ -117,6 +119,10 @@ export const router = createBrowserRouter([ path: '/auth/callback', element: }, + { + path: '/story/:storyId', + element: + }, ], }, ]); \ No newline at end of file diff --git a/src/types/database.ts b/src/types/database.ts index 06ab889..e304dc0 100644 --- a/src/types/database.ts +++ b/src/types/database.ts @@ -94,6 +94,8 @@ export interface StoryPage { export interface Story { id: string; student_id: string; + class_id: string; + school_id: string; title: string; theme: string; content: {