Skip to main content

cloudflare_dns/ui/components/
create_form.rs

1use 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}