import { useState } from 'react' import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import { PlusIcon, PencilIcon, TrashIcon, MapPinIcon, BuildingOfficeIcon, WrenchScrewdriverIcon, ArchiveBoxIcon, TruckIcon, } from '@heroicons/react/24/outline' import clsx from 'clsx' import { poisApi } from '@/api' import { MapContainer } from '@/components/mapa' import POILayer from '@/components/mapa/POILayer' import Card from '@/components/ui/Card' import Button from '@/components/ui/Button' import Modal from '@/components/ui/Modal' import Input from '@/components/ui/Input' import Select from '@/components/ui/Select' import Table from '@/components/ui/Table' import { useToast } from '@/components/ui/Toast' import { POI } from '@/types' interface POIForm { nombre: string tipo: POI['tipo'] direccion: string lat: number | '' lng: number | '' telefono?: string notas?: string } const defaultForm: POIForm = { nombre: '', tipo: 'cliente', direccion: '', lat: '', lng: '', } const tipoIcons: Record = { cliente: , taller: , gasolinera: , almacen: , otro: , } const tipoColors: Record = { cliente: 'text-accent-400', taller: 'text-warning-400', gasolinera: 'text-success-400', almacen: 'text-purple-400', otro: 'text-slate-400', } export default function POIs() { const queryClient = useQueryClient() const toast = useToast() const [isModalOpen, setIsModalOpen] = useState(false) const [form, setForm] = useState(defaultForm) const [editingPOI, setEditingPOI] = useState(null) const [viewMode, setViewMode] = useState<'map' | 'table'>('map') const [filterTipo, setFilterTipo] = useState('') const { data: pois, isLoading } = useQuery({ queryKey: ['pois'], queryFn: () => poisApi.list(), }) const createMutation = useMutation({ mutationFn: poisApi.create, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['pois'] }) toast.success('Punto de interes creado') handleCloseModal() }, onError: () => { toast.error('Error al crear punto de interes') }, }) const updateMutation = useMutation({ mutationFn: ({ id, data }: { id: string; data: Partial }) => poisApi.update(id, data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['pois'] }) toast.success('Punto de interes actualizado') handleCloseModal() }, onError: () => { toast.error('Error al actualizar') }, }) const deleteMutation = useMutation({ mutationFn: poisApi.delete, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['pois'] }) toast.success('Punto de interes eliminado') }, onError: () => { toast.error('Error al eliminar') }, }) const handleCloseModal = () => { setIsModalOpen(false) setForm(defaultForm) setEditingPOI(null) } const handleNewPOI = () => { setForm(defaultForm) setEditingPOI(null) setIsModalOpen(true) } const handleEditPOI = (poi: POI) => { setForm({ nombre: poi.nombre, tipo: poi.tipo, direccion: poi.direccion, lat: poi.lat, lng: poi.lng, telefono: poi.telefono, notas: poi.notas, }) setEditingPOI(poi) setIsModalOpen(true) } const handleDeletePOI = (id: string) => { if (confirm('¿Estas seguro de eliminar este punto de interes?')) { deleteMutation.mutate(id) } } const handleMapClick = (lat: number, lng: number) => { if (isModalOpen) { setForm({ ...form, lat, lng }) } } const handleSubmit = (e: React.FormEvent) => { e.preventDefault() if (!form.nombre || !form.direccion) { toast.error('Completa los campos requeridos') return } if (form.lat === '' || form.lng === '') { toast.error('Selecciona una ubicacion en el mapa') return } const poiData = { nombre: form.nombre, tipo: form.tipo, direccion: form.direccion, lat: form.lat as number, lng: form.lng as number, telefono: form.telefono, notas: form.notas, } if (editingPOI) { updateMutation.mutate({ id: editingPOI.id, data: poiData }) } else { createMutation.mutate(poiData as Omit) } } const poisList = pois || [] const filteredPOIs = filterTipo ? poisList.filter((p) => p.tipo === filterTipo) : poisList const columns = [ { key: 'nombre', header: 'Nombre', render: (poi: POI) => (
{tipoIcons[poi.tipo]}

{poi.nombre}

{poi.tipo}

), }, { key: 'direccion', header: 'Direccion', render: (poi: POI) => {poi.direccion}, }, { key: 'telefono', header: 'Telefono', render: (poi: POI) => ( {poi.telefono || '-'} ), }, { key: 'coordenadas', header: 'Coordenadas', render: (poi: POI) => ( {poi.lat.toFixed(5)}, {poi.lng.toFixed(5)} ), }, { key: 'acciones', header: '', sortable: false, render: (poi: POI) => (
), }, ] // Stats by type const stats = { cliente: poisList.filter((p) => p.tipo === 'cliente').length, taller: poisList.filter((p) => p.tipo === 'taller').length, gasolinera: poisList.filter((p) => p.tipo === 'gasolinera').length, almacen: poisList.filter((p) => p.tipo === 'almacen').length, otro: poisList.filter((p) => p.tipo === 'otro').length, } return (
{/* Header */}

Puntos de Interes

Gestiona ubicaciones importantes para tu flota

{/* Stats */}
{Object.entries(stats).map(([tipo, count]) => ( setFilterTipo(filterTipo === tipo ? '' : tipo)} >
{tipoIcons[tipo as POI['tipo']]}

{count}

{tipo}

))}
{/* Content */} {viewMode === 'map' ? (
) : ( p.id} isLoading={isLoading} pagination pageSize={15} emptyMessage="No hay puntos de interes" /> )} {/* Create/Edit Modal */}
setForm({ ...form, nombre: e.target.value })} placeholder="Ej: Cliente ABC" /> setForm({ ...form, direccion: e.target.value })} placeholder="Ej: Av. Principal 123, Ciudad" /> setForm({ ...form, telefono: e.target.value })} placeholder="Ej: +52 555 123 4567" />