Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@
.DS_Store
*.pem

# IA
.claude/
.playwright-cli/
.playwright/

# debug
npm-debug.log*
yarn-debug.log*
Expand Down
63 changes: 32 additions & 31 deletions app/(protected)/bienes/bienes-client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { useState } from 'react'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'
import { Button } from '@/components/ui/button'
import { formatCurrency } from '@/lib/utils'
import { Building2, Plus, Edit2, Trash2 } from 'lucide-react'
Expand Down Expand Up @@ -163,61 +164,61 @@ export function BienesClient({ properties: initialProperties }: BienesClientProp
<CardHeader className="px-8 py-6 border-b border-border/30 bg-primary/5">
<CardTitle className="text-xl">Lista de Bienes</CardTitle>
</CardHeader>
<CardContent className="p-0 overflow-x-auto">
<table className="w-full min-w-[900px]">
<thead>
<tr className="border-b border-border/30 bg-accent/5">
<th className="text-left text-[10px] font-bold text-muted-foreground uppercase tracking-widest px-8 py-4">Nombre</th>
<th className="text-left text-[10px] font-bold text-muted-foreground uppercase tracking-widest px-4 py-4">Tipo</th>
<th className="text-left text-[10px] font-bold text-muted-foreground uppercase tracking-widest px-4 py-4">Dirección</th>
<th className="text-right text-[10px] font-bold text-muted-foreground uppercase tracking-widest px-4 py-4">Valor Compra</th>
<th className="text-right text-[10px] font-bold text-muted-foreground uppercase tracking-widest px-4 py-4">Valor Actual</th>
<th className="text-right text-[10px] font-bold text-muted-foreground uppercase tracking-widest px-8 py-4 w-32">Acciones</th>
</tr>
</thead>
<tbody>
<CardContent className="p-0">
<Table className="min-w-[800px]">
<TableHeader>
<TableRow className="hover:bg-transparent">
<TableHead className="font-semibold uppercase text-[10px] tracking-widest text-muted-foreground">Nombre</TableHead>
<TableHead className="font-semibold uppercase text-[10px] tracking-widest text-muted-foreground">Tipo</TableHead>
<TableHead className="font-semibold uppercase text-[10px] tracking-widest text-muted-foreground">Dirección</TableHead>
<TableHead className="font-semibold uppercase text-[10px] tracking-widest text-muted-foreground text-right">Valor Compra</TableHead>
<TableHead className="font-semibold uppercase text-[10px] tracking-widest text-muted-foreground text-right">Valor Actual</TableHead>
<TableHead className="font-semibold uppercase text-[10px] tracking-widest text-muted-foreground text-right sticky right-0 bg-card z-20 shadow-[-8px_0_8px_-8px_rgba(0,0,0,0.1)] border-l border-border/10 w-24 pr-4">Acciones</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{safeProperties.map((property) => (
<tr key={property.id} className="border-b border-border/10 hover:bg-accent/30 transition-colors group">
<td className="px-8 py-4">
<TableRow key={property.id}>
<TableCell className="py-4">
<p className="font-bold text-lg">{property.name}</p>
{property.description && (
<p className="text-xs text-muted-foreground mt-0.5 truncate max-w-[200px]">{property.description}</p>
)}
</td>
<td className="px-4 py-4">
</TableCell>
<TableCell className="py-4">
<span className="inline-flex items-center px-3 py-1 bg-accent/50 text-muted-foreground rounded-lg text-xs font-bold uppercase tracking-tighter">
{typeLabel(property.type)}
</span>
</td>
<td className="px-4 py-4 text-sm text-muted-foreground">{property.address || '-'}</td>
<td className="px-4 py-4 text-right text-sm text-muted-foreground">{formatCurrency(property.purchaseValue)}</td>
<td className="px-4 py-4 text-right">
</TableCell>
<TableCell className="py-4 text-sm text-muted-foreground">{property.address || '-'}</TableCell>
<TableCell className="py-4 text-right text-sm text-muted-foreground">{formatCurrency(property.purchaseValue)}</TableCell>
<TableCell className="py-4 text-right">
<span className="text-lg font-bold text-primary">{formatCurrency(property.currentValue)}</span>
</td>
<td className="px-8 py-4">
</TableCell>
<TableCell className="sticky right-0 bg-card z-10 shadow-[-8px_0_8px_-8px_rgba(0,0,0,0.1)] border-l border-border/10 w-24 pr-4">
<div className="flex items-center justify-end gap-2">
<Button
onClick={() => handleOpenEdit(property)}
variant="ghost"
size="sm"
className="h-10 w-10 p-0 rounded-lg hover:bg-primary/10 hover:text-primary transition-colors group"
className="h-10 w-10 p-0 rounded-lg hover:bg-primary/10 hover:text-primary transition-colors"
>
<Edit2 className='w-4 h-4 group-hover:text-primary' />
<Edit2 className='w-4 h-4' />
</Button>
<Button
onClick={() => setDeletingId(property.id)}
variant="ghost"
size="sm"
className="h-10 w-10 p-0 rounded-lg hover:bg-rose-500/10 hover:text-rose-500 transition-colors group"
className="h-10 w-10 p-0 rounded-lg hover:bg-rose-500/10 hover:text-rose-500 transition-colors"
>
<Trash2 className='w-4 h-4 group-hover:text-rose-500' />
<Trash2 className='w-4 h-4' />
</Button>
</div>
</td>
</tr>
</TableCell>
</TableRow>
))}
</tbody>
</table>
</TableBody>
</Table>
</CardContent>
</Card>
)}
Expand Down
17 changes: 14 additions & 3 deletions app/(protected)/categorias/categorias-client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
import { Plus, Tag, Trash2, Edit2, X } from 'lucide-react'
import { Plus, Tag, Trash2, Edit2, Package, ShoppingBag } from 'lucide-react'
import { Modal } from '@/components/ui/modal'
import { EmptyState } from '@/components/ui/empty-state'
import { createCategory, deleteCategory, updateCategory } from '@/lib/actions/categories'
import { ConfirmationModal } from '@/components/ui/confirmation-modal'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
Expand Down Expand Up @@ -105,7 +106,12 @@ export function CategoriasClient({ categories: initialCategories }: CategoriasCl
</CardHeader>
<CardContent className="p-0">
{supplyCategories.length === 0 ? (
<div className="p-8 text-center text-muted-foreground">No hay categorías de este tipo</div>
<EmptyState
icon={Package}
title="Sin categorías de insumos"
description="Crea categorías para organizar tus insumos."
compact
/>
) : (
<div className="divide-y divide-border/30">
{supplyCategories.map(category => (
Expand Down Expand Up @@ -134,7 +140,12 @@ export function CategoriasClient({ categories: initialCategories }: CategoriasCl
</CardHeader>
<CardContent className="p-0">
{productCategories.length === 0 ? (
<div className="p-8 text-center text-muted-foreground">No hay categorías de este tipo</div>
<EmptyState
icon={ShoppingBag}
title="Sin categorías de productos"
description="Crea categorías para organizar tus productos."
compact
/>
) : (
<div className="divide-y divide-border/30">
{productCategories.map(category => (
Expand Down
136 changes: 64 additions & 72 deletions app/(protected)/clientes/clientes-client.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
'use client'

import { useState } from 'react'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { Card, CardContent } from '@/components/ui/card'
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'
import { Button } from '@/components/ui/button'
import { Users, Plus, Phone, Mail, MapPin, Edit2, Trash2 } from 'lucide-react'
import { ConfirmationModal } from '@/components/ui/confirmation-modal'
import { Modal } from '@/components/ui/modal'
import { CustomerFormModal } from '@/components/customer-form-modal'
import { EmptyState } from '@/components/ui/empty-state'
import { ExportButton } from '@/components/ui/export-button'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { deleteCustomer } from '@/lib/actions/customers'

Expand Down Expand Up @@ -136,76 +135,69 @@ export function ClientesClient({ customers: initialCustomers }: ClientesClientPr
onAction={handleOpenNew}
/>
) : (
<Card className="rounded-lg border-border/40 bg-card/30 backdrop-blur-md overflow-hidden p-0">
<CardHeader className="px-8 py-6 border-b border-border/30 bg-primary/5">
<CardTitle className="text-xl">Base de Clientes</CardTitle>
</CardHeader>
<CardContent className="p-0">
<Table className="min-w-[800px]">
<TableHeader>
<TableRow className="hover:bg-transparent">
<TableHead className="font-semibold uppercase text-[10px] tracking-widest text-muted-foreground">Cliente</TableHead>
<TableHead className="font-semibold uppercase text-[10px] tracking-widest text-muted-foreground">Contacto</TableHead>
<TableHead className="font-semibold uppercase text-[10px] tracking-widest text-muted-foreground">Ventas</TableHead>
<TableHead className="font-semibold uppercase text-[10px] tracking-widest text-muted-foreground text-right sticky right-0 bg-card z-20 shadow-[-8px_0_8px_-8px_rgba(0,0,0,0.1)] border-l border-border/10 w-24 pr-4">Acciones</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{(customers ?? []).map((customer: Customer) => (
<TableRow key={customer.id} className="hover:bg-accent/30 group transition-colors">
<TableCell className="py-4">
<div className="flex flex-col">
<span className="font-bold text-lg">{customer.name}</span>
<div className="flex items-center gap-1 text-xs text-muted-foreground mt-1">
<MapPin size={12} />
{customer.address || 'Sin dirección'}
</div>
</div>
</TableCell>
<TableCell>
<div className="space-y-1">
<div className="flex items-center gap-2 text-sm">
<Mail size={14} className="text-muted-foreground" />
{customer.email || '-'}
</div>
<div className="flex items-center gap-2 text-sm font-medium">
<Phone size={14} className="text-primary" />
{customer.phone || '-'}
</div>
</div>
</TableCell>
<TableCell>
<div className="flex items-center gap-2">
<span className="text-xl font-extrabold text-primary">{customer.saleCount}</span>
<span className="text-[10px] font-bold uppercase tracking-widest text-muted-foreground">Compras</span>
</div>
</TableCell>
<TableCell className="sticky right-0 bg-card z-10 shadow-[-8px_0_8px_-8px_rgba(0,0,0,0.1)] border-l border-border/10 w-24 pr-4">
<div className="flex justify-end gap-2">
<Button
onClick={() => handleOpenEdit(customer)}
variant="ghost"
size="sm"
className="h-10 w-10 p-0 rounded-lg hover:bg-primary/10 hover:text-primary transition-colors group"
>
<Edit2 className='w-4 h-4 group-hover:text-primary' />
</Button>
<Button
onClick={() => setDeletingCustomer(customer)}
variant="ghost"
size="sm"
className="h-10 w-10 p-0 rounded-lg hover:bg-rose-500/10 hover:text-rose-500 transition-colors group"
>
<Trash2 className='w-4 h-4 group-hover:text-rose-500' />
</Button>
</div>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</CardContent>
</Card>
<Table className="min-w-[800px]">
<TableHeader>
<TableRow className="hover:bg-transparent">
<TableHead className="font-semibold uppercase text-[10px] tracking-widest text-muted-foreground">Cliente</TableHead>
<TableHead className="font-semibold uppercase text-[10px] tracking-widest text-muted-foreground">Contacto</TableHead>
<TableHead className="font-semibold uppercase text-[10px] tracking-widest text-muted-foreground">Ventas</TableHead>
<TableHead className="font-semibold uppercase text-[10px] tracking-widest text-muted-foreground text-right sticky right-0 bg-card z-20 shadow-[-8px_0_8px_-8px_rgba(0,0,0,0.1)] border-l border-border/10 w-24 pr-4">Acciones</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{(customers ?? []).map((customer: Customer) => (
<TableRow key={customer.id} className="hover:bg-accent/30 group transition-colors">
<TableCell className="py-4">
<div className="flex flex-col">
<span className="font-bold text-lg">{customer.name}</span>
<div className="flex items-center gap-1 text-xs text-muted-foreground mt-1">
<MapPin size={12} />
{customer.address || 'Sin dirección'}
</div>
</div>
</TableCell>
<TableCell>
<div className="space-y-1">
<div className="flex items-center gap-2 text-sm">
<Mail size={14} className="text-muted-foreground" />
{customer.email || '-'}
</div>
<div className="flex items-center gap-2 text-sm font-medium">
<Phone size={14} className="text-primary" />
{customer.phone || '-'}
</div>
</div>
</TableCell>
<TableCell>
<div className="flex items-center gap-2">
<span className="text-xl font-extrabold text-primary">{customer.saleCount}</span>
<span className="text-[10px] font-bold uppercase tracking-widest text-muted-foreground">Compras</span>
</div>
</TableCell>
<TableCell className="sticky right-0 bg-card z-10 shadow-[-8px_0_8px_-8px_rgba(0,0,0,0.1)] border-l border-border/10 w-24 pr-4">
<div className="flex justify-end gap-2">
<Button
onClick={() => handleOpenEdit(customer)}
variant="ghost"
size="sm"
className="h-10 w-10 p-0 rounded-lg hover:bg-primary/10 hover:text-primary transition-colors group"
>
<Edit2 className='w-4 h-4 group-hover:text-primary' />
</Button>
<Button
onClick={() => setDeletingCustomer(customer)}
variant="ghost"
size="sm"
className="h-10 w-10 p-0 rounded-lg hover:bg-rose-500/10 hover:text-rose-500 transition-colors group"
>
<Trash2 className='w-4 h-4 group-hover:text-rose-500' />
</Button>
</div>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
)}

{/* Modal */}
Expand Down
Loading
Loading