finished conversion to tailwind

This commit is contained in:
badblocks 2025-03-11 23:45:27 -07:00
parent 6e2843c60e
commit d62956d465
50 changed files with 2490 additions and 1273 deletions

View file

@ -1,32 +1,32 @@
from collections import defaultdict
from django.views.generic import TemplateView
from django.urls import reverse_lazy
from django.db.models import Count, Q, Prefetch, Sum
from django.db.models import Count, Q, Prefetch, Sum, F, IntegerField, Value, BooleanField, Case, When
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from trades.models import TradeOffer
from trades.models import TradeOffer, TradeAcceptance, TradeOfferHaveCard, TradeOfferWantCard
from cards.models import Card, CardSet, Rarity
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page
from django.template.response import TemplateResponse
from django.http import HttpResponseRedirect
@method_decorator(cache_page(60), name='get') # Cache view for 60 seconds
@method_decorator(cache_page(60), name='get')
class HomePageView(TemplateView):
template_name = "home/home.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# Use POST data if available, else fallback to GET
request_data = self.request.POST if self.request.method == "POST" else self.request.GET
def get_base_trade_offer_queryset(self):
"""
Returns a queryset for TradeOffer that includes prefetches and denormalized aggregates.
"""
active_states = [
TradeAcceptance.AcceptanceState.ACCEPTED,
TradeAcceptance.AcceptanceState.SENT,
TradeAcceptance.AcceptanceState.RECEIVED,
TradeAcceptance.AcceptanceState.THANKED_BY_INITIATOR,
TradeAcceptance.AcceptanceState.THANKED_BY_ACCEPTOR,
TradeAcceptance.AcceptanceState.THANKED_BY_BOTH,
]
# --- Search form logic ---
offered_cards = request_data.getlist("offered_cards")
wanted_cards = request_data.getlist("wanted_cards")
context["offered_cards"] = offered_cards
context["wanted_cards"] = wanted_cards
# Define prefetch objects ordered by number of associated trade offers ascending,
# and by id secondarily.
have_cards_prefetch = Prefetch(
'have_cards',
queryset=Card.objects.annotate(
@ -40,11 +40,9 @@ class HomePageView(TemplateView):
).order_by("trade_offer_count", "id")
)
search_results = None
if offered_cards or wanted_cards:
# Instead of filtering by a 'state' field (which no longer exists),
# we fetch all offers. You may later add logic to filter only "open" offers.
qs = TradeOffer.objects.all().prefetch_related(
qs = (
TradeOffer.objects.all()
.prefetch_related(
have_cards_prefetch,
"have_cards__decks",
"have_cards__rarity",
@ -52,116 +50,80 @@ class HomePageView(TemplateView):
want_cards_prefetch,
"want_cards__decks",
"want_cards__rarity",
"want_cards__cardset"
).select_related(
"initiated_by__user"
"want_cards__cardset",
"acceptances"
)
if offered_cards:
try:
offered_card_ids = [int(card) for card in offered_cards]
except ValueError:
qs = qs.none()
else:
qs = qs.filter(want_cards__id__in=offered_card_ids)
if wanted_cards:
try:
wanted_card_ids = [int(card) for card in wanted_cards]
except ValueError:
qs = qs.none()
else:
qs = qs.filter(have_cards__id__in=wanted_card_ids)
page_number = request_data.get("page", 1)
paginator = Paginator(qs, 6)
try:
search_results = paginator.page(page_number)
except PageNotAnInteger:
search_results = paginator.page(1)
except EmptyPage:
search_results = paginator.page(paginator.num_pages)
context["search_results"] = search_results
# --- Recently posted offers (latest 5, newest first) ---
context["recent_offers"] = TradeOffer.objects.order_by("-created_at").prefetch_related(
have_cards_prefetch,
"have_cards__decks",
"have_cards__rarity",
"have_cards__cardset",
want_cards_prefetch,
"want_cards__decks",
"want_cards__rarity",
"want_cards__cardset"
).select_related(
"initiated_by__user"
)[:5]
# --- Most offered cards ---
context["most_offered_cards"] = Card.objects.filter(
tradeofferhavecard__isnull=False
).annotate(
offer_count=Sum("tradeofferhavecard__quantity")
).order_by("-offer_count").select_related("rarity", "cardset").prefetch_related("decks")[:5]
# --- Most wanted cards ---
context["most_wanted_cards"] = Card.objects.filter(
tradeofferwantcard__isnull=False
).annotate(
offer_count=Sum("tradeofferwantcard__quantity")
).order_by("-offer_count").select_related("rarity", "cardset").prefetch_related("decks")[:5]
# --- Least offered cards ---
context["least_offered_cards"] = Card.objects.annotate(
offer_count=Sum("tradeofferhavecard__quantity")
).order_by("offer_count", "?")[:5]
# --- Featured offers grouped by rarity (using card.rarity.icon for tab names) ---
featured = {}
all_offers = list(
TradeOffer.objects.order_by("created_at").prefetch_related(
have_cards_prefetch,
"have_cards__decks",
"have_cards__rarity",
"have_cards__cardset",
want_cards_prefetch,
"want_cards__decks",
"want_cards__rarity",
"want_cards__cardset"
).select_related(
"initiated_by__user"
.select_related("initiated_by__user")
.annotate(
is_active=Case(
When(
Q(total_have_accepted__lt=F('total_have_quantity')) &
Q(total_want_accepted__lt=F('total_want_quantity')),
then=Value(True)
),
default=Value(False),
output_field=BooleanField()
)
)
)
featured["All"] = all_offers[:5]
return qs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# Add available_cards QuerySet so card_multiselect works properly.
context["available_cards"] = Card.objects.all() \
.order_by("name", "rarity__pk") \
.select_related("rarity", "cardset") \
.prefetch_related("decks")
# Group offers by normalized rarity id from their have_cards
# Reuse base trade offer queryset for market stats
base_offer_qs = self.get_base_trade_offer_queryset().filter(manually_closed=False, is_active=True)
# Recent Offers
recent_offers_qs = base_offer_qs.order_by("-created_at")[:10]
context["recent_offers"] = list(recent_offers_qs)[:5]
# Most Offered Cards
context["most_offered_cards"] = (
Card.objects.filter(tradeofferhavecard__isnull=False)
.annotate(offer_count=Sum("tradeofferhavecard__quantity"))
.order_by("-offer_count")
.select_related("rarity", "cardset")
.prefetch_related("decks")[:5]
)
# Most Wanted Cards
context["most_wanted_cards"] = (
Card.objects.filter(tradeofferwantcard__isnull=False)
.annotate(offer_count=Sum("tradeofferwantcard__quantity"))
.order_by("-offer_count")
.select_related("rarity", "cardset")
.prefetch_related("decks")[:5]
)
# Least Offered Cards
context["least_offered_cards"] = (
Card.objects.annotate(offer_count=Sum("tradeofferhavecard__quantity"))
.order_by("offer_count", "?")[:5]
)
# Featured Offers grouped by rarity
all_offers = base_offer_qs.order_by("created_at")
featured = {}
featured["All"] = all_offers[:5]
grouped = defaultdict(list)
for offer in all_offers:
normalized_ids = set()
for card in offer.have_cards.all():
if card.rarity:
normalized_ids.add(card.rarity.normalized_id)
normalized_ids = {card.rarity.normalized_id for card in offer.have_cards.all() if card.rarity}
for norm in normalized_ids:
grouped[norm].append(offer)
# Map each normalized rarity id to a representative icon
norm_ids_available = list(grouped.keys())
rareness_qs = Rarity.objects.filter(pk__in=[6] + [nid for nid in norm_ids_available if nid != 6])
rarity_map = {rarity.pk: rarity.icons for rarity in rareness_qs}
# Order groups by descending normalized rarity id
for norm in sorted(grouped.keys(), reverse=True):
offers = grouped[norm]
icon_label = rarity_map.get(norm)
if icon_label:
featured[icon_label] = offers[:5]
context["featured_offers"] = featured
return context
def post(self, request, *args, **kwargs):
# If the request is AJAX, return only the search results fragment
context = self.get_context_data(**kwargs)
if request.headers.get('x-requested-with') == 'XMLHttpRequest':
return TemplateResponse(request, "home/_search_results.html", context)
return self.render_to_response(context)
return context