commit 0d33c910e0337020ddf14824d08cd959b77e951c
parent 1b659a51242b36a7d95c2014b5d07587388b1802
Author: triesap <tyson@radroots.org>
Date: Sun, 7 Jun 2026 13:11:27 -0700
ui: bootstrap account farm details step
Diffstat:
5 files changed, 748 insertions(+), 1 deletion(-)
diff --git a/crates/desktop/src/source_guards.rs b/crates/desktop/src/source_guards.rs
@@ -43,6 +43,9 @@ const ALLOWED_WINDOW_LITERALS: &[&str] = &[
"account-more",
"account-profile-change-photo",
"account-profile-remove-photo",
+ "account-farm-continue-location",
+ "account-farm-save-draft",
+ "account-farm-view-profile",
"account-scroll",
"account-tabs",
"account_1",
@@ -384,6 +387,58 @@ const REQUIRED_WINDOW_COPY_KEYS: &[&str] = &[
"AppTextKey::AccountProfileLanguageValue",
"AppTextKey::AccountProfileLanguageFrenchValue",
"AppTextKey::AccountProfileLanguageSpanishValue",
+ "AppTextKey::AccountFarmDetailsFarmProfileTitle",
+ "AppTextKey::AccountFarmDetailsFarmProfileIntro",
+ "AppTextKey::AccountFarmDetailsFarmNameLabel",
+ "AppTextKey::AccountFarmDetailsPublicFarmNameLabel",
+ "AppTextKey::AccountFarmDetailsShortDescriptionLabel",
+ "AppTextKey::AccountFarmDetailsFarmTypeLabel",
+ "AppTextKey::AccountFarmDetailsContactEmailLabel",
+ "AppTextKey::AccountFarmDetailsPublicPhoneLabel",
+ "AppTextKey::AccountFarmDetailsWebsiteLabel",
+ "AppTextKey::AccountFarmDetailsEstablishedYearLabel",
+ "AppTextKey::AccountFarmDetailsAboutFarmLabel",
+ "AppTextKey::AccountFarmDetailsFarmNameValue",
+ "AppTextKey::AccountFarmDetailsPublicFarmNameValue",
+ "AppTextKey::AccountFarmDetailsShortDescriptionValue",
+ "AppTextKey::AccountFarmDetailsContactEmailValue",
+ "AppTextKey::AccountFarmDetailsPublicPhoneValue",
+ "AppTextKey::AccountFarmDetailsWebsiteValue",
+ "AppTextKey::AccountFarmDetailsEstablishedYearValue",
+ "AppTextKey::AccountFarmDetailsAboutFarmValue",
+ "AppTextKey::AccountFarmDetailsFarmLocationValue",
+ "AppTextKey::AccountFarmDetailsRequiredFieldNote",
+ "AppTextKey::AccountFarmDetailsCompletenessTitle",
+ "AppTextKey::AccountFarmDetailsCompletenessPercent",
+ "AppTextKey::AccountFarmDetailsCompletenessCallout",
+ "AppTextKey::AccountFarmDetailsCompletenessBody",
+ "AppTextKey::AccountFarmDetailsStepFarmProfile",
+ "AppTextKey::AccountFarmDetailsStepLocation",
+ "AppTextKey::AccountFarmDetailsStepOperatingDetails",
+ "AppTextKey::AccountFarmDetailsStepPickupFulfillment",
+ "AppTextKey::AccountFarmDetailsStepReviewPublish",
+ "AppTextKey::AccountFarmDetailsStatusInProgress",
+ "AppTextKey::AccountFarmDetailsStatusNotStarted",
+ "AppTextKey::AccountFarmDetailsSummaryTitle",
+ "AppTextKey::AccountFarmDetailsFarmTypeSummaryLabel",
+ "AppTextKey::AccountFarmDetailsEstablishedSummaryLabel",
+ "AppTextKey::AccountFarmDetailsViewFarmProfileAction",
+ "AppTextKey::AccountFarmDetailsSaveDraftAction",
+ "AppTextKey::AccountFarmDetailsContinueLocationAction",
+ "AppTextKey::AccountFarmDetailsFarmTypeVegetableFarm",
+ "AppTextKey::AccountFarmDetailsFarmTypeFruitOrchard",
+ "AppTextKey::AccountFarmDetailsFarmTypeBerryFarm",
+ "AppTextKey::AccountFarmDetailsFarmTypeHerbFarm",
+ "AppTextKey::AccountFarmDetailsFarmTypeFlowerFarm",
+ "AppTextKey::AccountFarmDetailsFarmTypeMushroomFarm",
+ "AppTextKey::AccountFarmDetailsFarmTypeGrainFieldCropFarm",
+ "AppTextKey::AccountFarmDetailsFarmTypeDairyFarm",
+ "AppTextKey::AccountFarmDetailsFarmTypeEggPoultryFarm",
+ "AppTextKey::AccountFarmDetailsFarmTypeLivestockFarm",
+ "AppTextKey::AccountFarmDetailsFarmTypeHoneyApiary",
+ "AppTextKey::AccountFarmDetailsFarmTypeNurseryPlantFarm",
+ "AppTextKey::AccountFarmDetailsFarmTypeMixedFarm",
+ "AppTextKey::AccountFarmDetailsFarmTypeOther",
"AppTextKey::HomeSetupBackAction",
"AppTextKey::HomeSetupBrowseMarketplaceAction",
"AppTextKey::HomeSetupConnectSignerAction",
diff --git a/crates/desktop/src/window.rs b/crates/desktop/src/window.rs
@@ -217,6 +217,7 @@ impl AccountTab {
}
type AccountProfileSelectState = SelectState<SearchableVec<SharedString>>;
+type AccountFarmProfileSelectState = SelectState<SearchableVec<SharedString>>;
#[derive(Clone)]
struct AccountProfileFormState {
@@ -305,6 +306,106 @@ fn account_profile_select_state(
})
}
+#[derive(Clone)]
+struct AccountFarmProfileFormState {
+ farm_name_input: Entity<InputState>,
+ public_farm_name_input: Entity<InputState>,
+ short_description_input: Entity<InputState>,
+ contact_email_input: Entity<InputState>,
+ public_phone_input: Entity<InputState>,
+ website_input: Entity<InputState>,
+ established_year_input: Entity<InputState>,
+ about_farm_input: Entity<InputState>,
+ farm_type_select: Entity<AccountFarmProfileSelectState>,
+}
+
+impl AccountFarmProfileFormState {
+ fn new(window: &mut Window, cx: &mut Context<HomeView>) -> Self {
+ Self {
+ farm_name_input: account_profile_input_state(
+ AppTextKey::AccountFarmDetailsFarmNameValue,
+ window,
+ cx,
+ ),
+ public_farm_name_input: account_profile_input_state(
+ AppTextKey::AccountFarmDetailsPublicFarmNameValue,
+ window,
+ cx,
+ ),
+ short_description_input: account_profile_input_state(
+ AppTextKey::AccountFarmDetailsShortDescriptionValue,
+ window,
+ cx,
+ ),
+ contact_email_input: account_profile_input_state(
+ AppTextKey::AccountFarmDetailsContactEmailValue,
+ window,
+ cx,
+ ),
+ public_phone_input: account_profile_input_state(
+ AppTextKey::AccountFarmDetailsPublicPhoneValue,
+ window,
+ cx,
+ ),
+ website_input: account_profile_input_state(
+ AppTextKey::AccountFarmDetailsWebsiteValue,
+ window,
+ cx,
+ ),
+ established_year_input: account_profile_input_state(
+ AppTextKey::AccountFarmDetailsEstablishedYearValue,
+ window,
+ cx,
+ ),
+ about_farm_input: account_profile_input_state(
+ AppTextKey::AccountFarmDetailsAboutFarmValue,
+ window,
+ cx,
+ ),
+ farm_type_select: account_farm_profile_select_state(
+ &[
+ AppTextKey::AccountFarmDetailsFarmTypeVegetableFarm,
+ AppTextKey::AccountFarmDetailsFarmTypeFruitOrchard,
+ AppTextKey::AccountFarmDetailsFarmTypeBerryFarm,
+ AppTextKey::AccountFarmDetailsFarmTypeHerbFarm,
+ AppTextKey::AccountFarmDetailsFarmTypeFlowerFarm,
+ AppTextKey::AccountFarmDetailsFarmTypeMushroomFarm,
+ AppTextKey::AccountFarmDetailsFarmTypeGrainFieldCropFarm,
+ AppTextKey::AccountFarmDetailsFarmTypeDairyFarm,
+ AppTextKey::AccountFarmDetailsFarmTypeEggPoultryFarm,
+ AppTextKey::AccountFarmDetailsFarmTypeLivestockFarm,
+ AppTextKey::AccountFarmDetailsFarmTypeHoneyApiary,
+ AppTextKey::AccountFarmDetailsFarmTypeNurseryPlantFarm,
+ AppTextKey::AccountFarmDetailsFarmTypeMixedFarm,
+ AppTextKey::AccountFarmDetailsFarmTypeOther,
+ ],
+ window,
+ cx,
+ ),
+ }
+ }
+}
+
+fn account_farm_profile_select_state(
+ value_keys: &[AppTextKey],
+ window: &mut Window,
+ cx: &mut Context<HomeView>,
+) -> Entity<AccountFarmProfileSelectState> {
+ let values = value_keys
+ .iter()
+ .copied()
+ .map(app_shared_text)
+ .collect::<Vec<_>>();
+ cx.new(|cx| {
+ SelectState::new(
+ SearchableVec::new(values),
+ Some(IndexPath::default().row(0)),
+ window,
+ cx,
+ )
+ })
+}
+
fn buyer_order_detail_focus_after_open(
runtime_changed: bool,
runtime: &DesktopAppRuntimeSummary,
@@ -433,6 +534,7 @@ pub struct HomeView {
focused_view: Option<HomeFocusedView>,
selected_account_tab: AccountTab,
account_profile_form: Option<AccountProfileFormState>,
+ account_farm_profile_form: Option<AccountFarmProfileFormState>,
relay_client: Option<RadrootsNostrClient>,
buyer_workspace_notice: Option<String>,
}
@@ -554,6 +656,7 @@ impl HomeView {
focused_view: None,
selected_account_tab: AccountTab::default(),
account_profile_form: None,
+ account_farm_profile_form: None,
relay_client: None,
buyer_workspace_notice: None,
}
@@ -5111,7 +5214,11 @@ impl HomeView {
let form = self.account_profile_form(window, cx).clone();
account_profile_panel(&form, cx).into_any_element()
}
- AccountTab::FarmDetails | AccountTab::Preferences | AccountTab::Security => {
+ AccountTab::FarmDetails => {
+ let form = self.account_farm_profile_form(window, cx).clone();
+ account_farm_profile_panel(&form, cx).into_any_element()
+ }
+ AccountTab::Preferences | AccountTab::Security => {
account_placeholder_panel(selected_tab.panel_text_key()).into_any_element()
}
};
@@ -5151,6 +5258,21 @@ impl HomeView {
};
form
}
+
+ fn account_farm_profile_form(
+ &mut self,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> &AccountFarmProfileFormState {
+ if self.account_farm_profile_form.is_none() {
+ self.account_farm_profile_form = Some(AccountFarmProfileFormState::new(window, cx));
+ }
+
+ let Some(form) = self.account_farm_profile_form.as_ref() else {
+ unreachable!();
+ };
+ form
+ }
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
@@ -9115,6 +9237,456 @@ fn account_profile_labeled_control(
.child(control)
}
+fn account_farm_profile_panel(
+ form: &AccountFarmProfileFormState,
+ cx: &mut Context<HomeView>,
+) -> impl IntoElement {
+ app_stack_v(APP_UI_THEME.shells.home_stack_gap_px)
+ .w_full()
+ .child(
+ div()
+ .w_full()
+ .flex()
+ .items_start()
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
+ .child(
+ div()
+ .flex_1()
+ .min_w_0()
+ .child(account_farm_profile_main_card(form)),
+ )
+ .child(
+ app_stack_v(APP_UI_THEME.shells.home_stack_gap_px)
+ .w(px(336.0))
+ .min_w(px(300.0))
+ .child(account_farm_profile_completeness_card())
+ .child(account_farm_profile_summary_card(cx)),
+ ),
+ )
+ .child(account_farm_profile_action_row(cx))
+}
+
+fn account_farm_profile_main_card(form: &AccountFarmProfileFormState) -> impl IntoElement {
+ account_farm_profile_card(
+ app_stack_v(APP_UI_THEME.shells.home_stack_gap_px)
+ .w_full()
+ .child(account_farm_profile_title_block(
+ AppTextKey::AccountFarmDetailsFarmProfileTitle,
+ AppTextKey::AccountFarmDetailsFarmProfileIntro,
+ ))
+ .child(account_farm_profile_field_row(
+ account_profile_input_field(
+ AppTextKey::AccountFarmDetailsFarmNameLabel,
+ &form.farm_name_input,
+ ),
+ account_profile_input_field(
+ AppTextKey::AccountFarmDetailsPublicFarmNameLabel,
+ &form.public_farm_name_input,
+ ),
+ ))
+ .child(account_farm_profile_field_row(
+ account_profile_input_field(
+ AppTextKey::AccountFarmDetailsShortDescriptionLabel,
+ &form.short_description_input,
+ ),
+ account_farm_profile_select_field(
+ AppTextKey::AccountFarmDetailsFarmTypeLabel,
+ &form.farm_type_select,
+ ),
+ ))
+ .child(account_farm_profile_field_row(
+ account_profile_input_field(
+ AppTextKey::AccountFarmDetailsContactEmailLabel,
+ &form.contact_email_input,
+ ),
+ account_profile_input_field(
+ AppTextKey::AccountFarmDetailsPublicPhoneLabel,
+ &form.public_phone_input,
+ ),
+ ))
+ .child(account_farm_profile_field_row(
+ account_profile_input_field(
+ AppTextKey::AccountFarmDetailsWebsiteLabel,
+ &form.website_input,
+ ),
+ account_profile_input_field(
+ AppTextKey::AccountFarmDetailsEstablishedYearLabel,
+ &form.established_year_input,
+ ),
+ ))
+ .child(account_farm_profile_text_area_field(
+ AppTextKey::AccountFarmDetailsAboutFarmLabel,
+ &form.about_farm_input,
+ ))
+ .child(
+ div()
+ .w_full()
+ .text_size(px(APP_UI_THEME.foundation.typography.utility_title_text_px))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
+ .child(app_shared_text(
+ AppTextKey::AccountFarmDetailsRequiredFieldNote,
+ )),
+ ),
+ )
+}
+
+fn account_farm_profile_card(content: impl IntoElement) -> impl IntoElement {
+ div()
+ .w_full()
+ .border_1()
+ .border_color(rgb(APP_UI_THEME.foundation.surfaces.divider))
+ .rounded(px(APP_UI_THEME.foundation.radii.large_px))
+ .bg(transparent_black())
+ .child(
+ div()
+ .w_full()
+ .p(px(APP_UI_THEME.shells.home_card_padding_px))
+ .child(content),
+ )
+}
+
+fn account_farm_profile_title_block(
+ title_key: AppTextKey,
+ body_key: AppTextKey,
+) -> impl IntoElement {
+ app_stack_v(8.0)
+ .w_full()
+ .child(
+ div()
+ .w_full()
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px * 1.1))
+ .font_weight(gpui::FontWeight::BOLD)
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
+ .child(app_shared_text(title_key)),
+ )
+ .child(
+ div()
+ .w_full()
+ .line_height(relative(1.35))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
+ .child(app_shared_text(body_key)),
+ )
+}
+
+fn account_farm_profile_field_row(
+ first: impl IntoElement,
+ second: impl IntoElement,
+) -> impl IntoElement {
+ div()
+ .w_full()
+ .flex()
+ .items_start()
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
+ .child(div().flex_1().min_w_0().child(first))
+ .child(div().flex_1().min_w_0().child(second))
+}
+
+fn account_farm_profile_select_field(
+ label_key: AppTextKey,
+ select: &Entity<AccountFarmProfileSelectState>,
+) -> impl IntoElement {
+ account_profile_labeled_control(
+ label_key,
+ Select::new(select).with_size(Size::Medium).w_full(),
+ )
+}
+
+fn account_farm_profile_text_area_field(
+ label_key: AppTextKey,
+ input: &Entity<InputState>,
+) -> impl IntoElement {
+ account_profile_labeled_control(label_key, app_text_input(input, false).w_full().h(px(76.0)))
+}
+
+fn account_farm_profile_completeness_card() -> impl IntoElement {
+ account_farm_profile_card(
+ app_stack_v(APP_UI_THEME.shells.home_stack_gap_px)
+ .w_full()
+ .child(
+ div()
+ .w_full()
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px * 1.1))
+ .font_weight(gpui::FontWeight::BOLD)
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
+ .child(app_shared_text(
+ AppTextKey::AccountFarmDetailsCompletenessTitle,
+ )),
+ )
+ .child(
+ div()
+ .w_full()
+ .flex()
+ .items_center()
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
+ .child(account_farm_profile_progress_badge())
+ .child(
+ app_stack_v(6.0)
+ .flex_1()
+ .min_w_0()
+ .child(
+ div()
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
+ .font_weight(gpui::FontWeight::BOLD)
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
+ .child(app_shared_text(
+ AppTextKey::AccountFarmDetailsCompletenessCallout,
+ )),
+ )
+ .child(
+ div()
+ .line_height(relative(1.3))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
+ .child(app_shared_text(
+ AppTextKey::AccountFarmDetailsCompletenessBody,
+ )),
+ ),
+ ),
+ )
+ .child(account_farm_profile_step_list()),
+ )
+}
+
+fn account_farm_profile_progress_badge() -> impl IntoElement {
+ div()
+ .size(px(72.0))
+ .rounded(px(36.0))
+ .border_1()
+ .border_color(rgb(APP_UI_THEME
+ .components
+ .app_button
+ .primary_colors
+ .background))
+ .bg(transparent_black())
+ .flex()
+ .items_center()
+ .justify_center()
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px * 1.25))
+ .font_weight(gpui::FontWeight::BOLD)
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
+ .child(app_shared_text(
+ AppTextKey::AccountFarmDetailsCompletenessPercent,
+ ))
+}
+
+fn account_farm_profile_step_list() -> impl IntoElement {
+ app_stack_v(8.0)
+ .w_full()
+ .child(account_farm_profile_step_row(
+ 1,
+ AppTextKey::AccountFarmDetailsStepFarmProfile,
+ AppTextKey::AccountFarmDetailsStatusInProgress,
+ true,
+ ))
+ .child(account_farm_profile_step_row(
+ 2,
+ AppTextKey::AccountFarmDetailsStepLocation,
+ AppTextKey::AccountFarmDetailsStatusNotStarted,
+ false,
+ ))
+ .child(account_farm_profile_step_row(
+ 3,
+ AppTextKey::AccountFarmDetailsStepOperatingDetails,
+ AppTextKey::AccountFarmDetailsStatusNotStarted,
+ false,
+ ))
+ .child(account_farm_profile_step_row(
+ 4,
+ AppTextKey::AccountFarmDetailsStepPickupFulfillment,
+ AppTextKey::AccountFarmDetailsStatusNotStarted,
+ false,
+ ))
+ .child(account_farm_profile_step_row(
+ 5,
+ AppTextKey::AccountFarmDetailsStepReviewPublish,
+ AppTextKey::AccountFarmDetailsStatusNotStarted,
+ false,
+ ))
+}
+
+fn account_farm_profile_step_row(
+ number: usize,
+ label_key: AppTextKey,
+ status_key: AppTextKey,
+ active: bool,
+) -> impl IntoElement {
+ let marker_bg = if active {
+ APP_UI_THEME.components.app_button.primary_colors.background
+ } else {
+ APP_UI_THEME.foundation.surfaces.divider
+ };
+ let marker_fg = if active {
+ APP_UI_THEME.components.app_button.primary_colors.foreground
+ } else {
+ APP_UI_THEME.foundation.text.secondary
+ };
+ let row_bg = if active {
+ APP_UI_THEME.foundation.surfaces.card_background
+ } else {
+ APP_UI_THEME.foundation.surfaces.window_background
+ };
+
+ div()
+ .w_full()
+ .rounded(px(APP_UI_THEME.foundation.radii.medium_px))
+ .bg(rgb(row_bg))
+ .px(px(8.0))
+ .py(px(6.0))
+ .flex()
+ .items_center()
+ .gap(px(8.0))
+ .child(
+ div()
+ .size(px(18.0))
+ .rounded(px(9.0))
+ .bg(rgb(marker_bg))
+ .flex()
+ .items_center()
+ .justify_center()
+ .text_size(px(APP_UI_THEME.foundation.typography.utility_title_text_px))
+ .font_weight(gpui::FontWeight::BOLD)
+ .text_color(rgb(marker_fg))
+ .child(number.to_string()),
+ )
+ .child(
+ div()
+ .flex_1()
+ .min_w_0()
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
+ .font_weight(gpui::FontWeight::MEDIUM)
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
+ .child(app_shared_text(label_key)),
+ )
+ .child(
+ div()
+ .text_size(px(APP_UI_THEME.foundation.typography.utility_title_text_px))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
+ .child(app_shared_text(status_key)),
+ )
+}
+
+fn account_farm_profile_summary_card(cx: &mut Context<HomeView>) -> impl IntoElement {
+ account_farm_profile_card(
+ app_stack_v(APP_UI_THEME.shells.home_stack_gap_px)
+ .w_full()
+ .child(
+ div()
+ .w_full()
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px * 1.1))
+ .font_weight(gpui::FontWeight::BOLD)
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
+ .child(app_shared_text(AppTextKey::AccountFarmDetailsSummaryTitle)),
+ )
+ .child(
+ div()
+ .w_full()
+ .flex()
+ .items_center()
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
+ .child(
+ div()
+ .size(px(56.0))
+ .rounded(px(28.0))
+ .bg(rgb(0xA7F3B8))
+ .flex()
+ .items_center()
+ .justify_center()
+ .child(
+ Icon::new(IconName::Building2)
+ .with_size(gpui_component::Size::Size(px(28.0)))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary)),
+ ),
+ )
+ .child(
+ app_stack_v(4.0)
+ .flex_1()
+ .min_w_0()
+ .child(
+ div()
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
+ .font_weight(gpui::FontWeight::BOLD)
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
+ .child(app_shared_text(
+ AppTextKey::AccountFarmDetailsFarmNameValue,
+ )),
+ )
+ .child(
+ div()
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
+ .child(app_shared_text(
+ AppTextKey::AccountFarmDetailsFarmLocationValue,
+ )),
+ ),
+ ),
+ )
+ .child(account_farm_profile_summary_row(
+ AppTextKey::AccountFarmDetailsFarmTypeSummaryLabel,
+ AppTextKey::AccountFarmDetailsFarmTypeVegetableFarm,
+ ))
+ .child(account_farm_profile_summary_row(
+ AppTextKey::AccountFarmDetailsEstablishedSummaryLabel,
+ AppTextKey::AccountFarmDetailsEstablishedYearValue,
+ ))
+ .child(action_button_full_width(
+ "account-farm-view-profile",
+ app_shared_text(AppTextKey::AccountFarmDetailsViewFarmProfileAction),
+ |_, _, _| {},
+ cx,
+ )),
+ )
+}
+
+fn account_farm_profile_summary_row(
+ label_key: AppTextKey,
+ value_key: AppTextKey,
+) -> impl IntoElement {
+ div()
+ .w_full()
+ .flex()
+ .items_center()
+ .justify_between()
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
+ .child(
+ div()
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
+ .child(app_shared_text(label_key)),
+ )
+ .child(
+ div()
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
+ .child(app_shared_text(value_key)),
+ )
+}
+
+fn account_farm_profile_action_row(cx: &mut Context<HomeView>) -> impl IntoElement {
+ div()
+ .w_full()
+ .flex()
+ .items_center()
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
+ .child(div().w(px(280.0)).child(action_button_full_width(
+ "account-farm-save-draft",
+ app_shared_text(AppTextKey::AccountFarmDetailsSaveDraftAction),
+ |_, _, _| {},
+ cx,
+ )))
+ .child(
+ div()
+ .flex_1()
+ .min_w_0()
+ .child(action_button_primary_full_width(
+ "account-farm-continue-location",
+ app_shared_text(AppTextKey::AccountFarmDetailsContinueLocationAction),
+ |_, _, _| {},
+ cx,
+ )),
+ )
+}
+
fn buyer_listings_feed(
section: PersonalSection,
rows: &[BuyerListingRow],
diff --git a/crates/i18n/src/keys.rs b/crates/i18n/src/keys.rs
@@ -55,6 +55,58 @@ define_app_text_keys! {
AccountProfileLanguageValue => "account.profile.language.value",
AccountProfileLanguageFrenchValue => "account.profile.language.french.value",
AccountProfileLanguageSpanishValue => "account.profile.language.spanish.value",
+ AccountFarmDetailsFarmProfileTitle => "account.farm_details.farm_profile.title",
+ AccountFarmDetailsFarmProfileIntro => "account.farm_details.farm_profile.intro",
+ AccountFarmDetailsFarmNameLabel => "account.farm_details.farm_name.label",
+ AccountFarmDetailsPublicFarmNameLabel => "account.farm_details.public_farm_name.label",
+ AccountFarmDetailsShortDescriptionLabel => "account.farm_details.short_description.label",
+ AccountFarmDetailsFarmTypeLabel => "account.farm_details.farm_type.label",
+ AccountFarmDetailsContactEmailLabel => "account.farm_details.contact_email.label",
+ AccountFarmDetailsPublicPhoneLabel => "account.farm_details.public_phone.label",
+ AccountFarmDetailsWebsiteLabel => "account.farm_details.website.label",
+ AccountFarmDetailsEstablishedYearLabel => "account.farm_details.established_year.label",
+ AccountFarmDetailsAboutFarmLabel => "account.farm_details.about_farm.label",
+ AccountFarmDetailsFarmNameValue => "account.farm_details.farm_name.value",
+ AccountFarmDetailsPublicFarmNameValue => "account.farm_details.public_farm_name.value",
+ AccountFarmDetailsShortDescriptionValue => "account.farm_details.short_description.value",
+ AccountFarmDetailsContactEmailValue => "account.farm_details.contact_email.value",
+ AccountFarmDetailsPublicPhoneValue => "account.farm_details.public_phone.value",
+ AccountFarmDetailsWebsiteValue => "account.farm_details.website.value",
+ AccountFarmDetailsEstablishedYearValue => "account.farm_details.established_year.value",
+ AccountFarmDetailsAboutFarmValue => "account.farm_details.about_farm.value",
+ AccountFarmDetailsFarmLocationValue => "account.farm_details.farm_location.value",
+ AccountFarmDetailsRequiredFieldNote => "account.farm_details.required_field.note",
+ AccountFarmDetailsCompletenessTitle => "account.farm_details.completeness.title",
+ AccountFarmDetailsCompletenessPercent => "account.farm_details.completeness.percent",
+ AccountFarmDetailsCompletenessCallout => "account.farm_details.completeness.callout",
+ AccountFarmDetailsCompletenessBody => "account.farm_details.completeness.body",
+ AccountFarmDetailsStepFarmProfile => "account.farm_details.step.farm_profile",
+ AccountFarmDetailsStepLocation => "account.farm_details.step.location",
+ AccountFarmDetailsStepOperatingDetails => "account.farm_details.step.operating_details",
+ AccountFarmDetailsStepPickupFulfillment => "account.farm_details.step.pickup_fulfillment",
+ AccountFarmDetailsStepReviewPublish => "account.farm_details.step.review_publish",
+ AccountFarmDetailsStatusInProgress => "account.farm_details.status.in_progress",
+ AccountFarmDetailsStatusNotStarted => "account.farm_details.status.not_started",
+ AccountFarmDetailsSummaryTitle => "account.farm_details.summary.title",
+ AccountFarmDetailsFarmTypeSummaryLabel => "account.farm_details.summary.farm_type.label",
+ AccountFarmDetailsEstablishedSummaryLabel => "account.farm_details.summary.established.label",
+ AccountFarmDetailsViewFarmProfileAction => "account.farm_details.view_farm_profile.action",
+ AccountFarmDetailsSaveDraftAction => "account.farm_details.save_draft.action",
+ AccountFarmDetailsContinueLocationAction => "account.farm_details.continue_location.action",
+ AccountFarmDetailsFarmTypeVegetableFarm => "account.farm_details.farm_type.vegetable_farm",
+ AccountFarmDetailsFarmTypeFruitOrchard => "account.farm_details.farm_type.fruit_orchard",
+ AccountFarmDetailsFarmTypeBerryFarm => "account.farm_details.farm_type.berry_farm",
+ AccountFarmDetailsFarmTypeHerbFarm => "account.farm_details.farm_type.herb_farm",
+ AccountFarmDetailsFarmTypeFlowerFarm => "account.farm_details.farm_type.flower_farm",
+ AccountFarmDetailsFarmTypeMushroomFarm => "account.farm_details.farm_type.mushroom_farm",
+ AccountFarmDetailsFarmTypeGrainFieldCropFarm => "account.farm_details.farm_type.grain_field_crop_farm",
+ AccountFarmDetailsFarmTypeDairyFarm => "account.farm_details.farm_type.dairy_farm",
+ AccountFarmDetailsFarmTypeEggPoultryFarm => "account.farm_details.farm_type.egg_poultry_farm",
+ AccountFarmDetailsFarmTypeLivestockFarm => "account.farm_details.farm_type.livestock_farm",
+ AccountFarmDetailsFarmTypeHoneyApiary => "account.farm_details.farm_type.honey_apiary",
+ AccountFarmDetailsFarmTypeNurseryPlantFarm => "account.farm_details.farm_type.nursery_plant_farm",
+ AccountFarmDetailsFarmTypeMixedFarm => "account.farm_details.farm_type.mixed_farm",
+ AccountFarmDetailsFarmTypeOther => "account.farm_details.farm_type.other",
HomeNavBrowse => "home.nav.browse",
HomeNavSearch => "home.nav.search",
HomeNavCart => "home.nav.cart",
diff --git a/crates/i18n/src/lib.rs b/crates/i18n/src/lib.rs
@@ -178,6 +178,22 @@ mod tests {
"Remove"
);
assert_eq!(
+ app_text(AppTextKey::AccountFarmDetailsFarmProfileTitle),
+ "Farm profile"
+ );
+ assert_eq!(
+ app_text(AppTextKey::AccountFarmDetailsFarmTypeVegetableFarm),
+ "Vegetable farm"
+ );
+ assert_eq!(
+ app_text(AppTextKey::AccountFarmDetailsSaveDraftAction),
+ "Save draft"
+ );
+ assert_eq!(
+ app_text(AppTextKey::AccountFarmDetailsContinueLocationAction),
+ "Continue to location"
+ );
+ assert_eq!(
app_text(AppTextKey::HomeTodayEmptySetupBody),
"Add a local account to start using Radroots on this device."
);
diff --git a/i18n/locales/en/messages.json b/i18n/locales/en/messages.json
@@ -34,6 +34,58 @@
"account.profile.language.value": "English",
"account.profile.language.french.value": "French",
"account.profile.language.spanish.value": "Spanish",
+ "account.farm_details.farm_profile.title": "Farm profile",
+ "account.farm_details.farm_profile.intro": "Tell us about your farm. This information helps build your public profile and connect you with customers.",
+ "account.farm_details.farm_name.label": "Farm name *",
+ "account.farm_details.public_farm_name.label": "Public farm name *",
+ "account.farm_details.short_description.label": "Short description *",
+ "account.farm_details.farm_type.label": "Farm type *",
+ "account.farm_details.contact_email.label": "Contact email *",
+ "account.farm_details.public_phone.label": "Public phone",
+ "account.farm_details.website.label": "Website",
+ "account.farm_details.established_year.label": "Established year",
+ "account.farm_details.about_farm.label": "About the farm *",
+ "account.farm_details.farm_name.value": "Tyson's Farm",
+ "account.farm_details.public_farm_name.value": "Tyson's Farm",
+ "account.farm_details.short_description.value": "Family-run farm growing quality produce.",
+ "account.farm_details.contact_email.value": "tyson@tysonsfarm.com",
+ "account.farm_details.public_phone.value": "+1 (250) 555-0198",
+ "account.farm_details.website.value": "https://tysonsfarm.com",
+ "account.farm_details.established_year.value": "2018",
+ "account.farm_details.about_farm.value": "We're a family-run farm in Victoria, British Columbia growing fresh, sustainable produce. Our mission is to nourish our community with high-quality vegetables while caring for the land.",
+ "account.farm_details.farm_location.value": "Victoria, BC, Canada",
+ "account.farm_details.required_field.note": "* Required field",
+ "account.farm_details.completeness.title": "Profile completeness",
+ "account.farm_details.completeness.percent": "18%",
+ "account.farm_details.completeness.callout": "Let's build a great profile.",
+ "account.farm_details.completeness.body": "Complete these steps to publish your farm profile.",
+ "account.farm_details.step.farm_profile": "Farm profile",
+ "account.farm_details.step.location": "Location",
+ "account.farm_details.step.operating_details": "Operating details",
+ "account.farm_details.step.pickup_fulfillment": "Pickup & fulfillment",
+ "account.farm_details.step.review_publish": "Review & publish",
+ "account.farm_details.status.in_progress": "In progress",
+ "account.farm_details.status.not_started": "Not started",
+ "account.farm_details.summary.title": "Farm summary",
+ "account.farm_details.summary.farm_type.label": "Farm type",
+ "account.farm_details.summary.established.label": "Established",
+ "account.farm_details.view_farm_profile.action": "View farm on profile",
+ "account.farm_details.save_draft.action": "Save draft",
+ "account.farm_details.continue_location.action": "Continue to location",
+ "account.farm_details.farm_type.vegetable_farm": "Vegetable farm",
+ "account.farm_details.farm_type.fruit_orchard": "Fruit farm / orchard",
+ "account.farm_details.farm_type.berry_farm": "Berry farm",
+ "account.farm_details.farm_type.herb_farm": "Herb farm",
+ "account.farm_details.farm_type.flower_farm": "Flower farm",
+ "account.farm_details.farm_type.mushroom_farm": "Mushroom farm",
+ "account.farm_details.farm_type.grain_field_crop_farm": "Grain & field crop farm",
+ "account.farm_details.farm_type.dairy_farm": "Dairy farm",
+ "account.farm_details.farm_type.egg_poultry_farm": "Egg & poultry farm",
+ "account.farm_details.farm_type.livestock_farm": "Livestock farm",
+ "account.farm_details.farm_type.honey_apiary": "Honey / apiary",
+ "account.farm_details.farm_type.nursery_plant_farm": "Nursery & plant farm",
+ "account.farm_details.farm_type.mixed_farm": "Mixed farm",
+ "account.farm_details.farm_type.other": "Other farm type",
"home.nav.browse": "Browse",
"home.nav.search": "Search",
"home.nav.cart": "Cart",