minor update

This commit is contained in:
2025-08-25 13:52:30 +05:30
parent c9bba5478b
commit 17f309dcda
8 changed files with 119 additions and 20 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
+54 -19
View File
@@ -34,37 +34,72 @@ class IssueCategory(models.Model):
def __str__(self):
return self.name
# issues/models.py
class Issue(models.Model):
STATUS_REPORTED = 'reported'
STATUS_ACKNOWLEDGED = 'acknowledged'
STATUS_IN_PROGRESS = 'in_progress'
STATUS_RESOLVED = 'resolved'
STATUS_CHOICES = [
('reported', 'Reported'),
('acknowledged', 'Acknowledged'),
('in_progress', 'In Progress'),
('resolved', 'Resolved'),
(STATUS_REPORTED, 'Reported'),
(STATUS_ACKNOWLEDGED, 'Acknowledged'),
(STATUS_IN_PROGRESS, 'In Progress'),
(STATUS_RESOLVED, 'Resolved'),
]
title = models.CharField(max_length=200)
description = models.TextField()
category = models.ForeignKey(IssueCategory, on_delete=models.SET_NULL, null=True, blank=True)
reporter = models.ForeignKey(User, on_delete=models.CASCADE, related_name='reported_issues')
location = models.CharField(max_length=200)
latitude = models.FloatField()
longitude = models.FloatField()
photo = models.ImageField(upload_to='issue_photos/', blank=True, null=True,
validators=[FileExtensionValidator(['jpg', 'jpeg', 'png', 'gif'])])
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='reported')
category = models.ForeignKey(
"IssueCategory",
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="issues"
)
reporter = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name="reported_issues"
)
location = models.CharField(max_length=200, blank=True)
latitude = models.FloatField(null=True, blank=True)
longitude = models.FloatField(null=True, blank=True)
photo = models.ImageField(
upload_to="issue_photos/",
blank=True,
null=True,
validators=[FileExtensionValidator(['jpg', 'jpeg', 'png', 'gif'])]
)
status = models.CharField(
max_length=20,
choices=STATUS_CHOICES,
default=STATUS_REPORTED
)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ["-created_at"] # 🔹 latest issues first by default
def __str__(self):
return self.title
return f"{self.title} ({self.get_status_display()})"
# 🔹 Helpers
def vote_count(self):
return self.votes.count()
return self.votes.count() if hasattr(self, "votes") else 0
def has_user_voted(self, user):
if user.is_authenticated:
if user.is_authenticated and hasattr(self, "votes"):
return self.votes.filter(user=user).exists()
return False
class Vote(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
@@ -19,6 +19,9 @@
<i class="fas fa-building me-2 text-success"></i>
<a href="{% url 'manage_departments' %}">Manage Departments</a>
</li>
<li class="list-group-item">
<a href="{% url 'manage_issues' %}">Manage Issues</a>
</li>
<li class="list-group-item">
<a href="#">Manage Roles & Permissions</a>
</li>
@@ -0,0 +1,53 @@
{% extends "core/base.html" %}
{% block content %}
<div class="container my-5">
<div class="card shadow-lg">
<div class="card-header bg-warning text-dark">
<h3>Manage Issues</h3>
</div>
<div class="card-body">
{% if issues %}
<table class="table table-bordered table-hover">
<thead class="table-light">
<tr>
<th>#</th>
<th>Title</th>
<th>Category</th>
<th>Reported By</th>
<th>Status</th>
<th>Created At</th>
</tr>
</thead>
<tbody>
{% for issue in issues %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ issue.title }}</td>
<td>{{ issue.category.name|default:"—" }}</td>
<td>{{ issue.reporter.username }}</td>
<td>
{% if issue.status == "reported" %}
<span class="badge bg-danger">Reported</span>
{% elif issue.status == "acknowledged" %}
<span class="badge bg-info text-dark">Acknowledged</span>
{% elif issue.status == "in_progress" %}
<span class="badge bg-warning text-dark">In Progress</span>
{% elif issue.status == "resolved" %}
<span class="badge bg-success">Resolved</span>
{% else %}
<span class="badge bg-secondary">Unknown</span>
{% endif %}
</td>
<td>{{ issue.created_at|date:"M d, Y H:i" }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p class="text-muted">No issues reported yet.</p>
{% endif %}
</div>
</div>
</div>
{% endblock %}
+2
View File
@@ -7,6 +7,8 @@ urlpatterns = [
path("superadmin/", views.superadmin_dashboard, name="superadmin_dashboard"),
path("superadmin/departments/", views.manage_departments, name="manage_departments"),
path("superadmin/departments/<int:pk>/", views.department_detail, name="department_detail"),
path("superadmin/manage/", views.manage_issues, name="manage_issues"),
path('register/', views.register, name='register'),
path('login/', views.custom_login, name='login'),
path('logout/', auth_views.LogoutView.as_view(), name='logout'),
+7 -1
View File
@@ -266,4 +266,10 @@ def department_detail(request, pk):
return render(request, "department/department_detail.html", {
"department": department,
"users": users,
})
})
@login_required
@user_passes_test(superadmin_check)
def manage_issues(request):
issues = Issue.objects.all().order_by("-created_at")
return render(request, "issues/manage_issues.html", {"issues": issues})