From bbf8f6ba3667b58cd3f4f12898db600964469c7b Mon Sep 17 00:00:00 2001 From: Anamaria Miranda <anny13miranda@gmail.com> Date: Wed, 26 Mar 2025 01:08:54 +0100 Subject: [PATCH 1/2] Added full management insights and wishlits --- server/web_app/public/css/global.css | 23 ++- server/web_app/public/css/insights.css | 55 ++++++++ server/web_app/public/css/users.css | 17 --- server/web_app/public/js/insights.js | 132 ++++++++++++++++++ server/web_app/public/js/users.js | 2 +- .../src/Controller/DashboardController.php | 13 +- server/web_app/templates/dashboard.html.twig | 2 +- server/web_app/templates/insights.html.twig | 68 ++++++++- .../templates/usersManagement.html.twig | 2 +- 9 files changed, 285 insertions(+), 29 deletions(-) diff --git a/server/web_app/public/css/global.css b/server/web_app/public/css/global.css index a868886..00e58ea 100644 --- a/server/web_app/public/css/global.css +++ b/server/web_app/public/css/global.css @@ -37,7 +37,6 @@ * { box-sizing: border-box; font-family: var(--font-family-style); - line-height: var(--line-heigth-normal); font-weight: var(--font-weight-regular); margin: 0; padding: 0; @@ -50,3 +49,25 @@ body { .container { margin: var(--padding-space-large); } + +.table-container { + margin: var(--padding-space-large); + overflow-x: auto; +} + +table { + width: 100%; + border-collapse: collapse; + background-color: var(--color-complementary); +} + +table th, table td { + border: var(--border-thin) solid var(--color-hover); + padding: var(--padding-space-small); + text-align: left; +} + +table th { + background-color: var(--color-hover); + color: var(--color-complementary); +} diff --git a/server/web_app/public/css/insights.css b/server/web_app/public/css/insights.css index 20d32d7..83179fb 100644 --- a/server/web_app/public/css/insights.css +++ b/server/web_app/public/css/insights.css @@ -1 +1,56 @@ @import url('global.css'); + +.controls { + display: flex; + gap: 20px; + margin-bottom: 20px; +} + +.selector { + display: inline-block; +} + +button { + padding: 8px 16px; + background-color: #4CAF50; + color: white; + border: none; + border-radius: 5px; + cursor: pointer; +} + +button:disabled { + background-color: grey; + +} + +.active { + background-color: green; + padding: var(--padding-space-small); + border-radius: 5%; +} + +.inactive { + background-color: var(--color-light); + padding: var(--padding-space-small); + border-radius: 5%; +} + +#filterControl { + display: flex; + justify-items: center; + margin: var(--margin-space-large); + flex-wrap: wrap; +} + +#pageTitle { + margin-top: 2%; +} + +select { + padding: 10px; + border: 2px solid #ccc; + border-radius: 5px; + background-color: #f9f9f9; + width: 200px; +} \ No newline at end of file diff --git a/server/web_app/public/css/users.css b/server/web_app/public/css/users.css index ace1e04..8caf7e0 100644 --- a/server/web_app/public/css/users.css +++ b/server/web_app/public/css/users.css @@ -1,22 +1,5 @@ @import url('global.css'); -table { - width: 100%; - border-collapse: collapse; - background-color: var(--color-complementary); -} - -table th, table td { - border: var(--border-thin) solid var(--color-hover); - padding: var(--padding-space-small); - text-align: left; -} - -table th { - background-color: var(--color-hover); - color: var(--color-complementary); -} - button { padding: 6px 12px; margin: var(--margin-space-xsmall); diff --git a/server/web_app/public/js/insights.js b/server/web_app/public/js/insights.js index e69de29..2c3cfab 100644 --- a/server/web_app/public/js/insights.js +++ b/server/web_app/public/js/insights.js @@ -0,0 +1,132 @@ +const ROUTE = 'http://localhost'; +const PORT = '8080'; + +// State management +let currentSort, currentTarget; +let isFetching = false; +const button = document.getElementById("refreshBtn"); +const form = document.getElementById("filterControl"); +const title = document.getElementById("pageTitle"); +const wishTitle = "Top 3 wishlists with the highest total purchase amount"; +const itemTitle = "Top 3 most expensive purchased items"; +const trItem = document.getElementById("itemsTable"); +const trWish = document.getElementById("wishlistsTable"); + +// Initialize from URL +function initFromUrl() { + const path = window.location.pathname; + const segments = path.split("/").filter(segment => segment !== ""); + currentSort = segments[segments.length - 1]; + currentTarget = segments[segments.length - 2]; +} + +// Main data loading function +async function fetchData() { + let url = ''; + if (currentTarget === 'items') { + url = `${ROUTE}:${PORT}/items?sortBy=price&sort=${currentSort}&onlyBought=true`; + } else { + url = `${ROUTE}:${PORT}/wishLists/sortedByTotalBought?sort=${currentSort}`; + } + + try { + const response = await fetch(url); + const data = await response.json(); + + // Populate table based on target + const tableBody = document.getElementById('dataBody'); + tableBody.innerHTML = ''; + + const itemsToDisplay = currentTarget === 'wishlists' ? data.wishLists : data.items; + populateTable(itemsToDisplay); + + title.innerText = currentTarget === "wishlists" ? wishTitle : itemTitle; + + if (currentTarget === "wishlists") { + trItem.hidden = true; + trWish.hidden = false; + } else { + trWish.hidden = true; + trItem.hidden = false; + } + + } catch (error) { + console.error('Error fetching data:', error); + } finally { + isFetching = false; + button.disabled = false; + } +} + +// Table population +function populateTable(data) { + const tableBody = document.getElementById('dataBody'); + + data.forEach(key => { + const row = document.createElement('tr'); + + if (currentTarget === 'items') { + row.innerHTML = ` + <td>${key.id}</td> + <td>${key.title}</td> + <td>${key.description}</td> + <td>${key.price}</td> + <td>${key.wishList.name}</td> + <td class="active">${key.wishList.isActive ? 'Active' : 'Unactive'}</td> + <td>${key.wishList.createdAt}</td> + <td>${key.wishList.expirationDate}</td> + <td>${key.wishList.user.username}</td> + `; + } else { + row.innerHTML = ` + <td>${key.wishList.id}</td> + <td>${key.wishList.name}</td> + <td>${key.wishList.description}</td> + <td>${key.totalPrice}</td> + <td> + <span class="${key.isActive ? 'active' : 'inactive'}"> + ${key.isActive ? 'Active' : 'Inactive'} + </span> + </td> + <td>${key.wishList.user.username}</td> + <td>${key.wishList.createdAt}</td> + <td>${key.wishList.expirationDate}</td> + `; + } + + tableBody.appendChild(row); + }); +} + +// Controlled data loading +function loadData() { + if (isFetching) return; + + isFetching = true; + button.disabled = true; + fetchData(); +} + +// Form submission handler +form.addEventListener("submit", function(event) { + event.preventDefault(); + + currentSort = document.getElementById('sort').value; + currentTarget = document.getElementById('target').value; + + // Update URL without reload + const newUrl = `/dashboard/insights/${currentTarget}/${currentSort}`; + window.history.pushState({ path: newUrl }, '', newUrl); + + loadData(); +}); + +// Handle browser navigation +window.addEventListener('popstate', () => { + initFromUrl(); + loadData(); +}); + +// Initial setup +initFromUrl(); +loadData(); \ No newline at end of file diff --git a/server/web_app/public/js/users.js b/server/web_app/public/js/users.js index c5ee461..6d4fdae 100644 --- a/server/web_app/public/js/users.js +++ b/server/web_app/public/js/users.js @@ -5,7 +5,7 @@ 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`); + const response = await fetch(`${ROUTE}:${PORT}/users?userRole=user`); const data = await response.json(); const tableBody = document.querySelector('#usersTable tbody'); tableBody.innerHTML = ''; // Clear current table rows diff --git a/server/web_app/src/Controller/DashboardController.php b/server/web_app/src/Controller/DashboardController.php index 0c9a0ec..a353f1e 100644 --- a/server/web_app/src/Controller/DashboardController.php +++ b/server/web_app/src/Controller/DashboardController.php @@ -29,13 +29,12 @@ class DashboardController extends AbstractController return $this->render('usersManagement.html.twig'); } - #[Route('/insights', name: 'manageInsights')] - public function items(): Response + #[Route('/insights/{type}/{order}', name: 'manageInsights', defaults: ['type' => 'wishlists', 'order' => 'asc'])] + public function insights(string $type, string $order): Response { - if (!$this->isGranted('ROLE_ADMIN')) { - return $this->redirectToRoute('error'); - } - - return $this->render('insights.html.twig'); + return $this->render('insights.html.twig', [ + 'target' => $type, + 'sort' => $order, + ]); } } diff --git a/server/web_app/templates/dashboard.html.twig b/server/web_app/templates/dashboard.html.twig index 75ab75c..ccec0af 100644 --- a/server/web_app/templates/dashboard.html.twig +++ b/server/web_app/templates/dashboard.html.twig @@ -6,7 +6,7 @@ {% block body %} <section class="container"> - <a class="card" href="{{ path('manageInsights') }}"> + <a class="card" href="{{ path('manageInsights', {'type': 'items', 'order': 'desc'}, false ) }}"> <article> <img src="{{ asset('img/gifts.png') }}" alt=""> <h4>Insights</h4> diff --git a/server/web_app/templates/insights.html.twig b/server/web_app/templates/insights.html.twig index f682d0e..b783655 100644 --- a/server/web_app/templates/insights.html.twig +++ b/server/web_app/templates/insights.html.twig @@ -1,9 +1,75 @@ {% extends 'base.html.twig' %} {% block styles %} - <link rel="stylesheet" href="{{ asset('css/insights.css') }}"> + <link rel="stylesheet" href="{{ asset('css/insights.css') }}"> {% endblock %} {% block body %} + {% if target == 'items' %} + <h3 id="pageTitle">Top 3 most expensive purchased items</h3> + {% else %} + <h3 id="pageTitle">Top 3 wishlists with the highest total purchase amount</h3> + {% endif %} + + <!-- Controls --> + <form id="filterControl" class="controls"> + <div class="selector"> + <label for="sort">Sort By:</label> + <select id="sort"> + <option value="asc" {% if sort == 'asc' %}selected{% endif %}>Ascending</option> + <option value="desc" {% if sort == 'desc' %}selected{% endif %}>Descending</option> + </select> + </div> + <div class="selector"> + <label for="target">Select Target:</label> + <select id="target"> + <option value="wishlists" {% if target == 'wishlists' %}selected{% endif %}>Wishlists</option> + <option value="items" {% if target == 'items' %}selected{% endif %}>Items</option> + </select> + </div> + <button id="refreshBtn" disabled type="submit">Update</button> + </form> + <!-- Table to show data --> + <section class="table-container"> + <table id="dataTable"> + <thead> + <tr id="itemsTable" + {% if target == 'wishlists' %} + hidden + {% endif %} + > + <th>ID</th> + <th>Title</th> + <th>Description</th> + <th>Price</th> + <th>WishList name</th> + <th>Status</th> + <th>Create at</th> + <th>Expiration date</th> + <th>WishList owner</th> + </tr> + + <tr id="wishlistsTable" + {% if target == 'items' %} + hidden + {% endif %} + > + <th>ID</th> + <th>Name</th> + <th>Description</th> + <th>Total Amount</th> + <th>Status</th> + <th>WishList owner</th> + <th>Creation Date</th> + <th>Expiration date</th> + </tr> + </thead> + <tbody id="dataBody"> + <!-- Data will be populated here dynamically --> + </tbody> + </table> + </section> + + <script src="{{ asset('js/insights.js') }}"></script> {% endblock %} diff --git a/server/web_app/templates/usersManagement.html.twig b/server/web_app/templates/usersManagement.html.twig index 1c16889..93a4a7f 100644 --- a/server/web_app/templates/usersManagement.html.twig +++ b/server/web_app/templates/usersManagement.html.twig @@ -7,7 +7,7 @@ {% block body %} <h3>User control panel</h3> - <article class="container"> + <article class="table-container"> <table id="usersTable"> <thead> <tr> -- GitLab From cf032370adae8f8f23a605b9df2fb3ecf198de56 Mon Sep 17 00:00:00 2001 From: Anamaria Miranda <anny13miranda@gmail.com> Date: Wed, 26 Mar 2025 03:01:12 +0100 Subject: [PATCH 2/2] Styles finished --- server/web_app/public/css/about.css | 57 ++++++++++++ server/web_app/public/css/global.css | 2 +- server/web_app/public/css/login.css | 73 ++++++++++++++++ server/web_app/public/css/menu.css | 86 +++++++++++++++---- server/web_app/public/css/wishlist.css | 21 +++++ server/web_app/public/js/wishlist.js | 72 ++++++++++++++++ server/web_app/public/svg/menu.svg | 16 ++++ .../web_app/src/Controller/MainController.php | 18 ++++ server/web_app/templates/about.html.twig | 37 ++++++++ server/web_app/templates/base.html.twig | 5 +- server/web_app/templates/login.html.twig | 37 ++++---- server/web_app/templates/menu.html.twig | 10 ++- server/web_app/templates/wishList.html.twig | 35 ++++++++ 13 files changed, 433 insertions(+), 36 deletions(-) create mode 100644 server/web_app/public/css/about.css create mode 100644 server/web_app/public/css/wishlist.css create mode 100644 server/web_app/public/js/wishlist.js create mode 100644 server/web_app/public/svg/menu.svg create mode 100644 server/web_app/templates/about.html.twig create mode 100644 server/web_app/templates/wishList.html.twig diff --git a/server/web_app/public/css/about.css b/server/web_app/public/css/about.css new file mode 100644 index 0000000..b386d2f --- /dev/null +++ b/server/web_app/public/css/about.css @@ -0,0 +1,57 @@ +@import url('global.css'); + +.about-container { + background-color: #f4f4f4; + color: #333; + padding: 40px; + margin: 20px; + border-radius: 8px; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + max-width: 900px; + margin: 50px auto; + text-align: center; +} + +h1 { + font-size: 2.5rem; + color: #007bff; + margin-bottom: 20px; +} + +.intro { + font-size: 1.1rem; + line-height: 1.6; + margin-bottom: 40px; + color: #555; +} + +.team { + display: flex; + flex-direction: column; + gap: 30px; +} + +.team-member { + background-color: #ffffff; + padding: 20px; + border-radius: 8px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + +.team-member h3 { + font-size: 1.5rem; + color: #333; +} + +.team-member p { + font-size: 1.1rem; + margin: 5px 0; + color: #666; +} + +.footer { + margin-top: 40px; + font-size: 1.2rem; + font-weight: bold; + color: #444; +} diff --git a/server/web_app/public/css/global.css b/server/web_app/public/css/global.css index 00e58ea..403e0fc 100644 --- a/server/web_app/public/css/global.css +++ b/server/web_app/public/css/global.css @@ -47,7 +47,7 @@ body { } .container { - margin: var(--padding-space-large); + margin: 5rem 2rem; } .table-container { diff --git a/server/web_app/public/css/login.css b/server/web_app/public/css/login.css index 20d32d7..0c4e1ad 100644 --- a/server/web_app/public/css/login.css +++ b/server/web_app/public/css/login.css @@ -1 +1,74 @@ @import url('global.css'); + +html, body { + height: 100%; + margin: 0; + display: flex; + justify-content: center; + align-items: center; +} + +.login-container { + width: 100%; + max-width: 400px; + background-color: #fff; + padding: 40px; + border-radius: 8px; + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); + text-align: center; +} + +#login-title { + font-size: 1.8rem; + color: var(--color-basic); + margin-bottom: 20px; +} + +label { + display: block; + margin-bottom: 5px; +} + +.input-username, .input-password { + width: 100%; + padding: 12px; + margin: 10px 0; + border: 1px solid #ccc; + border-radius: 4px; + font-size: 1rem; +} + +.btn-submit { + width: 100%; + padding: 12px; + background-color: var(--color-basic); + border: none; + color: white; + border-radius: 4px; + font-size: 1.1rem; + cursor: pointer; + transition: background-color 0.3s ease; +} + +.btn-submit:hover { + background-color: var(--color-secondary); +} + +#extra-links { + text-align: center; + margin-top: 20px; + font-size: 0.9rem; +} + +.link-create-account, .link-forgot-password { + color: var(--color-basic); + text-decoration: none; +} + +.link-create-account:hover, .link-forgot-password:hover { + text-decoration: underline; +} + +#extra-links p { + margin: 5px 0; +} diff --git a/server/web_app/public/css/menu.css b/server/web_app/public/css/menu.css index f47392a..5543e31 100644 --- a/server/web_app/public/css/menu.css +++ b/server/web_app/public/css/menu.css @@ -1,36 +1,90 @@ @import url('global.css'); -nav { - background-color: var(--color-hover); +header { + background-color: var(--color-primary); + color: #fff; + display: flex; + flex-direction: column; + align-items: flex-end; + position: absolute; + top: 0; + right: 0; width: 100%; + z-index: 10; +} + +.menu-toggle { + display: none; +} + +.menu-icon { + margin: var(--padding-space-normal); + width: var(--font-size-big); + height: var(--font-size-big); + cursor: pointer; +} + +.svg-icon { + width: 100%; + height: 100%; } nav ul { list-style-type: none; - padding: 0; - margin: 0; - display: flex; - flex-direction: row; + display: none; + gap: var(--padding-space-small); } -nav ul li { - margin: var(--margin-space-xsmall) 0; +.menu-toggle:checked + .menu-icon + nav ul { + display: flex; + flex-direction: column; } nav ul li a { - color: var(--color-complementary); - text-decoration: none; - font-size: var(--font-size-normal); - display: block; padding: var(--padding-space-normal); - border-radius: var(--padding-space-small) var(--border-thick); - transition: background-color 0.3s, color 0.3s; + text-decoration: none; + color: var(--color-secondary); } -nav ul li a:hover { - background-color: var(--color-secondary); +@media (min-width: 767px) { + + nav { + background-color: var(--color-hover); + width: 100%; + } + + nav ul { + list-style-type: none; + padding: 0; + margin: 0; + display: flex; + flex-direction: row; + } + + nav ul li { + margin: var(--margin-space-xsmall) 0; + } + + nav ul li a { + color: var(--color-complementary); + text-decoration: none; + font-size: var(--font-size-normal); + display: block; + padding: var(--padding-space-normal); + border-radius: var(--padding-space-small) var(--border-thick); + transition: background-color 0.3s, color 0.3s; + } + + nav ul li a:hover { + background-color: var(--color-secondary); + } + + .menu-icon { + display: none; + } } + .login { margin-left: auto; } diff --git a/server/web_app/public/css/wishlist.css b/server/web_app/public/css/wishlist.css new file mode 100644 index 0000000..a5084e6 --- /dev/null +++ b/server/web_app/public/css/wishlist.css @@ -0,0 +1,21 @@ +@import url('global.css'); + +button { + padding: 6px 12px; + margin: var(--margin-space-xsmall); + border: none; + border-radius: var(--border-thick); + color: var(--color-complementary); + cursor: pointer; + background-color: var(--color-basic); +} + +button:hover { + background-color: var(--color-hover); + color: var(--color-complementary); +} + +button:disabled { + background-color: var(--color-light); + color: black; +} diff --git a/server/web_app/public/js/wishlist.js b/server/web_app/public/js/wishlist.js new file mode 100644 index 0000000..53b971b --- /dev/null +++ b/server/web_app/public/js/wishlist.js @@ -0,0 +1,72 @@ +const ROUTE = 'http://localhost'; +const PORT = '8080'; + +// 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}`; + + try { + const response = await fetch(url); + const data = await response.json(); + console.log(data) + populateTable(data.wishLists); // Populate the table with the fetched data + } catch (error) { + console.error('Error fetching data:', error); + } +} + +// Function to populate the table with the wishlists +function populateTable(data) { + const tableBody = document.getElementById('dataBody'); + tableBody.innerHTML = ''; // Clear the existing rows + + console.log(data) + data.forEach(item => { + const row = document.createElement('tr'); + + row.innerHTML = ` + <td>${item.id}</td> + <td>${item.name}</td> + <td>${item.description}</td> + <td>${item.isActive ? 'Active': 'Unactive' }</td> + <td>${item.createdAt.date}</td> + <td>${item.expirationDate.date}</td> + <td> + <button onclick="editItem(${item.id})">Edit</button> + <button onclick="deleteItem(${item.id})">Delete</button> + <button onclick="inviteItem(${item.id})">Invite</button> + <button onclick="shareItem(${item.id})">Share</button> + <button onclick="detailsItem(${item.id})">Details</button> + </td> + `; + + tableBody.appendChild(row); + }); +} + +// Functions for the action buttons (Edit, Delete, Invite, Share, Details) +function editItem(id) { + console.log('Edit item', id); +} + +function deleteItem(id) { + console.log('Delete item', id); +} + +function inviteItem(id) { + console.log('Invite item', id); +} + +function shareItem(id) { + console.log('Share item', id); +} + +function detailsItem(id) { + console.log('Item details', id); +} + +// Fetch the wishlists when the page loads +window.onload = fetchData; diff --git a/server/web_app/public/svg/menu.svg b/server/web_app/public/svg/menu.svg new file mode 100644 index 0000000..f1d7159 --- /dev/null +++ b/server/web_app/public/svg/menu.svg @@ -0,0 +1,16 @@ +<?xml version="1.0" ?> + +<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools --> +<svg width="800px" height="800px" viewBox="0 0 12 12" enable-background="new 0 0 12 12" id="svg_1" version="1.1" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + +<g> + +<rect fill="#FFFFFF" height="1" width="11" x="0.5" y="5.5"/> + +<rect fill="#FFFFFF" height="1" width="11" x="0.5" y="2.5"/> + +<rect fill="#FFFFFF" height="1" width="11" x="0.5" y="8.5"/> + +</g> + +</svg> \ No newline at end of file diff --git a/server/web_app/src/Controller/MainController.php b/server/web_app/src/Controller/MainController.php index 9296ac2..723f623 100644 --- a/server/web_app/src/Controller/MainController.php +++ b/server/web_app/src/Controller/MainController.php @@ -15,6 +15,24 @@ class MainController extends AbstractController return $this->render('home.html.twig'); } + #[Route('/about', name: 'about')] + public function aboutUs(): Response + { + return $this->render('about.html.twig'); + } + + #[Route('/myWishLists', name: 'myWishLists')] + public function myWishLits(): Response + { + $user = $this->getUser(); + + if ($user) { + return $this->render('wishList.html.twig'); + } + + return $this->redirectToRoute('error'); + } + #[Route('/login', name: 'app_login')] public function login(AuthenticationUtils $authenticationUtils): Response { diff --git a/server/web_app/templates/about.html.twig b/server/web_app/templates/about.html.twig new file mode 100644 index 0000000..ef23e32 --- /dev/null +++ b/server/web_app/templates/about.html.twig @@ -0,0 +1,37 @@ +{% extends 'base.html.twig' %} + +{% block styles %} + <link rel="stylesheet" href="{{ asset('css/about.css') }}"> +{% endblock %} + +{% block body %} + <div class="about-container"> + <h1>About Us</h1> + + <p class="intro">The project is a web platform designed for users to create and share gift wishlists. Users can register, log in, and manage their wishlists, including adding, editing, and deleting items. Each wishlist can be shared via a unique URL, allowing others to view and purchase gifts. When an item is purchased, the buyer can upload proof, and the item is marked as bought. The platform also includes an administration dashboard for tracking the most valuable gifts and managing user accounts.</p> + + <div class="team"> + <h2>Teams</h2> + + <div class="team-member"> + <h3>Team 1: use case 1 - Gift wishlist creation</h3> + <p>WANG Lixi</p> + <p>ZHANG Chen</p> + </div> + + <div class="team-member"> + <h3>Team 2: use case 2 - Purchasing a gift for someone from that person’s wishlist</h3> + <p>XIANG Yuntian</p> + <p>ZHU Xinlei</p> + </div> + + <div class="team-member"> + <h3>Team 3: use case 3 - Administration</h3> + <p>MIRANDA RODRIGUEZ Anamaria</p> + <p>PEREZ RAMIREZ Julian</p> + </div> + </div> + + <p class="footer">WEBAPP - IMT Atlantique</p> + </div> +{% endblock %} diff --git a/server/web_app/templates/base.html.twig b/server/web_app/templates/base.html.twig index 68d3bc3..881ed8b 100644 --- a/server/web_app/templates/base.html.twig +++ b/server/web_app/templates/base.html.twig @@ -7,7 +7,10 @@ <title>{% block title %}Wishlist app{% endblock %}</title> </head> <body> - {% include 'menu.html.twig' %} + <header> + {% include 'menu.html.twig' %} + </header> + {% block body %}{% endblock %} </body> </html> \ No newline at end of file diff --git a/server/web_app/templates/login.html.twig b/server/web_app/templates/login.html.twig index 7bb685f..0a86232 100644 --- a/server/web_app/templates/login.html.twig +++ b/server/web_app/templates/login.html.twig @@ -7,20 +7,25 @@ {% endblock %} {% block body %} - <form action="{{ path('app_login_check') }}" method="post"> - - <h3>Please sign in</h3> - <label for="username">User Name</label> - <input type="text" value="{{ last_username }}" name="_username" id="username" class="form-control" autocomplete="username" required autofocus> - <label for="password">Password</label> - <input type="password" name="_password" id="password" class="form-control" autocomplete="current-password" required> - - <input type="hidden" name="_csrf_token" - value="{{ csrf_token('authenticate') }}" - > - - <button> - Sign in - </button> - </form> + <div class="login-container"> + <form action="{{ path('app_login_check') }}" method="post" id="login-form"> + + <div class="form-title" id="login-title">Please sign in</div> + + <label for="username" class="label-username">User Name</label> + <input type="text" value="{{ last_username }}" name="_username" id="username" class="input-username" autocomplete="username" required autofocus> + + <label for="password" class="label-password">Password</label> + <input type="password" name="_password" id="password" class="input-password" autocomplete="current-password" required> + + <input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}"> + + <button type="submit" class="btn-submit">Sign in</button> + + <div class="extra-links" id="extra-links"> + <p><a href="#" class="link-create-account">Create an account</a></p> + <p><a href="#" class="link-forgot-password">You forgot your password? Click here</a></p> + </div> + </form> + </div> {% endblock %} diff --git a/server/web_app/templates/menu.html.twig b/server/web_app/templates/menu.html.twig index 253cf91..7b59306 100644 --- a/server/web_app/templates/menu.html.twig +++ b/server/web_app/templates/menu.html.twig @@ -2,15 +2,21 @@ <link rel="stylesheet" href="{{ asset('css/menu.css') }}"> {% endblock %} +<input type="checkbox" id="menuToggle" class="menu-toggle"> + +<label for="menuToggle" class="menu-icon"> + <img src="{{ asset('svg/menu.svg') }}" class="svg-icon" alt="Menu Icon"> +</label> + <nav> <ul> - <li><a href=#>My wishlists</a></li> - <li><a href=#>Shared wishlists</a></li> + <li><a href="{{ path('about') }}">About us</a></li> {% if is_granted('ROLE_ADMIN') %} <li><a href="{{ path('dashboard') }}">Dashboard </a></li> {% endif %} {% if app.user %} + <li><a href="{{ path('myWishLists') }}">My wishlists</a></li> <li class="login"><a href="{{ path('app_logout') }}">Logout</a></li> {% else %} <li class="login"><a href="{{ path('app_login') }}">Login</a></li> diff --git a/server/web_app/templates/wishList.html.twig b/server/web_app/templates/wishList.html.twig new file mode 100644 index 0000000..443db77 --- /dev/null +++ b/server/web_app/templates/wishList.html.twig @@ -0,0 +1,35 @@ +{% extends 'base.html.twig' %} + +{% block styles %} + <link rel="stylesheet" href="{{ asset('css/wishlist.css') }}"> +{% endblock %} + +{% block body %} + <h3>Wishlists</h1> + + <!-- Table to show wishlists --> + <section class="container"> + <table id="wishlistTable"> + <thead> + <tr> + <th>ID</th> + <th>Name</th> + <th>Description</th> + <th>Status</th> + <th>Created At</th> + <th>Expiration Date</th> + <th>Actions</th> + </tr> + </thead> + <tbody id="dataBody"> + <!-- Data will be populated here dynamically --> + </tbody> + </table> + </section> + + <script> + const userId = {{ app.user.id }}; + </script> + + <script src="{{ asset('js/wishlist.js') }}"></script> +{% endblock %} -- GitLab