Update backend to allow creating tasks to work with the browser.

This commit is contained in:
Drew Galbraith 2024-07-05 22:56:25 -07:00
parent d2dfbb9a4a
commit f3ccc4f194
4 changed files with 49 additions and 2 deletions

View File

@ -0,0 +1,6 @@
CREATE TABLE IF NOT EXISTS task (
id integer NOT NULL PRIMARY KEY AUTOINCREMENT,
title text NOT NULL,
description text,
CHECK(title <> '')
);

View File

@ -1,8 +1,15 @@
use std::sync::Arc;
use std::{collections::HashMap, sync::Arc};
use serde::Serialize;
use sqlx::SqlitePool;
#[derive(Clone)]
pub struct AppState {
pub db_pool: Arc<SqlitePool>,
}
#[derive(Serialize)]
pub struct FormErrorResponse {
pub message: String,
pub field_errors: HashMap<String, String>,
}

View File

@ -24,7 +24,9 @@ async fn main() {
.fallback(handle404)
.route(
"/tasks",
get(routes::tasks::list).post(routes::tasks::create),
get(routes::tasks::list)
.post(routes::tasks::create)
.options(routes::tasks::options),
)
.with_state(state);

View File

@ -1,9 +1,12 @@
use std::collections::HashMap;
use axum::extract::{Json, State};
use axum::http::header;
use axum::http::StatusCode;
use axum::response::IntoResponse;
use serde::Deserialize;
use crate::global::FormErrorResponse;
use crate::{global::AppState, models::Task};
pub async fn list(state: State<AppState>) -> impl IntoResponse {
@ -23,6 +26,23 @@ pub struct NewTask {
}
pub async fn create(state: State<AppState>, Json(req): Json<NewTask>) -> impl IntoResponse {
if req.title.is_empty() {
return (
StatusCode::BAD_REQUEST,
[(header::ACCESS_CONTROL_ALLOW_ORIGIN, "*")],
serde_json::to_string(&FormErrorResponse {
message: "Failed to validate new task".to_string(),
field_errors: [(
"title".to_string(),
"Task title must not be empty.".to_string(),
)]
.iter()
.cloned()
.collect(),
})
.unwrap(),
);
}
let task = Task::new(req.title, req.description);
let new_task = task.insert(&state.db_pool).await.unwrap();
@ -33,3 +53,15 @@ pub async fn create(state: State<AppState>, Json(req): Json<NewTask>) -> impl In
serde_json::to_string(&new_task).unwrap(),
)
}
pub async fn options() -> impl IntoResponse {
(
StatusCode::OK,
[
(header::ACCESS_CONTROL_ALLOW_ORIGIN, "*"),
(header::ACCESS_CONTROL_ALLOW_METHODS, "POST, GET, OPTIONS"),
(header::ACCESS_CONTROL_ALLOW_HEADERS, "Content-Type"),
(header::ACCESS_CONTROL_MAX_AGE, "86400"),
],
)
}