Skip to content

Commit bd0e351

Browse files
committed
Added Admin
1 parent 0c97bdf commit bd0e351

5 files changed

Lines changed: 561 additions & 1 deletion

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# ResQTrack
1+
# ResQTrack
22

33
ResQTrack is a lightweight, full‑stack web app that coordinates animal rescue across citizens, NGOs, volunteers, animal hospitals and donors. Citizens can quickly report an injured animal, NGOs and volunteers can act, hospitals can be listed, and donors can contribute — all tracked end‑to‑end.
44

backend/app/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from .routes.hospitals import hospitals_bp
1010
from .routes.donations import donations_bp
1111
from .routes.uploads import uploads_bp
12+
from .routes.admin import admin_bp
1213

1314

1415
def create_app(config_class: type = Config) -> Flask:
@@ -36,5 +37,6 @@ def create_app(config_class: type = Config) -> Flask:
3637
app.register_blueprint(hospitals_bp)
3738
app.register_blueprint(donations_bp)
3839
app.register_blueprint(uploads_bp)
40+
app.register_blueprint(admin_bp)
3941

4042
return app

backend/app/routes/admin.py

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
from flask import Blueprint, request
2+
from flask_jwt_extended import jwt_required
3+
from ..extensions import db
4+
from ..models import AnimalCase, NGO, Volunteer, Donation, Hospital, CaseStatus
5+
6+
admin_bp = Blueprint("admin", __name__, url_prefix="/admin")
7+
8+
9+
@admin_bp.get("/cases")
10+
def get_all_cases():
11+
"""Get all animal cases for admin dashboard"""
12+
cases = AnimalCase.query.order_by(AnimalCase.created_at.desc()).all()
13+
return {
14+
"cases": [
15+
{
16+
"id": case.id,
17+
"case_code": case.case_code,
18+
"reporter_name": case.reporter_name,
19+
"reporter_phone": case.reporter_phone,
20+
"location": case.location,
21+
"animal_type": case.animal_type.value if case.animal_type else "Other",
22+
"urgency": case.urgency,
23+
"status": case.status.value if case.status else "PENDING",
24+
"notes": case.notes,
25+
"media_url": case.media_url,
26+
"created_at": case.created_at.isoformat() if case.created_at else None,
27+
"updated_at": case.updated_at.isoformat() if case.updated_at else None,
28+
}
29+
for case in cases
30+
]
31+
}
32+
33+
34+
@admin_bp.get("/ngos")
35+
def get_all_ngos():
36+
"""Get all NGOs for admin dashboard"""
37+
ngos = NGO.query.order_by(NGO.created_at.desc()).all()
38+
return {
39+
"ngos": [
40+
{
41+
"id": ngo.id,
42+
"name": ngo.name,
43+
"email": ngo.email,
44+
"phone": ngo.phone,
45+
"location": ngo.location,
46+
"operating_zones": ngo.operating_zones,
47+
"approved": ngo.approved,
48+
"created_at": ngo.created_at.isoformat() if ngo.created_at else None,
49+
"updated_at": ngo.updated_at.isoformat() if ngo.updated_at else None,
50+
}
51+
for ngo in ngos
52+
]
53+
}
54+
55+
56+
@admin_bp.get("/volunteers")
57+
def get_all_volunteers():
58+
"""Get all volunteers for admin dashboard"""
59+
volunteers = Volunteer.query.order_by(Volunteer.created_at.desc()).all()
60+
return {
61+
"volunteers": [
62+
{
63+
"id": vol.id,
64+
"name": vol.name,
65+
"email": vol.email,
66+
"phone": vol.phone,
67+
"location": vol.location,
68+
"expertise": vol.expertise,
69+
"availability": vol.availability,
70+
"approved": vol.approved,
71+
"ngo_id": vol.ngo_id,
72+
"created_at": vol.created_at.isoformat() if vol.created_at else None,
73+
"updated_at": vol.updated_at.isoformat() if vol.updated_at else None,
74+
}
75+
for vol in volunteers
76+
]
77+
}
78+
79+
80+
@admin_bp.get("/donations")
81+
def get_all_donations():
82+
"""Get all donations for admin dashboard"""
83+
donations = Donation.query.order_by(Donation.created_at.desc()).all()
84+
return {
85+
"donations": [
86+
{
87+
"id": donation.id,
88+
"donor_name": donation.donor_name,
89+
"donor_email": donation.donor_email,
90+
"amount": float(donation.amount) if donation.amount else 0,
91+
"currency": donation.currency,
92+
"category": donation.category,
93+
"payment_provider": donation.payment_provider,
94+
"payment_id": donation.payment_id,
95+
"ngo_id": donation.ngo_id,
96+
"created_at": donation.created_at.isoformat() if donation.created_at else None,
97+
"updated_at": donation.updated_at.isoformat() if donation.updated_at else None,
98+
}
99+
for donation in donations
100+
]
101+
}
102+
103+
104+
@admin_bp.get("/hospitals")
105+
def get_all_hospitals():
106+
"""Get all hospitals for admin dashboard"""
107+
hospitals = Hospital.query.order_by(Hospital.created_at.desc()).all()
108+
return {
109+
"hospitals": [
110+
{
111+
"id": hospital.id,
112+
"name": hospital.name,
113+
"address": hospital.address,
114+
"phone": hospital.phone,
115+
"location": hospital.location,
116+
"is_24x7": hospital.is_24x7,
117+
"treatment_types": hospital.treatment_types,
118+
"created_at": hospital.created_at.isoformat() if hospital.created_at else None,
119+
"updated_at": hospital.updated_at.isoformat() if hospital.updated_at else None,
120+
}
121+
for hospital in hospitals
122+
]
123+
}
124+
125+
126+
@admin_bp.patch("/ngos/<int:ngo_id>/approve")
127+
@jwt_required()
128+
def approve_ngo(ngo_id: int):
129+
"""Approve an NGO registration"""
130+
ngo = NGO.query.get_or_404(ngo_id)
131+
ngo.approved = True
132+
db.session.commit()
133+
return {"message": "NGO approved successfully"}, 200
134+
135+
136+
@admin_bp.patch("/volunteers/<int:volunteer_id>/approve")
137+
@jwt_required()
138+
def approve_volunteer(volunteer_id: int):
139+
"""Approve a volunteer registration"""
140+
volunteer = Volunteer.query.get_or_404(volunteer_id)
141+
volunteer.approved = True
142+
db.session.commit()
143+
return {"message": "Volunteer approved successfully"}, 200
144+
145+
146+
@admin_bp.patch("/cases/<int:case_id>/status")
147+
@jwt_required()
148+
def update_case_status(case_id: int):
149+
"""Update case status"""
150+
data = request.get_json(silent=True) or {}
151+
new_status = (data.get("status") or "").upper()
152+
153+
if new_status not in {s.name for s in CaseStatus}:
154+
return {"error": "invalid status"}, 400
155+
156+
case = AnimalCase.query.get_or_404(case_id)
157+
case.status = CaseStatus[new_status]
158+
db.session.commit()
159+
return {"message": "Case status updated successfully"}, 200

0 commit comments

Comments
 (0)