use std::collections::HashMap; use leptos::prelude::*; use uuid::Uuid; use crate::common::ValueType; use crate::components::{Toast, ToastContext}; use crate::pages::api::students::{get_student_data, PutStudentData}; use crate::utils::get_user_claims; pub struct StudentFormInfo { pub data_map: RwSignal>, pub user_id: Memo>, pub submit_action: Callback<()>, pub refresh_trigger: Trigger, pub data_resource: Resource, ServerFnError>>, pub submit_pending: Memo, } pub fn use_student_form( form_type: impl Into>, enable_toasts: bool, ) -> StudentFormInfo { let form_type = form_type.into(); let user_claims = get_user_claims(); let user_id = Memo::new(move |_| { user_claims.get() .map(|info| info.claims.subject.clone()) }); let data_map = RwSignal::new(HashMap::new()); let refresh_trigger = Trigger::new(); let data_resource = Resource::new( move || (user_id.get().unwrap_or_default(), form_type.get(), refresh_trigger.track()), async move |(id, form_type, _)| get_student_data( id, form_type, ).await ); Effect::new(move || { data_resource.with(|map_opt| { let Some(Ok(map)) = map_opt else { return; }; data_map.set(map.to_owned()); }); }); let submit_action = ServerAction::::new(); let on_submit = move || { submit_action.dispatch(PutStudentData { subject: user_id.get().unwrap_or_default(), data_type: form_type.get(), data_map: data_map.get() }); }; if enable_toasts { let mut toasts = expect_context::(); Effect::watch( move || submit_action.value().get(), move |value, _, _| { let Some(result) = value else { return; }; let toast = match result { Ok(_) => Toast::new() .id(Uuid::new_v4()) .header("Submission Successful") .msg("You may continue editing or fill out another form."), Err(e) => Toast::new() .id(Uuid::new_v4()) .header("Submission Failed") .msg(e.to_string()) }; toasts.toast(toast); untrack(move || submit_action.clear()); }, false ); } StudentFormInfo { data_map, refresh_trigger, data_resource, user_id, submit_action: on_submit.into(), submit_pending: submit_action.pending() } }