feat: add /plants page

main
Jef Roosens 2025-01-24 21:49:46 +01:00
parent 18499631ea
commit dce23599ef
No known key found for this signature in database
GPG Key ID: 21FD3D77D56BAF49
4 changed files with 51 additions and 17 deletions

View File

@ -1,7 +1,7 @@
use diesel::prelude::*; use diesel::prelude::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::db::{schema::*, DbPool, DbResult}; use crate::db::{schema::*, DbPool, DbResult, Pagination};
#[derive(Serialize, Queryable, Selectable)] #[derive(Serialize, Queryable, Selectable)]
#[diesel(table_name = plants)] #[diesel(table_name = plants)]
@ -45,4 +45,12 @@ impl Plant {
.first(&mut pool.get()?) .first(&mut pool.get()?)
.optional()?) .optional()?)
} }
pub fn page(pool: &DbPool, page: Pagination) -> DbResult<Vec<Self>> {
Ok(plants::table
.select(Self::as_select())
.offset((page.page * page.per_page).into())
.limit(page.per_page.into())
.get_results(&mut pool.get()?)?)
}
} }

View File

@ -1,20 +1,20 @@
use axum::{ use axum::{
extract::{Path, State}, extract::{Path, Query, State},
http::HeaderMap, http::HeaderMap,
response::Html, response::Html,
routing::{get, post}, routing::get,
Form, Router, Form, Router,
}; };
use tera::Context; use tera::Context;
use crate::db::{self, DbError, Event, Plant}; use crate::db::{self, DbError, Event, Pagination, Plant};
use super::error::AppError; use super::error::AppError;
pub fn app() -> axum::Router<crate::Context> { pub fn app() -> axum::Router<crate::Context> {
Router::new() Router::new()
.route("/{id}", get(get_plant_page)) .route("/{id}", get(get_plant_page))
.route("/", post(post_plant)) .route("/", get(get_plants).post(post_plant))
} }
async fn get_plant_page( async fn get_plant_page(
@ -54,6 +54,26 @@ async fn get_plant_page(
} }
} }
async fn get_plants(
State(ctx): State<crate::Context>,
Query(page): Query<Pagination>,
headers: HeaderMap,
) -> super::Result<Html<String>> {
let plants = tokio::task::spawn_blocking(move || db::Plant::page(&ctx.pool, page))
.await
.unwrap()?;
let mut context = Context::new();
context.insert("plants", &plants);
Ok(Html(super::render_view(
&ctx.tera,
"views/plants.html",
&context,
&headers,
)?))
}
async fn post_plant( async fn post_plant(
State(ctx): State<crate::Context>, State(ctx): State<crate::Context>,
Form(plant): Form<db::NewPlant>, Form(plant): Form<db::NewPlant>,

View File

@ -8,9 +8,13 @@
</div> </div>
{% endmacro info %} {% endmacro info %}
{% macro name(plant) %}
<a hx-get="/plants/{{ plant.id }}" hx-target="#content" hx-push-url="true">{{ plant.name }} (<em>{{ plant.species }}</em>)</a>
{% endmacro %}
{% macro li(plant) %} {% macro li(plant) %}
<li> <li>
<a hx-get="/plants/{{ plant.id }}" hx-target="#content" hx-push-url="true">{{ plant.name }}</a> ({{ plant.species }}) {{ self::name(plant=plant) }}
</li> </li>
{% endmacro li %} {% endmacro li %}
@ -26,16 +30,9 @@
{% macro form(target="#plants > ul") %} {% macro form(target="#plants > ul") %}
<form hx-post="/plants" hx-target="{{ target }}" hx-swap="beforeend"> <form hx-post="/plants" hx-target="{{ target }}" hx-swap="beforeend">
<label for="name">Name:</label> <input type="text" id="name" name="name" placeholder="My super cool plant"></br>
<input type="text" id="name" name="name"></br> <input type="text" id="species" name="species" placeholder="Philodendron Candens"></br>
<label for="species">Species:</label> <textarea id="description" name="description" rows=2 placeholder="An additional description"></textarea></br>
<input type="text" id="species" name="species"></br> <input type="submit" value="Add plant">
<label for="description">Description:</label>
<textarea id="description" name="description" rows=4></textarea></br>
<input type="submit">
</form> </form>
{% endmacro %} {% endmacro %}
{% macro name(plant) %}
<a hx-get="/plants/{{ plant.id }}" hx-target="#content" hx-push-url="true">{{ plant.name }} (<em>{{ plant.species }}</em>)</a>
{% endmacro %}

View File

@ -0,0 +1,9 @@
{% import "components/plant.html" as comp_plant %}
<h1>Plants</h1>
<ul>
{% for plant in plants %}
{{ comp_plant::li(plant=plant) }}
{% endfor %}
</ul>