Add Commerce module and enhance Admin Panel sections

This commit is contained in:
gpt-engineer-app[bot]
2025-10-10 23:54:41 +00:00
parent 2f1f19b6f5
commit dd051b1e73
8 changed files with 821 additions and 7 deletions

View File

@@ -54,7 +54,8 @@ import {
Shield,
Radio,
Sparkles,
Leaf
Leaf,
Store
} from 'lucide-react';
const DashboardLayout = ({ children }: { children: React.ReactNode }) => {
@@ -159,6 +160,7 @@ const DashboardLayout = ({ children }: { children: React.ReactNode }) => {
{ icon: Shield, label: 'Security', path: '/dashboard/security' },
{ icon: Car, label: 'Vehicle Management', path: '/dashboard/vehicle-management' },
{ icon: Leaf, label: 'Sustainability', path: '/dashboard/sustainability' },
{ icon: Store, label: 'Comercios', path: '/dashboard/establishments' },
{ icon: Wallet, label: 'Wallet', path: '/dashboard/wallet' },
{ icon: MessageSquare, label: 'Message', path: '/dashboard/messages', badge: '2' },
];

View File

@@ -539,9 +539,93 @@ const ContentTab: React.FC<ContentTabProps> = ({ isSuperAdmin, activeSubTab = 'd
<TabsContent value="guides" className="space-y-4">
<div className="flex justify-between items-center">
<h3 className="text-lg font-semibold">Gestión de Guías Turísticos</h3>
<Badge variant="secondary" className="text-sm">
{Array.isArray(guides) ? guides.length : 0} Guías Registrados
</Badge>
<Dialog>
<DialogTrigger asChild>
<Button className="flex items-center gap-2">
<Plus className="w-4 h-4" />
Nuevo Guía
</Button>
</DialogTrigger>
<DialogContent className="max-w-2xl">
<DialogHeader>
<DialogTitle>Crear Nuevo Guía</DialogTitle>
</DialogHeader>
<div className="grid gap-4">
<div>
<Label>Número de Licencia</Label>
<Input
value={newGuide.licenseNumber}
onChange={(e) => setNewGuide({ ...newGuide, licenseNumber: e.target.value })}
placeholder="Ej: GUIDE-2024-001"
/>
</div>
<div>
<Label>Especialidades (separadas por coma)</Label>
<Input
value={newGuide.specialties.join(', ')}
onChange={(e) => setNewGuide({
...newGuide,
specialties: e.target.value.split(',').map(s => s.trim())
})}
placeholder="Historia, Naturaleza, Aventura"
/>
</div>
<div>
<Label>Idiomas (separados por coma)</Label>
<Input
value={newGuide.languages.join(', ')}
onChange={(e) => setNewGuide({
...newGuide,
languages: e.target.value.split(',').map(l => l.trim())
})}
placeholder="Español, Inglés, Francés"
/>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<Label>Tarifa por Hora ($)</Label>
<Input
type="number"
value={newGuide.hourlyRate}
onChange={(e) => setNewGuide({ ...newGuide, hourlyRate: parseFloat(e.target.value) || 0 })}
/>
</div>
<div>
<Label>Tarifa Diaria ($)</Label>
<Input
type="number"
value={newGuide.dailyRate}
onChange={(e) => setNewGuide({ ...newGuide, dailyRate: parseFloat(e.target.value) || 0 })}
/>
</div>
</div>
<div>
<Label>Biografía</Label>
<Textarea
value={newGuide.bio}
onChange={(e) => setNewGuide({ ...newGuide, bio: e.target.value })}
placeholder="Experiencia y descripción del guía..."
rows={3}
/>
</div>
<Button onClick={async () => {
try {
await apiClient.post('/tourism/guides', {
...newGuide,
userId: 1
});
setNewGuide({ licenseNumber: '', specialties: [''], languages: [''], hourlyRate: 0, dailyRate: 0, bio: '', certifications: {} });
loadData();
toast({ title: 'Guía creado', description: 'El guía se creó correctamente.' });
} catch (error: any) {
toast({ title: 'Error', description: error?.message || 'No se pudo crear el guía.' });
}
}}>
Crear Guía
</Button>
</div>
</DialogContent>
</Dialog>
</div>
<div className="grid gap-4">
@@ -565,6 +649,32 @@ const ContentTab: React.FC<ContentTabProps> = ({ isSuperAdmin, activeSubTab = 'd
<Badge variant={guide.isVerified ? "default" : "secondary"}>
{guide.isVerified ? 'Verificado' : 'Pendiente'}
</Badge>
{isSuperAdmin && (
<div className="flex gap-1">
<Button
variant="outline"
size="sm"
onClick={() => console.log('Edit guide:', guide.id)}
>
<Edit className="w-4 h-4" />
</Button>
<Button
variant="outline"
size="sm"
onClick={async () => {
try {
await apiClient.delete(`/tourism/guides/${guide.id}`);
loadData();
toast({ title: 'Guía eliminado', description: 'Se eliminó correctamente.' });
} catch (error) {
toast({ title: 'Error', description: 'No se pudo eliminar el guía.' });
}
}}
>
<Trash2 className="w-4 h-4" />
</Button>
</div>
)}
</div>
</CardHeader>
<CardContent>
@@ -589,9 +699,88 @@ const ContentTab: React.FC<ContentTabProps> = ({ isSuperAdmin, activeSubTab = 'd
<TabsContent value="taxis" className="space-y-4">
<div className="flex justify-between items-center">
<h3 className="text-lg font-semibold">Gestión de Taxis</h3>
<Badge variant="secondary" className="text-sm">
{Array.isArray(taxis) ? taxis.length : 0} Taxis Disponibles
</Badge>
<Dialog>
<DialogTrigger asChild>
<Button className="flex items-center gap-2">
<Plus className="w-4 h-4" />
Nuevo Taxi
</Button>
</DialogTrigger>
<DialogContent className="max-w-2xl">
<DialogHeader>
<DialogTitle>Registrar Nuevo Taxi</DialogTitle>
</DialogHeader>
<div className="grid gap-4">
<div>
<Label>Número de Licencia</Label>
<Input
value={newTaxi.licenseNumber}
onChange={(e) => setNewTaxi({ ...newTaxi, licenseNumber: e.target.value })}
placeholder="Ej: TAXI-2024-001"
/>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<Label>Placa del Vehículo</Label>
<Input
value={newTaxi.vehiclePlate}
onChange={(e) => setNewTaxi({ ...newTaxi, vehiclePlate: e.target.value })}
placeholder="ABC-123"
/>
</div>
<div>
<Label>Modelo</Label>
<Input
value={newTaxi.vehicleModel}
onChange={(e) => setNewTaxi({ ...newTaxi, vehicleModel: e.target.value })}
placeholder="Toyota Corolla"
/>
</div>
</div>
<div className="grid grid-cols-3 gap-4">
<div>
<Label>Año</Label>
<Input
type="number"
value={newTaxi.vehicleYear}
onChange={(e) => setNewTaxi({ ...newTaxi, vehicleYear: parseInt(e.target.value) || new Date().getFullYear() })}
/>
</div>
<div>
<Label>Color</Label>
<Input
value={newTaxi.vehicleColor}
onChange={(e) => setNewTaxi({ ...newTaxi, vehicleColor: e.target.value })}
placeholder="Blanco"
/>
</div>
<div>
<Label>Capacidad</Label>
<Input
type="number"
value={newTaxi.vehicleCapacity}
onChange={(e) => setNewTaxi({ ...newTaxi, vehicleCapacity: parseInt(e.target.value) || 4 })}
/>
</div>
</div>
<Button onClick={async () => {
try {
await apiClient.post('/tourism/taxis', {
...newTaxi,
userId: 1 // You should get this from auth
});
setNewTaxi({ licenseNumber: '', vehiclePlate: '', vehicleModel: '', vehicleYear: new Date().getFullYear(), vehicleColor: '', vehicleCapacity: 4 });
loadData();
toast({ title: 'Taxi registrado', description: 'El taxi se registró correctamente.' });
} catch (error: any) {
toast({ title: 'Error', description: error?.message || 'No se pudo registrar el taxi.' });
}
}}>
Registrar Taxi
</Button>
</div>
</DialogContent>
</Dialog>
</div>
<div className="grid gap-4">
@@ -615,6 +804,32 @@ const ContentTab: React.FC<ContentTabProps> = ({ isSuperAdmin, activeSubTab = 'd
<Badge variant={taxi.isAvailable ? "default" : "secondary"}>
{taxi.isAvailable ? 'Disponible' : 'Ocupado'}
</Badge>
{isSuperAdmin && (
<div className="flex gap-1">
<Button
variant="outline"
size="sm"
onClick={() => console.log('Edit taxi:', taxi.id)}
>
<Edit className="w-4 h-4" />
</Button>
<Button
variant="outline"
size="sm"
onClick={async () => {
try {
await apiClient.delete(`/tourism/taxis/${taxi.id}`);
loadData();
toast({ title: 'Taxi eliminado', description: 'Se eliminó correctamente.' });
} catch (error) {
toast({ title: 'Error', description: 'No se pudo eliminar el taxi.' });
}
}}
>
<Trash2 className="w-4 h-4" />
</Button>
</div>
)}
</div>
</CardHeader>
<CardContent>

View File

@@ -0,0 +1,85 @@
import React from 'react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { TrendingUp, Users, DollarSign, Eye } from 'lucide-react';
const BusinessAnalytics = () => {
return (
<div className="space-y-6">
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Total Comercios</CardTitle>
<TrendingUp className="h-4 w-4 text-blue-600" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">769</div>
<p className="text-xs text-gray-600 mt-1">+12% este mes</p>
</CardContent>
</Card>
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Visitas Totales</CardTitle>
<Eye className="h-4 w-4 text-purple-600" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">45.2K</div>
<p className="text-xs text-gray-600 mt-1">Este mes</p>
</CardContent>
</Card>
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Usuarios Activos</CardTitle>
<Users className="h-4 w-4 text-green-600" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">2,345</div>
<p className="text-xs text-gray-600 mt-1">Propietarios</p>
</CardContent>
</Card>
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Ingresos</CardTitle>
<DollarSign className="h-4 w-4 text-orange-600" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">$124K</div>
<p className="text-xs text-gray-600 mt-1">Este mes</p>
</CardContent>
</Card>
</div>
<Card>
<CardHeader>
<CardTitle>Comercios Más Populares</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-3">
{[
{ name: 'Restaurante El Faro', visits: '2.4K', category: 'Restaurante' },
{ name: 'Hotel Paradise', visits: '1.8K', category: 'Hotel' },
{ name: 'Boutique Fashion', visits: '1.5K', category: 'Tienda' },
{ name: 'Spa Wellness', visits: '1.2K', category: 'Servicios' },
{ name: 'Club Nocturno', visits: '980', category: 'Entretenimiento' }
].map((item, idx) => (
<div key={idx} className="flex items-center justify-between border-b pb-2">
<div>
<p className="font-medium">{item.name}</p>
<p className="text-sm text-gray-600">{item.category}</p>
</div>
<div className="text-right">
<p className="font-semibold">{item.visits}</p>
<p className="text-xs text-gray-600">visitas</p>
</div>
</div>
))}
</div>
</CardContent>
</Card>
</div>
);
};
export default BusinessAnalytics;

View File

@@ -0,0 +1,47 @@
import React from 'react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
import { UtensilsCrossed, Hotel, ShoppingBag, Music, Wrench, Building } from 'lucide-react';
const categories = [
{ id: 1, name: 'Restaurantes', icon: UtensilsCrossed, count: 145, color: 'bg-orange-100 text-orange-600' },
{ id: 2, name: 'Hoteles', icon: Hotel, count: 67, color: 'bg-blue-100 text-blue-600' },
{ id: 3, name: 'Tiendas', icon: ShoppingBag, count: 234, color: 'bg-purple-100 text-purple-600' },
{ id: 4, name: 'Entretenimiento', icon: Music, count: 89, color: 'bg-pink-100 text-pink-600' },
{ id: 5, name: 'Servicios', icon: Wrench, count: 156, color: 'bg-green-100 text-green-600' },
{ id: 6, name: 'Otros', icon: Building, count: 78, color: 'bg-gray-100 text-gray-600' }
];
const BusinessCategories = () => {
return (
<div className="space-y-6">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{categories.map((category) => {
const Icon = category.icon;
return (
<Card key={category.id} className="hover:shadow-lg transition-shadow cursor-pointer">
<CardHeader>
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
<div className={`w-12 h-12 rounded-lg ${category.color} flex items-center justify-center`}>
<Icon className="h-6 w-6" />
</div>
<CardTitle className="text-lg">{category.name}</CardTitle>
</div>
<Badge variant="secondary">{category.count}</Badge>
</div>
</CardHeader>
<CardContent>
<p className="text-sm text-gray-600">
{category.count} establecimientos registrados en esta categoría
</p>
</CardContent>
</Card>
);
})}
</div>
</div>
);
};
export default BusinessCategories;

View File

@@ -0,0 +1,306 @@
import React, { useState, useEffect } from 'react';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea';
import { Label } from '@/components/ui/label';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { Store, Plus, Edit, Trash2, MapPin, Phone, Globe, Clock, Star, Search } from 'lucide-react';
import { useToast } from '@/hooks/use-toast';
import { apiClient } from '@/services/adminApi';
const BusinessList = () => {
const [businesses, setBusinesses] = useState<any[]>([]);
const [loading, setLoading] = useState(false);
const [searchTerm, setSearchTerm] = useState('');
const { toast } = useToast();
const [newBusiness, setNewBusiness] = useState({
name: '',
description: '',
category: '',
address: '',
phone: '',
email: '',
website: '',
coordinates: { x: 0, y: 0 },
openingHours: {
monday: '9:00-18:00',
tuesday: '9:00-18:00',
wednesday: '9:00-18:00',
thursday: '9:00-18:00',
friday: '9:00-18:00',
saturday: '10:00-14:00',
sunday: 'Cerrado'
},
images: ['']
});
const loadBusinesses = async () => {
setLoading(true);
try {
const data = await apiClient.get('/establishments?page=1&limit=50');
setBusinesses(Array.isArray(data) ? data : (data as any)?.establishments || []);
} catch (error) {
console.error('Error loading businesses:', error);
} finally {
setLoading(false);
}
};
useEffect(() => {
loadBusinesses();
}, []);
const handleCreate = async () => {
try {
await apiClient.post('/establishments', {
...newBusiness,
coordinates: `(${newBusiness.coordinates.x},${newBusiness.coordinates.y})`,
images: newBusiness.images.filter(img => img.trim() !== '')
});
setNewBusiness({
name: '', description: '', category: '', address: '', phone: '', email: '', website: '',
coordinates: { x: 0, y: 0 }, images: [''],
openingHours: {
monday: '9:00-18:00', tuesday: '9:00-18:00', wednesday: '9:00-18:00',
thursday: '9:00-18:00', friday: '9:00-18:00', saturday: '10:00-14:00', sunday: 'Cerrado'
}
});
loadBusinesses();
toast({ title: 'Comercio creado', description: 'El establecimiento se creó correctamente.' });
} catch (error: any) {
toast({ title: 'Error', description: error?.message || 'No se pudo crear el comercio.' });
}
};
const handleDelete = async (id: string) => {
try {
await apiClient.delete(`/establishments/${id}`);
loadBusinesses();
toast({ title: 'Comercio eliminado', description: 'Se eliminó correctamente.' });
} catch (error) {
toast({ title: 'Error', description: 'No se pudo eliminar el comercio.' });
}
};
const filteredBusinesses = businesses.filter(b =>
b.name?.toLowerCase().includes(searchTerm.toLowerCase()) ||
b.category?.toLowerCase().includes(searchTerm.toLowerCase())
);
return (
<div className="space-y-6">
<div className="flex items-center justify-between gap-4">
<div className="relative flex-1 max-w-md">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" />
<Input
placeholder="Buscar comercios..."
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
className="pl-10"
/>
</div>
<Dialog>
<DialogTrigger asChild>
<Button>
<Plus className="h-4 w-4 mr-2" />
Nuevo Comercio
</Button>
</DialogTrigger>
<DialogContent className="max-w-3xl max-h-[90vh] overflow-y-auto">
<DialogHeader>
<DialogTitle>Registrar Nuevo Comercio</DialogTitle>
</DialogHeader>
<div className="grid gap-4">
<div className="grid grid-cols-2 gap-4">
<div>
<Label>Nombre del Comercio</Label>
<Input
value={newBusiness.name}
onChange={(e) => setNewBusiness({ ...newBusiness, name: e.target.value })}
placeholder="Restaurante El Caribe"
/>
</div>
<div>
<Label>Categoría</Label>
<Select value={newBusiness.category} onValueChange={(v) => setNewBusiness({ ...newBusiness, category: v })}>
<SelectTrigger>
<SelectValue placeholder="Selecciona categoría" />
</SelectTrigger>
<SelectContent>
<SelectItem value="restaurant">Restaurante</SelectItem>
<SelectItem value="hotel">Hotel</SelectItem>
<SelectItem value="store">Tienda</SelectItem>
<SelectItem value="entertainment">Entretenimiento</SelectItem>
<SelectItem value="services">Servicios</SelectItem>
</SelectContent>
</Select>
</div>
</div>
<div>
<Label>Descripción</Label>
<Textarea
value={newBusiness.description}
onChange={(e) => setNewBusiness({ ...newBusiness, description: e.target.value })}
placeholder="Describe el comercio..."
rows={3}
/>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<Label>Dirección</Label>
<Input
value={newBusiness.address}
onChange={(e) => setNewBusiness({ ...newBusiness, address: e.target.value })}
placeholder="Calle Principal #123"
/>
</div>
<div>
<Label>Teléfono</Label>
<Input
value={newBusiness.phone}
onChange={(e) => setNewBusiness({ ...newBusiness, phone: e.target.value })}
placeholder="+1 809-555-0123"
/>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<Label>Email</Label>
<Input
type="email"
value={newBusiness.email}
onChange={(e) => setNewBusiness({ ...newBusiness, email: e.target.value })}
placeholder="contacto@negocio.com"
/>
</div>
<div>
<Label>Sitio Web</Label>
<Input
value={newBusiness.website}
onChange={(e) => setNewBusiness({ ...newBusiness, website: e.target.value })}
placeholder="https://www.negocio.com"
/>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<Label>Latitud</Label>
<Input
type="number"
step="any"
value={newBusiness.coordinates.y}
onChange={(e) => setNewBusiness({
...newBusiness,
coordinates: { ...newBusiness.coordinates, y: parseFloat(e.target.value) || 0 }
})}
/>
</div>
<div>
<Label>Longitud</Label>
<Input
type="number"
step="any"
value={newBusiness.coordinates.x}
onChange={(e) => setNewBusiness({
...newBusiness,
coordinates: { ...newBusiness.coordinates, x: parseFloat(e.target.value) || 0 }
})}
/>
</div>
</div>
<div>
<Label>URLs de Imágenes (separadas por coma)</Label>
<Textarea
value={newBusiness.images.join(', ')}
onChange={(e) => setNewBusiness({
...newBusiness,
images: e.target.value.split(',').map(url => url.trim())
})}
placeholder="https://ejemplo.com/imagen1.jpg, https://ejemplo.com/imagen2.jpg"
rows={2}
/>
</div>
<Button onClick={handleCreate} className="w-full">
Crear Comercio
</Button>
</div>
</DialogContent>
</Dialog>
</div>
<div className="grid gap-4">
{filteredBusinesses.map((business) => (
<Card key={business.id} className="hover:shadow-lg transition-shadow">
<CardHeader>
<div className="flex items-start justify-between">
<div className="flex items-center gap-4">
<div className="w-16 h-16 rounded-lg bg-orange-100 flex items-center justify-center">
<Store className="h-8 w-8 text-orange-600" />
</div>
<div>
<CardTitle>{business.name}</CardTitle>
<CardDescription className="flex items-center gap-2 mt-1">
<Badge variant="outline">{business.category}</Badge>
{business.isVerified && (
<Badge className="bg-green-100 text-green-800">Verificado</Badge>
)}
</CardDescription>
</div>
</div>
<div className="flex items-center gap-2">
<Badge variant="outline" className="flex items-center gap-1">
<Star className="h-3 w-3 fill-yellow-500 text-yellow-500" />
{business.rating || '4.5'}
</Badge>
<Button variant="outline" size="sm" onClick={() => console.log('Edit:', business.id)}>
<Edit className="h-4 w-4" />
</Button>
<Button variant="outline" size="sm" onClick={() => handleDelete(business.id)}>
<Trash2 className="h-4 w-4" />
</Button>
</div>
</div>
</CardHeader>
<CardContent>
<p className="text-sm text-gray-600 mb-4">{business.description}</p>
<div className="grid grid-cols-2 gap-3 text-sm">
<div className="flex items-center gap-2 text-gray-600">
<MapPin className="h-4 w-4" />
{business.address || 'Sin dirección'}
</div>
<div className="flex items-center gap-2 text-gray-600">
<Phone className="h-4 w-4" />
{business.phone || 'Sin teléfono'}
</div>
{business.website && (
<div className="flex items-center gap-2 text-gray-600">
<Globe className="h-4 w-4" />
<a href={business.website} target="_blank" rel="noopener noreferrer" className="text-blue-600 hover:underline">
Sitio web
</a>
</div>
)}
<div className="flex items-center gap-2 text-gray-600">
<Clock className="h-4 w-4" />
{business.isOpen ? 'Abierto' : 'Cerrado'}
</div>
</div>
</CardContent>
</Card>
))}
</div>
</div>
);
};
export default BusinessList;

View File

@@ -0,0 +1,98 @@
import React from 'react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { CheckCircle, XCircle, Clock, FileText } from 'lucide-react';
const pendingVerifications = [
{ id: 1, name: 'Restaurante La Marina', category: 'Restaurante', submitted: '2025-10-08', documents: 3 },
{ id: 2, name: 'Hotel Vista Mar', category: 'Hotel', submitted: '2025-10-09', documents: 5 },
{ id: 3, name: 'Boutique Fashion', category: 'Tienda', submitted: '2025-10-10', documents: 2 }
];
const BusinessVerification = () => {
return (
<div className="space-y-6">
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Pendientes</CardTitle>
<Clock className="h-4 w-4 text-yellow-600" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">12</div>
<p className="text-xs text-gray-600 mt-1">Solicitudes por revisar</p>
</CardContent>
</Card>
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Aprobados</CardTitle>
<CheckCircle className="h-4 w-4 text-green-600" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">245</div>
<p className="text-xs text-gray-600 mt-1">Comercios verificados</p>
</CardContent>
</Card>
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Rechazados</CardTitle>
<XCircle className="h-4 w-4 text-red-600" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">8</div>
<p className="text-xs text-gray-600 mt-1">Este mes</p>
</CardContent>
</Card>
</div>
<Card>
<CardHeader>
<CardTitle>Solicitudes Pendientes</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-4">
{pendingVerifications.map((item) => (
<div key={item.id} className="border rounded-lg p-4 flex items-center justify-between">
<div className="flex items-center gap-4">
<div className="w-12 h-12 rounded-lg bg-yellow-100 flex items-center justify-center">
<FileText className="h-6 w-6 text-yellow-600" />
</div>
<div>
<h3 className="font-semibold">{item.name}</h3>
<div className="flex items-center gap-2 mt-1">
<Badge variant="outline" className="text-xs">{item.category}</Badge>
<span className="text-xs text-gray-600">
Enviado: {item.submitted}
</span>
<span className="text-xs text-gray-600">
{item.documents} documentos
</span>
</div>
</div>
</div>
<div className="flex gap-2">
<Button size="sm" variant="outline">
Revisar
</Button>
<Button size="sm" variant="default" className="bg-green-600 hover:bg-green-700">
<CheckCircle className="h-4 w-4 mr-1" />
Aprobar
</Button>
<Button size="sm" variant="destructive">
<XCircle className="h-4 w-4 mr-1" />
Rechazar
</Button>
</div>
</div>
))}
</div>
</CardContent>
</Card>
</div>
);
};
export default BusinessVerification;