Spaces:
Running
Running
Alberto Pérez
es de clases de guitarraDescripción de la Aplicación: Plataforma de Gestión para Profesores de Clases Particulares Esta es una aplicación web moderna y flexible diseñada para profesores de guitarra, baile o cualquier otra disciplina, que les permite gestionar de forma eficiente sus sesiones semanales con diferentes alumnos. La plataforma ofrece un panel de control intuitivo para el profesor, donde puede visualizar métricas clave como horas impartidas, alumnos activos e ingresos por semana y mes. Permite la validación y edición de perfiles de alumnos, la asignación a clases y la gestión de horarios. Los alumnos, por su parte, pueden acceder a sus próximas clases, horarios, estado de pagos y actualizar sus datos personales. La aplicación está diseñada para ser adaptable a diversos modelos de enseñanza, desde profesores que se desplazan a domicilio hasta escuelas con clases fijas. Stack Tecnológico: Frontend: Desarrollado con React utilizando JavaScript y el entorno de desarrollo Vite para una experiencia de usuario dinámica y rápida. Framework: Se utiliza Next.js para aprovechar sus capacidades de renderizado y, crucialmente, para la creación de API Routes que actúan como la capa de backend. Base de Datos: PostgreSQL será la base de datos relacional robusta y escalable para almacenar toda la información de usuarios, clases, reservas y pagos. Estilo y Componentes UI: La interfaz de usuario será moderna y responsiva, haciendo uso de Material UI para componentes pre-diseñados de alta calidad y una estética profesional, complementada con Tailwind CSS para un control granular del diseño. Estructura del Proyecto: Frontend (React Components): Componentes interactivos para los dashboards del profesor y del alumno, formularios de gestión, calendario, tablas de métricas, etc. Backend (Next.js API Routes): Funciones serverless que se encargarán de la lógica de negocio, la autenticación de usuarios (profesores y alumnos), y la interacción segura con la base de datos PostgreSQL para operaciones CRUD (Crear, Leer, Actualizar, Borrar) de alumnos, clases, reservas y pagos. Base de Datos (PostgreSQL): Tablas para users (con roles), students (perfiles de alumnos), classes (definición de sesiones), bookings (reservas de alumnos a clases) y payments (registro de cuotas). Esta arquitectura asegura una aplicación eficiente, escalable y fácil de mantener, ideal para un entorno de gestión de clases dinámico. - Follow Up Deployment
3f351bd verified | <html lang="es"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Gestor de Clases de Guitarra</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> | |
| <script> | |
| tailwind.config = { | |
| darkMode: 'class', | |
| theme: { | |
| extend: { | |
| colors: { | |
| primary: { | |
| light: '#4f46e5', | |
| dark: '#6366f1', | |
| }, | |
| secondary: { | |
| light: '#f43f5e', | |
| dark: '#fb7185', | |
| }, | |
| } | |
| } | |
| } | |
| } | |
| </script> | |
| <style> | |
| .completed { | |
| position: relative; | |
| } | |
| .completed::after { | |
| content: ''; | |
| position: absolute; | |
| left: 0; | |
| top: 50%; | |
| width: 100%; | |
| height: 2px; | |
| background: currentColor; | |
| transform: rotate(-5deg); | |
| } | |
| .dark .completed::after { | |
| background: #fff; | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-50 dark:bg-gray-900 transition-colors duration-200"> | |
| <div id="app" class="min-h-screen flex flex-col"> | |
| <!-- Header --> | |
| <header class="bg-white dark:bg-gray-800 shadow-sm"> | |
| <div class="container mx-auto px-4 py-4 flex justify-between items-center"> | |
| <div class="flex items-center space-x-2"> | |
| <span class="material-icons text-primary-light dark:text-primary-dark text-3xl">school</span> | |
| <h1 class="text-xl font-bold text-gray-800 dark:text-white">Clases de Guitarra</h1> | |
| </div> | |
| <div class="flex items-center space-x-4"> | |
| <button id="theme-toggle" class="p-2 rounded-full hover:bg-gray-200 dark:hover:bg-gray-700"> | |
| <span id="theme-icon" class="material-icons text-gray-600 dark:text-gray-300">dark_mode</span> | |
| </button> | |
| <div class="relative"> | |
| <button id="user-menu" class="flex items-center space-x-2 focus:outline-none"> | |
| <div class="w-8 h-8 rounded-full bg-primary-light dark:bg-primary-dark flex items-center justify-center text-white"> | |
| <span class="material-icons text-sm">person</span> | |
| </div> | |
| <span class="text-gray-700 dark:text-gray-300 font-medium">Profesor</span> | |
| </button> | |
| <div id="user-dropdown" class="hidden absolute right-0 mt-2 w-48 bg-white dark:bg-gray-800 rounded-md shadow-lg py-1 z-10"> | |
| <a href="#" class="block px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700">Perfil</a> | |
| <a href="#" class="block px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700">Configuración</a> | |
| <a href="#" class="block px-4 py-2 text-sm text-red-600 hover:bg-gray-100 dark:hover:bg-gray-700">Cerrar sesión</a> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </header> | |
| <!-- Main Content --> | |
| <main class="flex-grow container mx-auto px-4 py-8"> | |
| <div class="grid grid-cols-1 lg:grid-cols-4 gap-6"> | |
| <!-- Sidebar --> | |
| <aside class="lg:col-span-1"> | |
| <div class="bg-white dark:bg-gray-800 rounded-lg shadow-sm p-4 sticky top-8"> | |
| <h2 class="text-lg font-semibold text-gray-800 dark:text-white mb-4">Menú</h2> | |
| <nav> | |
| <ul class="space-y-2"> | |
| <li> | |
| <a href="#" class="flex items-center space-x-3 p-2 rounded-lg bg-primary-light dark:bg-primary-dark text-white"> | |
| <span class="material-icons">dashboard</span> | |
| <span>Dashboard</span> | |
| </a> | |
| </li> | |
| <li> | |
| <a href="#" class="flex items-center space-x-3 p-2 rounded-lg text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"> | |
| <span class="material-icons">group</span> | |
| <span>Estudiantes</span> | |
| </a> | |
| </li> | |
| <li> | |
| <a href="#" class="flex items-center space-x-3 p-2 rounded-lg text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"> | |
| <span class="material-icons">class</span> | |
| <span>Clases</span> | |
| </a> | |
| </li> | |
| <li> | |
| <a href="#" class="flex items-center space-x-3 p-2 rounded-lg text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"> | |
| <span class="material-icons">assignment</span> | |
| <span>Tareas</span> | |
| </a> | |
| </li> | |
| <li> | |
| <a href="#" class="flex items-center space-x-3 p-2 rounded-lg text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"> | |
| <span class="material-icons">settings</span> | |
| <span>Configuración</span> | |
| </a> | |
| </li> | |
| </ul> | |
| </nav> | |
| </div> | |
| </aside> | |
| <!-- Content Area --> | |
| <div class="lg:col-span-3"> | |
| <!-- Welcome Card --> | |
| <div class="bg-gradient-to-r from-primary-light to-primary-dark dark:from-primary-dark dark:to-indigo-600 rounded-lg shadow-sm p-6 mb-6"> | |
| <div class="flex flex-col md:flex-row md:items-center md:justify-between"> | |
| <div> | |
| <h2 class="text-2xl font-bold text-white">Bienvenido, Profesor de Guitarra</h2> | |
| <p class="text-indigo-100 mt-2">Gestiona tus clases, alumnos y horarios de enseñanza.</p> | |
| </div> | |
| <button class="mt-4 md:mt-0 bg-white text-primary-light dark:text-primary-dark px-4 py-2 rounded-lg font-medium hover:bg-opacity-90 transition"> | |
| Crear nueva clase | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Stats Cards --> | |
| <div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6"> | |
| <div class="bg-white dark:bg-gray-800 rounded-lg shadow-sm p-4"> | |
| <div class="flex items-center justify-between"> | |
| <div> | |
| <p class="text-sm text-gray-500 dark:text-gray-400">Clases de guitarra</p> | |
| <h3 class="text-2xl font-bold text-gray-800 dark:text-white mt-1">24</h3> | |
| </div> | |
| <div class="p-3 rounded-full bg-indigo-100 dark:bg-indigo-900 text-primary-light dark:text-primary-dark"> | |
| <span class="material-icons">class</span> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="bg-white dark:bg-gray-800 rounded-lg shadow-sm p-4"> | |
| <div class="flex items-center justify-between"> | |
| <div> | |
| <p class="text-sm text-gray-500 dark:text-gray-400">Estudiantes</p> | |
| <h3 class="text-2xl font-bold text-gray-800 dark:text-white mt-1">156</h3> | |
| </div> | |
| <div class="p-3 rounded-full bg-green-100 dark:bg-green-900 text-green-600 dark:text-green-400"> | |
| <span class="material-icons">group</span> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="bg-white dark:bg-gray-800 rounded-lg shadow-sm p-4"> | |
| <div class="flex items-center justify-between"> | |
| <div> | |
| <p class="text-sm text-gray-500 dark:text-gray-400">Tareas pendientes</p> | |
| <h3 class="text-2xl font-bold text-gray-800 dark:text-white mt-1">12</h3> | |
| </div> | |
| <div class="p-3 rounded-full bg-amber-100 dark:bg-amber-900 text-amber-600 dark:text-amber-400"> | |
| <span class="material-icons">assignment</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Classes Table --> | |
| <div class="bg-white dark:bg-gray-800 rounded-lg shadow-sm overflow-hidden"> | |
| <div class="p-4 border-b border-gray-200 dark:border-gray-700 flex justify-between items-center"> | |
| <h2 class="text-lg font-semibold text-gray-800 dark:text-white">Clases Recientes</h2> | |
| <button class="text-sm text-primary-light dark:text-primary-dark hover:underline">Ver todas</button> | |
| </div> | |
| <div class="overflow-x-auto"> | |
| <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700"> | |
| <thead class="bg-gray-50 dark:bg-gray-700"> | |
| <tr> | |
| <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">Nombre</th> | |
| <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">Fecha</th> | |
| <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">Estudiantes</th> | |
| <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">Estado</th> | |
| <th scope="col" class="px-6 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">Acciones</th> | |
| </tr> | |
| </thead> | |
| <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700"> | |
| <tr> | |
| <td class="px-6 py-4 whitespace-nowrap"> | |
| <div class="flex items-center"> | |
| <div class="flex-shrink-0 h-10 w-10 rounded-full bg-indigo-100 dark:bg-indigo-900 flex items-center justify-center text-primary-light dark:text-primary-dark"> | |
| <span class="material-icons">music_note</span> | |
| </div> | |
| <div class="ml-4"> | |
| <div class="text-sm font-medium text-gray-900 dark:text-white">Guitarra Acústica</div> | |
| <div class="text-sm text-gray-500 dark:text-gray-400">Nivel Básico</div> | |
| </div> | |
| </div> | |
| </td> | |
| <td class="px-6 py-4 whitespace-nowrap"> | |
| <div class="text-sm text-gray-900 dark:text-white">15 Mar 2023</div> | |
| <div class="text-sm text-gray-500 dark:text-gray-400">10:00 AM</div> | |
| </td> | |
| <td class="px-6 py-4 whitespace-nowrap"> | |
| <div class="text-sm text-gray-900 dark:text-white">32</div> | |
| </td> | |
| <td class="px-6 py-4 whitespace-nowrap"> | |
| <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200">Completada</span> | |
| </td> | |
| <td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"> | |
| <button class="text-primary-light dark:text-primary-dark hover:text-indigo-900 dark:hover:text-indigo-300 mr-3">Editar</button> | |
| <button class="text-red-600 hover:text-red-900 dark:hover:text-red-400">Eliminar</button> | |
| </td> | |
| </tr> | |
| <tr> | |
| <td class="px-6 py-4 whitespace-nowrap"> | |
| <div class="flex items-center"> | |
| <div class="flex-shrink-0 h-10 w-10 rounded-full bg-purple-100 dark:bg-purple-900 flex items-center justify-center text-purple-600 dark:text-purple-400"> | |
| <span class="material-icons">music_video</span> | |
| </div> | |
| <div class="ml-4"> | |
| <div class="text-sm font-medium text-gray-900 dark:text-white">Guitarra Eléctrica</div> | |
| <div class="text-sm text-gray-500 dark:text-gray-400">Nivel Intermedio</div> | |
| </div> | |
| </div> | |
| </td> | |
| <td class="px-6 py-4 whitespace-nowrap"> | |
| <div class="text-sm text-gray-900 dark:text-white">16 Mar 2023</div> | |
| <div class="text-sm text-gray-500 dark:text-gray-400">08:00 AM</div> | |
| </td> | |
| <td class="px-6 py-4 whitespace-nowrap"> | |
| <div class="text-sm text-gray-900 dark:text-white">28</div> | |
| </td> | |
| <td class="px-6 py-4 whitespace-nowrap"> | |
| <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200">Pendiente</span> | |
| </td> | |
| <td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"> | |
| <button class="text-primary-light dark:text-primary-dark hover:text-indigo-900 dark:hover:text-indigo-300 mr-3">Editar</button> | |
| <button class="text-red-600 hover:text-red-900 dark:hover:text-red-400">Eliminar</button> | |
| </td> | |
| </tr> | |
| <tr> | |
| <td class="px-6 py-4 whitespace-nowrap"> | |
| <div class="flex items-center"> | |
| <div class="flex-shrink-0 h-10 w-10 rounded-full bg-blue-100 dark:bg-blue-900 flex items-center justify-center text-blue-600 dark:text-blue-400"> | |
| <span class="material-icons">library_music</span> | |
| </div> | |
| <div class="ml-4"> | |
| <div class="text-sm font-medium text-gray-900 dark:text-white completed">Teoría Musical</div> | |
| <div class="text-sm text-gray-500 dark:text-gray-400">Todos los niveles</div> | |
| </div> | |
| </div> | |
| </td> | |
| <td class="px-6 py-4 whitespace-nowrap"> | |
| <div class="text-sm text-gray-900 dark:text-white">14 Mar 2023</div> | |
| <div class="text-sm text-gray-500 dark:text-gray-400">11:00 AM</div> | |
| </td> | |
| <td class="px-6 py-4 whitespace-nowrap"> | |
| <div class="text-sm text-gray-900 dark:text-white">25</div> | |
| </td> | |
| <td class="px-6 py-4 whitespace-nowrap"> | |
| <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200">Cancelada</span> | |
| </td> | |
| <td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"> | |
| <button class="text-primary-light dark:text-primary-dark hover:text-indigo-900 dark:hover:text-indigo-300 mr-3">Editar</button> | |
| <button class="text-red-600 hover:text-red-900 dark:hover:text-red-400">Eliminar</button> | |
| </td> | |
| </tr> | |
| <tr> | |
| <td class="px-6 py-4 whitespace-nowrap"> | |
| <div class="flex items-center"> | |
| <div class="flex-shrink-0 h-10 w-10 rounded-full bg-green-100 dark:bg-green-900 flex items-center justify-center text-green-600 dark:text-green-400"> | |
| <span class="material-icons">graphic_eq</span> | |
| </div> | |
| <div class="ml-4"> | |
| <div class="text-sm font-medium text-gray-900 dark:text-white">Improvisación</div> | |
| <div class="text-sm text-gray-500 dark:text-gray-400">Nivel Avanzado</div> | |
| </div> | |
| </div> | |
| </td> | |
| <td class="px-6 py-4 whitespace-nowrap"> | |
| <div class="text-sm text-gray-900 dark:text-white">17 Mar 2023</div> | |
| <div class="text-sm text-gray-500 dark:text-gray-400">09:00 AM</div> | |
| </td> | |
| <td class="px-6 py-4 whitespace-nowrap"> | |
| <div class="text-sm text-gray-900 dark:text-white">30</div> | |
| </td> | |
| <td class="px-6 py-4 whitespace-nowrap"> | |
| <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200">Programada</span> | |
| </td> | |
| <td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"> | |
| <button class="text-primary-light dark:text-primary-dark hover:text-indigo-900 dark:hover:text-indigo-300 mr-3">Editar</button> | |
| <button class="text-red-600 hover:text-red-900 dark:hover:text-red-400">Eliminar</button> | |
| </td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| </div> | |
| <div class="px-4 py-3 bg-gray-50 dark:bg-gray-700 text-right sm:px-6"> | |
| <button class="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-primary-light dark:bg-primary-dark hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"> | |
| <span class="material-icons mr-2">add</span> | |
| Nueva Clase | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| <!-- Footer --> | |
| <footer class="bg-white dark:bg-gray-800 shadow-sm mt-8"> | |
| <div class="container mx-auto px-4 py-6"> | |
| <div class="flex flex-col md:flex-row justify-between items-center"> | |
| <div class="flex items-center space-x-2 mb-4 md:mb-0"> | |
| <span class="material-icons text-primary-light dark:text-primary-dark">school</span> | |
| <span class="text-gray-700 dark:text-gray-300 font-medium">Gestor de Clases de Guitarra</span> | |
| </div> | |
| <div class="text-sm text-gray-500 dark:text-gray-400"> | |
| © 2023 Todos los derechos reservados. | |
| </div> | |
| </div> | |
| </div> | |
| </footer> | |
| </div> | |
| <script> | |
| // Theme toggle functionality | |
| const themeToggle = document.getElementById('theme-toggle'); | |
| const themeIcon = document.getElementById('theme-icon'); | |
| const html = document.documentElement; | |
| // Check for saved theme preference or use preferred color scheme | |
| const savedTheme = localStorage.getItem('theme') || | |
| (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'); | |
| // Apply the saved theme | |
| if (savedTheme === 'dark') { | |
| html.classList.add('dark'); | |
| themeIcon.textContent = 'light_mode'; | |
| } else { | |
| html.classList.remove('dark'); | |
| themeIcon.textContent = 'dark_mode'; | |
| } | |
| // Toggle theme on button click | |
| themeToggle.addEventListener('click', () => { | |
| html.classList.toggle('dark'); | |
| if (html.classList.contains('dark')) { | |
| themeIcon.textContent = 'light_mode'; | |
| localStorage.setItem('theme', 'dark'); | |
| } else { | |
| themeIcon.textContent = 'dark_mode'; | |
| localStorage.setItem('theme', 'light'); | |
| } | |
| }); | |
| // User dropdown functionality | |
| const userMenu = document.getElementById('user-menu'); | |
| const userDropdown = document.getElementById('user-dropdown'); | |
| userMenu.addEventListener('click', () => { | |
| userDropdown.classList.toggle('hidden'); | |
| }); | |
| // Close dropdown when clicking outside | |
| document.addEventListener('click', (e) => { | |
| if (!userMenu.contains(e.target) && !userDropdown.contains(e.target)) { | |
| userDropdown.classList.add('hidden'); | |
| } | |
| }); | |
| // Class completion toggle (example functionality) | |
| document.querySelectorAll('table tbody tr').forEach(row => { | |
| const classNameCell = row.querySelector('.text-sm.font-medium'); | |
| classNameCell.addEventListener('click', () => { | |
| classNameCell.classList.toggle('completed'); | |
| }); | |
| }); | |
| </script> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=DobleFilo/academia-calendar" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |