Compare commits

..

10 Commits

Author SHA1 Message Date
Gokuldevx ab7373fc34 initial commit 2026-02-02 10:52:20 +05:30
Gokuldevx 2767fdf674 update 2025-09-08 17:56:45 +05:30
Gokuldevx be2dc882b3 initial commit 2025-08-28 16:00:16 +05:30
Gokuldevx 345887d56f initial commit 2025-08-28 15:26:04 +05:30
Gokuldevx 0c838571a2 initial commit 2025-08-28 15:22:46 +05:30
Gokuldevx 2d0bbe73bd initial commit 2025-08-28 15:11:40 +05:30
Gokuldevx 70ae15064c initial commit 2025-08-28 14:55:03 +05:30
Gokuldevx 143dd17e6b initial commit 2025-08-28 14:52:13 +05:30
Gokuldevx c67538d474 initial commit 2025-08-28 12:40:12 +05:30
Gokuldevx 716461af49 initial commit 2025-08-28 11:46:58 +05:30
77 changed files with 115 additions and 123 deletions
+2 -2
View File
@@ -1,2 +1,2 @@
civicenv
civicProject.code-workspace
.env
issue_photos/
View File
-10
View File
@@ -1,10 +0,0 @@
SECRET_KEY="django-insecure-wa6p9d+go#+evjql%m(+e5eti$%z7yx2o#cbq8bsh!==icxua3"
DEBUG="False"
CLOUD_NAME="dkxbfoesf"
API_KEY="658671916285379"
API_SECRET="_CwNDj4L2dE9yH90Ynj7slPlbo0"
CLOUDINARY_URL="cloudinary://658671916285379:_CwNDj4L2dE9yH90Ynj7slPlbo0@dkxbfoesf"
DATABASE_URL="postgresql://civicfix_user:YG56PWj9Xj1DvYIKF35TKmIEjrsfis6d@dpg-d2mpapripnbc73f5vaj0-a.oregon-postgres.render.com/civicfix"
SUPERUSER_USERNAME="admin"
SUPERUSER_PASSWORD="82c96bb18606401630ab9d2836325fbd"
SUPERUSER_EMAIL="gokuldevse2001@gmail.com"
-2
View File
@@ -1,2 +0,0 @@
.env
issue_photos/
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,78 +0,0 @@
{% extends "core/base.html" %}
{% block content %}
<div class="container my-5">
<div class="card shadow-lg">
<div class="card-header bg-warning text-black d-flex justify-content-between align-items-center">
<h3>Manage Issues</h3>
<a href="{% url 'superadmin_dashboard' %}" class="btn btn-light btn-sm">Back to Dashboard</a>
</div>
<div class="card-body">
{% if issues %}
<table class="table table-bordered table-hover">
<thead class="table-light">
<tr>
<th>No.</th>
<th>Title</th>
<th>Reported By</th>
<th>Status</th>
<th>Created At</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for issue in issues %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ issue.title }}</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>
<td>
{% if issue.department %}
<span class="fw-bold text-primary">{{ issue.department.name }}</span>
{% else %}
<!-- Assign Department Form -->
<form method="post" action="" class="d-inline">
{% csrf_token %}
<input type="hidden" name="issue_id" value="{{ issue.id }}">
<select name="department" class="form-select form-select-sm d-inline w-auto">
<option value="">— Select Department —</option>
{% for dept in departments %}
<option value="{{ dept.id }}">{{ dept.name }}</option>
{% endfor %}
</select>
<button type="submit" class="btn btn-sm btn-primary">Assign</button>
</form>
<!-- Report Fake Button -->
<a href="{% url 'delete_fake_issue' issue.id %}"
class="btn btn-sm btn-danger ms-1"
onclick="return confirm('Are you sure you want to delete this issue as FAKE?');">
<i class="fas fa-ban"></i> Report Fake
</a>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p class="text-muted">No issues reported yet.</p>
{% endif %}
</div>
</div>
</div>
{% endblock %}
@@ -24,17 +24,19 @@ INSTALLED_APPS = [
'django.contrib.humanize',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# Third-party
'cloudinary',
'cloudinary_storage',
'django.contrib.staticfiles',
'whitenoise.runserver_nostatic',
# Local apps
'core.apps.CoreConfig',
]
CLOUDINARY_STORAGE = {
'CLOUD_NAME': os.getenv('CLOUD_NAME'),
'API_KEY': os.getenv('API_KEY'),
'API_SECRET': os.getenv('API_SECRET'),
}
AUTH_USER_MODEL = 'core.User'
MIDDLEWARE = [
@@ -93,17 +95,20 @@ USE_TZ = True
# Static & Media files
STATIC_URL = "/static/"
STATIC_ROOT = BASE_DIR / "staticfiles"
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
cloudinary.config(
cloud_name = os.getenv("CLOUD_NAME"),
api_key = os.getenv("API_KEY"),
api_secret = os.getenv("API_SECRET")
cloud_name=os.getenv("CLOUD_NAME"),
api_key=os.getenv("API_KEY"),
api_secret=os.getenv("API_SECRET"),
secure=True
)
MEDIA_URL = f"https://res.cloudinary.com/{os.getenv('CLOUD_NAME')}/"
# Default storage (Cloudinary)
DEFAULT_FILE_STORAGE = 'cloudinary_storage.storage.MediaCloudinaryStorage'
# Auth redirects
LOGIN_REDIRECT_URL = 'citizen_dashboard'
LOGIN_URL = 'login'
-16
View File
@@ -1,16 +0,0 @@
<!-- base.html -->
{% load static %}
<!DOCTYPE html>
<html>
<head>
<title>Civixfix - {% block title %}{% endblock %}</title>
<link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet">
</head>
<body>
<div class="container mt-4">
{% block content %}{% endblock %}
</div>
<script src="{% static 'js/bootstrap.bundle.min.js' %}"></script>
</body>
</html>
Binary file not shown.
Binary file not shown.
Binary file not shown.
+3 -3
View File
@@ -1,3 +1,4 @@
from cloudinary.models import CloudinaryField
from datetime import timedelta
from django.contrib.auth.models import AbstractUser
from django.core.validators import FileExtensionValidator
@@ -116,11 +117,10 @@ class Issue(models.Model):
latitude = models.FloatField(null=True, blank=True)
longitude = models.FloatField(null=True, blank=True)
photo = models.ImageField(
upload_to="issue_photos/",
photo = CloudinaryField(
'images',
blank=True,
null=True,
validators=[FileExtensionValidator(['jpg', 'jpeg', 'png', 'gif'])]
)
status = models.CharField(
@@ -22,6 +22,7 @@
<th>#</th>
<th>Title</th>
<th>Reported By</th>
<th>Location</th>
<th>Status</th>
<th>Created At</th>
<th>Action</th>
@@ -33,6 +34,7 @@
<td>{{ forloop.counter }}</td>
<td>{{ issue.title }}</td>
<td>{{ issue.reporter.username }}</td>
<td>{{ issue.location }}</td>
<td>
{% if issue.status == "reported" %}
<span class="badge bg-danger">Reported</span>
@@ -46,6 +48,7 @@
<span class="badge bg-secondary">Unknown</span>
{% endif %}
</td>
<td>{{ issue.created_at|date:"M d, Y H:i" }}</td>
<td>
{% if issue.status in "reported,acknowledged" %}
+81
View File
@@ -0,0 +1,81 @@
{% extends "core/base.html" %}
{% block content %}
<div class="container my-5">
<div class="card shadow-lg">
<div class="card-header bg-warning text-black d-flex justify-content-between align-items-center">
<h3>Manage Issues</h3>
<a href="{% url 'superadmin_dashboard' %}" class="btn btn-light btn-sm">Back to Dashboard</a>
</div>
<div class="card-body">
{% if issues %}
<table class="table table-bordered table-hover">
<thead class="table-light">
<tr>
<th>No.</th>
<th>Title</th>
<th>Reported By</th>
<th>Status</th>
<th>Created At</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for issue in issues %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ issue.title }}</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>
<td>
{% if issue.department %}
<span class="fw-bold text-primary">{{ issue.department.name }}</span>
{% else %}
<!-- Assign Department Form -->
<form method="post" action="" class="d-inline">
{% csrf_token %}
<input type="hidden" name="issue_id" value="{{ issue.id }}">
<select name="department" class="form-select form-select-sm d-inline w-auto">
<option value="">— Select Department —</option>
{% for dept in departments %}
<option value="{{ dept.id }}">{{ dept.name }}</option>
{% endfor %}
</select>
<button type="submit" class="btn btn-sm btn-primary">Assign</button>
</form>
<!-- Report Fake Button -->
<a href="{% url 'delete_fake_issue' issue.id %}" class="btn btn-sm btn-danger ms-1"
onclick="return confirm('Are you sure you want to delete this issue as FAKE?');">
<i class="fas fa-ban"></i> Report Fake
</a>
<a href="{% url 'delete_issue' issue.id %}" class="btn btn-sm btn-outline-danger ms-1"
onclick="return confirm('Are you sure you want to permanently delete this issue? This cannot be undone.');">
<i class="fas fa-trash"></i> Delete
</a>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p class="text-muted">No issues reported yet.</p>
{% endif %}
</div>
</div>
</div>
{% endblock %}
+1
View File
@@ -26,4 +26,5 @@ urlpatterns = [
path('unban-user/<int:user_id>/', views.unban_user, name='unban_user'),
path('issues/<int:issue_id>/delete_fake/', views.delete_fake_issue, name='delete_fake_issue'),
path("reports/", views.superadmin_reports, name="superadmin_reports"),
path('delete-issue/<int:issue_id>/', views.delete_issue, name='delete_issue'),
]
+10 -2
View File
@@ -76,8 +76,8 @@ def report_issue(request):
@login_required
def view_all_issues(request):
if not request.user.is_citizen:
messages.error(request, 'Access denied. Citizen role required.')
if not request.user.is_active:
messages.error(request, 'Access denied.')
return redirect('home')
# Efficiently annotate whether the current user has voted
@@ -384,6 +384,14 @@ def superadmin_reports(request):
}
return render(request, "core/superadmin_reports.html", context)
@login_required
@user_passes_test(superadmin_check)
def delete_issue(request, issue_id):
issue = get_object_or_404(Issue, id=issue_id)
issue.delete()
messages.success(request, "Issue deleted successfully.")
return redirect('manage_issues')
def resolver_check(user):
return user.is_resolver
View File