Various small bug fixes, break out pagination for cards into its own mixin and templatetag

This commit is contained in:
badblocks 2025-03-29 00:27:40 -07:00
parent 05a279fa3a
commit 138a929da6
17 changed files with 225 additions and 136 deletions

View file

@ -1,4 +1,5 @@
{% load card_badge %}
{% load pagination_tags %}
{% if group_by and groups %}
{% for group in groups %}
<div class="divider">{{ group.group }}</div>
@ -20,21 +21,7 @@
</div>
{% endif %}
<!-- Pagination Controls -->
<div class="mt-6">
{% if is_paginated %}
<div class="flex justify-center space-x-2">
{% if page_obj.has_previous %}
<button class="btn btn-outline" @click="$dispatch('change-page', { page: {{ page_obj.previous_page_number }} })">
Previous
</button>
{% endif %}
<span>Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}</span>
{% if page_obj.has_next %}
<button class="btn btn-outline" @click="$dispatch('change-page', { page: {{ page_obj.next_page_number }} })">
Next
</button>
{% endif %}
</div>
{% endif %}
</div>
<!-- Somewhere in your template, e.g., after the card list: -->
{% if page_obj %}
{% render_pagination page_obj %}
{% endif %}

View file

@ -18,35 +18,40 @@
x-init="loadCards()"
x-on:change-page.window="page = $event.detail.page; loadCards()"
>
<h1 class="text-2xl font-bold mb-4">Cards</h1>
<div class="flex flex-wrap items-center justify-between mb-6">
<!-- Sort Dropdown -->
<div class="dropdown dropdown-end m-1">
<div tabindex="0" class="btn">
<span x-text="order === 'absolute' ? 'Absolute' : (order === 'alphabetical' ? 'Alphabetical' : 'Rarity')"></span> 🞃
</div>
<ul tabindex="0" class="dropdown-content menu p-2 shadow bg-base-100 rounded-box w-52">
<li><a href="#" @click.prevent="order = 'absolute'; page = 1; loadCards()">Absolute</a></li>
<li><a href="#" @click.prevent="order = 'alphabetical'; page = 1; loadCards()">Alphabetical</a></li>
<li><a href="#" @click.prevent="order = 'rarity'; page = 1; loadCards()">Rarity</a></li>
</ul>
<div>
<h1 class="text-2xl font-bold">Cards</h1>
</div>
<!-- Grouping Dropdown -->
<div class="dropdown dropdown-end m-1">
<div tabindex="0" class="btn">
<span x-text="groupBy === 'none' ? 'No Group' : (groupBy.charAt(0).toUpperCase() + groupBy.slice(1))"></span> 🞃
<div>
<!-- Sort Dropdown -->
<div class="dropdown dropdown-end m-1">
<div tabindex="0" class="btn">
Sort by: <span x-text="order === 'absolute' ? 'None' : (order === 'alphabetical' ? 'Alphabetical' : 'Rarity')"></span> 🞃
</div>
<ul tabindex="0" class="dropdown-content menu p-2 shadow bg-base-100 rounded-box w-52">
<li><a href="#" @click.prevent="order = 'absolute'; page = 1; loadCards()">None</a></li>
<li><a href="#" @click.prevent="order = 'alphabetical'; page = 1; loadCards()">Alphabetical</a></li>
<li><a href="#" @click.prevent="order = 'rarity'; page = 1; loadCards()">Rarity</a></li>
</ul>
</div>
<!-- Grouping Dropdown -->
<div class="dropdown dropdown-end m-1">
<div tabindex="0" class="btn">
Group by: <span x-text="groupBy === 'none' ? 'None' : (groupBy.charAt(0).toUpperCase() + groupBy.slice(1))"></span> 🞃
</div>
<ul tabindex="0" class="dropdown-content menu p-2 shadow bg-base-100 rounded-box w-52">
<li><a href="#" @click.prevent="groupBy = 'none'; page = 1; loadCards()">None</a></li>
<li><a href="#" @click.prevent="groupBy = 'deck'; page = 1; loadCards()">Deck</a></li>
<li><a href="#" @click.prevent="groupBy = 'cardset'; page = 1; loadCards()">Cardset</a></li>
<li><a href="#" @click.prevent="groupBy = 'rarity'; page = 1; loadCards()">Rarity</a></li>
</ul>
</div>
<ul tabindex="0" class="dropdown-content menu p-2 shadow bg-base-100 rounded-box w-52">
<li><a href="#" @click.prevent="groupBy = 'none'; page = 1; loadCards()">No Group</a></li>
<li><a href="#" @click.prevent="groupBy = 'deck'; page = 1; loadCards()">Deck</a></li>
<li><a href="#" @click.prevent="groupBy = 'cardset'; page = 1; loadCards()">Cardset</a></li>
<li><a href="#" @click.prevent="groupBy = 'rarity'; page = 1; loadCards()">Rarity</a></li>
</ul>
</div>
</div>
<!-- Container for the partial card list -->
<div x-ref="cardList">
<!-- The contents of _card_list.html will be loaded here via AJAX -->
</div>
</div>
{% endblock %}

