Skip to content
Snippets Groups Projects
Commit fb72faa2 authored by Zahdi's avatar Zahdi
Browse files
parents 6cc11600 8c029508
No related branches found
No related tags found
No related merge requests found
......@@ -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'),
],
]);
}
......
......@@ -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;
}
......
......@@ -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();
......
......@@ -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 %}
......@@ -31,6 +31,6 @@
<button title="Delete wishlist">🗑</button>
</div>
</div>
{% end for %}
{% endfor %}
</div>
{% endblock %}
{# 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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment