Various small bug fixes, break out pagination for cards into its own mixin and templatetag
This commit is contained in:
parent
05a279fa3a
commit
138a929da6
17 changed files with 225 additions and 136 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 5.1.2 on 2025-03-28 04:43
|
# Generated by Django 5.1.2 on 2025-03-29 03:33
|
||||||
|
|
||||||
import accounts.models
|
import accounts.models
|
||||||
import django.contrib.auth.models
|
import django.contrib.auth.models
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 5.1.2 on 2025-03-28 04:43
|
# Generated by Django 5.1.2 on 2025-03-29 03:33
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
|
||||||
42
cards/mixins.py
Normal file
42
cards/mixins.py
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
from math import ceil
|
||||||
|
|
||||||
|
class ReusablePaginationMixin:
|
||||||
|
"""
|
||||||
|
A mixin that encapsulates reusable pagination logic.
|
||||||
|
Use in Django ListViews to generate custom pagination context.
|
||||||
|
"""
|
||||||
|
per_page = 10 # Default; can be overridden in your view.
|
||||||
|
|
||||||
|
def paginate_data(self, data_list, page_number):
|
||||||
|
"""
|
||||||
|
Paginate a list of items.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
data_list (list): The list of items to paginate.
|
||||||
|
page_number (int): Current page number.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
tuple: (paginated_items, pagination_context)
|
||||||
|
"""
|
||||||
|
total_items = len(data_list)
|
||||||
|
num_pages = ceil(total_items / self.per_page) if self.per_page > 0 else 1
|
||||||
|
|
||||||
|
# Ensure page_number is within valid bounds.
|
||||||
|
if page_number < 1:
|
||||||
|
page_number = 1
|
||||||
|
elif page_number > num_pages:
|
||||||
|
page_number = num_pages
|
||||||
|
|
||||||
|
start = (page_number - 1) * self.per_page
|
||||||
|
end = page_number * self.per_page
|
||||||
|
items = data_list[start:end]
|
||||||
|
|
||||||
|
pagination_context = {
|
||||||
|
"number": page_number,
|
||||||
|
"has_previous": page_number > 1,
|
||||||
|
"has_next": page_number < num_pages,
|
||||||
|
"previous_page": page_number - 1 if page_number > 1 else 1,
|
||||||
|
"next_page": page_number + 1 if page_number < num_pages else num_pages,
|
||||||
|
"paginator": {"num_pages": num_pages},
|
||||||
|
}
|
||||||
|
return items, pagination_context
|
||||||
11
cards/templatetags/pagination_tags.py
Normal file
11
cards/templatetags/pagination_tags.py
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
from django import template
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
|
||||||
|
@register.inclusion_tag("templatetags/pagination_controls.html", takes_context=True)
|
||||||
|
def render_pagination(context, page_obj):
|
||||||
|
"""
|
||||||
|
Renders pagination controls given a page_obj.
|
||||||
|
The controls use values like page_obj.number, page_obj.has_previous, etc.
|
||||||
|
"""
|
||||||
|
return {"page_obj": page_obj}
|
||||||
|
|
@ -3,6 +3,7 @@ from django.urls import reverse_lazy
|
||||||
from django.views.generic import UpdateView, DeleteView, CreateView, ListView, DetailView
|
from django.views.generic import UpdateView, DeleteView, CreateView, ListView, DetailView
|
||||||
from cards.models import Card
|
from cards.models import Card
|
||||||
from trades.models import TradeOffer
|
from trades.models import TradeOffer
|
||||||
|
from cards.mixins import ReusablePaginationMixin
|
||||||
|
|
||||||
class CardDetailView(DetailView):
|
class CardDetailView(DetailView):
|
||||||
model = Card
|
model = Card
|
||||||
|
|
@ -62,9 +63,9 @@ class TradeOfferWantCardListView(ListView):
|
||||||
context['side'] = 'want'
|
context['side'] = 'want'
|
||||||
return context
|
return context
|
||||||
|
|
||||||
class CardListView(ListView):
|
class CardListView(ReusablePaginationMixin, ListView):
|
||||||
model = Card
|
model = Card
|
||||||
paginate_by = 100 # For non-grouped mode; grouping mode will override default pagination.
|
paginate_by = 36 # For non-grouped mode; grouping mode will override default pagination.
|
||||||
context_object_name = "cards"
|
context_object_name = "cards"
|
||||||
|
|
||||||
def get_template_names(self):
|
def get_template_names(self):
|
||||||
|
|
@ -102,13 +103,11 @@ class CardListView(ListView):
|
||||||
context["group_by"] = group_by
|
context["group_by"] = group_by
|
||||||
|
|
||||||
if group_by in ("deck", "cardset", "rarity"):
|
if group_by in ("deck", "cardset", "rarity"):
|
||||||
# Fetch the complete queryset (no slicing)
|
|
||||||
full_qs = self.get_queryset()
|
full_qs = self.get_queryset()
|
||||||
all_cards = list(full_qs)
|
all_cards = list(full_qs)
|
||||||
flat_cards = []
|
flat_cards = []
|
||||||
|
|
||||||
if group_by == "deck":
|
if group_by == "deck":
|
||||||
# Each card may belong to multiple decks – reproduce the existing logic.
|
|
||||||
for card in all_cards:
|
for card in all_cards:
|
||||||
for deck in card.decks.all():
|
for deck in card.decks.all():
|
||||||
flat_cards.append({"group": deck.name, "card": card})
|
flat_cards.append({"group": deck.name, "card": card})
|
||||||
|
|
@ -119,23 +118,19 @@ class CardListView(ListView):
|
||||||
flat_cards.sort(key=lambda x: x["group"].lower())
|
flat_cards.sort(key=lambda x: x["group"].lower())
|
||||||
elif group_by == "rarity":
|
elif group_by == "rarity":
|
||||||
for card in all_cards:
|
for card in all_cards:
|
||||||
flat_cards.append({"group": card.rarity_level, "card": card})
|
flat_cards.append({"group": card.rarity_icon, "sort_group": card.rarity_level, "card": card})
|
||||||
flat_cards.sort(key=lambda x: x["group"], reverse=True)
|
flat_cards.sort(key=lambda x: x["sort_group"], reverse=True)
|
||||||
|
|
||||||
total_cards = len(flat_cards)
|
|
||||||
try:
|
try:
|
||||||
page_number = int(self.request.GET.get("page", 1))
|
page_number = int(self.request.GET.get("page", 1))
|
||||||
if page_number < 1:
|
|
||||||
page_number = 1
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
page_number = 1
|
page_number = 1
|
||||||
|
|
||||||
per_page = 96
|
# Use our custom mixin logic here
|
||||||
start = (page_number - 1) * per_page
|
self.per_page = 36
|
||||||
end = page_number * per_page
|
page_flat_cards, pagination_context = self.paginate_data(flat_cards, page_number)
|
||||||
page_flat_cards = flat_cards[start:end]
|
|
||||||
|
|
||||||
# Reassemble the flat list into grouped structure for just this page.
|
# Reassemble the flat list into groups for the current page.
|
||||||
page_groups = []
|
page_groups = []
|
||||||
for item in page_flat_cards:
|
for item in page_flat_cards:
|
||||||
group_value = item["group"]
|
group_value = item["group"]
|
||||||
|
|
@ -145,25 +140,22 @@ class CardListView(ListView):
|
||||||
else:
|
else:
|
||||||
page_groups.append({"group": group_value, "cards": [card_obj]})
|
page_groups.append({"group": group_value, "cards": [card_obj]})
|
||||||
context["groups"] = page_groups
|
context["groups"] = page_groups
|
||||||
|
context["page_obj"] = pagination_context
|
||||||
# Set up custom pagination context.
|
context["total_cards"] = len(flat_cards)
|
||||||
from math import ceil
|
|
||||||
num_pages = ceil(total_cards / per_page)
|
|
||||||
page_obj = {
|
|
||||||
"number": page_number,
|
|
||||||
"has_previous": page_number > 1,
|
|
||||||
"has_next": page_number < num_pages,
|
|
||||||
"previous_page_number": page_number - 1 if page_number > 1 else None,
|
|
||||||
"next_page_number": page_number + 1 if page_number < num_pages else None,
|
|
||||||
"paginator": {
|
|
||||||
"num_pages": num_pages,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
context["page_obj"] = page_obj
|
|
||||||
context["is_paginated"] = total_cards > per_page
|
|
||||||
context["total_cards"] = total_cards
|
|
||||||
# Optionally, keep the full queryset in object_list.
|
|
||||||
context["object_list"] = full_qs
|
context["object_list"] = full_qs
|
||||||
return context
|
return context
|
||||||
|
else:
|
||||||
|
# For non-grouped mode, transform the built-in paginator page
|
||||||
|
if "page_obj" in context:
|
||||||
|
page = context["page_obj"]
|
||||||
|
# Create a unified pagination context dict
|
||||||
|
custom_page_obj = {
|
||||||
|
"number": page.number,
|
||||||
|
"has_previous": page.has_previous(),
|
||||||
|
"has_next": page.has_next(),
|
||||||
|
"previous_page": page.previous_page_number() if page.has_previous() else 1,
|
||||||
|
"next_page": page.next_page_number() if page.has_next() else page.paginator.num_pages,
|
||||||
|
"paginator": {"num_pages": page.paginator.num_pages},
|
||||||
|
}
|
||||||
|
context["page_obj"] = custom_page_obj
|
||||||
return context
|
return context
|
||||||
|
|
@ -2,6 +2,7 @@ from collections import defaultdict, OrderedDict
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
from django.db.models import Count, Q, Prefetch, Sum, F, IntegerField, Value, BooleanField, Case, When
|
from django.db.models import Count, Q, Prefetch, Sum, F, IntegerField, Value, BooleanField, Case, When
|
||||||
|
from django.db.models.functions import Coalesce
|
||||||
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
|
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
|
||||||
from trades.models import TradeOffer, TradeAcceptance, TradeOfferHaveCard, TradeOfferWantCard
|
from trades.models import TradeOffer, TradeAcceptance, TradeOfferHaveCard, TradeOfferWantCard
|
||||||
from cards.models import Card
|
from cards.models import Card
|
||||||
|
|
@ -61,7 +62,9 @@ class HomePageView(TemplateView):
|
||||||
# Least Offered Cards
|
# Least Offered Cards
|
||||||
try:
|
try:
|
||||||
context["least_offered_cards"] = (
|
context["least_offered_cards"] = (
|
||||||
Card.objects.annotate(offer_count=Sum("tradeofferhavecard__quantity"))
|
Card.objects.annotate(
|
||||||
|
offer_count=Coalesce(Sum("tradeofferhavecard__quantity"), 0)
|
||||||
|
)
|
||||||
.order_by("offer_count")[:6]
|
.order_by("offer_count")[:6]
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
|
||||||
|
|
@ -4463,7 +4463,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
3
|
3
|
||||||
],
|
],
|
||||||
"rarity_icon": "🌟🌟",
|
"rarity_icon": "⭐️⭐️",
|
||||||
"rarity_level": 6,
|
"rarity_level": 6,
|
||||||
"created_at": "2025-02-17T02:44:18.706Z",
|
"created_at": "2025-02-17T02:44:18.706Z",
|
||||||
"updated_at": "2025-02-17T02:44:18.706Z"
|
"updated_at": "2025-02-17T02:44:18.706Z"
|
||||||
|
|
@ -4479,7 +4479,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
2
|
2
|
||||||
],
|
],
|
||||||
"rarity_icon": "🌟🌟",
|
"rarity_icon": "⭐️⭐️",
|
||||||
"rarity_level": 6,
|
"rarity_level": 6,
|
||||||
"created_at": "2025-02-17T02:44:18.706Z",
|
"created_at": "2025-02-17T02:44:18.706Z",
|
||||||
"updated_at": "2025-02-17T02:44:18.706Z"
|
"updated_at": "2025-02-17T02:44:18.706Z"
|
||||||
|
|
@ -4495,7 +4495,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
4
|
4
|
||||||
],
|
],
|
||||||
"rarity_icon": "🌟🌟",
|
"rarity_icon": "⭐️⭐️",
|
||||||
"rarity_level": 6,
|
"rarity_level": 6,
|
||||||
"created_at": "2025-02-17T02:44:18.706Z",
|
"created_at": "2025-02-17T02:44:18.706Z",
|
||||||
"updated_at": "2025-02-17T02:44:18.706Z"
|
"updated_at": "2025-02-17T02:44:18.706Z"
|
||||||
|
|
@ -4511,7 +4511,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
2
|
2
|
||||||
],
|
],
|
||||||
"rarity_icon": "🌟🌟",
|
"rarity_icon": "⭐️⭐️",
|
||||||
"rarity_level": 6,
|
"rarity_level": 6,
|
||||||
"created_at": "2025-02-17T02:44:18.706Z",
|
"created_at": "2025-02-17T02:44:18.706Z",
|
||||||
"updated_at": "2025-02-17T02:44:18.706Z"
|
"updated_at": "2025-02-17T02:44:18.706Z"
|
||||||
|
|
@ -4527,7 +4527,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
3
|
3
|
||||||
],
|
],
|
||||||
"rarity_icon": "🌟🌟",
|
"rarity_icon": "⭐️⭐️",
|
||||||
"rarity_level": 6,
|
"rarity_level": 6,
|
||||||
"created_at": "2025-02-17T02:44:18.706Z",
|
"created_at": "2025-02-17T02:44:18.706Z",
|
||||||
"updated_at": "2025-02-17T02:44:18.706Z"
|
"updated_at": "2025-02-17T02:44:18.706Z"
|
||||||
|
|
@ -4543,7 +4543,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
4
|
4
|
||||||
],
|
],
|
||||||
"rarity_icon": "🌟🌟",
|
"rarity_icon": "⭐️⭐️",
|
||||||
"rarity_level": 6,
|
"rarity_level": 6,
|
||||||
"created_at": "2025-02-17T02:44:18.706Z",
|
"created_at": "2025-02-17T02:44:18.706Z",
|
||||||
"updated_at": "2025-02-17T02:44:18.706Z"
|
"updated_at": "2025-02-17T02:44:18.706Z"
|
||||||
|
|
@ -4559,7 +4559,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
3
|
3
|
||||||
],
|
],
|
||||||
"rarity_icon": "🌟🌟🌟",
|
"rarity_icon": "⭐️⭐️⭐️",
|
||||||
"rarity_level": 7,
|
"rarity_level": 7,
|
||||||
"created_at": "2025-02-17T02:44:18.706Z",
|
"created_at": "2025-02-17T02:44:18.706Z",
|
||||||
"updated_at": "2025-02-17T02:44:18.706Z"
|
"updated_at": "2025-02-17T02:44:18.706Z"
|
||||||
|
|
@ -4575,7 +4575,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
4
|
4
|
||||||
],
|
],
|
||||||
"rarity_icon": "🌟🌟🌟",
|
"rarity_icon": "⭐️⭐️⭐️",
|
||||||
"rarity_level": 7,
|
"rarity_level": 7,
|
||||||
"created_at": "2025-02-17T02:44:18.706Z",
|
"created_at": "2025-02-17T02:44:18.706Z",
|
||||||
"updated_at": "2025-02-17T02:44:18.706Z"
|
"updated_at": "2025-02-17T02:44:18.706Z"
|
||||||
|
|
@ -4591,7 +4591,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
2
|
2
|
||||||
],
|
],
|
||||||
"rarity_icon": "🌟🌟🌟",
|
"rarity_icon": "⭐️⭐️⭐️",
|
||||||
"rarity_level": 7,
|
"rarity_level": 7,
|
||||||
"created_at": "2025-02-17T02:44:18.706Z",
|
"created_at": "2025-02-17T02:44:18.706Z",
|
||||||
"updated_at": "2025-02-17T02:44:18.706Z"
|
"updated_at": "2025-02-17T02:44:18.706Z"
|
||||||
|
|
@ -4609,7 +4609,7 @@
|
||||||
3,
|
3,
|
||||||
4
|
4
|
||||||
],
|
],
|
||||||
"rarity_icon": "🌟🌟🌟",
|
"rarity_icon": "⭐️⭐️⭐️",
|
||||||
"rarity_level": 7,
|
"rarity_level": 7,
|
||||||
"created_at": "2025-02-17T02:44:18.706Z",
|
"created_at": "2025-02-17T02:44:18.706Z",
|
||||||
"updated_at": "2025-02-17T02:44:18.706Z"
|
"updated_at": "2025-02-17T02:44:18.706Z"
|
||||||
|
|
@ -5991,7 +5991,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
5
|
5
|
||||||
],
|
],
|
||||||
"rarity_icon": "🌟🌟",
|
"rarity_icon": "⭐️⭐️",
|
||||||
"rarity_level": 6,
|
"rarity_level": 6,
|
||||||
"created_at": "2025-02-17T02:44:18.706Z",
|
"created_at": "2025-02-17T02:44:18.706Z",
|
||||||
"updated_at": "2025-02-17T02:44:18.706Z"
|
"updated_at": "2025-02-17T02:44:18.706Z"
|
||||||
|
|
@ -6007,7 +6007,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
5
|
5
|
||||||
],
|
],
|
||||||
"rarity_icon": "🌟🌟",
|
"rarity_icon": "⭐️⭐️",
|
||||||
"rarity_level": 6,
|
"rarity_level": 6,
|
||||||
"created_at": "2025-02-17T02:44:18.706Z",
|
"created_at": "2025-02-17T02:44:18.706Z",
|
||||||
"updated_at": "2025-02-17T02:44:18.706Z"
|
"updated_at": "2025-02-17T02:44:18.706Z"
|
||||||
|
|
@ -6023,7 +6023,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
5
|
5
|
||||||
],
|
],
|
||||||
"rarity_icon": "🌟🌟🌟",
|
"rarity_icon": "⭐️⭐️⭐️",
|
||||||
"rarity_level": 7,
|
"rarity_level": 7,
|
||||||
"created_at": "2025-02-17T02:44:18.706Z",
|
"created_at": "2025-02-17T02:44:18.706Z",
|
||||||
"updated_at": "2025-02-17T02:44:18.706Z"
|
"updated_at": "2025-02-17T02:44:18.706Z"
|
||||||
|
|
@ -9218,7 +9218,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
6
|
6
|
||||||
],
|
],
|
||||||
"rarity_icon": "🌟🌟",
|
"rarity_icon": "⭐️⭐️",
|
||||||
"rarity_level": 6,
|
"rarity_level": 6,
|
||||||
"created_at": "2025-02-17T02:44:18.706Z",
|
"created_at": "2025-02-17T02:44:18.706Z",
|
||||||
"updated_at": "2025-02-17T02:44:18.706Z"
|
"updated_at": "2025-02-17T02:44:18.706Z"
|
||||||
|
|
@ -9234,7 +9234,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
7
|
7
|
||||||
],
|
],
|
||||||
"rarity_icon": "🌟🌟",
|
"rarity_icon": "⭐️⭐️",
|
||||||
"rarity_level": 6,
|
"rarity_level": 6,
|
||||||
"created_at": "2025-02-17T02:44:18.706Z",
|
"created_at": "2025-02-17T02:44:18.706Z",
|
||||||
"updated_at": "2025-02-17T02:44:18.706Z"
|
"updated_at": "2025-02-17T02:44:18.706Z"
|
||||||
|
|
@ -9250,7 +9250,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
6
|
6
|
||||||
],
|
],
|
||||||
"rarity_icon": "🌟🌟",
|
"rarity_icon": "⭐️⭐️",
|
||||||
"rarity_level": 6,
|
"rarity_level": 6,
|
||||||
"created_at": "2025-02-17T02:44:18.706Z",
|
"created_at": "2025-02-17T02:44:18.706Z",
|
||||||
"updated_at": "2025-02-17T02:44:18.706Z"
|
"updated_at": "2025-02-17T02:44:18.706Z"
|
||||||
|
|
@ -9266,7 +9266,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
7
|
7
|
||||||
],
|
],
|
||||||
"rarity_icon": "🌟🌟",
|
"rarity_icon": "⭐️⭐️",
|
||||||
"rarity_level": 6,
|
"rarity_level": 6,
|
||||||
"created_at": "2025-02-17T02:44:18.706Z",
|
"created_at": "2025-02-17T02:44:18.706Z",
|
||||||
"updated_at": "2025-02-17T02:44:18.706Z"
|
"updated_at": "2025-02-17T02:44:18.706Z"
|
||||||
|
|
@ -9282,7 +9282,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
6
|
6
|
||||||
],
|
],
|
||||||
"rarity_icon": "🌟🌟",
|
"rarity_icon": "⭐️⭐️",
|
||||||
"rarity_level": 6,
|
"rarity_level": 6,
|
||||||
"created_at": "2025-02-17T02:44:18.706Z",
|
"created_at": "2025-02-17T02:44:18.706Z",
|
||||||
"updated_at": "2025-02-17T02:44:18.706Z"
|
"updated_at": "2025-02-17T02:44:18.706Z"
|
||||||
|
|
@ -9298,7 +9298,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
7
|
7
|
||||||
],
|
],
|
||||||
"rarity_icon": "🌟🌟",
|
"rarity_icon": "⭐️⭐️",
|
||||||
"rarity_level": 6,
|
"rarity_level": 6,
|
||||||
"created_at": "2025-02-17T02:44:18.706Z",
|
"created_at": "2025-02-17T02:44:18.706Z",
|
||||||
"updated_at": "2025-02-17T02:44:18.706Z"
|
"updated_at": "2025-02-17T02:44:18.706Z"
|
||||||
|
|
@ -9314,7 +9314,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
6
|
6
|
||||||
],
|
],
|
||||||
"rarity_icon": "🌟🌟",
|
"rarity_icon": "⭐️⭐️",
|
||||||
"rarity_level": 6,
|
"rarity_level": 6,
|
||||||
"created_at": "2025-02-17T02:44:18.706Z",
|
"created_at": "2025-02-17T02:44:18.706Z",
|
||||||
"updated_at": "2025-02-17T02:44:18.706Z"
|
"updated_at": "2025-02-17T02:44:18.706Z"
|
||||||
|
|
@ -9330,7 +9330,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
7
|
7
|
||||||
],
|
],
|
||||||
"rarity_icon": "🌟🌟",
|
"rarity_icon": "⭐️⭐️",
|
||||||
"rarity_level": 6,
|
"rarity_level": 6,
|
||||||
"created_at": "2025-02-17T02:44:18.706Z",
|
"created_at": "2025-02-17T02:44:18.706Z",
|
||||||
"updated_at": "2025-02-17T02:44:18.706Z"
|
"updated_at": "2025-02-17T02:44:18.706Z"
|
||||||
|
|
@ -9346,7 +9346,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
7
|
7
|
||||||
],
|
],
|
||||||
"rarity_icon": "🌟🌟🌟",
|
"rarity_icon": "⭐️⭐️⭐️",
|
||||||
"rarity_level": 7,
|
"rarity_level": 7,
|
||||||
"created_at": "2025-02-17T02:44:18.706Z",
|
"created_at": "2025-02-17T02:44:18.706Z",
|
||||||
"updated_at": "2025-02-17T02:44:18.706Z"
|
"updated_at": "2025-02-17T02:44:18.706Z"
|
||||||
|
|
@ -9362,7 +9362,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
6
|
6
|
||||||
],
|
],
|
||||||
"rarity_icon": "🌟🌟🌟",
|
"rarity_icon": "⭐️⭐️⭐️",
|
||||||
"rarity_level": 7,
|
"rarity_level": 7,
|
||||||
"created_at": "2025-02-17T02:44:18.706Z",
|
"created_at": "2025-02-17T02:44:18.706Z",
|
||||||
"updated_at": "2025-02-17T02:44:18.706Z"
|
"updated_at": "2025-02-17T02:44:18.706Z"
|
||||||
|
|
@ -12484,7 +12484,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
9
|
9
|
||||||
],
|
],
|
||||||
"rarity_level": 6,
|
"rarity_level": 5,
|
||||||
"rarity_icon": "✨",
|
"rarity_icon": "✨",
|
||||||
"created_at": "2025-03-26T12:25:17.706Z",
|
"created_at": "2025-03-26T12:25:17.706Z",
|
||||||
"updated_at": "2025-03-26T12:25:17.706Z"
|
"updated_at": "2025-03-26T12:25:17.706Z"
|
||||||
|
|
@ -12500,7 +12500,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
9
|
9
|
||||||
],
|
],
|
||||||
"rarity_level": 6,
|
"rarity_level": 5,
|
||||||
"rarity_icon": "✨",
|
"rarity_icon": "✨",
|
||||||
"created_at": "2025-03-26T12:25:17.706Z",
|
"created_at": "2025-03-26T12:25:17.706Z",
|
||||||
"updated_at": "2025-03-26T12:25:17.706Z"
|
"updated_at": "2025-03-26T12:25:17.706Z"
|
||||||
|
|
@ -12516,7 +12516,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
9
|
9
|
||||||
],
|
],
|
||||||
"rarity_level": 6,
|
"rarity_level": 5,
|
||||||
"rarity_icon": "✨",
|
"rarity_icon": "✨",
|
||||||
"created_at": "2025-03-26T12:25:17.706Z",
|
"created_at": "2025-03-26T12:25:17.706Z",
|
||||||
"updated_at": "2025-03-26T12:25:17.706Z"
|
"updated_at": "2025-03-26T12:25:17.706Z"
|
||||||
|
|
@ -12532,7 +12532,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
9
|
9
|
||||||
],
|
],
|
||||||
"rarity_level": 6,
|
"rarity_level": 5,
|
||||||
"rarity_icon": "✨",
|
"rarity_icon": "✨",
|
||||||
"created_at": "2025-03-26T12:25:17.706Z",
|
"created_at": "2025-03-26T12:25:17.706Z",
|
||||||
"updated_at": "2025-03-26T12:25:17.706Z"
|
"updated_at": "2025-03-26T12:25:17.706Z"
|
||||||
|
|
@ -12548,7 +12548,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
9
|
9
|
||||||
],
|
],
|
||||||
"rarity_level": 6,
|
"rarity_level": 5,
|
||||||
"rarity_icon": "✨",
|
"rarity_icon": "✨",
|
||||||
"created_at": "2025-03-26T12:25:17.706Z",
|
"created_at": "2025-03-26T12:25:17.706Z",
|
||||||
"updated_at": "2025-03-26T12:25:17.706Z"
|
"updated_at": "2025-03-26T12:25:17.706Z"
|
||||||
|
|
@ -12564,7 +12564,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
9
|
9
|
||||||
],
|
],
|
||||||
"rarity_level": 6,
|
"rarity_level": 5,
|
||||||
"rarity_icon": "✨",
|
"rarity_icon": "✨",
|
||||||
"created_at": "2025-03-26T12:25:17.706Z",
|
"created_at": "2025-03-26T12:25:17.706Z",
|
||||||
"updated_at": "2025-03-26T12:25:17.706Z"
|
"updated_at": "2025-03-26T12:25:17.706Z"
|
||||||
|
|
@ -12580,7 +12580,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
9
|
9
|
||||||
],
|
],
|
||||||
"rarity_level": 6,
|
"rarity_level": 5,
|
||||||
"rarity_icon": "✨",
|
"rarity_icon": "✨",
|
||||||
"created_at": "2025-03-26T12:25:17.706Z",
|
"created_at": "2025-03-26T12:25:17.706Z",
|
||||||
"updated_at": "2025-03-26T12:25:17.706Z"
|
"updated_at": "2025-03-26T12:25:17.706Z"
|
||||||
|
|
@ -12596,7 +12596,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
9
|
9
|
||||||
],
|
],
|
||||||
"rarity_level": 6,
|
"rarity_level": 5,
|
||||||
"rarity_icon": "✨",
|
"rarity_icon": "✨",
|
||||||
"created_at": "2025-03-26T12:25:17.706Z",
|
"created_at": "2025-03-26T12:25:17.706Z",
|
||||||
"updated_at": "2025-03-26T12:25:17.706Z"
|
"updated_at": "2025-03-26T12:25:17.706Z"
|
||||||
|
|
@ -12612,7 +12612,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
9
|
9
|
||||||
],
|
],
|
||||||
"rarity_level": 6,
|
"rarity_level": 5,
|
||||||
"rarity_icon": "✨",
|
"rarity_icon": "✨",
|
||||||
"created_at": "2025-03-26T12:25:17.706Z",
|
"created_at": "2025-03-26T12:25:17.706Z",
|
||||||
"updated_at": "2025-03-26T12:25:17.706Z"
|
"updated_at": "2025-03-26T12:25:17.706Z"
|
||||||
|
|
@ -12628,7 +12628,7 @@
|
||||||
"decks": [
|
"decks": [
|
||||||
9
|
9
|
||||||
],
|
],
|
||||||
"rarity_level": 6,
|
"rarity_level": 5,
|
||||||
"rarity_icon": "✨",
|
"rarity_icon": "✨",
|
||||||
"created_at": "2025-03-26T12:25:17.706Z",
|
"created_at": "2025-03-26T12:25:17.706Z",
|
||||||
"updated_at": "2025-03-26T12:25:17.706Z"
|
"updated_at": "2025-03-26T12:25:17.706Z"
|
||||||
|
|
|
||||||
|
|
@ -58,5 +58,25 @@
|
||||||
"created_at": "2025-03-13T04:52:29.166Z",
|
"created_at": "2025-03-13T04:52:29.166Z",
|
||||||
"updated_at": "2025-03-13T04:52:29.166Z"
|
"updated_at": "2025-03-13T04:52:29.166Z"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "account.emailaddress",
|
||||||
|
"pk": 1,
|
||||||
|
"fields": {
|
||||||
|
"user": 1,
|
||||||
|
"email": "rob@badblocks.email",
|
||||||
|
"verified": true,
|
||||||
|
"primary": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "account.emailaddress",
|
||||||
|
"pk": 2,
|
||||||
|
"fields": {
|
||||||
|
"user": 2,
|
||||||
|
"email": "nathanward2016@gmail.com",
|
||||||
|
"verified": true,
|
||||||
|
"primary": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
{% load card_badge %}
|
{% load card_badge %}
|
||||||
|
{% load pagination_tags %}
|
||||||
{% if group_by and groups %}
|
{% if group_by and groups %}
|
||||||
{% for group in groups %}
|
{% for group in groups %}
|
||||||
<div class="divider">{{ group.group }}</div>
|
<div class="divider">{{ group.group }}</div>
|
||||||
|
|
@ -20,21 +21,7 @@
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<!-- Pagination Controls -->
|
<!-- Somewhere in your template, e.g., after the card list: -->
|
||||||
<div class="mt-6">
|
{% if page_obj %}
|
||||||
{% if is_paginated %}
|
{% render_pagination page_obj %}
|
||||||
<div class="flex justify-center space-x-2">
|
{% endif %}
|
||||||
{% 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>
|
|
||||||
|
|
|
||||||
|
|
@ -18,15 +18,19 @@
|
||||||
x-init="loadCards()"
|
x-init="loadCards()"
|
||||||
x-on:change-page.window="page = $event.detail.page; 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">
|
<div class="flex flex-wrap items-center justify-between mb-6">
|
||||||
|
<div>
|
||||||
|
<h1 class="text-2xl font-bold">Cards</h1>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
<!-- Sort Dropdown -->
|
<!-- Sort Dropdown -->
|
||||||
<div class="dropdown dropdown-end m-1">
|
<div class="dropdown dropdown-end m-1">
|
||||||
<div tabindex="0" class="btn">
|
<div tabindex="0" class="btn">
|
||||||
<span x-text="order === 'absolute' ? 'Absolute' : (order === 'alphabetical' ? 'Alphabetical' : 'Rarity')"></span> 🞃
|
Sort by: <span x-text="order === 'absolute' ? 'None' : (order === 'alphabetical' ? 'Alphabetical' : 'Rarity')"></span> 🞃
|
||||||
</div>
|
</div>
|
||||||
<ul tabindex="0" class="dropdown-content menu p-2 shadow bg-base-100 rounded-box w-52">
|
<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 = '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 = 'alphabetical'; page = 1; loadCards()">Alphabetical</a></li>
|
||||||
<li><a href="#" @click.prevent="order = 'rarity'; page = 1; loadCards()">Rarity</a></li>
|
<li><a href="#" @click.prevent="order = 'rarity'; page = 1; loadCards()">Rarity</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
@ -34,19 +38,20 @@
|
||||||
<!-- Grouping Dropdown -->
|
<!-- Grouping Dropdown -->
|
||||||
<div class="dropdown dropdown-end m-1">
|
<div class="dropdown dropdown-end m-1">
|
||||||
<div tabindex="0" class="btn">
|
<div tabindex="0" class="btn">
|
||||||
<span x-text="groupBy === 'none' ? 'No Group' : (groupBy.charAt(0).toUpperCase() + groupBy.slice(1))"></span> 🞃
|
Group by: <span x-text="groupBy === 'none' ? 'None' : (groupBy.charAt(0).toUpperCase() + groupBy.slice(1))"></span> 🞃
|
||||||
</div>
|
</div>
|
||||||
<ul tabindex="0" class="dropdown-content menu p-2 shadow bg-base-100 rounded-box w-52">
|
<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 = '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 = '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 = 'cardset'; page = 1; loadCards()">Cardset</a></li>
|
||||||
<li><a href="#" @click.prevent="groupBy = 'rarity'; page = 1; loadCards()">Rarity</a></li>
|
<li><a href="#" @click.prevent="groupBy = 'rarity'; page = 1; loadCards()">Rarity</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<!-- Container for the partial card list -->
|
<!-- Container for the partial card list -->
|
||||||
<div x-ref="cardList">
|
<div x-ref="cardList">
|
||||||
<!-- The contents of _card_list.html will be loaded here via AJAX -->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
@ -1,21 +1,8 @@
|
||||||
{% load card_badge %}
|
{% 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 %}
|
{% if cards %}
|
||||||
<div class="mx-4 grid gap-3 grid-cols-[repeat(auto-fit,minmax(150px,1fr))] justify-items-center">
|
<div class="mx-4 grid gap-3 grid-cols-[repeat(auto-fit,minmax(150px,1fr))] justify-items-center">
|
||||||
{% for card in cards %}
|
{% for card in cards %}
|
||||||
{% if mode == "offered" %}
|
|
||||||
<a href="{% url 'cards:card_detail' card.id %}"
|
<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">
|
class="flex justify-between items-center text-primary no-underline">
|
||||||
{% card_badge card card.offer_count %}
|
{% card_badge card card.offer_count %}
|
||||||
</a>
|
</a>
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body my-4 p-0">
|
<div class="card-body my-4 p-0">
|
||||||
{% cache 3600 most_offered_cards %}
|
{% 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 %}
|
{% endcache %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -61,7 +61,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body my-4 p-0">
|
<div class="card-body my-4 p-0">
|
||||||
{% cache 3600 most_wanted_cards %}
|
{% 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 %}
|
{% endcache %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -74,7 +74,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body my-4 p-0">
|
<div class="card-body my-4 p-0">
|
||||||
{% cache 3600 least_offered_cards %}
|
{% 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 %}
|
{% endcache %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -121,8 +121,8 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
<!-- DaisyUI Tabs for Featured Offers -->
|
<!-- 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">
|
<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 -->
|
<!-- 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">
|
<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 -->
|
<!-- Radio inputs for controlling tab state -->
|
||||||
|
|
|
||||||
|
|
@ -7,14 +7,14 @@
|
||||||
<div class="container mx-auto max-w-4xl mt-6" x-data="{ allExpanded: false }">
|
<div class="container mx-auto max-w-4xl mt-6" x-data="{ allExpanded: false }">
|
||||||
<!-- Header-->
|
<!-- Header-->
|
||||||
<div class="flex justify-between items-center mb-4">
|
<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>
|
<div>
|
||||||
<form method="get" class="flex items-center space-x-4" x-data>
|
<form method="get" class="flex items-center gap-4" x-data>
|
||||||
<label class="cursor-pointer flex items-center space-x-2">
|
<label class="cursor-pointer flex items-center gap-2">
|
||||||
<span x-text="allExpanded ? 'Collapse All' : 'Expand All'"></span>
|
<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 })">
|
<input type="checkbox" name="all_expanded" value="true" class="toggle toggle-primary" @click="allExpanded = !allExpanded; $dispatch('toggle-all', { expanded: allExpanded })">
|
||||||
</label>
|
</label>
|
||||||
<label class="cursor-pointer flex items-center space-x-2">
|
<label class="cursor-pointer flex items-center gap-2">
|
||||||
<span>Only Closed</span>
|
<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 %}>
|
<input type="checkbox" name="show_closed" value="true" class="toggle toggle-primary" @change="$el.form.submit()" {% if show_closed %}checked{% endif %}>
|
||||||
</label>
|
</label>
|
||||||
|
|
@ -24,7 +24,9 @@
|
||||||
</div>
|
</div>
|
||||||
<!-- Trade Offers -->
|
<!-- Trade Offers -->
|
||||||
<section class="mb-12">
|
<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
|
<div
|
||||||
id="all-trade-offers"
|
id="all-trade-offers"
|
||||||
x-data="tradeOffersPagination('{% url 'trade_offer_list' %}?')"
|
x-data="tradeOffersPagination('{% url 'trade_offer_list' %}?')"
|
||||||
|
|
|
||||||
|
|
@ -4,5 +4,5 @@
|
||||||
<div class="rarity row-start-2 col-span-2 truncate self-end align-bottom text-xs">{{ rarity }}</div>
|
<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 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>
|
</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>
|
</div>
|
||||||
38
theme/templatetags/pagination_controls.html
Normal file
38
theme/templatetags/pagination_controls.html
Normal 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>
|
||||||
|
|
@ -57,7 +57,7 @@
|
||||||
<!-- Main Trade Offer Row -->
|
<!-- Main Trade Offer Row -->
|
||||||
<div class="flip-face-body self-start">
|
<div class="flip-face-body self-start">
|
||||||
<a href="{% url 'trade_offer_detail' pk=offer_pk %}" class="no-underline block">
|
<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 %}
|
{% 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 -->
|
<!-- 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">
|
<div class="flex flex-row gap-2 justify-around">
|
||||||
|
|
@ -151,6 +151,8 @@
|
||||||
d="M19 9l-7 7-7-7" />
|
d="M19 9l-7 7-7-7" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<div class="h-5"></div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if not screenshot_mode %}
|
{% if not screenshot_mode %}
|
||||||
<div class="flip-face-footer self-end">
|
<div class="flip-face-footer self-end">
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 5.1.2 on 2025-03-28 04:43
|
# Generated by Django 5.1.2 on 2025-03-29 03:33
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue