Diff -- /var/www/vhosts/webstls.com/httpdocs/TEMPLATES/webstls_messages.html
Diff

/var/www/vhosts/webstls.com/httpdocs/TEMPLATES/webstls_messages.html

added on WebSTLs (webstls.com) at 2026-07-01 22:27:01

Added
+425
lines
Removed
-0
lines
Context
0
unchanged
Blobs
from
to 2691378773fc
Restore this content →
Unified diff
Naive LCS-based line diff. Additions in emerald, deletions in rose. Both sides decompressed live from BLOB_STORE.
1<div class="page-head">
2 <div>
3 <span class="page-eyebrow"><span class="dot"></span> Multi-platform inbox</span>
4 <h1 class="page-title">Messages, comments &amp; reviews</h1>
5 <p class="page-subtitle">Every comment, review, and DM from every platform. One inbox. No more juggling tabs.</p>
6 </div>
7 <div class="page-actions">
8 [if:$not_tutorial_mode]<a href="/messages.cgi?tutorial=1" class="btn btn-secondary"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>Sample Data View</a>[/if]
9 [if:$tutorial_mode]<a href="/messages.cgi" class="btn btn-secondary"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>Exit sample view</a>[/if]
10 [if:$has_messages][if:$not_tutorial_mode]
11 <form method="POST" action="/messages_action.cgi" style="display:inline">
12 <input type="hidden" name="action" value="mark_all_read">
13 <button type="submit" class="btn btn-secondary"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"/></svg>Mark all read</button>
14 </form>
15 [/if][/if]
16 <a href="/marketplaces.cgi" class="btn btn-primary">Connect platforms</a>
17 </div>
18</div>
19
20[if:$tutorial_mode]
21<div class="tutorial-banner">
22 <div class="tutorial-banner-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg></div>
23 <div class="tutorial-banner-body">
24 <div class="tutorial-banner-title">Tutorial &middot; Sample data only</div>
25 <div class="tutorial-banner-text">The five messages on the left, the open thread in the middle, and the reply panel are all example data &mdash; nothing here is from your real marketplaces or storefront. Use this to see how the inbox reads once you start getting comments and reviews.</div>
26 </div>
27 <a href="/messages.cgi" class="btn btn-secondary btn-sm">Exit sample view</a>
28</div>
29
30<div class="tutorial-intro">
31 <div class="tutorial-intro-eyebrow">A walkthrough of the multi-platform inbox</div>
32 <h2 class="tutorial-intro-title">Every comment and review, in one place.</h2>
33 <p class="tutorial-intro-text">A background worker checks each connected marketplace every 10 minutes and writes new comments and reviews into <code>external_comments</code> tagged with the platform name. Comments on your own WebSTLs storefront write here instantly with <code>platform_name='storefront'</code>. The four filter tabs at the top of the list (<strong>All</strong>, <strong>Unread</strong>, <strong>Flagged</strong>, <strong>Archived</strong>) all run off the same table with simple status filters.</p>
34 <p class="tutorial-intro-text">When you reply from this page, WebSTLs queues the reply for the source platform and posts it under your connected account &mdash; no copy-paste, no tab-juggling. Replies show inline under the original message with a <em>SENT</em>, <em>SENDING</em>, or <em>FAILED</em> pill so you always know what landed. Use the <strong>Flag</strong> button to mark a message for follow-up (refunds, complaints, urgent questions) and <strong>Archive</strong> to hide resolved threads without deleting them.</p>
35 <p class="tutorial-intro-text tutorial-intro-foot">Click <a href="/messages.cgi" class="text-brand fw-700">Exit sample view</a> to return to your real inbox, or <a href="/marketplaces.cgi" class="text-brand fw-700">connect a marketplace</a> to start populating it.</p>
36</div>
37[/if]
38
39<!-- Top-level Inbox / Reports tabs. Pill-style so the section
40 switch is impossible to miss. Moved above content so they're
41 always visible regardless of how big the empty state is. -->
42<style>
43 .mm-tabs { display:flex; gap:8px; margin-bottom:20px; }
44 .mm-tab {
45 display:inline-flex; align-items:center; gap:8px;
46 padding:11px 22px; height:42px;
47 border-radius:11px;
48 font-size:13px; font-weight:700;
49 letter-spacing:0.5px; text-transform:uppercase;
50 text-decoration:none;
51 border:1px solid var(--col-border);
52 background:var(--col-surface-2);
53 color:var(--col-text-2);
54 transition: background 0.15s, color 0.15s, border-color 0.15s, transform 0.12s, box-shadow 0.15s;
55 }
56 .mm-tab:hover {
57 background:var(--col-surface-3); color:var(--col-text);
58 border-color:rgba(59,130,246,0.40);
59 transform:translateY(-1px);
60 }
61 .mm-tab.active {
62 background:linear-gradient(135deg, rgba(59,130,246,0.30) 0%, rgba(99,102,241,0.22) 100%);
63 border-color:rgba(59,130,246,0.75);
64 color:#fff;
65 box-shadow:0 0 18px rgba(59,130,246,0.45);
66 }
67 .mm-tab svg { width:16px; height:16px; flex-shrink:0; opacity:0.85; }
68 .mm-tab.active svg { opacity:1; }
69</style>
70<div class="mm-tabs">
71 <a href="/messages.cgi" class="mm-tab[if:$mtab_inbox] active[/if]">
72 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
73 Inbox
74 </a>
75 <a href="/messages.cgi?tab=reports" class="mm-tab[if:$mtab_reports] active[/if]">
76 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 3v18h18"/><path d="M7 14l4-4 4 4 6-6"/></svg>
77 Reports
78 </a>
79</div>
80
81[if:$mtab_inbox]
82[if:$has_support_threads]
83<!-- Support threads: ALL recent threads with the WebSTLs team. Shows
84 even when read so the user always has a path into their support
85 history from the inbox; unread ones get the green NEW badge. -->
86<div style="background:linear-gradient(135deg, rgba(59,130,246,0.10), rgba(59,130,246,0.04));border:1px solid rgba(59,130,246,0.40);border-radius:12px;padding:14px 18px;margin-bottom:18px">
87 <div style="display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:8px">
88 <span style="display:inline-block;width:9px;height:9px;border-radius:50%;background:#3b82f6;box-shadow:0 0 6px rgba(59,130,246,0.8)"></span>
89 <span style="font-size:11px;letter-spacing:1.5px;text-transform:uppercase;font-weight:700;color:#93c5fd">Your support threads</span>
90 [if:$has_support_unread]<span style="font-size:11px;color:#6ee7b7;font-weight:700;margin-left:auto">$support_unread_count unread reply from the WebSTLs team</span>[/if]
91 [if:!$has_support_unread]<a href="/support.cgi?new=1" style="font-size:11px;color:#93c5fd;text-decoration:none;font-weight:700;margin-left:auto">+ New request</a>[/if]
92 </div>
93 <!-- Same compact row anatomy as the admin inbox: subject (truncating)
94 | status pill | unread badge | timestamp. Keeps padding tight so
95 this section fits well above the marketplace-comment inbox. -->
96 <style>
97 .us-thread { display:flex;align-items:center;gap:8px;padding:6px 12px;
98 background:var(--col-surface-2);border:1px solid var(--col-border);
99 border-radius:8px;text-decoration:none;color:var(--col-text);
100 min-height:32px;transition:border-color 0.12s, background 0.12s; }
101 .us-thread:hover { border-color:var(--col-accent); }
102 .us-thread-subj { font-size:13px;font-weight:600;color:var(--col-text);
103 flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:1.3; }
104 .us-pill { padding:1px 7px;border-radius:10px;font-size:10px;font-weight:700;
105 letter-spacing:0.4px;flex-shrink:0; }
106 .us-pill.st-needs { background:rgba(239,68,68,0.15);color:#f87171;border:1px solid rgba(239,68,68,0.32); }
107 .us-pill.st-waiting { background:rgba(245,158,11,0.15);color:#fbbf24;border:1px solid rgba(245,158,11,0.32); }
108 .us-pill.st-resolved { background:rgba(34,197,94,0.15);color:#4ade80;border:1px solid rgba(34,197,94,0.32); }
109 .us-pill.st-closed { background:rgba(148,163,184,0.15);color:#cbd5e1;border:1px solid rgba(148,163,184,0.32); }
110 .us-pill.st-open { background:rgba(59,130,246,0.18);color:#60a5fa;border:1px solid rgba(59,130,246,0.36); }
111 .us-thread-unread { min-width:18px;height:18px;padding:0 5px;border-radius:9px;
112 background:#10b981;color:#fff;font-size:10px;font-weight:800;
113 display:inline-flex;align-items:center;justify-content:center;flex-shrink:0; }
114 .us-thread-time { font-size:11px;color:var(--col-text-3);flex-shrink:0; }
115 </style>
116 <div style="display:flex;flex-direction:column;gap:2px">
117 [loop:@support_threads]
118 <a href="$loop1.href" class="us-thread" title="$loop1.subject -- $loop1.status_label">
119 <span class="us-thread-subj">$loop1.subject</span>
120 <span class="us-pill $loop1.pill_class">$loop1.status_label</span>
121 [if:$loop1.has_unread]<span class="us-thread-unread">$loop1.unread</span>[/if]
122 <span class="us-thread-time">$loop1.last_at</span>
123 </a>
124 [/loop]
125 </div>
126</div>
127[/if]
128
129[if:$no_messages]
130[if:$has_mp_connected]
131<!-- User has connected marketplaces but no comments yet. Show
132 compact "Connected" pill row + small "Connect more" hint
133 so they know which platforms are wired up and which they
134 could still add. -->
135<div style="background:var(--col-surface-1);border:1px solid var(--col-border);border-radius:12px;padding:14px 18px;margin-bottom:18px">
136 <div style="display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:10px">
137 <span style="display:inline-block;width:9px;height:9px;border-radius:50%;background:#10b981;box-shadow:0 0 6px rgba(16,185,129,0.7)"></span>
138 <span style="font-size:11px;letter-spacing:1.5px;text-transform:uppercase;font-weight:700;color:#6ee7b7">Connected &middot; $mp_connected_count</span>
139 <span style="font-size:11px;color:var(--col-text-3)">Waiting for comments &mdash; we check every 10 minutes.</span>
140 <a href="/marketplaces.cgi" style="margin-left:auto;font-size:11px;font-weight:700;color:#93c5fd;text-decoration:none">Manage &rarr;</a>
141 </div>
142 <div style="display:flex;flex-wrap:wrap;gap:6px;margin-bottom:[if:$has_mp_available]12px[/if][if:!$has_mp_available]0[/if]">
143 [loop:@mp_connected]
144 <span style="display:inline-flex;align-items:center;gap:5px;padding:4px 10px;background:rgba(16,185,129,0.16);border:1px solid rgba(16,185,129,0.45);border-radius:999px;font-size:12px;font-weight:600;color:#6ee7b7">
145 <svg viewBox="0 0 24 24" width="11" height="11" fill="none" stroke="currentColor" stroke-width="3"><polyline points="20 6 9 17 4 12"/></svg>
146 $loop1.name
147 </span>
148 [/loop]
149 </div>
150 [if:$has_mp_available]
151 <div style="display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding-top:10px;border-top:1px solid var(--col-border)">
152 <span style="font-size:10px;letter-spacing:1.5px;text-transform:uppercase;font-weight:700;color:var(--col-text-3);margin-right:4px">Connect more</span>
153 [loop:@mp_available]
154 <a href="/marketplaces.cgi" style="display:inline-flex;align-items:center;gap:4px;padding:3px 9px;background:var(--col-surface-2);border:1px solid var(--col-border);border-radius:999px;font-size:11px;font-weight:600;color:var(--col-text-2);text-decoration:none;transition:border-color 0.12s, color 0.12s">+ $loop1.name</a>
155 [/loop]
156 </div>
157 [/if]
158</div>
159[/if]
160[if:!$has_mp_connected]
161<!-- ===== Compact empty state for users with no connections yet. ===== -->
162<div style="background:var(--col-surface-1);border:1px solid var(--col-border);border-radius:12px;padding:18px 22px;margin-bottom:18px;display:flex;align-items:center;gap:18px;flex-wrap:wrap">
163 <div style="width:44px;height:44px;border-radius:11px;background:linear-gradient(140deg, rgba(124,58,237,0.20), rgba(59,130,246,0.20));border:1px solid rgba(124,58,237,0.42);display:grid;place-items:center;flex-shrink:0">
164 <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="1.8" style="color:var(--col-accent-bright)"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2Z"/></svg>
165 </div>
166 <div style="flex:1;min-width:240px">
167 <div style="font-family:var(--font-display);font-size:15px;color:#fff;font-weight:700;margin-bottom:2px">No marketplace comments yet</div>
168 <div style="font-size:12.5px;color:var(--col-text-2);line-height:1.55">Connect Cults3D / Gumroad / MyMiniFactory / Patreon and replies post back through one inbox. Comments on your WebSTLs storefront and replies from the WebSTLs support team also appear here automatically.</div>
169 </div>
170 <a href="/marketplaces.cgi" class="btn btn-primary" style="flex-shrink:0">Connect a platform</a>
171</div>
172[/if]
173[/if]
174[/if]
175
176[if:$mtab_reports]
177<!-- ===== Reports tab ===== -->
178[if:$has_reports_data]
179<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:14px;margin-bottom:18px">
180 <div style="background:var(--col-surface-1);border:1px solid var(--col-border);border-radius:12px;padding:16px 18px">
181 <div style="font-size:11px;font-weight:700;color:var(--col-text-3);letter-spacing:1.2px;text-transform:uppercase;margin-bottom:6px">Comments (30d)</div>
182 <div style="font-family:var(--font-display,sans-serif);font-size:28px;color:var(--col-text);line-height:1">$rep_total_30d</div>
183 </div>
184 <div style="background:var(--col-surface-1);border:1px solid var(--col-border);border-radius:12px;padding:16px 18px">
185 <div style="font-size:11px;font-weight:700;color:var(--col-text-3);letter-spacing:1.2px;text-transform:uppercase;margin-bottom:6px">Avg per day</div>
186 <div style="font-family:var(--font-display,sans-serif);font-size:28px;color:#93c5fd;line-height:1">$rep_avg_per_day</div>
187 </div>
188 <div style="background:var(--col-surface-1);border:1px solid var(--col-border);border-radius:12px;padding:16px 18px">
189 <div style="font-size:11px;font-weight:700;color:var(--col-text-3);letter-spacing:1.2px;text-transform:uppercase;margin-bottom:6px">Top platform</div>
190 <div style="font-family:var(--font-display,sans-serif);font-size:22px;color:#6ee7b7;line-height:1;text-transform:capitalize">$rep_top_platform</div>
191 </div>
192 <div style="background:var(--col-surface-1);border:1px solid var(--col-border);border-radius:12px;padding:16px 18px">
193 <div style="font-size:11px;font-weight:700;color:var(--col-text-3);letter-spacing:1.2px;text-transform:uppercase;margin-bottom:6px">Unread now</div>
194 <div style="font-family:var(--font-display,sans-serif);font-size:28px;color:#fbbf24;line-height:1">$count_unread</div>
195 </div>
196</div>
197<style>
198 .mc-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(420px,1fr)); gap:14px; margin-bottom:18px; }
199 .mc-card { position:relative; background:var(--col-surface-1); border:1px solid var(--col-border); border-radius:14px; padding:18px 20px; }
200 .mc-head { display:flex; align-items:baseline; justify-content:space-between; margin-bottom:10px; }
201 .mc-title { font-size:12px; letter-spacing:1.5px; text-transform:uppercase; font-weight:700; color:var(--col-text-3); }
202 .mc-sub { font-size:11px; color:var(--col-text-3); }
203 .ac-hot { cursor:pointer; }
204 .ac-tip {
205 position:absolute; pointer-events:none; opacity:0; transition:opacity 0.1s;
206 background:rgba(8,12,26,0.96); border:1px solid var(--col-border);
207 color:#fff; font-size:12px; padding:7px 11px; border-radius:7px;
208 white-space:nowrap; box-shadow:0 6px 18px rgba(0,0,0,0.45);
209 transform:translate(-50%, -100%); margin-top:-8px; z-index:50;
210 }
211 .ac-tip strong { color:var(--col-accent-bright); }
212</style>
213<div class="mc-grid">
214 <div class="mc-card" data-chart-id="vol">
215 <div class="mc-head">
216 <span class="mc-title">Comment volume &middot; last 30 days</span>
217 <span class="mc-sub" style="color:#93c5fd">$rep_total_30d total</span>
218 </div>
219 $chart_vol_html
220 <div class="ac-tip"></div>
221 </div>
222 <div class="mc-card">
223 <div class="mc-head">
224 <span class="mc-title">By platform &middot; last 30 days</span>
225 <span class="mc-sub">Top: $rep_top_platform</span>
226 </div>
227 $chart_plat_html
228 </div>
229</div>
230<script>
231(function () {
232 document.querySelectorAll('.mc-card').forEach(function (card) {
233 var svg = card.querySelector('.ac-svg');
234 var tip = card.querySelector('.ac-tip');
235 var guide= card.querySelector('.ac-guide');
236 var dot = card.querySelector('.ac-dot');
237 if (!svg || !tip) return;
238 var vb = svg.viewBox.baseVal;
239 function showAt(hot) {
240 var x = parseFloat(hot.getAttribute('data-x'));
241 var y = parseFloat(hot.getAttribute('data-y'));
242 if (guide) { guide.setAttribute('x1', x); guide.setAttribute('x2', x); guide.setAttribute('opacity', 0.55); }
243 if (dot) { dot.setAttribute('cx', x); dot.setAttribute('cy', y); dot.setAttribute('opacity', 1); }
244 var rect = svg.getBoundingClientRect();
245 var domX = (x / vb.width) * rect.width;
246 var domY = (y / vb.height) * rect.height;
247 tip.style.left = domX + 'px';
248 tip.style.top = domY + 'px';
249 tip.innerHTML = '<strong>' + hot.getAttribute('data-value') + '</strong> on ' + hot.getAttribute('data-label');
250 tip.style.opacity = '1';
251 }
252 function hide() {
253 tip.style.opacity = '0';
254 if (guide) guide.setAttribute('opacity', 0);
255 if (dot) dot.setAttribute('opacity', 0);
256 }
257 card.querySelectorAll('.ac-hot').forEach(function (hot) {
258 hot.addEventListener('mouseenter', function () { showAt(hot); });
259 hot.addEventListener('mouseleave', hide);
260 hot.addEventListener('click', function () {
261 var iso = hot.getAttribute('data-iso');
262 if (iso) location.href = '/messages.cgi?day=' + encodeURIComponent(iso);
263 });
264 });
265 });
266})();
267</script>
268[/if]
269[if:!$has_reports_data]
270<div style="background:var(--col-surface-1);border:1px solid var(--col-border);border-radius:14px;padding:28px 24px;text-align:center;color:var(--col-text-2)">
271 <div style="font-size:14px;color:var(--col-text);font-weight:600;margin-bottom:6px">No data to chart yet</div>
272 <div style="font-size:13px">Once comments and reviews start flowing in from your connected platforms, this page will show trends over time. <a href="/marketplaces.cgi" style="color:var(--col-accent-bright)">Connect a platform &rarr;</a></div>
273</div>
274[/if]
275[/if]
276
277[if:$mtab_inbox]
278[if:$has_messages]
279<style>
280 /* Messages-page-only: the four filter tabs (All / Unread / Flagged /
281 Archived) need to fit on a single line inside the ~340px list
282 column. Tight padding + smaller font keeps every tab visible. */
283 .msg-tabs { flex-wrap: nowrap; gap: 2px; overflow-x: auto; }
284 .msg-tabs .tab {
285 padding: 6px 7px;
286 font-size: 11px;
287 white-space: nowrap;
288 flex-shrink: 0;
289 }
290 .msg-tabs .tab .msg-count {
291 margin-left: 3px;
292 font-size: 10px;
293 opacity: 0.75;
294 }
295</style>
296<div class="dash-grid" style="grid-template-columns:340px 1fr;gap:16px">
297
298 <!-- ===== List ===== -->
299 <div class="module" style="padding:0;overflow:hidden;align-self:flex-start">
300 <div class="module-head">
301 <div class="tabs msg-tabs" style="margin:0">
302 <a href="/messages.cgi?filter=all" class="tab[if:$is_filter_all] active[/if]" style="text-decoration:none">All<span class="msg-count">$count_all</span></a>
303 <a href="/messages.cgi?filter=unread" class="tab[if:$is_filter_unread] active[/if]" style="text-decoration:none">Unread<span class="msg-count">$count_unread</span></a>
304 <a href="/messages.cgi?filter=flagged" class="tab[if:$is_filter_flagged] active[/if]" style="text-decoration:none">Flagged<span class="msg-count">$count_flagged</span></a>
305 <a href="/messages.cgi?filter=archived" class="tab[if:$is_filter_archived] active[/if]" style="text-decoration:none">Archived<span class="msg-count">$count_archived</span></a>
306 </div>
307 </div>
308 <div style="display:flex;flex-direction:column;max-height:calc(100vh - 280px);overflow-y:auto">
309 [loop:@list_rows]
310 <a href="$loop1.select_url"
311 title="$loop1.author_safe -- $loop1.body_preview"
312 style="display:flex;align-items:center;gap:8px;padding:7px 12px;border-bottom:1px solid var(--col-border);text-decoration:none;color:inherit;min-height:32px;[if:$loop1.is_selected]background:rgba(59,130,246,0.08);border-left:3px solid var(--col-accent);[/if][if:!$loop1.is_unread]opacity:0.78;[/if]">
313 <span class="pill $loop1.pill_class" style="font-size:9px;flex-shrink:0">$loop1.platform_label</span>
314 [if:$loop1.is_flagged]<span class="pill danger" style="font-size:9px;flex-shrink:0">FLAG</span>[/if]
315 <span class="text-sm fw-600" style="color:#fff;flex-shrink:0;max-width:110px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">$loop1.author_safe</span>
316 <span class="text-xs text-secondary" style="flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">[if:$loop1.has_rating]<span style="color:var(--col-warning)">$loop1.rating_stars</span> [/if]$loop1.body_preview</span>
317 <span class="text-xs text-dim" style="flex-shrink:0">$loop1.ago</span>
318 </a>
319 [/loop]
320 </div>
321 </div>
322
323 <!-- ===== Detail ===== -->
324 <div class="module">
325 [if:$has_selected]
326 <div class="module-head">
327 <div class="left">
328 <div class="user-avatar" style="background:linear-gradient(130deg,#3b82f6,#7c3aed)">$selected.author_initials</div>
329 <div>
330 <div class="module-title">$selected.author_safe</div>
331 <div class="module-sub">$selected.platform_label[if:$selected.has_rating] &middot; <span style="color:var(--col-warning)">$selected.rating_stars</span>[/if]</div>
332 </div>
333 </div>
334 <div class="flex gap-2">
335 [if:$selected.has_permalink]<a href="$selected.permalink" target="_blank" rel="noopener" class="icon-btn" title="Open on source platform"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg></a>[/if]
336 <form method="POST" action="/messages_action.cgi" style="display:inline">
337 <input type="hidden" name="action" value="flag">
338 <input type="hidden" name="id" value="$selected.id">
339 <input type="hidden" name="filter" value="$filter">
340 <button type="submit" class="icon-btn" title="Flag for follow-up"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1Z"/></svg></button>
341 </form>
342 <form method="POST" action="/messages_action.cgi" style="display:inline">
343 <input type="hidden" name="action" value="archive">
344 <input type="hidden" name="id" value="$selected.id">
345 <input type="hidden" name="filter" value="$filter">
346 <button type="submit" class="icon-btn" title="Archive"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="21 8 21 21 3 21 3 8"/><rect x="1" y="3" width="22" height="5"/></svg></button>
347 </form>
348 </div>
349 </div>
350 <div class="module-body">
351 <div style="background:var(--col-surface-2);border:1px solid var(--col-border);border-radius:12px;padding:18px;margin-bottom:18px">
352 <div class="flex items-center gap-2 mb-2">
353 <span class="pill $selected.pill_class">$selected.platform_label</span>
354 <span class="text-xs text-dim">$selected.occurred_fmt</span>
355 [if:$selected.has_rating]<span style="margin-left:auto;color:var(--col-warning)">$selected.rating_stars</span>[/if]
356 </div>
357 <p style="color:#fff;line-height:1.7;font-size:15px;white-space:pre-wrap;margin:0">$selected.body_safe</p>
358 </div>
359
360 [if:$has_thread]
361 <div class="text-xs text-dim mb-2" style="letter-spacing:1.5px;text-transform:uppercase">Your replies</div>
362 [loop:@thread]
363 <div style="background:rgba(124,58,237,0.08);border:1px solid rgba(124,58,237,0.30);border-radius:10px;padding:14px 16px;margin-bottom:10px">
364 <div class="flex items-center gap-2 mb-1" style="font-size:11px">
365 [if:$loop1.is_sent]<span class="pill success" style="font-size:9px">SENT</span>[/if]
366 [if:$loop1.is_pending]<span class="pill warning" style="font-size:9px">SENDING</span>[/if]
367 [if:$loop1.is_failed]<span class="pill danger" style="font-size:9px">FAILED</span>[/if]
368 <span class="text-xs text-dim" style="margin-left:auto">$loop1.ago</span>
369 </div>
370 <div style="font-size:14px;line-height:1.6;color:#fff;white-space:pre-wrap">$loop1.body_safe</div>
371 [if:$loop1.is_failed]<div class="text-xs" style="color:#fca5a5;margin-top:8px">Send failed -- retry from the Marketplaces page after fixing the connection.</div>[/if]
372 </div>
373 [/loop]
374 [/if]
375
376 <form method="POST" action="/messages_action.cgi">
377 <input type="hidden" name="action" value="reply">
378 <input type="hidden" name="id" value="$selected.id">
379 <input type="hidden" name="filter" value="$filter">
380
381 <div class="text-xs text-dim mb-2" style="letter-spacing:1.5px;text-transform:uppercase">Quick reply</div>
382 <textarea class="textarea" rows="4" name="body" required placeholder="Type your reply... we will post it back to $selected.platform_label under your account."></textarea>
383
384 <div class="flex gap-2 mt-3" style="flex-wrap:wrap">
385 <button type="button" class="btn btn-secondary btn-sm we-quick-reply" data-text="Thanks for the print!">Thanks for the print!</button>
386 <button type="button" class="btn btn-secondary btn-sm we-quick-reply" data-text="Glad it worked out for you!">Glad it worked out for you!</button>
387 <button type="button" class="btn btn-secondary btn-sm we-quick-reply" data-text="More like this coming soon -- stay tuned.">More like this coming soon</button>
388 <button type="button" class="btn btn-secondary btn-sm we-quick-reply" data-text="Appreciate the feedback -- I will look into it.">Appreciate the feedback</button>
389 </div>
390 <div class="flex justify-between items-center mt-3" style="flex-wrap:wrap;gap:10px">
391 <span class="text-xs text-dim">Posts back to $selected.platform_label as <strong>$reply_handle</strong></span>
392 <button type="submit" class="btn btn-primary"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 2 11 13"/><path d="m22 2-7 20-4-9-9-4 20-7Z"/></svg>Send</button>
393 </div>
394 </form>
395 </div>
396 [/if]
397
398 [if:$no_selected]
399 <div class="module-body" style="text-align:center;padding:60px 24px">
400 <div class="text-sm fw-600" style="color:#fff;margin-bottom:6px">No message selected</div>
401 <div class="text-xs text-dim">Pick a thread on the left to read and reply.</div>
402 </div>
403 [/if]
404 </div>
405</div>
406
407<script>
408 // Quick-reply chips: insert their text into the reply textarea so
409 // the seller can lightly customize before sending.
410 document.querySelectorAll('.we-quick-reply').forEach(function(btn){
411 btn.addEventListener('click', function(){
412 var ta = btn.closest('form').querySelector('textarea[name=body]');
413 if (!ta) return;
414 var cur = ta.value || '';
415 ta.value = cur ? (cur.replace(/\s+$/,'') + ' ' + btn.dataset.text) : btn.dataset.text;
416 ta.focus();
417 });
418 });
419</script>
420[/if]
421[/if]
422
423<!-- Trailing non-conditional content: MODS::Template returns eval's
424 value, and a file ending in [/if] silently renders empty. -->
425<div style="height:0"></div>
Keyboard: j next diff k previous diff g top G bottom r restore c compile-check ? help