leptos_forms_rs/devtools/debug/
debug_utilities.rs1use crate::core::types::FieldValue;
6use crate::core::{Form, FormHandle};
7use leptos::prelude::GetUntracked;
8use std::collections::HashMap;
9use std::time::SystemTime;
10
11use super::super::types::{FieldChange, FormSnapshot, IntegrityCheck, SnapshotDiff};
12
13pub struct DebugUtilities;
15
16impl DebugUtilities {
17 pub fn create_form_snapshot<T: Form + Send + Sync + PartialEq>(
18 form_handle: &FormHandle<T>,
19 ) -> FormSnapshot {
20 let form_data = form_handle.values().get_untracked();
21 let state = form_handle.state().get_untracked();
22 let mut field_values = HashMap::new();
23
24 for field_metadata in &T::schema().field_metadata {
25 let value = form_data.get_field_value(&field_metadata.name);
26 field_values.insert(field_metadata.name.clone(), value);
27 }
28
29 FormSnapshot {
30 form_name: T::schema().name,
31 timestamp: SystemTime::now(),
32 field_count: T::schema().field_metadata.len(),
33 field_values,
34 is_dirty: state.is_dirty,
35 is_submitting: state.is_submitting,
36 has_errors: !state.errors.is_empty(),
37 }
38 }
39
40 pub fn compare_snapshots(snapshot1: &FormSnapshot, snapshot2: &FormSnapshot) -> SnapshotDiff {
41 let mut changed_fields = Vec::new();
42
43 for (field_name, value1) in &snapshot1.field_values {
44 if let Some(value2) = snapshot2.field_values.get(field_name) {
45 if value1 != value2 {
46 changed_fields.push(FieldChange {
47 field_name: field_name.clone(),
48 old_value: Some(value1.clone()),
49 new_value: Some(value2.clone()),
50 });
51 }
52 }
53 }
54
55 SnapshotDiff {
56 has_changes: !changed_fields.is_empty(),
57 changed_fields,
58 }
59 }
60
61 pub fn export_form_data<T: Form + Send + Sync + PartialEq + std::fmt::Debug>(
62 form_handle: &FormHandle<T>,
63 ) -> String {
64 let form_data = form_handle.values().get_untracked();
65 let state = form_handle.state().get_untracked();
66
67 format!(
68 "Form: {}\nFields: {}\nIs Dirty: {}\nIs Submitting: {}\nHas Errors: {}\nData: {:?}",
69 T::schema().name,
70 T::schema().field_metadata.len(),
71 state.is_dirty,
72 state.is_submitting,
73 !state.errors.is_empty(),
74 form_data
75 )
76 }
77
78 pub fn validate_form_integrity<T: Form + Send + Sync + PartialEq>(
79 form_handle: &FormHandle<T>,
80 ) -> IntegrityCheck {
81 let mut issues = Vec::new();
82
83 let form_data = form_handle.values().get_untracked();
85 for field_metadata in &T::schema().field_metadata {
86 if field_metadata.is_required {
87 let value = form_data.get_field_value(&field_metadata.name);
88 if matches!(value, FieldValue::Null)
89 || matches!(value, FieldValue::String(ref s) if s.is_empty())
90 {
91 issues.push(format!("Required field '{}' is empty", field_metadata.name));
92 }
93 }
94 }
95
96 IntegrityCheck {
97 is_valid: issues.is_empty(),
98 issues,
99 }
100 }
101}