use std::marker::PhantomData;
use axum::http::Method;
use quokka::{
handler::html::TemplateDataLoader,
state::{FromState, ProvideState},
};
use crate::{
data::Severity,
service::{AdminCreateForm, FormBuilder, FormProperties},
};
use super::{AdminPageData, AdminPageLoader};
pub struct AdminCreateFormPageLoader<S, F> {
form_builder: FormBuilder<S>,
admin_page_loader: AdminPageLoader,
state: S,
_form: PhantomData<F>,
}
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
pub struct AdminFormCreatePageData {
form: FormProperties,
}
impl<S, F> TemplateDataLoader<S> for AdminCreateFormPageLoader<S, F>
where
S: ProvideState<AdminPageLoader>,
S: Send + Sync + Clone + 'static,
F: Send + Sync + 'static,
F: AdminCreateForm<S> + 'static,
{
type Args = (Method, <AdminPageLoader as TemplateDataLoader<S>>::Args);
type Data = AdminPageData<AdminFormCreatePageData>;
#[tracing::instrument(
skip_all,
target = "quokka_admin::service::page_loader::admin_create_form_page_loader::AdminCreateFormPageLoader"
)]
async fn load_data(&self, (method, base_params): Self::Args) -> quokka::Result<Self::Data> {
let mut base = <AdminPageLoader as TemplateDataLoader<S>>::load_data(
&self.admin_page_loader,
base_params,
)
.await?;
if method == Method::POST {
tracing::debug!(
create_form = std::any::type_name::<F>(),
"Received POST method in AdminCreateFormPageLoader::load_data, this indicates a success for us",
);
base = base.message(
Severity::Success.message("Entity Created", "Entity created successfully"),
);
}
let form = self
.form_builder
.construct_form_data(F::get_form())
.await
.inspect_err(|error| {
tracing::error!(
?error,
create_form = std::any::type_name::<F>(),
"Unable to construct form data in create form",
);
})?;
Ok(base.page(AdminFormCreatePageData { form }))
}
#[tracing::instrument(
skip_all,
target = "quokka_admin::service::page_loader::admin_create_form_page_loader::AdminCreateFormPageLoader"
)]
async fn render_error(&self, error: quokka::Error) -> impl axum::response::IntoResponse {
<AdminPageLoader as TemplateDataLoader<S>>::render_error(&self.admin_page_loader, error)
.await
}
}
impl<S, F> FromState<S> for AdminCreateFormPageLoader<S, F>
where
S: Clone,
S: ProvideState<FormBuilder<S>>,
S: ProvideState<AdminPageLoader>,
{
fn from_state(state: &S) -> Self {
Self {
form_builder: state.provide(),
admin_page_loader: state.provide(),
state: state.clone(),
_form: PhantomData,
}
}
}
impl<S: Clone, F> Clone for AdminCreateFormPageLoader<S, F> {
fn clone(&self) -> Self {
Self {
form_builder: self.form_builder.clone(),
admin_page_loader: self.admin_page_loader.clone(),
state: self.state.clone(),
_form: PhantomData,
}
}
}