from django.contrib import messages from django.contrib.auth import authenticate, login from django.contrib.auth.decorators import login_required from django.contrib.auth.forms import AuthenticationForm from django.db.models import Exists, OuterRef from django.http import JsonResponse from django.shortcuts import render, redirect from django.views.decorators.http import require_POST from .models import Issue, IssueCategory, User, Vote from .forms import CitizenRegistrationForm, IssueForm def home(request): total_issues = Issue.objects.count() resolved_issues = Issue.objects.filter(status='resolved').count() active_users = User.objects.filter(is_active=True).count() # Get recently reported issues (last 3 issues) recent_issues = Issue.objects.all().order_by('-created_at')[:3] for issue in recent_issues: issue.user_has_voted = issue.has_user_voted(request.user) if request.user.is_authenticated else False # Get municipal departments count (assuming you have a Department model) # If you don't have one yet, you can use a placeholder or create the model municipal_departments = 5 # Placeholder - replace with actual count when you have the model context = { 'total_issues': total_issues, 'resolved_issues': resolved_issues, 'active_users': active_users, 'municipal_departments': municipal_departments, 'recent_issues': recent_issues, } return render(request, 'core/index.html', context) @login_required def citizen_dashboard(request): if not request.user.is_citizen: messages.error(request, 'Access denied. Citizen role required.') return redirect('home') # Get only basic data for now all_user_issues = Issue.objects.filter(reporter=request.user) user_issues_display = all_user_issues.order_by('-created_at')[:5] resolved_count = all_user_issues.filter(status='resolved').count() categories = IssueCategory.objects.all() context = { 'user_issues': user_issues_display, 'resolved_count': resolved_count, 'categories': categories, 'issue_form': IssueForm(), } return render(request, 'core/citizen_dashboard.html', context) @login_required def report_issue(request): if not request.user.is_citizen: messages.error(request, 'Access denied. Citizen role required.') return redirect('home') if request.method == 'POST': form = IssueForm(request.POST, request.FILES) if form.is_valid(): issue = form.save(commit=False) issue.reporter = request.user issue.save() messages.success(request, 'Issue reported successfully!') return redirect('citizen_dashboard') else: messages.error(request, 'Please correct the errors below.') else: form = IssueForm() return render(request, 'core/report_issue.html', {'form': form}) @login_required def view_all_issues(request): if not request.user.is_citizen: messages.error(request, 'Access denied. Citizen role required.') return redirect('home') # Efficiently annotate whether the current user has voted user_vote_subq = Vote.objects.filter(user=request.user, issue_id=OuterRef('pk')) issues = ( Issue.objects .select_related('category', 'reporter') .annotate(user_has_voted=Exists(user_vote_subq)) .order_by('-created_at') ) categories = IssueCategory.objects.all() # Optional filters (status/category) if you wired the dropdowns status = request.GET.get('status') or '' category_id = request.GET.get('category') or '' if status: issues = issues.filter(status=status) if category_id: issues = issues.filter(category_id=category_id) return render(request, 'core/view_all_issues.html', { 'issues': issues, 'categories': categories, 'selected_status': status, 'selected_category': category_id, }) def register(request): if request.method == 'POST': form = CitizenRegistrationForm(request.POST) if form.is_valid(): user = form.save() messages.success(request, 'Registration successful! Please login.') return redirect('login') else: form = CitizenRegistrationForm() return render(request, 'core/register.html', {'form': form}) def custom_login(request): if request.method == 'POST': form = AuthenticationForm(request, data=request.POST) if form.is_valid(): username = form.cleaned_data.get('username') password = form.cleaned_data.get('password') user = authenticate(username=username, password=password) if user is not None: login(request, user) messages.success(request, f'Welcome back, {username}!') return redirect('home') else: messages.error(request, 'Invalid username or password.') else: messages.error(request, 'Invalid username or password.') else: form = AuthenticationForm() return render(request, 'core/login.html', {'form': form}) @login_required @require_POST def vote_issue(request, issue_id): try: issue = Issue.objects.get(id=issue_id) vote, created = Vote.objects.get_or_create(user=request.user, issue=issue) if not created: # User already voted, so remove the vote (toggle) vote.delete() voted = False else: voted = True return JsonResponse({ 'success': True, 'voted': voted, 'vote_count': issue.vote_count() }) except Issue.DoesNotExist: return JsonResponse({'success': False, 'error': 'Issue not found'}) except Exception as e: return JsonResponse({'success': False, 'error': str(e)})