gm_lib/tui/app/pages/
address_book_display.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 AddressBookDisplayPage {
53 pub id: usize,
54 pub form: Form<FormItem>,
55}
56
57impl AddressBookDisplayPage {
58 pub fn new(id: usize, name: String, address: String) -> crate::Result<Self> {
59 Ok(Self {
60 id,
61 form: Form::init(|form| {
62 *form.get_text_mut(FormItem::Name) = name;
63 *form.get_text_mut(FormItem::Address) = address;
64 Ok(())
65 })?,
66 })
67 }
68}
69
70impl Component for AddressBookDisplayPage {
71 fn handle_event(
72 &mut self,
73 event: &Event,
74 _area: ratatui::prelude::Rect,
75 _transmitter: &mpsc::Sender<Event>,
76 _shutdown_signal: &Arc<AtomicBool>,
77 _shared_state: &SharedState,
78 ) -> crate::Result<HandleResult> {
79 let mut handle_result = HandleResult::default();
80
81 self.form.handle_event(
82 event,
83 |_, _| Ok(()),
84 |label, form| {
85 if label == FormItem::SaveButton {
86 let name = form.get_text(FormItem::Name);
87 if name.is_empty() {
88 let error = form.get_text_mut(FormItem::ErrorText);
89 *error = "Please enter name, you cannot leave it empty".to_string();
90 } else {
91 let mut address_book = AddressBook::load()?;
92
93 let address = form.get_text(FormItem::Address);
94 let result = address
95 .parse()
96 .map_err(crate::Error::from)
97 .map(|address| {
98 address_book.update(
99 self.id,
100 AddressBookEntry {
101 name: name.clone(),
102 address,
103 },
104 )
105 })
106 .and_then(|inner| inner);
107 if let Err(e) = result {
108 let error = form.get_text_mut(FormItem::ErrorText);
109 *error = format!("{e:?}");
110 } else {
111 handle_result.page_pops = 1;
112 handle_result.reload = true;
113 }
114 }
115 }
116 Ok(())
117 },
118 )?;
119
120 Ok(handle_result)
121 }
122
123 fn render_component(
124 &self,
125 area: ratatui::prelude::Rect,
126 buf: &mut ratatui::prelude::Buffer,
127 ss: &SharedState,
128 ) -> ratatui::prelude::Rect
129 where
130 Self: Sized,
131 {
132 self.form.render(area, buf, &ss.theme);
133 area
134 }
135}