06/15 Phase 3 codes

This commit is contained in:
2026-06-15 14:19:14 -04:00
parent c2064b84b4
commit 60526262f0
20 changed files with 802 additions and 7 deletions
+5
View File
@@ -16,6 +16,11 @@
{% if current_user.is_authenticated %}
<a href="{{ url_for('listings.create') }}">{{ _('Post') }}</a>
<a href="{{ url_for('listings.mine') }}">{{ _('My listings') }}</a>
<a href="{{ url_for('messaging.my_favorites') }}">{{ _('Saved') }}</a>
<a href="{{ url_for('messaging.inbox') }}" class="msg-link">
{{ _('Messages') }}
{% if unread_count %}<span class="badge-count">{{ unread_count }}</span>{% endif %}
</a>
<span class="hi">{{ current_user.display_name }}</span>
<a href="{{ url_for('auth.logout') }}">{{ _('Sign out') }}</a>
{% else %}
+14 -1
View File
@@ -52,7 +52,20 @@
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"><button class="btn danger" type="submit">{{ _('Delete') }}</button>
</form>
{% else %}
<p class="muted small">{{ _('Messaging arrives in Phase 3.') }}</p>
{% if current_user.is_authenticated %}
<a class="btn" href="{{ url_for('messaging.start_conversation', listing_id=listing.id) }}">
{{ _('Contact seller') }}
</a>
<form method="post"
action="{{ url_for('messaging.toggle_favorite', listing_id=listing.id) }}">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<button class="btn ghost" type="submit">{{ _('♥ Save listing') }}</button>
</form>
{% else %}
<a class="btn" href="{{ url_for('auth.login') }}?next={{ request.path }}">
{{ _('Sign in to contact') }}
</a>
{% endif %}
{% endif %}
</aside>
</article>
+37
View File
@@ -0,0 +1,37 @@
{% extends "base.html" %}
{% from "auth/_macros.html" import field %}
{% block title %}{{ _('Conversation') }}{% endblock %}
{% block content %}
<div class="conv-wrap">
<div class="conv-header card">
<a class="muted small" href="{{ url_for('messaging.inbox') }}">&larr; {{ _('Inbox') }}</a>
<h3>{{ conv.listing.title }}</h3>
<span class="muted small">{{ _('with') }} {{ other.display_name }}</span>
{% if not reveal %}
<p class="mask-notice muted small">
{{ _('Phone numbers, emails, and links are hidden until your account is trusted. Verify your email and build trust to unlock contact info.') }}
</p>
{% endif %}
</div>
<div class="thread">
{% for msg, body in masked_messages %}
<div class="bubble {{ 'mine' if msg.sender_id == current_user.id else 'theirs' }}">
<div class="bubble-body">{{ body | replace('\n','<br>') | safe }}</div>
<div class="bubble-meta muted small">
{{ msg.sender.display_name }} · {{ msg.created_at.strftime('%b %d %H:%M') }}
{% if msg.sender_id == current_user.id and msg.is_read %}· {{ _('Read') }}{% endif %}
</div>
</div>
{% endfor %}
</div>
<div class="reply-box card">
<form method="post" novalidate>
{{ form.hidden_tag() }}
{{ field(form.body) }}
{{ form.submit(class="btn") }}
</form>
</div>
</div>
{% endblock %}
+34
View File
@@ -0,0 +1,34 @@
{% extends "base.html" %}
{% block title %}{{ _('Saved listings') }}{% endblock %}
{% block content %}
<div class="card">
<h2>{{ _('Saved listings') }}</h2>
{% if not pagination.items %}
<p class="muted">{{ _('No saved listings yet.') }}</p>
{% endif %}
<div class="grid">
{% for fav in pagination.items %}
{% set l = fav.listing %}
<a class="tile card" href="{{ url_for('listings.detail', listing_id=l.id) }}">
{% if l.cover %}
<img class="thumb" src="{{ url_for('listings.media', rel=l.cover.thumb_path) }}" alt="">
{% else %}
<div class="thumb noimg">{{ _('No photo') }}</div>
{% endif %}
<div class="tile-body">
<div class="tile-title">{{ l.title }}</div>
<div class="muted small">{{ l.price_display or '—' }}</div>
</div>
</a>
{% endfor %}
</div>
<div class="pager">
{% if pagination.has_prev %}
<a href="{{ url_for('messaging.my_favorites', page=pagination.prev_num) }}">&larr; {{ _('Prev') }}</a>
{% endif %}
{% if pagination.has_next %}
<a href="{{ url_for('messaging.my_favorites', page=pagination.next_num) }}">{{ _('Next') }} &rarr;</a>
{% endif %}
</div>
</div>
{% endblock %}
+46
View File
@@ -0,0 +1,46 @@
{% extends "base.html" %}
{% block title %}{{ _('Messages') }}{% endblock %}
{% block content %}
<div class="card">
<div class="inbox-head">
<h2>{{ _('Messages') }}</h2>
{% if unread_total %}<span class="badge-count">{{ unread_total }}</span>{% endif %}
</div>
{% if not pagination.items %}
<p class="muted">{{ _('No conversations yet.') }}</p>
{% endif %}
<ul class="conv-list">
{% for conv in pagination.items %}
{% set unread = conv.unread_count(current_user) %}
{% set other = conv.other_party(current_user) %}
<li class="conv-row {{ 'unread' if unread }}">
<a href="{{ url_for('messaging.conversation', conv_id=conv.id) }}">
<div class="conv-meta">
<span class="conv-who">{{ other.display_name }}</span>
{% if unread %}<span class="badge-count sm">{{ unread }}</span>{% endif %}
<span class="conv-time muted small">
{{ conv.last_message_at.strftime('%b %d') if conv.last_message_at else '' }}
</span>
</div>
<div class="conv-listing muted small">
{{ _('Re:') }} {{ conv.listing.title[:60] }}
</div>
{% if conv.messages %}
<div class="conv-preview muted small">
{{ conv.messages[-1].body[:80] }}…
</div>
{% endif %}
</a>
</li>
{% endfor %}
</ul>
<div class="pager">
{% if pagination.has_prev %}
<a href="{{ url_for('messaging.inbox', page=pagination.prev_num) }}">&larr; {{ _('Prev') }}</a>
{% endif %}
{% if pagination.has_next %}
<a href="{{ url_for('messaging.inbox', page=pagination.next_num) }}">{{ _('Next') }} &rarr;</a>
{% endif %}
</div>
</div>
{% endblock %}
+19
View File
@@ -0,0 +1,19 @@
{% extends "base.html" %}
{% from "auth/_macros.html" import field %}
{% block title %}{{ _('Contact seller') }}{% endblock %}
{% block content %}
<div class="card narrow">
<h2>{{ _('Contact seller') }}</h2>
<p class="muted">{{ _('Re:') }} <a href="{{ url_for('listings.detail', listing_id=listing.id) }}">{{ listing.title }}</a></p>
{% if not created %}
<p class="muted small">{{ _('You already have a conversation about this listing.') }}
<a href="{{ url_for('messaging.conversation', conv_id=conv.id) }}">{{ _('View it') }}</a>
</p>
{% endif %}
<form method="post" novalidate>
{{ form.hidden_tag() }}
{{ field(form.body) }}
{{ form.submit(class="btn") }}
</form>
</div>
{% endblock %}