Improve the frontend

This commit is contained in:
Urtzi Alfaro
2025-10-21 19:50:07 +02:00
parent 05da20357d
commit 8d30172483
105 changed files with 14699 additions and 4630 deletions

View File

@@ -283,7 +283,7 @@ const TeamPage: React.FC = () => {
if (isLoading) {
return (
<div className="p-6 space-y-6">
<div className="space-y-6">
<PageHeader
title="Gestión de Equipo"
description="Administra los miembros del equipo, roles y permisos"
@@ -300,7 +300,7 @@ const TeamPage: React.FC = () => {
return (
<div className="p-6 space-y-6">
<div className="space-y-6">
<PageHeader
title={t('settings:team.title', 'Gestión de Equipo')}
description={t('settings:team.description', 'Administra los miembros del equipo, roles y permisos')}
@@ -368,48 +368,46 @@ const TeamPage: React.FC = () => {
] as FilterConfig[]}
/>
{/* Add Member Button */}
{canManageTeam && filteredMembers.length > 0 && (
<div className="flex justify-end">
<Button
onClick={() => setShowAddForm(true)}
variant="primary"
size="md"
className="font-medium px-4 py-2 shadow-sm hover:shadow-md transition-all duration-200"
>
<Plus className="w-4 h-4 mr-2 flex-shrink-0" />
<span>Agregar Miembro</span>
</Button>
</div>
)}
{/* Team Members List - Responsive grid */}
<div className="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-4 lg:gap-6">
{filteredMembers.map((member) => (
<StatusCard
key={member.id}
id={`team-member-${member.id}`}
statusIndicator={getMemberStatusConfig(member)}
title={member.user?.full_name || member.user_full_name}
subtitle={member.user?.email || member.user_email}
primaryValue={Math.floor((Date.now() - new Date(member.joined_at).getTime()) / (1000 * 60 * 60 * 24))}
primaryValueLabel="días"
secondaryInfo={{
label: 'Estado',
value: member.is_active ? 'Activo' : 'Inactivo'
}}
metadata={[
`Email: ${member.user?.email || member.user_email}`,
`Teléfono: ${member.user?.phone || 'No disponible'}`,
...(member.role === TENANT_ROLES.OWNER ? ['🏢 Propietario de la organización'] : [])
]}
actions={getMemberActions(member)}
className={`
${!member.is_active ? 'opacity-75' : ''}
transition-all duration-200 hover:scale-[1.02]
`}
/>
))}
{filteredMembers.map((member: any) => {
const user = member.user;
const daysInTeam = Math.floor((Date.now() - new Date(member.joined_at).getTime()) / (1000 * 60 * 60 * 24));
const lastLogin = user?.last_login ? new Date(user.last_login).toLocaleDateString('es-ES', {
year: 'numeric',
month: 'short',
day: 'numeric'
}) : 'Nunca';
return (
<StatusCard
key={member.id}
id={`team-member-${member.id}`}
statusIndicator={getMemberStatusConfig(member)}
title={user?.full_name || member.user_full_name || 'Usuario'}
subtitle={user?.email || member.user_email || ''}
primaryValue={daysInTeam}
primaryValueLabel="días en el equipo"
secondaryInfo={{
label: 'Último acceso',
value: lastLogin
}}
metadata={[
`Email: ${user?.email || member.user_email || 'No disponible'}`,
`Teléfono: ${user?.phone || 'No disponible'}`,
`Idioma: ${user?.language?.toUpperCase() || 'No especificado'}`,
`Unido: ${new Date(member.joined_at).toLocaleDateString('es-ES', { year: 'numeric', month: 'short', day: 'numeric' })}`,
...(member.role === TENANT_ROLES.OWNER ? ['🏢 Propietario de la organización'] : []),
...(user?.timezone ? [`Zona horaria: ${user.timezone}`] : [])
]}
actions={getMemberActions(member)}
className={`
${!member.is_active ? 'opacity-75' : ''}
transition-all duration-200 hover:scale-[1.02]
`}
/>
);
})}
</div>
{filteredMembers.length === 0 && (