Skip to main content

quokka_admin/service/page_loader/
admin_create_form_page_loader.rs

1use std::marker::PhantomData;
2
3use axum::http::Method;
4use quokka::{
5    handler::html::TemplateDataLoader,
6    state::{FromState, ProvideState},
7};
8
9use crate::{
10    data::Severity,
11    service::{AdminCreateForm, FormBuilder, FormProperties},
12};
13
14use super::{AdminPageData, AdminPageLoader};
15
16pub struct AdminCreateFormPageLoader<S, F> {
17    form_builder: FormBuilder<S>,
18    admin_page_loader: AdminPageLoader,
19    state: S,
20    _form: PhantomData<F>,
21}
22
23#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
24pub struct AdminFormCreatePageData {
25    form: FormProperties,
26}
27
28impl<S, F> TemplateDataLoader<S> for AdminCreateFormPageLoader<S, F>
29where
30    S: ProvideState<AdminPageLoader>,
31    S: Send + Sync + Clone + 'static,
32    F: Send + Sync + 'static,
33    F: AdminCreateForm<S> + 'static,
34{
35    type Args = (Method, <AdminPageLoader as TemplateDataLoader<S>>::Args);
36
37    type Data = AdminPageData<AdminFormCreatePageData>;
38
39    #[tracing::instrument(
40        skip_all,
41        target = "quokka_admin::service::page_loader::admin_create_form_page_loader::AdminCreateFormPageLoader"
42    )]
43    async fn load_data(&self, (method, base_params): Self::Args) -> quokka::Result<Self::Data> {
44        let mut base = <AdminPageLoader as TemplateDataLoader<S>>::load_data(
45            &self.admin_page_loader,
46            base_params,
47        )
48        .await?;
49
50        if method == Method::POST {
51            tracing::debug!(
52                create_form = std::any::type_name::<F>(),
53                "Received POST method in AdminCreateFormPageLoader::load_data, this indicates a success for us",
54            );
55
56            base = base.message(
57                Severity::Success.message("Entity Created", "Entity created successfully"),
58            );
59        }
60
61        let form = self
62            .form_builder
63            .construct_form_data(F::get_form())
64            .await
65            .inspect_err(|error| {
66                tracing::error!(
67                    ?error,
68                    create_form = std::any::type_name::<F>(),
69                    "Unable to construct form data in create form",
70                );
71            })?;
72
73        Ok(base.page(AdminFormCreatePageData { form }))
74    }
75
76    #[tracing::instrument(
77        skip_all,
78        target = "quokka_admin::service::page_loader::admin_create_form_page_loader::AdminCreateFormPageLoader"
79    )]
80    async fn render_error(&self, error: quokka::Error) -> impl axum::response::IntoResponse {
81        <AdminPageLoader as TemplateDataLoader<S>>::render_error(&self.admin_page_loader, error)
82            .await
83    }
84}
85
86impl<S, F> FromState<S> for AdminCreateFormPageLoader<S, F>
87where
88    S: Clone,
89    S: ProvideState<FormBuilder<S>>,
90    S: ProvideState<AdminPageLoader>,
91{
92    fn from_state(state: &S) -> Self {
93        Self {
94            form_builder: state.provide(),
95            admin_page_loader: state.provide(),
96            state: state.clone(),
97            _form: PhantomData,
98        }
99    }
100}
101
102impl<S: Clone, F> Clone for AdminCreateFormPageLoader<S, F> {
103    fn clone(&self) -> Self {
104        Self {
105            form_builder: self.form_builder.clone(),
106            admin_page_loader: self.admin_page_loader.clone(),
107            state: self.state.clone(),
108            _form: PhantomData,
109        }
110    }
111}