{# Reusable marketplace listing card. Usage: {% from "components/listing_card.html" import listing_card %} {{ listing_card(listing, actions=['view', 'edit', 'delete'], show_status=true, meta=['condition', 'date']) }} Parameters: listing - a Listing model instance (required). actions - ordered list of action keys to render in the footer. Supported: 'view', 'edit', 'delete', 'quickview', 'remove_saved'. 'edit'/'delete'/'remove_saved' are rendered "soft-disabled" (visible, Coming-Soon toast) until their features ship. show_status - show the listing status badge (top-right). Default: false. meta - ordered list of meta rows under the price. Supported: 'condition', 'location', 'date'. Default: ['condition', 'date']. The component never fabricates data: it only renders fields present on the listing. Keep page-specific wiring (modals, etc.) on the page, not here. #} {% from "components/premium_badge.html" import premium_badge_pill, featured_badge %} {% from "components/badges.html" import mk_badge %} {% from "components/reputation.html" import rep_inline %} {% from "components/trust_badges.html" import trust_badge_top %} {% macro listing_card(listing, actions=['view'], show_status=false, meta=['condition', 'date'], saved_at=none, favorite=false, premium_ids=none, section_badge=none, reputations=none, badges=none) %} {% set cover = listing.images[0] if listing.images else None %} {% set detail_url = url_for('marketplace.listing_detail', public_id=listing.public_id) %}
{% if cover %} {{ listing.title }} {% else %}
No image available
{% endif %}
{# Single top overlay: a flex row spanning the image. The left cluster holds the category + section badges (each sized to its content); the right cluster holds the status badge and the fixed favorite button. justify-content: space-between guarantees the badge and the heart can never overlap, for any badge type or screen size — no margin hacks. #}
{{ listing.category.name }} {% if section_badge %}{{ mk_badge(section_badge) }}{% endif %}
{% if show_status %} {{ listing.status.value|title }} {% endif %} {% if favorite %} {% if current_user.is_authenticated and listing.seller_id != current_user.id %}
{% elif not current_user.is_authenticated %} {% endif %} {% endif %}

{{ listing.title }}

₹{{ "{:,.2f}".format(listing.price) }}
{# Seller reputation — read from the precomputed cache map (one query/page, no N+1). Absent row / no reviews renders a subtle "New Seller". #} {% if reputations is not none %}
{{ rep_inline(reputations.get(listing.seller_id)) }} {# Highest-priority badge only, to keep the card compact. #} {% if badges is not none %}{{ trust_badge_top(badges.get(listing.seller_id)) }}{% endif %}
{% endif %} {# Grids pass a precomputed `premium_ids` set (one query/page) so we check the seller_id column and never load the seller or query per card. Without it (single-card use), fall back to the permissions helper. #} {% set seller_is_premium = (listing.seller_id in premium_ids) if premium_ids is not none else show_premium_badge(listing.seller) %} {% set listing_featured = is_featured_now(listing) %} {# In discovery rows the overlay section_badge already conveys the listing's status, so the in-body Featured badge is suppressed there — a card never stacks a section badge and a Featured badge at once. #} {% set show_featured = listing_featured and not section_badge %} {% if show_featured or seller_is_premium %}
{% if show_featured %}{{ featured_badge('sm') }}{% endif %} {% if seller_is_premium %}{{ premium_badge_pill('Premium Seller', 'sm') }}{% endif %}
{% endif %} {% if meta or saved_at %}
    {% if 'condition' in meta %}
  • {{ listing.condition.value|title }}
  • {% endif %} {% if 'location' in meta %}
  • {{ listing.location or 'On campus' }}
  • {% endif %} {% if 'date' in meta %}
  • Listed
  • {% endif %} {% if saved_at %}
  • Saved
  • {% endif %}
{% endif %} {% if actions %}
{% if 'view_details' in actions %} View Details {% endif %} {% if 'view' in actions %} View {% endif %} {% if 'quickview' in actions %} {% endif %} {% if 'edit' in actions %} {% endif %} {% if 'delete' in actions %} {% endif %} {% if 'feature' in actions and listing.status.value == 'available' %} {% if can_feature_listing(current_user) %} {% if listing_featured %} {% set days_left = featured_days_left(listing) %}
Expires in {{ days_left }} day{{ '' if days_left == 1 else 's' }} Change Featured
{% else %}
{% endif %} {% else %} Upgrade to Premium Premium {% endif %} {% endif %} {% if 'remove_saved' in actions %}
{% endif %}
{% endif %}
{% endmacro %}