feat: bulk XML upload, period selector, and session persistence
- Add bulk XML CFDI upload support (up to 300MB) - Add period selector component for month/year navigation - Fix session persistence on page refresh (Zustand hydration) - Fix income/expense classification based on tenant RFC - Fix IVA calculation from XML (correct Impuestos element) - Add error handling to reportes page - Support multiple CORS origins - Update reportes service with proper Decimal/BigInt handling - Add RFC to tenant view store for proper CFDI classification - Update README with changelog and new features Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import { getTenants, type Tenant } from '@/lib/api/tenants';
|
||||
import { useTenantViewStore } from '@/stores/tenant-view-store';
|
||||
import { useAuthStore } from '@/stores/auth-store';
|
||||
@@ -11,6 +11,7 @@ import { cn } from '@/lib/utils';
|
||||
export function TenantSelector() {
|
||||
const [open, setOpen] = useState(false);
|
||||
const { user } = useAuthStore();
|
||||
const queryClient = useQueryClient();
|
||||
const { viewingTenantId, viewingTenantName, setViewingTenant, clearViewingTenant } = useTenantViewStore();
|
||||
|
||||
const { data: tenants, isLoading } = useQuery({
|
||||
@@ -57,17 +58,26 @@ export function TenantSelector() {
|
||||
<Building className="h-4 w-4" />
|
||||
<span className="max-w-[150px] truncate">{displayName}</span>
|
||||
{isViewingOther && (
|
||||
<button
|
||||
<span
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
clearViewingTenant();
|
||||
window.location.reload();
|
||||
queryClient.invalidateQueries();
|
||||
}}
|
||||
className="ml-1 p-0.5 rounded hover:bg-primary/20"
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.stopPropagation();
|
||||
clearViewingTenant();
|
||||
queryClient.invalidateQueries();
|
||||
}
|
||||
}}
|
||||
className="ml-1 p-0.5 rounded hover:bg-primary/20 cursor-pointer"
|
||||
title="Volver a mi empresa"
|
||||
>
|
||||
<X className="h-3 w-3" />
|
||||
</button>
|
||||
</span>
|
||||
)}
|
||||
<ChevronDown className={cn('h-4 w-4 transition-transform', open && 'rotate-180')} />
|
||||
</button>
|
||||
@@ -87,7 +97,7 @@ export function TenantSelector() {
|
||||
onClick={() => {
|
||||
clearViewingTenant();
|
||||
setOpen(false);
|
||||
window.location.reload();
|
||||
queryClient.invalidateQueries();
|
||||
}}
|
||||
className={cn(
|
||||
'flex w-full items-center gap-3 rounded-md px-3 py-2 text-sm hover:bg-accent transition-colors',
|
||||
@@ -113,9 +123,9 @@ export function TenantSelector() {
|
||||
<button
|
||||
key={tenant.id}
|
||||
onClick={() => {
|
||||
setViewingTenant(tenant.id, tenant.nombre);
|
||||
setViewingTenant(tenant.id, tenant.nombre, tenant.rfc);
|
||||
setOpen(false);
|
||||
window.location.reload();
|
||||
queryClient.invalidateQueries();
|
||||
}}
|
||||
className={cn(
|
||||
'flex w-full items-center gap-3 rounded-md px-3 py-2 text-sm hover:bg-accent transition-colors',
|
||||
|
||||
Reference in New Issue
Block a user