View file

@ -1,21 +1,8 @@
{% load card_badge %}
{% comment %}
This partial expects:
- cards: a list of card objects
- mode: a string that determines the render style.
It should be "offered" for Most Offered Cards and "wanted" for Most Wanted Cards.
- Optional:
'show_zero' flag (default False): if True, also display cards with 0 offers.
'layout' variable: if set to "auto", use an auto-fit grid based on available horizontal space.
{% endcomment %}
{% if cards %}
<div class="mx-4 grid gap-3 grid-cols-[repeat(auto-fit,minmax(150px,1fr))] justify-items-center">
{% for card in cards %}
{% if mode == "offered" %}
<a href="{% url 'cards:card_detail' card.id %}"
{% else %}
<a href="{% url 'cards:card_detail' card.id %}"
{% endif %}
class="flex justify-between items-center text-primary no-underline">
{% card_badge card card.offer_count %}
</a>

View file

@ -48,7 +48,7 @@
</div>
<div class="card-body my-4 p-0">
{% cache 3600 most_offered_cards %}
{% include "home/_card_list.html" with cards=most_offered_cards mode="wanted" %}
{% include "home/_card_list.html" with cards=most_offered_cards %}
{% endcache %}
</div>
</div>
@ -61,7 +61,7 @@
</div>
<div class="card-body my-4 p-0">
{% cache 3600 most_wanted_cards %}
{% include "home/_card_list.html" with cards=most_wanted_cards mode="offered" %}
{% include "home/_card_list.html" with cards=most_wanted_cards %}
{% endcache %}
</div>
</div>
@ -74,7 +74,7 @@
</div>
<div class="card-body my-4 p-0">
{% cache 3600 least_offered_cards %}
{% include "home/_card_list.html" with cards=least_offered_cards mode="wanted" %}
{% include "home/_card_list.html" with cards=least_offered_cards %}
{% endcache %}
</div>
</div>
@ -121,8 +121,8 @@
{% endif %}
{% endfor %}
</div>
<!-- DaisyUI Tabs for Featured Offers -->
<div class="card card-border bg-base-100 shadow-lg w-96 md:w-80 lg:w-96 mt-8 mx-auto">
<!-- DaisyUI Tabs for Featured Offers (hidden for now) -->
<div class="card card-border bg-base-100 shadow-lg w-96 md:w-80 lg:w-96 mt-8 mx-auto hidden">
<!-- Tabs navigation using daisyUI tabs-box -->
<div class="tabs tabs-box bg-white dark:bg-base-100 grid grid-cols-3 gap-1.5 justify-items-stretch">
<!-- Radio inputs for controlling tab state -->

View file

