major updation
This commit is contained in:
@@ -35,32 +35,56 @@
|
||||
<body>
|
||||
<!-- Navigation -->
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark sticky-top">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="{% url 'home' %}">
|
||||
<i class="fas fa-bullhorn me-2"></i>Civixfix
|
||||
</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 active" href="{% url 'home' %}">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#features">Features</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#how-it-works">How It Works</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="d-flex">
|
||||
<a href="{% url 'login' %}" class="btn btn-outline-light me-2">Login</a>
|
||||
<a href="{% url 'register' %}" class="btn btn-primary">Register</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="{% url 'home' %}">
|
||||
<i class="fas fa-bullhorn me-2"></i>Civixfix
|
||||
</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 active" href="{% url 'home' %}">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#features">Features</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#how-it-works">How It Works</a>
|
||||
</li>
|
||||
{% if user.is_authenticated and user.is_citizen %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'citizen_dashboard' %}">Dashboard</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
<div class="d-flex">
|
||||
{% if user.is_authenticated %}
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-outline-light dropdown-toggle" type="button" data-bs-toggle="dropdown">
|
||||
<i class="fas fa-user me-1"></i> {{ user.username }}
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-end">
|
||||
<li><a class="dropdown-item" href="{% url 'citizen_dashboard' %}">Dashboard</a></li>
|
||||
<li><a class="dropdown-item" href="#">Profile</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li>
|
||||
<form method="post" action="{% url 'logout' %}">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="dropdown-item">Logout</button>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{% else %}
|
||||
<a href="{% url 'login' %}" class="btn btn-outline-light me-2">Login</a>
|
||||
<a href="{% url 'register' %}" class="btn btn-primary">Register</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- Main Content -->
|
||||
<main>
|
||||
|
||||
@@ -0,0 +1,240 @@
|
||||
{% extends "core/base.html" %}
|
||||
{% block title %}Citizen Dashboard - CivixFix{% endblock %}
|
||||
|
||||
{% block extra_css %}
|
||||
<style>
|
||||
.dashboard-card {
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
.dashboard-card:hover {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
.map-container {
|
||||
height: 300px;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
border: 2px dashed #dee2e6;
|
||||
}
|
||||
.issue-status {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container-fluid py-4">
|
||||
<div class="row">
|
||||
<!-- Sidebar - Quick Actions -->
|
||||
<div class="col-md-3">
|
||||
<div class="card shadow-sm dashboard-card">
|
||||
<div class="card-body text-center">
|
||||
<h5 class="card-title">Welcome, {{ user.username }}</h5>
|
||||
<p class="text-muted">Citizen Dashboard</p>
|
||||
|
||||
<div class="d-grid gap-2 mb-3">
|
||||
<button class="btn btn-primary btn-lg" data-bs-toggle="modal" data-bs-target="#reportIssueModal">
|
||||
<i class="fas fa-plus me-2"></i>Report New Issue
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<h6>Quick Stats</h6>
|
||||
<div class="row text-center">
|
||||
<div class="col-6">
|
||||
<div class="bg-light p-2 rounded">
|
||||
<h4 class="mb-0 text-primary">{{ user_issues.count }}</h4>
|
||||
<small>My Reports</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="bg-light p-2 rounded">
|
||||
<h4 class="mb-0 text-success">
|
||||
{{ resolved_count }}
|
||||
</h4>
|
||||
<small>Resolved</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Content - Recent Issues -->
|
||||
<div class="col-md-9">
|
||||
<!-- Welcome Message -->
|
||||
<div class="card shadow-sm dashboard-card mb-4">
|
||||
<div class="card-body">
|
||||
<h4>Welcome to CivixFix!</h4>
|
||||
<p class="text-muted mb-0">
|
||||
Report community issues, track their progress, and help make your neighborhood better.
|
||||
Start by reporting an issue using the button on the left.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- My Recent Issues -->
|
||||
<div class="card shadow-sm dashboard-card">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">My Recent Reports</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% for issue in user_issues %}
|
||||
<div class="card mb-3">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-start">
|
||||
<div class="flex-grow-1">
|
||||
<h6 class="card-title mb-1">{{ issue.title }}</h6>
|
||||
<p class="card-text text-muted mb-2 small">
|
||||
{{ issue.description|truncatewords:15 }}
|
||||
</p>
|
||||
<div class="d-flex gap-2 align-items-center">
|
||||
<span class="badge bg-secondary">{{ issue.category.name|default:"No Category" }}</span>
|
||||
<span class="badge bg-{% if issue.status == 'resolved' %}success{% elif issue.status == 'in_progress' %}warning{% else %}primary{% endif %} issue-status">
|
||||
{{ issue.get_status_display }}
|
||||
</span>
|
||||
<small class="text-muted">{{ issue.created_at|date:"M d, Y" }}</small>
|
||||
</div>
|
||||
</div>
|
||||
{% if issue.photo %}
|
||||
<div class="ms-3">
|
||||
<img src="{{ issue.photo.url }}" alt="Issue photo"
|
||||
class="img-fluid rounded" style="max-height: 60px; max-width: 80px;">
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% empty %}
|
||||
<div class="text-center py-4">
|
||||
<i class="fas fa-inbox fa-3x text-muted mb-3"></i>
|
||||
<h5>No issues reported yet</h5>
|
||||
<p class="text-muted">Click "Report New Issue" to get started!</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Report Issue Modal -->
|
||||
<div class="modal fade" id="reportIssueModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Report New Issue</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="issueForm" method="post" enctype="multipart/form-data" action="{% url 'report_issue' %}">
|
||||
{% csrf_token %}
|
||||
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
<div class="alert alert-{{ message.tags }} alert-dismissible fade show mb-3">
|
||||
{{ message }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Issue Title*</label>
|
||||
{{ issue_form.title }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Category</label>
|
||||
{{ issue_form.category }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Description*</label>
|
||||
{{ issue_form.description }}
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Location*</label>
|
||||
{{ issue_form.location }}
|
||||
<small class="text-muted">Click on the map to select location</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Photo (Optional)</label>
|
||||
{{ issue_form.photo }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Hidden latitude/longitude fields -->
|
||||
{{ issue_form.latitude }}
|
||||
{{ issue_form.longitude }}
|
||||
|
||||
<div class="map-container mb-3">
|
||||
<div id="map" style="height: 100%;"></div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="submit" form="issueForm" class="btn btn-primary">
|
||||
<i class="fas fa-paper-plane me-2"></i>Report Issue
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_js %}
|
||||
<!-- Leaflet JS -->
|
||||
<script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Initialize map
|
||||
const map = L.map('map').setView([51.505, -0.09], 13);
|
||||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
attribution: '© OpenStreetMap contributors'
|
||||
}).addTo(map);
|
||||
|
||||
let marker = null;
|
||||
|
||||
// Add click event to map
|
||||
map.on('click', function(e) {
|
||||
if (marker) {
|
||||
map.removeLayer(marker);
|
||||
}
|
||||
|
||||
marker = L.marker(e.latlng).addTo(map)
|
||||
.bindPopup('Selected location').openPopup();
|
||||
|
||||
// Update form fields
|
||||
$('#id_latitude').val(e.latlng.lat);
|
||||
$('#id_longitude').val(e.latlng.lng);
|
||||
|
||||
// Reverse geocode to get address
|
||||
fetch(`https://nominatim.openstreetmap.org/reverse?format=json&lat=${e.latlng.lat}&lon=${e.latlng.lng}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
$('#id_location').val(data.display_name || 'Selected location');
|
||||
});
|
||||
});
|
||||
|
||||
// Add Bootstrap classes to form fields
|
||||
$('input:not([type="file"]), select, textarea').addClass('form-control');
|
||||
$('input[type="file"]').addClass('form-control-file');
|
||||
|
||||
// Add specific classes to description field
|
||||
$('#id_description').addClass('form-control').attr('rows', '3');
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,54 @@
|
||||
{% extends "core/base.html" %}
|
||||
|
||||
{% block title %}Login{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container py-5">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<div class="card shadow">
|
||||
<div class="card-body p-5">
|
||||
<h2 class="card-title text-center mb-4">Login to Your Account</h2>
|
||||
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
<div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert">
|
||||
{{ message }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="id_username" class="form-label">Username</label>
|
||||
<input type="text" name="username" class="form-control" id="id_username" required>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label for="id_password" class="form-label">Password</label>
|
||||
<input type="password" name="password" class="form-control" id="id_password" required>
|
||||
</div>
|
||||
|
||||
<div class="d-grid mb-3">
|
||||
<button type="submit" class="btn btn-primary btn-lg">Login</button>
|
||||
</div>
|
||||
|
||||
<div class="text-center">
|
||||
<a href="#" class="text-decoration-none">Forgot password?</a>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<hr class="my-4">
|
||||
|
||||
<p class="text-center text-muted">
|
||||
Don't have an account? <a href="{% url 'register' %}" class="text-decoration-none">Register here</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,5 +1,4 @@
|
||||
{% extends "core/base.html" %}
|
||||
|
||||
{% block title %}Register as Citizen{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
@@ -9,38 +8,50 @@
|
||||
<div class="card shadow">
|
||||
<div class="card-body p-5">
|
||||
<h2 class="card-title text-center mb-4">Create Citizen Account</h2>
|
||||
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
{# Messages block - FIXED SYNTAX #}
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
<div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert">
|
||||
{{ message }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{# Form errors block - FIXED SYNTAX #}
|
||||
{% if form.errors %}
|
||||
<div class="alert alert-danger">
|
||||
<strong>Error!</strong> Please correct the following:
|
||||
<ul>
|
||||
<div class="alert alert-danger">
|
||||
<strong>Error!</strong> Please correct the following:
|
||||
<ul>
|
||||
{% for field, errors in form.errors.items %}
|
||||
{% for error in errors %}
|
||||
<li>{{ error }}</li>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="id_username" class="form-label">Username</label>
|
||||
{{ form.username }}
|
||||
<small class="text-muted">Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.</small>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="id_email" class="form-label">Email</label>
|
||||
{{ form.email }}
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="id_phone" class="form-label">Phone (Optional)</label>
|
||||
{{ form.phone }}
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="id_password1" class="form-label">Password</label>
|
||||
{{ form.password1 }}
|
||||
@@ -53,20 +64,20 @@
|
||||
</ul>
|
||||
</small>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-4">
|
||||
<label for="id_password2" class="form-label">Password Confirmation</label>
|
||||
{{ form.password2 }}
|
||||
<small class="text-muted">Enter the same password as before, for verification.</small>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="d-grid">
|
||||
<button type="submit" class="btn btn-primary btn-lg">Register</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
<hr class="my-4">
|
||||
|
||||
|
||||
<p class="text-center text-muted">
|
||||
Already have an account? <a href="{% url 'login' %}" class="text-decoration-none">Login here</a>
|
||||
</p>
|
||||
@@ -79,10 +90,14 @@
|
||||
|
||||
{% block extra_js %}
|
||||
<script>
|
||||
// Add Bootstrap classes to form fields
|
||||
$(document).ready(function() {
|
||||
$('input').addClass('form-control');
|
||||
$(document).ready(function () {
|
||||
// Add Bootstrap classes to all input fields
|
||||
$('input:not([type="checkbox"]):not([type="radio"])').addClass('form-control');
|
||||
$('input[type="checkbox"]').removeClass('form-control').addClass('form-check-input');
|
||||
$('input[type="radio"]').removeClass('form-control').addClass('form-check-input');
|
||||
|
||||
// Add Bootstrap classes to select fields
|
||||
$('select').addClass('form-select');
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user