Add in_game_name field to FriendCode model
This commit is contained in:
parent
4792906907
commit
bc181b12d9
19 changed files with 113 additions and 56 deletions
|
|
@ -2,6 +2,7 @@ from django import forms
|
||||||
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
|
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
|
||||||
from .models import CustomUser, FriendCode
|
from .models import CustomUser, FriendCode
|
||||||
from allauth.account.forms import SignupForm
|
from allauth.account.forms import SignupForm
|
||||||
|
from crispy_tailwind.tailwind import CSSContainer
|
||||||
|
|
||||||
class CustomUserChangeForm(UserChangeForm):
|
class CustomUserChangeForm(UserChangeForm):
|
||||||
|
|
||||||
|
|
@ -12,7 +13,7 @@ class CustomUserChangeForm(UserChangeForm):
|
||||||
class FriendCodeForm(forms.ModelForm):
|
class FriendCodeForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = FriendCode
|
model = FriendCode
|
||||||
fields = ["friend_code"]
|
fields = ["friend_code", "in_game_name"]
|
||||||
|
|
||||||
def clean_friend_code(self):
|
def clean_friend_code(self):
|
||||||
friend_code = self.cleaned_data.get("friend_code", "").strip()
|
friend_code = self.cleaned_data.get("friend_code", "").strip()
|
||||||
|
|
@ -30,12 +31,32 @@ class CustomUserCreationForm(SignupForm):
|
||||||
model = CustomUser
|
model = CustomUser
|
||||||
fields = ['email', 'username', 'friend_code']
|
fields = ['email', 'username', 'friend_code']
|
||||||
|
|
||||||
|
email = forms.EmailField(
|
||||||
|
required=True,
|
||||||
|
label="Email",
|
||||||
|
widget=forms.TextInput(attrs={'placeholder': 'Email', 'class':'dark:bg-base-100'})
|
||||||
|
)
|
||||||
|
|
||||||
|
username = forms.CharField(
|
||||||
|
max_length=24,
|
||||||
|
required=True,
|
||||||
|
label="Username",
|
||||||
|
widget=forms.TextInput(attrs={'placeholder': 'Username', 'class':'dark:bg-base-100'})
|
||||||
|
)
|
||||||
|
|
||||||
friend_code = forms.CharField(
|
friend_code = forms.CharField(
|
||||||
max_length=19,
|
max_length=19,
|
||||||
required=True,
|
required=True,
|
||||||
label="Friend Code",
|
label="Friend Code",
|
||||||
help_text="Enter your friend code in the format XXXX-XXXX-XXXX-XXXX.",
|
help_text="Enter your friend code in the format XXXX-XXXX-XXXX-XXXX.",
|
||||||
widget=forms.TextInput(attrs={'placeholder': 'XXXX-XXXX-XXXX-XXXX'})
|
widget=forms.TextInput(attrs={'placeholder': 'XXXX-XXXX-XXXX-XXXX', 'class':'dark:bg-base-100'})
|
||||||
|
)
|
||||||
|
in_game_name = forms.CharField(
|
||||||
|
max_length=16,
|
||||||
|
required=True,
|
||||||
|
label="In-Game Name",
|
||||||
|
help_text="Enter your in-game name.",
|
||||||
|
widget=forms.TextInput(attrs={'placeholder': 'In-Game Name', 'class':'dark:bg-base-100'})
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 5.1.2 on 2025-03-13 01:46
|
# Generated by Django 5.1.2 on 2025-03-14 05:35
|
||||||
|
|
||||||
import django.contrib.auth.models
|
import django.contrib.auth.models
|
||||||
import django.contrib.auth.validators
|
import django.contrib.auth.validators
|
||||||
|
|
@ -48,6 +48,7 @@ class Migration(migrations.Migration):
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('friend_code', models.CharField(max_length=19)),
|
('friend_code', models.CharField(max_length=19)),
|
||||||
|
('in_game_name', models.CharField(max_length=16)),
|
||||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||||
('updated_at', models.DateTimeField(auto_now=True)),
|
('updated_at', models.DateTimeField(auto_now=True)),
|
||||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='friend_codes', to=settings.AUTH_USER_MODEL)),
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='friend_codes', to=settings.AUTH_USER_MODEL)),
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ class CustomUser(AbstractUser):
|
||||||
|
|
||||||
class FriendCode(models.Model):
|
class FriendCode(models.Model):
|
||||||
friend_code = models.CharField(max_length=19)
|
friend_code = models.CharField(max_length=19)
|
||||||
|
in_game_name = models.CharField(max_length=16, null=False, blank=False)
|
||||||
user = models.ForeignKey(CustomUser, on_delete=models.PROTECT, related_name='friend_codes')
|
user = models.ForeignKey(CustomUser, on_delete=models.PROTECT, related_name='friend_codes')
|
||||||
created_at = models.DateTimeField(auto_now_add=True)
|
created_at = models.DateTimeField(auto_now_add=True)
|
||||||
updated_at = models.DateTimeField(auto_now=True)
|
updated_at = models.DateTimeField(auto_now=True)
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ class DeleteFriendCodeView(LoginRequiredMixin, DeleteView):
|
||||||
return redirect(self.success_url)
|
return redirect(self.success_url)
|
||||||
|
|
||||||
# Also check if this friend code is referenced by any trade offer.
|
# Also check if this friend code is referenced by any trade offer.
|
||||||
if self.object.initiated_by.exists() or self.object.accepted_by.exists():
|
if self.object.initiated_trade_offers.exists() or self.object.trade_acceptances.exists():
|
||||||
messages.error(
|
messages.error(
|
||||||
request,
|
request,
|
||||||
"Cannot remove this friend code because there are existing trade offers associated with it."
|
"Cannot remove this friend code because there are existing trade offers associated with it."
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 5.1.2 on 2025-03-13 01:46
|
# Generated by Django 5.1.2 on 2025-03-14 05:35
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,8 @@ class HomePageView(TemplateView):
|
||||||
"want_cards__decks",
|
"want_cards__decks",
|
||||||
"want_cards__rarity",
|
"want_cards__rarity",
|
||||||
"want_cards__cardset",
|
"want_cards__cardset",
|
||||||
"acceptances"
|
"acceptances",
|
||||||
|
|
||||||
)
|
)
|
||||||
.select_related("initiated_by__user")
|
.select_related("initiated_by__user")
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@
|
||||||
"pk": 1,
|
"pk": 1,
|
||||||
"fields": {
|
"fields": {
|
||||||
"friend_code": "9167-8051-9691-8032",
|
"friend_code": "9167-8051-9691-8032",
|
||||||
|
"in_game_name": "badblocks",
|
||||||
"user": 1,
|
"user": 1,
|
||||||
"created_at": "2025-03-13T04:21:05.166Z",
|
"created_at": "2025-03-13T04:21:05.166Z",
|
||||||
"updated_at": "2025-03-13T04:21:05.166Z"
|
"updated_at": "2025-03-13T04:21:05.166Z"
|
||||||
|
|
@ -52,6 +53,7 @@
|
||||||
"pk": 2,
|
"pk": 2,
|
||||||
"fields": {
|
"fields": {
|
||||||
"friend_code": "1234-2938-7848-7636",
|
"friend_code": "1234-2938-7848-7636",
|
||||||
|
"in_game_name": "backrolls",
|
||||||
"user": 2,
|
"user": 2,
|
||||||
"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"
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
{% if messages %}
|
{% if messages %}
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
{% for message in messages %}
|
{% for message in messages %}
|
||||||
<div class="alert alert-{{ message.tags }} bg-base-100 mb-4">
|
<div class="alert alert-{{ message.tags }} bg-base-100 mb-4 flex justify-between items-center">
|
||||||
{{ message }}
|
<span>{{ message }}</span>
|
||||||
|
<button class="btn btn-xs btn-circle" onclick="this.parentElement.remove();" aria-label="Dismiss">✕</button>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
{% trans "Friend Codes" %}
|
{% trans "Friend Codes" %}
|
||||||
</a>
|
</a>
|
||||||
<a href="{% url 'account_logout' %}" class="btn btn-warning">
|
<a href="{% url 'account_logout' %}" class="btn btn-warning">
|
||||||
{% trans "Logout" %}
|
{% trans "Sign Out" %}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
|
|
||||||
{% block head_title %}{% trans "Sign Up" %}{% endblock %}
|
{% block head_title %}{% trans "Sign Up" %}{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
@ -34,6 +35,11 @@
|
||||||
{{ form.friend_code }}
|
{{ form.friend_code }}
|
||||||
{{ form.friend_code.errors }}
|
{{ form.friend_code.errors }}
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="{{ form.in_game_name.id_for_label }}" class="block font-medium">{{ form.in_game_name.label }}</label>
|
||||||
|
{{ form.in_game_name }}
|
||||||
|
{{ form.in_game_name.errors }}
|
||||||
|
</div>
|
||||||
<button type="submit" class="btn btn-primary w-full">{% trans "Sign Up" %}</button>
|
<button type="submit" class="btn btn-primary w-full">{% trans "Sign Up" %}</button>
|
||||||
</form>
|
</form>
|
||||||
<div class="mt-4 text-center">
|
<div class="mt-4 text-center">
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<title>{% block title %}PᴋMɴ Trade Club{% endblock title %}</title>
|
<title>[PᴋMɴ Trade Club] {% block title %}{% endblock title %}</title>
|
||||||
<link rel="shortcut icon" href="{% static 'images/favicon.ico' %}">
|
<link rel="shortcut icon" href="{% static 'images/favicon.ico' %}">
|
||||||
<!-- Choices.js -->
|
<!-- Choices.js -->
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/choices.js@11.0.6/public/assets/styles/choices.min.css" />
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/choices.js@11.0.6/public/assets/styles/choices.min.css" />
|
||||||
|
|
@ -113,7 +113,7 @@
|
||||||
Friend Codes
|
Friend Codes
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="{% url 'account_logout' %}">Logout</a></li>
|
<li><a href="{% url 'account_logout' %}">Sign Out</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
{% load crispy_forms_tags %}
|
{% load crispy_forms_tags i18n %}
|
||||||
|
|
||||||
{% block title %}Add Friend Code{% endblock %}
|
{% block title %}Add Friend Code{% endblock %}
|
||||||
|
|
||||||
|
|
@ -8,8 +8,18 @@
|
||||||
<h1 class="text-3xl font-bold mb-4">Add Friend Code</h1>
|
<h1 class="text-3xl font-bold mb-4">Add Friend Code</h1>
|
||||||
<form method="post" class="space-y-4">
|
<form method="post" class="space-y-4">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form|crispy }}
|
{{ form.non_field_errors }}
|
||||||
<button type="submit" class="btn btn-primary w-full">Add Friend Code</button>
|
<div>
|
||||||
|
<label for="{{ form.friend_code.id_for_label }}" class="block font-medium">{{ form.friend_code.label }}</label>
|
||||||
|
{{ form.friend_code }}
|
||||||
|
{{ form.friend_code.errors }}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="{{ form.in_game_name.id_for_label }}" class="block font-medium">{{ form.in_game_name.label }}</label>
|
||||||
|
{{ form.in_game_name }}
|
||||||
|
{{ form.in_game_name.errors }}
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary w-full">{% trans "Add Friend Code" %}</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
|
|
@ -19,11 +29,11 @@
|
||||||
|
|
||||||
<!-- Include Cleave Zen from a CDN -->
|
<!-- Include Cleave Zen from a CDN -->
|
||||||
<script src="https://unpkg.com/cleave-zen@0.0.17/dist/cleave-zen.umd.js"></script>
|
<script src="https://unpkg.com/cleave-zen@0.0.17/dist/cleave-zen.umd.js"></script>
|
||||||
<script>
|
<script defer>
|
||||||
document.addEventListener('DOMContentLoaded', function(){
|
document.addEventListener('DOMContentLoaded', function(){
|
||||||
// Initialize Cleave Zen on the friend code input field.
|
// Initialize Cleave Zen on the friend code input field.
|
||||||
// Make sure that the input ID is correct (e.g., provided by Django's widget rendering).
|
// Make sure that the input ID is correct (e.g., provided by Django's widget rendering).
|
||||||
new CleaveZen('#id_friend_code', {
|
cleaveZen('#id_friend_code', {
|
||||||
delimiters: ['-', '-', '-'], // Inserts dashes between the blocks.
|
delimiters: ['-', '-', '-'], // Inserts dashes between the blocks.
|
||||||
blocks: [4, 4, 4, 4],
|
blocks: [4, 4, 4, 4],
|
||||||
numericOnly: true
|
numericOnly: true
|
||||||
|
|
|
||||||
|
|
@ -9,19 +9,21 @@
|
||||||
{% if friend_codes %}
|
{% if friend_codes %}
|
||||||
<ul class="space-y-2">
|
<ul class="space-y-2">
|
||||||
{% for code in friend_codes %}
|
{% for code in friend_codes %}
|
||||||
<li class="flex items-center justify-between {% if user.default_friend_code and code.id == user.default_friend_code.id %}bg-green-200 dark:bg-green-300 dark:text-base-100{% else %}bg-base-100 dark:bg-base-900 dark:text-white{% endif %} p-4 rounded shadow">
|
<li class="flex flex-col sm:flex-row items-start sm:items-center justify-between {% if user.default_friend_code and code.id == user.default_friend_code.id %}bg-green-200 dark:bg-green-300 dark:text-base-100{% else %}bg-base-100 dark:bg-base-900 dark:text-white{% endif %} p-4 rounded shadow">
|
||||||
<div>
|
<div class="flex-2">
|
||||||
<span class="font-mono">{{ code.friend_code }}</span>
|
<span>{{ code.in_game_name }}</span>
|
||||||
{% if user.default_friend_code and code.id == user.default_friend_code.id %}
|
|
||||||
<span class="badge badge-success ml-2">Default</span>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center space-x-2">
|
<div class="flex-3 text-center">
|
||||||
|
<span class="font-mono">{{ code.friend_code }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex-2 flex items-center space-x-2 self-end">
|
||||||
{% if user.default_friend_code and not code.id == user.default_friend_code.id %}
|
{% if user.default_friend_code and not code.id == user.default_friend_code.id %}
|
||||||
<form method="post" action="{% url 'change_default_friend_code' code.id %}">
|
<form method="post" action="{% url 'change_default_friend_code' code.id %}">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<button type="submit" class="btn btn-secondary btn-sm">Set as Default</button>
|
<button type="submit" class="btn btn-secondary btn-sm">Set as Default</button>
|
||||||
</form>
|
</form>
|
||||||
|
{% elif user.default_friend_code and code.id == user.default_friend_code.id %}
|
||||||
|
<span class="badge badge-success ml-2">Default</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a href="{% url 'delete_friend_code' code.id %}" class="btn btn-error btn-sm">Delete</a>
|
<a href="{% url 'delete_friend_code' code.id %}" class="btn btn-error btn-sm">Delete</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -27,11 +27,9 @@
|
||||||
<button type="submit" class="btn btn-primary grow">
|
<button type="submit" class="btn btn-primary grow">
|
||||||
Find a Trade Offer
|
Find a Trade Offer
|
||||||
</button>
|
</button>
|
||||||
{% if user.is_authenticated %}
|
|
||||||
<a href="{% url 'trade_offer_create' %}" id="createTradeOfferBtn" class="btn btn-secondary grow">
|
<a href="{% url 'trade_offer_create' %}" id="createTradeOfferBtn" class="btn btn-secondary grow">
|
||||||
Create Trade Offer
|
Create Trade Offer
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ Expected variables:
|
||||||
- friend_codes: A list or QuerySet of FriendCode objects.
|
- friend_codes: A list or QuerySet of FriendCode objects.
|
||||||
- selected_friend_code (optional): The currently selected FriendCode. If not provided, the user's default friend code is used.
|
- selected_friend_code (optional): The currently selected FriendCode. If not provided, the user's default friend code is used.
|
||||||
- field_name (optional): The name/id for the input element (default "friend_code").
|
- field_name (optional): The name/id for the input element (default "friend_code").
|
||||||
- label (optional): The label text (default "Friend Code").
|
- label (optional): The label text (default None).
|
||||||
{% endcomment %}
|
{% endcomment %}
|
||||||
|
|
||||||
{% with field_name=field_name|default:"friend_code" label=label|default:"" %}
|
{% with field_name=field_name|default:"friend_code" label=label|default:"" %}
|
||||||
|
|
@ -19,7 +19,7 @@ Expected variables:
|
||||||
<select id="{{ field_name }}" name="{{ field_name }}" class="select select-bordered w-full" @change="$el.form.submit()">
|
<select id="{{ field_name }}" name="{{ field_name }}" class="select select-bordered w-full" @change="$el.form.submit()">
|
||||||
{% for code in friend_codes %}
|
{% for code in friend_codes %}
|
||||||
<option value="{{ code.pk }}" {% if effective_friend_code and code.pk|stringformat:"s" == effective_friend_code.pk|stringformat:"s" %}selected{% endif %}>
|
<option value="{{ code.pk }}" {% if effective_friend_code and code.pk|stringformat:"s" == effective_friend_code.pk|stringformat:"s" %}selected{% endif %}>
|
||||||
{{ code.friend_code }}
|
{{ code.in_game_name }}
|
||||||
</option>
|
</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
|
|
|
||||||
|
|
@ -98,8 +98,8 @@ if (!window.tradeOfferCard) {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
|
<div class="flex justify-center my-1 h-5">
|
||||||
{% if have_cards_available|length > 1 or want_cards_available|length > 1 %}
|
{% if have_cards_available|length > 1 or want_cards_available|length > 1 %}
|
||||||
<div class="flex justify-center my-1">
|
|
||||||
<svg @click="badgeExpanded = !badgeExpanded"
|
<svg @click="badgeExpanded = !badgeExpanded"
|
||||||
x-bind:class="{ 'rotate-180': badgeExpanded }"
|
x-bind:class="{ 'rotate-180': badgeExpanded }"
|
||||||
class="transition-transform duration-500 h-5 w-5 cursor-pointer"
|
class="transition-transform duration-500 h-5 w-5 cursor-pointer"
|
||||||
|
|
@ -107,9 +107,9 @@ if (!window.tradeOfferCard) {
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
d="M19 9l-7 7-7-7" />
|
d="M19 9l-7 7-7-7" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div class="self-end">
|
<div class="self-end">
|
||||||
<div class="flex justify-between px-2 pb-2">
|
<div class="flex justify-between px-2 pb-2">
|
||||||
<div class="text-gray-500 text-sm tooltip tooltip-right" data-tip="ID: {{ offer.hash }}">
|
<div class="text-gray-500 text-sm tooltip tooltip-right" data-tip="ID: {{ offer.hash }}">
|
||||||
|
|
@ -214,8 +214,8 @@ if (!window.tradeOfferCard) {
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex justify-center my-1 h-5">
|
||||||
{% if offer.acceptances.all|length > 1 %}
|
{% if offer.acceptances.all|length > 1 %}
|
||||||
<div class="flex justify-center my-1">
|
|
||||||
<svg @click="acceptanceExpanded = !acceptanceExpanded"
|
<svg @click="acceptanceExpanded = !acceptanceExpanded"
|
||||||
x-bind:class="{ 'rotate-180': acceptanceExpanded }"
|
x-bind:class="{ 'rotate-180': acceptanceExpanded }"
|
||||||
class="transition-transform duration-500 h-5 w-5 cursor-pointer"
|
class="transition-transform duration-500 h-5 w-5 cursor-pointer"
|
||||||
|
|
@ -223,9 +223,9 @@ if (!window.tradeOfferCard) {
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
d="M19 9l-7 7-7-7" />
|
d="M19 9l-7 7-7-7" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div class="flex justify-between px-2 pb-2 self-end">
|
<div class="flex justify-between px-2 pb-2 self-end">
|
||||||
<!-- Back-to-front flip button -->
|
<!-- Back-to-front flip button -->
|
||||||
<div class="text-gray-500 cursor-pointer"
|
<div class="text-gray-500 cursor-pointer"
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 5.1.2 on 2025-03-13 01:46
|
# Generated by Django 5.1.2 on 2025-03-14 05:35
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,6 @@ def render_trade_offer(context, offer):
|
||||||
Groups acceptances for each card on both the have and want sides.
|
Groups acceptances for each card on both the have and want sides.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Use the already prefetched acceptances.
|
|
||||||
acceptances = offer.acceptances.all()
|
|
||||||
have_cards_available = []
|
have_cards_available = []
|
||||||
want_cards_available = []
|
want_cards_available = []
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,6 @@ class TradeOfferCreateView(LoginRequiredMixin, CreateView):
|
||||||
template_name = "trades/trade_offer_create.html"
|
template_name = "trades/trade_offer_create.html"
|
||||||
success_url = reverse_lazy("trade_offer_list")
|
success_url = reverse_lazy("trade_offer_list")
|
||||||
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
|
||||||
if not request.user.friend_codes.exists():
|
|
||||||
raise PermissionDenied("No friend codes available for your account.")
|
|
||||||
return super().dispatch(request, *args, **kwargs)
|
|
||||||
|
|
||||||
def get_form(self, form_class=None):
|
def get_form(self, form_class=None):
|
||||||
form = super().get_form(form_class)
|
form = super().get_form(form_class)
|
||||||
# Restrict the 'initiated_by' choices to friend codes owned by the logged-in user.
|
# Restrict the 'initiated_by' choices to friend codes owned by the logged-in user.
|
||||||
|
|
@ -86,8 +81,21 @@ class TradeOfferAllListView(ListView):
|
||||||
'trade_offer_want_cards__card',
|
'trade_offer_want_cards__card',
|
||||||
Prefetch(
|
Prefetch(
|
||||||
'acceptances',
|
'acceptances',
|
||||||
queryset=TradeAcceptance.objects.select_related('accepted_by', 'requested_card', 'offered_card')
|
queryset=TradeAcceptance.objects.select_related('accepted_by', 'requested_card', 'offered_card').prefetch_related(
|
||||||
|
'requested_card__decks',
|
||||||
|
'offered_card__decks',
|
||||||
|
'requested_card__rarity',
|
||||||
|
'offered_card__rarity',
|
||||||
|
'requested_card__cardset',
|
||||||
|
'offered_card__cardset',
|
||||||
)
|
)
|
||||||
|
),
|
||||||
|
'trade_offer_have_cards__card__decks',
|
||||||
|
'trade_offer_want_cards__card__decks',
|
||||||
|
'trade_offer_have_cards__card__rarity',
|
||||||
|
'trade_offer_want_cards__card__rarity',
|
||||||
|
'trade_offer_have_cards__card__cardset',
|
||||||
|
'trade_offer_want_cards__card__cardset'
|
||||||
)
|
)
|
||||||
.order_by("-updated_at")
|
.order_by("-updated_at")
|
||||||
)
|
)
|
||||||
|
|
@ -115,8 +123,21 @@ class TradeOfferAllListView(ListView):
|
||||||
'trade_offer_want_cards__card',
|
'trade_offer_want_cards__card',
|
||||||
Prefetch(
|
Prefetch(
|
||||||
'acceptances',
|
'acceptances',
|
||||||
queryset=TradeAcceptance.objects.select_related('accepted_by', 'requested_card', 'offered_card')
|
queryset=TradeAcceptance.objects.select_related('accepted_by', 'requested_card', 'offered_card').prefetch_related(
|
||||||
|
'requested_card__decks',
|
||||||
|
'offered_card__decks',
|
||||||
|
'requested_card__rarity',
|
||||||
|
'offered_card__rarity',
|
||||||
|
'requested_card__cardset',
|
||||||
|
'offered_card__cardset',
|
||||||
)
|
)
|
||||||
|
),
|
||||||
|
'trade_offer_have_cards__card__decks',
|
||||||
|
'trade_offer_want_cards__card__decks',
|
||||||
|
'trade_offer_have_cards__card__rarity',
|
||||||
|
'trade_offer_want_cards__card__rarity',
|
||||||
|
'trade_offer_have_cards__card__cardset',
|
||||||
|
'trade_offer_want_cards__card__cardset'
|
||||||
)
|
)
|
||||||
.order_by("-updated_at")
|
.order_by("-updated_at")
|
||||||
)
|
)
|
||||||
|
|
@ -314,7 +335,7 @@ class TradeOfferDeleteView(LoginRequiredMixin, DeleteView):
|
||||||
messages.success(request, "Trade offer has been deleted.")
|
messages.success(request, "Trade offer has been deleted.")
|
||||||
return super().delete(request, *args, **kwargs)
|
return super().delete(request, *args, **kwargs)
|
||||||
|
|
||||||
class TradeOfferSearchView(LoginRequiredMixin, ListView):
|
class TradeOfferSearchView(ListView):
|
||||||
"""
|
"""
|
||||||
Reworked trade offer search view using POST.
|
Reworked trade offer search view using POST.
|
||||||
|
|
||||||
|
|
@ -427,11 +448,6 @@ class TradeOfferDetailView(LoginRequiredMixin, DetailView):
|
||||||
model = TradeOffer
|
model = TradeOffer
|
||||||
template_name = "trades/trade_offer_detail.html"
|
template_name = "trades/trade_offer_detail.html"
|
||||||
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
|
||||||
if not request.user.friend_codes.exists():
|
|
||||||
raise PermissionDenied("No friend codes available for your account.")
|
|
||||||
return super().dispatch(request, *args, **kwargs)
|
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return (
|
return (
|
||||||
TradeOffer.objects.select_related('initiated_by')
|
TradeOffer.objects.select_related('initiated_by')
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue