update trade acceptance styling and layout, and also trade acceptance update/details page. fixes #16

This commit is contained in:
badblocks 2025-04-10 23:55:08 -07:00
parent 1c95ccfff7
commit 5fbe80e83a
14 changed files with 257 additions and 139 deletions

View file

@ -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
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')),
],
options={
'ordering': ['card__name'],
'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')),
],
options={
'ordering': ['card__name'],
'unique_together': {('trade_offer', 'card')},
},
),

View file

@ -100,7 +100,6 @@ class TradeOffer(models.Model):
# Use super().save() here to avoid recursion.
super(TradeOffer, self).save(update_fields=["rarity_level", "rarity_icon"])
# New derived properties for available cards
@property
def have_cards_available(self):
# 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)
qty_accepted = models.PositiveIntegerField(default=0, editable=False)
@property
def qty_available(self):
return self.quantity - self.qty_accepted
def __str__(self):
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)
qty_accepted = models.PositiveIntegerField(default=0, editable=False)
@property
def qty_available(self):
return self.quantity - self.qty_accepted
def __str__(self):
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",
}
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
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)
@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
def is_completed(self):
return self.state in {

View file

@ -1,5 +1,6 @@
from django import template
from math import ceil
from trades.models import TradeAcceptance
register = template.Library()
@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
]
acceptances = [acceptance for acceptance in list(offer.acceptances.all())
if acceptance.is_active
]
acceptances = list(offer.acceptances.all())
# Determine if the offer should show its back side (acceptances view) by default.
# 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.
"""
return {
"acceptance": acceptance,
"request": context.get("request"),