- Implemented a comprehensive health check utility to monitor system dependencies including NocoDB, SMTP, Represent API, disk space, and memory usage. - Created a logger utility using Winston for structured logging with daily rotation and various log levels. - Developed a metrics utility using Prometheus client to track application performance metrics such as email sends, HTTP requests, and user activity. - Added a backup script for automated backups of NocoDB data, uploaded files, and environment configurations with optional S3 support. - Introduced a toggle script to switch between development (MailHog) and production (ProtonMail) SMTP configurations.
302 lines
25 KiB
HTML
302 lines
25 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Response Wall | BNKops Influence</title>
|
|
<link rel="stylesheet" href="/css/styles.css">
|
|
<link rel="stylesheet" href="/css/response-wall.css">
|
|
</head>
|
|
<body>
|
|
<!-- Campaign Header -->
|
|
<div class="response-wall-header">
|
|
<div class="response-wall-header-content">
|
|
<h1>📢 Community Response Wall</h1>
|
|
<h2 id="campaign-name" class="campaign-subtitle" style="display: none;"></h2>
|
|
<p id="campaign-description">See what representatives are saying back to constituents</p>
|
|
|
|
<div class="header-nav-buttons">
|
|
<button class="nav-btn" id="nav-to-campaign">
|
|
← Back to Campaign
|
|
</button>
|
|
<button class="nav-btn" id="nav-to-home">
|
|
🏠 Home
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Social Share Buttons in Header -->
|
|
<div class="share-buttons-header">
|
|
<!-- Expandable Social Menu -->
|
|
<div class="share-socials-container">
|
|
<button class="share-btn-primary" id="share-socials-toggle" title="Share on Socials">
|
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="share-icon">
|
|
<path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81 1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9c-1.66 0-3 1.34-3 3s1.34 3 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92 1.61 0 2.92-1.31 2.92-2.92s-1.31-2.92-2.92-2.92z"/>
|
|
</svg>
|
|
<span>Socials</span>
|
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="chevron-icon">
|
|
<path d="M7 10l5 5 5-5z"/>
|
|
</svg>
|
|
</button>
|
|
|
|
<!-- Expandable Social Options -->
|
|
<div class="share-socials-menu" id="share-socials-menu">
|
|
<button class="share-btn-small" id="share-facebook" title="Facebook">
|
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/></svg>
|
|
</button>
|
|
<button class="share-btn-small" id="share-twitter" title="Twitter/X">
|
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>
|
|
</button>
|
|
<button class="share-btn-small" id="share-linkedin" title="LinkedIn">
|
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/></svg>
|
|
</button>
|
|
<button class="share-btn-small" id="share-whatsapp" title="WhatsApp">
|
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413Z"/></svg>
|
|
</button>
|
|
<button class="share-btn-small" id="share-bluesky" title="Bluesky">
|
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 10.8c-1.087-2.114-4.046-6.053-6.798-7.995C2.566.944 1.561 1.266.902 1.565.139 1.908 0 3.08 0 3.768c0 .69.378 5.65.624 6.479.815 2.736 3.713 3.66 6.383 3.364.136-.02.275-.039.415-.056-.138.022-.276.04-.415.056-3.912.58-7.387 2.005-2.83 7.078 5.013 5.19 6.87-1.113 7.823-4.308.953 3.195 2.05 9.271 7.733 4.308 4.267-4.308 1.172-6.498-2.74-7.078a8.741 8.741 0 0 1-.415-.056c.14.017.279.036.415.056 2.67.297 5.568-.628 6.383-3.364.246-.828.624-5.79.624-6.478 0-.69-.139-1.861-.902-2.206-.659-.298-1.664-.62-4.3 1.24C16.046 4.748 13.087 8.687 12 10.8Z"/></svg>
|
|
</button>
|
|
<button class="share-btn-small" id="share-instagram" title="Instagram">
|
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M7.8 2h8.4C19.4 2 22 4.6 22 7.8v8.4a5.8 5.8 0 0 1-5.8 5.8H7.8C4.6 22 2 19.4 2 16.2V7.8A5.8 5.8 0 0 1 7.8 2m-.2 2A3.6 3.6 0 0 0 4 7.6v8.8C4 18.39 5.61 20 7.6 20h8.8a3.6 3.6 0 0 0 3.6-3.6V7.6C20 5.61 18.39 4 16.4 4H7.6m9.65 1.5a1.25 1.25 0 0 1 1.25 1.25A1.25 1.25 0 0 1 17.25 8 1.25 1.25 0 0 1 16 6.75a1.25 1.25 0 0 1 1.25-1.25M12 7a5 5 0 0 1 5 5 5 5 0 0 1-5 5 5 5 0 0 1-5-5 5 5 0 0 1 5-5m0 2a3 3 0 0 0-3 3 3 3 0 0 0 3 3 3 3 0 0 0 3-3 3 3 0 0 0-3-3z"/></svg>
|
|
</button>
|
|
<button class="share-btn-small" id="share-reddit" title="Reddit">
|
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0zm5.01 4.744c.688 0 1.25.561 1.25 1.249a1.25 1.25 0 0 1-2.498.056l-2.597-.547-.8 3.747c1.824.07 3.48.632 4.674 1.488.308-.309.73-.491 1.207-.491.968 0 1.754.786 1.754 1.754 0 .716-.435 1.333-1.01 1.614a3.111 3.111 0 0 1 .042.52c0 2.694-3.13 4.87-7.004 4.87-3.874 0-7.004-2.176-7.004-4.87 0-.183.015-.366.043-.534A1.748 1.748 0 0 1 4.028 12c0-.968.786-1.754 1.754-1.754.463 0 .898.196 1.207.49 1.207-.883 2.878-1.43 4.744-1.487l.885-4.182a.342.342 0 0 1 .14-.197.35.35 0 0 1 .238-.042l2.906.617a1.214 1.214 0 0 1 1.108-.701zM9.25 12C8.561 12 8 12.562 8 13.25c0 .687.561 1.248 1.25 1.248.687 0 1.248-.561 1.248-1.249 0-.688-.561-1.249-1.249-1.249zm5.5 0c-.687 0-1.248.561-1.248 1.25 0 .687.561 1.248 1.249 1.248.688 0 1.249-.561 1.249-1.249 0-.687-.562-1.249-1.25-1.249zm-5.466 3.99a.327.327 0 0 0-.231.094.33.33 0 0 0 0 .463c.842.842 2.484.913 2.961.913.477 0 2.105-.056 2.961-.913a.361.361 0 0 0 .029-.463.33.33 0 0 0-.464 0c-.547.533-1.684.73-2.512.73-.828 0-1.979-.196-2.512-.73a.326.326 0 0 0-.232-.095z"/></svg>
|
|
</button>
|
|
<button class="share-btn-small" id="share-threads" title="Threads">
|
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12.186 24h-.007c-3.581-.024-6.334-1.205-8.184-3.509C2.35 18.44 1.5 15.586 1.472 12.01v-.017c.03-3.579.879-6.43 2.525-8.482C5.845 1.205 8.6.024 12.18 0h.014c2.746.02 5.043.725 6.826 2.098 1.677 1.29 2.858 3.13 3.509 5.467l-2.04.569c-.542-1.947-1.499-3.488-2.846-4.576-1.488-1.2-3.457-1.806-5.854-1.826h-.01c-3.015.022-5.26.918-6.675 2.662C3.873 6.034 3.13 8.39 3.108 11.98v.014c.022 3.585.766 5.937 2.209 6.99 1.407 1.026 3.652 1.545 6.674 1.545h.01c.297 0 .597-.002.892-.009l.034 2.037c-.33.008-.665.012-1.001.012zM17.822 15.13v.002c-.184 1.376-.865 2.465-2.025 3.234-1.222.81-2.878 1.221-4.922 1.221-1.772 0-3.185-.34-4.197-1.009-.944-.625-1.488-1.527-1.617-2.68-.119-1.066.152-2.037.803-2.886.652-.85 1.595-1.464 2.802-1.823 1.102-.33 2.396-.495 3.847-.495h.343v1.615h-.343c-1.274 0-2.395.144-3.332.428-.937.284-1.653.713-2.129 1.275-.476.562-.664 1.229-.556 1.979.097.671.45 1.21 1.051 1.603.723.473 1.816.711 3.252.711 1.738 0 3.097-.35 4.042-.995.809-.552 1.348-1.349 1.603-2.373l1.98.193zM12.626 10.561v.002c-1.197 0-2.234.184-3.083.546-.938.4-1.668 1.017-2.169 1.835-.499.816-.748 1.792-.739 2.902l-2.037-.022c-.012-1.378.304-2.608.939-3.658.699-1.158 1.688-2.065 2.941-2.696 1.05-.527 2.274-.792 3.638-.792h.51v1.883h-.51z"/></svg>
|
|
</button>
|
|
<button class="share-btn-small" id="share-telegram" title="Telegram">
|
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M11.944 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0a12 12 0 0 0-.056 0zm4.962 7.224c.1-.002.321.023.465.14a.506.506 0 0 1 .171.325c.016.093.036.306.02.472-.18 1.898-.962 6.502-1.36 8.627-.168.9-.499 1.201-.82 1.23-.696.065-1.225-.46-1.9-.902-1.056-.693-1.653-1.124-2.678-1.8-1.185-.78-.417-1.21.258-1.91.177-.184 3.247-2.977 3.307-3.23.007-.032.014-.15-.056-.212s-.174-.041-.249-.024c-.106.024-1.793 1.14-5.061 3.345-.48.33-.913.49-1.302.48-.428-.008-1.252-.241-1.865-.44-.752-.245-1.349-.374-1.297-.789.027-.216.325-.437.893-.663 3.498-1.524 5.83-2.529 6.998-3.014 3.332-1.386 4.025-1.627 4.476-1.635z"/></svg>
|
|
</button>
|
|
<button class="share-btn-small" id="share-mastodon" title="Mastodon">
|
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M23.268 5.313c-.35-2.578-2.617-4.61-5.304-5.004C17.51.242 15.792 0 11.813 0h-.03c-3.98 0-4.835.242-5.288.309C3.882.692 1.496 2.518.917 5.127.64 6.412.61 7.837.661 9.143c.074 1.874.088 3.745.26 5.611.118 1.24.325 2.47.62 3.68.55 2.237 2.777 4.098 4.96 4.857 2.336.792 4.849.923 7.256.38.265-.061.527-.132.786-.213.585-.184 1.27-.39 1.774-.753a.057.057 0 0 0 .023-.043v-1.809a.052.052 0 0 0-.02-.041.053.053 0 0 0-.046-.01 20.282 20.282 0 0 1-4.709.545c-2.73 0-3.463-1.284-3.674-1.818a5.593 5.593 0 0 1-.319-1.433.053.053 0 0 1 .066-.054c1.517.363 3.072.546 4.632.546.376 0 .75 0 1.125-.01 1.57-.044 3.224-.124 4.768-.422.038-.008.077-.015.11-.024 2.435-.464 4.753-1.92 4.989-5.604.008-.145.03-1.52.03-1.67.002-.512.167-3.63-.024-5.545zm-3.748 9.195h-2.561V8.29c0-1.309-.55-1.976-1.67-1.976-1.23 0-1.846.79-1.846 2.35v3.403h-2.546V8.663c0-1.56-.617-2.35-1.848-2.35-1.112 0-1.668.668-1.67 1.977v6.218H4.822V8.102c0-1.31.337-2.35 1.011-3.12.696-.77 1.608-1.164 2.74-1.164 1.311 0 2.302.5 2.962 1.498l.638 1.06.638-1.06c.66-.999 1.65-1.498 2.96-1.498 1.13 0 2.043.395 2.74 1.164.675.77 1.012 1.81 1.012 3.12z"/></svg>
|
|
</button>
|
|
<button class="share-btn-small" id="share-sms" title="SMS">
|
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H6l-2 2V4h16v12zM7 9h2v2H7zm4 0h2v2h-2zm4 0h2v2h-2z"/></svg>
|
|
</button>
|
|
<button class="share-btn-small" id="share-slack" title="Slack">
|
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M5.042 15.165a2.528 2.528 0 0 1-2.52 2.523A2.528 2.528 0 0 1 0 15.165a2.527 2.527 0 0 1 2.522-2.52h2.52v2.52zm1.271 0a2.527 2.527 0 0 1 2.521-2.52 2.527 2.527 0 0 1 2.521 2.52v6.313A2.528 2.528 0 0 1 8.834 24a2.528 2.528 0 0 1-2.521-2.522v-6.313zM8.834 5.042a2.528 2.528 0 0 1-2.521-2.52A2.528 2.528 0 0 1 8.834 0a2.528 2.528 0 0 1 2.521 2.522v2.52H8.834zm0 1.271a2.528 2.528 0 0 1 2.521 2.521 2.528 2.528 0 0 1-2.521 2.521H2.522A2.528 2.528 0 0 1 0 8.834a2.528 2.528 0 0 1 2.522-2.521h6.312zm10.122 2.521a2.528 2.528 0 0 1 2.522-2.521A2.528 2.528 0 0 1 24 8.834a2.528 2.528 0 0 1-2.522 2.521h-2.522V8.834zm-1.268 0a2.528 2.528 0 0 1-2.523 2.521 2.527 2.527 0 0 1-2.52-2.521V2.522A2.527 2.527 0 0 1 15.165 0a2.528 2.528 0 0 1 2.523 2.522v6.312zm-2.523 10.122a2.528 2.528 0 0 1 2.523 2.522A2.528 2.528 0 0 1 15.165 24a2.527 2.527 0 0 1-2.52-2.522v-2.522h2.52zm0-1.268a2.527 2.527 0 0 1-2.52-2.523 2.526 2.526 0 0 1 2.52-2.52h6.313A2.527 2.527 0 0 1 24 15.165a2.528 2.528 0 0 1-2.522 2.523h-6.313z"/></svg>
|
|
</button>
|
|
<button class="share-btn-small" id="share-discord" title="Discord">
|
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z"/></svg>
|
|
</button>
|
|
<button class="share-btn-small" id="share-print" title="Print">
|
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M19 8H5c-1.66 0-3 1.34-3 3v6h4v4h12v-4h4v-6c0-1.66-1.34-3-3-3zm-3 11H8v-5h8v5zm3-7c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm-1-9H6v4h12V3z"/></svg>
|
|
</button>
|
|
<button class="share-btn-small" id="share-email" title="Email">
|
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"/></svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Always-visible buttons -->
|
|
<button class="share-btn-primary" id="share-copy" title="Copy Link">
|
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
<path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/>
|
|
</svg>
|
|
<span>Copy Link</span>
|
|
</button>
|
|
<button class="share-btn-primary" id="share-qrcode" title="Show QR Code">
|
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
<path d="M3 11h8V3H3v8zm2-6h4v4H5V5zM3 21h8v-8H3v8zm2-6h4v4H5v-4zM13 3v8h8V3h-8zm6 6h-4V5h4v4zM13 13h2v2h-2zM15 15h2v2h-2zM13 17h2v2h-2zM17 13h2v2h-2zM19 15h2v2h-2zM17 17h2v2h-2zM19 19h2v2h-2z"/>
|
|
</svg>
|
|
<span>QR Code</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="container">
|
|
<!-- Stats Banner -->
|
|
<div class="stats-banner" id="stats-banner" style="display: none;">
|
|
<div class="stat-item">
|
|
<span class="stat-number" id="stat-total-responses">0</span>
|
|
<span class="stat-label">Total Responses</span>
|
|
</div>
|
|
<div class="stat-item">
|
|
<span class="stat-number" id="stat-verified">0</span>
|
|
<span class="stat-label">Verified</span>
|
|
</div>
|
|
<div class="stat-item">
|
|
<span class="stat-number" id="stat-upvotes">0</span>
|
|
<span class="stat-label">Total Upvotes</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Controls -->
|
|
<div class="response-controls">
|
|
<div class="filter-group">
|
|
<label for="sort-select">Sort by:</label>
|
|
<select id="sort-select">
|
|
<option value="recent">Most Recent</option>
|
|
<option value="upvotes">Most Upvoted</option>
|
|
<option value="verified">Verified First</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="filter-group">
|
|
<label for="level-filter">Filter by Level:</label>
|
|
<select id="level-filter">
|
|
<option value="">All Levels</option>
|
|
<option value="Federal">Federal</option>
|
|
<option value="Provincial">Provincial</option>
|
|
<option value="Municipal">Municipal</option>
|
|
<option value="School Board">School Board</option>
|
|
</select>
|
|
</div>
|
|
|
|
<button class="btn btn-primary" id="submit-response-btn">
|
|
✍️ Share a Response
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Loading Indicator -->
|
|
<div id="loading" class="loading" style="display: none;">
|
|
<p>Loading responses...</p>
|
|
</div>
|
|
|
|
<!-- Empty State -->
|
|
<div id="empty-state" class="empty-state" style="display: none;">
|
|
<p>No responses yet. Be the first to share!</p>
|
|
<button class="btn btn-primary" id="empty-state-submit-btn">Share a Response</button>
|
|
</div>
|
|
|
|
<!-- Responses Container -->
|
|
<div id="responses-container"></div>
|
|
|
|
<!-- Load More Button -->
|
|
<div class="load-more-container" id="load-more-container" style="display: none;">
|
|
<button class="btn btn-secondary" id="load-more-btn">Load More</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Submit Response Modal -->
|
|
<div id="submit-modal" class="modal">
|
|
<div class="modal-content">
|
|
<span class="close" id="modal-close-btn">×</span>
|
|
<h2>Share a Representative Response</h2>
|
|
<form id="submit-response-form" enctype="multipart/form-data">
|
|
<!-- Postal Code Lookup -->
|
|
<div class="form-group">
|
|
<label for="modal-postal-code">Find Your Representative by Postal Code</label>
|
|
<div class="postal-lookup-container">
|
|
<input type="text" id="modal-postal-code" placeholder="Enter postal code (e.g., T5K 2J1)" maxlength="7">
|
|
<button type="button" class="btn btn-secondary" id="lookup-rep-btn">🔍 Search</button>
|
|
</div>
|
|
<small>Search for representatives by postal code to auto-fill details</small>
|
|
</div>
|
|
|
|
<!-- Representatives Selection (Hidden by default) -->
|
|
<div class="form-group" id="rep-select-group" style="display: none;">
|
|
<label for="rep-select">Select Representative *</label>
|
|
<select id="rep-select" size="5">
|
|
<!-- Options will be populated by JavaScript -->
|
|
</select>
|
|
<small>Click on a representative to auto-fill the form</small>
|
|
</div>
|
|
|
|
<!-- Manual Entry Fields -->
|
|
<div class="form-group">
|
|
<label for="representative-name">Representative Name *</label>
|
|
<input type="text" id="representative-name" name="representative_name" required>
|
|
<small>Or enter manually if not found above</small>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="representative-title">Representative Title</label>
|
|
<input type="text" id="representative-title" name="representative_title" placeholder="e.g., MLA, MP, Councillor">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="representative-level">Government Level *</label>
|
|
<select id="representative-level" name="representative_level" required>
|
|
<option value="">Select level...</option>
|
|
<option value="Federal">Federal</option>
|
|
<option value="Provincial">Provincial</option>
|
|
<option value="Municipal">Municipal</option>
|
|
<option value="School Board">School Board</option>
|
|
</select>
|
|
</div>
|
|
|
|
<!-- Hidden field to store representative email for verification -->
|
|
<input type="hidden" id="representative-email" name="representative_email">
|
|
|
|
<div class="form-group">
|
|
<label for="response-type">Response Type *</label>
|
|
<select id="response-type" name="response_type" required>
|
|
<option value="">Select type...</option>
|
|
<option value="Email">Email</option>
|
|
<option value="Letter">Letter</option>
|
|
<option value="Phone Call">Phone Call</option>
|
|
<option value="Meeting">Meeting</option>
|
|
<option value="Social Media">Social Media</option>
|
|
<option value="Other">Other</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="response-text">Response Text *</label>
|
|
<textarea id="response-text" name="response_text" rows="6" required placeholder="Paste or type the response you received..."></textarea>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="user-comment">Your Comment (Optional)</label>
|
|
<textarea id="user-comment" name="user_comment" rows="3" placeholder="Add your thoughts about this response..."></textarea>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="screenshot">Screenshot (Optional)</label>
|
|
<input type="file" id="screenshot" name="screenshot" accept="image/*">
|
|
<small>Upload a screenshot of the response (max 5MB)</small>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="submitted-by-name">Your Name (Optional)</label>
|
|
<input type="text" id="submitted-by-name" name="submitted_by_name">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="submitted-by-email">Your Email (Optional)</label>
|
|
<input type="email" id="submitted-by-email" name="submitted_by_email">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>
|
|
<input type="checkbox" id="is-anonymous" name="is_anonymous">
|
|
Post anonymously (don't show my name)
|
|
</label>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>
|
|
<input type="checkbox" id="send-verification" name="send_verification">
|
|
Send verification request to representative
|
|
</label>
|
|
<small>This will email the representative to verify this response is authentic</small>
|
|
</div>
|
|
|
|
<div class="form-actions">
|
|
<button type="button" class="btn btn-secondary" id="cancel-submit-btn">Cancel</button>
|
|
<button type="submit" class="btn btn-primary">Submit Response</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- QR Code Modal -->
|
|
<div id="qrcode-modal" class="qrcode-modal">
|
|
<div class="qrcode-modal-content">
|
|
<span class="qrcode-close">×</span>
|
|
<h2>Scan QR Code to Visit Response Wall</h2>
|
|
<div class="qrcode-container">
|
|
<img id="qrcode-image" src="" alt="Response Wall QR Code">
|
|
</div>
|
|
<p class="qrcode-instructions">Scan this code with your phone to visit this response wall</p>
|
|
<button class="btn btn-secondary" id="download-qrcode-btn">Download QR Code</button>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="/js/api-client.js"></script>
|
|
<script src="/js/response-wall.js"></script>
|
|
</body>
|
|
</html>
|