1use serde::{Deserialize, Serialize};
41
42#[derive(Debug, Clone, Serialize, Deserialize)]
47pub struct StaticFormMetadata {
48 pub id: String,
50
51 pub action: String,
53
54 pub method: String,
56
57 pub class: String,
59
60 pub fields: Vec<StaticFieldMetadata>,
62}
63
64impl StaticFormMetadata {
65 pub fn new(
67 id: impl Into<String>,
68 action: impl Into<String>,
69 method: impl Into<String>,
70 class: impl Into<String>,
71 ) -> Self {
72 Self {
73 id: id.into(),
74 action: action.into(),
75 method: method.into(),
76 class: class.into(),
77 fields: Vec::new(),
78 }
79 }
80
81 pub fn with_field(mut self, field: StaticFieldMetadata) -> Self {
83 self.fields.push(field);
84 self
85 }
86
87 pub fn with_fields(mut self, fields: Vec<StaticFieldMetadata>) -> Self {
89 self.fields = fields;
90 self
91 }
92}
93
94#[derive(Debug, Clone, Serialize, Deserialize)]
99pub struct StaticFieldMetadata {
100 pub name: String,
102
103 pub field_type: String,
105
106 pub widget: String,
108
109 pub required: bool,
111
112 pub label: String,
114
115 pub placeholder: String,
117
118 pub input_class: String,
120
121 pub wrapper_class: String,
123
124 pub label_class: String,
126
127 pub error_class: String,
129}
130
131impl StaticFieldMetadata {
132 pub fn new(name: impl Into<String>, field_type: impl Into<String>) -> Self {
134 let name_str = name.into();
135 Self {
136 label: name_str.clone(),
137 name: name_str,
138 field_type: field_type.into(),
139 widget: "TextInput".to_string(),
140 required: false,
141 placeholder: String::new(),
142 input_class: "reinhardt-input".to_string(),
143 wrapper_class: "reinhardt-field".to_string(),
144 label_class: "reinhardt-label".to_string(),
145 error_class: "reinhardt-error".to_string(),
146 }
147 }
148
149 pub fn with_widget(mut self, widget: impl Into<String>) -> Self {
151 self.widget = widget.into();
152 self
153 }
154
155 pub fn with_required(mut self, required: bool) -> Self {
157 self.required = required;
158 self
159 }
160
161 pub fn with_label(mut self, label: impl Into<String>) -> Self {
163 self.label = label.into();
164 self
165 }
166
167 pub fn with_placeholder(mut self, placeholder: impl Into<String>) -> Self {
169 self.placeholder = placeholder.into();
170 self
171 }
172
173 pub fn with_input_class(mut self, class: impl Into<String>) -> Self {
175 self.input_class = class.into();
176 self
177 }
178
179 pub fn with_wrapper_class(mut self, class: impl Into<String>) -> Self {
181 self.wrapper_class = class.into();
182 self
183 }
184
185 pub fn with_label_class(mut self, class: impl Into<String>) -> Self {
187 self.label_class = class.into();
188 self
189 }
190
191 pub fn with_error_class(mut self, class: impl Into<String>) -> Self {
193 self.error_class = class.into();
194 self
195 }
196}
197
198#[cfg(test)]
199mod tests {
200 use super::*;
201 use rstest::rstest;
202
203 #[rstest]
204 fn test_static_form_metadata_creation() {
205 let form = StaticFormMetadata::new("login-form", "/api/login", "POST", "login-form");
206
207 assert_eq!(form.id, "login-form");
208 assert_eq!(form.action, "/api/login");
209 assert_eq!(form.method, "POST");
210 assert_eq!(form.class, "login-form");
211 assert!(form.fields.is_empty());
212 }
213
214 #[rstest]
215 fn test_static_form_metadata_with_fields() {
216 let form = StaticFormMetadata::new("my-form", "/api/submit", "POST", "my-form")
217 .with_fields(vec![
218 StaticFieldMetadata::new("username", "CharField").with_required(true),
219 StaticFieldMetadata::new("email", "EmailField"),
220 ]);
221
222 assert_eq!(form.id, "my-form");
223 assert_eq!(form.fields.len(), 2);
224 assert_eq!(form.fields[0].name, "username");
225 assert!(form.fields[0].required);
226 assert_eq!(form.fields[1].name, "email");
227 assert!(!form.fields[1].required);
228 }
229
230 #[rstest]
231 fn test_static_field_metadata_defaults() {
232 let field = StaticFieldMetadata::new("test_field", "CharField");
233
234 assert_eq!(field.name, "test_field");
235 assert_eq!(field.label, "test_field");
236 assert_eq!(field.field_type, "CharField");
237 assert_eq!(field.widget, "TextInput");
238 assert!(!field.required);
239 assert!(field.placeholder.is_empty());
240 assert_eq!(field.input_class, "reinhardt-input");
241 assert_eq!(field.wrapper_class, "reinhardt-field");
242 assert_eq!(field.label_class, "reinhardt-label");
243 assert_eq!(field.error_class, "reinhardt-error");
244 }
245
246 #[rstest]
247 fn test_static_field_metadata_customization() {
248 let field = StaticFieldMetadata::new("email", "EmailField")
249 .with_widget("EmailInput")
250 .with_required(true)
251 .with_label("Email Address")
252 .with_placeholder("Enter your email")
253 .with_input_class("custom-input")
254 .with_wrapper_class("custom-wrapper");
255
256 assert_eq!(field.name, "email");
257 assert_eq!(field.label, "Email Address");
258 assert_eq!(field.widget, "EmailInput");
259 assert!(field.required);
260 assert_eq!(field.placeholder, "Enter your email");
261 assert_eq!(field.input_class, "custom-input");
262 assert_eq!(field.wrapper_class, "custom-wrapper");
263 }
264
265 #[rstest]
266 fn test_static_metadata_serialization() {
267 let form = StaticFormMetadata::new("test-form", "/api/test", "POST", "test-form")
268 .with_field(StaticFieldMetadata::new("name", "CharField").with_required(true));
269
270 let json = serde_json::to_string(&form).expect("Failed to serialize");
271 assert!(json.contains("\"id\":\"test-form\""));
272 assert!(json.contains("\"action\":\"/api/test\""));
273 assert!(json.contains("\"name\":\"name\""));
274
275 let deserialized: StaticFormMetadata =
276 serde_json::from_str(&json).expect("Failed to deserialize");
277 assert_eq!(deserialized.id, "test-form");
278 assert_eq!(deserialized.action, "/api/test");
279 assert_eq!(deserialized.fields.len(), 1);
280 }
281}