Skip to main content

gm_lib/tui/app/pages/
address_book_create.rs

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