@ -7,14 +7,14 @@
<div class="container mx-auto max-w-4xl mt-6" x-data="{ allExpanded: false }">
<!-- Header-->
<div class="flex justify-between items-center mb-4">
<a href="{% url 'trade_offer_create' %}" class="btn btn-success">Create New Offer</a>
<h1 class="text-2xl font-bold">All Trade Offers</h1>
<div>
<form method="get" class="flex items-center space-x-4" x-data>
<label class="cursor-pointer flex items-center space-x-2">
<form method="get" class="flex items-center gap-4" x-data>
<label class="cursor-pointer flex items-center gap-2">
<span x-text="allExpanded ? 'Collapse All' : 'Expand All'"></span>
<input type="checkbox" name="all_expanded" value="true" class="toggle toggle-primary" @click="allExpanded = !allExpanded; $dispatch('toggle-all', { expanded: allExpanded })">
</label>
<label class="cursor-pointer flex items-center space-x-2">
<label class="cursor-pointer flex items-center gap-2">
<span>Only Closed</span>
<input type="checkbox" name="show_closed" value="true" class="toggle toggle-primary" @change="$el.form.submit()" {% if show_closed %}checked{% endif %}>
</label>
@ -24,7 +24,9 @@
</div>
<!-- Trade Offers -->
<section class="mb-12">
<h2 class="text-2xl font-bold mb-4">All Trade Offers</h2>
<div class="flex justify-end mb-4">
<a href="{% url 'trade_offer_create' %}" class="btn btn-success">Create New Offer</a>
</div>
<div
id="all-trade-offers"
x-data="tradeOffersPagination('{% url 'trade_offer_list' %}?')"

View file

@ -4,5 +4,5 @@
<div class="rarity row-start-2 col-span-2 truncate self-end align-bottom text-xs">{{ rarity }}</div>
<div class="cardset row-start-2 col-start-3 col-span-2 text-right truncate self-end align-bottom font-semibold leading-none text-sm">{{ cardset }}</div>
</div>
{% if quantity %}<span class="card-quantity-badge freeze-bg-color absolute top-3.75 right-1.5 bg-gray-600 text-white text-sm font-semibold rounded-full px-1.5">{{ quantity }}</span>{% endif %}
{% if quantity != "" %}<span class="card-quantity-badge freeze-bg-color absolute top-3.75 right-1.5 bg-gray-600 text-white text-sm font-semibold rounded-full px-1.5">{{ quantity }}</span>{% endif %}
</div>

View file

@ -0,0 +1,38 @@
<div class="flex justify-center items-center space-x-2">
<!-- First Button -->
<button class="btn btn-outline btn-md"
{% if not page_obj.has_previous %}disabled{% endif %}
@click="$dispatch('change-page', { page: 1 })">
First
</button>
<!-- Previous Button -->
<button class="btn btn-outline btn-md"
{% if not page_obj.has_previous %}disabled{% endif %}
@click="$dispatch('change-page', { page: {{ page_obj.previous_page }} })">
Prev
</button>
<!-- Goto Page -->
<span class="flex items-center space-x-1 gap-2">
<input type="number" min="1" max="{{ page_obj.paginator.num_pages }}" value="{{ page_obj.number }}"
class="input input-xs text-center" id="gotoPageInput">
<button class="btn btn-outline btn-md"
@click="(document.getElementById('gotoPageInput').value >= 1 && document.getElementById('gotoPageInput').value <= {{ page_obj.paginator.num_pages }}) && $dispatch('change-page', { page: parseInt(document.getElementById('gotoPageInput').value) })">
Go
</button>
</span>
<!-- Next Button -->
<button class="btn btn-outline btn-md"
{% if not page_obj.has_next %}disabled{% endif %}
@click="$dispatch('change-page', { page: {{ page_obj.next_page }} })">
Next
</button>
<!-- Last Button -->
<button class="btn btn-outline btn-md"
{% if page_obj.number == page_obj.paginator.num_pages %}disabled{% endif %}
@click="$dispatch('change-page', { page: {{ page_obj.paginator.num_pages }} })">
Last
</button>
</div>
<div class="flex items-center justify-center mt-2">
<span>Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}</span>
</div>

View file

@ -57,7 +57,7 @@
<!-- Main Trade Offer Row -->
<div class="flip-face-body self-start">
<a href="{% url 'trade_offer_detail' pk=offer_pk %}" class="no-underline block">
<div class="px-2 main-badges {% if not screenshot_mode and have_cards_available|length == 1 and want_cards_available|length == 1 %}py-[14px]{%else%}pb-0{% endif %}">
<div class="px-2 main-badges pb-0">
{% if screenshot_mode and num_cards_available >= 4 %}
<!-- When screenshot_mode is true, use an outer grid with 3 columns: Has side, a vertical divider, and Wants side -->
<div class="flex flex-row gap-2 justify-around">
@ -151,6 +151,8 @@
d="M19 9l-7 7-7-7" />
</svg>
</div>
{% else %}
<div class="h-5"></div>
{% endif %}
{% if not screenshot_mode %}
<div class="flip-face-footer self-end">