This commit is contained in:
Adrian Woźniak 2023-09-13 18:05:17 +02:00
parent b9f94d0fd4
commit a5954e6966
3 changed files with 168 additions and 18 deletions

View File

@ -1,11 +1,11 @@
use actix_web::http::header::ContentType;
use actix_web::web::{scope, Data, Form, ServiceConfig};
use actix_web::web::{scope, Data, Form, Path, ServiceConfig};
use actix_web::{get, post, HttpRequest, HttpResponse};
use askama_actix::Template;
use autometrics::autometrics;
use oswilno_contract::parking_space_rents;
use oswilno_contract::sea_orm_active_enums::ParkingSpaceState;
use oswilno_contract::parking_spaces;
use oswilno_contract::sea_orm_active_enums::ParkingSpaceState;
use oswilno_contract::{accounts, parking_space_locations};
use oswilno_session::{Authenticated, MaybeAuthenticated};
use oswilno_view::{
@ -27,7 +27,9 @@ pub fn mount(config: &mut ServiceConfig) {
scope("/parking-spaces")
.service(form_show)
.service(all_parking_spaces)
.service(create),
.service(create)
.service(edit_show)
.service(update),
);
}
@ -75,9 +77,7 @@ async fn all_parking_spaces(
let account_id = session.as_ref().map(|s| s.account_id());
let session = session.map(Into::into);
eprintln!("######################################################################");
tracing::debug!("session {session:?}");
eprintln!("session {session:?}");
let mut parking_spaces = load_parking_spaces(db, account_id).await;
parking_spaces.session = session.clone();
@ -159,10 +159,12 @@ async fn load_parking_spaces(
};
let locations: Vec<_> = load_locations(db).await.into_iter().map(Rc::new).collect();
let location_by_id = locations.iter().fold(BTreeMap::new(), |mut memo, location| {
memo.insert(location.id, location.clone());
memo
});
let location_by_id = locations
.iter()
.fold(BTreeMap::new(), |mut memo, location| {
memo.insert(location.id, location.clone());
memo
});
AllPartialParkingSpace {
account_by_id,
@ -235,8 +237,9 @@ struct ParkingSpaceFormPartial {
#[derive(Debug, Default, serde::Deserialize)]
struct CreateParkingSpace {
location_id: u32,
spot: Option<u32>,
id: Option<i32>,
location_id: i32,
spot: Option<i32>,
}
#[autometrics]
@ -249,7 +252,11 @@ async fn create(
lang: Lang,
) -> HttpResponse {
use oswilno_contract::parking_spaces::*;
let CreateParkingSpace { location_id, spot } = p.into_inner();
let CreateParkingSpace {
location_id,
spot,
id: _,
} = p.into_inner();
let db = db.into_inner();
let model = ActiveModel {
@ -262,7 +269,11 @@ async fn create(
if let Err(_e) = model.save(&*db).await {
return HttpResponse::BadRequest().body(
ParkingSpaceFormPartial {
form: CreateParkingSpace { location_id, spot },
form: CreateParkingSpace {
location_id,
spot,
id: None,
},
t: t.into_inner(),
lang,
errors: Default::default(),
@ -314,3 +325,119 @@ async fn ensure_locations(db: Arc<sea_orm::DatabaseConnection>) {
.ok();
}
}
#[get("/edit/{id}")]
async fn edit_show(
req: HttpRequest,
session: Authenticated,
t: Data<TranslationStorage>,
lang: Lang,
db: Data<DatabaseConnection>,
id: Path<i32>,
) -> HttpResponse {
let db = db.into_inner();
let id = id.into_inner();
let parking_space = oswilno_contract::parking_spaces::Entity::find()
.filter(oswilno_contract::parking_spaces::Column::Id.eq(id))
.one(&*db)
.await;
let parking_space = match parking_space {
Ok(Some(parking_space)) => parking_space,
_ => {
return HttpResponse::NotFound()
.append_header(("HX-Redirect", "/"))
.finish()
}
};
let session = session.into();
let body = ParkingSpaceFormPartial {
form: CreateParkingSpace {
location_id: parking_space.location_id.unwrap_or(0),
spot: parking_space.spot,
id: Some(id),
},
locations: load_locations(db.clone()).await,
lang,
errors: Default::default(),
t: t.into_inner(),
};
let main = Main {
body,
title: Blank,
opts: MainOpts {
show: true,
search: None,
session: Some(session),
},
};
let html = if is_partial(&req) {
main.render()
} else {
Layout { main }.render()
};
HttpResponse::Ok()
.append_header(ContentType::html())
.body(html.unwrap())
}
#[autometrics]
#[post("/update")]
async fn update(
db: Data<sea_orm::DatabaseConnection>,
p: Form<CreateParkingSpace>,
session: Authenticated,
t: Data<TranslationStorage>,
lang: Lang,
) -> HttpResponse {
use oswilno_contract::parking_spaces::*;
let CreateParkingSpace {
id,
location_id,
spot,
} = p.into_inner();
let db = db.into_inner();
let Some(id) = id else {
return HttpResponse::BadRequest()
.append_header(("HX-Redirect", "/"))
.finish();
};
let parking_space = oswilno_contract::parking_spaces::Entity::find()
.filter(oswilno_contract::parking_spaces::Column::Id.eq(id))
.one(&*db)
.await;
let _parking_space = match parking_space {
Ok(Some(parking_space)) => parking_space,
_ => {
return HttpResponse::NotFound()
.append_header(("HX-Redirect", "/"))
.finish()
}
};
let model = ActiveModel {
id: Set(id),
location_id: Set(Some(location_id as i32)),
spot: Set(spot.map(|n| n as i32)),
account_id: Set(session.account_id()),
..Default::default()
};
if let Err(_e) = model.update(&*db).await {
return HttpResponse::BadRequest().body(
ParkingSpaceFormPartial {
form: CreateParkingSpace { location_id, spot, id: Some(id) },
t: t.into_inner(),
lang,
errors: Default::default(),
locations: load_locations(db.clone()).await,
}
.render()
.unwrap(),
);
}
HttpResponse::SeeOther()
.append_header(("Location", "/parking-spaces/all"))
.append_header(("HX-Redirect", "/parking-spaces/all"))
.finish()
}

View File

@ -41,13 +41,21 @@
{% if let Some(location) = location_by_id.get(location_id) -%}
{% if let Some(spot) = parking_space.spot -%}
{% if let Some(account) = account_by_id.get(parking_space.account_id) -%}
<div class="flex items-center space-x-4">
<div class="flex items-center justify-between space-x-4">
<div class="flex-shrink-0">
<span class="text-sm font-medium text-white-900 truncate dark:text-black">{{location.name}}</span>
<span class="text-sm font-medium text-white-900 truncate dark:text-black">{{location.number}}</span>
<span class="text-sm font-medium text-white-900 truncate dark:text-black">Etap {{location.stage}}</span>
<span class="text-sm font-medium text-white-900 truncate dark:text-black">
{{location.name}}
</span>
<span class="text-sm font-medium text-white-900 truncate dark:text-black">
{{location.number}}
</span>
<span class="text-sm font-medium text-white-900 truncate dark:text-black">
Etap {{location.stage}}
</span>
</div>
<div class="inline-flex items-center text-base font-semibold text-gray-900 dark:text-black">
{{spot}}
</div>
<div class="inline-flex items-center text-base font-semibold text-gray-900 dark:text-black">{{spot}}</div>
{% match parking_space.state %}
{% when ParkingSpaceState::Pending %}
@ -57,6 +65,16 @@
{% when ParkingSpaceState::Banned %}
<div class="inline-flex items-center text-base font-semibold text-red-900 dark:text-red">Rejected</div>
{% endmatch %}
<div>
<a
href="/parking-spaces/edit/{{parking_space.id}}"
hx-target="main"
hx-get="/parking-spaces/edit/{{parking_space.id}}"
hx-headers='{"Accept":"text/html-partial"}'
>
Edit
</a>
</div>
</div>
{% endif %}

View File

@ -5,6 +5,11 @@
<oswilno-error>{{error|t(lang,t)}}</oswilno-error>
{% endfor %}
<form hx-post="/parking-spaces/create" hx-target="main">
{% match form.id %}
{% when Some with (id) %}
<input type="hidden" name="id" value="{{id}}" />
{% when _ %}
{% endmatch %}
<div class="mb-4">
<label
for="location_id"