se sube vistas
This commit is contained in:
1 parent
509272a643
commit
a8c484c1de
16 files changed
+1994
-256
No files matched your search
@@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
import { useNavigate } from 'react-router';
|
||||
import {
|
||||
FiStar,
|
||||
FiClock,
|
||||
@@ -14,15 +15,19 @@ interface CourseCardProps {
|
||||
course: Course;
|
||||
isInCart: boolean;
|
||||
onAddToCart: (course: Course) => void;
|
||||
onOpenDetails: (course: Course) => void;
|
||||
onOpenDetails?: (course: Course) => void;
|
||||
}
|
||||
|
||||
export const CourseCard: React.FC<CourseCardProps> = ({
|
||||
course,
|
||||
isInCart,
|
||||
onAddToCart,
|
||||
onOpenDetails,
|
||||
}) => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const handleCourseClick = () => {
|
||||
navigate(`/course/${course.id}`);
|
||||
};
|
||||
const discountPercent = Math.round(
|
||||
((course.originalPrice - course.price) / course.originalPrice) * 100
|
||||
);
|
||||
@@ -47,7 +52,7 @@ export const CourseCard: React.FC<CourseCardProps> = ({
|
||||
|
||||
{/* Top Image Section */}
|
||||
<div>
|
||||
<div className="relative aspect-video w-full overflow-hidden bg-slate-800 cursor-pointer" onClick={() => onOpenDetails(course)}>
|
||||
<div className="relative aspect-video w-full overflow-hidden bg-slate-800 cursor-pointer" onClick={handleCourseClick}>
|
||||
<img
|
||||
src={course.thumbnail}
|
||||
alt={course.title}
|
||||
@@ -79,11 +84,11 @@ export const CourseCard: React.FC<CourseCardProps> = ({
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onOpenDetails(course);
|
||||
handleCourseClick();
|
||||
}}
|
||||
className="px-3.5 py-2 bg-white/90 hover:bg-white text-slate-950 rounded-xl text-xs font-bold flex items-center gap-1.5 shadow-lg transform translate-y-2 group-hover:translate-y-0 transition-transform"
|
||||
>
|
||||
<FiEye /> Vista Rápida
|
||||
<FiEye /> Ver Curso Completo
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -112,7 +117,7 @@ export const CourseCard: React.FC<CourseCardProps> = ({
|
||||
|
||||
{/* Title */}
|
||||
<h3
|
||||
onClick={() => onOpenDetails(course)}
|
||||
onClick={handleCourseClick}
|
||||
className="text-base font-bold text-white group-hover:text-cyan-300 transition-colors line-clamp-2 cursor-pointer leading-snug"
|
||||
>
|
||||
{course.title}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import React from 'react';
|
||||
|
||||
interface BrandLogoProps {
|
||||
size?: 'sm' | 'md' | 'lg';
|
||||
showSubtitle?: boolean;
|
||||
}
|
||||
|
||||
export const BrandLogo: React.FC<BrandLogoProps> = ({ size = 'md', showSubtitle = true }) => {
|
||||
const iconSizes = {
|
||||
sm: 'w-8 h-8',
|
||||
md: 'w-10 h-10',
|
||||
lg: 'w-12 h-12',
|
||||
};
|
||||
|
||||
const textSizes = {
|
||||
sm: 'text-lg',
|
||||
md: 'text-xl',
|
||||
lg: 'text-2xl',
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-3 group select-none cursor-pointer">
|
||||
{/* Official PNG Logo Image with sleek container styling */}
|
||||
<div className={`relative ${iconSizes[size]} p-0.5 rounded-xl bg-slate-900 border border-slate-700/80 shadow-md shadow-cyan-950/40 group-hover:border-cyan-500/60 group-hover:scale-105 transition-all duration-300 overflow-hidden`}>
|
||||
<img
|
||||
src="/logo.png"
|
||||
alt="RyCourses Emblem"
|
||||
className="w-full h-full object-cover rounded-[10px]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Typography */}
|
||||
<div>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className={`${textSizes[size]} font-extrabold tracking-tight text-white group-hover:text-cyan-300 transition-colors`}>
|
||||
Ry<span className="text-transparent bg-clip-text bg-gradient-to-r from-cyan-400 to-blue-400">Courses</span>
|
||||
</span>
|
||||
</div>
|
||||
{showSubtitle && (
|
||||
<p className="text-[11px] text-slate-400 font-medium tracking-wide">Plataforma Educativa</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,6 +1,5 @@
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
FiBookOpen,
|
||||
FiMail,
|
||||
FiCheckCircle,
|
||||
FiGlobe,
|
||||
@@ -10,6 +9,8 @@ import {
|
||||
} from 'react-icons/fi';
|
||||
import { FaTwitter, FaYoutube, FaGithub, FaLinkedin, FaDiscord } from 'react-icons/fa';
|
||||
|
||||
import { BrandLogo } from '../common/BrandLogo';
|
||||
|
||||
export const Footer: React.FC = () => {
|
||||
const [email, setEmail] = useState('');
|
||||
const [subscribed, setSubscribed] = useState(false);
|
||||
@@ -25,52 +26,6 @@ export const Footer: React.FC = () => {
|
||||
|
||||
return (
|
||||
<footer className="bg-slate-950 border-t border-slate-800 text-slate-400 text-sm">
|
||||
{/* Top Banner / Newsletter */}
|
||||
<div className="border-b border-slate-800/80 bg-gradient-to-r from-blue-950/40 via-indigo-950/40 to-slate-950/80">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
||||
<div className="flex flex-col lg:flex-row items-center justify-between gap-8">
|
||||
<div className="max-w-xl text-center lg:text-left">
|
||||
<span className="inline-flex items-center gap-2 px-3 py-1 rounded-full text-xs font-semibold bg-cyan-500/10 text-cyan-400 border border-cyan-500/20 mb-3">
|
||||
<FiAward /> Actualizaciones semanales de cursos
|
||||
</span>
|
||||
<h3 className="text-2xl font-bold text-white">
|
||||
Suscríbete para recibir descuentos exclusivos y nuevos lanzamientos
|
||||
</h3>
|
||||
<p className="text-slate-400 text-xs sm:text-sm mt-2">
|
||||
Únete a más de 50,000 profesionales que potencian su carrera cada semana. Sin spam.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Newsletter form */}
|
||||
<form onSubmit={handleSubscribe} className="w-full max-w-md">
|
||||
<div className="flex flex-col sm:flex-row gap-2">
|
||||
<div className="relative flex-1">
|
||||
<FiMail className="absolute left-3.5 top-3.5 text-slate-500" />
|
||||
<input
|
||||
type="email"
|
||||
required
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
placeholder="[email protected]"
|
||||
className="w-full pl-10 pr-4 py-3 bg-slate-900 border border-slate-700 rounded-xl text-sm text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-cyan-500"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
type="submit"
|
||||
className="px-6 py-3 bg-gradient-to-r from-blue-600 to-cyan-500 hover:from-blue-500 hover:to-cyan-400 text-white font-semibold rounded-xl text-sm transition-all shadow-lg shadow-cyan-500/20 whitespace-nowrap"
|
||||
>
|
||||
{subscribed ? '¡Suscrito!' : 'Suscribirme'}
|
||||
</button>
|
||||
</div>
|
||||
{subscribed && (
|
||||
<p className="flex items-center gap-1.5 text-emerald-400 text-xs mt-2 animate-fadeIn">
|
||||
<FiCheckCircle /> ¡Gracias por suscribirte! Revisa tu bandeja de entrada pronto.
|
||||
</p>
|
||||
)}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Main Footer Links */}
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-14">
|
||||
@@ -78,15 +33,8 @@ export const Footer: React.FC = () => {
|
||||
|
||||
{/* Brand col */}
|
||||
<div className="col-span-2 lg:col-span-2">
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<div className="w-10 h-10 rounded-xl bg-gradient-to-tr from-indigo-600 via-blue-500 to-cyan-400 p-[2px]">
|
||||
<div className="w-full h-full bg-slate-950 rounded-[10px] flex items-center justify-center">
|
||||
<FiBookOpen className="text-cyan-400 text-lg" />
|
||||
</div>
|
||||
</div>
|
||||
<span className="text-xl font-bold text-white tracking-tight">
|
||||
Ry<span className="text-cyan-400">Courses</span>
|
||||
</span>
|
||||
<div className="mb-4">
|
||||
<BrandLogo size="md" />
|
||||
</div>
|
||||
<p className="text-xs text-slate-400 leading-relaxed mb-6 max-w-sm">
|
||||
La plataforma líder para aprender habilidades de alta demanda y convertir tu conocimiento profesional en un negocio digital rentable.
|
||||
|
||||
+145
-120
@@ -1,106 +1,101 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useNavigate, useLocation } from 'react-router';
|
||||
import {
|
||||
FiSearch,
|
||||
FiShoppingCart,
|
||||
FiHeart,
|
||||
FiBell,
|
||||
FiMenu,
|
||||
FiX,
|
||||
FiBookOpen,
|
||||
FiPlusCircle,
|
||||
FiCompass,
|
||||
FiHome,
|
||||
FiGrid,
|
||||
FiUser,
|
||||
FiShield,
|
||||
} from 'react-icons/fi';
|
||||
import { FaGraduationCap, FaChalkboardTeacher } from 'react-icons/fa';
|
||||
import type { ViewMode } from '../../types/course';
|
||||
import { FaChalkboardTeacher } from 'react-icons/fa';
|
||||
import { BrandLogo } from '../common/BrandLogo';
|
||||
|
||||
interface NavbarProps {
|
||||
viewMode: ViewMode;
|
||||
onToggleViewMode: (mode: ViewMode) => void;
|
||||
cartCount: number;
|
||||
onOpenCart: () => void;
|
||||
onOpenCreateCourseModal: () => void;
|
||||
onOpenCreateCourseModal?: () => void;
|
||||
searchQuery: string;
|
||||
onSearchChange: (query: string) => void;
|
||||
}
|
||||
|
||||
export const Navbar: React.FC<NavbarProps> = ({
|
||||
viewMode,
|
||||
onToggleViewMode,
|
||||
cartCount,
|
||||
onOpenCart,
|
||||
onOpenCreateCourseModal,
|
||||
searchQuery,
|
||||
onSearchChange,
|
||||
}) => {
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
||||
const [categoryDropdown, setCategoryDropdown] = useState(false);
|
||||
|
||||
const currentPath = location.pathname;
|
||||
const isSellerMode = currentPath === '/seller' || currentPath.startsWith('/seller/');
|
||||
|
||||
const handleSearchInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
onSearchChange(e.target.value);
|
||||
if (currentPath !== '/courses' && e.target.value.trim() !== '') {
|
||||
navigate('/courses');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<header className="sticky top-0 z-40 w-full border-b border-slate-800/80 bg-slate-950/80 backdrop-blur-md transition-all">
|
||||
<header className="sticky top-0 z-40 w-full border-b border-slate-800/80 bg-slate-950/90 backdrop-blur-xl transition-all">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex items-center justify-between h-20 gap-4">
|
||||
|
||||
{/* Logo */}
|
||||
<div className="flex items-center gap-8">
|
||||
<div
|
||||
onClick={() => onToggleViewMode('buyer')}
|
||||
className="flex items-center gap-3 cursor-pointer group select-none"
|
||||
>
|
||||
<div className="w-11 h-11 rounded-xl bg-gradient-to-tr from-indigo-600 via-blue-500 to-cyan-400 p-[2px] shadow-lg shadow-indigo-500/20 group-hover:scale-105 transition-transform">
|
||||
<div className="w-full h-full bg-slate-950 rounded-[10px] flex items-center justify-center">
|
||||
<FiBookOpen className="text-cyan-400 text-xl" />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<span className="text-xl font-black tracking-tight text-white group-hover:text-cyan-300 transition-colors">
|
||||
Ry<span className="text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-cyan-400">Courses</span>
|
||||
</span>
|
||||
<span className="text-[10px] font-bold px-1.5 py-0.5 rounded bg-indigo-500/20 text-indigo-300 border border-indigo-500/30">
|
||||
PRO
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-[11px] text-slate-400 font-medium tracking-wide">Plataforma Educativa</p>
|
||||
</div>
|
||||
{/* 1. Left Brand & Main Links */}
|
||||
<div className="flex items-center gap-6 shrink-0">
|
||||
<div onClick={() => navigate('/')}>
|
||||
<BrandLogo size="md" />
|
||||
</div>
|
||||
|
||||
{/* Quick Categories dropdown (Desktop) */}
|
||||
{viewMode === 'buyer' && (
|
||||
<div className="relative hidden lg:block">
|
||||
<button
|
||||
onClick={() => setCategoryDropdown(!categoryDropdown)}
|
||||
className="flex items-center gap-2 px-3.5 py-2 rounded-lg text-sm font-medium text-slate-300 hover:text-white hover:bg-slate-800/60 border border-slate-700/60 transition"
|
||||
>
|
||||
<FiCompass className="text-cyan-400" />
|
||||
<span>Explorar</span>
|
||||
</button>
|
||||
{/* Quick Nav Links */}
|
||||
<nav className="hidden lg:flex items-center gap-1">
|
||||
<button
|
||||
onClick={() => navigate('/')}
|
||||
className={`flex items-center gap-1.5 px-3 py-2 rounded-xl text-xs font-semibold transition-all ${
|
||||
currentPath === '/'
|
||||
? 'bg-slate-800 text-cyan-400 border border-cyan-500/30'
|
||||
: 'text-slate-300 hover:text-white hover:bg-slate-900'
|
||||
}`}
|
||||
>
|
||||
<FiHome />
|
||||
<span>Inicio</span>
|
||||
</button>
|
||||
|
||||
{categoryDropdown && (
|
||||
<div
|
||||
onMouseLeave={() => setCategoryDropdown(false)}
|
||||
className="absolute top-full left-0 mt-2 w-56 rounded-xl bg-slate-900 border border-slate-800 shadow-2xl p-2 z-50 animate-in fade-in slide-in-from-top-2 duration-200"
|
||||
>
|
||||
{['Desarrollo Web', 'Inteligencia Artificial', 'Diseño UI/UX', 'Ciberseguridad', 'Marketing Digital', 'Negocios'].map((cat) => (
|
||||
<button
|
||||
key={cat}
|
||||
onClick={() => {
|
||||
onSearchChange(cat);
|
||||
setCategoryDropdown(false);
|
||||
}}
|
||||
className="w-full text-left px-3 py-2 text-xs font-medium text-slate-300 hover:text-cyan-300 hover:bg-slate-800/80 rounded-lg transition"
|
||||
>
|
||||
{cat}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<button
|
||||
onClick={() => navigate('/courses')}
|
||||
className={`flex items-center gap-1.5 px-3 py-2 rounded-xl text-xs font-semibold transition-all ${
|
||||
currentPath === '/courses'
|
||||
? 'bg-slate-800 text-cyan-400 border border-cyan-500/30'
|
||||
: 'text-slate-300 hover:text-white hover:bg-slate-900'
|
||||
}`}
|
||||
>
|
||||
<FiGrid />
|
||||
<span>Catálogo</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => navigate('/admin')}
|
||||
className={`flex items-center gap-1.5 px-3 py-2 rounded-xl text-xs font-semibold transition-all ${
|
||||
currentPath === '/admin'
|
||||
? 'bg-slate-800 text-cyan-400 border border-cyan-500/30'
|
||||
: 'text-slate-300 hover:text-white hover:bg-slate-900'
|
||||
}`}
|
||||
>
|
||||
<FiShield />
|
||||
<span>Admin</span>
|
||||
</button>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
{/* Search bar (Desktop) */}
|
||||
{viewMode === 'buyer' && (
|
||||
<div className="hidden md:flex flex-1 max-w-md mx-4">
|
||||
{/* 2. Spacious Center Search Bar */}
|
||||
{!isSellerMode && (
|
||||
<div className="hidden md:flex flex-1 max-w-xl mx-2">
|
||||
<div className="relative w-full">
|
||||
<div className="absolute inset-y-0 left-0 pl-3.5 flex items-center pointer-events-none text-slate-400">
|
||||
<FiSearch className="text-base" />
|
||||
@@ -108,98 +103,105 @@ export const Navbar: React.FC<NavbarProps> = ({
|
||||
<input
|
||||
type="text"
|
||||
value={searchQuery}
|
||||
onChange={(e) => onSearchChange(e.target.value)}
|
||||
placeholder="¿Qué habilidad quieres aprender hoy? (React, Python, Figma...)"
|
||||
className="w-full pl-10 pr-16 py-2.5 bg-slate-900/90 border border-slate-700/70 rounded-xl text-sm text-slate-100 placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-cyan-500/50 focus:border-cyan-500 transition-all shadow-inner"
|
||||
onChange={handleSearchInputChange}
|
||||
placeholder="¿Qué quieres aprender hoy? (React, Python, Figma...)"
|
||||
className="w-full pl-10 pr-12 py-2.5 bg-slate-900/90 border border-slate-700/80 rounded-xl text-xs text-slate-100 placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-cyan-500/50 focus:border-cyan-500 transition-all shadow-inner"
|
||||
/>
|
||||
<div className="absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none">
|
||||
<kbd className="hidden xl:inline-block px-1.5 py-0.5 text-[10px] font-semibold text-slate-400 bg-slate-800 border border-slate-700 rounded">
|
||||
Ctrl + K
|
||||
⌘K
|
||||
</kbd>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* View Mode Switcher (Estudiante vs Instructor) & User Actions */}
|
||||
<div className="flex items-center gap-3">
|
||||
{/* 3. Right Actions & Role Switcher */}
|
||||
<div className="flex items-center gap-2.5 shrink-0">
|
||||
|
||||
{/* Mode Switcher pill */}
|
||||
<div className="bg-slate-900/90 p-1 rounded-xl border border-slate-800 flex items-center shadow-inner">
|
||||
{/* Buyer vs Seller Switcher pill */}
|
||||
<div className="bg-slate-900 p-1 rounded-xl border border-slate-800 flex items-center shadow-inner">
|
||||
<button
|
||||
onClick={() => onToggleViewMode('buyer')}
|
||||
className={`flex items-center gap-2 px-3 py-1.5 rounded-lg text-xs font-semibold transition-all ${
|
||||
viewMode === 'buyer'
|
||||
onClick={() => navigate('/courses')}
|
||||
className={`flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-semibold transition-all ${
|
||||
!isSellerMode
|
||||
? 'bg-gradient-to-r from-blue-600 to-cyan-500 text-white shadow-md shadow-cyan-500/20'
|
||||
: 'text-slate-400 hover:text-slate-200'
|
||||
}`}
|
||||
title="Modo Estudiante - Explorar y Comprar cursos"
|
||||
>
|
||||
<FaGraduationCap className="text-sm" />
|
||||
<FiGrid className="text-xs" />
|
||||
<span className="hidden sm:inline">Comprar</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => onToggleViewMode('seller')}
|
||||
className={`flex items-center gap-2 px-3 py-1.5 rounded-lg text-xs font-semibold transition-all ${
|
||||
viewMode === 'seller'
|
||||
onClick={() => navigate('/seller')}
|
||||
className={`flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-semibold transition-all ${
|
||||
isSellerMode
|
||||
? 'bg-gradient-to-r from-indigo-600 to-violet-500 text-white shadow-md shadow-violet-500/20'
|
||||
: 'text-slate-400 hover:text-slate-200'
|
||||
}`}
|
||||
title="Modo Instructor - Vender y Gestionar cursos"
|
||||
>
|
||||
<FaChalkboardTeacher className="text-sm" />
|
||||
<FaChalkboardTeacher className="text-xs" />
|
||||
<span className="hidden sm:inline">Vender</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* If seller mode: Create Course button */}
|
||||
{viewMode === 'seller' && (
|
||||
{isSellerMode && (
|
||||
<button
|
||||
onClick={onOpenCreateCourseModal}
|
||||
className="hidden sm:flex items-center gap-2 px-4 py-2 rounded-xl bg-gradient-to-r from-violet-600 to-indigo-600 hover:from-violet-500 hover:to-indigo-500 text-white font-medium text-xs shadow-lg shadow-violet-600/30 hover:scale-[1.02] transition-all"
|
||||
onClick={() => navigate('/seller/create')}
|
||||
className="hidden sm:flex items-center gap-1.5 px-3.5 py-2 rounded-xl bg-gradient-to-r from-violet-600 to-indigo-600 hover:from-violet-500 hover:to-indigo-500 text-white font-medium text-xs shadow-lg shadow-violet-600/30 transition-all"
|
||||
>
|
||||
<FiPlusCircle className="text-base" />
|
||||
<FiPlusCircle className="text-sm" />
|
||||
<span>Crear Curso</span>
|
||||
</button>
|
||||
)}
|
||||
|
||||
{/* Cart button (buyer mode) */}
|
||||
{viewMode === 'buyer' && (
|
||||
{/* Cart button (Buyer mode) */}
|
||||
{!isSellerMode && (
|
||||
<button
|
||||
onClick={onOpenCart}
|
||||
className="relative p-2.5 text-slate-300 hover:text-white bg-slate-900/80 hover:bg-slate-800 border border-slate-700/80 rounded-xl transition"
|
||||
className="relative p-2.5 text-slate-300 hover:text-white bg-slate-900 hover:bg-slate-800 border border-slate-700/80 rounded-xl transition"
|
||||
aria-label="Carrito de compras"
|
||||
>
|
||||
<FiShoppingCart className="text-lg" />
|
||||
<FiShoppingCart className="text-base" />
|
||||
{cartCount > 0 && (
|
||||
<span className="absolute -top-1.5 -right-1.5 w-5 h-5 bg-gradient-to-tr from-rose-500 to-pink-500 text-white text-[11px] font-bold rounded-full flex items-center justify-center animate-bounce shadow-md">
|
||||
<span className="absolute -top-1.5 -right-1.5 w-5 h-5 bg-gradient-to-tr from-rose-500 to-pink-500 text-white text-[11px] font-bold rounded-full flex items-center justify-center shadow-md">
|
||||
{cartCount}
|
||||
</span>
|
||||
)}
|
||||
</button>
|
||||
)}
|
||||
|
||||
{/* Wishlist */}
|
||||
{viewMode === 'buyer' && (
|
||||
<button className="hidden sm:flex p-2.5 text-slate-400 hover:text-rose-400 bg-slate-900/60 hover:bg-slate-800/80 border border-slate-800 rounded-xl transition">
|
||||
<FiHeart className="text-lg" />
|
||||
{/* Login & Register Buttons */}
|
||||
<div className="hidden xl:flex items-center gap-2 pl-2 border-l border-slate-800">
|
||||
<button
|
||||
onClick={() => navigate('/login')}
|
||||
className="px-3 py-1.5 text-xs font-semibold text-slate-300 hover:text-white transition"
|
||||
>
|
||||
Iniciar Sesión
|
||||
</button>
|
||||
)}
|
||||
|
||||
{/* Notification Bell */}
|
||||
<button className="relative hidden sm:flex p-2.5 text-slate-400 hover:text-amber-400 bg-slate-900/60 hover:bg-slate-800/80 border border-slate-800 rounded-xl transition">
|
||||
<FiBell className="text-lg" />
|
||||
<span className="absolute top-2 right-2 w-2 h-2 bg-amber-400 rounded-full"></span>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => navigate('/register')}
|
||||
className="px-3.5 py-1.5 rounded-xl bg-cyan-500/10 hover:bg-cyan-500/20 text-cyan-400 font-semibold text-xs border border-cyan-500/30 transition"
|
||||
>
|
||||
Registrarse
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* User Profile Avatar */}
|
||||
<div className="flex items-center gap-2 pl-2 border-l border-slate-800">
|
||||
<div className="relative cursor-pointer">
|
||||
<div
|
||||
onClick={() => navigate('/login')}
|
||||
className="relative cursor-pointer group"
|
||||
title="Mi Cuenta"
|
||||
>
|
||||
<img
|
||||
src="https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=100&auto=format&fit=crop&q=80"
|
||||
alt="Usuario"
|
||||
className="w-9 h-9 rounded-full object-cover ring-2 ring-indigo-500/50 hover:ring-cyan-400 transition"
|
||||
className="w-9 h-9 rounded-full object-cover ring-2 ring-indigo-500/50 group-hover:ring-cyan-400 transition"
|
||||
/>
|
||||
<span className="absolute bottom-0 right-0 w-2.5 h-2.5 bg-emerald-500 ring-2 ring-slate-950 rounded-full"></span>
|
||||
</div>
|
||||
@@ -223,34 +225,57 @@ export const Navbar: React.FC<NavbarProps> = ({
|
||||
<input
|
||||
type="text"
|
||||
value={searchQuery}
|
||||
onChange={(e) => onSearchChange(e.target.value)}
|
||||
onChange={handleSearchInputChange}
|
||||
placeholder="Buscar cursos..."
|
||||
className="w-full pl-10 pr-4 py-2 bg-slate-900 border border-slate-700 rounded-lg text-sm text-white"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
<button
|
||||
onClick={() => { onToggleViewMode('buyer'); setMobileMenuOpen(false); }}
|
||||
className={`flex items-center justify-center gap-2 p-2.5 rounded-lg text-xs font-semibold ${
|
||||
viewMode === 'buyer' ? 'bg-blue-600 text-white' : 'bg-slate-800 text-slate-300'
|
||||
onClick={() => { navigate('/'); setMobileMenuOpen(false); }}
|
||||
className={`flex items-center justify-center gap-1.5 p-2 rounded-lg text-xs font-semibold ${
|
||||
currentPath === '/' ? 'bg-blue-600 text-white' : 'bg-slate-800 text-slate-300'
|
||||
}`}
|
||||
>
|
||||
<FaGraduationCap /> Modo Comprador
|
||||
<FiHome /> Inicio
|
||||
</button>
|
||||
<button
|
||||
onClick={() => { onToggleViewMode('seller'); setMobileMenuOpen(false); }}
|
||||
className={`flex items-center justify-center gap-2 p-2.5 rounded-lg text-xs font-semibold ${
|
||||
viewMode === 'seller' ? 'bg-violet-600 text-white' : 'bg-slate-800 text-slate-300'
|
||||
onClick={() => { navigate('/courses'); setMobileMenuOpen(false); }}
|
||||
className={`flex items-center justify-center gap-1.5 p-2 rounded-lg text-xs font-semibold ${
|
||||
currentPath === '/courses' ? 'bg-cyan-600 text-white' : 'bg-slate-800 text-slate-300'
|
||||
}`}
|
||||
>
|
||||
<FaChalkboardTeacher /> Modo Vendedor
|
||||
<FiGrid /> Catálogo
|
||||
</button>
|
||||
<button
|
||||
onClick={() => { navigate('/seller'); setMobileMenuOpen(false); }}
|
||||
className={`flex items-center justify-center gap-1.5 p-2 rounded-lg text-xs font-semibold ${
|
||||
currentPath === '/seller' ? 'bg-violet-600 text-white' : 'bg-slate-800 text-slate-300'
|
||||
}`}
|
||||
>
|
||||
<FaChalkboardTeacher /> Vender
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{viewMode === 'seller' && (
|
||||
<div className="grid grid-cols-2 gap-2 pt-2 border-t border-slate-800">
|
||||
<button
|
||||
onClick={() => { onOpenCreateCourseModal(); setMobileMenuOpen(false); }}
|
||||
onClick={() => { navigate('/login'); setMobileMenuOpen(false); }}
|
||||
className="w-full py-2.5 bg-slate-800 text-white font-semibold rounded-lg text-xs flex items-center justify-center gap-2"
|
||||
>
|
||||
<FiUser /> Iniciar Sesión
|
||||
</button>
|
||||
<button
|
||||
onClick={() => { navigate('/register'); setMobileMenuOpen(false); }}
|
||||
className="w-full py-2.5 bg-cyan-600 text-white font-semibold rounded-lg text-xs flex items-center justify-center gap-2"
|
||||
>
|
||||
Registrarse
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{isSellerMode && (
|
||||
<button
|
||||
onClick={() => { navigate('/seller/create'); setMobileMenuOpen(false); }}
|
||||
className="w-full py-2.5 bg-gradient-to-r from-violet-600 to-indigo-600 text-white font-semibold rounded-lg text-xs flex items-center justify-center gap-2"
|
||||
>
|
||||
<FiPlusCircle /> Crear Nuevo Curso
|
||||
|
||||
@@ -4,7 +4,6 @@ import {
|
||||
FiUsers,
|
||||
FiStar,
|
||||
FiBookOpen,
|
||||
FiTrendingUp,
|
||||
FiArrowUpRight,
|
||||
FiActivity
|
||||
} from 'react-icons/fi';
|
||||
|
||||
Reference in new issue
Block a user