diff --git a/public/css/home.css b/public/css/home.css index d8e65e7..f0e0550 100644 --- a/public/css/home.css +++ b/public/css/home.css @@ -11,12 +11,45 @@ h1 { color: #f8b435; } -.emoji-container { +.section-divider { + border: none; + border-top: 3px solid #f8b435; + margin: 50px auto 20px; + width: 80%; +} + +.section-break-icon { + text-align: center; + font-size: 2rem; + margin: -20px 0; + color: #f8b435; +} + +.section-title { + margin: 40px 10px; + font-size: 1.8rem; + color: #f8f5e0; +} + +.emoji-container:not(.base) { + display: grid; + grid-template-columns: repeat(5, 1fr); + gap: 30px; + width: fit-content; + margin: 0 auto; +} + +.emoji-container.base { display: flex; justify-content: center; flex-wrap: wrap; gap: 30px; - margin-bottom: 10rem; + + border: 3px dashed #f8b435; + padding: 20px; + margin: 0 auto 30px auto; + border-radius: 15px; + width: fit-content; } .emoji-card { @@ -43,7 +76,7 @@ h1 { /* Animation brillance pour rareté légendaire */ @keyframes shine { 0% { background-position: 0px; } - 100% { background-position: 177px; } + 100% { background-position: 168px; } } .emoji-card.gold { @@ -54,17 +87,17 @@ h1 { .emoji-card.gold::before { content: ''; position: absolute; - top: 0; + top: 1%; left: 1%; - width: 98%; - height: 100%; + width: 97%; + height: 99%; background: linear-gradient( 120deg, rgba(255, 255, 255, 0) 0%, - rgba(255, 255, 255, 0.5) 50%, + rgba(255, 255, 255, 0.8) 50%, rgba(255, 255, 255, 0) 100% ); - animation: shine 5s infinite; + animation: shine 3.5s infinite; pointer-events: none; z-index: -1; } @@ -219,7 +252,7 @@ color: #555; #selection-status { font-size: 1.1rem; - margin-bottom: 20px; + margin-top: 4rem; font-weight: bold; color: #f9e8c0; } @@ -245,4 +278,37 @@ color: #555; .vs-text { font-size: 1.5rem; font-weight: bold; +} + +/* Pagination */ + +.pagination-bar { + margin: 4rem 4rem; + display: flex; + justify-content: center; + align-items: center; + gap: 10px; + color: #f8f5e0; + font-family: 'Georgia', serif; +} + +.pagination-bar button { + background: none; + border: none; + font-size: 1.1rem; + color: #f8f5e0; + cursor: pointer; + padding: 5px 10px; + border-radius: 50%; + transition: background 0.2s ease; +} + +.pagination-bar button.active { + background: #333; + color: white; + font-weight: bold; +} + +.pagination-bar button:hover:not(.active) { + color: #f8b435; } \ No newline at end of file diff --git a/public/js/home.js b/public/js/home.js index 2ab31ba..800d866 100644 --- a/public/js/home.js +++ b/public/js/home.js @@ -77,7 +77,7 @@ document.addEventListener('DOMContentLoaded', () => { console.log(`Accouplement : ${name1} et ${name2}`); } - // Réinitialiser après l'action + // Réinitialiser après l'action (seulement si pas redirigé) selectedCards.forEach(card => card.classList.remove('selected')); selectedCards = []; updateSelectionDisplay(); @@ -86,7 +86,9 @@ document.addEventListener('DOMContentLoaded', () => { // Ouvre / Ferme la popup d'information function togglePopup(id) { const popup = document.getElementById('popup-' + id); - popup.style.display = (popup.style.display === 'block') ? 'none' : 'block'; + if (popup) { + popup.style.display = (popup.style.display === 'block') ? 'none' : 'block'; + } } // Fermer les autres popups en cliquant ailleurs @@ -104,7 +106,7 @@ document.addEventListener('DOMContentLoaded', () => { const sortBy = document.getElementById('sort-select').value; const searchTerm = document.getElementById('search-input').value.toLowerCase(); - const cards = Array.from(document.querySelectorAll('.emoji-card')); + const cards = Array.from(document.querySelectorAll('#collection-container .emoji-card')); cards.forEach(card => { const color = card.dataset.color; @@ -121,7 +123,7 @@ document.addEventListener('DOMContentLoaded', () => { }); if (sortBy !== 'none') { - const container = document.querySelector('.emoji-container'); + const container = document.getElementById('collection-container'); // ✅ corrigé const visibleCards = cards.filter(c => c.style.display !== 'none'); visibleCards.sort((a, b) => { @@ -131,21 +133,29 @@ document.addEventListener('DOMContentLoaded', () => { }); visibleCards.forEach(card => container.appendChild(card)); + paginateCards(); } } // Appel Fonctionnalité de popup d'information document.querySelectorAll('.detail-icon').forEach(icon => { icon.addEventListener('click', (e) => { - const id = icon.parentElement.dataset.id; - togglePopup(id); - e.stopPropagation(); // empêche le clic d’aller à la carte + const card = icon.closest('.emoji-card'); + const id = card?.dataset.id; + if (id) { + togglePopup(id); + } + e.stopPropagation(); // évite que ça sélectionne la carte }); }); - // Appel Fonctionnalité de sélection des cartes - document.querySelectorAll('.emoji-card').forEach(card => { - card.addEventListener('click', () => toggleSelection(card)); + // Appliquer l'écouteur à toutes les cartes (base + collection) + document.querySelectorAll('.emoji-container').forEach(container => { + container.addEventListener('click', (e) => { + const card = e.target.closest('.emoji-card'); + if (!card || e.target.closest('.detail-icon')) return; // Ignore si clic sur icône ℹ️ + toggleSelection(card); + }); }); // Appel Fonctionnalité de combat et reproduction @@ -160,4 +170,66 @@ document.addEventListener('DOMContentLoaded', () => { document.getElementById('search-input').addEventListener('input', applyFilters); document.getElementById('rarete-filter').addEventListener('change', applyFilters); document.getElementById('sort-select').addEventListener('change', applyFilters); + + /***** Partie Pagination ******/ + + const ITEMS_PER_PAGE = 10; + let currentPage = 1; + + function paginateCards() { + const allCards = Array.from(document.querySelectorAll('#collection-container .emoji-card')); + const container = document.getElementById('collection-container'); + const totalPages = Math.ceil(allCards.length / ITEMS_PER_PAGE); + + // Masquer toutes les cartes + allCards.forEach(card => card.style.display = 'none'); + + // Afficher uniquement les cartes de la page courante + const start = (currentPage - 1) * ITEMS_PER_PAGE; + const end = start + ITEMS_PER_PAGE; + + allCards.slice(start, end).forEach(card => card.style.display = 'block'); + + renderPagination(totalPages); + } + + function renderPagination(totalPages) { + const pagination = document.getElementById('pagination'); + pagination.innerHTML = ''; + + const addBtn = (text, page = null, isActive = false, disabled = false) => { + const btn = document.createElement('button'); + btn.textContent = text; + if (isActive) btn.classList.add('active'); + if (disabled) btn.disabled = true; + if (page !== null) { + btn.addEventListener('click', () => { + currentPage = page; + paginateCards(); + }); + } + pagination.appendChild(btn); + }; + + addBtn('Précédent', currentPage - 1, false, currentPage === 1); + + for (let i = 1; i <= totalPages; i++) { + if ( + i === 1 || + i === totalPages || + (i >= currentPage - 1 && i <= currentPage + 1) + ) { + addBtn(i, i, i === currentPage); + } else if ( + i === 2 && currentPage > 3 || + i === totalPages - 1 && currentPage < totalPages - 2 + ) { + addBtn('...'); + } + } + + addBtn('Suivant', currentPage + 1, false, currentPage === totalPages); + } + + paginateCards(); }); \ No newline at end of file diff --git a/src/Command/PopulateDBEmojiAvailableCommand.php b/src/Command/PopulateDBEmojiAvailableCommand.php new file mode 100644 index 0000000..62404d4 --- /dev/null +++ b/src/Command/PopulateDBEmojiAvailableCommand.php @@ -0,0 +1,76 @@ +connection = $connection; + } + + protected function configure() + { + $this + ->setDescription('Populate the database.'); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + try { + + // On supprime la table si elle existe déjà + $this->connection->executeStatement('DROP TABLE IF EXISTS stock_emoji'); + + // On crée la table + $this->connection->executeStatement(' + CREATE TABLE stock_emoji ( + id INT PRIMARY KEY, + code VARCHAR(255) NOT NULL + ) + '); + + // On peuple la table + $this->connection->executeStatement("INSERT INTO stock_emoji (id, code) VALUES + (1,'🤖'), + (2,'😺'), + (3,'🧠'), + (4,'👻'), + (5,'🧟'), + (6,'🐶'), + (7,'👽'), + (8,'🧛'), + (9,'🎃'), + (10,'🐸'), + (11,'⚡'), + (12,'💀'), + (13,'🔥'), + (14,'🧙'), + (15,'🌪️'), + (16,'😎'), + (17,'😁'), + (18,'🌟'), + (19,'😈') + "); + + $output->writeln('Base de données peuplée.'); + } catch (\Exception $e) { + $output->writeln('Erreur : ' . $e->getMessage() . ''); + return Command::FAILURE; + } + + return Command::SUCCESS; + } +} diff --git a/src/Controller/HomeController.php b/src/Controller/HomeController.php index f5df842..95761d7 100644 --- a/src/Controller/HomeController.php +++ b/src/Controller/HomeController.php @@ -11,7 +11,7 @@ class HomeController extends AbstractController #[Route('/', name: 'home')] public function index(): Response { - $emojis = [ + $emojisDeBase = [ [ 'id' => 1, 'nom' => 'Bob', @@ -21,7 +21,7 @@ class HomeController extends AbstractController 'intelligence' => 7.8, 'vitesse' => 10.0, 'nbCombatGagne' => 3, - 'rarete' => 2, // épique + 'rarete' => 3, // épique ], [ 'id' => 2, @@ -43,24 +43,169 @@ class HomeController extends AbstractController 'intelligence' => 18.0, 'vitesse' => 17.0, 'nbCombatGagne' => 10, - 'rarete' => 4, // légendaire + 'rarete' => 5, // légendaire + ], + [ + 'id' => 4, + 'nom' => 'Sophie', + 'code' => '😎', + 'force' => 8.0, + 'robustesse' => 7.5, + 'intelligence' => 9.0, + 'vitesse' => 8.5, + 'nbCombatGagne' => 2, + 'rarete' => 4, // mythique ] ]; - // Ajout de la couleur selon la rareté - foreach ($emojis as &$emoji) { + $emojisCrees = [ + [ + 'id' => 6, + 'nom' => 'Benoit', + 'code' => '🤖', + 'force' => 15.0, + 'robustesse' => 12.0, + 'intelligence' => 14.0, + 'vitesse' => 13.0, + 'nbCombatGagne' => 5, + 'rarete' => 3, // épique + ], + [ + 'id' => 7, + 'nom' => 'Eric', + 'code' => '🌟', + 'force' => 18.0, + 'robustesse' => 16.0, + 'intelligence' => 17.0, + 'vitesse' => 19.0, + 'nbCombatGagne' => 8, + 'rarete' => 5, // légendaire + ], + [ + 'id' => 5, + 'nom' => 'Alice', + 'code' => '🥳', + 'force' => 6.0, + 'robustesse' => 5.0, + 'intelligence' => 4.5, + 'vitesse' => 6.5, + 'nbCombatGagne' => 0, + 'rarete' => 2, // rare + ], + [ + 'id' => 8, + 'nom' => 'Bobette', + 'code' => '🤩', + 'force' => 10.0, + 'robustesse' => 9.0, + 'intelligence' => 11.0, + 'vitesse' => 12.0, + 'nbCombatGagne' => 4, + 'rarete' => 4, // mythique + ], + [ + 'id' => 9, + 'nom' => 'Charlie', + 'code' => '😇', + 'force' => 7.0, + 'robustesse' => 6.0, + 'intelligence' => 8.0, + 'vitesse' => 7.5, + 'nbCombatGagne' => 2, + 'rarete' => 1, // commun + ], + [ + 'id' => 10, + 'nom' => 'Diana', + 'code' => '😈', + 'force' => 14.0, + 'robustesse' => 13.0, + 'intelligence' => 15.0, + 'vitesse' => 16.0, + 'nbCombatGagne' => 6, + 'rarete' => 4, // mythique + ], + [ + 'id' => 11, + 'nom' => 'Ethan', + 'code' => '🤯', + 'force' => 9.0, + 'robustesse' => 8.0, + 'intelligence' => 10.0, + 'vitesse' => 11.0, + 'nbCombatGagne' => 3, + 'rarete' => 3, // épique + ], + [ + 'id' => 12, + 'nom' => 'Fiona', + 'code' => '🥺', + 'force' => 4.0, + 'robustesse' => 3.5, + 'intelligence' => 5.0, + 'vitesse' => 4.5, + 'nbCombatGagne' => 1, + 'rarete' => 1, // commun + ], + [ + 'id' => 13, + 'nom' => 'George', + 'code' => '😜', + 'force' => 11.0, + 'robustesse' => 10.0, + 'intelligence' => 12.0, + 'vitesse' => 13.5, + 'nbCombatGagne' => 2, + 'rarete' => 3, // épique + ], + [ + 'id' => 14, + 'nom' => 'Hannah', + 'code' => '😏', + 'force' => 3.0, + 'robustesse' => 2.5, + 'intelligence' => 4.0, + 'vitesse' => 3.5, + 'nbCombatGagne' => 0, + 'rarete' => 2, // rare + ], + [ + 'id' => 15, + 'nom' => 'Ian', + 'code' => '😬', + 'force' => 17.0, + 'robustesse' => 14.0, + 'intelligence' => 16.0, + 'vitesse' => 18.0, + 'nbCombatGagne' => 7, + 'rarete' => 5, // légendaire + ], + ]; + + foreach ($emojisDeBase as &$emoji) { + $emoji['color'] = match ($emoji['rarete']) { + 2 => 'green', + 3 => 'purple', + 4 => 'red', + 5 => 'gold', + default => 'gray', + }; + } + foreach ($emojisCrees as &$emoji) { $emoji['color'] = match ($emoji['rarete']) { - 1 => 'green', // commun - 2 => 'purple', // épique - 3 => 'red', // mythique - 4 => 'gold', // légendaire - default => 'gray' + 2 => 'green', + 3 => 'purple', + 4 => 'red', + 5 => 'gold', + default => 'gray', }; } + return $this->render('home/index.html.twig', [ - 'emojis' => $emojis, + 'emojisDeBase' => $emojisDeBase, + 'emojisCrees' => $emojisCrees, ]); } } diff --git a/src/Entity/StockEmoji.php b/src/Entity/StockEmoji.php new file mode 100644 index 0000000..1626de0 --- /dev/null +++ b/src/Entity/StockEmoji.php @@ -0,0 +1,35 @@ +id; + } + + public function getCode(): ?string + { + return $this->code; + } + + public function setCode(string $code): self + { + $this->code = $code; + + return $this; + } +} diff --git a/src/Repository/StockEmojiRepository.php b/src/Repository/StockEmojiRepository.php new file mode 100644 index 0000000..a50b840 --- /dev/null +++ b/src/Repository/StockEmojiRepository.php @@ -0,0 +1,48 @@ + + * + * @method StockEmoji|null find($id, $lockMode = null, $lockVersion = null) + * @method StockEmoji|null findOneBy(array $criteria, array $orderBy = null) + * @method StockEmoji[] findAll() + * @method StockEmoji[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class StockEmojiRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, StockEmoji::class); + } + +// /** +// * @return StockEmoji[] Returns an array of StockEmoji objects +// */ +// public function findByExampleField($value): array +// { +// return $this->createQueryBuilder('s') +// ->andWhere('s.exampleField = :val') +// ->setParameter('val', $value) +// ->orderBy('s.id', 'ASC') +// ->setMaxResults(10) +// ->getQuery() +// ->getResult() +// ; +// } + +// public function findOneBySomeField($value): ?StockEmoji +// { +// return $this->createQueryBuilder('s') +// ->andWhere('s.exampleField = :val') +// ->setParameter('val', $value) +// ->getQuery() +// ->getOneOrNullResult() +// ; +// } +} diff --git a/templates/home/index.html.twig b/templates/home/index.html.twig index d48c919..2f191c6 100644 --- a/templates/home/index.html.twig +++ b/templates/home/index.html.twig @@ -10,6 +10,38 @@

🧬 Ma collection de créatures 🐾

+

🌱 Vos créatures de base

+ +
+ {% for emoji in emojisDeBase %} +
+ +
Level {{ emoji.nbCombatGagne }}
+
{{ emoji.code }}
+
{{ emoji.nom }}
+
ℹ️
+ + +
+ {% endfor %} +
+ +
🔻
+ +

📦 Votre collection personnelle

+
@@ -32,18 +64,20 @@
-
Sélectionnez 2 créatures...
- -
- {% for emoji in emojis %} -
+
+ {% for emoji in emojisCrees %} +
Level {{ emoji.nbCombatGagne }}
{{ emoji.code }}
{{ emoji.nom }}
-
ℹ️
+
ℹ️
+ + +
Sélectionnez 2 créatures de votre choix pour commencer ...
+
- - + +
{% endblock %}