Improve the frontend 3

This commit is contained in:
Urtzi Alfaro
2025-10-30 21:08:07 +01:00
parent 36217a2729
commit 63f5c6d512
184 changed files with 21512 additions and 7442 deletions

View File

@@ -5,7 +5,7 @@ import { DialogModal } from '../../../../components/ui/DialogModal/DialogModal';
import { PageHeader } from '../../../../components/layout';
import { useAuthUser } from '../../../../stores/auth.store';
import { useCurrentTenant } from '../../../../stores';
import { useToast } from '../../../../hooks/ui/useToast';
import { showToast } from '../../../../utils/toast';
import { subscriptionService, type UsageSummary, type AvailablePlans } from '../../../../api';
import { useSubscriptionEvents } from '../../../../contexts/SubscriptionEventsContext';
import { SubscriptionPricingCards } from '../../../../components/subscription/SubscriptionPricingCards';
@@ -13,7 +13,6 @@ import { SubscriptionPricingCards } from '../../../../components/subscription/Su
const SubscriptionPage: React.FC = () => {
const user = useAuthUser();
const currentTenant = useCurrentTenant();
const { addToast } = useToast();
const { notifySubscriptionChanged } = useSubscriptionEvents();
const [usageSummary, setUsageSummary] = useState<UsageSummary | null>(null);
@@ -36,7 +35,7 @@ const SubscriptionPage: React.FC = () => {
const tenantId = currentTenant?.id || user?.tenant_id;
if (!tenantId) {
addToast('No se encontró información del tenant', { type: 'error' });
showToast.error('No se encontró información del tenant');
return;
}
@@ -120,7 +119,7 @@ const SubscriptionPage: React.FC = () => {
setAvailablePlans(plans);
} catch (error) {
console.error('Error loading subscription data:', error);
addToast("No se pudo cargar la información de suscripción", { type: 'error' });
showToast.error("No se pudo cargar la información de suscripción");
} finally {
setSubscriptionLoading(false);
}
@@ -135,7 +134,7 @@ const SubscriptionPage: React.FC = () => {
const tenantId = currentTenant?.id || user?.tenant_id;
if (!tenantId || !selectedPlan) {
addToast('Información de tenant no disponible', { type: 'error' });
showToast.error('Información de tenant no disponible');
return;
}
@@ -148,14 +147,17 @@ const SubscriptionPage: React.FC = () => {
);
if (!validation.can_upgrade) {
addToast(validation.reason || 'No se puede actualizar el plan', { type: 'error' });
showToast.error(validation.reason || 'No se puede actualizar el plan');
return;
}
const result = await subscriptionService.upgradePlan(tenantId, selectedPlan);
if (result.success) {
addToast(result.message, { type: 'success' });
showToast.success(result.message);
// Invalidate cache to ensure fresh data on next fetch
subscriptionService.invalidateCache();
// Broadcast subscription change event to refresh sidebar and other components
notifySubscriptionChanged();
@@ -164,11 +166,11 @@ const SubscriptionPage: React.FC = () => {
setUpgradeDialogOpen(false);
setSelectedPlan('');
} else {
addToast('Error al cambiar el plan', { type: 'error' });
showToast.error('Error al cambiar el plan');
}
} catch (error) {
console.error('Error upgrading plan:', error);
addToast('Error al procesar el cambio de plan', { type: 'error' });
showToast.error('Error al procesar el cambio de plan');
} finally {
setUpgrading(false);
}
@@ -182,7 +184,7 @@ const SubscriptionPage: React.FC = () => {
const tenantId = currentTenant?.id || user?.tenant_id;
if (!tenantId) {
addToast('Información de tenant no disponible', { type: 'error' });
showToast.error('Información de tenant no disponible');
return;
}
@@ -199,9 +201,8 @@ const SubscriptionPage: React.FC = () => {
day: 'numeric'
});
addToast(
`Suscripción cancelada. Acceso de solo lectura a partir del ${effectiveDate} (${daysRemaining} días restantes)`,
{ type: 'success' }
showToast.success(
`Suscripción cancelada. Acceso de solo lectura a partir del ${effectiveDate} (${daysRemaining} días restantes)`
);
}
@@ -209,7 +210,7 @@ const SubscriptionPage: React.FC = () => {
setCancellationDialogOpen(false);
} catch (error) {
console.error('Error cancelling subscription:', error);
addToast('Error al cancelar la suscripción', { type: 'error' });
showToast.error('Error al cancelar la suscripción');
} finally {
setCancelling(false);
}
@@ -219,7 +220,7 @@ const SubscriptionPage: React.FC = () => {
const tenantId = currentTenant?.id || user?.tenant_id;
if (!tenantId) {
addToast('No se encontró información del tenant', { type: 'error' });
showToast.error('No se encontró información del tenant');
return;
}
@@ -236,7 +237,7 @@ const SubscriptionPage: React.FC = () => {
]);
} catch (error) {
console.error('Error loading invoices:', error);
addToast('Error al cargar las facturas', { type: 'error' });
showToast.error('Error al cargar las facturas');
} finally {
setInvoicesLoading(false);
}
@@ -245,7 +246,7 @@ const SubscriptionPage: React.FC = () => {
const handleDownloadInvoice = (invoiceId: string) => {
// In a real implementation, this would download the actual invoice
console.log(`Downloading invoice: ${invoiceId}`);
addToast(`Descargando factura ${invoiceId}`, { type: 'info' });
showToast.info(`Descargando factura ${invoiceId}`);
};
const ProgressBar: React.FC<{ value: number; className?: string }> = ({ value, className = '' }) => {
@@ -389,7 +390,7 @@ const SubscriptionPage: React.FC = () => {
<ProgressBar value={usageSummary.usage.users.usage_percentage} />
<p className="text-xs text-[var(--text-secondary)] flex items-center justify-between">
<span>{usageSummary.usage.users.usage_percentage}% utilizado</span>
<span className="font-medium">{usageSummary.usage.users.unlimited ? 'Ilimitado' : `${usageSummary.usage.users.limit - usageSummary.usage.users.current} restantes`}</span>
<span className="font-medium">{usageSummary.usage.users.unlimited ? 'Ilimitado' : `${(usageSummary.usage.users.limit ?? 0) - usageSummary.usage.users.current} restantes`}</span>
</p>
</div>
@@ -410,7 +411,7 @@ const SubscriptionPage: React.FC = () => {
<ProgressBar value={usageSummary.usage.locations.usage_percentage} />
<p className="text-xs text-[var(--text-secondary)] flex items-center justify-between">
<span>{usageSummary.usage.locations.usage_percentage}% utilizado</span>
<span className="font-medium">{usageSummary.usage.locations.unlimited ? 'Ilimitado' : `${usageSummary.usage.locations.limit - usageSummary.usage.locations.current} restantes`}</span>
<span className="font-medium">{usageSummary.usage.locations.unlimited ? 'Ilimitado' : `${(usageSummary.usage.locations.limit ?? 0) - usageSummary.usage.locations.current} restantes`}</span>
</p>
</div>
</div>
@@ -437,7 +438,7 @@ const SubscriptionPage: React.FC = () => {
<ProgressBar value={usageSummary.usage.products.usage_percentage} />
<p className="text-xs text-[var(--text-secondary)] flex items-center justify-between">
<span>{usageSummary.usage.products.usage_percentage}% utilizado</span>
<span className="font-medium">{usageSummary.usage.products.unlimited ? 'Ilimitado' : `${usageSummary.usage.products.limit - usageSummary.usage.products.current} restantes`}</span>
<span className="font-medium">{usageSummary.usage.products.unlimited ? 'Ilimitado' : `${(usageSummary.usage.products.limit ?? 0) - usageSummary.usage.products.current} restantes`}</span>
</p>
</div>
@@ -458,7 +459,7 @@ const SubscriptionPage: React.FC = () => {
<ProgressBar value={usageSummary.usage.recipes.usage_percentage} />
<p className="text-xs text-[var(--text-secondary)] flex items-center justify-between">
<span>{usageSummary.usage.recipes.usage_percentage}% utilizado</span>
<span className="font-medium">{usageSummary.usage.recipes.unlimited ? 'Ilimitado' : `${usageSummary.usage.recipes.limit - usageSummary.usage.recipes.current} restantes`}</span>
<span className="font-medium">{usageSummary.usage.recipes.unlimited ? 'Ilimitado' : `${(usageSummary.usage.recipes.limit ?? 0) - usageSummary.usage.recipes.current} restantes`}</span>
</p>
</div>
@@ -479,7 +480,7 @@ const SubscriptionPage: React.FC = () => {
<ProgressBar value={usageSummary.usage.suppliers.usage_percentage} />
<p className="text-xs text-[var(--text-secondary)] flex items-center justify-between">
<span>{usageSummary.usage.suppliers.usage_percentage}% utilizado</span>
<span className="font-medium">{usageSummary.usage.suppliers.unlimited ? 'Ilimitado' : `${usageSummary.usage.suppliers.limit - usageSummary.usage.suppliers.current} restantes`}</span>
<span className="font-medium">{usageSummary.usage.suppliers.unlimited ? 'Ilimitado' : `${(usageSummary.usage.suppliers.limit ?? 0) - usageSummary.usage.suppliers.current} restantes`}</span>
</p>
</div>
</div>
@@ -506,7 +507,7 @@ const SubscriptionPage: React.FC = () => {
<ProgressBar value={usageSummary.usage.training_jobs_today.usage_percentage} />
<p className="text-xs text-[var(--text-secondary)] flex items-center justify-between">
<span>{usageSummary.usage.training_jobs_today.usage_percentage}% utilizado</span>
<span className="font-medium">{usageSummary.usage.training_jobs_today.unlimited ? 'Ilimitado' : `${usageSummary.usage.training_jobs_today.limit - usageSummary.usage.training_jobs_today.current} restantes`}</span>
<span className="font-medium">{usageSummary.usage.training_jobs_today.unlimited ? 'Ilimitado' : `${(usageSummary.usage.training_jobs_today.limit ?? 0) - usageSummary.usage.training_jobs_today.current} restantes`}</span>
</p>
</div>
@@ -527,7 +528,7 @@ const SubscriptionPage: React.FC = () => {
<ProgressBar value={usageSummary.usage.forecasts_today.usage_percentage} />
<p className="text-xs text-[var(--text-secondary)] flex items-center justify-between">
<span>{usageSummary.usage.forecasts_today.usage_percentage}% utilizado</span>
<span className="font-medium">{usageSummary.usage.forecasts_today.unlimited ? 'Ilimitado' : `${usageSummary.usage.forecasts_today.limit - usageSummary.usage.forecasts_today.current} restantes`}</span>
<span className="font-medium">{usageSummary.usage.forecasts_today.unlimited ? 'Ilimitado' : `${(usageSummary.usage.forecasts_today.limit ?? 0) - usageSummary.usage.forecasts_today.current} restantes`}</span>
</p>
</div>
</div>
@@ -554,7 +555,7 @@ const SubscriptionPage: React.FC = () => {
<ProgressBar value={usageSummary.usage.api_calls_this_hour.usage_percentage} />
<p className="text-xs text-[var(--text-secondary)] flex items-center justify-between">
<span>{usageSummary.usage.api_calls_this_hour.usage_percentage}% utilizado</span>
<span className="font-medium">{usageSummary.usage.api_calls_this_hour.unlimited ? 'Ilimitado' : `${usageSummary.usage.api_calls_this_hour.limit - usageSummary.usage.api_calls_this_hour.current} restantes`}</span>
<span className="font-medium">{usageSummary.usage.api_calls_this_hour.unlimited ? 'Ilimitado' : `${(usageSummary.usage.api_calls_this_hour.limit ?? 0) - usageSummary.usage.api_calls_this_hour.current} restantes`}</span>
</p>
</div>
@@ -575,7 +576,7 @@ const SubscriptionPage: React.FC = () => {
<ProgressBar value={usageSummary.usage.file_storage_used_gb.usage_percentage} />
<p className="text-xs text-[var(--text-secondary)] flex items-center justify-between">
<span>{usageSummary.usage.file_storage_used_gb.usage_percentage}% utilizado</span>
<span className="font-medium">{usageSummary.usage.file_storage_used_gb.unlimited ? 'Ilimitado' : `${(usageSummary.usage.file_storage_used_gb.limit - usageSummary.usage.file_storage_used_gb.current).toFixed(2)} GB restantes`}</span>
<span className="font-medium">{usageSummary.usage.file_storage_used_gb.unlimited ? 'Ilimitado' : `${((usageSummary.usage.file_storage_used_gb.limit ?? 0) - usageSummary.usage.file_storage_used_gb.current).toFixed(2)} GB restantes`}</span>
</p>
</div>
</div>