update trade acceptance styling and layout, and also trade acceptance update/details page. fixes #16
This commit is contained in:
parent
1c95ccfff7
commit
5fbe80e83a
14 changed files with 257 additions and 139 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 5.1.2 on 2025-04-08 06:24
|
# Generated by Django 5.1.2 on 2025-04-13 05:10
|
||||||
|
|
||||||
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-04-08 06:24
|
# Generated by Django 5.1.2 on 2025-04-13 05:10
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
|
||||||
|
|
@ -29,3 +29,8 @@ def card_badge_inline(card, quantity=None):
|
||||||
'expanded': True,
|
'expanded': True,
|
||||||
})
|
})
|
||||||
return mark_safe(html)
|
return mark_safe(html)
|
||||||
|
|
||||||
|
@register.filter
|
||||||
|
def addstr(arg1, arg2):
|
||||||
|
"""concatenate arg1 & arg2"""
|
||||||
|
return str(arg1) + str(arg2)
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
"password": "pbkdf2_sha256$870000$NxQDOyPzAvM3FgLL5z0SRy$JuET4f8HI55Oy1umkzg6WtjFVpYTt+UfpZWqPff4EO4=",
|
"password": "pbkdf2_sha256$870000$NxQDOyPzAvM3FgLL5z0SRy$JuET4f8HI55Oy1umkzg6WtjFVpYTt+UfpZWqPff4EO4=",
|
||||||
"last_login": "2025-03-13T04:52:57.949Z",
|
"last_login": "2025-03-13T04:52:57.949Z",
|
||||||
"is_superuser": false,
|
"is_superuser": false,
|
||||||
"username": "nathanward2016@gmail.com",
|
"username": "backrolls",
|
||||||
"first_name": "",
|
"first_name": "",
|
||||||
"last_name": "",
|
"last_name": "",
|
||||||
"email": "nathanward2016@gmail.com",
|
"email": "nathanward2016@gmail.com",
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ module.exports = {
|
||||||
'bg-success',
|
'bg-success',
|
||||||
'bg-warning',
|
'bg-warning',
|
||||||
'bg-error',
|
'bg-error',
|
||||||
|
'text-gray-700'
|
||||||
],
|
],
|
||||||
theme: {
|
theme: {
|
||||||
extend: {},
|
extend: {},
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
{% 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>
|
||||||
<div class="flex justify-center flex-wrap">
|
<div class="flex justify-center flex-wrap gap-2">
|
||||||
{% for card in group.cards %}
|
{% for card in group.cards %}
|
||||||
<a href="{% url 'cards:card_detail' card.pk %}">
|
<a href="{% url 'cards:card_detail' card.pk %}">
|
||||||
{% card_badge card expanded=True %}
|
{% card_badge card expanded=True %}
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="flex justify-center flex-wrap">
|
<div class="flex justify-center flex-wrap gap-2">
|
||||||
{% for card in cards %}
|
{% for card in cards %}
|
||||||
<a href="{% url 'cards:card_detail' card.pk %}">
|
<a href="{% url 'cards:card_detail' card.pk %}">
|
||||||
{% card_badge card expanded=True %}
|
{% card_badge card expanded=True %}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,28 @@
|
||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
{% load trade_offer_tags %}
|
{% load trade_offer_tags card_badge %}
|
||||||
|
|
||||||
{% block title %}Update Trade{% endblock title %}
|
{% block title %}Update Trade{% endblock title %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container mx-auto max-w-xl mt-6">
|
{% if form and form.errors %}
|
||||||
<h2 class="text-2xl font-bold">Update Trade</h2>
|
<div class="alert alert-error mt-4">
|
||||||
<div class="text-center py-8">
|
<strong>Please correct the errors below:</strong>
|
||||||
|
<ul>
|
||||||
|
{% for field in form %}
|
||||||
|
{% for error in field.errors %}
|
||||||
|
<li>{{ error }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
{% for error in form.non_field_errors %}
|
||||||
|
<li>{{ error }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<h2 class="text-2xl font-bold">Trade Details</h2>
|
||||||
|
|
||||||
|
<div class="card card-border bg-base-100 shadow-lg mx-auto p-6 m-4 text-sm">
|
||||||
|
<div class="text-center mb-4">
|
||||||
<ul class="steps">
|
<ul class="steps">
|
||||||
{% if object.is_thanked %}
|
{% if object.is_thanked %}
|
||||||
<li class="step step-primary">Accepted</li>
|
<li class="step step-primary">Accepted</li>
|
||||||
|
|
@ -44,14 +60,29 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="divider"></div>
|
||||||
<div class="py-8">
|
<div class="grid grid-cols-2 justify-items-end items-baseline gap-4">
|
||||||
{% render_trade_acceptance object %}
|
<div class="font-semibold">Initiator:</div>
|
||||||
|
<div class="justify-self-start">{{ object.trade_offer.initiated_by.user.username }}</div>
|
||||||
|
<div class="font-semibold">Initiator's Card:</div>
|
||||||
|
<div class="justify-self-start">{% card_badge object.offered_card %}</div>
|
||||||
|
<div class="font-semibold">Acceptor:</div>
|
||||||
|
<div class="justify-self-start">{{ object.accepted_by.user.username }}</div>
|
||||||
|
<div class="font-semibold">Acceptor's Card:</div>
|
||||||
|
<div class="justify-self-start">{% card_badge object.requested_card %}</div>
|
||||||
|
<div class="font-semibold">State:</div>
|
||||||
|
<div class="justify-self-start">{{ object.get_state_display }}, Waiting on {% if object.is_initiator_state %}{{ object.accepted_by.user.username }}{% else %}{{ object.trade_offer.initiated_by.user.username }}{% endif %} to {{ object.next_action_label }}</div>
|
||||||
|
<div class="font-semibold">ID:</div>
|
||||||
|
<div class="justify-self-start">#{{ object.hash }}</div>
|
||||||
|
<div class="font-semibold">Trade Offer:</div>
|
||||||
|
<div class="justify-self-start"><a class="link link-hover" href="{% url 'trade_offer_detail' object.trade_offer.id %}">#{{ object.trade_offer.hash }}</a></div>
|
||||||
|
<div class="font-semibold">Created At:</div>
|
||||||
|
<div class="justify-self-start">{{ object.created_at }}</div>
|
||||||
|
<div class="font-semibold">Last Updated:</div>
|
||||||
|
<div class="justify-self-start">{{ object.updated_at }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-6 card card-border bg-base-100 shadow-lg mx-auto p-6 mb-4">
|
|
||||||
<h3 class="text-xl font-semibold mb-4">Select an action:</h3>
|
|
||||||
{% if form.fields.state.choices %}
|
{% if form.fields.state.choices %}
|
||||||
|
<div class="divider"></div>
|
||||||
<div class="flex flex-row gap-2">
|
<div class="flex flex-row gap-2">
|
||||||
{% for state_value, state_label in form.fields.state.choices %}
|
{% for state_value, state_label in form.fields.state.choices %}
|
||||||
<form method="post" class="mb-2 flex-1">
|
<form method="post" class="mb-2 flex-1">
|
||||||
|
|
@ -63,26 +94,6 @@
|
||||||
</form>
|
</form>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
|
||||||
<p>No available actions.</p>
|
|
||||||
<!--button class="btn-info"></button-->
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% if form and form.errors %}
|
|
||||||
<div class="alert alert-error mt-4">
|
|
||||||
<strong>Please correct the errors below:</strong>
|
|
||||||
<ul>
|
|
||||||
{% for field in form %}
|
|
||||||
{% for error in field.errors %}
|
|
||||||
<li>{{ error }}</li>
|
|
||||||
{% endfor %}
|
|
||||||
{% endfor %}
|
|
||||||
{% for error in form.non_field_errors %}
|
|
||||||
<li>{{ error }}</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
@ -1,23 +1,21 @@
|
||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
{% load trade_offer_tags %}
|
{% load trade_offer_tags card_badge %}
|
||||||
|
|
||||||
{% block title %}{{title}}{% endblock title %}
|
{% block title %}{{title}}{% endblock title %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container mx-auto max-w-2xl mt-6">
|
<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="flex justify-center mt-10">
|
<div class="card card-border bg-base-100 shadow-lg mx-auto p-6 m-4 text-sm">
|
||||||
{% render_trade_offer object %}
|
|
||||||
</div>
|
|
||||||
{% if acceptance_form %}
|
{% if acceptance_form %}
|
||||||
<div class="w-3/4 mx-auto mt-4">
|
<div class="col-span-2 w-3/4 mx-auto card card-border bg-base-200 shadow-lg p-6 mb-8">
|
||||||
<h3 class="text-xl font-semibold mt-6 mb-2">Accept This Offer</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 %}
|
||||||
<input type="hidden" name="next" value="{% url 'trade_offer_detail' pk=object.pk %}">
|
<input type="hidden" name="next" value="{% url 'trade_offer_detail' pk=object.pk %}">
|
||||||
|
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<label for="{{ acceptance_form.offered_card.id_for_label }}" class="block text-sm font-medium text-gray-700">I have:</label>
|
<label for="{{ acceptance_form.offered_card.id_for_label }}" class="block text-sm font-medium mb-1">I have:</label>
|
||||||
{{ acceptance_form.offered_card }}
|
{{ acceptance_form.offered_card }}
|
||||||
{% for error in acceptance_form.offered_card.errors %}
|
{% for error in acceptance_form.offered_card.errors %}
|
||||||
<p class="mt-1 text-sm text-red-600">{{ error }}</p>
|
<p class="mt-1 text-sm text-red-600">{{ error }}</p>
|
||||||
|
|
@ -25,7 +23,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<label for="{{ acceptance_form.requested_card.id_for_label }}" class="block text-sm font-medium text-gray-700">I want:</label>
|
<label for="{{ acceptance_form.requested_card.id_for_label }}" class="block text-sm font-medium mb-1">I want:</label>
|
||||||
{{ acceptance_form.requested_card }}
|
{{ acceptance_form.requested_card }}
|
||||||
{% for error in acceptance_form.requested_card.errors %}
|
{% for error in acceptance_form.requested_card.errors %}
|
||||||
<p class="mt-1 text-sm text-red-600">{{ error }}</p>
|
<p class="mt-1 text-sm text-red-600">{{ error }}</p>
|
||||||
|
|
@ -34,7 +32,7 @@
|
||||||
|
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
{% if not acceptance_form.accepted_by.field.widget.is_hidden %}
|
{% if not acceptance_form.accepted_by.field.widget.is_hidden %}
|
||||||
<label for="{{ acceptance_form.accepted_by.id_for_label }}" class="block text-sm font-medium text-gray-700">
|
<label for="{{ acceptance_form.accepted_by.id_for_label }}" class="block text-sm font-medium">
|
||||||
Accepted By
|
Accepted By
|
||||||
</label>
|
</label>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
@ -43,8 +41,6 @@
|
||||||
<p class="mt-1 text-sm text-red-600">{{ error }}</p>
|
<p class="mt-1 text-sm text-red-600">{{ error }}</p>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<div class="mt-6 flex justify-end">
|
<div class="mt-6 flex justify-end">
|
||||||
{% if is_initiator %}
|
{% if is_initiator %}
|
||||||
|
|
@ -52,7 +48,50 @@
|
||||||
{% elif request.user.is_authenticated %}
|
{% elif request.user.is_authenticated %}
|
||||||
<button type="submit" class="btn btn-primary">Accept Trade</button>
|
<button type="submit" class="btn btn-primary">Accept Trade</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<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="flex flex-wrap flex-col gap-2 text-left mt-4">
|
||||||
|
{% for card in object.have_cards_available %}
|
||||||
|
{% card_badge card.card card.qty_available %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="font-semibold justify-self-start text-lg">Cards They Want:
|
||||||
|
<div class="flex flex-wrap flex-col gap-2 mt-4">
|
||||||
|
{% for card in object.want_cards_available %}
|
||||||
|
{% card_badge card.card card.qty_available %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="divider"></div>
|
||||||
|
<div class="grid grid-cols-2 justify-items-end items-baseline gap-4">
|
||||||
|
<div class="font-semibold">Initiator:</div>
|
||||||
|
<div class="justify-self-start">{{ object.initiated_by.user.username }}</div>
|
||||||
|
<div class="font-semibold">ID:</div>
|
||||||
|
<div class="justify-self-start">#{{ object.hash }}</div>
|
||||||
|
<div class="font-semibold">Created At:</div>
|
||||||
|
<div class="justify-self-start">{{ object.created_at }}</div>
|
||||||
|
<div class="font-semibold">Last Updated:</div>
|
||||||
|
<div class="justify-self-start">{{ object.updated_at }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="divider"></div>
|
||||||
|
<div class="font-semibold text-center 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">
|
||||||
|
{% 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="">{% card_badge trade.offered_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>
|
||||||
|
{% empty %}
|
||||||
|
<div class="text-center justify-center w-full text-center">No trades yet.</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{% if not expanded %}
|
{% if not expanded %}
|
||||||
<div class="relative block m-1">
|
<div class="relative block">
|
||||||
<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-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 max-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>
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="relative block m-1">
|
<div class="relative block">
|
||||||
<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-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 %}
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,50 @@
|
||||||
{% 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 w-90 mx-auto">
|
||||||
|
<div class="cursor-pointer" @click.stop="window.location.href='{% url 'trade_acceptance_update' pk=acceptance.pk %}'">
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<div class="py-4 mx-4">
|
<div class="my-4 mx-4">
|
||||||
<div class="flex justify-between items-center">
|
<div class="flex justify-start items-center">
|
||||||
<!-- Left: Initiator's avatar (moved from center) and "Has" -->
|
<!-- Left: Initiator's avatar and "Has" -->
|
||||||
<div class="flex items-center ms-8">
|
<div class="flex items-center">
|
||||||
<div class="avatar mr-2">
|
<div class="avatar me-2">
|
||||||
<div class="w-10 rounded-full">
|
<div class="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>
|
||||||
<span class="text-sm font-semibold">Has</span>
|
<div class="text-gray-500 text-sm">
|
||||||
|
{% if acceptance.is_initiator_state %}
|
||||||
|
{{ acceptance.action_label_2 }}
|
||||||
|
{% else %}
|
||||||
|
Waiting on {{ acceptance.trade_offer.initiated_by.user.username }} to {{ acceptance.next_action_label }}...
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Main Card Row: Single row with the acceptance's cards -->
|
||||||
|
<div class="px-2 pb-0">
|
||||||
|
<div class="grid grid-cols-2 items-center">
|
||||||
|
<div class="flex flex-col items-center">
|
||||||
|
<div class="cursor-pointer" @click.stop="window.location.href='{% url 'cards:card_detail' pk=acceptance.requested_card.pk %}'">{% card_badge acceptance.requested_card %}</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col items-center">
|
||||||
|
<div class="cursor-pointer" @click.stop="window.location.href='{% url 'cards:card_detail' pk=acceptance.offered_card.pk %}'">{% card_badge acceptance.offered_card %}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="my-4 mx-4">
|
||||||
|
<div class="flex justify-end items-center">
|
||||||
<!-- Right: "Wants" with the acceptor's avatar -->
|
<!-- Right: "Wants" with the acceptor's avatar -->
|
||||||
<div class="flex items-center me-8">
|
<div class="flex items-center">
|
||||||
<span class="text-sm font-semibold mr-2">Wants</span>
|
<div class="text-gray-500 text-sm">
|
||||||
<div class="avatar">
|
{% if acceptance.is_acceptor_state %}
|
||||||
|
{{ acceptance.action_label_2 }}
|
||||||
|
{% else %}
|
||||||
|
Waiting on {{ acceptance.accepted_by.user.username }} to {{ acceptance.next_action_label }}...
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="avatar ms-2">
|
||||||
<div class="w-10 rounded-full">
|
<div class="w-10 rounded-full">
|
||||||
{{ acceptance.accepted_by.user.email|gravatar:40 }}
|
{{ acceptance.accepted_by.user.email|gravatar:40 }}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -24,31 +52,5 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Main Card Row: Single row with the acceptance's cards -->
|
|
||||||
<a href="{% url 'trade_acceptance_update' pk=acceptance.pk %}" class="no-underline block">
|
|
||||||
<div class="px-2 pb-0">
|
|
||||||
<div class="grid grid-cols-2 items-center">
|
|
||||||
<div class="flex flex-col items-center">
|
|
||||||
{% card_badge acceptance.requested_card %}
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-col items-center">
|
|
||||||
{% card_badge acceptance.offered_card %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Footer: Only info button with acceptance hash -->
|
|
||||||
<div class="flex justify-between p-2">
|
|
||||||
<div class="text-gray-500 text-sm">
|
|
||||||
{{ acceptance.get_state_display }}
|
|
||||||
</div>
|
|
||||||
<div class="text-gray-500 text-sm tooltip tooltip-left" data-tip="ID: {{ acceptance.hash }}">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round"
|
|
||||||
d="M11.25 11.25l.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0zm-9-3.75h.008v.008H12V8.25z" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -27,12 +27,12 @@
|
||||||
{% if num_cards_available > 0 %}
|
{% if num_cards_available > 0 %}
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
{% for card in have_cards_available %}
|
{% for card in have_cards_available %}
|
||||||
<div class="cursor-pointer" @click.stop="window.location.href='{% url 'cards:card_detail' pk=card.card.pk %}'">{% card_badge card.card card.quantity %}</div>
|
<div class="cursor-pointer m-1" @click.stop="window.location.href='{% url 'cards:card_detail' pk=card.card.pk %}'">{% card_badge card.card card.quantity %}</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
{% for card in want_cards_available %}
|
{% for card in want_cards_available %}
|
||||||
<div class="cursor-pointer" @click.stop="window.location.href='{% url 'cards:card_detail' pk=card.card.pk %}'">{% card_badge card.card card.quantity %}</div>
|
<div class="cursor-pointer m-1" @click.stop="window.location.href='{% url 'cards:card_detail' pk=card.card.pk %}'">{% card_badge card.card card.quantity %}</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 5.1.2 on 2025-04-08 06:24
|
# Generated by Django 5.1.2 on 2025-04-13 05:10
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
@ -52,6 +52,7 @@ class Migration(migrations.Migration):
|
||||||
('trade_offer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='trade_offer_have_cards', to='trades.tradeoffer')),
|
('trade_offer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='trade_offer_have_cards', to='trades.tradeoffer')),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
|
'ordering': ['card__name'],
|
||||||
'unique_together': {('trade_offer', 'card')},
|
'unique_together': {('trade_offer', 'card')},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
@ -70,6 +71,7 @@ class Migration(migrations.Migration):
|
||||||
('trade_offer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='trade_offer_want_cards', to='trades.tradeoffer')),
|
('trade_offer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='trade_offer_want_cards', to='trades.tradeoffer')),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
|
'ordering': ['card__name'],
|
||||||
'unique_together': {('trade_offer', 'card')},
|
'unique_together': {('trade_offer', 'card')},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,6 @@ class TradeOffer(models.Model):
|
||||||
# Use super().save() here to avoid recursion.
|
# Use super().save() here to avoid recursion.
|
||||||
super(TradeOffer, self).save(update_fields=["rarity_level", "rarity_icon"])
|
super(TradeOffer, self).save(update_fields=["rarity_level", "rarity_icon"])
|
||||||
|
|
||||||
# New derived properties for available cards
|
|
||||||
@property
|
@property
|
||||||
def have_cards_available(self):
|
def have_cards_available(self):
|
||||||
# Returns the list of have_cards (through objects) that still have available quantity.
|
# Returns the list of have_cards (through objects) that still have available quantity.
|
||||||
|
|
@ -136,6 +135,10 @@ class TradeOfferHaveCard(models.Model):
|
||||||
quantity = models.PositiveIntegerField(default=1)
|
quantity = models.PositiveIntegerField(default=1)
|
||||||
qty_accepted = models.PositiveIntegerField(default=0, editable=False)
|
qty_accepted = models.PositiveIntegerField(default=0, editable=False)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def qty_available(self):
|
||||||
|
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.name} x{self.quantity} (Accepted: {self.qty_accepted})"
|
||||||
|
|
||||||
|
|
@ -166,6 +169,10 @@ class TradeOfferWantCard(models.Model):
|
||||||
quantity = models.PositiveIntegerField(default=1)
|
quantity = models.PositiveIntegerField(default=1)
|
||||||
qty_accepted = models.PositiveIntegerField(default=0, editable=False)
|
qty_accepted = models.PositiveIntegerField(default=0, editable=False)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def qty_available(self):
|
||||||
|
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.name} x{self.quantity} (Accepted: {self.qty_accepted})"
|
||||||
|
|
||||||
|
|
@ -246,6 +253,17 @@ class TradeAcceptance(models.Model):
|
||||||
AcceptanceState.THANKED_BY_BOTH: "Send Thanks",
|
AcceptanceState.THANKED_BY_BOTH: "Send Thanks",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ALTERNATE_ACTION_LABELS_2 = {
|
||||||
|
AcceptanceState.REJECTED_BY_INITIATOR: "Rejected this Trade",
|
||||||
|
AcceptanceState.REJECTED_BY_ACCEPTOR: "Rejected this Trade",
|
||||||
|
AcceptanceState.ACCEPTED: "Accepted this Trade",
|
||||||
|
AcceptanceState.SENT: "Sent the Card",
|
||||||
|
AcceptanceState.RECEIVED: "Received the Card and Responded",
|
||||||
|
AcceptanceState.THANKED_BY_INITIATOR: "Sent Thanks",
|
||||||
|
AcceptanceState.THANKED_BY_ACCEPTOR: "Sent Thanks",
|
||||||
|
AcceptanceState.THANKED_BY_BOTH: "Sent Thanks",
|
||||||
|
}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_action_label_for_state(cls, state_value):
|
def get_action_label_for_state(cls, state_value):
|
||||||
"""
|
"""
|
||||||
|
|
@ -262,6 +280,46 @@ class TradeAcceptance(models.Model):
|
||||||
"""
|
"""
|
||||||
return self.get_action_label_for_state(self.state)
|
return self.get_action_label_for_state(self.state)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def next_action_label(self):
|
||||||
|
"""
|
||||||
|
Returns what the next action label would be based on the current state.
|
||||||
|
"""
|
||||||
|
if self.state == self.AcceptanceState.ACCEPTED:
|
||||||
|
return self.get_action_label_for_state(self.AcceptanceState.SENT)
|
||||||
|
elif self.state == self.AcceptanceState.SENT:
|
||||||
|
return self.get_action_label_for_state(self.AcceptanceState.RECEIVED)
|
||||||
|
elif self.state == self.AcceptanceState.RECEIVED or self.state == self.AcceptanceState.THANKED_BY_ACCEPTOR or self.state == self.AcceptanceState.THANKED_BY_INITIATOR:
|
||||||
|
return self.get_action_label_for_state(self.AcceptanceState.THANKED_BY_BOTH)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_action_label_for_state_2(cls, state_value):
|
||||||
|
"""
|
||||||
|
Returns the alternate action label for the provided state_value.
|
||||||
|
If no alternate label exists, falls back to the default label.
|
||||||
|
"""
|
||||||
|
default = dict(cls.AcceptanceState.choices).get(state_value, state_value)
|
||||||
|
return cls.ALTERNATE_ACTION_LABELS_2.get(state_value, default)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def action_label_2(self):
|
||||||
|
"""
|
||||||
|
For the current acceptance state, return the alternate action label.
|
||||||
|
"""
|
||||||
|
return self.get_action_label_for_state_2(self.state)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_initiator_state(self):
|
||||||
|
return self.state in [self.AcceptanceState.SENT.value, self.AcceptanceState.THANKED_BY_INITIATOR.value, self.AcceptanceState.THANKED_BY_BOTH.value]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_acceptor_state(self):
|
||||||
|
return self.state in [self.AcceptanceState.ACCEPTED.value, self.AcceptanceState.RECEIVED.value, self.AcceptanceState.THANKED_BY_ACCEPTOR.value, self.AcceptanceState.THANKED_BY_BOTH.value]
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_completed(self):
|
def is_completed(self):
|
||||||
return self.state in {
|
return self.state in {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
from django import template
|
from django import template
|
||||||
from math import ceil
|
from math import ceil
|
||||||
|
from trades.models import TradeAcceptance
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
|
|
||||||
@register.inclusion_tag('templatetags/trade_offer.html', takes_context=True)
|
@register.inclusion_tag('templatetags/trade_offer.html', takes_context=True)
|
||||||
|
|
@ -20,9 +21,7 @@ def render_trade_offer(context, offer):
|
||||||
if card.quantity > card.qty_accepted
|
if card.quantity > card.qty_accepted
|
||||||
]
|
]
|
||||||
|
|
||||||
acceptances = [acceptance for acceptance in list(offer.acceptances.all())
|
acceptances = list(offer.acceptances.all())
|
||||||
if acceptance.is_active
|
|
||||||
]
|
|
||||||
|
|
||||||
# Determine if the offer should show its back side (acceptances view) by default.
|
# Determine if the offer should show its back side (acceptances view) by default.
|
||||||
# If either side has no available cards, then flip the offer.
|
# If either side has no available cards, then flip the offer.
|
||||||
|
|
@ -51,6 +50,7 @@ def render_trade_acceptance(context, acceptance):
|
||||||
"""
|
"""
|
||||||
Renders a simple trade acceptance view with a single row and simplified header/footer.
|
Renders a simple trade acceptance view with a single row and simplified header/footer.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"acceptance": acceptance,
|
"acceptance": acceptance,
|
||||||
"request": context.get("request"),
|
"request": context.get("request"),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue