\n\t\t`;\n\t\tcopyCss(shadow);\n\t}\n});\n", "customElements.define('oswilno-parking-space', class extends HTMLElement {\n\tconstructor() {\n\t\tsuper();\n\t\tconst shadow = this.attachShadow({ mode: 'open' });\n\t\tshadow.innerHTML = `\n\t\t\t\n\t\t\t
\n\t\t\t\n\t\t\t
\n\t\t`;\n\t}\n});\n", "import './elements/oswilno-price.js';\nimport './elements/oswilno-error.js';\nimport './elements/oswilno-parking-space.js';\nimport(\"https://unpkg.com/htmx.org@1.9.4/dist/htmx.min.js\");\n\nconst READ_AUTH_HEADER = 'Authorization';\nconst AUTH_HEADER = 'ACX-Authorization';\nconst REFRESH_HEADER = 'ACX-Refresh';\nconst body = document.body;\nbody.addEventListener('htmx:beforeOnLoad', function (evt) {\n\tconst detail = evt.detail;\n\tconst xhr = detail.xhr;\n\tconst status = xhr.status;\n\tconst successful = detail.successful;\n\n\tif (status === 200) {\n\t\tconst bearer = xhr.getResponseHeader(READ_AUTH_HEADER);\n\t\tif (bearer) {\n\t\t\tconsole.log(xhr);\n\t\t\tlocalStorage.setItem('jwt', bearer.replace(/^Bearer /i, ''));\n\t\t}\n\t\tconst refresh = xhr.getResponseHeader(REFRESH_HEADER);\n\t\tif (refresh) {\n\t\t\tlocalStorage.setItem('refresh', bearer.replace(/^Bearer /i, ''));\n\t\t}\n\t} else if (status === 401) {\n\t\tlocalStorage.removeItem('jwt');\n\t}\n\tif (status === 422 || status === 400) {\n\t\tdetail.shouldSwap = true;\n\t\tdetail.isError = false;\n\t}\n});\nbody.addEventListener('htmx:configRequest', function (evt) {\n\tif (!localStorage.getItem('jwt')) {\n\t\treturn;\n\t}\n\tevt.detail.headers[AUTH_HEADER] = 'Bearer ' + (localStorage.getItem('jwt') || '');\n\tevt.detail.headers[READ_AUTH_HEADER] = 'Bearer ' + (localStorage.getItem('jwt') || '');\n\tevt.detail.headers[REFRESH_HEADER] = (localStorage.getItem('refresh') || '');\n});\n\n"],
"mappings": "0sBAAA,eAAe,OAAO,gBAAiB,cAAc,WAAY,CAChE,aAAc,CACb,MAAM,EACN,KAAK,aAAa,CAAE,KAAM,MAAO,CAAC,CACnC,CACA,mBAAoB,CACnB,IAAIA,EAAS,KAAK,WACdC,EAAQ,SAAS,KAAK,aAAa,OAAO,CAAC,EAC3C,MAAMA,CAAK,IAAGA,EAAQ,GAC1B,IAAMC,EAAa,SAAS,KAAK,aAAa,YAAY,CAAC,EACvDC,EAAQF,EACRG,EAAQ,EACP,MAAMF,CAAU,IACpBC,EAAQ,KAAK,MAAMF,EAAQC,CAAU,EACrCE,EAAQH,EAAQC,GAEjB,IAAMG,EAAW,KAAK,aAAa,UAAU,GAAK,MAClDL,EAAO,UAAY,4CAA4CG,CAAK,IAAIC,GAAS,GAAKA,EAAQA,EAAQ,GAAG,IAAKC,CAAS,QACxH,CACD,CAAC,ECnBM,IAAMC,EAAWC,GAAW,CAClC,IAAIC,EAAM,GACV,QAASC,EAAI,EAAGA,EAAI,SAAS,YAAY,OAAQA,IAAK,CACrD,IAAMC,EAAa,SAAS,YAAYD,CAAC,EACzC,QAASE,EAAI,EAAGA,EAAID,EAAW,MAAM,OAAQC,IAC5CH,GAAOE,EAAW,MAAMC,CAAC,EAAE,OAE7B,CACA,IAAMC,EAAQ,IAAI,cAClBA,EAAM,YAAYJ,CAAG,EACrBD,EAAO,mBAAqB,CAACK,CAAK,CACnC,ECTA,eAAe,OAAO,gBAAiB,cAAc,WAAY,CAChE,aAAc,CACb,MAAM,EACN,IAAMC,EAAS,KAAK,aAAa,CAAE,KAAM,MAAO,CAAC,EACjDA,EAAO,UAAY;AAAA;AAAA;AAAA;AAAA;AAAA,IAMnBC,EAAQD,CAAM,CACf,CACD,CAAC,ECdD,eAAe,OAAO,wBAAyB,cAAc,WAAY,CACxE,aAAc,CACb,MAAM,EACN,IAAME,EAAS,KAAK,aAAa,CAAE,KAAM,MAAO,CAAC,EACjDA,EAAO,UAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAQpB,CACD,CAAC,ECVD,OAAO,mDAAmD,EAE1D,IAAMC,EAAmB,gBACnBC,EAAc,oBACdC,EAAiB,cACjBC,EAAO,SAAS,KACtBA,EAAK,iBAAiB,oBAAqB,SAAUC,EAAK,CACzD,IAAMC,EAASD,EAAI,OACbE,EAAMD,EAAO,IACbE,EAASD,EAAI,OACbE,EAAaH,EAAO,WAE1B,GAAIE,IAAW,IAAK,CACnB,IAAME,EAASH,EAAI,kBAAkBN,CAAgB,EACjDS,IACH,QAAQ,IAAIH,CAAG,EACf,aAAa,QAAQ,MAAOG,EAAO,QAAQ,YAAa,EAAE,CAAC,GAE5CH,EAAI,kBAAkBJ,CAAc,GAEnD,aAAa,QAAQ,UAAWO,EAAO,QAAQ,YAAa,EAAE,CAAC,CAEjE,MAAWF,IAAW,KACrB,aAAa,WAAW,KAAK,GAE1BA,IAAW,KAAOA,IAAW,OAChCF,EAAO,WAAa,GACpBA,EAAO,QAAU,GAEnB,CAAC,EACDF,EAAK,iBAAiB,qBAAsB,SAAUC,EAAK,CACrD,aAAa,QAAQ,KAAK,IAG/BA,EAAI,OAAO,QAAQH,CAAW,EAAI,WAAa,aAAa,QAAQ,KAAK,GAAK,IAC9EG,EAAI,OAAO,QAAQJ,CAAgB,EAAI,WAAa,aAAa,QAAQ,KAAK,GAAK,IACnFI,EAAI,OAAO,QAAQF,CAAc,EAAK,aAAa,QAAQ,SAAS,GAAK,GAC1E,CAAC",
"names": ["shadow", "price", "multiplier", "major", "minor", "currency", "copyCss", "shadow", "css", "i", "styleSheet", "j", "sheet", "shadow", "copyCss", "shadow", "READ_AUTH_HEADER", "AUTH_HEADER", "REFRESH_HEADER", "body", "evt", "detail", "xhr", "status", "successful", "bearer"]
}
diff --git a/assets/style.css b/assets/style.css
index c487891..ea21bb3 100644
--- a/assets/style.css
+++ b/assets/style.css
@@ -809,10 +809,6 @@ select {
margin-right: 0.25rem;
}
-.mr-2 {
- margin-right: 0.5rem;
-}
-
.mr-3 {
margin-right: 0.75rem;
}
@@ -877,10 +873,6 @@ select {
height: 100%;
}
-.min-h-screen {
- min-height: 100vh;
-}
-
.w-10 {
width: 2.5rem;
}
@@ -921,14 +913,18 @@ select {
max-width: 1280px;
}
-.flex-shrink-0 {
- flex-shrink: 0;
-}
-
.list-none {
list-style-type: none;
}
+.grid-flow-col {
+ grid-auto-flow: column;
+}
+
+.grid-cols-4 {
+ grid-template-columns: repeat(4, minmax(0, 1fr));
+}
+
.flex-col {
flex-direction: column;
}
@@ -945,6 +941,10 @@ select {
align-items: center;
}
+.justify-end {
+ justify-content: flex-end;
+}
+
.justify-center {
justify-content: center;
}
@@ -1018,11 +1018,6 @@ select {
background-color: rgb(0 0 0 / var(--tw-bg-opacity));
}
-.bg-blue-100 {
- --tw-bg-opacity: 1;
- background-color: rgb(219 234 254 / var(--tw-bg-opacity));
-}
-
.bg-blue-700 {
--tw-bg-opacity: 1;
background-color: rgb(29 78 216 / var(--tw-bg-opacity));
@@ -1057,11 +1052,6 @@ select {
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
}
-.bg-yellow-100 {
- --tw-bg-opacity: 1;
- background-color: rgb(254 249 195 / var(--tw-bg-opacity));
-}
-
.bg-cover {
background-size: cover;
}
@@ -1117,11 +1107,6 @@ select {
padding-right: 1.5rem;
}
-.py-1 {
- padding-top: 0.25rem;
- padding-bottom: 0.25rem;
-}
-
.py-2 {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
@@ -1175,6 +1160,11 @@ select {
line-height: 1.5rem;
}
+.text-lg {
+ font-size: 1.125rem;
+ line-height: 1.75rem;
+}
+
.text-sm {
font-size: 0.875rem;
line-height: 1.25rem;
@@ -1210,11 +1200,6 @@ select {
color: rgb(96 165 250 / var(--tw-text-opacity));
}
-.text-blue-800 {
- --tw-text-opacity: 1;
- color: rgb(30 64 175 / var(--tw-text-opacity));
-}
-
.text-emerald-500 {
--tw-text-opacity: 1;
color: rgb(16 185 129 / var(--tw-text-opacity));
@@ -1255,11 +1240,6 @@ select {
color: rgb(185 28 28 / var(--tw-text-opacity));
}
-.text-red-800 {
- --tw-text-opacity: 1;
- color: rgb(153 27 27 / var(--tw-text-opacity));
-}
-
.text-white {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity));
@@ -1270,11 +1250,6 @@ select {
color: rgb(250 204 21 / var(--tw-text-opacity));
}
-.text-yellow-800 {
- --tw-text-opacity: 1;
- color: rgb(133 77 14 / var(--tw-text-opacity));
-}
-
.opacity-75 {
opacity: 0.75;
}
@@ -1443,36 +1418,16 @@ select {
border-color: rgb(55 65 81 / var(--tw-border-opacity));
}
- .dark\:bg-blue-900 {
- --tw-bg-opacity: 1;
- background-color: rgb(30 58 138 / var(--tw-bg-opacity));
- }
-
.dark\:bg-gray-700 {
--tw-bg-opacity: 1;
background-color: rgb(55 65 81 / var(--tw-bg-opacity));
}
- .dark\:bg-red-900 {
- --tw-bg-opacity: 1;
- background-color: rgb(127 29 29 / var(--tw-bg-opacity));
- }
-
- .dark\:bg-yellow-900 {
- --tw-bg-opacity: 1;
- background-color: rgb(113 63 18 / var(--tw-bg-opacity));
- }
-
.dark\:text-black {
--tw-text-opacity: 1;
color: rgb(0 0 0 / var(--tw-text-opacity));
}
- .dark\:text-blue-300 {
- --tw-text-opacity: 1;
- color: rgb(147 197 253 / var(--tw-text-opacity));
- }
-
.dark\:text-gray-200 {
--tw-text-opacity: 1;
color: rgb(229 231 235 / var(--tw-text-opacity));
@@ -1488,21 +1443,11 @@ select {
color: rgb(229 229 229 / var(--tw-text-opacity));
}
- .dark\:text-red-300 {
- --tw-text-opacity: 1;
- color: rgb(252 165 165 / var(--tw-text-opacity));
- }
-
.dark\:text-white {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity));
}
- .dark\:text-yellow-300 {
- --tw-text-opacity: 1;
- color: rgb(253 224 71 / var(--tw-text-opacity));
- }
-
.dark\:placeholder-gray-400::-moz-placeholder {
--tw-placeholder-opacity: 1;
color: rgb(156 163 175 / var(--tw-placeholder-opacity));
@@ -1677,6 +1622,26 @@ select {
}
}
+@media (min-width: 1024px) {
+ .lg\:grid {
+ display: grid;
+ }
+
+ .lg\:min-h-ffh {
+ min-height: calc(100vh - 80px);
+ }
+}
+
+@media (min-width: 1280px) {
+ .xl\:flex {
+ display: flex;
+ }
+
+ .xl\:min-h-ffhl {
+ min-height: calc(100vh - 80px - 192px);
+ }
+}
+
.\[\&\.active\]\:text-black\/90.active {
color: rgb(0 0 0 / 0.9);
}
diff --git a/crates/oswilno-parking-space/src/lib.rs b/crates/oswilno-parking-space/src/lib.rs
index a6e6e68..4c754c3 100644
--- a/crates/oswilno-parking-space/src/lib.rs
+++ b/crates/oswilno-parking-space/src/lib.rs
@@ -27,6 +27,7 @@ pub async fn init(db: Arc
) {
pub fn mount(config: &mut ServiceConfig) {
config.service(root).service(
scope("/parking-spaces")
+ .service(parking_space_rent_form)
.service(form_show)
.service(all_parking_spaces)
.service(create)
@@ -296,17 +297,20 @@ async fn create(
}
async fn ensure_locations(db: Arc) {
- use oswilno_contract::parking_space_locations::{ActiveModel,Entity};
+ use oswilno_contract::parking_space_locations::{ActiveModel, Entity};
let records: Vec<_> = [
+ // 1
("Wilno", 1, "1a"),
("Wilno", 1, "1b"),
("Wilno", 1, "2AF1"),
("Wilno", 1, "2AF2"),
("Wilno", 1, "3"),
("Wilno", 1, "4"),
+ // 2
("Wilno", 2, "1"),
("Wilno", 2, "2"),
("Wilno", 2, "3"),
+ // 3
("Wilno", 3, "1"),
("Wilno", 3, "2"),
("Wilno", 3, "3"),
@@ -319,14 +323,15 @@ async fn ensure_locations(db: Arc) {
// 5
("Wilno", 5, "1"),
("Wilno", 5, "2"),
- ].into_iter().map(|(name, number, stage)|
- oswilno_contract::parking_space_locations::ActiveModel {
- name: Set(name.to_string()),
- number: Set(number),
- stage: Set(stage.to_string()),
- ..Default::default()
- }
- ).collect();
+ ]
+ .into_iter()
+ .map(|(name, number, stage)| ActiveModel {
+ name: Set(name.to_string()),
+ number: Set(number),
+ stage: Set(stage.to_string()),
+ ..Default::default()
+ })
+ .collect();
Entity::insert_many(records).exec(&*db).await.ok();
}
@@ -451,26 +456,113 @@ async fn update(
.finish()
}
-#[derive(Debug, Deserialize)]
-struct ParkingSpaceForm {
+#[derive(Deserialize, Debug, Default)]
+struct ParkingSpaceRentForm {
pub id: Option,
- pub price: i32,
- pub parking_space_id: i32,
+ pub price: Option,
}
-#[get("/parking-space-rents/form")]
-async fn parking_space_rent_form() -> HttpResponse {
- todo!()
+#[derive(Debug, Template)]
+#[template(path = "../templates/parking-space-rents/form.html")]
+struct ParkingSpaceRentFormTemplate {
+ pub form: ParkingSpaceRentForm,
+ pub parking_space: oswilno_contract::parking_spaces::Model,
+ pub location: oswilno_contract::parking_space_locations::Model,
+ lang: Lang,
+ t: Arc,
}
-#[get("/parking-space-rents/edit/{id}")]
-async fn parking_space_rent_edit(id: Path) -> HttpResponse {
+
+#[get("/{parking_space_id}/parking-space-rents/form")]
+async fn parking_space_rent_form(
+ req: HttpRequest,
+ db: Data,
+ session: MaybeAuthenticated,
+ parking_space_id: Path,
+ t: Data,
+ lang: Lang,
+) -> HttpResponse {
+ let parking_space_id = parking_space_id.into_inner();
+ let db = db.into_inner();
+ let session = session.into_option();
+ let _account_id = session.as_ref().map(|s| s.account_id());
+ let session = session.map(Into::into);
+ let parking_space = {
+ use ::oswilno_contract::parking_spaces::{Column, Entity};
+ let res = Entity::find()
+ .filter(Column::Id.eq(parking_space_id))
+ .one(&*db)
+ .await;
+ match res {
+ Ok(Some(entity)) => entity,
+ error => {
+ tracing::debug!("Parking space does not exists: {error:?}");
+ return HttpResponse::NotFound()
+ .body("Invalid request, parking space does not exists");
+ }
+ }
+ };
+ let location = {
+ use ::oswilno_contract::parking_space_locations::{Column, Entity};
+ let Some(location_id) = parking_space.location_id else {
+ tracing::debug!("Parking space does not have location id");
+ return HttpResponse::NotFound()
+ .body("Invalid request, parking space does not have location");
+ };
+ let res = Entity::find()
+ .filter(Column::Id.eq(location_id))
+ .one(&*db)
+ .await;
+ match res {
+ Ok(Some(entity)) => entity,
+ error => {
+ tracing::debug!("Parking space location does not exists: {error:?}");
+ return HttpResponse::NotFound()
+ .body("Invalid request, parking space location does not exists");
+ }
+ }
+ };
+ let body = ParkingSpaceRentFormTemplate {
+ parking_space,
+ location,
+ form: ParkingSpaceRentForm::default(),
+ lang,
+ t: t.into_inner(),
+ };
+ let main = Main {
+ body,
+ title: Blank,
+ opts: MainOpts {
+ show: true,
+ search: None,
+ session,
+ },
+ };
+ let html = if is_partial(&req) {
+ main.render()
+ } else {
+ Layout { main }.render()
+ };
+ HttpResponse::Ok()
+ .append_header((
+ "HX-Redirect",
+ format!(
+ "/parking-spaces/{}/parking-space-rents/form",
+ parking_space_id
+ )
+ .as_str(),
+ ))
+ .append_header(("HX-Retarget", "main"))
+ .body(html.unwrap())
+}
+#[get("/{parking_space_id}/parking-space-rents/edit/{id}")]
+async fn parking_space_rent_edit(_id: Path) -> HttpResponse {
todo!()
}
#[post("/parking-space-rents/create")]
-async fn parking_space_rent_create(form: Form) -> HttpResponse {
+async fn parking_space_rent_create(_form: Form) -> HttpResponse {
todo!()
}
#[put("/parking-space-rents/update")]
-async fn parking_space_rent_update(form: Form) -> HttpResponse {
+async fn parking_space_rent_update(_form: Form) -> HttpResponse {
todo!()
}
diff --git a/crates/oswilno-parking-space/templates/parking-space-rents/form.html b/crates/oswilno-parking-space/templates/parking-space-rents/form.html
index a8fd97f..d27cf5e 100644
--- a/crates/oswilno-parking-space/templates/parking-space-rents/form.html
+++ b/crates/oswilno-parking-space/templates/parking-space-rents/form.html
@@ -1,48 +1,53 @@
-