gm_lib/tui/app/pages/
address_book_create.rs1use crate::{
2 disk::{AddressBook, AddressBookEntry, DiskInterface},
3 tui::{
4 app::{
5 widgets::form::{Form, FormItemIndex, FormWidget},
6 SharedState,
7 },
8 events::Event,
9 traits::{Component, HandleResult},
10 },
11};
12use std::sync::{atomic::AtomicBool, mpsc, Arc};
13use strum::EnumIter;
14
15#[derive(EnumIter, PartialEq)]
16pub enum FormItem {
17 Heading,
18 Name,
19 Address,
20 SaveButton,
21 ErrorText,
22}
23impl FormItemIndex for FormItem {
24 fn index(self) -> usize {
25 self as usize
26 }
27}
28impl TryFrom<FormItem> for FormWidget {
29 type Error = crate::Error;
30 fn try_from(value: FormItem) -> crate::Result<Self> {
31 let widget = match value {
32 FormItem::Heading => FormWidget::Heading("Edit AddressBook entry"),
33 FormItem::Name => FormWidget::InputBox {
34 label: "name",
35 text: String::new(),
36 empty_text: None,
37 currency: None,
38 },
39 FormItem::Address => FormWidget::InputBox {
40 label: "address",
41 text: String::new(),
42 empty_text: None,
43 currency: None,
44 },
45 FormItem::SaveButton => FormWidget::Button { label: "Save" },
46 FormItem::ErrorText => FormWidget::ErrorText(String::new()),
47 };
48 Ok(widget)
49 }
50}
51
52pub struct AddressBookCreatePage {
53 pub form: Form<FormItem>,
54}
55
56impl AddressBookCreatePage {
57 pub fn new(name: String, address: String) -> crate::Result<Self> {
58 Ok(Self {
59 form: Form::init(|form| {
60 *form.get_text_mut(FormItem::Name) = name;
61 *form.get_text_mut(FormItem::Address) = address;
62 Ok(())
63 })?,
64 })
65 }
66}
67
68impl Component for AddressBookCreatePage {
69 fn handle_event(
70 &mut self,
71 event: &Event,
72 _area: ratatui::prelude::Rect,
73 _transmitter: &mpsc::Sender<Event>,
74 _shutdown_signal: &Arc<AtomicBool>,
75 _shared_state: &SharedState,
76 ) -> crate::Result<HandleResult> {
77 let mut handle_result = HandleResult::default();
78
79 self.form.handle_event(
80 event,
81 |_, _| Ok(()),
82 |label, form| {
83 if label == FormItem::SaveButton {
84 let name = form.get_text(FormItem::Name);
85 if name.is_empty() {
86 let error = form.get_text_mut(FormItem::ErrorText);
87 *error = "Please enter name, you cannot leave it empty".to_string();
88 } else {
89 let mut address_book = AddressBook::load()?;
90
91 let address = form.get_text(FormItem::Address);
92
93 let result =
94 address
95 .parse()
96 .map_err(crate::Error::from)
97 .and_then(|address| {
98 address_book.add(AddressBookEntry {
99 name: name.clone(),
100 address,
101 })
102 });
103 if let Err(e) = result {
104 let error = form.get_text_mut(FormItem::ErrorText);
105 *error = format!("{e:?}");
106 } else {
107 handle_result.page_pops = 1;
108 handle_result.reload = true;
109 }
110 }
111 }
112 Ok(())
113 },
114 )?;
115
116 Ok(handle_result)
117 }
118
119 fn render_component(
120 &self,
121 area: ratatui::prelude::Rect,
122 buf: &mut ratatui::prelude::Buffer,
123 ss: &SharedState,
124 ) -> ratatui::prelude::Rect
125 where
126 Self: Sized,
127 {
128 self.form.render(area, buf, &ss.theme);
129
130 area
131 }
132}