1use crate::classes::ClassBuilder;
7use serde::{Deserialize, Serialize};
8use std::collections::HashMap;
9use std::fmt;
10
11#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
13pub enum ValidationRule {
14 Required,
16 Pattern(String),
18 Length(usize, usize),
20 Range(f64, f64),
22 Custom(String),
24}
25
26impl fmt::Display for ValidationRule {
27 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28 match self {
29 ValidationRule::Required => write!(f, "required"),
30 ValidationRule::Pattern(pattern) => write!(f, "pattern:{}", pattern),
31 ValidationRule::Length(min, max) => write!(f, "length:{}-{}", min, max),
32 ValidationRule::Range(min, max) => write!(f, "range:{}-{}", min, max),
33 ValidationRule::Custom(rule) => write!(f, "{}", rule),
34 }
35 }
36}
37
38impl ValidationRule {
39 pub fn to_class_name(&self) -> String {
41 match self {
42 ValidationRule::Required => "validation-required".to_string(),
43 ValidationRule::Pattern(pattern) => format!(
44 "validation-pattern-{}",
45 pattern
46 .replace(":", "-")
47 .replace("(", "")
48 .replace(")", "")
49 .replace("*", "star")
50 .replace("+", "plus")
51 .replace("?", "question")
52 .replace("^", "caret")
53 .replace("$", "dollar")
54 .replace("|", "pipe")
55 .replace("\\", "backslash")
56 .replace("/", "slash")
57 .replace(" ", "-")
58 ),
59 ValidationRule::Length(min, max) => format!("validation-length-{}-{}", min, max),
60 ValidationRule::Range(min, max) => format!("validation-range-{}-{}", min, max),
61 ValidationRule::Custom(rule) => format!(
62 "validation-{}",
63 rule.replace(":", "-")
64 .replace("(", "")
65 .replace(")", "")
66 .replace("*", "star")
67 .replace("+", "plus")
68 .replace("?", "question")
69 .replace("^", "caret")
70 .replace("$", "dollar")
71 .replace("|", "pipe")
72 .replace("\\", "backslash")
73 .replace("/", "slash")
74 .replace(" ", "-")
75 ),
76 }
77 }
78
79 pub fn to_css_value(&self) -> String {
81 self.to_string()
82 }
83}
84
85#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
87pub enum ValidationSeverity {
88 Error,
90 Warning,
92 Info,
94 Success,
96 Custom(String),
98}
99
100impl fmt::Display for ValidationSeverity {
101 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102 match self {
103 ValidationSeverity::Error => write!(f, "error"),
104 ValidationSeverity::Warning => write!(f, "warning"),
105 ValidationSeverity::Info => write!(f, "info"),
106 ValidationSeverity::Success => write!(f, "success"),
107 ValidationSeverity::Custom(severity) => write!(f, "{}", severity),
108 }
109 }
110}
111
112impl ValidationSeverity {
113 pub fn to_class_name(&self) -> String {
115 match self {
116 ValidationSeverity::Error => "validation-error".to_string(),
117 ValidationSeverity::Warning => "validation-warning".to_string(),
118 ValidationSeverity::Info => "validation-info".to_string(),
119 ValidationSeverity::Success => "validation-success".to_string(),
120 ValidationSeverity::Custom(severity) => format!("validation-{}", severity),
121 }
122 }
123
124 pub fn to_css_value(&self) -> String {
126 self.to_string()
127 }
128}
129
130#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
132pub enum ValidationScope {
133 Global,
135 Local,
137 Component,
139 Page,
141 Custom(String),
143}
144
145impl fmt::Display for ValidationScope {
146 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147 match self {
148 ValidationScope::Global => write!(f, "global"),
149 ValidationScope::Local => write!(f, "local"),
150 ValidationScope::Component => write!(f, "component"),
151 ValidationScope::Page => write!(f, "page"),
152 ValidationScope::Custom(scope) => write!(f, "{}", scope),
153 }
154 }
155}
156
157impl ValidationScope {
158 pub fn to_class_name(&self) -> String {
160 match self {
161 ValidationScope::Global => "validation-global".to_string(),
162 ValidationScope::Local => "validation-local".to_string(),
163 ValidationScope::Component => "validation-component".to_string(),
164 ValidationScope::Page => "validation-page".to_string(),
165 ValidationScope::Custom(scope) => format!("validation-{}", scope),
166 }
167 }
168
169 pub fn to_css_value(&self) -> String {
171 self.to_string()
172 }
173}
174
175#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
177pub enum ValidationMode {
178 Strict,
180 Loose,
182 Custom,
184 Disabled,
186 CustomMode(String),
188}
189
190impl fmt::Display for ValidationMode {
191 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
192 match self {
193 ValidationMode::Strict => write!(f, "strict"),
194 ValidationMode::Loose => write!(f, "loose"),
195 ValidationMode::Custom => write!(f, "custom"),
196 ValidationMode::Disabled => write!(f, "disabled"),
197 ValidationMode::CustomMode(mode) => write!(f, "{}", mode),
198 }
199 }
200}
201
202impl ValidationMode {
203 pub fn to_class_name(&self) -> String {
205 match self {
206 ValidationMode::Strict => "validation-strict".to_string(),
207 ValidationMode::Loose => "validation-loose".to_string(),
208 ValidationMode::Custom => "validation-custom".to_string(),
209 ValidationMode::Disabled => "validation-disabled".to_string(),
210 ValidationMode::CustomMode(mode) => format!("validation-{}", mode),
211 }
212 }
213
214 pub fn to_css_value(&self) -> String {
216 self.to_string()
217 }
218}
219
220#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
222pub enum ValidationResult {
223 Valid,
225 Invalid(String),
227 Warning(String),
229 Info(String),
231 Custom(String),
233}
234
235impl fmt::Display for ValidationResult {
236 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
237 match self {
238 ValidationResult::Valid => write!(f, "valid"),
239 ValidationResult::Invalid(message) => write!(f, "invalid:{}", message),
240 ValidationResult::Warning(message) => write!(f, "warning:{}", message),
241 ValidationResult::Info(message) => write!(f, "info:{}", message),
242 ValidationResult::Custom(result) => write!(f, "{}", result),
243 }
244 }
245}
246
247impl ValidationResult {
248 pub fn to_class_name(&self) -> String {
250 match self {
251 ValidationResult::Valid => "validation-valid".to_string(),
252 ValidationResult::Invalid(_) => "validation-invalid".to_string(),
253 ValidationResult::Warning(_) => "validation-warning".to_string(),
254 ValidationResult::Info(_) => "validation-info".to_string(),
255 ValidationResult::Custom(result) => format!("validation-{}", result),
256 }
257 }
258
259 pub fn to_css_value(&self) -> String {
261 self.to_string()
262 }
263}
264
265pub trait EnhancedValidationUtilities {
267 fn validation_rule(self, rule: ValidationRule) -> Self;
269 fn validation_severity(self, severity: ValidationSeverity) -> Self;
271 fn validation_scope(self, scope: ValidationScope) -> Self;
273 fn validation_mode(self, mode: ValidationMode) -> Self;
275 fn validation_result(self, result: ValidationResult) -> Self;
277 fn validation_custom(self, name: &str, options: HashMap<String, String>) -> Self;
279}
280
281impl EnhancedValidationUtilities for ClassBuilder {
282 fn validation_rule(self, rule: ValidationRule) -> Self {
283 self.class(rule.to_class_name())
284 }
285
286 fn validation_severity(self, severity: ValidationSeverity) -> Self {
287 self.class(severity.to_class_name())
288 }
289
290 fn validation_scope(self, scope: ValidationScope) -> Self {
291 self.class(scope.to_class_name())
292 }
293
294 fn validation_mode(self, mode: ValidationMode) -> Self {
295 self.class(mode.to_class_name())
296 }
297
298 fn validation_result(self, result: ValidationResult) -> Self {
299 self.class(result.to_class_name())
300 }
301
302 fn validation_custom(self, name: &str, _options: HashMap<String, String>) -> Self {
303 let validation_class = format!("validation-{}", name);
304 self.class(&validation_class)
305 }
306}
307
308pub trait EnhancedValidationConvenience {
310 fn validation_required(self) -> Self;
312 fn validation_pattern(self, pattern: &str) -> Self;
314 fn validation_length(self, min: usize, max: usize) -> Self;
316 fn validation_range(self, min: f64, max: f64) -> Self;
318 fn validation_error(self) -> Self;
320 fn validation_warning(self) -> Self;
322 fn validation_info(self) -> Self;
324 fn validation_success(self) -> Self;
326 fn validation_global(self) -> Self;
328 fn validation_local(self) -> Self;
330 fn validation_component(self) -> Self;
332 fn validation_page(self) -> Self;
334 fn validation_strict(self) -> Self;
336 fn validation_loose(self) -> Self;
338 fn validation_custom_mode(self) -> Self;
340 fn validation_disabled(self) -> Self;
342 fn validation_valid(self) -> Self;
344 fn validation_invalid(self, message: &str) -> Self;
346 fn validation_warning_result(self, message: &str) -> Self;
348 fn validation_info_result(self, message: &str) -> Self;
350}
351
352impl EnhancedValidationConvenience for ClassBuilder {
353 fn validation_required(self) -> Self {
354 self.validation_rule(ValidationRule::Required)
355 }
356
357 fn validation_pattern(self, pattern: &str) -> Self {
358 self.validation_rule(ValidationRule::Pattern(pattern.to_string()))
359 }
360
361 fn validation_length(self, min: usize, max: usize) -> Self {
362 self.validation_rule(ValidationRule::Length(min, max))
363 }
364
365 fn validation_range(self, min: f64, max: f64) -> Self {
366 self.validation_rule(ValidationRule::Range(min, max))
367 }
368
369 fn validation_error(self) -> Self {
370 self.validation_severity(ValidationSeverity::Error)
371 }
372
373 fn validation_warning(self) -> Self {
374 self.validation_severity(ValidationSeverity::Warning)
375 }
376
377 fn validation_info(self) -> Self {
378 self.validation_severity(ValidationSeverity::Info)
379 }
380
381 fn validation_success(self) -> Self {
382 self.validation_severity(ValidationSeverity::Success)
383 }
384
385 fn validation_global(self) -> Self {
386 self.validation_scope(ValidationScope::Global)
387 }
388
389 fn validation_local(self) -> Self {
390 self.validation_scope(ValidationScope::Local)
391 }
392
393 fn validation_component(self) -> Self {
394 self.validation_scope(ValidationScope::Component)
395 }
396
397 fn validation_page(self) -> Self {
398 self.validation_scope(ValidationScope::Page)
399 }
400
401 fn validation_strict(self) -> Self {
402 self.validation_mode(ValidationMode::Strict)
403 }
404
405 fn validation_loose(self) -> Self {
406 self.validation_mode(ValidationMode::Loose)
407 }
408
409 fn validation_custom_mode(self) -> Self {
410 self.validation_mode(ValidationMode::Custom)
411 }
412
413 fn validation_disabled(self) -> Self {
414 self.validation_mode(ValidationMode::Disabled)
415 }
416
417 fn validation_valid(self) -> Self {
418 self.validation_result(ValidationResult::Valid)
419 }
420
421 fn validation_invalid(self, message: &str) -> Self {
422 self.validation_result(ValidationResult::Invalid(message.to_string()))
423 }
424
425 fn validation_warning_result(self, message: &str) -> Self {
426 self.validation_result(ValidationResult::Warning(message.to_string()))
427 }
428
429 fn validation_info_result(self, message: &str) -> Self {
430 self.validation_result(ValidationResult::Info(message.to_string()))
431 }
432}
433
434#[cfg(test)]
435mod tests {
436 use super::*;
437 use crate::classes::ClassBuilder;
438
439 #[test]
440 fn test_validation_rule_enum_values() {
441 assert_eq!(ValidationRule::Required.to_string(), "required");
442 assert_eq!(
443 ValidationRule::Pattern("test".to_string()).to_string(),
444 "pattern:test"
445 );
446 assert_eq!(ValidationRule::Length(1, 10).to_string(), "length:1-10");
447 assert_eq!(ValidationRule::Range(0.0, 100.0).to_string(), "range:0-100");
448 assert_eq!(
449 ValidationRule::Custom("custom".to_string()).to_string(),
450 "custom"
451 );
452 }
453
454 #[test]
455 fn test_validation_rule_class_names() {
456 assert_eq!(
457 ValidationRule::Required.to_class_name(),
458 "validation-required"
459 );
460 assert_eq!(
461 ValidationRule::Pattern("test".to_string()).to_class_name(),
462 "validation-pattern-test"
463 );
464 assert_eq!(
465 ValidationRule::Length(1, 10).to_class_name(),
466 "validation-length-1-10"
467 );
468 assert_eq!(
469 ValidationRule::Range(0.0, 100.0).to_class_name(),
470 "validation-range-0-100"
471 );
472 assert_eq!(
473 ValidationRule::Custom("custom".to_string()).to_class_name(),
474 "validation-custom"
475 );
476 }
477
478 #[test]
479 fn test_validation_severity_enum_values() {
480 assert_eq!(ValidationSeverity::Error.to_string(), "error");
481 assert_eq!(ValidationSeverity::Warning.to_string(), "warning");
482 assert_eq!(ValidationSeverity::Info.to_string(), "info");
483 assert_eq!(ValidationSeverity::Success.to_string(), "success");
484 assert_eq!(
485 ValidationSeverity::Custom("custom".to_string()).to_string(),
486 "custom"
487 );
488 }
489
490 #[test]
491 fn test_validation_severity_class_names() {
492 assert_eq!(
493 ValidationSeverity::Error.to_class_name(),
494 "validation-error"
495 );
496 assert_eq!(
497 ValidationSeverity::Warning.to_class_name(),
498 "validation-warning"
499 );
500 assert_eq!(ValidationSeverity::Info.to_class_name(), "validation-info");
501 assert_eq!(
502 ValidationSeverity::Success.to_class_name(),
503 "validation-success"
504 );
505 assert_eq!(
506 ValidationSeverity::Custom("custom".to_string()).to_class_name(),
507 "validation-custom"
508 );
509 }
510
511 #[test]
512 fn test_validation_scope_enum_values() {
513 assert_eq!(ValidationScope::Global.to_string(), "global");
514 assert_eq!(ValidationScope::Local.to_string(), "local");
515 assert_eq!(ValidationScope::Component.to_string(), "component");
516 assert_eq!(ValidationScope::Page.to_string(), "page");
517 assert_eq!(
518 ValidationScope::Custom("custom".to_string()).to_string(),
519 "custom"
520 );
521 }
522
523 #[test]
524 fn test_validation_scope_class_names() {
525 assert_eq!(ValidationScope::Global.to_class_name(), "validation-global");
526 assert_eq!(ValidationScope::Local.to_class_name(), "validation-local");
527 assert_eq!(
528 ValidationScope::Component.to_class_name(),
529 "validation-component"
530 );
531 assert_eq!(ValidationScope::Page.to_class_name(), "validation-page");
532 assert_eq!(
533 ValidationScope::Custom("custom".to_string()).to_class_name(),
534 "validation-custom"
535 );
536 }
537
538 #[test]
539 fn test_validation_mode_enum_values() {
540 assert_eq!(ValidationMode::Strict.to_string(), "strict");
541 assert_eq!(ValidationMode::Loose.to_string(), "loose");
542 assert_eq!(ValidationMode::Custom.to_string(), "custom");
543 assert_eq!(ValidationMode::Disabled.to_string(), "disabled");
544 assert_eq!(
545 ValidationMode::CustomMode("custom".to_string()).to_string(),
546 "custom"
547 );
548 }
549
550 #[test]
551 fn test_validation_mode_class_names() {
552 assert_eq!(ValidationMode::Strict.to_class_name(), "validation-strict");
553 assert_eq!(ValidationMode::Loose.to_class_name(), "validation-loose");
554 assert_eq!(ValidationMode::Custom.to_class_name(), "validation-custom");
555 assert_eq!(
556 ValidationMode::Disabled.to_class_name(),
557 "validation-disabled"
558 );
559 assert_eq!(
560 ValidationMode::CustomMode("custom".to_string()).to_class_name(),
561 "validation-custom"
562 );
563 }
564
565 #[test]
566 fn test_validation_result_enum_values() {
567 assert_eq!(ValidationResult::Valid.to_string(), "valid");
568 assert_eq!(
569 ValidationResult::Invalid("message".to_string()).to_string(),
570 "invalid:message"
571 );
572 assert_eq!(
573 ValidationResult::Warning("message".to_string()).to_string(),
574 "warning:message"
575 );
576 assert_eq!(
577 ValidationResult::Info("message".to_string()).to_string(),
578 "info:message"
579 );
580 assert_eq!(
581 ValidationResult::Custom("custom".to_string()).to_string(),
582 "custom"
583 );
584 }
585
586 #[test]
587 fn test_validation_result_class_names() {
588 assert_eq!(ValidationResult::Valid.to_class_name(), "validation-valid");
589 assert_eq!(
590 ValidationResult::Invalid("message".to_string()).to_class_name(),
591 "validation-invalid"
592 );
593 assert_eq!(
594 ValidationResult::Warning("message".to_string()).to_class_name(),
595 "validation-warning"
596 );
597 assert_eq!(
598 ValidationResult::Info("message".to_string()).to_class_name(),
599 "validation-info"
600 );
601 assert_eq!(
602 ValidationResult::Custom("custom".to_string()).to_class_name(),
603 "validation-custom"
604 );
605 }
606
607 #[test]
608 fn test_enhanced_validation_utilities() {
609 let classes = ClassBuilder::new()
610 .validation_rule(ValidationRule::Required)
611 .validation_severity(ValidationSeverity::Error)
612 .validation_scope(ValidationScope::Global)
613 .validation_mode(ValidationMode::Strict)
614 .validation_result(ValidationResult::Valid);
615
616 let result = classes.build();
617 assert!(result.classes.contains("validation-required"));
618 assert!(result.classes.contains("validation-error"));
619 assert!(result.classes.contains("validation-global"));
620 assert!(result.classes.contains("validation-strict"));
621 assert!(result.classes.contains("validation-valid"));
622 }
623
624 #[test]
625 fn test_enhanced_validation_convenience() {
626 let classes = ClassBuilder::new()
627 .validation_required()
628 .validation_pattern("test")
629 .validation_length(1, 10)
630 .validation_range(0.0, 100.0)
631 .validation_error()
632 .validation_warning()
633 .validation_info()
634 .validation_success()
635 .validation_global()
636 .validation_local()
637 .validation_component()
638 .validation_page()
639 .validation_strict()
640 .validation_loose()
641 .validation_custom_mode()
642 .validation_disabled()
643 .validation_valid()
644 .validation_invalid("message")
645 .validation_warning_result("message")
646 .validation_info_result("message");
647
648 let result = classes.build();
649 assert!(result.classes.contains("validation-required"));
650 assert!(result.classes.contains("validation-pattern-test"));
651 assert!(result.classes.contains("validation-length-1-10"));
652 assert!(result.classes.contains("validation-range-0-100"));
653 assert!(result.classes.contains("validation-error"));
654 assert!(result.classes.contains("validation-warning"));
655 assert!(result.classes.contains("validation-info"));
656 assert!(result.classes.contains("validation-success"));
657 assert!(result.classes.contains("validation-global"));
658 assert!(result.classes.contains("validation-local"));
659 assert!(result.classes.contains("validation-component"));
660 assert!(result.classes.contains("validation-page"));
661 assert!(result.classes.contains("validation-strict"));
662 assert!(result.classes.contains("validation-loose"));
663 assert!(result.classes.contains("validation-custom"));
664 assert!(result.classes.contains("validation-disabled"));
665 assert!(result.classes.contains("validation-valid"));
666 assert!(result.classes.contains("validation-invalid"));
667 assert!(result.classes.contains("validation-warning"));
668 assert!(result.classes.contains("validation-info"));
669 }
670
671 #[test]
672 fn test_enhanced_validation_serialization() {
673 let validation_rule = ValidationRule::Required;
674 let serialized = serde_json::to_string(&validation_rule).unwrap();
675 let deserialized: ValidationRule = serde_json::from_str(&serialized).unwrap();
676 assert_eq!(validation_rule, deserialized);
677
678 let validation_severity = ValidationSeverity::Error;
679 let serialized = serde_json::to_string(&validation_severity).unwrap();
680 let deserialized: ValidationSeverity = serde_json::from_str(&serialized).unwrap();
681 assert_eq!(validation_severity, deserialized);
682
683 let validation_scope = ValidationScope::Global;
684 let serialized = serde_json::to_string(&validation_scope).unwrap();
685 let deserialized: ValidationScope = serde_json::from_str(&serialized).unwrap();
686 assert_eq!(validation_scope, deserialized);
687
688 let validation_mode = ValidationMode::Strict;
689 let serialized = serde_json::to_string(&validation_mode).unwrap();
690 let deserialized: ValidationMode = serde_json::from_str(&serialized).unwrap();
691 assert_eq!(validation_mode, deserialized);
692
693 let validation_result = ValidationResult::Valid;
694 let serialized = serde_json::to_string(&validation_result).unwrap();
695 let deserialized: ValidationResult = serde_json::from_str(&serialized).unwrap();
696 assert_eq!(validation_result, deserialized);
697 }
698
699 #[test]
700 fn test_enhanced_validation_comprehensive_usage() {
701 let classes = ClassBuilder::new()
702 .validation_rule(ValidationRule::Required)
703 .validation_severity(ValidationSeverity::Error)
704 .validation_scope(ValidationScope::Global)
705 .validation_mode(ValidationMode::Strict)
706 .validation_result(ValidationResult::Valid)
707 .validation_required()
708 .validation_pattern("test")
709 .validation_length(1, 10)
710 .validation_range(0.0, 100.0)
711 .validation_error()
712 .validation_warning()
713 .validation_info()
714 .validation_success()
715 .validation_global()
716 .validation_local()
717 .validation_component()
718 .validation_page()
719 .validation_strict()
720 .validation_loose()
721 .validation_custom_mode()
722 .validation_disabled()
723 .validation_valid()
724 .validation_invalid("message")
725 .validation_warning_result("message")
726 .validation_info_result("message");
727
728 let result = classes.build();
729 assert!(result.classes.contains("validation-required"));
730 assert!(result.classes.contains("validation-error"));
731 assert!(result.classes.contains("validation-global"));
732 assert!(result.classes.contains("validation-strict"));
733 assert!(result.classes.contains("validation-valid"));
734 assert!(result.classes.contains("validation-pattern-test"));
735 assert!(result.classes.contains("validation-length-1-10"));
736 assert!(result.classes.contains("validation-range-0-100"));
737 assert!(result.classes.contains("validation-warning"));
738 assert!(result.classes.contains("validation-info"));
739 assert!(result.classes.contains("validation-success"));
740 assert!(result.classes.contains("validation-local"));
741 assert!(result.classes.contains("validation-component"));
742 assert!(result.classes.contains("validation-page"));
743 assert!(result.classes.contains("validation-loose"));
744 assert!(result.classes.contains("validation-custom"));
745 assert!(result.classes.contains("validation-disabled"));
746 assert!(result.classes.contains("validation-invalid"));
747 }
748}