i18n: UsersView completamente traducido (headers, labels, empty/error states)

This commit is contained in:
2026-05-27 20:02:53 -05:00
parent 27303ab3d4
commit efa68d8705
+21 -19
View File
@@ -1,5 +1,6 @@
<script setup lang="ts">
import { ref, onMounted, computed } from 'vue'
import { useI18n } from 'vue-i18n'
import { AgGridVue } from 'ag-grid-vue3'
import type { ColDef } from 'ag-grid-community'
import { ModuleRegistry, AllCommunityModule } from 'ag-grid-community'
@@ -18,6 +19,7 @@ import {
ModuleRegistry.registerModules([AllCommunityModule])
const { t } = useI18n()
const store = useUsersStore()
const gridReady = ref(false)
@@ -63,10 +65,10 @@ const stats = computed(() => ({
}, {} as Record<string, number>),
}))
const columnDefs: ColDef[] = [
const columnDefs = computed<ColDef[]>(() => [
{
field: 'full_name',
headerName: 'Nombre',
headerName: t('users.name'),
flex: 2,
minWidth: 180,
filter: true,
@@ -78,10 +80,10 @@ const columnDefs: ColDef[] = [
</div>`
},
},
{ field: 'email', headerName: 'Email', flex: 2, minWidth: 200, filter: true },
{ field: 'email', headerName: t('users.email'), flex: 2, minWidth: 200, filter: true },
{
field: 'role',
headerName: 'Rol',
headerName: t('users.role'),
width: 90,
filter: true,
cellRenderer: (params: any) => {
@@ -90,11 +92,11 @@ const columnDefs: ColDef[] = [
return `<span class="inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${cls}">${params.value}</span>`
},
},
{ field: 'cell', headerName: 'Célula', width: 110, filter: true, cellRenderer: (p: any) => p.value || '—' },
{ field: 'seniority', headerName: 'Seniority', width: 100, filter: true, cellRenderer: (p: any) => p.value || '—' },
{ field: 'cell', headerName: t('users.cell'), width: 110, filter: true, cellRenderer: (p: any) => p.value || '—' },
{ field: 'seniority', headerName: t('users.seniority'), width: 100, filter: true, cellRenderer: (p: any) => p.value || '—' },
{
field: 'projects_count',
headerName: 'Proyectos',
headerName: t('users.projects'),
width: 100,
filter: 'agNumberColumnFilter',
cellRenderer: (params: any) => {
@@ -105,7 +107,7 @@ const columnDefs: ColDef[] = [
},
{
field: 'projects',
headerName: 'Asignaciones',
headerName: t('users.assignments'),
flex: 3,
minWidth: 200,
cellRenderer: (params: any) => {
@@ -114,7 +116,7 @@ const columnDefs: ColDef[] = [
return p.map((n: string) => `<span class="inline-flex rounded-full bg-muted px-2 py-0.5 text-xs mr-1">${n}</span>`).join('')
},
},
]
])
onMounted(() => {
store.fetchAll()
@@ -126,13 +128,13 @@ onMounted(() => {
<!-- Header -->
<div class="flex items-center justify-between">
<div>
<h2 class="text-2xl font-bold tracking-tight">Equipo</h2>
<h2 class="text-2xl font-bold tracking-tight">{{ t('users.teamTitle') }}</h2>
<p class="text-muted-foreground">
{{ store.users.length }} miembros · {{ store.employees.length }} asignaciones en KAPPA
{{ t('users.teamSubtitle', { users: store.users.length, emps: store.employees.length }) }}
</p>
</div>
<Badge variant="outline" class="text-sm">
{{ stats.active }} activos
{{ t('users.activeCount', { count: stats.active }) }}
</Badge>
</div>
@@ -150,13 +152,13 @@ onMounted(() => {
<template v-else-if="store.error">
<div class="flex flex-col items-center gap-3 py-12 text-center">
<IconExclamationCircle class="size-10 text-destructive" />
<p class="text-lg font-medium">Error al cargar usuarios</p>
<p class="text-lg font-medium">{{ t('users.loadError') }}</p>
<p class="text-sm text-muted-foreground">{{ store.error }}</p>
<button
class="rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90"
@click="store.fetchAll()"
>
Reintentar
{{ t('common.retry') }}
</button>
</div>
</template>
@@ -165,8 +167,8 @@ onMounted(() => {
<template v-else-if="store.users.length === 0">
<div class="flex flex-col items-center gap-3 py-12 text-center">
<IconUsers class="size-10 text-muted-foreground" />
<p class="text-lg font-medium">Sin usuarios</p>
<p class="text-sm text-muted-foreground">No se encontraron usuarios en KAPPA.</p>
<p class="text-lg font-medium">{{ t('users.emptyTitle') }}</p>
<p class="text-sm text-muted-foreground">{{ t('users.emptyDescription') }}</p>
</div>
</template>
@@ -194,7 +196,7 @@ onMounted(() => {
<!-- Team Member Cards -->
<div>
<h3 class="text-sm font-semibold text-muted-foreground uppercase tracking-wider mb-3">
Miembros del equipo · {{ teamMembers.length }}
{{ t('users.teamMembers', { count: teamMembers.length }) }}
</h3>
<div class="grid grid-cols-1 gap-3 @xl:grid-cols-2 @3xl:grid-cols-3">
<Card
@@ -232,7 +234,7 @@ onMounted(() => {
{{ user.cell }}
</span>
<span v-if="user.seniority" class="capitalize">{{ user.seniority }}</span>
<span class="font-medium text-foreground">{{ user.projects_count }} proyecto{{ user.projects_count !== 1 ? 's' : '' }}</span>
<span class="font-medium text-foreground">{{ t('users.projectCount', { count: user.projects_count }) }}</span>
</div>
<div v-if="user.projects.length" class="flex flex-wrap gap-1 mt-2">
<span
@@ -254,7 +256,7 @@ onMounted(() => {
<!-- AG Grid table -->
<div>
<h3 class="text-sm font-semibold text-muted-foreground uppercase tracking-wider mb-3">
Todos los usuarios
{{ t('users.allUsers') }}
</h3>
<div
class="ag-theme-alpha-shadcn w-full rounded-lg border overflow-hidden"