refactor(web): add has_ai_extract flag to all page templates

Propagate has_ai_extract boolean through every template struct and
route handler so nav.html can conditionally show the scan link.
This commit is contained in:
Jon Seager 2026-02-03 19:14:47 +00:00
parent b668d368e7
commit 023ad1ac31
No known key found for this signature in database
10 changed files with 29 additions and 0 deletions

View file

@ -20,6 +20,7 @@ const SESSION_COOKIE_NAME: &str = "brewlog_session";
struct LoginTemplate { struct LoginTemplate {
nav_active: &'static str, nav_active: &'static str,
is_authenticated: bool, is_authenticated: bool,
has_ai_extract: bool,
error: Option<String>, error: Option<String>,
} }
@ -42,6 +43,7 @@ pub(crate) async fn login_page(
let template = LoginTemplate { let template = LoginTemplate {
nav_active: "login", nav_active: "login",
is_authenticated: false, is_authenticated: false,
has_ai_extract: false,
error: None, error: None,
}; };
@ -130,6 +132,7 @@ fn show_login_error(message: &str) -> Result<Response, StatusCode> {
let template = LoginTemplate { let template = LoginTemplate {
nav_active: "login", nav_active: "login",
is_authenticated: false, is_authenticated: false,
has_ai_extract: false,
error: Some(message.to_string()), error: Some(message.to_string()),
}; };

View file

@ -99,6 +99,7 @@ pub(crate) async fn bags_page(
let template = BagsTemplate { let template = BagsTemplate {
nav_active: "bags", nav_active: "bags",
is_authenticated, is_authenticated,
has_ai_extract: state.has_ai_extract(),
open_bags, open_bags,
bags, bags,
roaster_options, roaster_options,

View file

@ -186,6 +186,7 @@ pub(crate) async fn brews_page(
let template = BrewsTemplate { let template = BrewsTemplate {
nav_active: "brews", nav_active: "brews",
is_authenticated, is_authenticated,
has_ai_extract: state.has_ai_extract(),
brews, brews,
bag_options, bag_options,
grinder_options, grinder_options,

View file

@ -69,6 +69,7 @@ pub(crate) async fn cafes_page(
let template = CafesTemplate { let template = CafesTemplate {
nav_active: "cafes", nav_active: "cafes",
is_authenticated, is_authenticated,
has_ai_extract: state.has_ai_extract(),
cafes, cafes,
navigator, navigator,
}; };
@ -94,6 +95,7 @@ pub(crate) async fn cafe_page(
let template = CafeDetailTemplate { let template = CafeDetailTemplate {
nav_active: "cafes", nav_active: "cafes",
is_authenticated, is_authenticated,
has_ai_extract: state.has_ai_extract(),
cafe: cafe_view, cafe: cafe_view,
}; };

View file

@ -74,6 +74,7 @@ pub(crate) async fn cups_page(
let template = CupsTemplate { let template = CupsTemplate {
nav_active: "cups", nav_active: "cups",
is_authenticated, is_authenticated,
has_ai_extract: state.has_ai_extract(),
cups, cups,
roast_options, roast_options,
cafe_options, cafe_options,

View file

@ -71,6 +71,7 @@ pub(crate) async fn gear_page(
let template = GearTemplate { let template = GearTemplate {
nav_active: "gear", nav_active: "gear",
is_authenticated, is_authenticated,
has_ai_extract: state.has_ai_extract(),
gear, gear,
navigator, navigator,
}; };

View file

@ -101,6 +101,7 @@ pub(crate) async fn roaster_page(
let template = RoasterDetailTemplate { let template = RoasterDetailTemplate {
nav_active: "roasters", nav_active: "roasters",
is_authenticated, is_authenticated,
has_ai_extract: state.has_ai_extract(),
roaster: roaster_view, roaster: roaster_view,
roasts: roasts.into_iter().map(RoastView::from_list_item).collect(), roasts: roasts.into_iter().map(RoastView::from_list_item).collect(),
}; };

View file

@ -121,6 +121,7 @@ pub(crate) async fn roast_page(
let template = RoastDetailTemplate { let template = RoastDetailTemplate {
nav_active: "roasts", nav_active: "roasts",
is_authenticated, is_authenticated,
has_ai_extract: state.has_ai_extract(),
roast: RoastView::from_domain(roast, &roaster.name, &roaster.slug), roast: RoastView::from_domain(roast, &roaster.name, &roaster.slug),
bags: bag_views, bags: bag_views,
}; };

View file

@ -93,6 +93,7 @@ pub(crate) async fn timeline_page(
let template = TimelineTemplate { let template = TimelineTemplate {
nav_active: "timeline", nav_active: "timeline",
is_authenticated, is_authenticated,
has_ai_extract: state.has_ai_extract(),
events: data.events, events: data.events,
navigator: data.navigator, navigator: data.navigator,
months: data.months, months: data.months,

View file

@ -37,6 +37,7 @@ pub struct RoasterListTemplate {
pub struct RoasterDetailTemplate { pub struct RoasterDetailTemplate {
pub nav_active: &'static str, pub nav_active: &'static str,
pub is_authenticated: bool, pub is_authenticated: bool,
pub has_ai_extract: bool,
pub roaster: RoasterView, pub roaster: RoasterView,
pub roasts: Vec<RoastView>, pub roasts: Vec<RoastView>,
} }
@ -57,6 +58,7 @@ pub struct RoastsTemplate {
pub struct RoastDetailTemplate { pub struct RoastDetailTemplate {
pub nav_active: &'static str, pub nav_active: &'static str,
pub is_authenticated: bool, pub is_authenticated: bool,
pub has_ai_extract: bool,
pub roast: RoastView, pub roast: RoastView,
pub bags: Vec<BagView>, pub bags: Vec<BagView>,
} }
@ -74,6 +76,7 @@ pub struct RoastListTemplate {
pub struct TimelineTemplate { pub struct TimelineTemplate {
pub nav_active: &'static str, pub nav_active: &'static str,
pub is_authenticated: bool, pub is_authenticated: bool,
pub has_ai_extract: bool,
pub events: Paginated<TimelineEventView>, pub events: Paginated<TimelineEventView>,
pub navigator: ListNavigator<TimelineSortKey>, pub navigator: ListNavigator<TimelineSortKey>,
pub months: Vec<TimelineMonthView>, pub months: Vec<TimelineMonthView>,
@ -93,6 +96,7 @@ pub struct TimelineChunkTemplate {
pub struct BagsTemplate { pub struct BagsTemplate {
pub nav_active: &'static str, pub nav_active: &'static str,
pub is_authenticated: bool, pub is_authenticated: bool,
pub has_ai_extract: bool,
pub open_bags: Vec<BagView>, pub open_bags: Vec<BagView>,
pub bags: Paginated<BagView>, pub bags: Paginated<BagView>,
pub roaster_options: Vec<RoasterOptionView>, pub roaster_options: Vec<RoasterOptionView>,
@ -113,6 +117,7 @@ pub struct BagListTemplate {
pub struct GearTemplate { pub struct GearTemplate {
pub nav_active: &'static str, pub nav_active: &'static str,
pub is_authenticated: bool, pub is_authenticated: bool,
pub has_ai_extract: bool,
pub gear: Paginated<GearView>, pub gear: Paginated<GearView>,
pub navigator: ListNavigator<GearSortKey>, pub navigator: ListNavigator<GearSortKey>,
} }
@ -136,6 +141,7 @@ pub struct RoastOptionsTemplate {
pub struct BrewsTemplate { pub struct BrewsTemplate {
pub nav_active: &'static str, pub nav_active: &'static str,
pub is_authenticated: bool, pub is_authenticated: bool,
pub has_ai_extract: bool,
pub brews: Paginated<BrewView>, pub brews: Paginated<BrewView>,
pub bag_options: Vec<BagOptionView>, pub bag_options: Vec<BagOptionView>,
pub grinder_options: Vec<GearOptionView>, pub grinder_options: Vec<GearOptionView>,
@ -158,6 +164,7 @@ pub struct BrewListTemplate {
pub struct CafesTemplate { pub struct CafesTemplate {
pub nav_active: &'static str, pub nav_active: &'static str,
pub is_authenticated: bool, pub is_authenticated: bool,
pub has_ai_extract: bool,
pub cafes: Paginated<CafeView>, pub cafes: Paginated<CafeView>,
pub navigator: ListNavigator<CafeSortKey>, pub navigator: ListNavigator<CafeSortKey>,
} }
@ -175,6 +182,7 @@ pub struct CafeListTemplate {
pub struct CafeDetailTemplate { pub struct CafeDetailTemplate {
pub nav_active: &'static str, pub nav_active: &'static str,
pub is_authenticated: bool, pub is_authenticated: bool,
pub has_ai_extract: bool,
pub cafe: CafeView, pub cafe: CafeView,
} }
@ -183,6 +191,7 @@ pub struct CafeDetailTemplate {
pub struct CupsTemplate { pub struct CupsTemplate {
pub nav_active: &'static str, pub nav_active: &'static str,
pub is_authenticated: bool, pub is_authenticated: bool,
pub has_ai_extract: bool,
pub cups: Paginated<CupView>, pub cups: Paginated<CupView>,
pub roast_options: Vec<RoastOptionView>, pub roast_options: Vec<RoastOptionView>,
pub cafe_options: Vec<CafeOptionView>, pub cafe_options: Vec<CafeOptionView>,
@ -197,6 +206,14 @@ pub struct CupListTemplate {
pub navigator: ListNavigator<CupSortKey>, pub navigator: ListNavigator<CupSortKey>,
} }
#[derive(Template)]
#[template(path = "scan.html")]
pub struct ScanTemplate {
pub nav_active: &'static str,
pub is_authenticated: bool,
pub has_ai_extract: bool,
}
pub fn render_template<T: Template>(template: T) -> Result<String, askama::Error> { pub fn render_template<T: Template>(template: T) -> Result<String, askama::Error> {
template.render() template.render()
} }