"""Admin (JWT-protected) endpoints: edit every section, manage enquiries. All routes here depend on ``get_current_admin`` via the router dependency, so an unauthenticated request gets 401 before reaching a handler. """ from __future__ import annotations from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session from app.db import get_db from app.models import ( Course, Enquiry, FeePlan, Profile, Review, SiteSettings, Subject, Testimonial, ) from app.schemas import ( CourseIn, CourseOut, EnquiryOut, EnquiryPatch, FeePlanIn, FeePlanOut, ProfileIn, ProfileOut, ReviewOut, ReviewPatch, SiteSettingsIn, SiteSettingsOut, SubjectIn, SubjectOut, TestimonialIn, TestimonialOut, ) from app.security import get_current_admin router = APIRouter(prefix="/admin", dependencies=[Depends(get_current_admin)]) # ---- Profile (singleton) ---- @router.put("/profile", response_model=ProfileOut) def update_profile(body: ProfileIn, db: Session = Depends(get_db)) -> Profile: obj = db.query(Profile).first() if not obj: obj = Profile() db.add(obj) for k, v in body.model_dump().items(): setattr(obj, k, v) db.commit() db.refresh(obj) return obj # ---- Settings (singleton) ---- @router.put("/settings", response_model=SiteSettingsOut) def update_settings(body: SiteSettingsIn, db: Session = Depends(get_db)) -> SiteSettings: obj = db.query(SiteSettings).first() if not obj: obj = SiteSettings() db.add(obj) for k, v in body.model_dump().items(): setattr(obj, k, v) db.commit() db.refresh(obj) return obj # ---- Subjects CRUD ---- @router.post("/subjects", response_model=SubjectOut, status_code=201) def create_subject(body: SubjectIn, db: Session = Depends(get_db)) -> Subject: obj = Subject(**body.model_dump()) db.add(obj) db.commit() db.refresh(obj) return obj @router.put("/subjects/{item_id}", response_model=SubjectOut) def update_subject(item_id: int, body: SubjectIn, db: Session = Depends(get_db)) -> Subject: obj = db.get(Subject, item_id) if not obj: raise HTTPException(404, "Subject not found") for k, v in body.model_dump().items(): setattr(obj, k, v) db.commit() db.refresh(obj) return obj @router.delete("/subjects/{item_id}", status_code=204) def delete_subject(item_id: int, db: Session = Depends(get_db)) -> None: obj = db.get(Subject, item_id) if obj: db.delete(obj) db.commit() # ---- Courses CRUD ---- @router.post("/courses", response_model=CourseOut, status_code=201) def create_course(body: CourseIn, db: Session = Depends(get_db)) -> Course: obj = Course(**body.model_dump()) db.add(obj) db.commit() db.refresh(obj) return obj @router.put("/courses/{item_id}", response_model=CourseOut) def update_course(item_id: int, body: CourseIn, db: Session = Depends(get_db)) -> Course: obj = db.get(Course, item_id) if not obj: raise HTTPException(404, "Course not found") for k, v in body.model_dump().items(): setattr(obj, k, v) db.commit() db.refresh(obj) return obj @router.delete("/courses/{item_id}", status_code=204) def delete_course(item_id: int, db: Session = Depends(get_db)) -> None: obj = db.get(Course, item_id) if obj: db.delete(obj) db.commit() # ---- Fees CRUD ---- @router.post("/fees", response_model=FeePlanOut, status_code=201) def create_fee(body: FeePlanIn, db: Session = Depends(get_db)) -> FeePlan: obj = FeePlan(**body.model_dump()) db.add(obj) db.commit() db.refresh(obj) return obj @router.put("/fees/{item_id}", response_model=FeePlanOut) def update_fee(item_id: int, body: FeePlanIn, db: Session = Depends(get_db)) -> FeePlan: obj = db.get(FeePlan, item_id) if not obj: raise HTTPException(404, "Fee plan not found") for k, v in body.model_dump().items(): setattr(obj, k, v) db.commit() db.refresh(obj) return obj @router.delete("/fees/{item_id}", status_code=204) def delete_fee(item_id: int, db: Session = Depends(get_db)) -> None: obj = db.get(FeePlan, item_id) if obj: db.delete(obj) db.commit() # ---- Testimonials CRUD ---- @router.post("/testimonials", response_model=TestimonialOut, status_code=201) def create_testimonial(body: TestimonialIn, db: Session = Depends(get_db)) -> Testimonial: obj = Testimonial(**body.model_dump()) db.add(obj) db.commit() db.refresh(obj) return obj @router.put("/testimonials/{item_id}", response_model=TestimonialOut) def update_testimonial(item_id: int, body: TestimonialIn, db: Session = Depends(get_db)) -> Testimonial: obj = db.get(Testimonial, item_id) if not obj: raise HTTPException(404, "Testimonial not found") for k, v in body.model_dump().items(): setattr(obj, k, v) db.commit() db.refresh(obj) return obj @router.delete("/testimonials/{item_id}", status_code=204) def delete_testimonial(item_id: int, db: Session = Depends(get_db)) -> None: obj = db.get(Testimonial, item_id) if obj: db.delete(obj) db.commit() # ---- Reviews (moderation) ---- @router.get("/reviews", response_model=list[ReviewOut]) def list_reviews(db: Session = Depends(get_db)) -> list[Review]: return db.query(Review).order_by(Review.created_at.desc(), Review.id.desc()).all() @router.patch("/reviews/{item_id}", response_model=ReviewOut) def patch_review(item_id: int, body: ReviewPatch, db: Session = Depends(get_db)) -> Review: obj = db.get(Review, item_id) if not obj: raise HTTPException(404, "Review not found") obj.is_approved = body.is_approved db.commit() db.refresh(obj) return obj @router.delete("/reviews/{item_id}", status_code=204) def delete_review(item_id: int, db: Session = Depends(get_db)) -> None: obj = db.get(Review, item_id) if obj: db.delete(obj) db.commit() # ---- Enquiries ---- @router.get("/enquiries", response_model=list[EnquiryOut]) def list_enquiries(db: Session = Depends(get_db)) -> list[Enquiry]: return db.query(Enquiry).order_by(Enquiry.created_at.desc(), Enquiry.id.desc()).all() @router.patch("/enquiries/{item_id}", response_model=EnquiryOut) def patch_enquiry(item_id: int, body: EnquiryPatch, db: Session = Depends(get_db)) -> Enquiry: obj = db.get(Enquiry, item_id) if not obj: raise HTTPException(404, "Enquiry not found") obj.is_read = body.is_read db.commit() db.refresh(obj) return obj @router.delete("/enquiries/{item_id}", status_code=204) def delete_enquiry(item_id: int, db: Session = Depends(get_db)) -> None: obj = db.get(Enquiry, item_id) if obj: db.delete(obj) db.commit()