diff --git a/.env b/.env index f52592bcdde2a1b1934985edbe9d9254fc2ac9f6..eb30919784bcdaddaf95d9aa8992ae45f7aeb7a8 100644 --- a/.env +++ b/.env @@ -27,7 +27,7 @@ MESSENGER_TRANSPORT_DSN=sync:// # DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db" # DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8.0.32&charset=utf8mb4" # DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=10.11.2-MariaDB&charset=utf8mb4" -DATABASE_URL="mysql://root:root@172.18.0.3:3306/wishlist?serverVersion=8.0" +DATABASE_URL="mysql://root:root@db_docker_symfony:3306/wishlist?serverVersion=8.0" ###< doctrine/doctrine-bundle ### APP_SECRET=3d9f431b0fd768e0cb2e8b139c66e9fd67ecbd49762f6a345d459e2f115f61b4 diff --git a/config/packages/security.yaml b/config/packages/security.yaml index b9d10f0e8672c8d08d54e58a61cde918c3875818..730a51d59c5f378a09e2851542bc18acce65cccc 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -26,7 +26,7 @@ security: access_control: - { path: ^/admin, allow_if: "user and user.isAdmin == true" } - #- { path: ^/user, allow_if: "user and user.isLocked == false" } + - { path: ^/*, allow_if: "user and user.isLocked != true" } when@test: security: diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 0e63ddeecd626fd30e476e754ff43f0f5f3fd263..fef96537d168fa9c22c83f939f7e22f3df50e227 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -10,7 +10,6 @@ services: ports: - 3306:3306 environment: - MYSQL_ROOT_USER: 'root' MYSQL_ROOT_PASSWORD: 'root' networks: - dev diff --git a/src/Controller/WishlistController.php b/src/Controller/WishlistController.php index 1a39ebad3397e67b8f4a4f0fe0f45fa8d708130a..24a225ff6509c799ca1bd7a442bafd9c99337dde 100644 --- a/src/Controller/WishlistController.php +++ b/src/Controller/WishlistController.php @@ -15,7 +15,7 @@ use Symfony\Component\Routing\Attribute\Route; final class WishlistController extends AbstractController { #[Route(name: 'app_wishlist_index', methods: ['GET'])] - public function index(WishlistRepository $wishlistRepository): Response + public function getWishLists(WishlistRepository $wishlistRepository): Response { return $this->render('wishlist/index.html.twig', [ 'wishlists' => $wishlistRepository->findAll(), @@ -23,11 +23,11 @@ final class WishlistController extends AbstractController } #[Route('/new', name: 'app_wishlist_new', methods: ['GET', 'POST'])] - public function new(Request $request, EntityManagerInterface $entityManager): Response + public function createWishlist(Request $request, EntityManagerInterface $entityManager): Response { $wishlist = new Wishlist(); - $name = $request->get('name'); - $wishlist->setName($name); + $name = $request->get(key: 'name'); + $wishlist->setName(name: $name); $deadline = $request->get('deadline') ; $wishlist->setDeadline($deadline); $entityManager->persist($wishlist); diff --git a/templates/wishlist/index.html.twig b/templates/wishlist/index.html.twig index f08571c4e46059f76d4f5d78d8fa32345f995300..54e8db1deb65e42c651f4f04dbc8b8288a69efec 100644 --- a/templates/wishlist/index.html.twig +++ b/templates/wishlist/index.html.twig @@ -1,36 +1,215 @@ - {% extends 'base.html.twig' %} -{% block title %} My Wishlists {% endblock %} +{% block title %}My Wishlists{% endblock %} + +{% block body %} +<header> + <div class="user-icon"></div> + <h1>My Wishlists</h1> + <input type="text" class="search-bar" placeholder="Search..."> +</header> +<div class="navbar"> + <button class="add-wishlist-btn" data-bs-toggle="modal" data-bs-target="#createWishlistModal">Add wishlist</button> +</div> -{% block body %} - <header> - <div class="user-icon"></div> - <h1>My Wishlists</h1> - <input type="text" class="search-bar" placeholder="Search..."> - </header> - - <div class="navbar"> - <button class="add-wishlist-btn">Add wishlist</button> +<!-- Create Wishlist Modal --> +<div class="modal fade" id="createWishlistModal" tabindex="-1" aria-labelledby="createWishlistModalLabel" aria-hidden="true"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <h5 class="modal-title" id="createWishlistModalLabel">Create New Wishlist</h5> + <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> + </div> + <div class="modal-body"> + <form id="createWishlistForm"> + <div class="mb-3"> + <label for="wishlistName" class="form-label">Name*</label> + <input type="text" class="form-control" id="wishlistName" required> + </div> + <div class="mb-3"> + <label for="wishlistDeadline" class="form-label">Deadline</label> + <input type="datetime-local" class="form-control" id="wishlistDeadline"> + </div> + <div class="mb-3 form-check"> + <input type="checkbox" class="form-check-input" id="wishlistIsDisabled"> + <label class="form-check-label" for="wishlistIsDisabled">Disabled</label> + </div> + </form> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button> + <button type="button" class="btn btn-primary" id="submitWishlist">Create</button> + </div> + </div> </div> - - <div class="container"> - {% for wishlist in wishlists %} - <div class="wishlist"> - <h2>{{ wishlist.title }}</h2> - <div class="wishlist-items"> +</div> + +<div class="container"> + {% for wishlist in wishlists %} + <div class="wishlist {% if wishlist.isDisabled %}wishlist-disabled{% endif %}"> + <div class="wishlist-header"> + <h2>{{ wishlist.name }}</h2> + {% if wishlist.deadline %} + <span class="deadline-badge"> + Due: {{ wishlist.deadline|date('Y-m-d H:i') }} + {% if wishlist.deadline|date('U') < 'now'|date('U') %} + <span class="deadline-passed">(Passed)</span> + {% endif %} + </span> + {% endif %} + {% if wishlist.isDisabled %} + <span class="disabled-badge">Disabled</span> + {% endif %} + </div> + <div class="wishlist-items"> {% for item in wishlist.items %} <div class="wishlist-item">📷</div> {% endfor %} - </div> - <p class="wishlist-footer">Authors: name1, name2</p> - <div class="wishlist-actions"> - <button title="Share wishlist">↗</button> - <button title="Edit title">✏</button> - <button title="Delete wishlist">🗑</button> - </div> </div> - {% endfor %} + <p class="wishlist-footer">Authors: name1, name2</p> + <div class="wishlist-actions"> + <button title="Share wishlist">↗</button> + <button title="Edit wishlist">✏</button> + <button title="Delete wishlist">🗑</button> + </div> </div> - {% endblock %} + {% endfor %} +</div> +{% endblock %} + +{% block javascripts %} +{{ parent() }} +<script> +document.addEventListener('DOMContentLoaded', function() { + document.getElementById('submitWishlist').addEventListener('click', function() { + const name = document.getElementById('wishlistName').value; + const deadline = document.getElementById('wishlistDeadline').value; + const isDisabled = document.getElementById('wishlistIsDisabled').checked; + + if (!name) { + alert('Please enter a name for your wishlist'); + return; + } + + fetch('/wishlists/create', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-Requested-With': 'XMLHttpRequest' + }, + body: JSON.stringify({ + name: name, + deadline: deadline, + isDisabled: isDisabled + }) + }) + .then(response => response.json()) + .then(data => { + if (data.success) { + bootstrap.Modal.getInstance(document.getElementById('createWishlistModal')).hide(); + window.location.reload(); + } else { + alert('Error creating wishlist: ' + data.message); + } + }) + .catch(error => { + console.error('Error:', error); + alert('An error occurred while creating the wishlist'); + }); + }); +}); +</script> +{% endblock %} + +{% block stylesheets %} +{{ parent() }} +<style> + .wishlist { + border: 1px solid #ddd; + border-radius: 8px; + padding: 15px; + margin-bottom: 20px; + box-shadow: 0 2px 4px rgba(0,0,0,0.1); + position: relative; + } + + .wishlist-disabled { + opacity: 0.7; + background-color: #f8f9fa; + } + + .wishlist-header { + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; + gap: 10px; + margin-bottom: 10px; + } + + .deadline-badge { + background: #e9ecef; + padding: 3px 8px; + border-radius: 4px; + font-size: 0.9em; + } + + .deadline-passed { + color: #dc3545; + font-weight: bold; + } + + .disabled-badge { + background: #6c757d; + color: white; + padding: 3px 8px; + border-radius: 4px; + font-size: 0.9em; + } + + .wishlist-items { + display: flex; + flex-wrap: wrap; + gap: 10px; + margin: 15px 0; + } + + .wishlist-item { + width: 60px; + height: 60px; + background: #f5f5f5; + border-radius: 4px; + display: flex; + align-items: center; + justify-content: center; + font-size: 24px; + } + + .wishlist-actions { + display: flex; + gap: 10px; + justify-content: flex-end; + } + + .wishlist-actions button { + background: none; + border: none; + cursor: pointer; + font-size: 18px; + } + + .add-wishlist-btn { + background-color: #4CAF50; + color: white; + border: none; + padding: 10px 15px; + border-radius: 4px; + cursor: pointer; + } + + .add-wishlist-btn:hover { + background-color: #45a049; + } +</style> +{% endblock %} \ No newline at end of file