remove trade offer expanding, fix flipping to work with new layout. all cards in trade offer are not expanded
This commit is contained in:
parent
c68d1fb5ec
commit
7c62c57433
11 changed files with 194 additions and 170 deletions
|
|
@ -5,14 +5,14 @@ from django.utils.safestring import mark_safe
|
|||
register = template.Library()
|
||||
|
||||
@register.inclusion_tag("templatetags/card_badge.html")
|
||||
def card_badge(card, quantity=None, static=False):
|
||||
def card_badge(card, quantity=None, expanded=False):
|
||||
return {
|
||||
'quantity': quantity,
|
||||
'style': card.style,
|
||||
'name': card.name,
|
||||
'rarity': card.rarity_icon,
|
||||
'cardset': card.cardset,
|
||||
'static': static,
|
||||
'expanded': expanded,
|
||||
}
|
||||
|
||||
@register.filter
|
||||
|
|
@ -26,6 +26,6 @@ def card_badge_inline(card, quantity=None):
|
|||
'name': card.name,
|
||||
'rarity': card.rarity_icon,
|
||||
'cardset': card.cardset,
|
||||
'static': True,
|
||||
'expanded': True,
|
||||
})
|
||||
return mark_safe(html)
|
||||
|
|
@ -130,17 +130,55 @@ const $$ = selector => Array.from(document.querySelector(selector));
|
|||
window.tradeOfferCard = function() {
|
||||
return {
|
||||
flipped: false,
|
||||
badgeExpanded: false,
|
||||
acceptanceExpanded: false,
|
||||
/**
|
||||
* Update the badge's expanded state.
|
||||
show_back: false,
|
||||
collapsed: false,
|
||||
/*
|
||||
* flipWithCollapse() now applies the height transition directly on the visible card face.
|
||||
* It measures the current face (front or back) and the target face's height,
|
||||
* then animates the current face's height change before toggling the flip.
|
||||
*
|
||||
* @param {boolean} expanded - The new state of the badge.
|
||||
* Make sure your template markup includes:
|
||||
* - x-ref="front" on the front card face
|
||||
* - x-ref="back" on the back card face
|
||||
*/
|
||||
setBadge(expanded) {
|
||||
this.badgeExpanded = expanded;
|
||||
},
|
||||
};
|
||||
flipWithCollapse() {
|
||||
// Determine the currently visible face and the target face.
|
||||
const currentFace = this.flipped ? this.$refs.back : this.$refs.front;
|
||||
const targetFace = this.flipped ? this.$refs.front : this.$refs.back;
|
||||
const container = this.$refs.container;
|
||||
|
||||
// Temporarily force target face to display to measure its height.
|
||||
const originalHeight = targetFace.style.height;
|
||||
const originalDisplay = targetFace.style.display;
|
||||
const originalPosition = targetFace.style.position;
|
||||
const originalVisibility = targetFace.style.visibility;
|
||||
targetFace.style.height = 'auto';
|
||||
targetFace.style.display = 'block';
|
||||
targetFace.style.position = 'absolute';
|
||||
targetFace.style.visibility = 'hidden';
|
||||
const targetHeight = targetFace.offsetHeight + 18;
|
||||
targetFace.style.height = originalHeight;
|
||||
targetFace.style.display = originalDisplay;
|
||||
targetFace.style.position = originalPosition;
|
||||
targetFace.style.visibility = originalVisibility;
|
||||
|
||||
container.setAttribute('x-collapse.duration.500ms.min.' + targetHeight + 'px', '');
|
||||
this.collapsed = true;
|
||||
setTimeout(() => {
|
||||
this.show_back = this.flipped;
|
||||
this.flipped = !this.flipped;
|
||||
setTimeout(() => {
|
||||
this.show_back = !this.show_back;
|
||||
}, 250)
|
||||
setTimeout(() => {
|
||||
this.collapsed = false;
|
||||
setTimeout(() => {
|
||||
container.removeAttribute('x-collapse.duration.500ms.min.' + targetHeight + 'px');
|
||||
}, 550);
|
||||
}, 550);
|
||||
}, 550);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
})();
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
<div class="flex justify-center flex-wrap">
|
||||
{% for card in group.cards %}
|
||||
<a href="{% url 'cards:card_detail' card.pk %}">
|
||||
{% card_badge card static=True %}
|
||||
{% card_badge card expanded=True %}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
<div class="flex justify-center flex-wrap">
|
||||
{% for card in cards %}
|
||||
<a href="{% url 'cards:card_detail' card.pk %}">
|
||||
{% card_badge card static=True %}
|
||||
{% card_badge card expanded=True %}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
{% for card in cards %}
|
||||
<a href="{% url 'cards:card_detail' card.id %}"
|
||||
class="flex justify-between items-center text-primary no-underline">
|
||||
{% card_badge card quantity=card.offer_count static=True %}
|
||||
{% card_badge card quantity=card.offer_count expanded=True %}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
{# Render a trade acceptance using our new tag #}
|
||||
{% render_trade_acceptance offer %}
|
||||
{% else %}
|
||||
{% render_trade_offer offer expanded=expanded %}
|
||||
{% render_trade_offer offer %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% empty %}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<div class="container mx-auto max-w-2xl mt-6">
|
||||
<h2 class="text-2xl font-bold">Trade Offer Details</h2>
|
||||
<div class="flex justify-center mt-10">
|
||||
{% render_trade_offer object expanded=True %}
|
||||
{% render_trade_offer object %}
|
||||
</div>
|
||||
{% if acceptance_form %}
|
||||
<div class="w-3/4 mx-auto mt-4">
|
||||
|
|
|
|||
|
|
@ -1,19 +1,19 @@
|
|||
{% if not static %}
|
||||
<div class="relative block">
|
||||
<div :class="badgeExpanded ? 'grid grid-rows-2 grid-cols-4 h-[52px]' : 'flex flex-row items-center h-[32px]'" x-transition.duration.500ms class="p-1.5 w-40 text-white shadow-lg" style="{{ style }}">
|
||||
<div :class="badgeExpanded ? 'row-start-1 col-start-1 col-span-3' : 'grow'" x-transition.duration.500ms class="truncate text-ellipsis font-semibold leading-tight text-sm">{{ name }}</div>
|
||||
<div x-show="badgeExpanded" x-transition.duration.500ms x-cloak class="row-start-2 col-start-1 col-span-3 truncate align-bottom text-xs">{{ rarity }}</div>
|
||||
<div x-show="true" x-transition.duration.500ms x-cloak :class="badgeExpanded ? 'row-start-2 col-start-4 col-span-1 align-bottom' : 'grow-0 shrink-0'" class="text-right truncate font-semibold leading-tight text-sm">{{ cardset }}</div>
|
||||
{% if quantity != None %}<div x-show="true" x-transition.duration.500ms x-cloak :class="badgeExpanded ? 'row-start-1 col-start-4 justify-self-end -me-0.5' : 'grow-0 shrink-0'" class="relative w-fit ps-1"><div class="card-quantity-badge relative bg-gray-600 text-white text-sm font-semibold rounded-full text-center size-max px-1.5">{{ quantity }}</div></div>{% endif %}
|
||||
{% if not expanded %}
|
||||
<div class="relative block m-1">
|
||||
<div class="flex flex-row items-center h-[32px] p-1.5 w-40 text-white shadow-lg" style="{{ style }}">
|
||||
<div class="grow truncate text-ellipsis font-semibold leading-tight text-sm">{{ name }}</div>
|
||||
<div class="grow-0 shrink-0 text-right truncate font-semibold leading-tight text-sm">{{ cardset }}</div>
|
||||
{% if quantity != None %}<div class="grow-0 shrink-0 relative w-fit ps-1">
|
||||
<div class="card-quantity-badge relative bg-gray-600 text-white text-sm font-semibold rounded-full text-center size-max px-1.5">{{ quantity }}</div></div>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="relative inline-block m-1">
|
||||
<div class="relative block m-1">
|
||||
<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 col-span-3 truncate text-ellipsis font-semibold leading-tight text-sm">{{ name }}</div>
|
||||
<div class="row-start-2 col-start-1 col-span-3 truncate align-bottom text-xs">{{ rarity }}</div>
|
||||
<div class="row-start-2 col-start-4 col-span-1 align-bottom text-right truncate font-semibold leading-tight text-sm">{{ cardset }}</div>
|
||||
{% if quantity != None %}<div class="row-start-1 col-start-4 justify-self-end -me-0.5 relative w-fit ps-1"><div class="card-quantity-badge relative bg-gray-600 text-white text-sm font-semibold rounded-full text-center size-max px-1.5">{{ quantity }}</div></div>{% endif %}
|
||||
<div class="row-start-1 col-start-1 col-span-3 truncate text-ellipsis self-start font-semibold leading-tight text-sm">{{ name }}</div>
|
||||
<div class="row-start-2 col-start-1 col-span-3 truncate self-end text-xs">{{ rarity }}</div>
|
||||
<div class="row-start-2 col-start-4 col-span-1 self-end text-right truncate font-semibold leading-tight text-sm">{{ cardset }}</div>
|
||||
{% if quantity != None %}<div class="row-start-1 col-start-4 self-start justify-self-end -me-0.5 relative w-fit ps-1"><div class="card-quantity-badge relative bg-gray-600 text-white text-sm font-semibold rounded-full text-center size-max px-1.5">{{ quantity }}</div></div>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
|
@ -1,104 +1,89 @@
|
|||
{% load gravatar card_badge cache %}
|
||||
{% url 'trade_offer_detail' pk=offer_pk as trade_offer_detail_url %}
|
||||
|
||||
{% cache 60 trade_offer offer_pk %}
|
||||
<div class="trade-offer-card m-2 h-full w-auto flex justify-center">
|
||||
<div x-data="tradeOfferCard()" x-init="defaultExpanded = {{expanded|lower}}; badgeExpanded = defaultExpanded; flipped = {{flipped|lower}}" class="trade-offer-card my-auto"
|
||||
@toggle-all.window="setBadge($event.detail.expanded)">
|
||||
<div x-data="tradeOfferCard()" x-init="flipped = {{flipped|lower}}; show_back = {{flipped|lower}}" class="trade-offer-card my-auto">
|
||||
<div {% if request_path != trade_offer_detail_url %}@click="window.location.href = '{{ trade_offer_detail_url }}'"{% endif %} class="no-underline block flip-container{% if request_path != trade_offer_detail_url %} cursor-pointer{% endif %}" style="perspective: 1000px;">
|
||||
<div x-ref="container" x-show="!collapsed" class="overflow-hidden 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" :class="{'rotate-y-180': flipped}">
|
||||
|
||||
<!-- Flip container providing perspective -->
|
||||
<div class="flip-container" style="perspective: 1000px;">
|
||||
<!--
|
||||
The rotating element (.flip-inner) now uses CSS Grid to stack its children in a single cell.
|
||||
Persistent border, shadow, and rounding are applied here and the card rotates entirely.
|
||||
-->
|
||||
<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-700 ease-in-out"
|
||||
:class="{'rotate-y-180': flipped}">
|
||||
|
||||
<!-- Front Face: Trade Offer -->
|
||||
<!-- Using grid placement classes (col-start-1 row-start-1) ensures both faces overlap -->
|
||||
<div x-show="!flipped" class="flip-face front col-start-1 row-start-1 grid grid-cols-1 auto-rows-min gap-2 content-between">
|
||||
<!-- Header -->
|
||||
<div class="flip-face-header self-start">
|
||||
<a href="{% url 'trade_offer_detail' pk=offer_pk %}" class="no-underline block">
|
||||
<!-- Set this container as relative to position the avatar absolutely -->
|
||||
<div class="relative mt-6 mb-4 mx-2 sm:mx-4">
|
||||
<!-- Two-column grid for the labels -->
|
||||
<div class="grid grid-cols-2">
|
||||
<span class="text-sm font-semibold text-center">Has</span>
|
||||
<span class="text-sm font-semibold text-center">Wants</span>
|
||||
</div>
|
||||
<!-- The avatar is placed absolutely and centered -->
|
||||
<div class="absolute inset-x-0 top-1/2 transform -translate-y-1/2 flex justify-center">
|
||||
<div class="avatar">
|
||||
<div class="w-10 rounded-full">
|
||||
{{ initiated_by_email|gravatar:40 }}
|
||||
<!-- Front Face: Trade Offer -->
|
||||
<!-- Using grid placement classes (col-start-1 row-start-1) ensures both faces overlap -->
|
||||
<div x-ref="front" x-show="!show_back" x-cloak class="flip-face front col-start-1 row-start-1 grid grid-cols-1 auto-rows-min gap-2 content-between">
|
||||
<!-- Header -->
|
||||
<div class="flip-face-header self-start">
|
||||
<!-- Set this container as relative to position the avatar absolutely -->
|
||||
<div class="relative mt-6 mb-4 mx-2 sm:mx-4">
|
||||
<!-- Two-column grid for the labels -->
|
||||
<div class="grid grid-cols-2">
|
||||
<span class="text-sm font-semibold text-center">Has</span>
|
||||
<span class="text-sm font-semibold text-center">Wants</span>
|
||||
</div>
|
||||
<!-- The avatar is placed absolutely and centered -->
|
||||
<div class="absolute inset-x-0 top-1/2 transform -translate-y-1/2 flex justify-center">
|
||||
<div class="avatar">
|
||||
<div class="w-10 rounded-full">
|
||||
{{ initiated_by_email|gravatar:40 }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Main Trade Offer Row -->
|
||||
<div class="flip-face-body self-start">
|
||||
{% if not flipped %}
|
||||
<div class="px-2 main-badges pb-0">
|
||||
<!-- Normal mode: just use an outer grid with 2 columns -->
|
||||
<div class="flex flex-row justify-around">
|
||||
<!-- Has Side -->
|
||||
<div class="flex flex-col">
|
||||
{% for card in have_cards_available %}
|
||||
<a href="{% url 'cards:card_detail' card.pk %}">
|
||||
{% card_badge card.card card.quantity %}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<!-- Wants Side -->
|
||||
<div class="flex flex-col">
|
||||
{% for card in want_cards_available %}
|
||||
<a href="{% url 'cards:card_detail' card.pk %}">
|
||||
{% card_badge card.card card.quantity %}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<!-- Main Trade Offer Row -->
|
||||
<div class="flip-face-body self-start">
|
||||
{% if not flipped %}
|
||||
<a href="{% url 'trade_offer_detail' pk=offer_pk %}" class="no-underline block">
|
||||
<div class="px-2 main-badges pb-0">
|
||||
<!-- Normal mode: just use an outer grid with 2 columns -->
|
||||
<div class="flex flex-row justify-around">
|
||||
<!-- Has Side -->
|
||||
<div class="flex flex-col gap-y-2">
|
||||
{% for card in have_cards_available %}
|
||||
{% card_badge card.card card.quantity %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
<!-- Wants Side -->
|
||||
<div class="flex flex-col gap-y-2">
|
||||
{% for card in want_cards_available %}
|
||||
{% card_badge card.card card.quantity %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
{% else %}
|
||||
<div class="flex justify-center mt-8">
|
||||
<div class="flex justify-center mb-1">
|
||||
<div class="text-sm">
|
||||
All cards have been accepted.
|
||||
All cards have been traded.
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="flip-face-footer self-end">
|
||||
<div class="flex justify-between px-2 pb-2">
|
||||
<div @click="badgeExpanded = !badgeExpanded" class="flex justify-center h-5 cursor-pointer tooltip tooltip-right" data-tip="Expand/Collapse">
|
||||
<svg x-bind:class="{ 'rotate-180': badgeExpanded }"
|
||||
class="transition-transform duration-500 h-5 w-5 cursor-pointer"
|
||||
xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"
|
||||
d="M19 9l-7 7-7-7" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="text-gray-500 text-sm tooltip tooltip-right" data-tip="ID: {{ offer_hash }}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
|
||||
stroke="currentColor" class="size-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round"
|
||||
d="m11.25 11.25.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 class="cursor-pointer text-gray-500 tooltip tooltip-left" data-tip="Flip to Accepted Trades" @click="flipped = true; acceptanceExpanded = defaultExpanded">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M3 8.689c0-.864.933-1.406 1.683-.977l7.108 4.061a1.125 1.125 0 0 1 0 1.954l-7.108 4.061A1.125 1.125 0 0 1 3 16.811V8.69ZM12.75 8.689c0-.864.933-1.406 1.683-.977l7.108 4.061a1.125 1.125 0 0 1 0 1.954l-7.108 4.061a1.125 1.125 0 0 1-1.683-.977V8.69Z" />
|
||||
</div>
|
||||
<div class="flip-face-footer self-end">
|
||||
<div class="flex justify-between px-2 pb-2">
|
||||
<div class="text-gray-500 text-sm tooltip tooltip-right" data-tip="ID: {{ offer_hash }}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
|
||||
stroke="currentColor" class="size-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round"
|
||||
d="m11.25 11.25.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 class="text-xs">{{ rarity_icon }}</div>
|
||||
<div class="cursor-pointer text-gray-500 tooltip tooltip-left" data-tip="Flip to Accepted Trades" @click.stop.prevent="flipWithCollapse()">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M3 8.689c0-.864.933-1.406 1.683-.977l7.108 4.061a1.125 1.125 0 0 1 0 1.954l-7.108 4.061A1.125 1.125 0 0 1 3 16.811V8.69ZM12.75 8.689c0-.864.933-1.406 1.683-.977l7.108 4.061a1.125 1.125 0 0 1 0 1.954l-7.108 4.061a1.125 1.125 0 0 1-1.683-.977V8.69Z" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Back Face: Acceptances View -->
|
||||
<!-- Placed in the same grid cell as the front face -->
|
||||
<div x-show="flipped" class="flip-face back col-start-1 row-start-1 grid grid-cols-1 auto-rows-min gap-2 content-between" style="transform: rotateY(180deg);">
|
||||
<div class="self-start">
|
||||
<a href="{% url 'trade_offer_detail' pk=offer_pk %}" class="no-underline block">
|
||||
<!-- Back Face: Acceptances View -->
|
||||
<!-- Placed in the same grid cell as the front face -->
|
||||
<div x-ref="back" x-show="show_back" x-cloak class="flip-face back col-start-1 row-start-1 grid grid-cols-1 auto-rows-min gap-2 content-between" style="transform: rotateY(180deg);">
|
||||
<div class="self-start">
|
||||
<div class="relative mt-6 mb-4 mx-2 sm:mx-4">
|
||||
<div class="grid grid-cols-2">
|
||||
<span class="text-sm font-semibold text-center">Has</span>
|
||||
|
|
@ -113,68 +98,65 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="self-start">
|
||||
<div class="px-2 pb-0">
|
||||
<div class="space-y-3">
|
||||
{% for acceptance in acceptances %}
|
||||
<a href="{% url 'trade_acceptance_update' pk=acceptance.pk %}" class="no-underline block mb-2"
|
||||
data-tooltip-html='<div class="flex items-center space-x-2">
|
||||
<div class="avatar">
|
||||
<div class="w-10 rounded-full">
|
||||
{{ acceptance.accepted_by.user.email|gravatar:"40" }}
|
||||
</div>
|
||||
<div class="self-start">
|
||||
<div class="px-2 pb-0">
|
||||
<div class="space-y-3">
|
||||
{% for acceptance in acceptances %}
|
||||
<a href="{% url 'trade_acceptance_update' pk=acceptance.pk %}" class="no-underline block mb-2"
|
||||
data-tooltip-html='<div class="flex items-center space-x-2">
|
||||
<div class="avatar">
|
||||
<div class="w-10 rounded-full">
|
||||
{{ acceptance.accepted_by.user.email|gravatar:"40" }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<span class="text-sm">Accepted by: {{ acceptance.accepted_by.user.username }}</span>
|
||||
<span class="text-sm">State: {{ acceptance.state }}</span>
|
||||
<span class="text-sm">Acceptance ID: {{ acceptance.hash }}</span>
|
||||
</div>
|
||||
</div>'>
|
||||
<div class="grid grid-cols-2 gap-1 justify-items-center">
|
||||
<div class="flex flex-col">
|
||||
<span class="text-sm">Accepted by: {{ acceptance.accepted_by.user.username }}</span>
|
||||
<span class="text-sm">State: {{ acceptance.state }}</span>
|
||||
<span class="text-sm">Acceptance ID: {{ acceptance.hash }}</span>
|
||||
</div>
|
||||
</div>'>
|
||||
<div class="grid grid-cols-2 justify-items-center">
|
||||
{% card_badge acceptance.requested_card %}
|
||||
{% card_badge acceptance.offered_card %}
|
||||
</div>
|
||||
</a>
|
||||
{% endfor %}
|
||||
{% empty %}
|
||||
<div class="flex justify-center items-center">
|
||||
<div class="text-sm">
|
||||
No trades yet.
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-between px-2 pb-2 self-end">
|
||||
<!-- Back-to-front flip button -->
|
||||
<div class="text-gray-500 cursor-pointer tooltip tooltip-right" data-tip="Flip to Offered Cards" @click="flipped = false; badgeExpanded = defaultExpanded">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M21 16.811c0 .864-.933 1.406-1.683.977l-7.108-4.061a1.125 1.125 0 0 1 0-1.954l7.108-4.061A1.125 1.125 0 0 1 21 8.689v8.122ZM11.25 16.811c0 .864-.933 1.406-1.683.977l-7.108-4.061a1.125 1.125 0 0 1 0-1.954l7.108-4.061a1.125 1.125 0 0 1 1.683.977v8.122Z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="px-1 text-center">
|
||||
<span class="text-sm font-semibold">
|
||||
Accepted Trades ({{ acceptances|length }})
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex justify-center h-5 tooltip tooltip-left" data-tip="Expand/Collapse">
|
||||
<svg @click="badgeExpanded = !badgeExpanded"
|
||||
x-bind:class="{ 'rotate-180': badgeExpanded }"
|
||||
class="transition-transform duration-500 h-5 w-5 cursor-pointer"
|
||||
xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"
|
||||
d="M19 9l-7 7-7-7" />
|
||||
</svg>
|
||||
<div class="flex justify-between px-2 pb-2 self-end items-center">
|
||||
<!-- Back-to-front flip button -->
|
||||
<div class="text-gray-500 cursor-pointer tooltip tooltip-right" data-tip="Flip to Offered Cards" @click.stop.prevent="flipWithCollapse()">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M21 16.811c0 .864-.933 1.406-1.683.977l-7.108-4.061a1.125 1.125 0 0 1 0-1.954l7.108-4.061A1.125 1.125 0 0 1 21 8.689v8.122ZM11.25 16.811c0 .864-.933 1.406-1.683.977l-7.108-4.061a1.125 1.125 0 0 1 0-1.954l7.108-4.061a1.125 1.125 0 0 1 1.683.977v8.122Z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="text-xs">{{ rarity_icon }}</div>
|
||||
<div class="px-1 text-center">
|
||||
<span class="text-xs text-gray-500">
|
||||
({{ acceptances|length }})
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<style>
|
||||
/* Ensure proper 3D transformations on the rotating element */
|
||||
.flip-inner {
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
/* Hide the back face of each card side */
|
||||
.flip-face {
|
||||
.flip-face-back-hidden {
|
||||
backface-visibility: hidden;
|
||||
-webkit-backface-visibility: hidden;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@
|
|||
<!-- Has Side (inner grid of 2 columns) -->
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
{% for card in have_cards_available %}
|
||||
{% card_badge card.card card.quantity static=True %}
|
||||
{% card_badge card.card card.quantity %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
<!-- Vertical Divider -->
|
||||
|
|
@ -55,7 +55,7 @@
|
|||
<!-- Wants Side (inner grid of 2 columns) -->
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
{% for card in want_cards_available %}
|
||||
{% card_badge card.card card.quantity static=True %}
|
||||
{% card_badge card.card card.quantity %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -65,13 +65,17 @@
|
|||
<!-- Has Side -->
|
||||
<div class="flex flex-col gap-2">
|
||||
{% for card in have_cards_available %}
|
||||
{% card_badge card.card card.quantity static=True %}
|
||||
{% card_badge card.card card.quantity %}
|
||||
{% empty %}
|
||||
<div class="text-xs text-center mb-2 ms-3">None left.</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<!-- Wants Side -->
|
||||
<div class="flex flex-col gap-2">
|
||||
{% for card in want_cards_available %}
|
||||
{% card_badge card.card card.quantity static=True %}
|
||||
{% card_badge card.card card.quantity %}
|
||||
{% empty %}
|
||||
<div class="text-xs text-center mb-2{% if expanded %} ms-8{% else %} me-4{% endif %}">None left.</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ from django import template
|
|||
register = template.Library()
|
||||
|
||||
@register.inclusion_tag('templatetags/trade_offer.html', takes_context=True)
|
||||
def render_trade_offer(context, offer, expanded=False):
|
||||
def render_trade_offer(context, offer):
|
||||
"""
|
||||
Renders a trade offer including detailed trade acceptance information.
|
||||
Freezes the through-model querysets to avoid extra DB hits.
|
||||
|
|
@ -33,7 +33,6 @@ def render_trade_offer(context, offer, expanded=False):
|
|||
|
||||
return {
|
||||
'offer_pk': offer.pk,
|
||||
'expanded': expanded,
|
||||
'flipped': flipped, # new flag to control the default face
|
||||
'offer_hash': offer.hash,
|
||||
'rarity_icon': offer.rarity_icon,
|
||||
|
|
@ -45,6 +44,7 @@ def render_trade_offer(context, offer, expanded=False):
|
|||
'in_game_name': offer.initiated_by.in_game_name,
|
||||
'friend_code': offer.initiated_by.friend_code,
|
||||
'num_cards_available': len(have_cards_available) + len(want_cards_available),
|
||||
'request_path': context.get("request").path,
|
||||
}
|
||||
|
||||
@register.inclusion_tag('templatetags/trade_acceptance.html', takes_context=True)
|
||||
|
|
@ -97,8 +97,8 @@ def render_trade_offer_png(context, offer, show_friend_code=False):
|
|||
]
|
||||
|
||||
num_cards = max(len(have_cards_available), len(want_cards_available))
|
||||
image_height = (num_cards * 52) + ((num_cards - 1) * 8) + 106
|
||||
# cards | padding between cards | header/footer
|
||||
image_height = (num_cards * 40) + 106
|
||||
# cards incl pad + header/footer
|
||||
if (len(have_cards_available) + len(want_cards_available)) >= 4:
|
||||
image_width = (4 * 160) + 160
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -498,9 +498,9 @@ class TradeOfferPNGView(View):
|
|||
trade_offer = get_object_or_404(TradeOffer, pk=kwargs['pk'])
|
||||
|
||||
# If the image is already generated and stored, serve it directly.
|
||||
if trade_offer.image:
|
||||
trade_offer.image.open()
|
||||
return HttpResponse(trade_offer.image.read(), content_type="image/png")
|
||||
# if trade_offer.image:
|
||||
# trade_offer.image.open()
|
||||
# return HttpResponse(trade_offer.image.read(), content_type="image/png")
|
||||
|
||||
# Acquire PostgreSQL advisory lock to prevent concurrent generation.
|
||||
from django.db import connection
|
||||
|
|
@ -509,10 +509,10 @@ class TradeOfferPNGView(View):
|
|||
cursor.execute("SELECT pg_advisory_lock(%s)", [lock_key])
|
||||
try:
|
||||
# Double-check if the image was generated while waiting for the lock.
|
||||
trade_offer.refresh_from_db()
|
||||
if trade_offer.image:
|
||||
trade_offer.image.open()
|
||||
return HttpResponse(trade_offer.image.read(), content_type="image/png")
|
||||
# trade_offer.refresh_from_db()
|
||||
# if trade_offer.image:
|
||||
# trade_offer.image.open()
|
||||
# return HttpResponse(trade_offer.image.read(), content_type="image/png")
|
||||
|
||||
tag_context = render_trade_offer_png(
|
||||
{'request': request}, trade_offer, show_friend_code=True
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue