cloudflare_dns/ui/components/
create_form.rs1use crate::ui::colors::*;
2use crate::ui::components::app_layout::{AppLayoutConfig, render_app_layout};
3use crate::ui::components::form_field::FormField;
4use iocraft::prelude::*;
5
6#[derive(Props)]
7pub struct CreateFormProps {
8 pub form_type: Option<State<String>>,
9 pub form_name: Option<State<String>>,
10 pub form_content: Option<State<String>>,
11 pub form_ttl: Option<State<String>>,
12 pub form_proxied: Option<State<String>>,
13 pub form_focus: i32,
14 pub status: String,
15 pub title: String,
16 pub hint: String,
17 pub submit_label: String,
18 pub zone_name: String,
19 pub domain_suffix: String,
20 pub is_editing: bool,
21}
22
23impl Default for CreateFormProps {
24 fn default() -> Self {
25 Self {
26 form_type: None,
27 form_name: None,
28 form_content: None,
29 form_ttl: None,
30 form_proxied: None,
31 form_focus: 1,
32 status: String::new(),
33 title: " Create DNS Record ".to_string(),
34 hint: "↑↓: navigate | esc: cancel".to_string(),
35 submit_label: "Submit".to_string(),
36 zone_name: String::new(),
37 domain_suffix: String::new(),
38 is_editing: false,
39 }
40 }
41}
42
43#[component]
44pub fn CreateForm(props: &CreateFormProps, mut hooks: Hooks) -> impl Into<AnyElement<'static>> {
45 let focus = props.form_focus;
46 let title = format!(" {} — {} ", props.title.trim(), props.zone_name);
47 let subtitle = props.title.trim();
48 let hint = props.hint.clone();
49 let form_type = props.form_type;
50 let form_name = props.form_name;
51 let form_content = props.form_content;
52 let form_ttl = props.form_ttl;
53 let form_proxied = props.form_proxied;
54 let submit_label = props.submit_label.clone();
55 let accent = if props.is_editing { SAPPHIRE } else { GREEN };
56
57 let content = element! {
58 View(flex_grow: 1.0, align_items: AlignItems::Center, justify_content: JustifyContent::Center) {
59 View(
60 border_style: BorderStyle::Round,
61 border_color: accent,
62 background_color: MANTEL,
63 padding_left: 3,
64 padding_right: 3,
65 padding_top: 2,
66 padding_bottom: 2,
67 width: 80,
68 ) {
69 View(flex_direction: FlexDirection::Column) {
70 View(margin_bottom: 1) {
71 Text(content: subtitle, color: accent, weight: Weight::Bold)
72 }
73 View(margin_bottom: 1) {
74 Text(content: hint, color: OVERLAY1)
75 }
76 FormField(label: "Type", value: form_type, has_focus: focus == 0, is_editable: false)
77 FormField(label: "Name", value: form_name, has_focus: focus == 1, suffix: props.domain_suffix.clone(), is_editable: true)
78 FormField(label: "IP Address", value: form_content, has_focus: focus == 2, is_editable: true)
79 FormField(label: "TTL", value: form_ttl, has_focus: focus == 3, is_editable: true)
80 FormField(label: "Proxied", value: form_proxied, has_focus: focus == 4, is_editable: false)
81 View(
82 margin_top: 1,
83 border_style: if focus == 5 { BorderStyle::Round } else { BorderStyle::None },
84 border_color: accent,
85 padding: if focus == 5 { 0 } else { 1 },
86 align_items: AlignItems::Center,
87 justify_content: JustifyContent::Center,
88 ) {
89 Text(content: submit_label, color: TEXT, weight: Weight::Bold, align: TextAlign::Center)
90 }
91 }
92 }
93 }
94 }.into_any();
95
96 render_app_layout(
97 AppLayoutConfig {
98 title,
99 title_bg: accent,
100 menu: " ↑↓: navigate | space: toggle [Type] or [Proxied] | enter: submit | esc: cancel | q: quit"
101 .to_string(),
102 menu_bg: SURFACE1,
103 status: props.status.clone(),
104 ..Default::default()
105 },
106 content,
107 &mut hooks,
108 )
109}