freealberta/map/app/public/admin.html
2025-07-17 19:40:31 -06:00

400 lines
19 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Admin Panel - BNKops Map - Interactive canvassing web-app & viewer">
<title>Admin Panel</title>
<!-- Favicon -->
<link rel="icon" type="image/x-icon" href="/favicon.ico">
<link rel="shortcut icon" href="/favicon.ico">
<!-- Leaflet CSS -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
crossorigin="" />
<!-- Custom CSS -->
<link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" href="css/admin.css">
</head>
<body>
<div id="app">
<!-- Header -->
<header class="header">
<button id="mobile-menu-toggle" class="mobile-menu-toggle">
<span></span>
<span></span>
<span></span>
</button>
<h1>Admin Panel</h1>
<div class="header-actions">
<a href="/" class="btn btn-secondary">← Back to Map</a>
<span id="admin-info" class="admin-info desktop-only"></span>
</div>
</header>
<!-- Main Content -->
<div class="admin-container">
<div class="admin-sidebar" id="admin-sidebar">
<div class="sidebar-header">
<h2>Admin Menu</h2>
<button id="close-sidebar" class="close-sidebar">×</button>
</div>
<nav class="admin-nav">
<a href="#start-location" class="active">
<span class="nav-icon">📍</span>
<span class="nav-text">Start Location</span>
</a>
<a href="#walk-sheet">
<span class="nav-icon">📄</span>
<span class="nav-text">Walk Sheet</span>
</a>
<a href="#shifts">
<span class="nav-icon">📅</span>
<span class="nav-text">Shifts</span>
</a>
<a href="#users">
<span class="nav-icon">👥</span>
<span class="nav-text">Users</span>
</a>
</nav>
<div class="sidebar-footer">
<div id="mobile-admin-info" class="mobile-admin-info mobile-only"></div>
</div>
</div>
<div class="admin-content">
<!-- Start Location Section -->
<section id="start-location" class="admin-section">
<h2>Map Start Location</h2>
<p>Set the default center point and zoom level for the map when users first load the application.</p>
<div class="admin-map-container">
<div id="admin-map" class="admin-map"></div>
<div class="location-controls">
<div class="form-group">
<label for="start-lat">Latitude</label>
<input type="number" id="start-lat" step="0.000001" min="-90" max="90">
</div>
<div class="form-group">
<label for="start-lng">Longitude</label>
<input type="number" id="start-lng" step="0.000001" min="-180" max="180">
</div>
<div class="form-group">
<label for="start-zoom">Zoom Level</label>
<input type="number" id="start-zoom" min="2" max="19" step="1">
</div>
<div class="form-actions">
<button id="use-current-view" class="btn btn-secondary">
Use Current Map View
</button>
<button id="save-start-location" class="btn btn-primary">
Save Start Location
</button>
</div>
<div class="help-text">
<p>💡 Tip: Navigate the map to your desired location and zoom level, then click "Use Current Map View" to capture the coordinates.</p>
</div>
</div>
</div>
</section>
<!-- Walk Sheet Section -->
<section id="walk-sheet" class="admin-section" style="display: none;">
<h2>Walk Sheet Configuration</h2>
<p>Design and configure printable walk sheets for door-to-door canvassing.</p>
<div class="walk-sheet-container">
<div class="walk-sheet-config">
<h3>Sheet Information</h3>
<div class="form-group">
<label for="walk-sheet-title">Sheet Title</label>
<input type="text" id="walk-sheet-title" placeholder="Campaign Walk Sheet">
</div>
<div class="form-group">
<label for="walk-sheet-subtitle">Subtitle</label>
<input type="text" id="walk-sheet-subtitle" placeholder="Door-to-Door Canvassing Form">
</div>
<div class="form-group">
<label for="walk-sheet-footer">Footer Text</label>
<textarea id="walk-sheet-footer" rows="3" placeholder="Contact info, legal text, etc."></textarea>
</div>
<h3>QR Codes</h3>
<p class="help-text-inline">Add up to 3 QR codes for quick access to digital resources.</p>
<!-- QR Code 1 -->
<div class="qr-code-group">
<h4>QR Code 1</h4>
<div class="form-row">
<div class="form-group">
<label for="qr-code-1-url">URL</label>
<input type="url" id="qr-code-1-url" placeholder="https://example.com/signup">
</div>
<div class="form-group">
<label for="qr-code-1-label">Label</label>
<input type="text" id="qr-code-1-label" placeholder="Sign Up">
</div>
</div>
</div>
<!-- QR Code 2 -->
<div class="qr-code-group">
<h4>QR Code 2</h4>
<div class="form-row">
<div class="form-group">
<label for="qr-code-2-url">URL</label>
<input type="url" id="qr-code-2-url" placeholder="https://example.com/donate">
</div>
<div class="form-group">
<label for="qr-code-2-label">Label</label>
<input type="text" id="qr-code-2-label" placeholder="Donate">
</div>
</div>
</div>
<!-- QR Code 3 -->
<div class="qr-code-group">
<h4>QR Code 3</h4>
<div class="form-row">
<div class="form-group">
<label for="qr-code-3-url">URL</label>
<input type="url" id="qr-code-3-url" placeholder="https://example.com/volunteer">
</div>
<div class="form-group">
<label for="qr-code-3-label">Label</label>
<input type="text" id="qr-code-3-label" placeholder="Volunteer">
</div>
</div>
</div>
<div class="form-actions">
<button id="save-walk-sheet" class="btn btn-primary">
Save Configuration
</button>
<button id="print-walk-sheet" class="btn btn-secondary">
🖨️ Print Sheet
</button>
</div>
</div>
<div class="walk-sheet-preview">
<h3>Preview</h3>
<div class="preview-controls">
<span class="preview-info">8.5" x 11" format</span>
</div>
<div id="walk-sheet-preview-content" class="walk-sheet-page">
<!-- Preview content will be generated here -->
</div>
</div>
</div>
</section>
<!-- Shifts Section -->
<section id="shifts" class="admin-section" style="display: none;">
<h2>Shift Management</h2>
<p>Create and manage volunteer shifts.</p>
<div class="shifts-admin-container">
<div class="shift-form">
<h3>Create New Shift</h3>
<form id="shift-form">
<div class="form-group">
<label for="shift-title">Title</label>
<input type="text" id="shift-title" required>
</div>
<div class="form-group">
<label for="shift-description">Description</label>
<textarea id="shift-description" rows="3"></textarea>
</div>
<div class="form-row">
<div class="form-group">
<label for="shift-date">Date</label>
<input type="date" id="shift-date" required>
</div>
<div class="form-group">
<label for="shift-start">Start Time</label>
<input type="time" id="shift-start" required>
</div>
<div class="form-group">
<label for="shift-end">End Time</label>
<input type="time" id="shift-end" required>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="shift-location">Location</label>
<input type="text" id="shift-location">
</div>
<div class="form-group">
<label for="shift-max-volunteers">Max Volunteers</label>
<input type="number" id="shift-max-volunteers" min="1" required>
</div>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">Create Shift</button>
<button type="button" class="btn btn-secondary" id="clear-shift-form">Clear</button>
</div>
</form>
</div>
<div class="shifts-list">
<h3>Existing Shifts</h3>
<div id="admin-shifts-list">
<!-- Shifts will be loaded here -->
</div>
</div>
</div>
</section>
<!-- Users Section -->
<section id="users" class="admin-section" style="display: none;">
<h2>User Management</h2>
<p>Create and manage user accounts for the application.</p>
<div class="users-admin-container">
<div class="user-form">
<h3>Create New User</h3>
<form id="user-form">
<div class="form-group">
<label for="user-email">Email *</label>
<input type="email" id="user-email" required>
</div>
<div class="form-group">
<label for="user-password">Password *</label>
<input type="password" id="user-password" required minlength="6">
</div>
<div class="form-group">
<label for="user-name">Name</label>
<input type="text" id="user-name">
</div>
<div class="form-group">
<label>
<input type="checkbox" id="user-admin"> Admin Access
</label>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">Create User</button>
<button type="button" class="btn btn-secondary" id="clear-user-form">Clear</button>
</div>
</form>
</div>
<div class="users-list">
<h3>Existing Users</h3>
<div id="users-table-container">
<table id="users-table" class="users-table">
<thead>
<tr>
<th>Email</th>
<th>Name</th>
<th>Admin</th>
<th>Created</th>
<th>Actions</th>
</tr>
</thead>
<tbody id="users-table-body">
<!-- Users will be loaded here -->
</tbody>
</table>
</div>
<div id="users-loading" class="loading-message" style="display: none;">
Loading users...
</div>
<div id="users-empty" class="empty-message" style="display: none;">
No users found.
</div>
</div>
</div>
</section>
</div>
</div>
<!-- Status Messages -->
<div id="status-container" class="status-container"></div>
</div>
<!-- Leaflet JS -->
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
crossorigin=""></script>
<!-- Custom QR Code Implementation -->
<script>
// Simple QR Code implementation using our server
window.QRCode = {
toCanvas: function(canvas, text, options, callback) {
if (typeof options === 'function') {
callback = options;
options = {};
}
const size = options.width || 200;
const qrUrl = `/api/qr?text=${encodeURIComponent(text)}&size=${size}`;
const img = new Image();
img.crossOrigin = 'anonymous';
img.onload = function() {
canvas.width = size;
canvas.height = size;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, size, size);
if (callback) callback(null);
};
img.onerror = function() {
console.error('Failed to load QR code from server');
// Fallback: draw a simple placeholder
canvas.width = size;
canvas.height = size;
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#ffffff';
ctx.fillRect(0, 0, size, size);
ctx.fillStyle = '#000000';
ctx.font = '12px Arial';
ctx.textAlign = 'center';
ctx.fillText('QR Code', size/2, size/2 - 10);
ctx.fillText('(Failed)', size/2, size/2 + 10);
if (callback) callback(new Error('Failed to load QR code'));
};
img.src = qrUrl;
}
};
console.log('Local QR Code implementation loaded');
</script>
<!-- Admin JavaScript -->
<script src="js/admin.js"></script>
</body>
</html>