Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
Alba María Álvarez
/
front_recipes
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
572f31c6
authored
Aug 29, 2025
by
Alba María Álvarez
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
feat(UserManagement): añadida funcionalidad para mostrar listado y cambiar paginación/ordenación
parent
8e37b66b
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
64 additions
and
115 deletions
src/views/UserManagement.vue
src/views/UserManagement.vue
View file @
572f31c6
...
...
@@ -25,42 +25,53 @@
</div>
</div>
<div
v-if=
"errorMsg"
class=
"alert alert-danger"
role=
"alert"
>
{{
errorMsg
}}
</div>
<div
class=
"table-responsive"
>
<table
class=
"table table-hover align-middle"
>
<thead
class=
"table-primary-custom"
>
<tr>
<th
scope=
"col"
@
click=
"sortBy('name')"
class=
"clickable-header"
>
<th
scope=
"col"
@
click=
"sortBy
Column
('name')"
class=
"clickable-header"
>
Nombre
<i
:class=
"getSortIcon('name')"
></i>
<i
v-if=
"userStore.sortBy === 'name'"
:class=
"userStore.sortDirection === 'asc' ? 'bi-caret-up-fill' : 'bi-caret-down-fill'"
></i>
<i
v-else
class=
"bi-arrow-down-up"
></i>
</th>
<th
scope=
"col"
@
click=
"sortBy('surname')"
class=
"clickable-header"
>
<th
scope=
"col"
@
click=
"sortBy
Column
('surname')"
class=
"clickable-header"
>
Apellidos
<i
:class=
"getSortIcon('surname')"
></i>
<i
v-if=
"userStore.sortBy === 'surname'"
:class=
"userStore.sortDirection === 'asc' ? 'bi-caret-up-fill' : 'bi-caret-down-fill'"
></i>
<i
v-else
class=
"bi-arrow-down-up"
></i>
</th>
<th
scope=
"col"
@
click=
"sortBy('email')"
class=
"clickable-header"
>
<th
scope=
"col"
@
click=
"sortBy
Column
('email')"
class=
"clickable-header"
>
Email
<i
:class=
"getSortIcon('email')"
></i>
<i
v-if=
"userStore.sortBy === 'email'"
:class=
"userStore.sortDirection === 'asc' ? 'bi-caret-up-fill' : 'bi-caret-down-fill'"
></i>
<i
v-else
class=
"bi-arrow-down-up"
></i>
</th>
<th
scope=
"col"
@
click=
"sortByColumn('role')"
class=
"clickable-header"
>
Rol
<i
v-if=
"userStore.sortBy === 'role'"
:class=
"userStore.sortDirection === 'asc' ? 'bi-caret-up-fill' : 'bi-caret-down-fill'"
></i>
<i
v-else
class=
"bi-arrow-down-up"
></i>
</th>
<th
scope=
"col"
>
Rol
</th>
<th
scope=
"col"
>
Estado
</th>
<th
scope=
"col"
>
Fecha desactivado
</th>
<th
scope=
"col"
>
Acciones
</th>
</tr>
</thead>
<tbody>
<tr
v-for=
"user in
paginatedU
sers"
:key=
"user.id"
>
<tr
v-for=
"user in
userStore.u
sers"
:key=
"user.id"
>
<td>
{{
user
.
name
}}
</td>
<td>
{{
user
.
surname
}}
</td>
<td>
{{
user
.
email
}}
</td>
<td>
{{
user
.
role
}}
</td>
<td>
<span
v-if=
"
user.active
"
class=
"badge bg-custom-active"
>
Activo
</span>
<span
v-if=
"
!user.deletedAt
"
class=
"badge bg-custom-active"
>
Activo
</span>
<span
v-else
class=
"badge bg-custom-inactive"
>
Inactivo
</span>
</td>
<td>
{{
user
.
de
activatedAt
?
user
.
deactiva
tedAt
:
'-'
}}
</td>
<td>
{{
user
.
de
letedAt
?
user
.
dele
tedAt
:
'-'
}}
</td>
<td>
<div
class=
"d-flex gap-2"
>
<button
v-if=
"
user.active
"
@
click=
"deactivateUser(user.id)"
class=
"btn btn-outline-danger btn-sm"
title=
"Desactivar"
>
<button
v-if=
"
!user.deletedAt
"
@
click=
"deactivateUser(user.id)"
class=
"btn btn-outline-danger btn-sm"
title=
"Desactivar"
>
<i
class=
"bi bi-person-slash"
></i>
</button>
<button
v-else
@
click=
"reactivateUser(user.id)"
class=
"btn btn-outline-success btn-sm"
title=
"Reactivar"
>
...
...
@@ -74,17 +85,17 @@
</div>
<div
class=
"d-flex justify-content-between align-items-center mt-3"
>
<div
class=
"small text-muted"
>
Mostrando
{{
startIndex
+
1
}}
a
{{
endIndex
}}
de
{{
users
.
length
}}
usuarios
</div>
<div
class=
"small text-muted"
>
Mostrando
{{
startIndex
}}
a
{{
endIndex
}}
de
{{
userStore
.
totalElements
}}
usuarios
</div>
<nav
aria-label=
"Page navigation"
>
<ul
class=
"pagination pagination-sm mb-0 pagination-custom"
>
<li
class=
"page-item"
:class=
"
{
'disabled': currentPage === 1
}">
<
a
class=
"page-link"
href=
"#"
@
click
.
prevent=
"prevPage"
>
Anterior
</a
>
<li
class=
"page-item"
:class=
"
{
disabled: userStore.currentPage === 0
}">
<
button
class=
"page-link"
@
click=
"goToPage(userStore.currentPage - 1)"
>
Anterior
</button
>
</li>
<li
class=
"page-item"
v-for=
"page in
totalPages"
:key=
"page"
:class=
"
{ 'active': page ===
currentPage }">
<
a
class=
"page-link"
href=
"#"
@
click
.
prevent=
"goToPage(page)"
>
{{
page
}}
</a
>
<li
class=
"page-item"
v-for=
"page in
userStore.totalPages"
:key=
"page"
:class=
"
{ active: page - 1 === userStore.
currentPage }">
<
button
class=
"page-link"
@
click=
"goToPage(page - 1)"
>
{{
page
}}
</button
>
</li>
<li
class=
"page-item"
:class=
"
{
'disabled': currentPage === totalPages
}">
<
a
class=
"page-link"
href=
"#"
@
click
.
prevent=
"nextPage"
>
Siguiente
</a
>
<li
class=
"page-item"
:class=
"
{
disabled: userStore.currentPage === userStore.totalPages - 1
}">
<
button
class=
"page-link"
@
click=
"goToPage(userStore.currentPage + 1)"
>
Siguiente
</button
>
</li>
</ul>
</nav>
...
...
@@ -97,113 +108,51 @@
</
template
>
<
script
setup
>
import
{
ref
,
computed
}
from
'vue'
;
const
users
=
ref
([
{
id
:
1
,
name
:
'Adrián'
,
surname
:
'García Pérez'
,
email
:
'adrian@example.com'
,
role
:
'Usuario'
,
active
:
true
,
deactivatedAt
:
null
},
{
id
:
2
,
name
:
'Sofía'
,
surname
:
'Martínez López'
,
email
:
'sofia@example.com'
,
role
:
'Administrador'
,
active
:
true
,
deactivatedAt
:
null
},
{
id
:
3
,
name
:
'Pablo'
,
surname
:
'Díaz Ruiz'
,
email
:
'pablo@example.com'
,
role
:
'Usuario'
,
active
:
false
,
deactivatedAt
:
'2024-05-10'
},
{
id
:
4
,
name
:
'Lucía'
,
surname
:
'Fernández Gil'
,
email
:
'lucia@example.com'
,
role
:
'Usuario'
,
active
:
true
,
deactivatedAt
:
null
},
{
id
:
5
,
name
:
'Javier'
,
surname
:
'Torres Soto'
,
email
:
'javier@example.com'
,
role
:
'Usuario'
,
active
:
false
,
deactivatedAt
:
'2024-05-15'
},
{
id
:
6
,
name
:
'Carla'
,
surname
:
'Jiménez Vega'
,
email
:
'carla@example.com'
,
role
:
'Usuario'
,
active
:
true
,
deactivatedAt
:
null
},
{
id
:
7
,
name
:
'Daniel'
,
surname
:
'Sánchez Milla'
,
email
:
'daniel@example.com'
,
role
:
'Usuario'
,
active
:
true
,
deactivatedAt
:
null
},
{
id
:
8
,
name
:
'Elena'
,
surname
:
'Soto Ramos'
,
email
:
'elena@example.com'
,
role
:
'Usuario'
,
active
:
false
,
deactivatedAt
:
'2024-05-20'
}
]);
// Estado de la paginación y ordenación
const
currentPage
=
ref
(
1
);
const
itemsPerPage
=
ref
(
5
);
const
sortKey
=
ref
(
'name'
);
const
sortOrder
=
ref
(
'asc'
);
// Propiedad computada para ordenar los usuarios
const
sortedUsers
=
computed
(()
=>
{
return
users
.
value
.
slice
().
sort
((
a
,
b
)
=>
{
const
keyA
=
a
[
sortKey
.
value
];
const
keyB
=
b
[
sortKey
.
value
];
if
(
typeof
keyA
===
'string'
)
{
const
result
=
keyA
.
localeCompare
(
keyB
);
return
sortOrder
.
value
===
'asc'
?
result
:
-
result
;
}
else
{
const
result
=
keyA
-
keyB
;
return
sortOrder
.
value
===
'asc'
?
result
:
-
result
;
}
});
});
// Propiedad computada para la paginación
const
paginatedUsers
=
computed
(()
=>
{
const
start
=
(
currentPage
.
value
-
1
)
*
itemsPerPage
.
value
;
const
end
=
start
+
parseInt
(
itemsPerPage
.
value
);
return
sortedUsers
.
value
.
slice
(
start
,
end
);
});
// Propiedad computada para el número total de páginas
const
totalPages
=
computed
(()
=>
{
return
Math
.
ceil
(
users
.
value
.
length
/
itemsPerPage
.
value
);
});
// Propiedades computadas para el rango de la tabla
const
startIndex
=
computed
(()
=>
(
currentPage
.
value
-
1
)
*
itemsPerPage
.
value
);
const
endIndex
=
computed
(()
=>
{
const
end
=
startIndex
.
value
+
parseInt
(
itemsPerPage
.
value
);
return
Math
.
min
(
end
,
users
.
value
.
length
);
import
{
useUserStore
}
from
'@/stores/userStore'
;
import
{
ref
,
onMounted
,
watch
,
computed
}
from
'vue'
;
const
userStore
=
useUserStore
();
const
errorMsg
=
ref
(
null
);
const
itemsPerPage
=
ref
(
userStore
.
pageSize
);
onMounted
(
async
()
=>
{
errorMsg
.
value
=
null
;
try
{
await
userStore
.
readAll
();
}
catch
(
error
)
{
errorMsg
.
value
=
'No se pudieron cargar los usuarios. Inténtalo de nuevo más tarde.'
;
}
});
//
Métodos de paginación
//
Cambip de página
const
goToPage
=
(
page
)
=>
{
currentPage
.
value
=
page
;
};
const
prevPage
=
()
=>
{
if
(
currentPage
.
value
>
1
)
{
currentPage
.
value
--
;
}
userStore
.
readAll
(
page
,
itemsPerPage
.
value
,
userStore
.
sortBy
,
userStore
.
sortDirection
);
};
const
nextPage
=
()
=>
{
if
(
currentPage
.
value
<
totalPages
.
value
)
{
currentPage
.
value
++
;
}
// Cambio de ordenación
const
sortByColumn
=
(
column
)
=>
{
// Si es la misma columna, invierte la dirección
const
newSortDirection
=
userStore
.
sortBy
===
column
&&
userStore
.
sortDirection
===
'asc'
?
'desc'
:
'asc'
;
userStore
.
readAll
(
0
,
itemsPerPage
.
value
,
column
,
newSortDirection
)
};
// Método de ordenación
const
sortBy
=
(
key
)
=>
{
if
(
sortKey
.
value
===
key
)
{
sortOrder
.
value
=
sortOrder
.
value
===
'asc'
?
'desc'
:
'asc'
;
}
else
{
sortKey
.
value
=
key
;
sortOrder
.
value
=
'asc'
;
}
};
// Cambios en itemsPerPage
watch
(
itemsPerPage
,
(
newSize
)
=>
{
userStore
.
fetchUsers
(
0
,
newSize
,
userStore
.
sortBy
,
userStore
.
sortDirection
);
});
// Método para mostrar el icono de ordenación
const
getSortIcon
=
(
key
)
=>
{
if
(
sortKey
.
value
!==
key
)
{
return
'bi bi-sort-alpha-down-alt'
;
}
return
sortOrder
.
value
===
'asc'
?
'bi bi-sort-alpha-down'
:
'bi bi-sort-alpha-up'
;
};
// Propiedad computada para el índice de inicio
const
startIndex
=
computed
(()
=>
{
if
(
userStore
.
totalElements
===
0
)
return
0
;
return
(
userStore
.
currentPage
*
userStore
.
pageSize
)
+
1
;
});
// Métodos para activar/desactivar usuarios
const
deactivateUser
=
(
id
)
=>
{
const
user
=
users
.
value
.
find
(
u
=>
u
.
id
===
id
);
if
(
user
)
{
user
.
active
=
false
;
user
.
deactivatedAt
=
new
Date
().
toISOString
().
slice
(
0
,
10
);
alert
(
`Usuario
${
user
.
name
}
desactivado.`
);
}
};
// Propiedad computada para el índice de fin
const
endIndex
=
computed
(()
=>
{
const
end
=
(
userStore
.
currentPage
+
1
)
*
userStore
.
pageSize
;
return
Math
.
min
(
end
,
userStore
.
totalElements
);
});
const
reactivateUser
=
(
id
)
=>
{
const
user
=
users
.
value
.
find
(
u
=>
u
.
id
===
id
);
if
(
user
)
{
user
.
active
=
true
;
user
.
deactivatedAt
=
null
;
alert
(
`Usuario
${
user
.
name
}
reactivado.`
);
}
};
</
script
>
<
style
scoped
>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment