Refactor dashboard sidebar
This commit is contained in:
120
src/App.tsx
120
src/App.tsx
@@ -35,6 +35,21 @@ import InvoiceDetail from "./pages/dashboard/InvoiceDetail";
|
|||||||
import HotelManagement from "./pages/dashboard/HotelManagement";
|
import HotelManagement from "./pages/dashboard/HotelManagement";
|
||||||
import RestaurantPOS from "./pages/dashboard/RestaurantPOS";
|
import RestaurantPOS from "./pages/dashboard/RestaurantPOS";
|
||||||
import Personalization from "./pages/dashboard/Personalization";
|
import Personalization from "./pages/dashboard/Personalization";
|
||||||
|
// Hotel pages
|
||||||
|
import HotelRooms from "./pages/dashboard/hotel/Rooms";
|
||||||
|
import HotelCheckIn from "./pages/dashboard/hotel/CheckIn";
|
||||||
|
import HotelRoomService from "./pages/dashboard/hotel/RoomServicePage";
|
||||||
|
import HotelKeyless from "./pages/dashboard/hotel/KeylessAccess";
|
||||||
|
import HotelStaff from "./pages/dashboard/hotel/Staff";
|
||||||
|
// Restaurant pages
|
||||||
|
import RestaurantPOS_Terminal from "./pages/dashboard/restaurant/POSPage";
|
||||||
|
import RestaurantOrders from "./pages/dashboard/restaurant/Orders";
|
||||||
|
import RestaurantKitchen from "./pages/dashboard/restaurant/Kitchen";
|
||||||
|
import RestaurantBills from "./pages/dashboard/restaurant/Bills";
|
||||||
|
import RestaurantTables from "./pages/dashboard/restaurant/Tables";
|
||||||
|
import RestaurantMenu from "./pages/dashboard/restaurant/Menu";
|
||||||
|
import RestaurantInventory from "./pages/dashboard/restaurant/Inventory";
|
||||||
|
import RestaurantStaff from "./pages/dashboard/restaurant/Staff";
|
||||||
import NotFound from "./pages/NotFound";
|
import NotFound from "./pages/NotFound";
|
||||||
|
|
||||||
const queryClient = new QueryClient();
|
const queryClient = new QueryClient();
|
||||||
@@ -249,6 +264,48 @@ const AppRouter = () => (
|
|||||||
</DashboardLayout>
|
</DashboardLayout>
|
||||||
</ProtectedRoute>
|
</ProtectedRoute>
|
||||||
} />
|
} />
|
||||||
|
<Route path="/dashboard/hotel" element={
|
||||||
|
<ProtectedRoute>
|
||||||
|
<DashboardLayout>
|
||||||
|
<HotelManagement />
|
||||||
|
</DashboardLayout>
|
||||||
|
</ProtectedRoute>
|
||||||
|
} />
|
||||||
|
<Route path="/dashboard/hotel/rooms" element={
|
||||||
|
<ProtectedRoute>
|
||||||
|
<DashboardLayout>
|
||||||
|
<HotelRooms />
|
||||||
|
</DashboardLayout>
|
||||||
|
</ProtectedRoute>
|
||||||
|
} />
|
||||||
|
<Route path="/dashboard/hotel/checkin" element={
|
||||||
|
<ProtectedRoute>
|
||||||
|
<DashboardLayout>
|
||||||
|
<HotelCheckIn />
|
||||||
|
</DashboardLayout>
|
||||||
|
</ProtectedRoute>
|
||||||
|
} />
|
||||||
|
<Route path="/dashboard/hotel/room-service" element={
|
||||||
|
<ProtectedRoute>
|
||||||
|
<DashboardLayout>
|
||||||
|
<HotelRoomService />
|
||||||
|
</DashboardLayout>
|
||||||
|
</ProtectedRoute>
|
||||||
|
} />
|
||||||
|
<Route path="/dashboard/hotel/keyless" element={
|
||||||
|
<ProtectedRoute>
|
||||||
|
<DashboardLayout>
|
||||||
|
<HotelKeyless />
|
||||||
|
</DashboardLayout>
|
||||||
|
</ProtectedRoute>
|
||||||
|
} />
|
||||||
|
<Route path="/dashboard/hotel/staff" element={
|
||||||
|
<ProtectedRoute>
|
||||||
|
<DashboardLayout>
|
||||||
|
<HotelStaff />
|
||||||
|
</DashboardLayout>
|
||||||
|
</ProtectedRoute>
|
||||||
|
} />
|
||||||
<Route path="/dashboard/restaurant-pos" element={
|
<Route path="/dashboard/restaurant-pos" element={
|
||||||
<ProtectedRoute>
|
<ProtectedRoute>
|
||||||
<DashboardLayout>
|
<DashboardLayout>
|
||||||
@@ -256,6 +313,69 @@ const AppRouter = () => (
|
|||||||
</DashboardLayout>
|
</DashboardLayout>
|
||||||
</ProtectedRoute>
|
</ProtectedRoute>
|
||||||
} />
|
} />
|
||||||
|
<Route path="/dashboard/restaurant" element={
|
||||||
|
<ProtectedRoute>
|
||||||
|
<DashboardLayout>
|
||||||
|
<RestaurantPOS />
|
||||||
|
</DashboardLayout>
|
||||||
|
</ProtectedRoute>
|
||||||
|
} />
|
||||||
|
<Route path="/dashboard/restaurant/pos" element={
|
||||||
|
<ProtectedRoute>
|
||||||
|
<DashboardLayout>
|
||||||
|
<RestaurantPOS_Terminal />
|
||||||
|
</DashboardLayout>
|
||||||
|
</ProtectedRoute>
|
||||||
|
} />
|
||||||
|
<Route path="/dashboard/restaurant/orders" element={
|
||||||
|
<ProtectedRoute>
|
||||||
|
<DashboardLayout>
|
||||||
|
<RestaurantOrders />
|
||||||
|
</DashboardLayout>
|
||||||
|
</ProtectedRoute>
|
||||||
|
} />
|
||||||
|
<Route path="/dashboard/restaurant/kitchen" element={
|
||||||
|
<ProtectedRoute>
|
||||||
|
<DashboardLayout>
|
||||||
|
<RestaurantKitchen />
|
||||||
|
</DashboardLayout>
|
||||||
|
</ProtectedRoute>
|
||||||
|
} />
|
||||||
|
<Route path="/dashboard/restaurant/bills" element={
|
||||||
|
<ProtectedRoute>
|
||||||
|
<DashboardLayout>
|
||||||
|
<RestaurantBills />
|
||||||
|
</DashboardLayout>
|
||||||
|
</ProtectedRoute>
|
||||||
|
} />
|
||||||
|
<Route path="/dashboard/restaurant/tables" element={
|
||||||
|
<ProtectedRoute>
|
||||||
|
<DashboardLayout>
|
||||||
|
<RestaurantTables />
|
||||||
|
</DashboardLayout>
|
||||||
|
</ProtectedRoute>
|
||||||
|
} />
|
||||||
|
<Route path="/dashboard/restaurant/menu" element={
|
||||||
|
<ProtectedRoute>
|
||||||
|
<DashboardLayout>
|
||||||
|
<RestaurantMenu />
|
||||||
|
</DashboardLayout>
|
||||||
|
</ProtectedRoute>
|
||||||
|
} />
|
||||||
|
<Route path="/dashboard/restaurant/inventory" element={
|
||||||
|
<ProtectedRoute>
|
||||||
|
<DashboardLayout>
|
||||||
|
<RestaurantInventory />
|
||||||
|
</DashboardLayout>
|
||||||
|
</ProtectedRoute>
|
||||||
|
} />
|
||||||
|
<Route path="/dashboard/restaurant/staff" element={
|
||||||
|
<ProtectedRoute>
|
||||||
|
<DashboardLayout>
|
||||||
|
<RestaurantStaff />
|
||||||
|
</DashboardLayout>
|
||||||
|
</ProtectedRoute>
|
||||||
|
} />
|
||||||
<Route path="/dashboard/personalization" element={
|
<Route path="/dashboard/personalization" element={
|
||||||
<ProtectedRoute>
|
<ProtectedRoute>
|
||||||
<DashboardLayout>
|
<DashboardLayout>
|
||||||
|
|||||||
@@ -39,7 +39,14 @@ import {
|
|||||||
ChevronRight,
|
ChevronRight,
|
||||||
Hotel,
|
Hotel,
|
||||||
UtensilsCrossed,
|
UtensilsCrossed,
|
||||||
Brain
|
Brain,
|
||||||
|
DoorOpen,
|
||||||
|
BellRing,
|
||||||
|
Key,
|
||||||
|
Receipt,
|
||||||
|
ChefHat,
|
||||||
|
Grid3x3,
|
||||||
|
Package
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
|
|
||||||
const DashboardLayout = ({ children }: { children: React.ReactNode }) => {
|
const DashboardLayout = ({ children }: { children: React.ReactNode }) => {
|
||||||
@@ -60,10 +67,35 @@ const DashboardLayout = ({ children }: { children: React.ReactNode }) => {
|
|||||||
|
|
||||||
const menuItems = [
|
const menuItems = [
|
||||||
{ icon: Home, label: 'Dashboard', path: '/dashboard' },
|
{ icon: Home, label: 'Dashboard', path: '/dashboard' },
|
||||||
{ icon: Settings, label: 'Admin Panel', path: '/dashboard/admin' },
|
{ icon: Settings, label: 'Admin Panel', path: '/dashboard/admin', hasSubmenu: true },
|
||||||
{ icon: Plus, label: 'Channel Manager', path: '/dashboard/channel-manager' },
|
{ icon: Plus, label: 'Channel Manager', path: '/dashboard/channel-manager', hasSubmenu: true },
|
||||||
{ icon: Hotel, label: 'Hotel Management', path: '/dashboard/hotel-management' },
|
{
|
||||||
{ icon: UtensilsCrossed, label: 'Restaurant POS', path: '/dashboard/restaurant-pos' },
|
icon: Hotel,
|
||||||
|
label: 'Hotel Management',
|
||||||
|
path: '/dashboard/hotel',
|
||||||
|
subItems: [
|
||||||
|
{ icon: Home, label: 'Habitaciones', path: '/dashboard/hotel/rooms' },
|
||||||
|
{ icon: DoorOpen, label: 'Check-in', path: '/dashboard/hotel/checkin' },
|
||||||
|
{ icon: BellRing, label: 'Room Service', path: '/dashboard/hotel/room-service' },
|
||||||
|
{ icon: Key, label: 'Acceso', path: '/dashboard/hotel/keyless' },
|
||||||
|
{ icon: Users, label: 'Personal', path: '/dashboard/hotel/staff' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: UtensilsCrossed,
|
||||||
|
label: 'Restaurant POS',
|
||||||
|
path: '/dashboard/restaurant',
|
||||||
|
subItems: [
|
||||||
|
{ icon: CreditCard, label: 'POS Terminal', path: '/dashboard/restaurant/pos' },
|
||||||
|
{ icon: Receipt, label: 'Pedidos', path: '/dashboard/restaurant/orders' },
|
||||||
|
{ icon: ChefHat, label: 'Cocina', path: '/dashboard/restaurant/kitchen' },
|
||||||
|
{ icon: Receipt, label: 'Cuentas', path: '/dashboard/restaurant/bills' },
|
||||||
|
{ icon: Grid3x3, label: 'Mesas', path: '/dashboard/restaurant/tables' },
|
||||||
|
{ icon: UtensilsCrossed, label: 'Menú', path: '/dashboard/restaurant/menu' },
|
||||||
|
{ icon: Package, label: 'Inventario', path: '/dashboard/restaurant/inventory' },
|
||||||
|
{ icon: Users, label: 'Personal', path: '/dashboard/restaurant/staff' }
|
||||||
|
]
|
||||||
|
},
|
||||||
{ icon: Brain, label: 'Personalization', path: '/dashboard/personalization' },
|
{ icon: Brain, label: 'Personalization', path: '/dashboard/personalization' },
|
||||||
{ icon: Wallet, label: 'Wallet', path: '/dashboard/wallet' },
|
{ icon: Wallet, label: 'Wallet', path: '/dashboard/wallet' },
|
||||||
{ icon: MessageSquare, label: 'Message', path: '/dashboard/messages', badge: '2' },
|
{ icon: MessageSquare, label: 'Message', path: '/dashboard/messages', badge: '2' },
|
||||||
@@ -168,37 +200,74 @@ const DashboardLayout = ({ children }: { children: React.ReactNode }) => {
|
|||||||
<div className="space-y-1 pr-8">
|
<div className="space-y-1 pr-8">
|
||||||
{menuItems.map((item) => {
|
{menuItems.map((item) => {
|
||||||
const Icon = item.icon;
|
const Icon = item.icon;
|
||||||
const isActive = location.pathname === item.path;
|
const isActive = location.pathname === item.path || location.pathname.startsWith(item.path + '/');
|
||||||
const isAdminPanel = item.path === '/dashboard/admin';
|
const isAdminPanel = item.path === '/dashboard/admin';
|
||||||
const isChannelManager = item.path === '/dashboard/channel-manager';
|
const isChannelManager = item.path === '/dashboard/channel-manager';
|
||||||
|
const hasDirectSubItems = item.subItems && item.subItems.length > 0;
|
||||||
|
const isExpanded = expandedItems[item.path] || (hasDirectSubItems && item.subItems.some(sub => location.pathname === sub.path));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={item.path}>
|
<div key={item.path}>
|
||||||
<Link
|
<div className={`flex items-center justify-between ${sidebarCollapsed ? '' : 'pr-2'}`}>
|
||||||
to={item.path}
|
<Link
|
||||||
className={`flex items-center space-x-3 px-7 py-2.5 rounded-none transition-all border-l-4 ${
|
to={item.path}
|
||||||
isActive
|
className={`flex items-center space-x-3 px-7 py-2.5 rounded-none transition-all border-l-4 flex-1 ${
|
||||||
? 'text-white border-l-4 rounded-r-full'
|
isActive
|
||||||
: 'text-gray-700 hover:text-red-500 border-transparent rounded-r-full'
|
? 'text-white border-l-4 rounded-r-full'
|
||||||
} ${sidebarCollapsed ? 'justify-center px-2' : ''}`}
|
: 'text-gray-700 hover:text-red-500 border-transparent rounded-r-full'
|
||||||
style={{
|
} ${sidebarCollapsed ? 'justify-center px-2' : ''}`}
|
||||||
backgroundColor: isActive ? 'rgba(248, 69, 37, 1)' : 'transparent',
|
style={{
|
||||||
borderLeftColor: isActive ? '#F84525' : 'transparent',
|
backgroundColor: isActive ? 'rgba(248, 69, 37, 1)' : 'transparent',
|
||||||
color: isActive ? '#F84525' : '#433c3a'
|
borderLeftColor: isActive ? '#F84525' : 'transparent',
|
||||||
}}
|
color: isActive ? '#F84525' : '#433c3a'
|
||||||
>
|
}}
|
||||||
<Icon className="w-5 h-5 flex-shrink-0" />
|
>
|
||||||
{!sidebarCollapsed && (
|
<Icon className="w-5 h-5 flex-shrink-0" />
|
||||||
<div className="flex items-center justify-between w-full">
|
{!sidebarCollapsed && (
|
||||||
<span className="font-medium">{item.label}</span>
|
<div className="flex items-center justify-between w-full">
|
||||||
{item.badge && (
|
<span className="font-medium">{item.label}</span>
|
||||||
<span className="bg-green-500 text-white text-xs px-2 py-0.5 rounded-full">
|
{item.badge && (
|
||||||
{item.badge}
|
<span className="bg-green-500 text-white text-xs px-2 py-0.5 rounded-full">
|
||||||
</span>
|
{item.badge}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Link>
|
||||||
|
{!sidebarCollapsed && hasDirectSubItems && (
|
||||||
|
<button
|
||||||
|
onClick={() => toggleExpanded(item.path)}
|
||||||
|
className="p-1 hover:bg-gray-200 rounded mr-2"
|
||||||
|
>
|
||||||
|
{isExpanded ? (
|
||||||
|
<ChevronDown className="w-3 h-3" />
|
||||||
|
) : (
|
||||||
|
<ChevronRight className="w-3 h-3" />
|
||||||
)}
|
)}
|
||||||
</div>
|
</button>
|
||||||
)}
|
)}
|
||||||
</Link>
|
</div>
|
||||||
|
|
||||||
|
{/* Direct sub-items (Hotel & Restaurant) */}
|
||||||
|
{!sidebarCollapsed && hasDirectSubItems && isExpanded && (
|
||||||
|
<div className="mt-1 ml-10 space-y-1">
|
||||||
|
{item.subItems.map((sub) => {
|
||||||
|
const SubIcon = sub.icon;
|
||||||
|
const activeSubPath = location.pathname === sub.path;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
key={sub.path}
|
||||||
|
to={sub.path}
|
||||||
|
className={`flex items-center space-x-2 px-3 py-2 rounded-md text-sm ${activeSubPath ? 'bg-orange-50 text-orange-800' : 'text-gray-600 hover:text-orange-600 hover:bg-gray-50'}`}
|
||||||
|
>
|
||||||
|
<SubIcon className="w-4 h-4" />
|
||||||
|
<span>{sub.label}</span>
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Channel Manager submenus */}
|
{/* Channel Manager submenus */}
|
||||||
{!sidebarCollapsed && isChannelManager && location.pathname.startsWith('/dashboard/channel-manager') && (
|
{!sidebarCollapsed && isChannelManager && location.pathname.startsWith('/dashboard/channel-manager') && (
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import React, { useState } from 'react';
|
import { Link } from 'react-router-dom';
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
import { Card, CardContent } from '@/components/ui/card';
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
|
||||||
import { Badge } from '@/components/ui/badge';
|
import { Badge } from '@/components/ui/badge';
|
||||||
import { Button } from '@/components/ui/button';
|
|
||||||
import {
|
import {
|
||||||
Hotel,
|
Hotel,
|
||||||
DoorOpen,
|
DoorOpen,
|
||||||
@@ -10,24 +8,12 @@ import {
|
|||||||
QrCode,
|
QrCode,
|
||||||
Users,
|
Users,
|
||||||
Bed,
|
Bed,
|
||||||
Calendar,
|
|
||||||
Clock,
|
|
||||||
CheckCircle,
|
|
||||||
AlertCircle,
|
|
||||||
Sparkles,
|
Sparkles,
|
||||||
UtensilsCrossed,
|
ArrowRight,
|
||||||
Key
|
Key
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import RoomManagement from '@/components/hotel/RoomManagement';
|
|
||||||
import CheckInSystem from '@/components/hotel/CheckInSystem';
|
|
||||||
import RoomService from '@/components/hotel/RoomService';
|
|
||||||
import KeylessEntry from '@/components/hotel/KeylessEntry';
|
|
||||||
import StaffManagement from '@/components/hotel/StaffManagement';
|
|
||||||
|
|
||||||
const HotelManagement = () => {
|
const HotelManagement = () => {
|
||||||
const [activeTab, setActiveTab] = useState('overview');
|
|
||||||
|
|
||||||
// Stats de ejemplo
|
|
||||||
const stats = {
|
const stats = {
|
||||||
totalRooms: 120,
|
totalRooms: 120,
|
||||||
occupied: 85,
|
occupied: 85,
|
||||||
@@ -41,8 +27,46 @@ const HotelManagement = () => {
|
|||||||
|
|
||||||
const occupancyRate = ((stats.occupied / stats.totalRooms) * 100).toFixed(1);
|
const occupancyRate = ((stats.occupied / stats.totalRooms) * 100).toFixed(1);
|
||||||
|
|
||||||
|
const sections = [
|
||||||
|
{
|
||||||
|
title: 'Gestión de Habitaciones',
|
||||||
|
description: 'Administra el estado y disponibilidad de habitaciones',
|
||||||
|
icon: Bed,
|
||||||
|
path: '/dashboard/hotel/rooms',
|
||||||
|
color: 'blue'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Check-in Digital',
|
||||||
|
description: 'Sistema de check-in automático sin contacto',
|
||||||
|
icon: DoorOpen,
|
||||||
|
path: '/dashboard/hotel/checkin',
|
||||||
|
color: 'green'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Room Service',
|
||||||
|
description: 'Gestión de pedidos de servicio a habitación',
|
||||||
|
icon: BellRing,
|
||||||
|
path: '/dashboard/hotel/room-service',
|
||||||
|
color: 'purple'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Acceso sin Llave',
|
||||||
|
description: 'Códigos QR y PINs para acceso a habitaciones',
|
||||||
|
icon: Key,
|
||||||
|
path: '/dashboard/hotel/keyless',
|
||||||
|
color: 'orange'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Gestión de Personal',
|
||||||
|
description: 'Administra el equipo del hotel por departamentos',
|
||||||
|
icon: Users,
|
||||||
|
path: '/dashboard/hotel/staff',
|
||||||
|
color: 'indigo'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-gradient-to-br from-blue-50 via-white to-purple-50 p-6">
|
<div className="container mx-auto p-6 space-y-6">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="mb-8">
|
<div className="mb-8">
|
||||||
<div className="flex items-center gap-3 mb-2">
|
<div className="flex items-center gap-3 mb-2">
|
||||||
@@ -50,237 +74,100 @@ const HotelManagement = () => {
|
|||||||
<Hotel className="w-6 h-6 text-white" />
|
<Hotel className="w-6 h-6 text-white" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h1 className="text-3xl font-bold text-gray-900">Hotel Management</h1>
|
<h1 className="text-3xl font-bold">Hotel Management</h1>
|
||||||
<p className="text-gray-600">Sistema integral de gestión hotelera</p>
|
<p className="text-muted-foreground">Sistema integral de gestión hotelera</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Overview Stats */}
|
{/* Overview Stats */}
|
||||||
{activeTab === 'overview' && (
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
|
<Card className="border-l-4 border-l-blue-500">
|
||||||
<Card className="border-l-4 border-l-blue-500">
|
<CardContent className="p-6">
|
||||||
<CardContent className="p-6">
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex items-center justify-between">
|
<div>
|
||||||
<div>
|
<p className="text-sm text-muted-foreground mb-1">Ocupación</p>
|
||||||
<p className="text-sm text-gray-600 mb-1">Ocupación</p>
|
<p className="text-2xl font-bold">{occupancyRate}%</p>
|
||||||
<p className="text-2xl font-bold text-gray-900">{occupancyRate}%</p>
|
<p className="text-xs text-muted-foreground">{stats.occupied}/{stats.totalRooms} habitaciones</p>
|
||||||
<p className="text-xs text-gray-500">{stats.occupied}/{stats.totalRooms} habitaciones</p>
|
|
||||||
</div>
|
|
||||||
<div className="w-12 h-12 rounded-full bg-blue-100 flex items-center justify-center">
|
|
||||||
<Bed className="w-6 h-6 text-blue-600" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
<div className="w-12 h-12 rounded-full bg-blue-100 flex items-center justify-center">
|
||||||
</Card>
|
<Bed className="w-6 h-6 text-blue-600" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
<Card className="border-l-4 border-l-green-500">
|
<Card className="border-l-4 border-l-green-500">
|
||||||
<CardContent className="p-6">
|
<CardContent className="p-6">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm text-gray-600 mb-1">Check-ins Hoy</p>
|
<p className="text-sm text-muted-foreground mb-1">Check-ins Hoy</p>
|
||||||
<p className="text-2xl font-bold text-gray-900">{stats.checkInsToday}</p>
|
<p className="text-2xl font-bold">{stats.checkInsToday}</p>
|
||||||
<p className="text-xs text-gray-500">{stats.checkOutsToday} check-outs</p>
|
<p className="text-xs text-muted-foreground">{stats.checkOutsToday} check-outs</p>
|
||||||
</div>
|
|
||||||
<div className="w-12 h-12 rounded-full bg-green-100 flex items-center justify-center">
|
|
||||||
<DoorOpen className="w-6 h-6 text-green-600" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
<div className="w-12 h-12 rounded-full bg-green-100 flex items-center justify-center">
|
||||||
</Card>
|
<DoorOpen className="w-6 h-6 text-green-600" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
<Card className="border-l-4 border-l-purple-500">
|
<Card className="border-l-4 border-l-purple-500">
|
||||||
<CardContent className="p-6">
|
<CardContent className="p-6">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm text-gray-600 mb-1">Room Service</p>
|
<p className="text-sm text-muted-foreground mb-1">Room Service</p>
|
||||||
<p className="text-2xl font-bold text-gray-900">{stats.roomServiceOrders}</p>
|
<p className="text-2xl font-bold">{stats.roomServiceOrders}</p>
|
||||||
<p className="text-xs text-gray-500">Pedidos activos</p>
|
<p className="text-xs text-muted-foreground">Pedidos activos</p>
|
||||||
</div>
|
|
||||||
<div className="w-12 h-12 rounded-full bg-purple-100 flex items-center justify-center">
|
|
||||||
<BellRing className="w-6 h-6 text-purple-600" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
<div className="w-12 h-12 rounded-full bg-purple-100 flex items-center justify-center">
|
||||||
</Card>
|
<BellRing className="w-6 h-6 text-purple-600" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
<Card className="border-l-4 border-l-orange-500">
|
<Card className="border-l-4 border-l-orange-500">
|
||||||
<CardContent className="p-6">
|
<CardContent className="p-6">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm text-gray-600 mb-1">Ingresos Hoy</p>
|
<p className="text-sm text-muted-foreground mb-1">Ingresos Hoy</p>
|
||||||
<p className="text-2xl font-bold text-gray-900">${stats.revenue.toLocaleString()}</p>
|
<p className="text-2xl font-bold">${stats.revenue.toLocaleString()}</p>
|
||||||
<p className="text-xs text-green-600">+12% vs ayer</p>
|
<p className="text-xs text-green-600">+12% vs ayer</p>
|
||||||
</div>
|
|
||||||
<div className="w-12 h-12 rounded-full bg-orange-100 flex items-center justify-center">
|
|
||||||
<Sparkles className="w-6 h-6 text-orange-600" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
<div className="w-12 h-12 rounded-full bg-orange-100 flex items-center justify-center">
|
||||||
</Card>
|
<Sparkles className="w-6 h-6 text-orange-600" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Sections Grid */}
|
||||||
|
<div>
|
||||||
|
<h2 className="text-xl font-semibold mb-4">Módulos del Sistema</h2>
|
||||||
|
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
|
||||||
|
{sections.map((section) => {
|
||||||
|
const Icon = section.icon;
|
||||||
|
return (
|
||||||
|
<Link key={section.path} to={section.path}>
|
||||||
|
<Card className="hover:shadow-lg transition-shadow cursor-pointer h-full">
|
||||||
|
<CardContent className="p-6">
|
||||||
|
<div className="flex items-start justify-between mb-4">
|
||||||
|
<div className={`w-12 h-12 rounded-lg bg-${section.color}-100 flex items-center justify-center`}>
|
||||||
|
<Icon className={`w-6 h-6 text-${section.color}-600`} />
|
||||||
|
</div>
|
||||||
|
<ArrowRight className="w-5 h-5 text-muted-foreground" />
|
||||||
|
</div>
|
||||||
|
<h3 className="font-semibold text-lg mb-2">{section.title}</h3>
|
||||||
|
<p className="text-sm text-muted-foreground">{section.description}</p>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
)}
|
</div>
|
||||||
|
|
||||||
{/* Main Content Tabs */}
|
|
||||||
<Tabs value={activeTab} onValueChange={setActiveTab} className="space-y-6">
|
|
||||||
<TabsList className="grid w-full grid-cols-6 lg:w-auto lg:inline-grid">
|
|
||||||
<TabsTrigger value="overview" className="flex items-center gap-2">
|
|
||||||
<Hotel className="w-4 h-4" />
|
|
||||||
<span className="hidden sm:inline">Resumen</span>
|
|
||||||
</TabsTrigger>
|
|
||||||
<TabsTrigger value="rooms" className="flex items-center gap-2">
|
|
||||||
<Bed className="w-4 h-4" />
|
|
||||||
<span className="hidden sm:inline">Habitaciones</span>
|
|
||||||
</TabsTrigger>
|
|
||||||
<TabsTrigger value="checkin" className="flex items-center gap-2">
|
|
||||||
<QrCode className="w-4 h-4" />
|
|
||||||
<span className="hidden sm:inline">Check-in</span>
|
|
||||||
</TabsTrigger>
|
|
||||||
<TabsTrigger value="roomservice" className="flex items-center gap-2">
|
|
||||||
<UtensilsCrossed className="w-4 h-4" />
|
|
||||||
<span className="hidden sm:inline">Room Service</span>
|
|
||||||
</TabsTrigger>
|
|
||||||
<TabsTrigger value="keyless" className="flex items-center gap-2">
|
|
||||||
<Key className="w-4 h-4" />
|
|
||||||
<span className="hidden sm:inline">Acceso</span>
|
|
||||||
</TabsTrigger>
|
|
||||||
<TabsTrigger value="staff" className="flex items-center gap-2">
|
|
||||||
<Users className="w-4 h-4" />
|
|
||||||
<span className="hidden sm:inline">Personal</span>
|
|
||||||
</TabsTrigger>
|
|
||||||
</TabsList>
|
|
||||||
|
|
||||||
<TabsContent value="overview" className="space-y-6">
|
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
||||||
{/* Habitaciones por Estado */}
|
|
||||||
<Card>
|
|
||||||
<CardHeader>
|
|
||||||
<CardTitle className="flex items-center gap-2">
|
|
||||||
<Bed className="w-5 h-5" />
|
|
||||||
Estado de Habitaciones
|
|
||||||
</CardTitle>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<div className="space-y-4">
|
|
||||||
<div className="flex items-center justify-between p-3 bg-green-50 rounded-lg">
|
|
||||||
<div className="flex items-center gap-3">
|
|
||||||
<div className="w-3 h-3 rounded-full bg-green-500"></div>
|
|
||||||
<span className="font-medium">Disponibles</span>
|
|
||||||
</div>
|
|
||||||
<Badge variant="secondary">{stats.available}</Badge>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center justify-between p-3 bg-blue-50 rounded-lg">
|
|
||||||
<div className="flex items-center gap-3">
|
|
||||||
<div className="w-3 h-3 rounded-full bg-blue-500"></div>
|
|
||||||
<span className="font-medium">Ocupadas</span>
|
|
||||||
</div>
|
|
||||||
<Badge variant="secondary">{stats.occupied}</Badge>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center justify-between p-3 bg-orange-50 rounded-lg">
|
|
||||||
<div className="flex items-center gap-3">
|
|
||||||
<div className="w-3 h-3 rounded-full bg-orange-500"></div>
|
|
||||||
<span className="font-medium">Mantenimiento</span>
|
|
||||||
</div>
|
|
||||||
<Badge variant="secondary">{stats.maintenance}</Badge>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
{/* Check-ins Pendientes */}
|
|
||||||
<Card>
|
|
||||||
<CardHeader>
|
|
||||||
<CardTitle className="flex items-center gap-2">
|
|
||||||
<Calendar className="w-5 h-5" />
|
|
||||||
Check-ins de Hoy
|
|
||||||
</CardTitle>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<div className="space-y-3">
|
|
||||||
{[1, 2, 3].map((i) => (
|
|
||||||
<div key={i} className="flex items-center justify-between p-3 border rounded-lg hover:bg-gray-50 transition-colors">
|
|
||||||
<div>
|
|
||||||
<p className="font-medium">Habitación {100 + i}</p>
|
|
||||||
<p className="text-sm text-gray-600">Reserva #{1234 + i} - 2 huéspedes</p>
|
|
||||||
</div>
|
|
||||||
<div className="text-right">
|
|
||||||
<p className="text-sm font-medium">14:00</p>
|
|
||||||
<Badge variant="outline" className="mt-1">Pendiente</Badge>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
<Button className="w-full mt-4" variant="outline">
|
|
||||||
Ver Todos los Check-ins
|
|
||||||
</Button>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Quick Actions */}
|
|
||||||
<Card>
|
|
||||||
<CardHeader>
|
|
||||||
<CardTitle>Acciones Rápidas</CardTitle>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
className="h-24 flex-col gap-2"
|
|
||||||
onClick={() => setActiveTab('checkin')}
|
|
||||||
>
|
|
||||||
<QrCode className="w-6 h-6" />
|
|
||||||
<span>Nuevo Check-in</span>
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
className="h-24 flex-col gap-2"
|
|
||||||
onClick={() => setActiveTab('rooms')}
|
|
||||||
>
|
|
||||||
<Bed className="w-6 h-6" />
|
|
||||||
<span>Gestionar Habitaciones</span>
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
className="h-24 flex-col gap-2"
|
|
||||||
onClick={() => setActiveTab('roomservice')}
|
|
||||||
>
|
|
||||||
<UtensilsCrossed className="w-6 h-6" />
|
|
||||||
<span>Room Service</span>
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
className="h-24 flex-col gap-2"
|
|
||||||
onClick={() => setActiveTab('keyless')}
|
|
||||||
>
|
|
||||||
<Key className="w-6 h-6" />
|
|
||||||
<span>Acceso Digital</span>
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</TabsContent>
|
|
||||||
|
|
||||||
<TabsContent value="rooms">
|
|
||||||
<RoomManagement />
|
|
||||||
</TabsContent>
|
|
||||||
|
|
||||||
<TabsContent value="checkin">
|
|
||||||
<CheckInSystem />
|
|
||||||
</TabsContent>
|
|
||||||
|
|
||||||
<TabsContent value="roomservice">
|
|
||||||
<RoomService />
|
|
||||||
</TabsContent>
|
|
||||||
|
|
||||||
<TabsContent value="keyless">
|
|
||||||
<KeylessEntry />
|
|
||||||
</TabsContent>
|
|
||||||
|
|
||||||
<TabsContent value="staff">
|
|
||||||
<StaffManagement />
|
|
||||||
</TabsContent>
|
|
||||||
</Tabs>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,20 +1,70 @@
|
|||||||
import { useState } from 'react';
|
import { Link } from 'react-router-dom';
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
import { Card, CardContent } from '@/components/ui/card';
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
import { UtensilsCrossed, QrCode, ChefHat, Receipt, CreditCard, Package, Users as UsersIcon, ArrowRight } from 'lucide-react';
|
||||||
import { UtensilsCrossed, QrCode, ChefHat, Receipt } from 'lucide-react';
|
|
||||||
import DigitalMenu from '@/components/restaurant/DigitalMenu';
|
|
||||||
import TableOrders from '@/components/restaurant/TableOrders';
|
|
||||||
import KitchenDisplay from '@/components/restaurant/KitchenDisplay';
|
|
||||||
import BillManagement from '@/components/restaurant/BillManagement';
|
|
||||||
import TableConfiguration from '@/components/restaurant/TableConfiguration';
|
|
||||||
import InventoryManagement from '@/components/restaurant/InventoryManagement';
|
|
||||||
import POSTerminal from '@/components/restaurant/POSTerminal';
|
|
||||||
import StaffManagement from '@/components/restaurant/StaffManagement';
|
|
||||||
|
|
||||||
const RestaurantPOS = () => {
|
const RestaurantPOS = () => {
|
||||||
const [activeOrders] = useState(12);
|
const activeOrders = 12;
|
||||||
const [pendingKitchen] = useState(8);
|
const pendingKitchen = 8;
|
||||||
const [dailyRevenue] = useState(4280);
|
const dailyRevenue = 4280;
|
||||||
|
|
||||||
|
const sections = [
|
||||||
|
{
|
||||||
|
title: 'Terminal POS',
|
||||||
|
description: 'Sistema de punto de venta completo',
|
||||||
|
icon: CreditCard,
|
||||||
|
path: '/dashboard/restaurant/pos',
|
||||||
|
color: 'green'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Pedidos en Mesa',
|
||||||
|
description: 'Gestiona pedidos de todas las mesas',
|
||||||
|
icon: Receipt,
|
||||||
|
path: '/dashboard/restaurant/orders',
|
||||||
|
color: 'blue'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Display de Cocina',
|
||||||
|
description: 'Vista de pedidos para el equipo de cocina',
|
||||||
|
icon: ChefHat,
|
||||||
|
path: '/dashboard/restaurant/kitchen',
|
||||||
|
color: 'orange'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Gestión de Cuentas',
|
||||||
|
description: 'Split bill, propinas y cierre de cuentas',
|
||||||
|
icon: Receipt,
|
||||||
|
path: '/dashboard/restaurant/bills',
|
||||||
|
color: 'purple'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Configuración de Mesas',
|
||||||
|
description: 'Gestiona el layout y estado de las mesas',
|
||||||
|
icon: QrCode,
|
||||||
|
path: '/dashboard/restaurant/tables',
|
||||||
|
color: 'indigo'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Menú Digital',
|
||||||
|
description: 'Gestiona platos y genera códigos QR',
|
||||||
|
icon: UtensilsCrossed,
|
||||||
|
path: '/dashboard/restaurant/menu',
|
||||||
|
color: 'red'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Inventario',
|
||||||
|
description: 'Control de stock y reposición de productos',
|
||||||
|
icon: Package,
|
||||||
|
path: '/dashboard/restaurant/inventory',
|
||||||
|
color: 'yellow'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Personal del Restaurante',
|
||||||
|
description: 'Administra tu equipo de trabajo',
|
||||||
|
icon: UsersIcon,
|
||||||
|
path: '/dashboard/restaurant/staff',
|
||||||
|
color: 'teal'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container mx-auto p-6 space-y-6">
|
<div className="container mx-auto p-6 space-y-6">
|
||||||
@@ -33,164 +83,76 @@ const RestaurantPOS = () => {
|
|||||||
{/* Stats Overview */}
|
{/* Stats Overview */}
|
||||||
<div className="grid gap-4 md:grid-cols-3">
|
<div className="grid gap-4 md:grid-cols-3">
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
<CardContent className="p-6">
|
||||||
<CardTitle className="text-sm font-medium">Pedidos Activos</CardTitle>
|
<div className="flex items-center justify-between">
|
||||||
<Receipt className="h-4 w-4 text-muted-foreground" />
|
<div>
|
||||||
</CardHeader>
|
<p className="text-sm text-muted-foreground mb-1">Pedidos Activos</p>
|
||||||
<CardContent>
|
<p className="text-2xl font-bold">{activeOrders}</p>
|
||||||
<div className="text-2xl font-bold">{activeOrders}</div>
|
<p className="text-xs text-muted-foreground">En proceso ahora</p>
|
||||||
<p className="text-xs text-muted-foreground">En proceso ahora</p>
|
</div>
|
||||||
|
<div className="w-12 h-12 rounded-full bg-blue-100 flex items-center justify-center">
|
||||||
|
<Receipt className="w-6 h-6 text-blue-600" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
<CardContent className="p-6">
|
||||||
<CardTitle className="text-sm font-medium">En Cocina</CardTitle>
|
<div className="flex items-center justify-between">
|
||||||
<ChefHat className="h-4 w-4 text-muted-foreground" />
|
<div>
|
||||||
</CardHeader>
|
<p className="text-sm text-muted-foreground mb-1">En Cocina</p>
|
||||||
<CardContent>
|
<p className="text-2xl font-bold">{pendingKitchen}</p>
|
||||||
<div className="text-2xl font-bold">{pendingKitchen}</div>
|
<p className="text-xs text-muted-foreground">Preparando</p>
|
||||||
<p className="text-xs text-muted-foreground">Preparando</p>
|
</div>
|
||||||
|
<div className="w-12 h-12 rounded-full bg-orange-100 flex items-center justify-center">
|
||||||
|
<ChefHat className="w-6 h-6 text-orange-600" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
<CardContent className="p-6">
|
||||||
<CardTitle className="text-sm font-medium">Ventas del Día</CardTitle>
|
<div className="flex items-center justify-between">
|
||||||
<QrCode className="h-4 w-4 text-muted-foreground" />
|
<div>
|
||||||
</CardHeader>
|
<p className="text-sm text-muted-foreground mb-1">Ventas del Día</p>
|
||||||
<CardContent>
|
<p className="text-2xl font-bold">${dailyRevenue.toLocaleString()}</p>
|
||||||
<div className="text-2xl font-bold">${dailyRevenue.toLocaleString()}</div>
|
<p className="text-xs text-green-600">+12% vs ayer</p>
|
||||||
<p className="text-xs text-muted-foreground">+12% vs ayer</p>
|
</div>
|
||||||
|
<div className="w-12 h-12 rounded-full bg-green-100 flex items-center justify-center">
|
||||||
|
<QrCode className="w-6 h-6 text-green-600" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Main Content */}
|
{/* Sections Grid */}
|
||||||
<Tabs defaultValue="pos" className="space-y-4">
|
<div>
|
||||||
<TabsList className="grid w-full grid-cols-8">
|
<h2 className="text-xl font-semibold mb-4">Módulos del Sistema</h2>
|
||||||
<TabsTrigger value="pos">POS</TabsTrigger>
|
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
|
||||||
<TabsTrigger value="orders">Pedidos</TabsTrigger>
|
{sections.map((section) => {
|
||||||
<TabsTrigger value="kitchen">Cocina</TabsTrigger>
|
const Icon = section.icon;
|
||||||
<TabsTrigger value="bills">Cuentas</TabsTrigger>
|
return (
|
||||||
<TabsTrigger value="tables">Mesas</TabsTrigger>
|
<Link key={section.path} to={section.path}>
|
||||||
<TabsTrigger value="menu">Menú</TabsTrigger>
|
<Card className="hover:shadow-lg transition-shadow cursor-pointer h-full">
|
||||||
<TabsTrigger value="inventory">Inventario</TabsTrigger>
|
<CardContent className="p-6">
|
||||||
<TabsTrigger value="staff">Personal</TabsTrigger>
|
<div className="flex items-start justify-between mb-4">
|
||||||
</TabsList>
|
<div className={`w-12 h-12 rounded-lg bg-${section.color}-100 flex items-center justify-center`}>
|
||||||
|
<Icon className={`w-6 h-6 text-${section.color}-600`} />
|
||||||
<TabsContent value="pos" className="space-y-4">
|
</div>
|
||||||
<Card>
|
<ArrowRight className="w-5 h-5 text-muted-foreground" />
|
||||||
<CardHeader>
|
</div>
|
||||||
<CardTitle>Terminal Punto de Venta</CardTitle>
|
<h3 className="font-semibold mb-2">{section.title}</h3>
|
||||||
<CardDescription>
|
<p className="text-sm text-muted-foreground">{section.description}</p>
|
||||||
Sistema POS completo conectado con inventario
|
</CardContent>
|
||||||
</CardDescription>
|
</Card>
|
||||||
</CardHeader>
|
</Link>
|
||||||
<CardContent>
|
);
|
||||||
<POSTerminal />
|
})}
|
||||||
</CardContent>
|
</div>
|
||||||
</Card>
|
</div>
|
||||||
</TabsContent>
|
|
||||||
|
|
||||||
<TabsContent value="menu" className="space-y-4">
|
|
||||||
<Card>
|
|
||||||
<CardHeader>
|
|
||||||
<CardTitle>Gestión de Menú y Platos</CardTitle>
|
|
||||||
<CardDescription>
|
|
||||||
Configura tu menú y genera códigos QR para las mesas
|
|
||||||
</CardDescription>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<DigitalMenu />
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</TabsContent>
|
|
||||||
|
|
||||||
<TabsContent value="orders" className="space-y-4">
|
|
||||||
<Card>
|
|
||||||
<CardHeader>
|
|
||||||
<CardTitle>Sistema de Pedidos en Mesa</CardTitle>
|
|
||||||
<CardDescription>
|
|
||||||
Gestiona pedidos de todas las mesas en tiempo real
|
|
||||||
</CardDescription>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<TableOrders />
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</TabsContent>
|
|
||||||
|
|
||||||
<TabsContent value="kitchen" className="space-y-4">
|
|
||||||
<Card>
|
|
||||||
<CardHeader>
|
|
||||||
<CardTitle>Display de Cocina</CardTitle>
|
|
||||||
<CardDescription>
|
|
||||||
Vista de pedidos para el equipo de cocina
|
|
||||||
</CardDescription>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<KitchenDisplay />
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</TabsContent>
|
|
||||||
|
|
||||||
<TabsContent value="bills" className="space-y-4">
|
|
||||||
<Card>
|
|
||||||
<CardHeader>
|
|
||||||
<CardTitle>Gestión de Cuentas</CardTitle>
|
|
||||||
<CardDescription>
|
|
||||||
Split bill, propinas y cierre de cuentas
|
|
||||||
</CardDescription>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<BillManagement />
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</TabsContent>
|
|
||||||
|
|
||||||
<TabsContent value="tables" className="space-y-4">
|
|
||||||
<Card>
|
|
||||||
<CardHeader>
|
|
||||||
<CardTitle>Configuración de Mesas</CardTitle>
|
|
||||||
<CardDescription>
|
|
||||||
Gestiona el layout y estado de las mesas del restaurante
|
|
||||||
</CardDescription>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<TableConfiguration />
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</TabsContent>
|
|
||||||
|
|
||||||
<TabsContent value="inventory" className="space-y-4">
|
|
||||||
<Card>
|
|
||||||
<CardHeader>
|
|
||||||
<CardTitle>Gestión de Inventario</CardTitle>
|
|
||||||
<CardDescription>
|
|
||||||
Control de stock, alertas y reposición de productos
|
|
||||||
</CardDescription>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<InventoryManagement />
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</TabsContent>
|
|
||||||
|
|
||||||
<TabsContent value="staff" className="space-y-4">
|
|
||||||
<Card>
|
|
||||||
<CardHeader>
|
|
||||||
<CardTitle>Gestión de Personal</CardTitle>
|
|
||||||
<CardDescription>
|
|
||||||
Administra tu equipo de restaurante
|
|
||||||
</CardDescription>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<StaffManagement />
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</TabsContent>
|
|
||||||
</Tabs>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
12
src/pages/dashboard/hotel/CheckIn.tsx
Normal file
12
src/pages/dashboard/hotel/CheckIn.tsx
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import CheckInSystem from '@/components/hotel/CheckInSystem';
|
||||||
|
|
||||||
|
const CheckIn = () => {
|
||||||
|
return (
|
||||||
|
<div className="container mx-auto p-6">
|
||||||
|
<h1 className="text-3xl font-bold mb-6">Check-in Digital</h1>
|
||||||
|
<CheckInSystem />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CheckIn;
|
||||||
12
src/pages/dashboard/hotel/KeylessAccess.tsx
Normal file
12
src/pages/dashboard/hotel/KeylessAccess.tsx
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import KeylessEntry from '@/components/hotel/KeylessEntry';
|
||||||
|
|
||||||
|
const KeylessAccess = () => {
|
||||||
|
return (
|
||||||
|
<div className="container mx-auto p-6">
|
||||||
|
<h1 className="text-3xl font-bold mb-6">Acceso sin Llave</h1>
|
||||||
|
<KeylessEntry />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default KeylessAccess;
|
||||||
12
src/pages/dashboard/hotel/RoomServicePage.tsx
Normal file
12
src/pages/dashboard/hotel/RoomServicePage.tsx
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import RoomService from '@/components/hotel/RoomService';
|
||||||
|
|
||||||
|
const RoomServicePage = () => {
|
||||||
|
return (
|
||||||
|
<div className="container mx-auto p-6">
|
||||||
|
<h1 className="text-3xl font-bold mb-6">Room Service</h1>
|
||||||
|
<RoomService />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RoomServicePage;
|
||||||
11
src/pages/dashboard/hotel/Rooms.tsx
Normal file
11
src/pages/dashboard/hotel/Rooms.tsx
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import RoomManagement from '@/components/hotel/RoomManagement';
|
||||||
|
|
||||||
|
const Rooms = () => {
|
||||||
|
return (
|
||||||
|
<div className="container mx-auto p-6">
|
||||||
|
<RoomManagement />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Rooms;
|
||||||
12
src/pages/dashboard/hotel/Staff.tsx
Normal file
12
src/pages/dashboard/hotel/Staff.tsx
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import StaffManagement from '@/components/hotel/StaffManagement';
|
||||||
|
|
||||||
|
const Staff = () => {
|
||||||
|
return (
|
||||||
|
<div className="container mx-auto p-6">
|
||||||
|
<h1 className="text-3xl font-bold mb-6">Personal del Hotel</h1>
|
||||||
|
<StaffManagement />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Staff;
|
||||||
12
src/pages/dashboard/restaurant/Bills.tsx
Normal file
12
src/pages/dashboard/restaurant/Bills.tsx
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import BillManagement from '@/components/restaurant/BillManagement';
|
||||||
|
|
||||||
|
const Bills = () => {
|
||||||
|
return (
|
||||||
|
<div className="container mx-auto p-6">
|
||||||
|
<h1 className="text-3xl font-bold mb-6">Gestión de Cuentas</h1>
|
||||||
|
<BillManagement />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Bills;
|
||||||
12
src/pages/dashboard/restaurant/Inventory.tsx
Normal file
12
src/pages/dashboard/restaurant/Inventory.tsx
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import InventoryManagement from '@/components/restaurant/InventoryManagement';
|
||||||
|
|
||||||
|
const Inventory = () => {
|
||||||
|
return (
|
||||||
|
<div className="container mx-auto p-6">
|
||||||
|
<h1 className="text-3xl font-bold mb-6">Gestión de Inventario</h1>
|
||||||
|
<InventoryManagement />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Inventory;
|
||||||
12
src/pages/dashboard/restaurant/Kitchen.tsx
Normal file
12
src/pages/dashboard/restaurant/Kitchen.tsx
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import KitchenDisplay from '@/components/restaurant/KitchenDisplay';
|
||||||
|
|
||||||
|
const Kitchen = () => {
|
||||||
|
return (
|
||||||
|
<div className="container mx-auto p-6">
|
||||||
|
<h1 className="text-3xl font-bold mb-6">Display de Cocina</h1>
|
||||||
|
<KitchenDisplay />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Kitchen;
|
||||||
12
src/pages/dashboard/restaurant/Menu.tsx
Normal file
12
src/pages/dashboard/restaurant/Menu.tsx
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import DigitalMenu from '@/components/restaurant/DigitalMenu';
|
||||||
|
|
||||||
|
const Menu = () => {
|
||||||
|
return (
|
||||||
|
<div className="container mx-auto p-6">
|
||||||
|
<h1 className="text-3xl font-bold mb-6">Menú Digital</h1>
|
||||||
|
<DigitalMenu />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Menu;
|
||||||
12
src/pages/dashboard/restaurant/Orders.tsx
Normal file
12
src/pages/dashboard/restaurant/Orders.tsx
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import TableOrders from '@/components/restaurant/TableOrders';
|
||||||
|
|
||||||
|
const Orders = () => {
|
||||||
|
return (
|
||||||
|
<div className="container mx-auto p-6">
|
||||||
|
<h1 className="text-3xl font-bold mb-6">Pedidos en Mesa</h1>
|
||||||
|
<TableOrders />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Orders;
|
||||||
12
src/pages/dashboard/restaurant/POSPage.tsx
Normal file
12
src/pages/dashboard/restaurant/POSPage.tsx
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import POSTerminal from '@/components/restaurant/POSTerminal';
|
||||||
|
|
||||||
|
const POSPage = () => {
|
||||||
|
return (
|
||||||
|
<div className="container mx-auto p-6">
|
||||||
|
<h1 className="text-3xl font-bold mb-6">Terminal POS</h1>
|
||||||
|
<POSTerminal />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default POSPage;
|
||||||
12
src/pages/dashboard/restaurant/Staff.tsx
Normal file
12
src/pages/dashboard/restaurant/Staff.tsx
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import StaffManagement from '@/components/restaurant/StaffManagement';
|
||||||
|
|
||||||
|
const Staff = () => {
|
||||||
|
return (
|
||||||
|
<div className="container mx-auto p-6">
|
||||||
|
<h1 className="text-3xl font-bold mb-6">Personal del Restaurante</h1>
|
||||||
|
<StaffManagement />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Staff;
|
||||||
12
src/pages/dashboard/restaurant/Tables.tsx
Normal file
12
src/pages/dashboard/restaurant/Tables.tsx
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import TableConfiguration from '@/components/restaurant/TableConfiguration';
|
||||||
|
|
||||||
|
const Tables = () => {
|
||||||
|
return (
|
||||||
|
<div className="container mx-auto p-6">
|
||||||
|
<h1 className="text-3xl font-bold mb-6">Configuración de Mesas</h1>
|
||||||
|
<TableConfiguration />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Tables;
|
||||||
Reference in New Issue
Block a user