| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484 |
- "use client"
- import { useState } from 'react'
- import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
- import { Button } from "@/components/ui/button"
- import { Input } from "@/components/ui/input"
- import { Label } from "@/components/ui/label"
- import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
- import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"
- import { Badge } from "@/components/ui/badge"
- import { Switch } from "@/components/ui/switch"
- import { useConfiguracionesTributarias } from '@/hooks/useConfiguracionesTributarias'
- import { Plus, Edit, Trash2, Save, RotateCcw } from 'lucide-react'
- export function ConfiguracionTributariaManager() {
- const {
- configuraciones,
- loading,
- error,
- createConfiguracion,
- updateConfiguracion,
- deleteConfiguracion,
- incrementarSecuencial,
- reiniciarSecuencial,
- } = useConfiguracionesTributarias()
- const [editingConfig, setEditingConfig] = useState<string | null>(null)
- const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false)
- const [isResetDialogOpen, setIsResetDialogOpen] = useState(false)
- const [resetConfigId, setResetConfigId] = useState<string | null>(null)
- const [resetSecuencial, setResetSecuencial] = useState('')
- const [formData, setFormData] = useState({
- ambiente: '1',
- tipoEmision: '1',
- razonSocial: '',
- nombreComercial: '',
- ruc: '',
- dirMatriz: '',
- estab: '001',
- ptoEmi: '001',
- secuencial: '000000001',
- activo: true,
- })
- const resetForm = () => {
- setFormData({
- ambiente: '1',
- tipoEmision: '1',
- razonSocial: '',
- nombreComercial: '',
- ruc: '',
- dirMatriz: '',
- estab: '001',
- ptoEmi: '001',
- secuencial: '000000001',
- activo: true,
- })
- }
- const handleCreate = async () => {
- try {
- await createConfiguracion(formData)
- setIsCreateDialogOpen(false)
- resetForm()
- } catch (error) {
- console.error('Error creating configuration:', error)
- }
- }
- const handleUpdate = async (id: string) => {
- try {
- await updateConfiguracion(id, formData)
- setEditingConfig(null)
- resetForm()
- } catch (error) {
- console.error('Error updating configuration:', error)
- }
- }
- const handleDelete = async (id: string) => {
- if (confirm('¿Está seguro de que desea eliminar esta configuración?')) {
- try {
- await deleteConfiguracion(id)
- } catch (error) {
- console.error('Error deleting configuration:', error)
- }
- }
- }
- const handleIncrementSecuencial = async (id: string) => {
- try {
- await incrementarSecuencial(id)
- } catch (error) {
- console.error('Error incrementing secuencial:', error)
- }
- }
- const handleResetSecuencial = (id: string, currentSecuencial: string) => {
- setResetConfigId(id)
- setResetSecuencial(currentSecuencial)
- setIsResetDialogOpen(true)
- }
- const confirmResetSecuencial = async () => {
- if (!resetConfigId || !resetSecuencial) return
- try {
- await reiniciarSecuencial(resetConfigId, resetSecuencial)
- setIsResetDialogOpen(false)
- setResetConfigId(null)
- setResetSecuencial('')
- } catch (error) {
- console.error('Error resetting secuencial:', error)
- }
- }
- const cancelReset = () => {
- setIsResetDialogOpen(false)
- setResetConfigId(null)
- setResetSecuencial('')
- }
- const startEdit = (config: any) => {
- setEditingConfig(config.id)
- setFormData({
- ambiente: config.ambiente,
- tipoEmision: config.tipoEmision,
- razonSocial: config.razonSocial,
- nombreComercial: config.nombreComercial,
- ruc: config.ruc,
- dirMatriz: config.dirMatriz,
- estab: config.estab,
- ptoEmi: config.ptoEmi,
- secuencial: config.secuencial,
- activo: config.activo,
- })
- }
- const cancelEdit = () => {
- setEditingConfig(null)
- resetForm()
- }
- if (loading && configuraciones.length === 0) {
- return <div className="flex justify-center items-center h-64">Cargando...</div>
- }
- if (error) {
- return <div className="text-red-500 text-center p-4">Error: {error}</div>
- }
- return (
- <div className="space-y-6">
- <div className="flex justify-between items-center">
- <div>
- <h2 className="text-2xl font-bold">Configuraciones Tributarias</h2>
- <p className="mt-2 text-muted-foreground">Gestiona la información tributaria de tu empresa</p>
- </div>
-
- <Dialog open={isCreateDialogOpen} onOpenChange={setIsCreateDialogOpen}>
- <DialogTrigger asChild>
- <Button onClick={() => { resetForm(); setIsCreateDialogOpen(true); }}>
- <Plus className="w-4 h-4 mr-2" />
- Nueva Configuración
- </Button>
- </DialogTrigger>
- <DialogContent className="max-w-2xl max-h-[90vh] overflow-y-auto">
- <DialogHeader>
- <DialogTitle>Nueva Configuración Tributaria</DialogTitle>
- <DialogDescription>
- Ingresa los datos de la configuración tributaria
- </DialogDescription>
- </DialogHeader>
- <ConfiguracionForm
- formData={formData}
- setFormData={setFormData}
- onSave={handleCreate}
- onCancel={() => setIsCreateDialogOpen(false)}
- />
- </DialogContent>
- </Dialog>
- </div>
- <div className="grid gap-4">
- {configuraciones.map((config) => (
- <Card key={config.id}>
- <CardHeader>
- <div className="flex justify-between items-start">
- <div>
- <CardTitle className="flex items-center gap-2">
- {config.razonSocial}
- <Badge variant={config.activo ? "default" : "secondary"}>
- {config.activo ? "Activa" : "Inactiva"}
- </Badge>
- </CardTitle>
- <CardDescription>
- RUC: {config.ruc} | {config.nombreComercial}
- </CardDescription>
- </div>
- <div className="flex gap-2">
- {editingConfig === config.id ? (
- <>
- <Button
- size="sm"
- onClick={() => handleUpdate(config.id)}
- disabled={loading}
- >
- <Save className="w-4 h-4" />
- </Button>
- <Button
- size="sm"
- variant="outline"
- onClick={cancelEdit}
- disabled={loading}
- >
- Cancelar
- </Button>
- </>
- ) : (
- <>
- <Button
- size="sm"
- variant="outline"
- onClick={() => startEdit(config)}
- >
- <Edit className="w-4 h-4" />
- </Button>
- <Button
- size="sm"
- variant="outline"
- onClick={() => handleIncrementSecuencial(config.id)}
- disabled={loading}
- >
- + Secuencial
- </Button>
- <Button
- size="sm"
- variant="outline"
- onClick={() => handleResetSecuencial(config.id, config.secuencial)}
- disabled={loading}
- >
- <RotateCcw className="w-4 h-4" />
- </Button>
- <Button
- size="sm"
- variant="destructive"
- onClick={() => handleDelete(config.id)}
- disabled={loading}
- >
- <Trash2 className="w-4 h-4" />
- </Button>
- </>
- )}
- </div>
- </div>
- </CardHeader>
- <CardContent>
- {editingConfig === config.id ? (
- <ConfiguracionForm
- formData={formData}
- setFormData={setFormData}
- onSave={() => handleUpdate(config.id)}
- onCancel={cancelEdit}
- isEdit
- />
- ) : (
- <div className="grid grid-cols-2 md:grid-cols-4 gap-4 text-sm">
- <div>
- <Label className="text-gray-600">Ambiente</Label>
- <p>{config.ambiente === '1' ? 'Pruebas' : 'Producción'}</p>
- </div>
- <div>
- <Label className="text-gray-600">Establecimiento</Label>
- <p>{config.estab}</p>
- </div>
- <div>
- <Label className="text-gray-600">Punto Emisión</Label>
- <p>{config.ptoEmi}</p>
- </div>
- <div>
- <Label className="text-gray-600">Secuencial</Label>
- <p>{config.secuencial}</p>
- </div>
- <div className="col-span-2 md:col-span-4">
- <Label className="text-gray-600">Dirección Matriz</Label>
- <p>{config.dirMatriz}</p>
- </div>
- </div>
- )}
- </CardContent>
- </Card>
- ))}
-
- {configuraciones.length === 0 && !loading && (
- <Card>
- <CardContent className="text-center py-8">
- <p className="text-gray-500">No hay configuraciones tributarias registradas</p>
- <Button
- className="mt-4"
- onClick={() => setIsCreateDialogOpen(true)}
- >
- <Plus className="w-4 h-4 mr-2" />
- Crear Primera Configuración
- </Button>
- </CardContent>
- </Card>
- )}
- </div>
- {/* Diálogo para reiniciar secuencial */}
- <Dialog open={isResetDialogOpen} onOpenChange={setIsResetDialogOpen}>
- <DialogContent>
- <DialogHeader>
- <DialogTitle>Reiniciar Secuencial</DialogTitle>
- <DialogDescription>
- Ingresa el nuevo número de secuencial para esta configuración.
- </DialogDescription>
- </DialogHeader>
- <div className="space-y-4">
- <div className="space-y-2">
- <Label htmlFor="resetSecuencial">Nuevo Secuencial</Label>
- <Input
- id="resetSecuencial"
- value={resetSecuencial}
- onChange={(e) => setResetSecuencial(e.target.value)}
- placeholder="000000001"
- maxLength={9}
- />
- <p className="text-sm text-gray-500">
- Ingresa un número entre 0 y 999999999. El sistema lo formateará automáticamente.
- </p>
- </div>
- <div className="flex justify-end gap-2">
- <Button variant="outline" onClick={cancelReset}>
- Cancelar
- </Button>
- <Button
- onClick={confirmResetSecuencial}
- disabled={!resetSecuencial || loading}
- >
- Reiniciar
- </Button>
- </div>
- </div>
- </DialogContent>
- </Dialog>
- </div>
- )
- }
- interface ConfiguracionFormProps {
- formData: any
- setFormData: (data: any) => void
- onSave: () => void
- onCancel: () => void
- isEdit?: boolean
- }
- function ConfiguracionForm({ formData, setFormData, onSave, onCancel, isEdit = false }: ConfiguracionFormProps) {
- return (
- <div className="space-y-4">
- <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
- <div className="space-y-2">
- <Label htmlFor="ambiente">Ambiente</Label>
- <Select value={formData.ambiente} onValueChange={(value) => setFormData({ ...formData, ambiente: value })}>
- <SelectTrigger>
- <SelectValue />
- </SelectTrigger>
- <SelectContent>
- <SelectItem value="1">1 - Pruebas</SelectItem>
- <SelectItem value="2">2 - Producción</SelectItem>
- </SelectContent>
- </Select>
- </div>
-
- <div className="space-y-2">
- <Label htmlFor="tipoEmision">Tipo Emisión</Label>
- <Select value={formData.tipoEmision} onValueChange={(value) => setFormData({ ...formData, tipoEmision: value })}>
- <SelectTrigger>
- <SelectValue />
- </SelectTrigger>
- <SelectContent>
- <SelectItem value="1">1 - Normal</SelectItem>
- </SelectContent>
- </Select>
- </div>
-
- <div className="space-y-2">
- <Label htmlFor="ruc">RUC *</Label>
- <Input
- id="ruc"
- value={formData.ruc}
- onChange={(e) => setFormData({ ...formData, ruc: e.target.value })}
- placeholder="13 dígitos"
- maxLength={13}
- />
- </div>
-
- <div className="space-y-2">
- <Label htmlFor="razonSocial">Razón Social *</Label>
- <Input
- id="razonSocial"
- value={formData.razonSocial}
- onChange={(e) => setFormData({ ...formData, razonSocial: e.target.value })}
- placeholder="Empresa S.A."
- />
- </div>
-
- <div className="space-y-2">
- <Label htmlFor="nombreComercial">Nombre Comercial *</Label>
- <Input
- id="nombreComercial"
- value={formData.nombreComercial}
- onChange={(e) => setFormData({ ...formData, nombreComercial: e.target.value })}
- placeholder="Nombre Comercial"
- />
- </div>
-
- <div className="space-y-2">
- <Label htmlFor="estab">Establecimiento</Label>
- <Input
- id="estab"
- value={formData.estab}
- onChange={(e) => setFormData({ ...formData, estab: e.target.value })}
- placeholder="001"
- maxLength={3}
- />
- </div>
-
- <div className="space-y-2">
- <Label htmlFor="ptoEmi">Punto Emisión</Label>
- <Input
- id="ptoEmi"
- value={formData.ptoEmi}
- onChange={(e) => setFormData({ ...formData, ptoEmi: e.target.value })}
- placeholder="001"
- maxLength={3}
- />
- </div>
-
- <div className="space-y-2">
- <Label htmlFor="secuencial">Secuencial</Label>
- <Input
- id="secuencial"
- value={formData.secuencial}
- onChange={(e) => setFormData({ ...formData, secuencial: e.target.value })}
- placeholder="000000001"
- maxLength={9}
- />
- </div>
-
- <div className="space-y-2 md:col-span-2">
- <Label htmlFor="dirMatriz">Dirección Matriz *</Label>
- <Input
- id="dirMatriz"
- value={formData.dirMatriz}
- onChange={(e) => setFormData({ ...formData, dirMatriz: e.target.value })}
- placeholder="Av. Principal 123 y Secundaria"
- />
- </div>
-
- {isEdit && (
- <div className="flex items-center space-x-2">
- <Switch
- id="activo"
- checked={formData.activo}
- onCheckedChange={(checked) => setFormData({ ...formData, activo: checked })}
- />
- <Label htmlFor="activo">Activa</Label>
- </div>
- )}
- </div>
-
- <div className="flex justify-end gap-2 pt-4">
- <Button variant="outline" onClick={onCancel}>
- Cancelar
- </Button>
- <Button onClick={onSave}>
- {isEdit ? 'Actualizar' : 'Guardar'}
- </Button>
- </div>
- </div>
- )
- }
|