react-vite-themes
Version:
A test/experimental React theme system created for learning purposes. Features atomic design components, SCSS variables, and dark/light theme support. Not intended for production use.
91 lines (90 loc) • 13.4 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useState, useMemo } from 'react';
import { Badge } from "../../../components/atoms/Badge";
import { Button } from "../../../components/atoms/Button";
import { Card } from "../../../components/atoms/Card";
import { Icon } from "../../../components/atoms/Icon";
import { ProgressBar } from "../../../components/atoms/ProgressBar";
import { StatCard } from "../../../components/molecules/StatCard";
import { Image } from "../../../components/atoms/Image";
import { Input } from "../../../components/atoms/Input";
import { Select } from "../../../components/atoms/Select";
import { Tabs } from "../../../components/molecules/Tabs";
import { Alert } from "../../../components/atoms/Alert";
import modulesData from '../seeds/extended-modules-data.json';
const categories = modulesData.categories;
const difficultyLevels = modulesData.difficultyLevels;
// ModuleCard component defined outside to avoid temporal dead zone
const ModuleCard = ({ module, viewMode }) => {
const getProgressColor = (progress) => {
if (progress === 100)
return 'success';
if (progress > 50)
return 'warning';
return 'primary';
};
const getDifficultyColor = (difficulty) => {
switch (difficulty) {
case 'beginner': return 'success';
case 'intermediate': return 'warning';
case 'advanced': return 'error';
default: return 'primary';
}
};
const getCategoryIcon = (categoryId) => {
const category = categories.find(cat => cat.id === categoryId);
return category?.icon || 'book';
};
return (_jsxs(Card, { variant: "neutral", style: "elevated", padding: "lg", className: `transition-all duration-300 hover:shadow-light-xl cursor-pointer ${viewMode === 'list' ? 'd-flex flex-row' : ''}`, image: viewMode === 'grid' ? {
src: module.image.src,
alt: module.image.alt,
height: "200px"
} : undefined, children: [viewMode === 'list' && (_jsx("div", { className: "w-32 h-24 mr-4 flex-shrink-0", children: _jsx(Image, { src: module.image.src, alt: module.image.alt, style: "natural", size: "md", className: "w-full h-full object-cover rounded-md" }) })), _jsxs("div", { className: `d-flex flex-column ${viewMode === 'list' ? 'flex-1' : 'h-100'}`, children: [_jsxs("div", { className: "d-flex justify-between align-start mb-3", children: [_jsxs("div", { className: "d-flex align-center gap-2", children: [_jsx(Icon, { name: getCategoryIcon(module.category), size: "sm", className: "text-primary-500" }), _jsx(Badge, { variant: "neutral", size: "sm", children: categories.find(cat => cat.id === module.category)?.name || module.category })] }), _jsxs("div", { className: "d-flex gap-2", children: [_jsx(Badge, { variant: getDifficultyColor(module.difficulty), size: "sm", children: module.difficulty }), module.progress > 0 && (_jsxs(Badge, { variant: getProgressColor(module.progress), size: "sm", children: [module.progress, "%"] }))] })] }), _jsx("h3", { className: "text-lg font-bold mb-2", children: module.title }), _jsx("p", { className: "text-secondary mb-4 flex-1 text-sm", children: module.description }), module.progress > 0 && (_jsx("div", { className: "mb-4", children: _jsx(ProgressBar, { value: module.progress, variant: getProgressColor(module.progress), size: "sm", showLabel: true, labelPosition: "top", isAnimated: true }) })), _jsx("div", { className: "d-flex justify-between align-center mb-3", children: _jsxs("div", { className: "d-flex gap-4 text-xs text-neutral-600", children: [_jsxs("span", { className: "d-flex align-center gap-1", children: [_jsx(Icon, { name: "lessons", size: "sm" }), module.lessons, " lecciones"] }), _jsxs("span", { className: "d-flex align-center gap-1", children: [_jsx(Icon, { name: "clock", size: "sm" }), module.duration] }), _jsxs("span", { className: "d-flex align-center gap-1", children: [_jsx(Icon, { name: "users", size: "sm" }), module.students, " estudiantes"] })] }) }), _jsx(Button, { variant: module.progress === 100 ? "success" : module.progress > 0 ? "secondary" : "primary", size: "sm", rightIcon: module.progress === 100 ? "check-circle" : "play-circle", className: "w-full", children: module.progress === 100 ? "Completado" : module.progress > 0 ? "Continuar" : "Comenzar" })] })] }, module.id));
};
const ModulesPage = () => {
const [searchTerm, setSearchTerm] = useState('');
const [selectedCategory, setSelectedCategory] = useState('all');
const [selectedDifficulty, setSelectedDifficulty] = useState('all');
const [viewMode, setViewMode] = useState('grid');
const [activeTab, setActiveTab] = useState('all');
const filteredModules = useMemo(() => {
return modulesData.allModules.filter((module) => {
const matchesSearch = module.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
module.description.toLowerCase().includes(searchTerm.toLowerCase());
const matchesCategory = selectedCategory === 'all' || module.category === selectedCategory;
const matchesDifficulty = selectedDifficulty === 'all' || module.difficulty === selectedDifficulty;
return matchesSearch && matchesCategory && matchesDifficulty;
});
}, [searchTerm, selectedCategory, selectedDifficulty]);
const featuredModules = filteredModules.slice(0, 3);
const recentModules = filteredModules.filter(module => new Date(module.lastUpdated) > new Date(Date.now() - 30 * 24 * 60 * 60 * 1000)).slice(0, 6);
const tabs = [
{
id: 'all',
label: 'Todos los Módulos',
icon: 'grid',
content: (_jsx("div", { className: "d-grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6", children: filteredModules.map((module) => (_jsx(ModuleCard, { module: module, viewMode: viewMode }, module.id))) }))
},
{
id: 'featured',
label: 'Destacados',
icon: 'star',
content: (_jsx("div", { className: "d-grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6", children: featuredModules.map((module) => (_jsx(ModuleCard, { module: module, viewMode: viewMode }, module.id))) }))
},
{
id: 'recent',
label: 'Recientes',
icon: 'clock',
content: (_jsx("div", { className: "d-grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6", children: recentModules.map((module) => (_jsx(ModuleCard, { module: module, viewMode: viewMode }, module.id))) }))
}
];
return (_jsxs("div", { className: "modules-page", children: [_jsxs("section", { className: "bg-gradient-rainbow-burst text-white py-12 relative overflow-hidden", children: [_jsxs("div", { className: "absolute inset-0 opacity-10", children: [_jsx("div", { className: "absolute top-0 left-0 w-64 h-64 bg-white rounded-full -translate-x-1/2 -translate-y-1/2" }), _jsx("div", { className: "absolute bottom-0 right-0 w-96 h-96 bg-white rounded-full translate-x-1/2 translate-y-1/2" })] }), _jsx("div", { className: "container relative z-10", children: _jsxs("div", { className: "text-center mb-8", children: [_jsx("h1", { className: "font-bold mb-4 text-4xl md:text-5xl", children: "Explora Nuestros M\u00F3dulos" }), _jsx("p", { className: "text-xl mb-8 w-75 mx-auto opacity-95", children: "M\u00E1s de 50 lecciones dise\u00F1adas espec\u00EDficamente para migrantes latinos en Alemania" }), _jsx("div", { className: "w-75 mx-auto mb-8", children: _jsx(Input, { placeholder: "Buscar m\u00F3dulos por t\u00EDtulo, descripci\u00F3n o categor\u00EDa...", value: searchTerm, onChange: (e) => setSearchTerm(e.target.value), leftIcon: _jsx(Icon, { name: "search", size: "md" }), size: "lg", isRounded: true, className: "shadow-light-lg" }) }), _jsxs("div", { className: "d-flex flex-wrap justify-center gap-4", children: [_jsx(StatCard, { value: modulesData.statistics.totalModules.toString(), subtitle: "M\u00F3dulos Disponibles", style: "glass", isHoverable: true, size: "sm" }), _jsx(StatCard, { value: modulesData.statistics.totalLessons.toString(), subtitle: "Lecciones Totales", style: "glass", isHoverable: true, size: "sm" }), _jsx(StatCard, { value: modulesData.statistics.totalCategories.toString(), subtitle: "Categor\u00EDas", style: "glass", isHoverable: true, size: "sm" }), _jsx(StatCard, { value: `${modulesData.statistics.completionRate}%`, subtitle: "Tasa de Completado", style: "glass", isHoverable: true, size: "sm" })] })] }) })] }), _jsxs("section", { className: "container-xl py-8", children: [_jsx(Alert, { variant: "info", title: "\uD83D\uDCCA Estad\u00EDsticas R\u00E1pidas", className: "mb-6", children: _jsxs("div", { className: "d-flex justify-between align-center", children: [_jsxs("span", { children: ["Mostrando ", filteredModules.length, " de ", modulesData.statistics.totalModules, " m\u00F3dulos"] }), _jsxs("div", { className: "d-flex gap-2", children: [_jsx(Button, { variant: viewMode === 'grid' ? "primary" : "secondary", size: "sm", centerIcon: "grid", onClick: () => setViewMode('grid') }), _jsx(Button, { variant: viewMode === 'list' ? "primary" : "secondary", size: "sm", centerIcon: "list", onClick: () => setViewMode('list') })] })] }) }), _jsx(Card, { variant: "neutral", style: "elevated", className: "mb-8", children: _jsxs("div", { className: "p-6", children: [_jsx("h3", { className: "text-lg font-semibold mb-4", children: "Filtros y Categor\u00EDas" }), _jsxs("div", { className: "mb-6", children: [_jsx("h4", { className: "text-sm font-medium mb-3 text-neutral-600", children: "Categor\u00EDas" }), _jsxs("div", { className: "d-flex flex-wrap gap-2", children: [_jsx(Button, { variant: selectedCategory === 'all' ? "primary" : "secondary", size: "sm", onClick: () => setSelectedCategory('all'), className: "shadow-light-sm", children: "Todas" }), categories.map((category) => (_jsx(Button, { variant: selectedCategory === category.id ? "primary" : "secondary", size: "sm", leftIcon: _jsx(Icon, { name: category.icon, size: "sm" }), onClick: () => setSelectedCategory(category.id), className: "shadow-light-sm", children: category.name }, category.id)))] })] }), _jsx("div", { className: "d-flex align-center gap-4", children: _jsxs("div", { className: "flex-1", children: [_jsx("h4", { className: "text-sm font-medium mb-3 text-neutral-600", children: "Nivel de Dificultad" }), _jsx(Select, { options: difficultyLevels.map((level) => ({
value: level.id,
label: level.name
})), value: selectedDifficulty, onChange: setSelectedDifficulty, placeholder: "Seleccionar nivel", size: "md", variant: "secondary" })] }) })] }) }), _jsx(Tabs, { tabs: tabs, variant: "underline", size: "md", defaultActiveTab: "all", onTabChange: setActiveTab, className: "mb-8" }), _jsxs("div", { className: "mb-8", children: [activeTab === 'all' && (_jsx("div", { className: "d-grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6", children: filteredModules.map((module) => (_jsx(ModuleCard, { module: module, viewMode: viewMode }, module.id))) })), activeTab === 'featured' && (_jsx("div", { className: "d-grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6", children: featuredModules.map((module) => (_jsx(ModuleCard, { module: module, viewMode: viewMode }, module.id))) })), activeTab === 'recent' && (_jsx("div", { className: "d-grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6", children: recentModules.map((module) => (_jsx(ModuleCard, { module: module, viewMode: viewMode }, module.id))) }))] }), filteredModules.length === 0 && (_jsxs(Card, { variant: "neutral", style: "elevated", className: "text-center py-12", children: [_jsx(Icon, { name: "search", size: "xl", className: "text-neutral-400 mb-4" }), _jsx("h3", { className: "text-xl font-semibold mb-2", children: "No se encontraron m\u00F3dulos" }), _jsx("p", { className: "text-neutral-600 mb-6", children: "Intenta ajustar tus filtros de b\u00FAsqueda o explorar otras categor\u00EDas" }), _jsx(Button, { variant: "primary", onClick: () => {
setSearchTerm('');
setSelectedCategory('all');
setSelectedDifficulty('all');
}, children: "Limpiar Filtros" })] })), _jsx(Card, { variant: "primary", style: "elevated", className: "text-center py-12 bg-gradient-sunset", children: _jsxs("div", { className: "w-75 mx-auto", children: [_jsx("h2", { className: "text-2xl font-bold mb-4 text-white", children: "\u00BFNo encuentras lo que buscas?" }), _jsx("p", { className: "text-white opacity-90 mb-6", children: "Estamos constantemente agregando nuevos m\u00F3dulos. Suscr\u00EDbete para recibir notificaciones sobre nuevos contenidos y actualizaciones." }), _jsxs("div", { className: "d-flex justify-center gap-4", children: [_jsx(Button, { variant: "light", size: "lg", leftIcon: _jsx(Icon, { name: "bell", size: "md" }), className: "shadow-light-lg", children: "Suscribirse" }), _jsx(Button, { variant: "light", size: "lg", leftIcon: _jsx(Icon, { name: "message", size: "md" }), className: "shadow-light-lg", children: "Contactar" })] })] }) })] })] }));
};
export default ModulesPage;