add bottomsheet navigation

This commit is contained in:
Jonas Heinrich 2026-03-10 23:31:50 +01:00
parent 3490cd6ed9
commit 5e4560e89e
51 changed files with 65 additions and 1470 deletions

View file

@ -243,7 +243,45 @@ fn build_ui(app: &Application) {
main_hdr.pack_end(&logout_btn);
main_hdr.pack_start(&refresh_btn);
// ── Return sheet (bottom sheet) ───────────────────────────────────────────
// ── Bottom sheet (rent + return) ──────────────────────────────────────────
// — Rent form —
let bike_entry = Entry::builder()
.placeholder_text("Bike number")
.input_purpose(gtk::InputPurpose::Digits)
.build();
let rent_err = Label::builder()
.css_classes(["error"])
.wrap(true)
.visible(false)
.build();
let rent_submit = Button::builder()
.label("Rent")
.css_classes(["suggested-action", "pill"])
.build();
let rent_spinner = Spinner::new();
let rent_sheet = Box::builder()
.orientation(Orientation::Vertical)
.spacing(16)
.build();
let rent_sheet_title = Label::builder()
.css_classes(["title-4"])
.label("Rent Bike")
.xalign(0.0)
.build();
let rent_form = Box::builder()
.orientation(Orientation::Vertical)
.spacing(12)
.build();
rent_form.append(&bike_entry);
rent_form.append(&rent_err);
rent_form.append(&rent_submit);
rent_form.append(&rent_spinner);
rent_sheet.append(&rent_sheet_title);
rent_sheet.append(&rent_form);
// — Return form —
let station_entry = Entry::builder()
.placeholder_text("Station number")
.input_purpose(gtk::InputPurpose::Digits)
@ -278,21 +316,31 @@ fn build_ui(app: &Application) {
ret_inner.add_named(&manual_form, Some("manual"));
ret_inner.add_named(&electric_msg, Some("electric"));
let sheet_title = Label::builder()
let ret_sheet = Box::builder()
.orientation(Orientation::Vertical)
.spacing(16)
.build();
let ret_sheet_title = Label::builder()
.css_classes(["title-4"])
.label("Return Bike")
.xalign(0.0)
.build();
ret_sheet.append(&ret_sheet_title);
ret_sheet.append(&ret_inner);
// — Shared sheet stack —
let sheet_stack = Stack::new();
sheet_stack.add_named(&rent_sheet, Some("rent"));
sheet_stack.add_named(&ret_sheet, Some("return"));
let sheet_box = Box::builder()
.orientation(Orientation::Vertical)
.spacing(16)
.margin_top(8)
.margin_bottom(24)
.margin_start(16)
.margin_end(16)
.build();
sheet_box.append(&sheet_title);
sheet_box.append(&ret_inner);
sheet_box.append(&sheet_stack);
let bottom_sheet = BottomSheet::builder()
.show_drag_handle(true)
@ -313,44 +361,6 @@ fn build_ui(app: &Application) {
.child(&main_body)
.build();
// ── Rent page ─────────────────────────────────────────────────────────────
let bike_entry = Entry::builder()
.placeholder_text("Bike number")
.input_purpose(gtk::InputPurpose::Digits)
.build();
let rent_err = Label::builder()
.css_classes(["error"])
.wrap(true)
.visible(false)
.build();
let rent_submit = Button::builder()
.label("Rent")
.css_classes(["suggested-action", "pill"])
.build();
let rent_spinner = Spinner::new();
let rent_form = Box::builder()
.orientation(Orientation::Vertical)
.spacing(12)
.margin_top(24).margin_bottom(24).margin_start(12).margin_end(12)
.build();
rent_form.append(&bike_entry);
rent_form.append(&rent_err);
rent_form.append(&rent_submit);
rent_form.append(&rent_spinner);
let rent_clamp = Clamp::builder().maximum_size(400).build();
rent_clamp.set_child(Some(&rent_form));
let rent_body = Box::builder().orientation(Orientation::Vertical).build();
rent_body.append(&HeaderBar::new());
rent_body.append(&rent_clamp);
let rent_page = NavigationPage::builder()
.title("Rent Bike")
.child(&rent_body)
.build();
// ── Navigation view ───────────────────────────────────────────────────────
let nav = NavigationView::new();
nav.push(&main_page);
@ -452,14 +462,17 @@ fn build_ui(app: &Application) {
});
}
// ── Open rent page ────────────────────────────────────────────────────────
// ── Open rent sheet ───────────────────────────────────────────────────────
{
let nav = nav.clone();
let rent_page = rent_page.clone();
let bottom_sheet = bottom_sheet.clone();
let sheet_stack = sheet_stack.clone();
let bike_entry = bike_entry.clone();
let rent_err = rent_err.clone();
rent_btn.connect_clicked(move |_| {
bike_entry.set_text("");
nav.push(&rent_page);
rent_err.set_visible(false);
sheet_stack.set_visible_child_name("rent");
bottom_sheet.set_open(true);
});
}
@ -470,7 +483,7 @@ fn build_ui(app: &Application) {
let err = rent_err.clone();
let spinner = rent_spinner.clone();
let btn = rent_submit.clone();
let nav = nav.clone();
let bottom_sheet = bottom_sheet.clone();
let bikes = bikes.clone();
let bikes_list = bikes_list.clone();
let list_stack = list_stack.clone();
@ -489,7 +502,7 @@ fn build_ui(app: &Application) {
let spinner = spinner.clone();
let btn = btn.clone();
let err = err.clone();
let nav = nav.clone();
let bottom_sheet = bottom_sheet.clone();
let bikes = bikes.clone();
let bikes_list = bikes_list.clone();
let list_stack = list_stack.clone();
@ -505,7 +518,7 @@ fn build_ui(app: &Application) {
err.set_label(&e);
err.set_visible(true);
} else {
nav.pop();
bottom_sheet.set_open(false);
load_rentals(key_reload, bikes, bikes_list, list_stack).await;
}
});
@ -516,6 +529,7 @@ fn build_ui(app: &Application) {
// ── Click rental row → open return bottom sheet ───────────────────────────
{
let bottom_sheet = bottom_sheet.clone();
let sheet_stack = sheet_stack.clone();
let bikes = bikes.clone();
let return_bike = return_bike.clone();
let ret_inner = ret_inner.clone();
@ -529,6 +543,7 @@ fn build_ui(app: &Application) {
ret_err.set_visible(false);
ret_inner.set_visible_child_name(if bike.electric_lock { "electric" } else { "manual" });
*return_bike.borrow_mut() = Some(bike);
sheet_stack.set_visible_child_name("return");
bottom_sheet.set_open(true);
}
});