diff --git a/src/Controller/HomeController.php b/src/Controller/HomeController.php index 6a27413e245f8a2b400aff981fdd99ee158e27e9..8967bd5f668ce2797499102ddae4c220248bd328 100644 --- a/src/Controller/HomeController.php +++ b/src/Controller/HomeController.php @@ -17,6 +17,8 @@ class HomeController extends AbstractController 'Login' => $this->generateUrl('login'), 'My Wishlists' => $this->generateUrl('app_wishlist_index'), 'Admin Dashboard' => $this->generateUrl('admin_dashboard'), + 'Profile' => $this->generateUrl('user_profile'), + ], ]); } diff --git a/src/Entity/User.php b/src/Entity/User.php index 3b99380de70e1e5d2765ef69d24c94c023e4f3e1..406c8d520278523a95f205da16acde3176a2d10a 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -164,7 +164,7 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface return $this->wishlists; } - public function addToAuthorWhishlists(Wishlists $wishlist){ + public function addToAuthorWhishlists(Wishlist $wishlist){ if (!$this->wishlists->contains($wishlist)) { $this->wishlists[] = $wishlist; } diff --git a/src/Entity/Wishlist.php b/src/Entity/Wishlist.php index 9c16360e90dd7fe7e5adfe93d8137a1594cb0313..60d02f6b46676bc0c8339747922d1879a7317770 100644 --- a/src/Entity/Wishlist.php +++ b/src/Entity/Wishlist.php @@ -32,6 +32,21 @@ class Wishlist #[ORM\OneToMany(targetEntity: Item::class, mappedBy: 'wishlist', orphanRemoval: true)] private Collection $items; + #[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'wishlists')] + #[ORM\JoinColumn(nullable: false)] + private ?User $owner = null; + + public function getOwner(): ?User + { + return $this->owner; + } + + public function setOwner(?User $owner): static + { + $this->owner = $owner; + return $this; + } + public function __construct() { $this->items = new ArrayCollection(); diff --git a/templates/home/index.html.twig b/templates/home/index.html.twig index c54658099b28dc9694277438e16e5df6408315ab..0358ab73afecfa4089f2eba954c8ab6291889184 100644 --- a/templates/home/index.html.twig +++ b/templates/home/index.html.twig @@ -3,7 +3,56 @@ {% block title %}Homepage{% endblock %} {% block body %} -<div class="container mt-5"> +<style> + body { + font-family: Arial, sans-serif; + background: linear-gradient(135deg, #00B8DE, #99CC33); + color: white; + text-align: center; + padding: 20px; + } + .container { + max-width: 600px; + margin: auto; + background: rgba(255, 255, 255, 0.2); + padding: 20px; + border-radius: 15px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); + backdrop-filter: blur(10px); + } + h1 { + font-size: 2em; + margin-bottom: 10px; + } + p { + font-size: 1.2em; + } + ul { + list-style: none; + padding: 0; + } + li { + margin: 15px 0; + } + a { + text-decoration: none; + background: white; + padding: 10px 15px; + border-radius: 8px; + color: #00B8DE; + font-weight: bold; + transition: 0.3s; + display: inline-block; + margin: 5px; + } + a:hover { + background: #99CC33; + color: white; + transform: scale(1.1); + } +</style> + +<div class="container"> <h1>Welcome to the Wishlist Project</h1> <p>Here are the main links to navigate through the project:</p> <ul> @@ -12,4 +61,18 @@ {% endfor %} </ul> </div> -{% endblock %} \ No newline at end of file + +<script> + document.addEventListener("DOMContentLoaded", function() { + const links = document.querySelectorAll("a"); + links.forEach(link => { + link.addEventListener("mouseover", () => { + link.style.boxShadow = "0px 4px 15px rgba(255, 255, 255, 0.5)"; + }); + link.addEventListener("mouseout", () => { + link.style.boxShadow = "none"; + }); + }); + }); +</script> +{% endblock %} diff --git a/templates/wishlist/index.html.twig b/templates/wishlist/index.html.twig index 3f6757e13f54603fcee0fce0623c0a6ec7ab01cb..f08571c4e46059f76d4f5d78d8fa32345f995300 100644 --- a/templates/wishlist/index.html.twig +++ b/templates/wishlist/index.html.twig @@ -31,6 +31,6 @@ <button title="Delete wishlist">🗑</button> </div> </div> - {% end for %} + {% endfor %} </div> {% endblock %} diff --git a/templates/wishlist/show.html.twig b/templates/wishlist/show.html.twig index f752ff1777d1f3395a16b0ed52264cbc001704d0..bead562e103c7b9b96a311fbbdaf2803e02a27e4 100644 --- a/templates/wishlist/show.html.twig +++ b/templates/wishlist/show.html.twig @@ -1,44 +1,234 @@ +{# templates/wishlist/show.html.twig #} {% extends 'base.html.twig' %} -{% block title %}Wishlist{% endblock %} +{% block title %}{{ wishlist.name }}{% endblock %} -{% block body %} - - <header> - <div class="user-icon"></div> - <div style="display:flex;justify-content:center;align-items:center;"> +{% block stylesheets %} + {{ parent() }} + <style> + body { + font-family: Arial, sans-serif; + max-width: 800px; + margin: 0 auto; + padding: 20px; + color: #333; + } - <h1>My wishlists</h1> + .wishlist-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 20px; + border-bottom: 1px solid #eee; + padding-bottom: 15px; + } - </div> - <input type="text" placeholder="Search…" class="search-bar"> - </header> - - - <table class="table"> - <tbody> - <tr> - <th>Id</th> - <td>{{ wishlist.id }}</td> - </tr> - <tr> - <th>Name</th> - <td>{{ wishlist.name }}</td> - </tr> - <tr> - <th>Deadline</th> - <td>{{ wishlist.deadline ? wishlist.deadline|date('Y-m-d H:i:s') : '' }}</td> - </tr> - <tr> - <th>IsDisabled</th> - <td>{{ wishlist.isDisabled ? 'Yes' : 'No' }}</td> - </tr> - </tbody> - </table> - - <a href="{{ path('app_wishlist_index') }}">back to list</a> - - <a href="{{ path('app_wishlist_edit', {'id': wishlist.id}) }}">edit</a> + .wishlist-title { + font-size: 24px; + font-weight: bold; + margin: 0; + } + + .wishlist-actions { + display: flex; + gap: 15px; + align-items: center; + } + + .search-view-container { + display: flex; + align-items: center; + gap: 10px; + } + + .view-switcher { + background: none; + border: none; + font-size: 20px; + cursor: pointer; + width: 32px; + height: 32px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + } + + .view-switcher:hover { + background-color: #f5f5f5; + } + + .add-item-btn { + background: none; + border: none; + color: #007bff; + cursor: pointer; + font-size: 14px; + padding: 5px 10px; + } + + .search-bar { + padding: 8px 12px; + border: 1px solid #ddd; + border-radius: 4px; + width: 200px; + } + + .items-list { + list-style-type: none; + padding: 0; + margin: 0; + } + + .item { + display: flex; + gap: 20px; + padding: 20px 0; + border-bottom: 1px solid #eee; + } + + .item-image { + width: 120px; + height: 120px; + object-fit: cover; + border-radius: 8px; + background-color: #f5f5f5; + flex-shrink: 0; + } + + .item-details { + flex-grow: 1; + } + + .item-title { + font-size: 18px; + font-weight: bold; + margin: 0 0 8px 0; + } + + .item-description { + color: #666; + margin-bottom: 12px; + line-height: 1.4; + } + + .item-price { + color: #28a745; + font-weight: bold; + margin-bottom: 15px; + } + + .item-actions { + display: flex; + justify-content: flex-end; + gap: 12px; + } + + .action-btn { + background: none; + border: none; + font-size: 18px; + cursor: pointer; + width: 32px; + height: 32px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + } + + .action-btn:hover { + background-color: rgba(0,0,0,0.05); + } + + .buy-btn { color: #28a745; } + .edit-btn { color: #ffc107; } + .delete-btn { color: #dc3545; } + + .empty-state { + color: #6c757d; + text-align: center; + padding: 40px 0; + font-style: italic; + } + + .item-count { + font-size: 14px; + color: #6c757d; + margin-top: 5px; + } + </style> +{% endblock %} - {{ include('wishlist/_delete_form.html.twig') }} +{% block body %} + <div class="wishlist-header"> + <div> + <h1 class="wishlist-title">{{ wishlist.name }}</h1> + <div class="item-count">{{ wishlist.items|length }} items</div> + </div> + <div class="wishlist-actions"> + <button class="add-item-btn">Add item</button> + <div class="search-view-container"> + <input type="text" class="search-bar" placeholder="Search..."> + <button class="view-switcher" title="Change view">≡</button> + </div> + </div> + </div> + + <ul class="items-list"> + {% for item in wishlist.items %} + <li class="item" data-item-id="{{ item.id }}"> + <img src="{{ item.imageUrl ?? 'https://via.placeholder.com/120?text=No+Image' }}" + alt="{{ item.name }}" + class="item-image"> + <div class="item-details"> + <h3 class="item-title">{{ item.name }}</h3> + <p class="item-description">{{ item.description ?? 'No description available' }}</p> + {% if item.price %} + <div class="item-price">${{ item.price|number_format(2) }}</div> + {% endif %} + <div class="item-actions"> + <button class="action-btn buy-btn" title="Buy" + onclick="window.open('{{ item.purchaseUrl }}', '_blank')">🛒</button> + <button class="action-btn edit-btn" title="Edit" + onclick="window.location.href='{{ path('wishlist_item_edit', {'id': item.id}) }}'">✏️</button> + <button class="action-btn delete-btn" title="Delete" + data-delete-url="{{ path('wishlist_item_delete', {'id': item.id}) }}">🗑️</button> + </div> + </div> + </li> + {% else %} + <div class="empty-state">No items in this wishlist yet</div> + {% endfor %} + </ul> {% endblock %} + +{% block javascripts %} + {{ parent() }} + <script> + document.addEventListener('DOMContentLoaded', function() { + // Delete button action + document.querySelectorAll('.delete-btn').forEach(btn => { + btn.addEventListener('click', function() { + if (confirm('Are you sure you want to delete this item?')) { + const deleteUrl = this.getAttribute('data-delete-url'); + fetch(deleteUrl, { + method: 'DELETE', + headers: { + 'X-Requested-With': 'XMLHttpRequest' + } + }) + .then(response => { + if (response.ok) { + this.closest('.item').remove(); + // Update item count + const itemCount = document.querySelectorAll('.item').length; + document.querySelector('.item-count').textContent = itemCount + ' items'; + } + }); + } + }); + }); + }); + </script> +{% endblock %} \ No newline at end of file