115 lines
4.8 KiB
HTML
115 lines
4.8 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>{% block title %}Grassroots Campaign Manager{% endblock %}</title>
|
|
|
|
<!-- Bootstrap 5 CSS -->
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
<!-- Bootstrap Icons -->
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css">
|
|
|
|
{% load static %}
|
|
<link rel="stylesheet" href="{% static 'css/custom.css' %}?v={{ deployment_timestamp }}">
|
|
|
|
{% if project_description %}
|
|
<meta name="description" content="{{ project_description }}">
|
|
{% endif %}
|
|
|
|
{% block head %}{% endblock %}
|
|
</head>
|
|
<body>
|
|
<nav class="navbar navbar-expand-lg sticky-top">
|
|
<div class="container">
|
|
<a class="navbar-brand d-flex align-items-center" href="/">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" class="bi bi-person-check-fill me-2" viewBox="0 0 16 16">
|
|
<path fill-rule="evenodd" d="M15.854 5.146a.5.5 0 0 1 0 .708l-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 0 1 .708-.708L12.5 7.793l2.646-2.647a.5.5 0 0 1 .708 0z"/>
|
|
<path d="M1 14s-1 0-1-1 1-4 6-4 6 3 6 4-1 1-1 1H1zm5-6a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"/>
|
|
</svg>
|
|
Grassroots
|
|
</a>
|
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
|
<span class="navbar-toggler-icon"></span>
|
|
</button>
|
|
<div class="collapse navbar-collapse" id="navbarNav">
|
|
<ul class="navbar-nav me-auto">
|
|
<li class="nav-item">
|
|
<a class="nav-link" href="/">Dashboard</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a class="nav-link" href="/voters/">Voters</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a class="nav-link" href="/events/">Events</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a class="nav-link" href="/volunteers/">Volunteers</a>
|
|
</li>
|
|
</ul>
|
|
<div class="d-flex align-items-center">
|
|
<a href="/admin/" class="btn btn-outline-primary btn-sm me-2">Admin Panel</a>
|
|
{% if user.is_authenticated %}
|
|
<span class="text-muted small me-2">{{ user.username }}</span>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<main>
|
|
{% if messages %}
|
|
<div class="container mt-3">
|
|
{% for message in messages %}
|
|
<div class="alert alert-{% if message.tags == 'error' %}danger{% else %}{{ message.tags }}{% endif %} alert-dismissible fade show" role="alert">
|
|
{{ message }}
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% block content %}{% endblock %}
|
|
</main>
|
|
|
|
<footer class="py-5 bg-white border-top mt-5">
|
|
<div class="container text-center">
|
|
<p class="text-muted mb-0">© 2026 Grassroots Campaign Manager. All rights reserved.</p>
|
|
</div>
|
|
</footer>
|
|
|
|
<!-- Bootstrap 5 JS Bundle -->
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
function formatPhoneNumber(value) {
|
|
if (!value) return value;
|
|
const phoneNumber = value.replace(/[^\d]/g, '');
|
|
const phoneNumberLength = phoneNumber.length;
|
|
if (phoneNumberLength < 4) return phoneNumber;
|
|
if (phoneNumberLength < 7) {
|
|
return `(${phoneNumber.slice(0, 3)}) ${phoneNumber.slice(3)}`;
|
|
}
|
|
return `(${phoneNumber.slice(0, 3)}) ${phoneNumber.slice(3, 6)}-${phoneNumber.slice(6, 10)}`;
|
|
}
|
|
|
|
function phoneNumberFormatter() {
|
|
const inputField = this;
|
|
const formattedFieldValue = formatPhoneNumber(inputField.value);
|
|
inputField.value = formattedFieldValue;
|
|
}
|
|
|
|
const phoneInputs = document.querySelectorAll('input[name="phone"], input[type="tel"]');
|
|
phoneInputs.forEach(input => {
|
|
input.addEventListener('input', phoneNumberFormatter);
|
|
// Also format on load if it has a value
|
|
if (input.value) {
|
|
input.value = formatPhoneNumber(input.value);
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|