use axum::Json; use axum::Router; use axum::extract::{Path, Query, State}; use axum::routing::{get, patch}; use holzleitner_application::dto::{ CarResponse, CarsList, CreateCarRequest, UpdateCarRequest, }; use serde::Deserialize; use uuid::Uuid; use crate::error::ApiError; use crate::extractors::AuthenticatedUser; use crate::state::AppState; pub fn router() -> Router { Router::new() .route("/me/cars", get(list_my_cars).post(create_my_car)) .route("/me/cars/{car_id}", patch(update_my_car)) } /// Query-Parameter für `GET /me/cars`. #[derive(Debug, Deserialize, Default)] #[serde(rename_all = "camelCase")] pub struct ListCarsQuery { /// Default `false` — Endpoint liefert standardmäßig auch /// deaktivierte Fahrzeuge **nicht** mit. #[serde(default)] pub include_inactive: bool, } /// Listet die Fahrzeuge des angemeldeten Fahrers. #[utoipa::path( get, path = "/me/cars", tag = "cars", params( ("includeInactive" = Option, Query, description = "Wenn true, werden inaktive Fahrzeuge mitgeliefert (default: false)") ), responses( (status = 200, description = "Fahrzeuge des Fahrers", body = CarsList), (status = 401, description = "Authentifizierung fehlgeschlagen") ), security(("bearer_auth" = [])) )] pub async fn list_my_cars( State(state): State, AuthenticatedUser(claims): AuthenticatedUser, Query(query): Query, ) -> Result, ApiError> { let cars = state .list_my_cars .execute(claims.personalnummer, query.include_inactive) .await?; Ok(Json(CarsList { cars })) } /// Legt ein neues Fahrzeug für den angemeldeten Fahrer an. #[utoipa::path( post, path = "/me/cars", tag = "cars", request_body = CreateCarRequest, responses( (status = 200, description = "Fahrzeug angelegt", body = CarResponse), (status = 400, description = "Validierungsfehler (z. B. doppeltes Kennzeichen)"), (status = 401, description = "Authentifizierung fehlgeschlagen") ), security(("bearer_auth" = [])) )] pub async fn create_my_car( State(state): State, AuthenticatedUser(claims): AuthenticatedUser, Json(req): Json, ) -> Result, ApiError> { let car = state .create_my_car .execute(claims.personalnummer, req) .await?; Ok(Json(CarResponse { car })) } /// Aktualisiert ein Fahrzeug (Kennzeichen ändern / deaktivieren). #[utoipa::path( patch, path = "/me/cars/{car_id}", tag = "cars", params(("car_id" = Uuid, Path)), request_body = UpdateCarRequest, responses( (status = 200, description = "Fahrzeug aktualisiert", body = CarResponse), (status = 400, description = "Validierungsfehler"), (status = 401, description = "Authentifizierung fehlgeschlagen"), (status = 404, description = "Fahrzeug nicht gefunden oder gehört nicht zu diesem Account") ), security(("bearer_auth" = [])) )] pub async fn update_my_car( State(state): State, AuthenticatedUser(claims): AuthenticatedUser, Path(car_id): Path, Json(req): Json, ) -> Result, ApiError> { let car = state .update_my_car .execute(car_id, claims.personalnummer, req) .await?; Ok(Json(CarResponse { car })) }