Improve the frontend 3
This commit is contained in:
@@ -2,7 +2,7 @@ import React, { useState } from 'react';
|
||||
import { Store, MapPin, Clock, Phone, Mail, Globe, Save, X, Edit3, Zap, Plus, Settings, Trash2, Wifi, WifiOff, AlertCircle, CheckCircle, Loader, Eye, EyeOff, Info } from 'lucide-react';
|
||||
import { Button, Card, Input, Select, Modal, Badge, Tabs } from '../../../../components/ui';
|
||||
import { PageHeader } from '../../../../components/layout';
|
||||
import { useToast } from '../../../../hooks/ui/useToast';
|
||||
import { showToast } from '../../../../utils/toast';
|
||||
import { usePOSConfigurationData, usePOSConfigurationManager } from '../../../../api/hooks/pos';
|
||||
import { POSConfiguration, POSProviderConfig } from '../../../../api/types/pos';
|
||||
import { posService } from '../../../../api/services/pos';
|
||||
@@ -38,7 +38,7 @@ interface BusinessHours {
|
||||
|
||||
|
||||
const BakeryConfigPage: React.FC = () => {
|
||||
const { addToast } = useToast();
|
||||
|
||||
const currentTenant = useCurrentTenant();
|
||||
const { loadUserTenants, setCurrentTenant } = useTenantActions();
|
||||
const tenantId = currentTenant?.id || '';
|
||||
@@ -287,9 +287,9 @@ const BakeryConfigPage: React.FC = () => {
|
||||
}
|
||||
|
||||
setHasUnsavedChanges(false);
|
||||
addToast('Configuración actualizada correctamente', { type: 'success' });
|
||||
showToast.success('Configuración actualizada correctamente');
|
||||
} catch (error) {
|
||||
addToast(`Error al actualizar: ${error instanceof Error ? error.message : 'Error desconocido'}`, { type: 'error' });
|
||||
showToast.error(`Error al actualizar: ${error instanceof Error ? error.message : 'Error desconocido'}`);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
@@ -364,7 +364,7 @@ const BakeryConfigPage: React.FC = () => {
|
||||
.map(field => field.label);
|
||||
|
||||
if (missingFields.length > 0) {
|
||||
addToast(`Campos requeridos: ${missingFields.join(', ')}`, 'error');
|
||||
showToast.error(`Campos requeridos: ${missingFields.join(', ')}`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -375,7 +375,7 @@ const BakeryConfigPage: React.FC = () => {
|
||||
config_id: selectedPosConfig.id,
|
||||
...posFormData,
|
||||
});
|
||||
addToast('Configuración actualizada correctamente', 'success');
|
||||
showToast.success('Configuración actualizada correctamente');
|
||||
setShowEditPosModal(false);
|
||||
loadPosConfigurations();
|
||||
} else {
|
||||
@@ -384,12 +384,12 @@ const BakeryConfigPage: React.FC = () => {
|
||||
tenant_id: tenantId,
|
||||
...posFormData,
|
||||
});
|
||||
addToast('Configuración creada correctamente', 'success');
|
||||
showToast.success('Configuración creada correctamente');
|
||||
setShowAddPosModal(false);
|
||||
loadPosConfigurations();
|
||||
}
|
||||
} catch (error) {
|
||||
addToast('Error al guardar la configuración', 'error');
|
||||
showToast.error('Error al guardar la configuración');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -402,12 +402,12 @@ const BakeryConfigPage: React.FC = () => {
|
||||
});
|
||||
|
||||
if (response.success) {
|
||||
addToast('Conexión exitosa', 'success');
|
||||
showToast.success('Conexión exitosa');
|
||||
} else {
|
||||
addToast(`Error en la conexión: ${response.message || 'Error desconocido'}`, 'error');
|
||||
showToast.error(`Error en la conexión: ${response.message || 'Error desconocido'}`);
|
||||
}
|
||||
} catch (error) {
|
||||
addToast('Error al probar la conexión', 'error');
|
||||
showToast.error('Error al probar la conexión');
|
||||
} finally {
|
||||
setTestingConnection(null);
|
||||
}
|
||||
@@ -423,10 +423,10 @@ const BakeryConfigPage: React.FC = () => {
|
||||
tenant_id: tenantId,
|
||||
config_id: configId,
|
||||
});
|
||||
addToast('Configuración eliminada correctamente', 'success');
|
||||
showToast.success('Configuración eliminada correctamente');
|
||||
loadPosConfigurations();
|
||||
} catch (error) {
|
||||
addToast('Error al eliminar la configuración', 'error');
|
||||
showToast.error('Error al eliminar la configuración');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1116,4 +1116,4 @@ const BakeryConfigPage: React.FC = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default BakeryConfigPage;
|
||||
export default BakeryConfigPage;
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Store, MapPin, Clock, Settings as SettingsIcon, Save, X, AlertCircle, L
|
||||
import { Button, Card, Input, Select } from '../../../../components/ui';
|
||||
import { Tabs, TabsList, TabsTrigger, TabsContent } from '../../../../components/ui/Tabs';
|
||||
import { PageHeader } from '../../../../components/layout';
|
||||
import { useToast } from '../../../../hooks/ui/useToast';
|
||||
import { showToast } from '../../../../utils/toast';
|
||||
import { useUpdateTenant } from '../../../../api/hooks/tenant';
|
||||
import { useCurrentTenant, useTenantActions } from '../../../../stores/tenant.store';
|
||||
import { useSettings, useUpdateSettings } from '../../../../api/hooks/settings';
|
||||
@@ -49,7 +49,7 @@ interface BusinessHours {
|
||||
|
||||
const BakerySettingsPage: React.FC = () => {
|
||||
const { t } = useTranslation('settings');
|
||||
const { addToast } = useToast();
|
||||
|
||||
const currentTenant = useCurrentTenant();
|
||||
const { loadUserTenants, setCurrentTenant } = useTenantActions();
|
||||
const tenantId = currentTenant?.id || '';
|
||||
@@ -221,10 +221,10 @@ const BakerySettingsPage: React.FC = () => {
|
||||
}
|
||||
|
||||
setHasUnsavedChanges(false);
|
||||
addToast(t('bakery.save_success'), { type: 'success' });
|
||||
showToast.success(t('bakery.save_success'));
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : t('common.error');
|
||||
addToast(`${t('bakery.save_error')}: ${errorMessage}`, { type: 'error' });
|
||||
showToast.error(`${t('bakery.save_error')}: ${errorMessage}`);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
@@ -252,10 +252,10 @@ const BakerySettingsPage: React.FC = () => {
|
||||
});
|
||||
|
||||
setHasUnsavedChanges(false);
|
||||
addToast(t('bakery.save_success'), { type: 'success' });
|
||||
showToast.success(t('bakery.save_success'));
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : t('common.error');
|
||||
addToast(`${t('bakery.save_error')}: ${errorMessage}`, { type: 'error' });
|
||||
showToast.error(`${t('bakery.save_error')}: ${errorMessage}`);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import {
|
||||
Sun,
|
||||
Settings
|
||||
} from 'lucide-react';
|
||||
import { useToast } from '../../../../hooks/ui/useToast';
|
||||
import { showToast } from '../../../../utils/toast';
|
||||
|
||||
// Backend-aligned preference types
|
||||
export interface NotificationPreferences {
|
||||
@@ -75,7 +75,7 @@ const CommunicationPreferences: React.FC<CommunicationPreferencesProps> = ({
|
||||
onReset,
|
||||
hasChanges
|
||||
}) => {
|
||||
const { addToast } = useToast();
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const [preferences, setPreferences] = useState<NotificationPreferences>({
|
||||
@@ -161,9 +161,9 @@ const CommunicationPreferences: React.FC<CommunicationPreferencesProps> = ({
|
||||
try {
|
||||
setIsLoading(true);
|
||||
await onSave(preferences);
|
||||
addToast('Preferencias guardadas correctamente', 'success');
|
||||
showToast.success('Preferencias guardadas correctamente');
|
||||
} catch (error) {
|
||||
addToast('Error al guardar las preferencias', 'error');
|
||||
showToast.error('Error al guardar las preferencias');
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
@@ -700,4 +700,4 @@ const CommunicationPreferences: React.FC<CommunicationPreferencesProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default CommunicationPreferences;
|
||||
export default CommunicationPreferences;
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
import { Button, Card, Avatar, Input, Select } from '../../../../components/ui';
|
||||
import { Tabs, TabsList, TabsTrigger, TabsContent } from '../../../../components/ui/Tabs';
|
||||
import { PageHeader } from '../../../../components/layout';
|
||||
import { useToast } from '../../../../hooks/ui/useToast';
|
||||
import { showToast } from '../../../../utils/toast';
|
||||
import { useAuthUser, useAuthActions } from '../../../../stores/auth.store';
|
||||
import { useAuthProfile, useUpdateProfile, useChangePassword } from '../../../../api/hooks/auth';
|
||||
import { useCurrentTenant } from '../../../../stores';
|
||||
@@ -49,7 +49,7 @@ interface PasswordData {
|
||||
const NewProfileSettingsPage: React.FC = () => {
|
||||
const { t } = useTranslation('settings');
|
||||
const navigate = useNavigate();
|
||||
const { addToast } = useToast();
|
||||
|
||||
const user = useAuthUser();
|
||||
const { logout } = useAuthActions();
|
||||
const currentTenant = useCurrentTenant();
|
||||
@@ -169,9 +169,9 @@ const NewProfileSettingsPage: React.FC = () => {
|
||||
await updateProfileMutation.mutateAsync(profileData);
|
||||
|
||||
setIsEditing(false);
|
||||
addToast(t('profile.save_changes'), { type: 'success' });
|
||||
showToast.success(t('profile.save_changes'));
|
||||
} catch (error) {
|
||||
addToast(t('common.error'), { type: 'error' });
|
||||
showToast.error(t('common.error'));
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
@@ -191,9 +191,9 @@ const NewProfileSettingsPage: React.FC = () => {
|
||||
|
||||
setShowPasswordForm(false);
|
||||
setPasswordData({ currentPassword: '', newPassword: '', confirmPassword: '' });
|
||||
addToast(t('profile.password.change_success'), { type: 'success' });
|
||||
showToast.success(t('profile.password.change_success'));
|
||||
} catch (error) {
|
||||
addToast(t('profile.password.change_error'), { type: 'error' });
|
||||
showToast.error(t('profile.password.change_error'));
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
@@ -246,9 +246,9 @@ const NewProfileSettingsPage: React.FC = () => {
|
||||
window.URL.revokeObjectURL(url);
|
||||
document.body.removeChild(a);
|
||||
|
||||
addToast(t('profile.privacy.export_success'), { type: 'success' });
|
||||
showToast.success(t('profile.privacy.export_success'));
|
||||
} catch (err) {
|
||||
addToast(t('profile.privacy.export_error'), { type: 'error' });
|
||||
showToast.error(t('profile.privacy.export_error'));
|
||||
} finally {
|
||||
setIsExporting(false);
|
||||
}
|
||||
@@ -256,12 +256,12 @@ const NewProfileSettingsPage: React.FC = () => {
|
||||
|
||||
const handleAccountDeletion = async () => {
|
||||
if (deleteConfirmEmail.toLowerCase() !== user?.email?.toLowerCase()) {
|
||||
addToast(t('common.error'), { type: 'error' });
|
||||
showToast.error(t('common.error'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!deletePassword) {
|
||||
addToast(t('common.error'), { type: 'error' });
|
||||
showToast.error(t('common.error'));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -270,14 +270,14 @@ const NewProfileSettingsPage: React.FC = () => {
|
||||
const { authService } = await import('../../../../api');
|
||||
await authService.deleteAccount(deleteConfirmEmail, deletePassword, deleteReason);
|
||||
|
||||
addToast(t('common.success'), { type: 'success' });
|
||||
showToast.success(t('common.success'));
|
||||
|
||||
setTimeout(() => {
|
||||
logout();
|
||||
navigate('/');
|
||||
}, 2000);
|
||||
} catch (err: any) {
|
||||
addToast(err.message || t('common.error'), { type: 'error' });
|
||||
showToast.error(err.message || t('common.error'));
|
||||
} finally {
|
||||
setIsDeleting(false);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Button, Card, Avatar, Input, Select, Tabs, Badge, Modal } from '../../.
|
||||
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 { useAuthProfile, useUpdateProfile, useChangePassword } from '../../../../api/hooks/auth';
|
||||
import { subscriptionService, type UsageSummary, type AvailablePlans } from '../../../../api';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -30,7 +30,7 @@ interface PasswordData {
|
||||
const ProfilePage: React.FC = () => {
|
||||
const user = useAuthUser();
|
||||
const { t } = useTranslation(['settings', 'auth']);
|
||||
const { addToast } = useToast();
|
||||
|
||||
|
||||
const { data: profile, isLoading: profileLoading, error: profileError } = useAuthProfile();
|
||||
const updateProfileMutation = useUpdateProfile();
|
||||
@@ -176,9 +176,9 @@ const ProfilePage: React.FC = () => {
|
||||
await updateProfileMutation.mutateAsync(profileData);
|
||||
|
||||
setIsEditing(false);
|
||||
addToast('Perfil actualizado correctamente', 'success');
|
||||
showToast.success('Perfil actualizado correctamente');
|
||||
} catch (error) {
|
||||
addToast('No se pudo actualizar tu perfil', 'error');
|
||||
showToast.error('No se pudo actualizar tu perfil');
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
@@ -198,9 +198,9 @@ const ProfilePage: React.FC = () => {
|
||||
|
||||
setShowPasswordForm(false);
|
||||
setPasswordData({ currentPassword: '', newPassword: '', confirmPassword: '' });
|
||||
addToast('Contraseña actualizada correctamente', 'success');
|
||||
showToast.success('Contraseña actualizada correctamente');
|
||||
} catch (error) {
|
||||
addToast('No se pudo cambiar tu contraseña', 'error');
|
||||
showToast.error('No se pudo cambiar tu contraseña');
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
@@ -269,7 +269,7 @@ const ProfilePage: React.FC = () => {
|
||||
const tenantId = currentTenant?.id || user?.tenant_id;
|
||||
|
||||
if (!tenantId) {
|
||||
addToast('No se encontró información del tenant', 'error');
|
||||
showToast.error('No se encontró información del tenant');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -284,7 +284,7 @@ const ProfilePage: React.FC = () => {
|
||||
setAvailablePlans(plans);
|
||||
} catch (error) {
|
||||
console.error('Error loading subscription data:', error);
|
||||
addToast("No se pudo cargar la información de suscripción", 'error');
|
||||
showToast.error("No se pudo cargar la información de suscripción");
|
||||
} finally {
|
||||
setSubscriptionLoading(false);
|
||||
}
|
||||
@@ -299,7 +299,7 @@ const ProfilePage: React.FC = () => {
|
||||
const tenantId = currentTenant?.id || user?.tenant_id;
|
||||
|
||||
if (!tenantId || !selectedPlan) {
|
||||
addToast('Información de tenant no disponible', 'error');
|
||||
showToast.error('Información de tenant no disponible');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -312,24 +312,24 @@ const ProfilePage: React.FC = () => {
|
||||
);
|
||||
|
||||
if (!validation.can_upgrade) {
|
||||
addToast(validation.reason || 'No se puede actualizar el plan', 'error');
|
||||
return;
|
||||
showToast.error(validation.reason || 'No se puede actualizar el plan');
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await subscriptionService.upgradePlan(tenantId, selectedPlan);
|
||||
|
||||
if (result.success) {
|
||||
addToast(result.message, 'success');
|
||||
showToast.success(result.message);
|
||||
|
||||
await loadSubscriptionData();
|
||||
setUpgradeDialogOpen(false);
|
||||
setSelectedPlan('');
|
||||
} else {
|
||||
addToast('Error al cambiar el plan', 'error');
|
||||
showToast.error('Error al cambiar el plan');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error upgrading plan:', error);
|
||||
addToast('Error al procesar el cambio de plan', 'error');
|
||||
showToast.error('Error al procesar el cambio de plan');
|
||||
} finally {
|
||||
setUpgrading(false);
|
||||
}
|
||||
@@ -953,4 +953,4 @@ const ProfilePage: React.FC = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default ProfilePage;
|
||||
export default ProfilePage;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -9,13 +9,13 @@ import { useUserActivity } from '../../../../api/hooks/user';
|
||||
import { userService } from '../../../../api/services/user';
|
||||
import { useAuthUser } from '../../../../stores/auth.store';
|
||||
import { useCurrentTenant, useCurrentTenantAccess } from '../../../../stores/tenant.store';
|
||||
import { useToast } from '../../../../hooks/ui/useToast';
|
||||
import { showToast } from '../../../../utils/toast';
|
||||
import { TENANT_ROLES, type TenantRole } from '../../../../types/roles';
|
||||
import { subscriptionService } from '../../../../api/services/subscription';
|
||||
|
||||
const TeamPage: React.FC = () => {
|
||||
const { t } = useTranslation(['settings']);
|
||||
const { addToast } = useToast();
|
||||
|
||||
const currentUser = useAuthUser();
|
||||
const currentTenant = useCurrentTenant();
|
||||
const currentTenantAccess = useCurrentTenantAccess();
|
||||
@@ -310,7 +310,7 @@ const TeamPage: React.FC = () => {
|
||||
setShowActivityModal(true);
|
||||
} catch (error) {
|
||||
console.error('Error fetching user activity:', error);
|
||||
addToast('Error al cargar la actividad del usuario', { type: 'error' });
|
||||
showToast.error('Error al cargar la actividad del usuario');
|
||||
} finally {
|
||||
setActivityLoading(false);
|
||||
}
|
||||
@@ -359,9 +359,9 @@ const TeamPage: React.FC = () => {
|
||||
memberUserId,
|
||||
});
|
||||
|
||||
addToast('Miembro removido exitosamente', { type: 'success' });
|
||||
showToast.success('Miembro removido exitosamente');
|
||||
} catch (error) {
|
||||
addToast('Error al remover miembro', { type: 'error' });
|
||||
showToast.error('Error al remover miembro');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -375,9 +375,9 @@ const TeamPage: React.FC = () => {
|
||||
newRole,
|
||||
});
|
||||
|
||||
addToast('Rol actualizado exitosamente', { type: 'success' });
|
||||
showToast.success('Rol actualizado exitosamente');
|
||||
} catch (error) {
|
||||
addToast('Error al actualizar rol', { type: 'error' });
|
||||
showToast.error('Error al actualizar rol');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -556,7 +556,7 @@ const TeamPage: React.FC = () => {
|
||||
if (!usageCheck.allowed) {
|
||||
const errorMessage = usageCheck.message ||
|
||||
`Has alcanzado el límite de ${usageCheck.limit} usuarios para tu plan. Actualiza tu suscripción para agregar más miembros.`;
|
||||
addToast(errorMessage, { type: 'error' });
|
||||
showToast.error(errorMessage);
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
|
||||
@@ -579,14 +579,14 @@ const TeamPage: React.FC = () => {
|
||||
timezone: 'Europe/Madrid'
|
||||
}
|
||||
});
|
||||
addToast('Usuario creado y agregado exitosamente', { type: 'success' });
|
||||
showToast.success('Usuario creado y agregado exitosamente');
|
||||
} else {
|
||||
await addMemberMutation.mutateAsync({
|
||||
tenantId,
|
||||
userId: userData.userId!,
|
||||
role,
|
||||
});
|
||||
addToast('Miembro agregado exitosamente', { type: 'success' });
|
||||
showToast.success('Miembro agregado exitosamente');
|
||||
}
|
||||
|
||||
setShowAddForm(false);
|
||||
@@ -597,9 +597,8 @@ const TeamPage: React.FC = () => {
|
||||
// Limit error already toasted above
|
||||
throw error;
|
||||
}
|
||||
addToast(
|
||||
userData.createUser ? 'Error al crear usuario' : 'Error al agregar miembro',
|
||||
{ type: 'error' }
|
||||
showToast.error(
|
||||
userData.createUser ? 'Error al crear usuario' : 'Error al agregar miembro'
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user