feat: initialize thoughts-frontend with Next.js, TypeScript, and ESLint
- Add ESLint configuration for Next.js and TypeScript support. - Create Next.js configuration file with standalone output option. - Initialize package.json with scripts for development, build, and linting. - Set up PostCSS configuration for Tailwind CSS. - Add SVG assets for UI components. - Create TypeScript configuration for strict type checking and module resolution.
This commit is contained in:
93
thoughts-backend/api/src/routers/user.rs
Normal file
93
thoughts-backend/api/src/routers/user.rs
Normal file
@@ -0,0 +1,93 @@
|
||||
use axum::{
|
||||
extract::{Path, Query, State},
|
||||
http::StatusCode,
|
||||
response::IntoResponse,
|
||||
routing::{get, post},
|
||||
Router,
|
||||
};
|
||||
use sea_orm::TryIntoModel;
|
||||
|
||||
use app::error::UserError;
|
||||
use app::persistence::user::{create_user, get_user, search_users};
|
||||
use app::state::AppState;
|
||||
use models::params::user::CreateUserParams;
|
||||
use models::queries::user::UserQuery;
|
||||
use models::schemas::user::{UserListSchema, UserSchema};
|
||||
|
||||
use crate::error::ApiError;
|
||||
use crate::extractor::{Json, Valid};
|
||||
use crate::models::{ApiErrorResponse, ParamsErrorResponse};
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "",
|
||||
request_body = CreateUserParams,
|
||||
responses(
|
||||
(status = 201, description = "User created", body = UserSchema),
|
||||
(status = 400, description = "Bad request", body = ApiErrorResponse),
|
||||
(status = 422, description = "Validation error", body = ParamsErrorResponse),
|
||||
(status = 500, description = "Internal server error", body = ApiErrorResponse),
|
||||
)
|
||||
)]
|
||||
async fn users_post(
|
||||
state: State<AppState>,
|
||||
Valid(Json(params)): Valid<Json<CreateUserParams>>,
|
||||
) -> Result<impl IntoResponse, ApiError> {
|
||||
let user = create_user(&state.conn, params)
|
||||
.await
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let user = user.try_into_model().unwrap();
|
||||
Ok((StatusCode::CREATED, Json(UserSchema::from(user))))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "",
|
||||
params(
|
||||
UserQuery
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "List users", body = UserListSchema),
|
||||
(status = 500, description = "Internal server error", body = ApiErrorResponse),
|
||||
)
|
||||
)]
|
||||
async fn users_get(
|
||||
state: State<AppState>,
|
||||
query: Query<UserQuery>,
|
||||
) -> Result<impl IntoResponse, ApiError> {
|
||||
let Query(query) = query;
|
||||
|
||||
let users = search_users(&state.conn, query)
|
||||
.await
|
||||
.map_err(ApiError::from)?;
|
||||
Ok(Json(UserListSchema::from(users)))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/{id}",
|
||||
params(
|
||||
("id" = i32, Path, description = "User id")
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "Get user", body = UserSchema),
|
||||
(status = 404, description = "Not found", body = ApiErrorResponse),
|
||||
(status = 500, description = "Internal server error", body = ApiErrorResponse),
|
||||
)
|
||||
)]
|
||||
async fn users_id_get(
|
||||
state: State<AppState>,
|
||||
Path(id): Path<i32>,
|
||||
) -> Result<impl IntoResponse, ApiError> {
|
||||
let user = get_user(&state.conn, id).await.map_err(ApiError::from)?;
|
||||
|
||||
user.map(|user| Json(UserSchema::from(user)))
|
||||
.ok_or_else(|| UserError::NotFound.into())
|
||||
}
|
||||
|
||||
pub fn create_user_router() -> Router<AppState> {
|
||||
Router::new()
|
||||
.route("/", post(users_post).get(users_get))
|
||||
.route("/{id}", get(users_id_get))
|
||||
}
|
Reference in New Issue
Block a user