use <a> tags for card_badge and trade_offer clickable areas (except for main card_badge row on trade_offers, still uses @click for now because the a tag can't wrap that content for some reason). closes #14
This commit is contained in:
parent
86b061c971
commit
afaa392b2f
22 changed files with 247 additions and 227 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 5.1.2 on 2025-04-14 04:07
|
# Generated by Django 5.1.2 on 2025-04-14 20:58
|
||||||
|
|
||||||
import accounts.models
|
import accounts.models
|
||||||
import django.contrib.auth.models
|
import django.contrib.auth.models
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ class CustomUser(AbstractUser):
|
||||||
enable_email_notifications = models.BooleanField(
|
enable_email_notifications = models.BooleanField(
|
||||||
default=True,
|
default=True,
|
||||||
verbose_name="Enable Email Notifications",
|
verbose_name="Enable Email Notifications",
|
||||||
help_text="Receive new trade notifications via email."
|
help_text="Receive trade notifications via email."
|
||||||
)
|
)
|
||||||
reputation_score = models.IntegerField(default=0)
|
reputation_score = models.IntegerField(default=0)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 5.1.2 on 2025-04-14 04:07
|
# Generated by Django 5.1.2 on 2025-04-14 20:58
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,8 @@ class HomePageView(TemplateView):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Get all cards ordered by name
|
# Get all cards ordered by name, exclude cards with rarity level > 5
|
||||||
context["cards"] = Card.objects.all().order_by("name")
|
context["cards"] = Card.objects.filter(rarity_level__lte=5).order_by("name", "rarity_level")
|
||||||
|
|
||||||
# Reuse base trade offer queryset for market stats
|
# Reuse base trade offer queryset for market stats
|
||||||
base_offer_qs = TradeOffer.objects.filter(is_closed=False)
|
base_offer_qs = TradeOffer.objects.filter(is_closed=False)
|
||||||
|
|
@ -39,7 +39,7 @@ class HomePageView(TemplateView):
|
||||||
# Most Offered Cards
|
# Most Offered Cards
|
||||||
try:
|
try:
|
||||||
context["most_offered_cards"] = (
|
context["most_offered_cards"] = (
|
||||||
Card.objects.filter(tradeofferhavecard__isnull=False)
|
Card.objects.filter(tradeofferhavecard__isnull=False).filter(rarity_level__lte=5)
|
||||||
.annotate(offer_count=Sum("tradeofferhavecard__quantity"))
|
.annotate(offer_count=Sum("tradeofferhavecard__quantity"))
|
||||||
.order_by("-offer_count")[:6]
|
.order_by("-offer_count")[:6]
|
||||||
)
|
)
|
||||||
|
|
@ -50,7 +50,7 @@ class HomePageView(TemplateView):
|
||||||
# Most Wanted Cards
|
# Most Wanted Cards
|
||||||
try:
|
try:
|
||||||
context["most_wanted_cards"] = (
|
context["most_wanted_cards"] = (
|
||||||
Card.objects.filter(tradeofferwantcard__isnull=False)
|
Card.objects.filter(tradeofferwantcard__isnull=False).filter(rarity_level__lte=5)
|
||||||
.annotate(offer_count=Sum("tradeofferwantcard__quantity"))
|
.annotate(offer_count=Sum("tradeofferwantcard__quantity"))
|
||||||
.order_by("-offer_count")[:6]
|
.order_by("-offer_count")[:6]
|
||||||
)
|
)
|
||||||
|
|
@ -61,7 +61,7 @@ class HomePageView(TemplateView):
|
||||||
# Least Offered Cards
|
# Least Offered Cards
|
||||||
try:
|
try:
|
||||||
context["least_offered_cards"] = (
|
context["least_offered_cards"] = (
|
||||||
Card.objects.annotate(
|
Card.objects.filter(rarity_level__lte=5).annotate(
|
||||||
offer_count=Coalesce(Sum("tradeofferhavecard__quantity"), 0)
|
offer_count=Coalesce(Sum("tradeofferhavecard__quantity"), 0)
|
||||||
)
|
)
|
||||||
.order_by("offer_count")[:6]
|
.order_by("offer_count")[:6]
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,9 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@theme {}
|
@theme {
|
||||||
|
--breakpoint-xs: 24rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -12,19 +12,19 @@ module.exports = {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Templates within theme app (<tailwind_app_name>/templates), e.g. base.html. */
|
/* Templates within theme app (<tailwind_app_name>/templates), e.g. base.html. */
|
||||||
'../templates/**/*.html',
|
"../templates/**/*.html",
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Main templates directory of the project (BASE_DIR/templates).
|
* Main templates directory of the project (BASE_DIR/templates).
|
||||||
* Adjust the following line to match your project structure.
|
* Adjust the following line to match your project structure.
|
||||||
*/
|
*/
|
||||||
'../../templates/**/*.html',
|
"../../templates/**/*.html",
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Templates in other django apps (BASE_DIR/<any_app_name>/templates).
|
* Templates in other django apps (BASE_DIR/<any_app_name>/templates).
|
||||||
* Adjust the following line to match your project structure.
|
* Adjust the following line to match your project structure.
|
||||||
*/
|
*/
|
||||||
'../../**/templates/**/*.html',
|
"../../**/templates/**/*.html",
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JS: If you use Tailwind CSS in JavaScript, uncomment the following lines and make sure
|
* JS: If you use Tailwind CSS in JavaScript, uncomment the following lines and make sure
|
||||||
|
|
@ -42,19 +42,19 @@ module.exports = {
|
||||||
// '../../**/*.py'
|
// '../../**/*.py'
|
||||||
],
|
],
|
||||||
safelist: [
|
safelist: [
|
||||||
'alert-info',
|
"alert-info",
|
||||||
'alert-success',
|
"alert-success",
|
||||||
'alert-warning',
|
"alert-warning",
|
||||||
'alert-error',
|
"alert-error",
|
||||||
'btn-info',
|
"btn-info",
|
||||||
'btn-success',
|
"btn-success",
|
||||||
'btn-warning',
|
"btn-warning",
|
||||||
'btn-error',
|
"btn-error",
|
||||||
'bg-info',
|
"bg-info",
|
||||||
'bg-success',
|
"bg-success",
|
||||||
'bg-warning',
|
"bg-warning",
|
||||||
'bg-error',
|
"bg-error",
|
||||||
'text-gray-700'
|
"text-gray-700",
|
||||||
],
|
],
|
||||||
theme: {
|
theme: {
|
||||||
extend: {},
|
extend: {},
|
||||||
|
|
@ -65,9 +65,9 @@ module.exports = {
|
||||||
* for forms. If you don't like it or have own styling for forms,
|
* for forms. If you don't like it or have own styling for forms,
|
||||||
* comment the line below to disable '@tailwindcss/forms'.
|
* comment the line below to disable '@tailwindcss/forms'.
|
||||||
*/
|
*/
|
||||||
require('@tailwindcss/forms'),
|
require("@tailwindcss/forms"),
|
||||||
require('@tailwindcss/typography'),
|
require("@tailwindcss/typography"),
|
||||||
require('@tailwindcss/aspect-ratio'),
|
require("@tailwindcss/aspect-ratio"),
|
||||||
],
|
],
|
||||||
darkMode: 'class',
|
darkMode: "class",
|
||||||
}
|
};
|
||||||
|
|
|
||||||
|
|
@ -106,8 +106,8 @@
|
||||||
{% with gravatar_profile=request.user.email|gravatar_profile_data %}
|
{% with gravatar_profile=request.user.email|gravatar_profile_data %}
|
||||||
|
|
||||||
<div class="hovercard-profile mb-4 text-center">
|
<div class="hovercard-profile mb-4 text-center">
|
||||||
<div class="avatar block mx-auto w-32">
|
<div class="avatar block mx-auto max-w-32">
|
||||||
<div class="W-32 rounded-full">
|
<div class="rounded-full">
|
||||||
{{ request.user.email|gravatar:128 }}
|
{{ request.user.email|gravatar:128 }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -79,13 +79,13 @@
|
||||||
{% if user.is_authenticated %}
|
{% if user.is_authenticated %}
|
||||||
<div class="hidden sm:block">
|
<div class="hidden sm:block">
|
||||||
<div class="btn btn-ghost btn-circle avatar">
|
<div class="btn btn-ghost btn-circle avatar">
|
||||||
<div class="w-10 rounded-full">
|
<div class="max-w-10 rounded-full">
|
||||||
<a tabindex="0" role="button" href="{% url 'dashboard' %}">{{ user.email|gravatar_no_hover:40 }}</a>
|
<a tabindex="0" role="button" href="{% url 'dashboard' %}">{{ user.email|gravatar_no_hover:40 }}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="flex gap-2">
|
<div class="gap-2 hidden sm:flex">
|
||||||
<a tabindex="0" role="button" class="btn btn-primary" href="{% url 'account_login' %}">Login</a>
|
<a tabindex="0" role="button" class="btn btn-primary" href="{% url 'account_login' %}">Login</a>
|
||||||
<a tabindex="1" role="button" class="btn btn-secondary" href="{% url 'account_signup' %}">Sign Up</a>
|
<a tabindex="1" role="button" class="btn btn-secondary" href="{% url 'account_signup' %}">Sign Up</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -94,7 +94,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Main Content -->
|
<!-- Main Content -->
|
||||||
<main class="container mx-auto p-4 w-full xl:w-256">
|
<main class="container mx-auto p-4 w-full xl:max-w-256">
|
||||||
{% include '_messages.html' %}
|
{% include '_messages.html' %}
|
||||||
{% block content %}{% endblock %}
|
{% block content %}{% endblock %}
|
||||||
</main>
|
</main>
|
||||||
|
|
@ -121,7 +121,7 @@
|
||||||
<span class="dock-label">Trades</span>
|
<span class="dock-label">Trades</span>
|
||||||
</button>
|
</button>
|
||||||
<button @click="window.location.href = '{{ dashboard_url }}'" class="{% if request.path == dashboard_url or request.path == settings_url %}dock-active{% endif %}">
|
<button @click="window.location.href = '{{ dashboard_url }}'" class="{% if request.path == dashboard_url or request.path == settings_url %}dock-active{% endif %}">
|
||||||
{% if user.is_authenticated %}<div tabindex="0" role="button" class="avatar"><div class="w-6 rounded-full">{{ user.email|gravatar_no_hover:40 }}</div></div>{% else %}<svg class="size-[1.2em]" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g fill="currentColor" stroke-linejoin="miter" stroke-linecap="butt"><circle cx="12" cy="12" r="3" fill="none" stroke="currentColor" stroke-linecap="square" stroke-miterlimit="10" stroke-width="2"></circle><path d="m22,13.25v-2.5l-2.318-.966c-.167-.581-.395-1.135-.682-1.654l.954-2.318-1.768-1.768-2.318.954c-.518-.287-1.073-.515-1.654-.682l-.966-2.318h-2.5l-.966,2.318c-.581.167-1.135.395-1.654.682l-2.318-.954-1.768,1.768.954,2.318c-.287.518-.515,1.073-.682,1.654l-2.318.966v2.5l2.318.966c.167.581.395,1.135.682,1.654l-.954,2.318,1.768,1.768,2.318-.954c.518.287,1.073.515,1.654.682l.966,2.318h2.5l.966-2.318c.581-.167,1.135-.395,1.654-.682l2.318.954,1.768-1.768-.954-2.318c.287-.518.515-1.073.682-1.654l2.318-.966Z" fill="none" stroke="currentColor" stroke-linecap="square" stroke-miterlimit="10" stroke-width="2"></path></g></svg>{% endif %}
|
{% if user.is_authenticated %}<div tabindex="0" role="button" class="avatar"><div class="max-w-6 rounded-full">{{ user.email|gravatar_no_hover:40 }}</div></div>{% else %}<svg class="size-[1.2em]" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g fill="currentColor" stroke-linejoin="miter" stroke-linecap="butt"><circle cx="12" cy="12" r="3" fill="none" stroke="currentColor" stroke-linecap="square" stroke-miterlimit="10" stroke-width="2"></circle><path d="m22,13.25v-2.5l-2.318-.966c-.167-.581-.395-1.135-.682-1.654l.954-2.318-1.768-1.768-2.318.954c-.518-.287-1.073-.515-1.654-.682l-.966-2.318h-2.5l-.966,2.318c-.581.167-1.135.395-1.654.682l-2.318-.954-1.768,1.768.954,2.318c-.287.518-.515,1.073-.682,1.654l-2.318.966v2.5l2.318.966c.167.581.395,1.135.682,1.654l-.954,2.318,1.768,1.768,2.318-.954c.518.287,1.073.515,1.654.682l.966,2.318h2.5l.966-2.318c.581-.167,1.135-.395,1.654-.682l2.318.954,1.768-1.768-.954-2.318c.287-.518.515-1.073.682-1.654l2.318-.966Z" fill="none" stroke="currentColor" stroke-linecap="square" stroke-miterlimit="10" stroke-width="2"></path></g></svg>{% endif %}
|
||||||
<span class="dock-label">Dashboard</span>
|
<span class="dock-label">Dashboard</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<ul tabindex="0" class="dropdown-content menu bg-base-100 rounded-box z-1 w-26 p-2 shadow-sm">
|
<ul tabindex="0" class="dropdown-content menu bg-base-100 rounded-box z-1 max-w-26 p-2 shadow-sm">
|
||||||
<li>
|
<li>
|
||||||
<a href="#" @click.prevent="order = 'newest'; page = 1; loadOffers()">
|
<a href="#" @click.prevent="order = 'newest'; page = 1; loadOffers()">
|
||||||
Newest
|
Newest
|
||||||
|
|
@ -81,7 +81,7 @@
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<ul tabindex="0" class="dropdown-content menu bg-base-100 rounded-box z-1 w-26 p-2 shadow-sm">
|
<ul tabindex="0" class="dropdown-content menu bg-base-100 rounded-box z-1 max-w-26 p-2 shadow-sm">
|
||||||
<li>
|
<li>
|
||||||
<a href="#" @click.prevent="order = 'newest'; page = 1; loadOffers()">
|
<a href="#" @click.prevent="order = 'newest'; page = 1; loadOffers()">
|
||||||
Newest
|
Newest
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
||||||
</svg>
|
</svg>
|
||||||
</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 max-w-52">
|
||||||
<li><a href="#" @click.prevent="order = 'absolute'; page = 1; loadCards()">Cardset</a></li>
|
<li><a href="#" @click.prevent="order = 'absolute'; page = 1; loadCards()">Cardset</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>
|
||||||
|
|
@ -46,7 +46,7 @@
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
||||||
</svg>
|
</svg>
|
||||||
</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 max-w-52">
|
||||||
<li><a href="#" @click.prevent="groupBy = 'none'; page = 1; loadCards()">None</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>
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
{% block title %}Edit Friend Code{% endblock %}
|
{% block title %}Edit Friend Code{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container mx-auto max-w-3xl mt-6">
|
|
||||||
<h1 class="text-3xl font-bold mb-4">Edit Friend Code</h1>
|
<h1 class="text-3xl font-bold mb-4">Edit Friend Code</h1>
|
||||||
|
|
||||||
<!-- Display the friend code as plain text -->
|
<!-- Display the friend code as plain text -->
|
||||||
|
|
@ -46,5 +45,4 @@
|
||||||
<button type="submit" form="edit-friendcode-form" class="btn btn-primary">Update</button>
|
<button type="submit" form="edit-friendcode-form" class="btn btn-primary">Update</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
@ -4,11 +4,10 @@
|
||||||
{% block title %}{{title}}{% endblock title %}
|
{% block title %}{{title}}{% endblock title %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container mx-auto mt-6">
|
|
||||||
<h2 class="text-2xl font-bold">Trade Offer Details</h2>
|
<h2 class="text-2xl font-bold">Trade Offer Details</h2>
|
||||||
<div class="card card-border bg-base-100 shadow-lg mx-auto p-6 m-4 text-sm">
|
<div class="card card-border bg-base-100 shadow-lg mx-auto px-2 py-4 m-2 text-sm">
|
||||||
{% if acceptance_form %}
|
{% if acceptance_form %}
|
||||||
<div class="col-span-2 w-3/4 mx-auto card card-border bg-base-200 shadow-lg p-6 mb-8">
|
<div class="col-span-2 max-w-3/4 mx-auto card card-border bg-base-200 shadow-lg p-6 mb-8">
|
||||||
<h3 class="text-xl font-semibold mb-2">Accept A Trade</h3>
|
<h3 class="text-xl font-semibold mb-2">Accept A Trade</h3>
|
||||||
<form method="post" action="{% url 'trade_acceptance_create' offer_pk=object.pk %}">
|
<form method="post" action="{% url 'trade_acceptance_create' offer_pk=object.pk %}">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
|
@ -53,15 +52,15 @@
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="grid grid-cols-2 justify-items-end items-baseline gap-4">
|
<div class="grid grid-cols-2 justify-items-end items-baseline gap-4">
|
||||||
<div class="font-semibold text-right text-lg">Cards They Have:
|
<div class="font-semibold text-right xs:text-lg">Cards They Have:
|
||||||
<div class="flex flex-wrap flex-col gap-2 text-left mt-4">
|
<div class="flex flex-wrap flex-col gap-2 text-left mt-4 items-center">
|
||||||
{% for card in object.have_cards_available %}
|
{% for card in object.have_cards_available %}
|
||||||
{% card_badge card.card card.qty_available %}
|
{% card_badge card.card card.qty_available %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="font-semibold justify-self-start text-lg">Cards They Want:
|
<div class="font-semibold justify-self-start xs:text-lg">Cards They Want:
|
||||||
<div class="flex flex-wrap flex-col gap-2 mt-4">
|
<div class="flex flex-wrap flex-col gap-2 mt-4 items-center">
|
||||||
{% for card in object.want_cards_available %}
|
{% for card in object.want_cards_available %}
|
||||||
{% card_badge card.card card.qty_available %}
|
{% card_badge card.card card.qty_available %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
@ -80,18 +79,17 @@
|
||||||
<div class="justify-self-start">{{ object.updated_at }}</div>
|
<div class="justify-self-start">{{ object.updated_at }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
<div class="font-semibold text-center text-lg mb-2">Trade History:</div>
|
<div class="font-semibold text-center sm:text-lg mb-2">Trade History:</div>
|
||||||
<div class="flex flex-row flex-wrap justify-start items-baseline w-90 lg:w-181 mx-auto">
|
<div class="flex flex-row flex-wrap justify-start items-baseline gap-y-2 w-65 xs:w-88 sm:w-90 lg:w-181 mx-auto">
|
||||||
{% for trade in object.acceptances.all %}
|
{% for trade in object.acceptances.all %}
|
||||||
<div class="p-2 grid grid-cols-2 justify-items-center items-baseline gap-1 w-90">
|
<div class="grid grid-cols-2 justify-items-between items-baseline w-65 xs:w-88 sm:w-90 lg:w-181">
|
||||||
<div class="">{% card_badge trade.offered_card %}</div>
|
<div class="">{% card_badge trade.offered_card %}</div>
|
||||||
<div class="">{% card_badge trade.requested_card %}</div>
|
<div class="">{% card_badge trade.requested_card %}</div>
|
||||||
<div class="col-span-2 text-center">{{ trade.accepted_by.user.username }} • <a class="link link-hover" href="{% url 'trade_acceptance_update' pk=trade.pk %}">#{{ trade.hash }}</a> • {{ trade.get_state_display }}</div>
|
<div class="col-span-2 text-center mt-1">{{ trade.accepted_by.user.username }} • <a class="link link-hover" href="{% url 'trade_acceptance_update' pk=trade.pk %}">#{{ trade.hash }}</a> • {{ trade.get_state_display }}</div>
|
||||||
</div>
|
</div>
|
||||||
{% empty %}
|
{% empty %}
|
||||||
<div class="text-center justify-center w-full text-center">No trades yet.</div>
|
<div class="text-center justify-center w-full text-center">No trades yet.</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
@ -10,10 +10,10 @@
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<div>
|
<div>
|
||||||
{% card_multiselect "have_cards" "I Have:" "Select zero or more cards..." cards have_cards %}
|
{% card_multiselect "have_cards" "I Have:" "Select some cards..." cards have_cards %}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{% card_multiselect "want_cards" "I Want:" "Select zero or more cards..." cards want_cards %}
|
{% card_multiselect "want_cards" "I Want:" "Select some cards..." cards want_cards %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col md:flex-row gap-4">
|
<div class="flex flex-col md:flex-row gap-4">
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
<a href="{{ url }}" @click.stop>
|
<a href="{{ url }}" @click.stop>
|
||||||
<div class="relative block">
|
<div class="relative block">
|
||||||
{% if not expanded %}
|
{% if not expanded %}
|
||||||
<div class="flex flex-row items-center h-[32px] p-1.5 w-40 text-white shadow-lg" style="{{ style }}">
|
<div class="flex flex-row items-center h-[32px] p-1.5 w-30 sm:w-40 text-white shadow-lg" style="{{ style }}">
|
||||||
<div class="grow"><div class="truncate text-ellipsis font-semibold leading-tight text-sm marquee-calc max-w-24">{{ name }}</div></div>
|
<div class="grow"><div class="truncate text-ellipsis font-semibold leading-tight text-sm marquee-calc w-4/5 sm:w-24">{{ name }}</div></div>
|
||||||
<div class="grow-0 shrink-0 text-right truncate font-semibold leading-tight text-sm">{{ cardset }}</div>
|
<div class="grow-0 shrink-0 text-right truncate font-semibold leading-tight text-sm">{{ cardset }}</div>
|
||||||
{% if quantity != None %}
|
{% if quantity != None %}
|
||||||
<div class="grow-0 shrink-0 relative w-fit ps-1">
|
<div class="grow-0 shrink-0 relative w-fit ps-1">
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="grid grid-rows-2 grid-cols-4 h-[52px] p-1.5 w-40 text-white shadow-lg" style="{{ style }}">
|
<div class="grid grid-rows-2 grid-cols-4 h-[52px] p-1.5 w-30 sm:w-40 text-white shadow-lg" style="{{ style }}">
|
||||||
<div class="row-start-1 col-start-1 {% if quantity != None %}col-span-3{% else %}col-span-4{% endif %} self-start leading-tight truncate text-ellipsis"><span class="font-semibold text-sm marquee-calc">{{ name }}</span></div>
|
<div class="row-start-1 col-start-1 {% if quantity != None %}col-span-3{% else %}col-span-4{% endif %} self-start leading-tight truncate text-ellipsis"><span class="font-semibold text-sm marquee-calc">{{ name }}</span></div>
|
||||||
{% if quantity != None %}
|
{% if quantity != None %}
|
||||||
<div class="row-start-1 col-start-4 col-span-1 self-start ms-auto leading-tight relative w-fit ps-1">
|
<div class="row-start-1 col-start-4 col-span-1 self-start ms-auto leading-tight relative w-fit ps-1">
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
{% load gravatar card_badge %}
|
{% load gravatar card_badge %}
|
||||||
|
|
||||||
<div class="card card-border bg-base-100 shadow-lg w-90 mx-auto">
|
<div class="card card-border bg-base-100 shadow-lg max-w-90 mx-auto">
|
||||||
<div class="cursor-pointer" @click.stop="window.location.href='{% url 'trade_acceptance_update' pk=acceptance.pk %}'">
|
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
|
<a href="{% url 'trade_acceptance_update' pk=acceptance.pk %}">
|
||||||
<div class="my-4 mx-4">
|
<div class="my-4 mx-4">
|
||||||
<div class="flex justify-start items-center">
|
<div class="flex justify-start items-center">
|
||||||
<!-- Left: Initiator's avatar and "Has" -->
|
<!-- Left: Initiator's avatar and "Has" -->
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<div class="avatar me-2 tooltip tooltip-top cursor-default" @click.stop.prevent data-tip="{{ acceptance.trade_offer.initiated_by.user.username }} | {{ acceptance.trade_offer.initiated_by.user.reputation_score }} rep">
|
<div class="avatar me-2 tooltip tooltip-top cursor-default" @click.stop.prevent data-tip="{{ acceptance.trade_offer.initiated_by.user.username }} | {{ acceptance.trade_offer.initiated_by.user.reputation_score }} rep">
|
||||||
<div class="w-10 rounded-full">
|
<div class="max-w-10 rounded-full">
|
||||||
{{ acceptance.trade_offer.initiated_by.user.email|gravatar:40 }}
|
{{ acceptance.trade_offer.initiated_by.user.email|gravatar:40 }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</a>
|
||||||
<!-- Main Card Row: Single row with the acceptance's cards -->
|
<!-- Main Card Row: Single row with the acceptance's cards -->
|
||||||
<div class="px-2 pb-0">
|
<div class="px-2 pb-0">
|
||||||
<div class="grid grid-cols-2 items-center">
|
<div class="grid grid-cols-2 items-center">
|
||||||
|
|
@ -33,6 +34,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<a href="{% url 'trade_acceptance_update' pk=acceptance.pk %}">
|
||||||
<div class="my-4 mx-4">
|
<div class="my-4 mx-4">
|
||||||
<div class="flex justify-end items-center">
|
<div class="flex justify-end items-center">
|
||||||
<!-- Right: "Wants" with the acceptor's avatar -->
|
<!-- Right: "Wants" with the acceptor's avatar -->
|
||||||
|
|
@ -45,12 +47,12 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="avatar ms-2 tooltip tooltip-bottom cursor-default" @click.stop.prevent data-tip="{{ acceptance.accepted_by.user.username}} | {{ acceptance.accepted_by.user.reputation_score }} rep">
|
<div class="avatar ms-2 tooltip tooltip-bottom cursor-default" @click.stop.prevent data-tip="{{ acceptance.accepted_by.user.username}} | {{ acceptance.accepted_by.user.reputation_score }} rep">
|
||||||
<div class="w-10 rounded-full">
|
<div class="max-w-10 rounded-full">
|
||||||
{{ acceptance.accepted_by.user.email|gravatar:40 }}
|
{{ acceptance.accepted_by.user.email|gravatar:40 }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
{% cache 60 trade_offer offer_pk %}
|
{% cache 60 trade_offer offer_pk %}
|
||||||
<div x-data="{ flipped: {{flipped|lower}}, offerExpanded: {{flipped|yesno:'false,true'}}, acceptanceExpanded: {{flipped|lower}} }" x-ref="tradeOffer" class="transition-all duration-500 trade-offer-card">
|
<div x-data="{ flipped: {{flipped|lower}}, offerExpanded: {{flipped|yesno:'false,true'}}, acceptanceExpanded: {{flipped|lower}} }" x-ref="tradeOffer" class="transition-all duration-500 trade-offer-card">
|
||||||
<div class="flip-container">
|
<div class="flip-container">
|
||||||
<div class="flip-inner grid grid-cols-1 grid-rows-1 card bg-base-100 card-border shadow-lg w-90 transform transition-transform duration-500 ease-in-out{%if flipped %} rotate-y-180{% endif %}"
|
<div class="flip-inner grid grid-cols-1 grid-rows-1 card bg-base-100 card-border shadow-lg max-w-90 transform transition-transform duration-500 ease-in-out{%if flipped %} rotate-y-180{% endif %}"
|
||||||
:class="{'rotate-y-180': flipped}">
|
:class="{'rotate-y-180': flipped}">
|
||||||
<div class="flip-face front rotate-y-0 col-start-1 row-start-1 grid grid-cols-1 auto-rows-min gap-2 content-between">
|
<div class="flip-face front rotate-y-0 col-start-1 row-start-1 grid grid-cols-1 auto-rows-min gap-2 content-between">
|
||||||
<div class="flip-face-header self-start">
|
<div class="flip-face-header self-start">
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="absolute inset-x-0 top-1/2 transform -translate-y-1/2 flex justify-center">
|
<div class="absolute inset-x-0 top-1/2 transform -translate-y-1/2 flex justify-center">
|
||||||
<div class="avatar tooltip tooltip-top cursor-default" @click.stop.prevent data-tip="{{ initiated_by_username }} | {{ initiated_reputation }} rep">
|
<div class="avatar tooltip tooltip-top cursor-default" @click.stop.prevent data-tip="{{ initiated_by_username }} | {{ initiated_reputation }} rep">
|
||||||
<div class="w-10 rounded-full">
|
<div class="max-w-10 rounded-full">
|
||||||
{{ initiated_by_email|gravatar:40 }}
|
{{ initiated_by_email|gravatar:40 }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -79,7 +79,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="absolute inset-x-0 top-1/2 transform -translate-y-1/2 flex justify-center">
|
<div class="absolute inset-x-0 top-1/2 transform -translate-y-1/2 flex justify-center">
|
||||||
<div class="avatar tooltip tooltip-top cursor-default" @click.stop.prevent data-tip="{{ initiated_by_username }} | {{ initiated_reputation }} rep">
|
<div class="avatar tooltip tooltip-top cursor-default" @click.stop.prevent data-tip="{{ initiated_by_username }} | {{ initiated_reputation }} rep">
|
||||||
<div class="w-10 rounded-full">
|
<div class="max-w-10 rounded-full">
|
||||||
{{ initiated_by_email|gravatar:40 }}
|
{{ initiated_by_email|gravatar:40 }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -88,16 +88,16 @@
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="flip-face-body self-start">
|
<div class="flip-face-body self-start">
|
||||||
<div class="px-2 space-y-3 text-xs">
|
<div class="text-xs">
|
||||||
<div x-show="acceptanceExpanded" x-collapse.duration.500ms class="flex flex-row flex-wrap justify-start items-baseline w-90 lg:w-181 mx-auto">
|
<div x-show="acceptanceExpanded" x-collapse.duration.500ms class="flex flex-row flex-wrap justify-center items-baseline mx-auto">
|
||||||
{% for trade in acceptances %}
|
{% for trade in acceptances %}
|
||||||
<div class="p-2 grid grid-cols-2 justify-items-center items-baseline gap-1">
|
<div class="mb-2 grid grid-cols-2 justify-items-center items-baseline gap-x-3 gap-y-1">
|
||||||
<div class="">{% card_badge trade.offered_card %}</div>
|
<div class="">{% card_badge trade.offered_card %}</div>
|
||||||
<div class="">{% card_badge trade.requested_card %}</div>
|
<div class="">{% card_badge trade.requested_card %}</div>
|
||||||
<div class="col-span-2 text-center">{{ trade.accepted_by.user.username }} • <a class="link link-hover" href="{% url 'trade_acceptance_update' pk=trade.pk %}">#{{ trade.hash }}</a> • {{ trade.get_state_display }}</div>
|
<div class="col-span-2 text-center tooltip tooltip-bottom" data-tip="{{ trade.accepted_by.user.username }} | {{ trade.accepted_by.user.reputation_score }} rep">{{ trade.accepted_by.user.username }} • <a class="link link-hover" href="{% url 'trade_acceptance_update' pk=trade.pk %}">#{{ trade.hash }}</a> • {{ trade.get_state_display }}</div>
|
||||||
</div>
|
</div>
|
||||||
{% empty %}
|
{% empty %}
|
||||||
<div class="text-center justify-center w-full text-center">No trades yet.</div>
|
<div class="w-full text-center">No trades yet.</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,51 +1,63 @@
|
||||||
{% load gravatar card_badge tailwind_tags %}<!DOCTYPE html>
|
{% load gravatar card_badge tailwind_tags %}<!DOCTYPE html>
|
||||||
<html style="background-color: transparent !important;">
|
<html style="background-color: transparent !important">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<style>
|
<style>
|
||||||
{% include 'static/css/dist/styles.css' %}
|
{% include 'static/css/dist/styles.css' %}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body style="background-color: transparent !important;">
|
<body style="background-color: transparent !important">
|
||||||
<div class="trade-offer-card-screenshot p-4 h-full w-auto flex justify-center" style="background-color: transparent !important;">
|
<div
|
||||||
|
class="trade-offer-card-screenshot p-4 h-full w-auto flex justify-center"
|
||||||
|
style="background-color: transparent !important"
|
||||||
|
>
|
||||||
<div class="transition-all duration-500 trade-offer-card my-auto">
|
<div class="transition-all duration-500 trade-offer-card my-auto">
|
||||||
|
|
||||||
<!-- Flip container providing perspective -->
|
<!-- Flip container providing perspective -->
|
||||||
<div class="flip-container">
|
<div class="flip-container">
|
||||||
<div class="flip-inner grid grid-cols-1 grid-rows-1 card bg-base-100 card-border shadow-lg {% if expanded %}w-180{% else %}w-96{% endif %} transform transition-transform duration-700 ease-in-out">
|
<div
|
||||||
|
class="flip-inner grid grid-cols-1 grid-rows-1 card bg-base-100 card-border shadow-lg {% if expanded %}w-180{% else %}w-96{% endif %} transform transition-transform duration-700 ease-in-out"
|
||||||
|
>
|
||||||
<!-- Front Face: Trade Offer -->
|
<!-- Front Face: Trade Offer -->
|
||||||
<div class="flip-face front mb-2 col-start-1 row-start-1 grid grid-cols-1 auto-rows-min gap-2 content-between">
|
<div
|
||||||
|
class="flip-face front mb-2 col-start-1 row-start-1 grid grid-cols-1 auto-rows-min gap-2 content-between"
|
||||||
|
>
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<div class="flip-face-header self-start">
|
<div class="flip-face-header self-start">
|
||||||
<a href="{% url 'trade_offer_detail' pk=offer_pk %}" class="no-underline block">
|
|
||||||
<div class="mt-6 mb-4 mx-2 sm:mx-4">
|
<div class="mt-6 mb-4 mx-2 sm:mx-4">
|
||||||
<!-- Two-column grid for the labels -->
|
<!-- Two-column grid for the labels -->
|
||||||
<div class="flex flex-row justify-around w-full relative">
|
<div class="flex flex-row justify-around w-full relative">
|
||||||
<div class="text-sm font-semibold text-center ms-3">Has</div>
|
<div class="text-sm font-semibold text-center ms-2">
|
||||||
<div class="absolute inset-x-0 top-1/2 transform -translate-y-1/2 flex justify-center">
|
Has
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="absolute inset-x-0 top-1/2 transform -translate-y-1/2 flex justify-center"
|
||||||
|
>
|
||||||
<div class="avatar">
|
<div class="avatar">
|
||||||
<div class="w-10 rounded-full">
|
<div class="w-10 rounded-full">
|
||||||
{{ initiated_by_email|gravatar:40 }}
|
{{ initiated_by_email|gravatar:40 }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm font-semibold text-center {% if expanded %}ms-8{% else %}me-2{% endif %}">Wants</div>
|
<div
|
||||||
|
class="text-sm font-semibold text-center {% if expanded %}ms-5{% endif %}"
|
||||||
|
>
|
||||||
|
Wants
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
<!-- 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">
|
|
||||||
<div class="px-4 main-badges pb-0">
|
<div class="px-4 main-badges pb-0">
|
||||||
{% if expanded %}
|
{% if expanded %}
|
||||||
<div class="flex flex-row gap-1 justify-around">
|
<div class="flex flex-row justify-around">
|
||||||
<!-- Has Side (inner grid of 2 columns) -->
|
<!-- Has Side (inner grid of 2 columns) -->
|
||||||
<div class="grid grid-cols-2 content-start">
|
<div class="grid grid-cols-2 content-start gap-1">
|
||||||
{% for card in have_cards_available %}
|
{% for card in have_cards_available %} {% card_badge card.card card.quantity %} {% empty %}
|
||||||
{% card_badge card.card card.quantity %}
|
<div class="text-xs text-center mb-2 ms-3 col-span-2">
|
||||||
|
None left.
|
||||||
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
<!-- Vertical Divider -->
|
<!-- Vertical Divider -->
|
||||||
|
|
@ -53,9 +65,11 @@
|
||||||
<div class="w-px bg-gray-300 h-full"></div>
|
<div class="w-px bg-gray-300 h-full"></div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Wants Side (inner grid of 2 columns) -->
|
<!-- Wants Side (inner grid of 2 columns) -->
|
||||||
<div class="grid grid-cols-2 content-start">
|
<div class="grid grid-cols-2 content-start gap-1">
|
||||||
{% for card in want_cards_available %}
|
{% for card in want_cards_available %} {% card_badge card.card card.quantity %} {% empty %}
|
||||||
{% card_badge card.card card.quantity %}
|
<div class="text-xs text-center mb-2 ms-3 col-span-2">
|
||||||
|
None left.
|
||||||
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -63,31 +77,36 @@
|
||||||
<!-- Normal mode: just use an outer grid with 2 columns -->
|
<!-- Normal mode: just use an outer grid with 2 columns -->
|
||||||
<div class="flex flex-row gap-1 justify-around">
|
<div class="flex flex-row gap-1 justify-around">
|
||||||
<!-- Has Side -->
|
<!-- Has Side -->
|
||||||
<div class="flex flex-col content-start">
|
<div class="flex flex-col content-start gap-1">
|
||||||
{% for card in have_cards_available %}
|
{% for card in have_cards_available %} {% card_badge card.card card.quantity %} {% empty %}
|
||||||
{% card_badge card.card card.quantity %}
|
<div class="text-xs text-center mb-2 ms-3">
|
||||||
{% empty %}
|
None left.
|
||||||
<div class="text-xs text-center mb-2 ms-3">None left.</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
<!-- Wants Side -->
|
<!-- Wants Side -->
|
||||||
<div class="flex flex-col content-start">
|
<div class="flex flex-col content-start gap-1">
|
||||||
{% for card in want_cards_available %}
|
{% for card in want_cards_available %} {% card_badge card.card card.quantity %} {% empty %}
|
||||||
{% card_badge card.card card.quantity %}
|
<div
|
||||||
{% empty %}
|
class="text-xs text-center mb-2{% if expanded %} ms-8{% else %} me-4{% endif %}"
|
||||||
<div class="text-xs text-center mb-2{% if expanded %} ms-8{% else %} me-4{% endif %}">None left.</div>
|
>
|
||||||
|
None left.
|
||||||
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flip-face-footer self-end">
|
<div class="flip-face-footer self-end">
|
||||||
<div class="flex flex-col gap-2 text-center">
|
<div class="flex flex-col gap-2 text-center">
|
||||||
<div class="text-sm font-semibold text-base-content">
|
<div class="text-sm font-semibold text-base-content">
|
||||||
{{ in_game_name }} {% if show_friend_code %}<span class="text-base-content/50">•</span> {{ friend_code }}{% endif %}
|
{% if show_friend_code %}{{ in_game_name }} <span
|
||||||
|
class="text-base-content/50"
|
||||||
|
>•</span
|
||||||
|
>
|
||||||
|
{{ friend_code }}{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -96,5 +115,5 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -55,15 +55,15 @@ class TradeAcceptanceCreateForm(forms.ModelForm):
|
||||||
elif default_friend_code and friend_codes.filter(pk=default_friend_code.pk).exists():
|
elif default_friend_code and friend_codes.filter(pk=default_friend_code.pk).exists():
|
||||||
self.initial["accepted_by"] = default_friend_code.pk
|
self.initial["accepted_by"] = default_friend_code.pk
|
||||||
|
|
||||||
# Update available requested_card choices from the TradeOffer's "have" side.
|
# Fix: Convert available 'have' cards (from through model) to Card objects.
|
||||||
active_states = [
|
self.fields["requested_card"].queryset = Card.objects.filter(
|
||||||
TradeAcceptance.AcceptanceState.ACCEPTED,
|
pk__in=trade_offer.have_cards_available_qs.values_list("card_id", flat=True)
|
||||||
TradeAcceptance.AcceptanceState.SENT,
|
)
|
||||||
TradeAcceptance.AcceptanceState.RECEIVED,
|
|
||||||
]
|
|
||||||
self.fields["requested_card"].queryset = trade_offer.have_cards_available_qs
|
|
||||||
|
|
||||||
self.fields["offered_card"].queryset = trade_offer.want_cards_available_qs
|
# Similarly for offered_card.
|
||||||
|
self.fields["offered_card"].queryset = Card.objects.filter(
|
||||||
|
pk__in=trade_offer.want_cards_available_qs.values_list("card_id", flat=True)
|
||||||
|
)
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 5.1.2 on 2025-04-14 04:07
|
# Generated by Django 5.1.2 on 2025-04-14 20:58
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,8 @@ class TradeOffer(models.Model):
|
||||||
if len(rarity_levels) > 1:
|
if len(rarity_levels) > 1:
|
||||||
raise ValidationError("All cards in a trade offer must have the same rarity.")
|
raise ValidationError("All cards in a trade offer must have the same rarity.")
|
||||||
first_card = cards[0]
|
first_card = cards[0]
|
||||||
|
if first_card.rarity_level > 5:
|
||||||
|
raise ValidationError("Cannot trade cards above one-star rarity.")
|
||||||
if self.rarity_level != first_card.rarity_level or self.rarity_icon != first_card.rarity_icon:
|
if self.rarity_level != first_card.rarity_level or self.rarity_icon != first_card.rarity_icon:
|
||||||
self.rarity_level = first_card.rarity_level
|
self.rarity_level = first_card.rarity_level
|
||||||
self.rarity_icon = first_card.rarity_icon
|
self.rarity_icon = first_card.rarity_icon
|
||||||
|
|
@ -140,11 +142,11 @@ class TradeOfferHaveCard(models.Model):
|
||||||
return self.quantity - self.qty_accepted
|
return self.quantity - self.qty_accepted
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.card.name} x{self.quantity} (Accepted: {self.qty_accepted})"
|
return f"#{self.card.cardnum} {self.card.cardset} {self.card.rarity_icon} {self.card.name}"
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
super().save(*args, **kwargs)
|
|
||||||
self.trade_offer.update_rarity_fields()
|
self.trade_offer.update_rarity_fields()
|
||||||
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
def delete(self, *args, **kwargs):
|
def delete(self, *args, **kwargs):
|
||||||
trade_offer = self.trade_offer
|
trade_offer = self.trade_offer
|
||||||
|
|
@ -174,7 +176,7 @@ class TradeOfferWantCard(models.Model):
|
||||||
return self.quantity - self.qty_accepted
|
return self.quantity - self.qty_accepted
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.card.name} x{self.quantity} (Accepted: {self.qty_accepted})"
|
return f"#{self.card.cardnum} {self.card.cardset} {self.card.rarity_icon} {self.card.name}"
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ def adjust_qty_for_trade_offer(trade_offer, card, side, delta):
|
||||||
def update_trade_offer_closed_status(trade_offer):
|
def update_trade_offer_closed_status(trade_offer):
|
||||||
"""
|
"""
|
||||||
Check if both sides of the trade offer meet the quantity requirement.
|
Check if both sides of the trade offer meet the quantity requirement.
|
||||||
Mark the trade_offer as closed if all cards have qty_accepted
|
Mark the trade_offer as closed if all cards on one side have qty_accepted
|
||||||
greater than or equal to quantity; otherwise, mark it as open.
|
greater than or equal to quantity; otherwise, mark it as open.
|
||||||
"""
|
"""
|
||||||
have_complete = not TradeOfferHaveCard.objects.filter(
|
have_complete = not TradeOfferHaveCard.objects.filter(
|
||||||
|
|
@ -107,6 +107,8 @@ def trade_acceptance_email_notification(sender, instance, created, **kwargs):
|
||||||
# return
|
# return
|
||||||
|
|
||||||
acting_user = instance._actioning_user
|
acting_user = instance._actioning_user
|
||||||
|
del instance._actioning_user
|
||||||
|
|
||||||
state = instance.state
|
state = instance.state
|
||||||
|
|
||||||
if state == TradeAcceptance.AcceptanceState.ACCEPTED:
|
if state == TradeAcceptance.AcceptanceState.ACCEPTED:
|
||||||
|
|
@ -169,9 +171,6 @@ def trade_acceptance_email_notification(sender, instance, created, **kwargs):
|
||||||
[recipient_user.email],
|
[recipient_user.email],
|
||||||
)
|
)
|
||||||
|
|
||||||
# Clean up the temporary attribute.
|
|
||||||
del instance._actioning_user
|
|
||||||
|
|
||||||
@receiver(post_save, sender=TradeAcceptance)
|
@receiver(post_save, sender=TradeAcceptance)
|
||||||
def trade_acceptance_reputation_update(sender, instance, created, **kwargs):
|
def trade_acceptance_reputation_update(sender, instance, created, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ class TradeOfferCreateView(LoginRequiredMixin, CreateView):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
from cards.models import Card
|
from cards.models import Card
|
||||||
# Ensure available_cards is a proper QuerySet
|
# Ensure available_cards is a proper QuerySet
|
||||||
context["cards"] = Card.objects.all().order_by("name", "rarity_level")
|
context["cards"] = Card.objects.filter(rarity_level__lte=5).order_by("name", "rarity_level")
|
||||||
friend_codes = self.request.user.friend_codes.all()
|
friend_codes = self.request.user.friend_codes.all()
|
||||||
if "initiated_by" in self.request.GET:
|
if "initiated_by" in self.request.GET:
|
||||||
try:
|
try:
|
||||||
|
|
@ -245,8 +245,8 @@ class TradeOfferSearchView(ListView):
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
from cards.models import Card
|
from cards.models import Card
|
||||||
# Populate available_cards to re-populate the multiselects.
|
# Populate available_cards to re-populate the multiselects. Exclude cards with rarity level > 5.
|
||||||
context["cards"] = Card.objects.all().order_by("name")
|
context["cards"] = Card.objects.filter(rarity_level__lte=5).order_by("name", "rarity_level")
|
||||||
if self.request.method == "POST":
|
if self.request.method == "POST":
|
||||||
context["have_cards"] = self.request.POST.getlist("have_cards")
|
context["have_cards"] = self.request.POST.getlist("have_cards")
|
||||||
context["want_cards"] = self.request.POST.getlist("want_cards")
|
context["want_cards"] = self.request.POST.getlist("want_cards")
|
||||||
|
|
@ -515,7 +515,7 @@ class TradeOfferPNGView(View):
|
||||||
return HttpResponse(trade_offer.image.read(), content_type="image/png")
|
return HttpResponse(trade_offer.image.read(), content_type="image/png")
|
||||||
|
|
||||||
tag_context = render_trade_offer_png(
|
tag_context = render_trade_offer_png(
|
||||||
{'request': request}, trade_offer, show_friend_code=True
|
{'request': request}, trade_offer, show_friend_code=trade_offer.initiated_by.user.show_friend_code_on_link_previews
|
||||||
)
|
)
|
||||||
image_width = tag_context.get('image_width')
|
image_width = tag_context.get('image_width')
|
||||||
image_height = tag_context.get('image_height')
|
image_height = tag_context.get('image_height')
|
||||||
|
|
@ -547,7 +547,7 @@ class TradeOfferPNGView(View):
|
||||||
page.on("console", lambda msg: print(f"Console {msg.type}: {msg.text}"))
|
page.on("console", lambda msg: print(f"Console {msg.type}: {msg.text}"))
|
||||||
page.on("pageerror", lambda err: print(f"Page error: {err}"))
|
page.on("pageerror", lambda err: print(f"Page error: {err}"))
|
||||||
page.on("requestfailed", lambda req: print(f"Failed to load: {req.url} - {req.failure.error_text}"))
|
page.on("requestfailed", lambda req: print(f"Failed to load: {req.url} - {req.failure.error_text}"))
|
||||||
page.set_content(html, wait_until="domcontentloaded")
|
page.set_content(html, wait_until="networkidle")
|
||||||
element = page.wait_for_selector(".trade-offer-card-screenshot")
|
element = page.wait_for_selector(".trade-offer-card-screenshot")
|
||||||
screenshot_bytes = element.screenshot(type="png", omit_background=True)
|
screenshot_bytes = element.screenshot(type="png", omit_background=True)
|
||||||
browser.close()
|
browser.close()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue