Skip to main content

max / makenotwork

5.8 KB · 152 lines History Blame Raw
1 //! promo-screen key-input handler (split out of tui/input.rs).
2
3 use super::{
4 App, AppEvent, ConfirmAction, DataPayload, KeyCode, KeyEvent, MnwApiClient, PromoCreateStep,
5 Screen, load_promo_codes, mpsc,
6 };
7
8 pub(crate) async fn handle_promo_input(
9 key: KeyEvent,
10 app: &mut App,
11 screen: &mut Screen,
12 api: &MnwApiClient,
13 tx: &mpsc::Sender<AppEvent>,
14 ) {
15 // Cancel pending confirmation on any key other than the confirmation key
16 if app.confirm_action.is_some() && !matches!(key.code, KeyCode::Char('d' | 'D')) {
17 app.confirm_action = None;
18 app.promo_status = None;
19 }
20
21 // Creating mode
22 if let Some(step) = app.promo_editing_step {
23 match key.code {
24 KeyCode::Esc => {
25 app.promo_editing_step = None;
26 app.promo_create_code.clear();
27 app.promo_create_discount.clear();
28 app.edit_buffer.clear();
29 app.promo_status = None;
30 }
31 KeyCode::Enter => match step {
32 PromoCreateStep::Code => {
33 if !app.edit_buffer.is_empty() {
34 app.promo_create_code = app.edit_buffer.clone();
35 app.edit_buffer.clear();
36 app.promo_editing_step = Some(PromoCreateStep::Discount);
37 app.promo_status = Some("Discount % (e.g. 25): _".to_string());
38 }
39 }
40 PromoCreateStep::Discount => {
41 let code = app.promo_create_code.clone();
42 let discount: i32 = app.edit_buffer.parse().unwrap_or(0);
43
44 let api = api.clone();
45 let user_id = app.user.user_id.clone();
46 let tx = tx.clone();
47 app.promo_status = Some("Creating...".to_string());
48
49 tokio::spawn(async move {
50 match api
51 .create_promo_code(&user_id, &code, "percentage", discount, None, None)
52 .await
53 {
54 Ok(_) => {
55 load_promo_codes(&api, &user_id, &tx).await;
56 }
57 Err(e) => {
58 let _ = tx
59 .send(AppEvent::DataLoaded(DataPayload::GenericError {
60 error: e.to_string(),
61 }))
62 .await;
63 }
64 }
65 });
66
67 app.promo_editing_step = None;
68 app.promo_create_code.clear();
69 app.promo_create_discount.clear();
70 app.edit_buffer.clear();
71 }
72 },
73 KeyCode::Backspace => {
74 app.edit_buffer.pop();
75 }
76 KeyCode::Char(c) => {
77 app.edit_buffer.push(c);
78 }
79 _ => {}
80 }
81 return;
82 }
83
84 // Normal mode
85 match key.code {
86 KeyCode::Char('j') | KeyCode::Down => app.move_down(screen),
87 KeyCode::Char('k') | KeyCode::Up => app.move_up(screen),
88 KeyCode::Esc => {
89 *screen = Screen::Home;
90 app.promo_codes.clear();
91 app.promo_status = None;
92 app.selected_index = 0;
93 }
94 KeyCode::Char('n' | 'N') => {
95 app.promo_editing_step = Some(PromoCreateStep::Code);
96 app.edit_buffer.clear();
97 app.promo_status = Some("Code: _".to_string());
98 }
99 KeyCode::Char('d' | 'D') if !app.promo_codes.is_empty() => {
100 let idx = app.selected_index;
101 if matches!(app.confirm_action, Some(ConfirmAction::DeletePromoCode { code_idx }) if code_idx == idx)
102 {
103 // Confirmed — execute delete
104 app.confirm_action = None;
105 let code_id = app.promo_codes[idx].id.clone();
106 let code_value = app.promo_codes[idx].code.clone();
107 let user_id = app.user.user_id.clone();
108 tracing::info!(
109 user_id = %user_id,
110 code_id = %code_id,
111 code = %code_value,
112 "delete promo code confirmed"
113 );
114 let api = api.clone();
115 let tx = tx.clone();
116 app.promo_status = Some("Deleting...".to_string());
117 tokio::spawn(async move {
118 match api.delete_promo_code(&user_id, &code_id).await {
119 Ok(()) => {
120 load_promo_codes(&api, &user_id, &tx).await;
121 }
122 Err(e) => {
123 let _ = tx
124 .send(AppEvent::DataLoaded(DataPayload::GenericError {
125 error: e.to_string(),
126 }))
127 .await;
128 }
129 }
130 });
131 } else {
132 // First press — ask for confirmation
133 app.confirm_action = Some(ConfirmAction::DeletePromoCode { code_idx: idx });
134 app.promo_status = Some(format!(
135 "Delete '{}'? Press d again to confirm",
136 app.promo_codes[idx].code
137 ));
138 }
139 }
140 KeyCode::Char('r' | 'R') => {
141 app.loading = true;
142 let api = api.clone();
143 let user_id = app.user.user_id.clone();
144 let tx = tx.clone();
145 tokio::spawn(async move {
146 load_promo_codes(&api, &user_id, &tx).await;
147 });
148 }
149 _ => {}
150 }
151 }
152