diff --git a/server/web_app/config/services.yaml b/server/web_app/config/services.yaml index 2d6a76f94dce138741e2d63ae83a11c1879031d9..ab18fc625d9168e68cd129212b222f13eac233db 100644 --- a/server/web_app/config/services.yaml +++ b/server/web_app/config/services.yaml @@ -11,6 +11,10 @@ services: autowire: true # Automatically injects dependencies in your services. autoconfigure: true # Automatically registers your services as commands, event subscribers, etc. + App\EventListener\ExceptionListener: + tags: + - { name: kernel.event_listener, event: kernel.exception } + # makes classes in src/ available to be used as services # this creates a service per class whose id is the fully-qualified class name App\: diff --git a/server/web_app/public/css/error.css b/server/web_app/public/css/error.css new file mode 100644 index 0000000000000000000000000000000000000000..3312cd5493da8820d848304f91776c4de4a717f8 --- /dev/null +++ b/server/web_app/public/css/error.css @@ -0,0 +1,32 @@ +@import url('global.css'); + +.error-container { + text-align: center; + padding: 50px; + max-width: 600px; + margin-top: 10%; +} + +h1 { + font-size: 36px; + color: #dc3545; +} + +p { + font-size: 18px; + color: #666; +} + +.btn { + display: inline-block; + padding: 12px 18px; + margin: 10px; + border-radius: 5px; + text-decoration: none; + background-color: var(--color-hover); + color: white; +} + +.btn:hover { + background-color: #0056b3; +} diff --git a/server/web_app/public/css/home.css b/server/web_app/public/css/home.css new file mode 100644 index 0000000000000000000000000000000000000000..8d4f955d2069185b1dce181681646a6ab1e47471 --- /dev/null +++ b/server/web_app/public/css/home.css @@ -0,0 +1,58 @@ +@import url('global.css'); + +.home-container { + text-align: center; + padding: 50px; + max-width: 600px; + margin: auto; +} + +.guest-content { + background: #f9f9f9; + padding: 30px; + border-radius: 10px; + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); +} + +.gift-image { + width: 180px; + height: auto; + margin-bottom: 20px; +} + +h2, h3 { + color: #333; +} + +p { + font-size: 16px; + color: #666; +} + +.btn { + display: inline-block; + padding: 12px 18px; + margin: 10px; + border-radius: 5px; + text-decoration: none; + font-weight: bold; + transition: background 0.3s ease; +} + +.btn-primary { + background-color: #28a745; + color: white; +} + +.btn-primary:hover { + background-color: #218838; +} + +.btn { + background-color: var(--color-hover); + color: white; +} + +.btn:hover { + background-color: #0056b3; +} diff --git a/server/web_app/public/css/users.css b/server/web_app/public/css/users.css index 8caf7e06603beafad437b281c9e9f559bdf585aa..de53fd5c914bf2feac72a12268a5f4ffc6ee9599 100644 --- a/server/web_app/public/css/users.css +++ b/server/web_app/public/css/users.css @@ -48,3 +48,29 @@ button:disabled { .popup button { margin: 10px; } + +.pagination { + text-align: center; + margin-top: 20px; +} + +.pagination button { + display: inline-block; + padding: 8px 12px; + margin: 0 5px; + border-radius: 4px; + background-color: var(--color-hover); + color: white; + border: none; + cursor: pointer; +} + +.pagination button:hover { + background-color: #0056b3; +} + +.pagination .active { + font-weight: bold; + background-color: #004085; +} + diff --git a/server/web_app/public/css/wishlist.css b/server/web_app/public/css/wishlist.css index a5084e6212544572d2c8c94df8a7158edc2b4289..415a35820b8d1526262fa6b957d6f8a8b2964e83 100644 --- a/server/web_app/public/css/wishlist.css +++ b/server/web_app/public/css/wishlist.css @@ -19,3 +19,29 @@ button:disabled { background-color: var(--color-light); color: black; } + +.pagination { + text-align: center; + margin-top: 20px; +} + +.pagination button { + display: inline-block; + padding: 8px 12px; + margin: 0 5px; + border-radius: 4px; + background-color: var(--color-hover); + color: white; + border: none; + cursor: pointer; +} + +.pagination button:hover { + background-color: #0056b3; +} + +.pagination .active { + font-weight: bold; + background-color: #004085; +} + diff --git a/server/web_app/public/js/users.js b/server/web_app/public/js/users.js index 9f069318a86ba29e5cc1acc8f169304f5fbdf29a..280acaa675198ae91b9ddee1eb51474e4ff1e76f 100644 --- a/server/web_app/public/js/users.js +++ b/server/web_app/public/js/users.js @@ -4,8 +4,11 @@ let currentAction = null; let currentUserId = null; let actionType = null; // New variable to track whether it's block or unblock -async function fetchUsers() { - const response = await fetch(`${ROUTE}:${PORT}/users?userRole=user`); +let currentPageUsers = 1; +const usersPerPage = 5; + +async function fetchUsers(page=1) { + const response = await fetch(`${ROUTE}:${PORT}/users?userRole=user&page=${page}&max=${usersPerPage}`); const data = await response.json(); const tableBody = document.querySelector('#usersTable tbody'); tableBody.innerHTML = ''; // Clear current table rows @@ -26,6 +29,26 @@ async function fetchUsers() { `; tableBody.appendChild(row); }); + + setupUserPagination(2, page); +} + +// Función para crear la paginación visualmente +function setupUserPagination(totalPages, currentPage) { + const paginationContainer = document.getElementById('userPagination'); + paginationContainer.innerHTML = ''; + + if (currentPage > 1) { + paginationContainer.innerHTML += `<button onclick="fetchUsers(${currentPage - 1})">« Prev</button>`; + } + + for (let i = 1; i <= totalPages; i++) { + paginationContainer.innerHTML += `<button class="${i === currentPage ? 'active' : ''}" onclick="fetchUsers(${i})">${i}</button>`; + } + + if (currentPage < totalPages) { + paginationContainer.innerHTML += `<button onclick="fetchUsers(${currentPage + 1})">Next »</button>`; + } } // Toggle block/unblock @@ -109,4 +132,4 @@ async function deleteUser(userId) { } } // Fetch users when the page loads -window.onload = fetchUsers; +window.onload = fetchUsers(currentPageUsers); diff --git a/server/web_app/public/js/wishlist.js b/server/web_app/public/js/wishlist.js index cd3965dad5ab38be0b588663ef73b79f48dab2de..ca34fa7dea5236e3ee95ff68ba1eb13a0d81981a 100644 --- a/server/web_app/public/js/wishlist.js +++ b/server/web_app/public/js/wishlist.js @@ -1,23 +1,42 @@ const ROUTE = 'http://34.70.36.158'; const PORT = '8080'; +let currentPage = 1; +const itemsPerPage = 5; // Obtener el parámetro `userId` de la URL const urlParams = new URLSearchParams(window.location.search); // Function to fetch wishlists and populate the table -async function fetchData() { - const url = `${ROUTE}:${PORT}/wishLists?userId=${userId}`; +async function fetchData(page = 1) { + const url = `${ROUTE}:${PORT}/wishLists?userId=${userId}&page=${page}&limit=${itemsPerPage}`; try { const response = await fetch(url); const data = await response.json(); - console.log(data) populateTable(data.wishLists); // Populate the table with the fetched data + setupPagination(2, page); } catch (error) { console.error('Error fetching data:', error); } } +function setupPagination(totalPages, currentPage) { + const paginationContainer = document.getElementById('pagination'); + paginationContainer.innerHTML = ''; + + if (currentPage > 1) { + paginationContainer.innerHTML += `<button onclick="fetchData(${currentPage - 1})">« Prev</button>`; + } + + for (let i = 1; i <= totalPages; i++) { + paginationContainer.innerHTML += `<button class="${i === currentPage ? 'active' : ''}" onclick="fetchData(${i})">${i}</button>`; + } + + if (currentPage < totalPages) { + paginationContainer.innerHTML += `<button onclick="fetchData(${currentPage + 1})">Next »</button>`; + } +} + // Function to populate the table with the wishlists function populateTable(data) { const tableBody = document.getElementById('dataBody'); @@ -69,4 +88,4 @@ function detailsItem(id) { } // Fetch the wishlists when the page loads -window.onload = fetchData; +window.onload = fetchData(currentPage); diff --git a/server/web_app/src/EventListener/ExceptionListener.php b/server/web_app/src/EventListener/ExceptionListener.php new file mode 100644 index 0000000000000000000000000000000000000000..0ce6d55cd325bcb5f46af0154566a25fa130a23c --- /dev/null +++ b/server/web_app/src/EventListener/ExceptionListener.php @@ -0,0 +1,30 @@ +<?php + +namespace App\EventListener; + +use Psr\Log\LoggerInterface; +use Symfony\Component\HttpFoundation\RedirectResponse; +use Symfony\Component\HttpKernel\Event\ExceptionEvent; +use Symfony\Component\Routing\RouterInterface; +use Symfony\Component\EventDispatcher\Attribute\AsEventListener; + +#[AsEventListener(event: 'kernel.exception')] +class ExceptionListener +{ + private RouterInterface $router; + private LoggerInterface $logger; + + public function __construct(RouterInterface $router, LoggerInterface $logger) + { + $this->router = $router; + $this->logger = $logger; + } + + public function onKernelException(ExceptionEvent $event) + { + $this->logger->error('🛑 ExceptionListener se ejecutó y redirige a /error'); + + $response = new RedirectResponse($this->router->generate('error')); + $event->setResponse($response); + } +} diff --git a/server/web_app/templates/error.html.twig b/server/web_app/templates/error.html.twig index f17a6b72a569ff2ebaa3e0119345b2d9bc9671e5..16312bb7c91972c4a6754a34df59a48f8b87414f 100644 --- a/server/web_app/templates/error.html.twig +++ b/server/web_app/templates/error.html.twig @@ -1 +1,13 @@ -{% block body %} This page does not exist or you do not have rigths to see {% endblock %} \ No newline at end of file +{% extends 'base.html.twig' %} + +{% block styles %} + <link rel="stylesheet" href="{{ asset('css/error.css') }}"> +{% endblock %} + +{% block body %} + <div class="error-container"> + <h1>Error</h1> + <p>This page does not exist or you do not have rigths to see.</p> + <a href="{{ path('home') }}" class="btn">Return to Homepage</a> + </div> +{% endblock %} \ No newline at end of file diff --git a/server/web_app/templates/home.html.twig b/server/web_app/templates/home.html.twig index 06d07ac7e2611893faa199e9a9867c77c5078bb5..76ba4bdb7ab02d8c650409642cdba2aa6deb4929 100644 --- a/server/web_app/templates/home.html.twig +++ b/server/web_app/templates/home.html.twig @@ -1,3 +1,31 @@ {% extends 'base.html.twig' %} -{% block body %} Welcome {% endblock %} +{% block styles %} + <link rel="stylesheet" href="{{ asset('css/home.css') }}"> +{% endblock %} + +{% block body %} + <section class="home-container container"> + {% if app.user %} + <h2>Welcome, {{ app.user.username }}!</h2> + <p>You are now logged in and ready to explore our platform.</p> + <p>Feel free to navigate through your dashboard, manage your wishlists, and connect with others.</p> + {% else %} + <div class="guest-content"> + <img src="{{ asset('img/gifts.png') }}" alt="Gift" class="gift-image"> + + <h2>Discover a World of Possibilities</h2> + <p>Are you curious about what we do and how we can help you? Learn more about our platform and how it can enhance your experience.</p> + <a href="{{ path('about') }}" class="btn">Learn More About Us</a> + + <h3>Already have an account?</h3> + <p>If you're already part of our community, log in now to access your account and continue where you left off.</p> + <a href="{{ path('app_login') }}" class="btn">Sign In</a> + + <h3>Join Us Today!</h3> + <p>Creating an account is quick and easy. Start managing your wishlists, sharing experiences, and making the most out of our platform.</p> + <a href="#" class="btn btn-primary">Create an Account</a> + </div> + {% endif %} + </section> +{% endblock %} diff --git a/server/web_app/templates/usersManagement.html.twig b/server/web_app/templates/usersManagement.html.twig index 93a4a7f8b621cc1d8a30538eedaac2deb7f4b5fa..86a57b6f875154e4bb840160284b47bd3b19165a 100644 --- a/server/web_app/templates/usersManagement.html.twig +++ b/server/web_app/templates/usersManagement.html.twig @@ -33,4 +33,6 @@ </div> <script src="{{ asset('js/users.js') }}"></script> + + <div id="userPagination" class="pagination"></div> {% endblock %} diff --git a/server/web_app/templates/wishList.html.twig b/server/web_app/templates/wishList.html.twig index 443db77cce5487203d28ef82f5a3aa60b6663989..9be12c80a74225f1d93895aafe4eb4282d19e544 100644 --- a/server/web_app/templates/wishList.html.twig +++ b/server/web_app/templates/wishList.html.twig @@ -32,4 +32,6 @@ </script> <script src="{{ asset('js/wishlist.js') }}"></script> + + <div id="pagination" class="pagination"></div> {% endblock %}