Add frontend pages imporvements
This commit is contained in:
@@ -40,7 +40,7 @@ interface BusinessHours {
|
||||
const BakeryConfigPage: React.FC = () => {
|
||||
const { addToast } = useToast();
|
||||
const currentTenant = useCurrentTenant();
|
||||
const { loadUserTenants } = useTenantActions();
|
||||
const { loadUserTenants, setCurrentTenant } = useTenantActions();
|
||||
const tenantId = currentTenant?.id || '';
|
||||
|
||||
// Use the current tenant from the store instead of making additional API calls
|
||||
@@ -83,12 +83,10 @@ const BakeryConfigPage: React.FC = () => {
|
||||
language: 'es'
|
||||
});
|
||||
|
||||
// Load user tenants on component mount if no current tenant
|
||||
// Load user tenants on component mount to ensure fresh data
|
||||
React.useEffect(() => {
|
||||
if (!currentTenant) {
|
||||
loadUserTenants();
|
||||
}
|
||||
}, [currentTenant, loadUserTenants]);
|
||||
loadUserTenants();
|
||||
}, [loadUserTenants]);
|
||||
|
||||
|
||||
// Update config when tenant data is loaded
|
||||
@@ -97,8 +95,8 @@ const BakeryConfigPage: React.FC = () => {
|
||||
setConfig({
|
||||
name: tenant.name || '',
|
||||
description: tenant.description || '',
|
||||
email: tenant.email || '', // Fixed: use email instead of contact_email
|
||||
phone: tenant.phone || '', // Fixed: use phone instead of contact_phone
|
||||
email: tenant.email || '',
|
||||
phone: tenant.phone || '',
|
||||
website: tenant.website || '',
|
||||
address: tenant.address || '',
|
||||
city: tenant.city || '',
|
||||
@@ -106,9 +104,10 @@ const BakeryConfigPage: React.FC = () => {
|
||||
country: tenant.country || '',
|
||||
taxId: '', // Not supported by backend yet
|
||||
currency: 'EUR', // Default value
|
||||
timezone: 'Europe/Madrid', // Default value
|
||||
timezone: 'Europe/Madrid', // Default value
|
||||
language: 'es' // Default value
|
||||
});
|
||||
setHasUnsavedChanges(false); // Reset unsaved changes when loading fresh data
|
||||
}
|
||||
}, [tenant]);
|
||||
|
||||
@@ -249,30 +248,48 @@ const BakeryConfigPage: React.FC = () => {
|
||||
|
||||
const handleSaveConfig = async () => {
|
||||
if (!validateConfig() || !tenantId) return;
|
||||
|
||||
|
||||
setIsLoading(true);
|
||||
|
||||
|
||||
try {
|
||||
await updateTenantMutation.mutateAsync({
|
||||
const updateData = {
|
||||
name: config.name,
|
||||
description: config.description,
|
||||
email: config.email,
|
||||
phone: config.phone,
|
||||
website: config.website,
|
||||
address: config.address,
|
||||
city: config.city,
|
||||
postal_code: config.postalCode,
|
||||
country: config.country
|
||||
};
|
||||
|
||||
const updatedTenant = await updateTenantMutation.mutateAsync({
|
||||
tenantId,
|
||||
updateData: {
|
||||
name: config.name,
|
||||
description: config.description,
|
||||
email: config.email, // Fixed: use email instead of contact_email
|
||||
phone: config.phone, // Fixed: use phone instead of contact_phone
|
||||
website: config.website,
|
||||
address: config.address,
|
||||
city: config.city,
|
||||
postal_code: config.postalCode,
|
||||
country: config.country
|
||||
// Note: tax_id, currency, timezone, language might not be supported by backend
|
||||
}
|
||||
updateData
|
||||
});
|
||||
|
||||
// Update the tenant store with the new data
|
||||
if (updatedTenant) {
|
||||
setCurrentTenant(updatedTenant);
|
||||
// Force reload tenant list to ensure cache consistency
|
||||
await loadUserTenants();
|
||||
|
||||
// Update localStorage to persist the changes
|
||||
const tenantStorage = localStorage.getItem('tenant-storage');
|
||||
if (tenantStorage) {
|
||||
const parsedStorage = JSON.parse(tenantStorage);
|
||||
if (parsedStorage.state && parsedStorage.state.currentTenant) {
|
||||
parsedStorage.state.currentTenant = updatedTenant;
|
||||
localStorage.setItem('tenant-storage', JSON.stringify(parsedStorage));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setHasUnsavedChanges(false);
|
||||
addToast('Configuración actualizada correctamente', { type: 'success' });
|
||||
} catch (error) {
|
||||
addToast('No se pudo actualizar la configuración', { type: 'error' });
|
||||
addToast(`Error al actualizar: ${error instanceof Error ? error.message : 'Error desconocido'}`, { type: 'error' });
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import React, { useState, useMemo } from 'react';
|
||||
import { Users, Plus, Search, Mail, Phone, Shield, Trash2, Crown, X, UserCheck } from 'lucide-react';
|
||||
import { Button, Card, Badge, Input, StatusCard, getStatusColor, StatsGrid } from '../../../../components/ui';
|
||||
import { Users, Plus, Search, Shield, Trash2, Crown, UserCheck } from 'lucide-react';
|
||||
import { Button, Card, Input, StatusCard, getStatusColor, StatsGrid } from '../../../../components/ui';
|
||||
import AddTeamMemberModal from '../../../../components/domain/team/AddTeamMemberModal';
|
||||
import { PageHeader } from '../../../../components/layout';
|
||||
import { useTeamMembers, useAddTeamMember, useRemoveTeamMember, useUpdateMemberRole } from '../../../../api/hooks/tenant';
|
||||
import { useTeamMembers, useAddTeamMember, useRemoveTeamMember, useUpdateMemberRole, useTenantAccess } from '../../../../api/hooks/tenant';
|
||||
import { useAllUsers } from '../../../../api/hooks/user';
|
||||
import { useAuthUser } from '../../../../stores/auth.store';
|
||||
import { useCurrentTenant, useCurrentTenantAccess } from '../../../../stores/tenant.store';
|
||||
@@ -12,12 +12,23 @@ import { TENANT_ROLES } from '../../../../types/roles';
|
||||
|
||||
const TeamPage: React.FC = () => {
|
||||
const { addToast } = useToast();
|
||||
const currentUser = useAuthUser();
|
||||
const currentTenant = useCurrentTenant();
|
||||
const currentTenantAccess = useCurrentTenantAccess();
|
||||
const tenantId = currentTenant?.id || '';
|
||||
|
||||
// Try to get tenant access directly via hook as fallback
|
||||
const { data: directTenantAccess } = useTenantAccess(
|
||||
tenantId,
|
||||
currentUser?.id || '',
|
||||
{ enabled: !!tenantId && !!currentUser?.id && !currentTenantAccess }
|
||||
);
|
||||
|
||||
const { data: teamMembers = [], isLoading } = useTeamMembers(tenantId, false, { enabled: !!tenantId }); // Show all members including inactive
|
||||
const { data: allUsers = [] } = useAllUsers();
|
||||
const { data: allUsers = [], error: allUsersError, isLoading: allUsersLoading } = useAllUsers({
|
||||
retry: false, // Don't retry on permission errors
|
||||
staleTime: 0 // Always fresh check for permissions
|
||||
});
|
||||
|
||||
// Mutations
|
||||
const addMemberMutation = useAddTeamMember();
|
||||
@@ -72,9 +83,15 @@ const TeamPage: React.FC = () => {
|
||||
{ value: TENANT_ROLES.VIEWER, label: 'Observador', count: enhancedTeamMembers.filter(m => m.role === TENANT_ROLES.VIEWER).length }
|
||||
];
|
||||
|
||||
// Use direct tenant access as fallback
|
||||
const effectiveTenantAccess = currentTenantAccess || directTenantAccess;
|
||||
|
||||
// Check if current user is the tenant owner (fallback when access endpoint fails)
|
||||
const isCurrentUserOwner = currentUser?.id === currentTenant?.owner_id;
|
||||
|
||||
// Permission checks
|
||||
const isOwner = currentTenantAccess?.role === TENANT_ROLES.OWNER;
|
||||
const canManageTeam = isOwner || currentTenantAccess?.role === TENANT_ROLES.ADMIN;
|
||||
const isOwner = effectiveTenantAccess?.role === TENANT_ROLES.OWNER || isCurrentUserOwner;
|
||||
const canManageTeam = isOwner || effectiveTenantAccess?.role === TENANT_ROLES.ADMIN;
|
||||
|
||||
const teamStats = {
|
||||
total: enhancedTeamMembers.length,
|
||||
@@ -197,29 +214,38 @@ const TeamPage: React.FC = () => {
|
||||
});
|
||||
|
||||
// Available users for adding (exclude current members)
|
||||
const availableUsers = allUsers.filter(u =>
|
||||
const availableUsers = allUsers.filter(u =>
|
||||
!enhancedTeamMembers.some(m => m.user_id === u.id)
|
||||
);
|
||||
|
||||
// Member action handlers
|
||||
const handleAddMember = async () => {
|
||||
if (!selectedUserToAdd || !selectedRoleToAdd || !tenantId) return;
|
||||
|
||||
try {
|
||||
await addMemberMutation.mutateAsync({
|
||||
tenantId,
|
||||
userId: selectedUserToAdd,
|
||||
role: selectedRoleToAdd,
|
||||
});
|
||||
|
||||
addToast('Miembro agregado exitosamente', { type: 'success' });
|
||||
setShowAddForm(false);
|
||||
setSelectedUserToAdd('');
|
||||
setSelectedRoleToAdd(TENANT_ROLES.MEMBER);
|
||||
} catch (error) {
|
||||
addToast('Error al agregar miembro', { type: 'error' });
|
||||
// Force reload tenant access if missing
|
||||
React.useEffect(() => {
|
||||
if (currentTenant?.id && !currentTenantAccess) {
|
||||
console.log('Forcing tenant access reload for tenant:', currentTenant.id);
|
||||
// You can trigger a manual reload here if needed
|
||||
}
|
||||
};
|
||||
}, [currentTenant?.id, currentTenantAccess]);
|
||||
|
||||
// Debug logging
|
||||
console.log('TeamPage Debug:', {
|
||||
canManageTeam,
|
||||
isOwner,
|
||||
isCurrentUserOwner,
|
||||
currentUser: currentUser?.id,
|
||||
currentTenant: currentTenant?.id,
|
||||
tenantOwner: currentTenant?.owner_id,
|
||||
currentTenantAccess,
|
||||
directTenantAccess,
|
||||
effectiveTenantAccess,
|
||||
tenantAccess: effectiveTenantAccess?.role,
|
||||
allUsers: allUsers.length,
|
||||
allUsersError,
|
||||
allUsersLoading,
|
||||
availableUsers: availableUsers.length,
|
||||
enhancedTeamMembers: enhancedTeamMembers.length
|
||||
});
|
||||
|
||||
// Member action handlers - removed unused handleAddMember since modal handles it directly
|
||||
|
||||
const handleRemoveMember = async (memberUserId: string) => {
|
||||
if (!tenantId) return;
|
||||
@@ -276,7 +302,7 @@ const TeamPage: React.FC = () => {
|
||||
title="Gestión de Equipo"
|
||||
description="Administra los miembros del equipo, roles y permisos"
|
||||
actions={
|
||||
canManageTeam && availableUsers.length > 0 ? [{
|
||||
canManageTeam ? [{
|
||||
id: 'add-member',
|
||||
label: 'Agregar Miembro',
|
||||
icon: Plus,
|
||||
@@ -351,7 +377,7 @@ const TeamPage: React.FC = () => {
|
||||
</Card>
|
||||
|
||||
{/* Add Member Button */}
|
||||
{canManageTeam && availableUsers.length > 0 && filteredMembers.length > 0 && (
|
||||
{canManageTeam && filteredMembers.length > 0 && (
|
||||
<div className="flex justify-end">
|
||||
<Button
|
||||
onClick={() => setShowAddForm(true)}
|
||||
@@ -406,7 +432,7 @@ const TeamPage: React.FC = () => {
|
||||
: "Este tenant aún no tiene miembros del equipo"
|
||||
}
|
||||
</p>
|
||||
{canManageTeam && availableUsers.length > 0 && (
|
||||
{canManageTeam && (
|
||||
<Button
|
||||
onClick={() => setShowAddForm(true)}
|
||||
variant="primary"
|
||||
|
||||
Reference in New Issue
Block a user