diff --git a/Cargo.lock b/Cargo.lock index 1f8b30c..b300c0a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -125,6 +125,7 @@ checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" dependencies = [ "async-trait", "axum-core", + "axum-macros", "bitflags 1.3.2", "bytes", "futures-util", @@ -166,6 +167,18 @@ dependencies = [ "tower-service", ] +[[package]] +name = "axum-macros" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdca6a10ecad987bda04e95606ef85a5417dcaac1a78455242d72e031e2b6b62" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.37", +] + [[package]] name = "backtrace" version = "0.3.69" diff --git a/Cargo.toml b/Cargo.toml index 605cdb2..d8a1fc3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ path = "src/lib/mod.rs" [dependencies] -axum = "0.6.20" +axum = { version = "0.6.20", features = ["macros"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.68" tokio = { version = "1.32.0", features = ["full"] } diff --git a/migrations/2023-09-30-201752_create_drinks/down.sql b/migrations/2023-09-30-201752_create_drinks/down.sql new file mode 100644 index 0000000..e1bc95e --- /dev/null +++ b/migrations/2023-09-30-201752_create_drinks/down.sql @@ -0,0 +1,2 @@ +-- This file should undo anything in `up.sql` +DROP TABLE drinks diff --git a/migrations/2023-09-30-201752_create_drinks/up.sql b/migrations/2023-09-30-201752_create_drinks/up.sql new file mode 100644 index 0000000..422ea6b --- /dev/null +++ b/migrations/2023-09-30-201752_create_drinks/up.sql @@ -0,0 +1,10 @@ +-- Your SQL goes here +CREATE TABLE drinks +( + id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, + price INT UNSIGNED NOT NULL, + quantity INT UNSIGNED NOT NULL, + shift INT UNSIGNED NOT NULL, + time DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, + FOREIGN KEY (shift) REFERENCES shifts(id) ON DELETE CASCADE +) diff --git a/src/api.rs b/src/api.rs index 63318fa..cc4023d 100644 --- a/src/api.rs +++ b/src/api.rs @@ -1,15 +1,18 @@ use axum::extract::Path; +use axum::Form; use axum::{extract::State, response::IntoResponse, routing::post}; -use cm_lib::models::Shift; +use cm_lib::models::{NewDrink, Shift}; use cm_lib::schema::shifts; use diesel::{ExpressionMethods, OptionalExtension, QueryDsl, SelectableHelper}; use diesel_async::{scoped_futures::ScopedFutureExt, AsyncConnection, RunQueryDsl}; +use serde::Deserialize; use crate::axum_ructe::render; use crate::AppState; pub(crate) fn router() -> axum::Router { axum::Router::new() + .route("/drinks", post(add_drink)) .route("/shifts/open", post(open_shift)) .route("/shifts/:id/close", post(close_shift)) } @@ -52,3 +55,42 @@ async fn close_shift(State(state): State, Path(id): Path) -> impl render!(crate::templates::home_html, None) } + +#[derive(Deserialize, Debug)] +struct DrinkForm { + shift_id: u32, + price: u32, + quantity: u32, +} + +impl Into for DrinkForm { + fn into(self) -> NewDrink { + NewDrink { + price: self.price, + quantity: self.quantity, + shift: self.shift_id, + } + } +} + +async fn add_drink( + State(state): State, + Form(form): Form, +) -> impl IntoResponse { + let mut conn = state.connection.get().await.unwrap(); + + tracing::debug!("{form:?}"); + + async { + use cm_lib::schema::drinks::dsl::*; + + diesel::insert_into(drinks) + .values::(form.into()) + .execute(&mut conn) + .await + .unwrap() + } + .await; + + axum::response::Redirect::to("/") +} diff --git a/src/lib/models.rs b/src/lib/models.rs index 743a82f..037d690 100644 --- a/src/lib/models.rs +++ b/src/lib/models.rs @@ -8,3 +8,23 @@ pub struct Shift { pub start: chrono::NaiveDateTime, pub end: Option, } + +#[derive(Queryable, Selectable, Debug)] +#[diesel(table_name = crate::schema::drinks)] +#[diesel(check_for_backend(diesel::mysql::Mysql))] +pub struct Drink { + pub id: u32, + pub price: u32, + pub quantity: u32, + pub shift: u32, + pub time: chrono::NaiveDateTime, +} + +#[derive(Insertable, Debug)] +#[diesel(table_name = crate::schema::drinks)] +#[diesel(check_for_backend(diesel::mysql::Mysql))] +pub struct NewDrink { + pub price: u32, + pub quantity: u32, + pub shift: u32, +} diff --git a/src/lib/schema.rs b/src/lib/schema.rs index e3617fc..2f49b49 100644 --- a/src/lib/schema.rs +++ b/src/lib/schema.rs @@ -1,5 +1,15 @@ // @generated automatically by Diesel CLI. +diesel::table! { + drinks (id) { + id -> Unsigned, + price -> Unsigned, + quantity -> Unsigned, + shift -> Unsigned, + time -> Datetime, + } +} + diesel::table! { shifts (id) { id -> Unsigned, @@ -7,3 +17,10 @@ diesel::table! { end -> Nullable, } } + +diesel::joinable!(drinks -> shifts (shift)); + +diesel::allow_tables_to_appear_in_same_query!( + drinks, + shifts, +); diff --git a/src/main.rs b/src/main.rs index e20c9e3..1995812 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ mod api; mod axum_ructe; +use axum::extract::Path; use axum_ructe::render; use axum::{extract::State, response::IntoResponse, routing::get, Router}; @@ -59,6 +60,7 @@ async fn main() { let app = Router::new() .nest("/api", api::router()) .route("/", get(root)) + .route("/shifts/:id/drinks", get(drinks)) .with_state(state); // run our app with hyper @@ -90,3 +92,7 @@ async fn root(State(state): State) -> impl IntoResponse { render!(templates::home_html, open_shift) } + +async fn drinks(Path(id): Path) -> impl IntoResponse { + render!(templates::drinks_html, id) +} diff --git a/templates/components/close_shift_button.rs.html b/templates/components/close_shift_button.rs.html index 8293e20..b88cd90 100644 --- a/templates/components/close_shift_button.rs.html +++ b/templates/components/close_shift_button.rs.html @@ -1,7 +1,7 @@ @use cm_lib::models::Shift; -@(open_shift: Shift) +@(open_shift: &Shift) - diff --git a/templates/components/open_shift_button.rs.html b/templates/components/open_shift_button.rs.html index 9073fbd..e87bffa 100644 --- a/templates/components/open_shift_button.rs.html +++ b/templates/components/open_shift_button.rs.html @@ -1,5 +1,5 @@ @() - diff --git a/templates/components/shift_button.rs.html b/templates/components/shift_button.rs.html index 0089cdd..67d6bb6 100644 --- a/templates/components/shift_button.rs.html +++ b/templates/components/shift_button.rs.html @@ -2,7 +2,7 @@ @use super::open_shift_button_html; @use cm_lib::models::Shift; -@(open_shift: Option) +@(open_shift: Option<&Shift>) @if open_shift.is_none() { @:open_shift_button_html() diff --git a/templates/drinks.rs.html b/templates/drinks.rs.html new file mode 100644 index 0000000..bfe5bf6 --- /dev/null +++ b/templates/drinks.rs.html @@ -0,0 +1,33 @@ +@use super::base_html; + +@(shift_id: u32) + +@:base_html({ + +
+ + + + + + + + + + + + + + + + + + + + + +
+ +}) diff --git a/templates/home.rs.html b/templates/home.rs.html index 1ca3a27..3346720 100644 --- a/templates/home.rs.html +++ b/templates/home.rs.html @@ -8,8 +8,15 @@
- @:shift_button_html(open_shift) + @:shift_button_html(open_shift.as_ref())
+ @if open_shift.is_some() { + + }
})