Skip to main content

gm_lib/tui/app/pages/
address_book_display.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 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}