- 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.
785 lines
37 KiB
HTML
785 lines
37 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title id="page-title">Campaign - BNKops Influence Tool</title>
|
|
<link rel="stylesheet" href="/css/styles.css">
|
|
<style>
|
|
.campaign-header {
|
|
background: linear-gradient(135deg, #3498db, #2c3e50);
|
|
color: white;
|
|
padding: 3rem 0;
|
|
text-align: center;
|
|
margin-bottom: 2rem;
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.campaign-header.has-cover {
|
|
background-size: cover;
|
|
background-position: center;
|
|
background-repeat: no-repeat;
|
|
min-height: 350px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.campaign-header.has-cover::before {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background: rgba(0, 0, 0, 0.5);
|
|
z-index: 1;
|
|
}
|
|
|
|
.campaign-header > * {
|
|
position: relative;
|
|
z-index: 2;
|
|
}
|
|
|
|
.campaign-header h1 {
|
|
font-size: 2.5rem;
|
|
margin-bottom: 1rem;
|
|
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.7);
|
|
}
|
|
|
|
.campaign-header-content {
|
|
max-width: 800px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.campaign-stats-header {
|
|
display: flex;
|
|
gap: 1.5rem;
|
|
justify-content: center;
|
|
margin-top: 1.5rem;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.stat-circle {
|
|
background: rgba(255, 255, 255, 0.2);
|
|
border: 2px solid rgba(255, 255, 255, 0.3);
|
|
border-radius: 50%;
|
|
width: 80px;
|
|
height: 80px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
backdrop-filter: blur(10px);
|
|
}
|
|
|
|
.stat-number {
|
|
font-size: 1.8rem;
|
|
font-weight: bold;
|
|
color: white;
|
|
line-height: 1;
|
|
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
|
|
}
|
|
|
|
.stat-label {
|
|
font-size: 0.7rem;
|
|
color: rgba(255, 255, 255, 0.9);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.5px;
|
|
margin-top: 0.25rem;
|
|
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3);
|
|
}
|
|
|
|
.share-buttons-header {
|
|
display: flex;
|
|
gap: 0.5rem;
|
|
justify-content: center;
|
|
margin-top: 1rem;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.share-btn-small {
|
|
background: rgba(255, 255, 255, 0.2);
|
|
border: 1px solid rgba(255, 255, 255, 0.3);
|
|
border-radius: 50%;
|
|
width: 36px;
|
|
height: 36px;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
cursor: pointer;
|
|
transition: all 0.2s;
|
|
backdrop-filter: blur(10px);
|
|
}
|
|
|
|
.share-btn-small:hover {
|
|
background: rgba(255, 255, 255, 0.3);
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
|
}
|
|
|
|
.share-btn-small svg {
|
|
width: 18px;
|
|
height: 18px;
|
|
fill: white;
|
|
}
|
|
|
|
.share-btn-small.copied {
|
|
background: rgba(40, 167, 69, 0.8);
|
|
border-color: rgba(40, 167, 69, 1);
|
|
}
|
|
|
|
.share-more-container {
|
|
position: relative;
|
|
display: inline-block;
|
|
}
|
|
|
|
.share-dropdown {
|
|
display: none;
|
|
position: absolute;
|
|
top: 100%;
|
|
right: 0;
|
|
margin-top: 0.5rem;
|
|
background: white;
|
|
border: 1px solid rgba(255, 255, 255, 0.3);
|
|
border-radius: 8px;
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
|
padding: 0.5rem;
|
|
z-index: 1000;
|
|
min-width: 200px;
|
|
}
|
|
|
|
.share-dropdown.show {
|
|
display: block;
|
|
}
|
|
|
|
.share-dropdown-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, 1fr);
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.share-dropdown-item {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
padding: 0.75rem 0.5rem;
|
|
border-radius: 6px;
|
|
background: rgba(52, 152, 219, 0.1);
|
|
cursor: pointer;
|
|
transition: all 0.2s;
|
|
text-decoration: none;
|
|
color: #2c3e50;
|
|
}
|
|
|
|
.share-dropdown-item:hover {
|
|
background: rgba(52, 152, 219, 0.2);
|
|
transform: translateY(-2px);
|
|
}
|
|
|
|
.share-dropdown-item svg {
|
|
width: 24px;
|
|
height: 24px;
|
|
margin-bottom: 0.25rem;
|
|
fill: #2c3e50;
|
|
}
|
|
|
|
.share-dropdown-item span {
|
|
font-size: 0.7rem;
|
|
text-align: center;
|
|
line-height: 1.2;
|
|
}
|
|
|
|
.share-btn-small.more-btn {
|
|
position: relative;
|
|
}
|
|
|
|
.share-btn-small.more-btn.active {
|
|
background: rgba(255, 255, 255, 0.4);
|
|
}
|
|
|
|
.campaign-content {
|
|
max-width: 800px;
|
|
margin: 0 auto;
|
|
padding: 0 1rem;
|
|
}
|
|
|
|
.call-to-action {
|
|
background: #fff3cd;
|
|
border: 1px solid #ffeaa7;
|
|
border-radius: 8px;
|
|
padding: 1.5rem;
|
|
margin-bottom: 2rem;
|
|
text-align: center;
|
|
}
|
|
|
|
.user-info-form {
|
|
background: white;
|
|
padding: 2rem;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|
margin-bottom: 2rem;
|
|
}
|
|
|
|
.email-preview {
|
|
background: #f8f9fa;
|
|
border: 1px solid #dee2e6;
|
|
border-radius: 8px;
|
|
padding: 1.5rem;
|
|
margin-bottom: 2rem;
|
|
}
|
|
|
|
.email-preview h3 {
|
|
color: #495057;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.email-subject {
|
|
font-weight: bold;
|
|
color: #2c3e50;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.email-body {
|
|
line-height: 1.6;
|
|
color: #495057;
|
|
white-space: pre-wrap;
|
|
}
|
|
|
|
.email-edit-subject, .email-edit-body {
|
|
width: 100%;
|
|
border: 1px solid #ced4da;
|
|
border-radius: 4px;
|
|
padding: 0.5rem;
|
|
font-family: inherit;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.email-edit-subject {
|
|
font-weight: bold;
|
|
font-size: 1rem;
|
|
}
|
|
|
|
.email-edit-body {
|
|
min-height: 150px;
|
|
resize: vertical;
|
|
line-height: 1.6;
|
|
}
|
|
|
|
.email-edit-actions {
|
|
display: flex;
|
|
gap: 0.5rem;
|
|
margin-top: 1rem;
|
|
}
|
|
|
|
.preview-mode .email-edit-subject,
|
|
.preview-mode .email-edit-body,
|
|
.preview-mode .email-edit-actions {
|
|
display: none;
|
|
}
|
|
|
|
.preview-mode .email-preview-actions {
|
|
display: block !important;
|
|
}
|
|
|
|
.edit-mode .email-subject,
|
|
.edit-mode .email-body,
|
|
.edit-mode .email-preview-actions {
|
|
display: none;
|
|
}
|
|
|
|
.representatives-grid {
|
|
display: grid;
|
|
gap: 1rem;
|
|
margin-bottom: 2rem;
|
|
}
|
|
|
|
.rep-card {
|
|
border: 1px solid #dee2e6;
|
|
border-radius: 8px;
|
|
padding: 1rem;
|
|
background: white;
|
|
transition: transform 0.2s, box-shadow 0.2s;
|
|
}
|
|
|
|
.rep-card:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
|
}
|
|
|
|
.rep-info {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 1rem;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.rep-photo {
|
|
width: 60px;
|
|
height: 60px;
|
|
border-radius: 50%;
|
|
object-fit: cover;
|
|
background: #e9ecef;
|
|
}
|
|
|
|
.rep-details h4 {
|
|
margin: 0 0 0.25rem 0;
|
|
color: #2c3e50;
|
|
}
|
|
|
|
.rep-details p {
|
|
margin: 0;
|
|
color: #6c757d;
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.rep-actions {
|
|
display: flex;
|
|
gap: 0.5rem;
|
|
justify-content: center;
|
|
}
|
|
|
|
.email-method-toggle {
|
|
display: flex;
|
|
gap: 1rem;
|
|
justify-content: center;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.method-option {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.progress-steps {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
margin-bottom: 2rem;
|
|
padding: 1rem;
|
|
background: #f8f9fa;
|
|
border-radius: 8px;
|
|
}
|
|
|
|
.step {
|
|
flex: 1;
|
|
text-align: center;
|
|
position: relative;
|
|
padding: 0.5rem;
|
|
}
|
|
|
|
.step.active {
|
|
color: #3498db;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.step.completed {
|
|
color: #27ae60;
|
|
}
|
|
|
|
.step:not(:last-child)::after {
|
|
content: '→';
|
|
position: absolute;
|
|
right: -50%;
|
|
color: #6c757d;
|
|
}
|
|
|
|
.loading-overlay {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background: rgba(0,0,0,0.7);
|
|
display: none;
|
|
justify-content: center;
|
|
align-items: center;
|
|
z-index: 1000;
|
|
}
|
|
|
|
.loading-content {
|
|
background: white;
|
|
padding: 2rem;
|
|
border-radius: 8px;
|
|
text-align: center;
|
|
}
|
|
|
|
/* Response Wall Button Styles */
|
|
.response-wall-button {
|
|
display: inline-block;
|
|
padding: 1rem 2rem;
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
color: white;
|
|
text-decoration: none;
|
|
border-radius: 50px;
|
|
font-size: 1.1rem;
|
|
font-weight: bold;
|
|
text-align: center;
|
|
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
|
|
position: relative;
|
|
overflow: hidden;
|
|
transition: transform 0.3s, box-shadow 0.3s;
|
|
animation: pulse-glow 2s ease-in-out infinite;
|
|
}
|
|
|
|
.response-wall-button:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6);
|
|
animation: none;
|
|
}
|
|
|
|
.response-wall-button::before {
|
|
content: '';
|
|
position: absolute;
|
|
top: -50%;
|
|
left: -50%;
|
|
width: 200%;
|
|
height: 200%;
|
|
background: linear-gradient(
|
|
45deg,
|
|
transparent,
|
|
rgba(255, 255, 255, 0.1),
|
|
transparent
|
|
);
|
|
transform: rotate(45deg);
|
|
animation: shine 3s ease-in-out infinite;
|
|
}
|
|
|
|
@keyframes pulse-glow {
|
|
0%, 100% {
|
|
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
|
|
}
|
|
50% {
|
|
box-shadow: 0 4px 25px rgba(102, 126, 234, 0.8), 0 0 30px rgba(102, 126, 234, 0.5);
|
|
}
|
|
}
|
|
|
|
@keyframes shine {
|
|
0% {
|
|
left: -50%;
|
|
}
|
|
100% {
|
|
left: 150%;
|
|
}
|
|
}
|
|
|
|
.response-wall-container {
|
|
text-align: center;
|
|
margin: 2rem 0;
|
|
padding: 2rem;
|
|
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
|
|
border-radius: 12px;
|
|
}
|
|
|
|
.response-wall-container h3 {
|
|
margin: 0 0 1rem 0;
|
|
color: #2c3e50;
|
|
font-size: 1.3rem;
|
|
}
|
|
|
|
.response-wall-container p {
|
|
margin: 0 0 1.5rem 0;
|
|
color: #666;
|
|
}
|
|
|
|
|
|
|
|
@media (max-width: 768px) {
|
|
.campaign-header h1 {
|
|
font-size: 2rem;
|
|
}
|
|
|
|
.progress-steps {
|
|
flex-direction: column;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.step:not(:last-child)::after {
|
|
content: '↓';
|
|
position: static;
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<!-- Loading Overlay -->
|
|
<div id="loading-overlay" class="loading-overlay">
|
|
<div class="loading-content">
|
|
<div class="spinner"></div>
|
|
<p id="loading-message">Loading campaign...</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Campaign Header -->
|
|
<div class="campaign-header">
|
|
<div class="container">
|
|
<div class="campaign-header-content">
|
|
<h1 id="campaign-title">Loading Campaign...</h1>
|
|
<p id="campaign-description"></p>
|
|
|
|
<!-- Campaign Stats in Header -->
|
|
<div id="campaign-stats-header" class="campaign-stats-header" style="display: none;">
|
|
<div id="email-stat-circle" class="stat-circle" style="display: none;">
|
|
<div class="stat-number" id="email-count-header">0</div>
|
|
<div class="stat-label">Emails</div>
|
|
</div>
|
|
<div id="call-stat-circle" class="stat-circle" style="display: none;">
|
|
<div class="stat-number" id="call-count-header">0</div>
|
|
<div class="stat-label">Calls</div>
|
|
</div>
|
|
</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>
|
|
|
|
<div class="campaign-content">
|
|
<!-- Call to Action -->
|
|
<div id="call-to-action" class="call-to-action" style="display: none;">
|
|
<!-- Content will be loaded dynamically -->
|
|
</div>
|
|
|
|
<!-- Progress Steps -->
|
|
<div class="progress-steps">
|
|
<div class="step active" id="step-info">Enter Your Info</div>
|
|
<div class="step" id="step-postal">Find Representatives</div>
|
|
<div class="step" id="step-send">Send Messages</div>
|
|
</div>
|
|
|
|
<!-- User Information Form -->
|
|
<div id="user-info-section" class="user-info-form">
|
|
<h2>Your Information</h2>
|
|
<p>We need some basic information to find your representatives and track campaign engagement.</p>
|
|
|
|
<form id="user-info-form">
|
|
<div class="form-group">
|
|
<label for="user-postal-code">Your Postal Code *</label>
|
|
<input type="text" id="user-postal-code" name="postalCode" required
|
|
placeholder="T5K 2M5" maxlength="7" style="text-transform: uppercase;">
|
|
</div>
|
|
|
|
<div id="optional-fields" style="display: none;">
|
|
<div class="form-group">
|
|
<label for="user-name">Your Name</label>
|
|
<input type="text" id="user-name" name="userName" placeholder="Your full name">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="user-email">Your Email (Optional - If you would like a reply)</label>
|
|
<input type="email" id="user-email" name="userEmail" placeholder="your@email.com">
|
|
</div>
|
|
</div>
|
|
|
|
<button type="submit" class="btn btn-primary">Find My Representatives</button>
|
|
</form>
|
|
</div>
|
|
|
|
<!-- Email Preview -->
|
|
<div id="email-preview" class="email-preview preview-mode" style="display: none;">
|
|
<h3>📧 Email Preview</h3>
|
|
<p id="preview-description">This is the message that will be sent to your representatives:</p>
|
|
|
|
<!-- Read-only preview -->
|
|
<div class="email-subject" id="preview-subject"></div>
|
|
<div class="email-body" id="preview-body"></div>
|
|
|
|
<!-- Editable fields -->
|
|
<input type="text" class="email-edit-subject" id="edit-subject" placeholder="Email Subject">
|
|
<textarea class="email-edit-body" id="edit-body" placeholder="Email Body"></textarea>
|
|
|
|
<div class="email-edit-actions">
|
|
<button type="button" class="btn btn-secondary" id="preview-email-btn">👁️ Preview</button>
|
|
<button type="button" class="btn btn-primary" id="save-email-btn">💾 Save Changes</button>
|
|
</div>
|
|
|
|
<!-- Preview mode actions -->
|
|
<div class="email-preview-actions" style="display: none; margin-top: 1rem; text-align: center;">
|
|
<button type="button" class="btn btn-secondary" id="edit-email-btn">✏️ Edit Email</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Representatives Section -->
|
|
<div id="representatives-section" style="display: none;">
|
|
<h2>Your Representatives</h2>
|
|
<p>Select how you'd like to contact each representative:</p>
|
|
|
|
<!-- Email Method Selection -->
|
|
<div id="email-method-selection" class="email-method-toggle">
|
|
<div class="method-option">
|
|
<input type="radio" id="method-smtp" name="emailMethod" value="smtp" checked>
|
|
<label for="method-smtp">📧 Send via our system</label>
|
|
</div>
|
|
<div class="method-option">
|
|
<input type="radio" id="method-mailto" name="emailMethod" value="mailto">
|
|
<label for="method-mailto">📬 Open in your email app</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="representatives-list" class="representatives-grid">
|
|
<!-- Representatives will be loaded here -->
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Response Wall Button -->
|
|
<div id="response-wall-section" class="response-wall-container" style="display: none;">
|
|
<h3>💬 See What People Are Saying</h3>
|
|
<p>Check out responses to people who have taken action on this campaign</p>
|
|
<a href="#" id="response-wall-link" class="response-wall-button">
|
|
View Response Wall
|
|
</a>
|
|
</div>
|
|
|
|
<!-- Success Message -->
|
|
<div id="success-section" style="display: none; text-align: center; padding: 2rem;">
|
|
<h2 style="color: #27ae60;">🎉 Thank you for taking action!</h2>
|
|
<p>Your emails have been processed. Democracy works when people like you get involved.</p>
|
|
<button class="btn btn-secondary" data-action="reload-page">Send More Emails</button>
|
|
</div>
|
|
|
|
<!-- Error Messages -->
|
|
<div id="error-message" class="error-message" style="display: none;"></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 Campaign</h2>
|
|
<div class="qrcode-container">
|
|
<img id="qrcode-image" src="" alt="Campaign QR Code">
|
|
</div>
|
|
<p class="qrcode-instructions">Scan this code with your phone to visit this campaign page</p>
|
|
<button class="btn btn-secondary" id="download-qrcode-btn">Download QR Code</button>
|
|
</div>
|
|
</div>
|
|
|
|
<footer style="text-align: center; margin-top: 2rem; padding: 1rem; border-top: 1px solid #e9ecef;">
|
|
<p>© 2025 <a href="https://bnkops.com/" target="_blank">BNKops</a> Influence Tool. Connect with democracy.</p>
|
|
<p><small><a href="/terms.html" id="terms-link" target="_blank">Terms of Use & Privacy Notice</a> | <a href="/index.html" id="home-link">Return to Main Page</a></small></p>
|
|
</footer>
|
|
|
|
<script src="/js/campaign.js"></script>
|
|
<script>
|
|
// Update footer links with APP_URL if needed for cross-origin scenarios
|
|
fetch('/api/config')
|
|
.then(res => res.json())
|
|
.then(config => {
|
|
if (config.appUrl && !window.location.href.startsWith(config.appUrl)) {
|
|
// Only update if we're on a different domain (e.g., CDN)
|
|
document.getElementById('terms-link').href = config.appUrl + '/terms.html';
|
|
document.getElementById('home-link').href = config.appUrl + '/index.html';
|
|
}
|
|
})
|
|
.catch(err => console.log('Config not loaded, using relative paths'));
|
|
</script>
|
|
</body>
|
|
</html> |