use axum::{Json, extract::Path, extract::State }; use axum::response::IntoResponse; use axum::http::StatusCode; use axum::extract::ws::Message; use serde::Serialize; use serde_json::json; use crate::rooms::extractor::UpdateRoomPayload; //use crate::utils::db_pool::*; use crate::utils::auth::AuthClaims; use crate::utils::db_pool::{HotelPool,AppState}; use std::sync::Arc; use r2d2::{Pool}; use r2d2_sqlite::SqliteConnectionManager; use dashmap::DashMap; use rusqlite::params; pub async fn hello_rooms() -> String { "hello from rooms".to_string() } pub async fn fake_db_update( State(state): State, AuthClaims { user_id, hotel_id }: AuthClaims, Path(room_id): Path, UpdateRoomPayload(payload): UpdateRoomPayload, ) -> impl IntoResponse { let pool = state.hotel_pools.get_pool(hotel_id); let conn = match pool.get() { Ok(conn) => conn, Err(err) => return (StatusCode::INTERNAL_SERVER_ERROR, format!("Pool error: {err}")), }; let result = conn.execute( "UPDATE rooms SET status = ?1 WHERE number = ?2", params![&payload.status, &room_id], ); match result { Ok(rows) if rows > 0 => (StatusCode::OK, format!("Updated room {room_id} in hotel {}", hotel_id)), Ok(_) => (StatusCode::NOT_FOUND, "No room found".to_string()), Err(err) => (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {err}")), } } pub async fn clean_db_update( State(state): State, Path(room_id): Path, AuthClaims { user_id, hotel_id }: AuthClaims, UpdateRoomPayload(payload): UpdateRoomPayload, ) -> impl IntoResponse { //TODO: make better error handling : // if wrong param collumn targeted, // if missing path param let pool = state.hotel_pools.get_pool(hotel_id); let conn = match pool.get(){ Ok(conn) => conn, Err(err) => return (StatusCode::INTERNAL_SERVER_ERROR, format!("Pool error: {err}")), }; let result: Result = conn.query_row( "UPDATE rooms SET status = ?1 WHERE id = ?2 RETURNING number", params![&payload.status, &room_id], |row| row.get(0), ); match result { Ok(room_number) => { // --- broadcast to all WS clients in the hotel --- if let Err(err) = conn.execute( "INSERT INTO room_history (room_id, room_number, status) VALUES (?1, ?2, ?3)", params![&room_id, &room_number, &payload.status], ) { return (StatusCode::INTERNAL_SERVER_ERROR, format!("Failed to insert history: {err}")); } if let Some(hotel_users) = state.ws_map.get(&hotel_id) { let update_msg = json!({ "room_id": room_id, "status": payload.status, "updated_by": user_id, }) .to_string(); for entry in hotel_users.iter() { let sender = entry.value(); // ignore errors (client disconnected) let _ = sender.send(Message::Text(update_msg.clone().into())); } } (StatusCode::OK, format!("updated room {room_id} in hotel {hotel_id}, with status: {}", payload.status)) } Ok(_) => (StatusCode::NOT_FOUND, "No room found".to_string()), Err(err) => (StatusCode::INTERNAL_SERVER_ERROR, format!("Error from DB: {err}")), } } #[derive(Serialize)] struct Room { id: i32, number: String, status: String, } pub async fn get_all_rooms( State(state): State, AuthClaims { hotel_id, .. }: AuthClaims, ) -> impl IntoResponse { let pool = state.hotel_pools.get_pool(hotel_id); let conn = match pool.get(){ Ok(conn) => conn, Err(err) => return (StatusCode::INTERNAL_SERVER_ERROR, format!("Pool error: {err}")), }; let mut stmt = match conn.prepare( "SELECT id, number, status FROM rooms ", ) { Ok(s) => s, Err(e) => return (StatusCode::INTERNAL_SERVER_ERROR, format!("Prepare failed: {}", e)), }; let room_iter = match stmt.query_map( params![],|row| { Ok(Room { id: row.get(0)?, number: row.get(1)?, status: row.get(2)?, }) }) { Ok(iter) => iter, Err(e) => return (StatusCode::INTERNAL_SERVER_ERROR, format!("Query failed: {}", e)), }; let rooms: Vec = match room_iter.collect::, _>>() { Ok(u) => u, Err(e) => return (StatusCode::INTERNAL_SERVER_ERROR, format!("Collect failed: {}", e)), }; match serde_json::to_string(&rooms) { Ok(json) => (StatusCode::OK, json), Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, format!("Serialization failed: {}", e)), } } struct RoomRequest { item_id: i32, item_amount: i32, token: String, }