commit ee0f4439b3e7a398a4ee84e44191ad43150033ec
parent 9f814f5fcdf7010b476624123c5d31da005f8bc8
Author: triesap <tyson@radroots.org>
Date: Sun, 7 Jun 2026 15:51:24 -0700
ui: expand farm details scroll view
Diffstat:
5 files changed, 1227 insertions(+), 52 deletions(-)
diff --git a/crates/desktop/src/source_guards.rs b/crates/desktop/src/source_guards.rs
@@ -56,6 +56,8 @@ const ALLOWED_WINDOW_LITERALS: &[&str] = &[
"account-settings-save-draft",
"account-farm-save",
"account-farm-save-draft",
+ "account-farm-add-pickup-window",
+ "account-farm-profile-preview",
"account-farm-view-profile",
"account-scroll",
"account-tabs",
@@ -454,6 +456,99 @@ const REQUIRED_WINDOW_COPY_KEYS: &[&str] = &[
"AppTextKey::AccountFarmDetailsFarmTypeNurseryPlantFarm",
"AppTextKey::AccountFarmDetailsFarmTypeMixedFarm",
"AppTextKey::AccountFarmDetailsFarmTypeOther",
+ "AppTextKey::AccountFarmDetailsLocationTitle",
+ "AppTextKey::AccountFarmDetailsLocationIntro",
+ "AppTextKey::AccountFarmDetailsMapNotImplemented",
+ "AppTextKey::AccountFarmDetailsStreetAddressLabel",
+ "AppTextKey::AccountFarmDetailsStreetAddressValue",
+ "AppTextKey::AccountFarmDetailsCityLabel",
+ "AppTextKey::AccountFarmDetailsCityValue",
+ "AppTextKey::AccountFarmDetailsProvinceLabel",
+ "AppTextKey::AccountFarmDetailsProvinceBritishColumbia",
+ "AppTextKey::AccountFarmDetailsProvinceAlberta",
+ "AppTextKey::AccountFarmDetailsPostalCodeLabel",
+ "AppTextKey::AccountFarmDetailsPostalCodeValue",
+ "AppTextKey::AccountFarmDetailsCountryLabel",
+ "AppTextKey::AccountFarmDetailsCountryCanada",
+ "AppTextKey::AccountFarmDetailsCountryUnitedStates",
+ "AppTextKey::AccountFarmDetailsServiceAreaLabel",
+ "AppTextKey::AccountFarmDetailsServiceAreaValue",
+ "AppTextKey::AccountFarmDetailsServiceAreaHelper",
+ "AppTextKey::AccountFarmDetailsExactAddressPublicLabel",
+ "AppTextKey::AccountFarmDetailsExactAddressPublicHelper",
+ "AppTextKey::AccountFarmDetailsLocationPreviewTitle",
+ "AppTextKey::AccountFarmDetailsLocationPreviewHelper",
+ "AppTextKey::AccountFarmDetailsOperatingTitle",
+ "AppTextKey::AccountFarmDetailsOperatingIntro",
+ "AppTextKey::AccountFarmDetailsGrowingPracticesLabel",
+ "AppTextKey::AccountFarmDetailsGrowingPracticeRegenerative",
+ "AppTextKey::AccountFarmDetailsGrowingPracticeOrganic",
+ "AppTextKey::AccountFarmDetailsProductionMethodsLabel",
+ "AppTextKey::AccountFarmDetailsProductionMethodOrganicPractices",
+ "AppTextKey::AccountFarmDetailsProductionMethodNoSpray",
+ "AppTextKey::AccountFarmDetailsSeasonDatesLabel",
+ "AppTextKey::AccountFarmDetailsSeasonStartValue",
+ "AppTextKey::AccountFarmDetailsSeasonEndValue",
+ "AppTextKey::AccountFarmDetailsOrderDaysLabel",
+ "AppTextKey::AccountFarmDetailsOrderDaysSummaryValue",
+ "AppTextKey::AccountFarmDetailsDayMon",
+ "AppTextKey::AccountFarmDetailsDayTue",
+ "AppTextKey::AccountFarmDetailsDayWed",
+ "AppTextKey::AccountFarmDetailsDayThu",
+ "AppTextKey::AccountFarmDetailsDayFri",
+ "AppTextKey::AccountFarmDetailsDaySat",
+ "AppTextKey::AccountFarmDetailsDaySun",
+ "AppTextKey::AccountFarmDetailsAboutProductsLabel",
+ "AppTextKey::AccountFarmDetailsAboutProductsValue",
+ "AppTextKey::AccountFarmDetailsCertificationsTitle",
+ "AppTextKey::AccountFarmDetailsCertificationsHelper",
+ "AppTextKey::AccountFarmDetailsCertificationCertifiedOrganic",
+ "AppTextKey::AccountFarmDetailsCertificationNaturallyGrown",
+ "AppTextKey::AccountFarmDetailsCertificationSmallFamilyFarm",
+ "AppTextKey::AccountFarmDetailsCertificationDeliveryAvailable",
+ "AppTextKey::AccountFarmDetailsCustomerNoteTitle",
+ "AppTextKey::AccountFarmDetailsCustomerNoteHelper",
+ "AppTextKey::AccountFarmDetailsCustomerNoteValue",
+ "AppTextKey::AccountFarmDetailsProfilePreviewTitle",
+ "AppTextKey::AccountFarmDetailsGrowingPracticesSummaryLabel",
+ "AppTextKey::AccountFarmDetailsSeasonSummaryLabel",
+ "AppTextKey::AccountFarmDetailsOrderDaysSummaryLabel",
+ "AppTextKey::AccountFarmDetailsPickupFulfillmentTitle",
+ "AppTextKey::AccountFarmDetailsPickupFulfillmentIntro",
+ "AppTextKey::AccountFarmDetailsFulfillmentModeLabel",
+ "AppTextKey::AccountFarmDetailsFulfillmentPickupOnly",
+ "AppTextKey::AccountFarmDetailsFulfillmentDelivery",
+ "AppTextKey::AccountFarmDetailsFulfillmentBoth",
+ "AppTextKey::AccountFarmDetailsPrimaryPickupLocationLabel",
+ "AppTextKey::AccountFarmDetailsPrimaryPickupLocationTitleValue",
+ "AppTextKey::AccountFarmDetailsPrimaryPickupLocationAddressValue",
+ "AppTextKey::AccountFarmDetailsPickupInstructionsLabel",
+ "AppTextKey::AccountFarmDetailsPickupInstructionsValue",
+ "AppTextKey::AccountFarmDetailsPickupInstructionsHelper",
+ "AppTextKey::AccountFarmDetailsPickupWindowsLabel",
+ "AppTextKey::AccountFarmDetailsPickupWindowDayHeader",
+ "AppTextKey::AccountFarmDetailsPickupWindowStartHeader",
+ "AppTextKey::AccountFarmDetailsPickupWindowEndHeader",
+ "AppTextKey::AccountFarmDetailsPickupWindowWednesday",
+ "AppTextKey::AccountFarmDetailsPickupWindowSaturday",
+ "AppTextKey::AccountFarmDetailsPickupWindowWednesdayStart",
+ "AppTextKey::AccountFarmDetailsPickupWindowWednesdayEnd",
+ "AppTextKey::AccountFarmDetailsPickupWindowSaturdayStart",
+ "AppTextKey::AccountFarmDetailsPickupWindowSaturdayEnd",
+ "AppTextKey::AccountFarmDetailsAddPickupWindowAction",
+ "AppTextKey::AccountFarmDetailsOrderCutoffLabel",
+ "AppTextKey::AccountFarmDetailsOrderCutoffHelper",
+ "AppTextKey::AccountFarmDetailsOrderCutoffNoonValue",
+ "AppTextKey::AccountFarmDetailsDeliveryRadiusTitle",
+ "AppTextKey::AccountFarmDetailsDeliveryRadiusHelper",
+ "AppTextKey::AccountFarmDetailsDeliveryRadiusValue",
+ "AppTextKey::AccountFarmDetailsDeliveryRadiusUnit",
+ "AppTextKey::AccountFarmDetailsDeliveryRadiusNote",
+ "AppTextKey::AccountFarmDetailsCustomerExperienceTitle",
+ "AppTextKey::AccountFarmDetailsCustomerExperienceIntro",
+ "AppTextKey::AccountFarmDetailsCustomerExperiencePickupTitle",
+ "AppTextKey::AccountFarmDetailsCustomerExperienceDeliveryTitle",
+ "AppTextKey::AccountFarmDetailsCustomerExperienceDeliveryBody",
"AppTextKey::AccountSettingsTitle",
"AppTextKey::AccountSettingsNostrRelaysTitle",
"AppTextKey::AccountSettingsNostrRelaysHelper",
diff --git a/crates/desktop/src/window.rs b/crates/desktop/src/window.rs
@@ -338,6 +338,21 @@ struct AccountFarmProfileFormState {
established_year_input: Entity<InputState>,
about_farm_input: Entity<InputState>,
farm_type_select: Entity<AccountFarmProfileSelectState>,
+ street_address_input: Entity<InputState>,
+ city_input: Entity<InputState>,
+ postal_code_input: Entity<InputState>,
+ province_select: Entity<AccountFarmProfileSelectState>,
+ country_select: Entity<AccountFarmProfileSelectState>,
+ service_area_select: Entity<AccountFarmProfileSelectState>,
+ growing_practices_select: Entity<AccountFarmProfileSelectState>,
+ season_start_input: Entity<InputState>,
+ season_end_input: Entity<InputState>,
+ about_products_input: Entity<InputState>,
+ customer_note_input: Entity<InputState>,
+ primary_pickup_location_select: Entity<AccountFarmProfileSelectState>,
+ pickup_instructions_input: Entity<InputState>,
+ order_cutoff_select: Entity<AccountFarmProfileSelectState>,
+ delivery_radius_input: Entity<InputState>,
}
impl AccountFarmProfileFormState {
@@ -403,6 +418,90 @@ impl AccountFarmProfileFormState {
window,
cx,
),
+ street_address_input: account_profile_input_state(
+ AppTextKey::AccountFarmDetailsStreetAddressValue,
+ window,
+ cx,
+ ),
+ city_input: account_profile_input_state(
+ AppTextKey::AccountFarmDetailsCityValue,
+ window,
+ cx,
+ ),
+ postal_code_input: account_profile_input_state(
+ AppTextKey::AccountFarmDetailsPostalCodeValue,
+ window,
+ cx,
+ ),
+ province_select: account_farm_profile_select_state(
+ &[
+ AppTextKey::AccountFarmDetailsProvinceBritishColumbia,
+ AppTextKey::AccountFarmDetailsProvinceAlberta,
+ ],
+ window,
+ cx,
+ ),
+ country_select: account_farm_profile_select_state(
+ &[
+ AppTextKey::AccountFarmDetailsCountryCanada,
+ AppTextKey::AccountFarmDetailsCountryUnitedStates,
+ ],
+ window,
+ cx,
+ ),
+ service_area_select: account_farm_profile_select_state(
+ &[AppTextKey::AccountFarmDetailsServiceAreaValue],
+ window,
+ cx,
+ ),
+ growing_practices_select: account_farm_profile_select_state(
+ &[
+ AppTextKey::AccountFarmDetailsGrowingPracticeRegenerative,
+ AppTextKey::AccountFarmDetailsGrowingPracticeOrganic,
+ ],
+ window,
+ cx,
+ ),
+ season_start_input: account_profile_input_state(
+ AppTextKey::AccountFarmDetailsSeasonStartValue,
+ window,
+ cx,
+ ),
+ season_end_input: account_profile_input_state(
+ AppTextKey::AccountFarmDetailsSeasonEndValue,
+ window,
+ cx,
+ ),
+ about_products_input: account_profile_autogrow_input_state(
+ AppTextKey::AccountFarmDetailsAboutProductsValue,
+ window,
+ cx,
+ ),
+ customer_note_input: account_profile_autogrow_input_state(
+ AppTextKey::AccountFarmDetailsCustomerNoteValue,
+ window,
+ cx,
+ ),
+ primary_pickup_location_select: account_farm_profile_select_state(
+ &[AppTextKey::AccountFarmDetailsPrimaryPickupLocationTitleValue],
+ window,
+ cx,
+ ),
+ pickup_instructions_input: account_profile_autogrow_input_state(
+ AppTextKey::AccountFarmDetailsPickupInstructionsValue,
+ window,
+ cx,
+ ),
+ order_cutoff_select: account_farm_profile_select_state(
+ &[AppTextKey::AccountFarmDetailsOrderCutoffNoonValue],
+ window,
+ cx,
+ ),
+ delivery_radius_input: account_profile_input_state(
+ AppTextKey::AccountFarmDetailsDeliveryRadiusValue,
+ window,
+ cx,
+ ),
}
}
@@ -440,6 +539,57 @@ impl AccountFarmProfileFormState {
AppTextKey::AccountFarmDetailsAboutFarmValue,
cx,
) || account_select_is_dirty(&self.farm_type_select, cx)
+ || account_input_is_dirty(
+ &self.street_address_input,
+ AppTextKey::AccountFarmDetailsStreetAddressValue,
+ cx,
+ )
+ || account_input_is_dirty(
+ &self.city_input,
+ AppTextKey::AccountFarmDetailsCityValue,
+ cx,
+ )
+ || account_input_is_dirty(
+ &self.postal_code_input,
+ AppTextKey::AccountFarmDetailsPostalCodeValue,
+ cx,
+ )
+ || account_select_is_dirty(&self.province_select, cx)
+ || account_select_is_dirty(&self.country_select, cx)
+ || account_select_is_dirty(&self.service_area_select, cx)
+ || account_select_is_dirty(&self.growing_practices_select, cx)
+ || account_input_is_dirty(
+ &self.season_start_input,
+ AppTextKey::AccountFarmDetailsSeasonStartValue,
+ cx,
+ )
+ || account_input_is_dirty(
+ &self.season_end_input,
+ AppTextKey::AccountFarmDetailsSeasonEndValue,
+ cx,
+ )
+ || account_input_is_dirty(
+ &self.about_products_input,
+ AppTextKey::AccountFarmDetailsAboutProductsValue,
+ cx,
+ )
+ || account_input_is_dirty(
+ &self.customer_note_input,
+ AppTextKey::AccountFarmDetailsCustomerNoteValue,
+ cx,
+ )
+ || account_select_is_dirty(&self.primary_pickup_location_select, cx)
+ || account_input_is_dirty(
+ &self.pickup_instructions_input,
+ AppTextKey::AccountFarmDetailsPickupInstructionsValue,
+ cx,
+ )
+ || account_select_is_dirty(&self.order_cutoff_select, cx)
+ || account_input_is_dirty(
+ &self.delivery_radius_input,
+ AppTextKey::AccountFarmDetailsDeliveryRadiusValue,
+ cx,
+ )
}
}
@@ -9598,37 +9748,45 @@ fn account_farm_profile_panel(
cx,
)),
))
- .child(
- div()
+ .child(account_farm_profile_section_row(
+ account_farm_profile_main_card(form, is_textarea_wrap_ready, cx),
+ app_stack_v(APP_UI_THEME.shells.home_stack_gap_px)
.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,
- is_textarea_wrap_ready,
- cx,
- )),
- )
- .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_completeness_card())
+ .child(account_farm_profile_summary_card(cx)),
+ ))
+ .child(account_farm_profile_section_row(
+ account_farm_location_card(form),
+ account_farm_location_preview_card(),
+ ))
+ .child(account_farm_profile_section_row(
+ account_farm_operating_card(form, is_textarea_wrap_ready, cx),
+ account_farm_profile_preview_card(cx),
+ ))
+ .child(account_farm_profile_section_row(
+ account_farm_fulfillment_card(form, is_textarea_wrap_ready, cx),
+ account_farm_customer_experience_card(),
+ ))
+}
+
+fn account_farm_profile_section_row(
+ main: impl IntoElement,
+ rail: 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(main))
+ .child(div().w(px(336.0)).min_w(px(300.0)).child(rail))
}
fn account_farm_profile_main_card(
form: &AccountFarmProfileFormState,
is_textarea_wrap_ready: bool,
cx: &mut Context<HomeView>,
-) -> impl IntoElement {
+) -> impl IntoElement + use<> {
account_farm_profile_card(
app_stack_v(APP_UI_THEME.shells.home_stack_gap_px)
.w_full()
@@ -9694,57 +9852,545 @@ fn account_farm_profile_main_card(
)
}
-fn account_farm_profile_card(content: impl IntoElement) -> impl IntoElement {
+fn account_farm_location_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::AccountFarmDetailsLocationTitle,
+ AppTextKey::AccountFarmDetailsLocationIntro,
+ ))
+ .child(account_farm_map_placeholder())
+ .child(account_farm_profile_field_row(
+ account_profile_input_field(
+ AppTextKey::AccountFarmDetailsStreetAddressLabel,
+ &form.street_address_input,
+ ),
+ account_profile_input_field(
+ AppTextKey::AccountFarmDetailsCityLabel,
+ &form.city_input,
+ ),
+ ))
+ .child(account_farm_profile_field_row(
+ account_farm_profile_select_field(
+ AppTextKey::AccountFarmDetailsProvinceLabel,
+ &form.province_select,
+ ),
+ account_profile_input_field(
+ AppTextKey::AccountFarmDetailsPostalCodeLabel,
+ &form.postal_code_input,
+ ),
+ ))
+ .child(account_farm_profile_field_row(
+ account_farm_profile_select_field(
+ AppTextKey::AccountFarmDetailsCountryLabel,
+ &form.country_select,
+ ),
+ account_farm_profile_select_field(
+ AppTextKey::AccountFarmDetailsServiceAreaLabel,
+ &form.service_area_select,
+ ),
+ ))
+ .child(account_farm_profile_helper_text(
+ AppTextKey::AccountFarmDetailsServiceAreaHelper,
+ ))
+ .child(account_farm_toggle_preview_row(
+ AppTextKey::AccountFarmDetailsExactAddressPublicLabel,
+ AppTextKey::AccountFarmDetailsExactAddressPublicHelper,
+ )),
+ )
+}
+
+fn account_farm_map_placeholder() -> impl IntoElement {
div()
.w_full()
+ .h(px(220.0))
+ .rounded(px(APP_UI_THEME.foundation.radii.large_px))
.border_1()
.border_color(rgb(APP_UI_THEME.foundation.surfaces.divider))
- .rounded(px(APP_UI_THEME.foundation.radii.large_px))
- .bg(transparent_black())
+ .bg(rgb(APP_UI_THEME.foundation.surfaces.card_background))
+ .flex()
+ .items_center()
+ .justify_center()
.child(
div()
- .w_full()
- .p(px(APP_UI_THEME.shells.home_card_padding_px))
- .child(content),
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
+ .font_weight(gpui::FontWeight::MEDIUM)
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
+ .child(app_shared_text(
+ AppTextKey::AccountFarmDetailsMapNotImplemented,
+ )),
)
}
-fn account_farm_profile_title_block(
- title_key: AppTextKey,
- body_key: AppTextKey,
-) -> impl IntoElement {
- app_stack_v(8.0)
+fn account_farm_location_preview_card() -> impl IntoElement {
+ account_farm_profile_card(
+ app_stack_v(APP_UI_THEME.shells.home_stack_gap_px)
+ .w_full()
+ .child(account_farm_preview_title(
+ AppTextKey::AccountFarmDetailsLocationPreviewTitle,
+ ))
+ .child(account_farm_icon_value_row(
+ IconName::Map,
+ AppTextKey::AccountFarmDetailsFarmLocationValue,
+ AppTextKey::AccountFarmDetailsServiceAreaValue,
+ ))
+ .child(account_farm_service_area_preview())
+ .child(account_farm_profile_helper_text(
+ AppTextKey::AccountFarmDetailsLocationPreviewHelper,
+ )),
+ )
+}
+
+fn account_farm_service_area_preview() -> impl IntoElement {
+ div()
.w_full()
+ .h(px(132.0))
+ .rounded(px(APP_UI_THEME.foundation.radii.medium_px))
+ .bg(rgb(APP_UI_THEME.foundation.surfaces.card_background))
+ .border_1()
+ .border_color(rgb(APP_UI_THEME.foundation.surfaces.divider))
+ .flex()
+ .items_center()
+ .justify_center()
.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))
+ .font_weight(gpui::FontWeight::MEDIUM)
.text_color(rgb(APP_UI_THEME.foundation.text.secondary))
- .child(app_shared_text(body_key)),
+ .child(app_shared_text(
+ AppTextKey::AccountFarmDetailsMapNotImplemented,
+ )),
)
}
-fn account_farm_profile_field_row(
- first: impl IntoElement,
- second: impl IntoElement,
+fn account_farm_operating_card(
+ form: &AccountFarmProfileFormState,
+ is_textarea_wrap_ready: bool,
+ cx: &mut Context<HomeView>,
+) -> impl IntoElement + use<> {
+ account_farm_profile_card(
+ app_stack_v(APP_UI_THEME.shells.home_stack_gap_px)
+ .w_full()
+ .child(account_farm_profile_title_block(
+ AppTextKey::AccountFarmDetailsOperatingTitle,
+ AppTextKey::AccountFarmDetailsOperatingIntro,
+ ))
+ .child(account_farm_profile_field_row(
+ account_farm_profile_select_field(
+ AppTextKey::AccountFarmDetailsGrowingPracticesLabel,
+ &form.growing_practices_select,
+ ),
+ account_farm_static_chip_group(
+ AppTextKey::AccountFarmDetailsProductionMethodsLabel,
+ &[
+ AppTextKey::AccountFarmDetailsProductionMethodOrganicPractices,
+ AppTextKey::AccountFarmDetailsProductionMethodNoSpray,
+ AppTextKey::AccountFarmDetailsGrowingPracticeRegenerative,
+ ],
+ 3,
+ ),
+ ))
+ .child(account_farm_profile_field_row(
+ account_farm_date_range_fields(
+ AppTextKey::AccountFarmDetailsSeasonDatesLabel,
+ &form.season_start_input,
+ &form.season_end_input,
+ ),
+ account_farm_day_chip_group(),
+ ))
+ .child(account_farm_profile_text_area_field(
+ AppTextKey::AccountFarmDetailsAboutProductsLabel,
+ &form.about_products_input,
+ is_textarea_wrap_ready,
+ cx,
+ ))
+ .child(account_farm_static_chip_group_with_helper(
+ AppTextKey::AccountFarmDetailsCertificationsTitle,
+ AppTextKey::AccountFarmDetailsCertificationsHelper,
+ &[
+ AppTextKey::AccountFarmDetailsCertificationCertifiedOrganic,
+ AppTextKey::AccountFarmDetailsCertificationNaturallyGrown,
+ AppTextKey::AccountFarmDetailsCertificationSmallFamilyFarm,
+ AppTextKey::AccountFarmDetailsCertificationDeliveryAvailable,
+ ],
+ 3,
+ ))
+ .child(account_farm_profile_text_area_field_with_helper(
+ AppTextKey::AccountFarmDetailsCustomerNoteTitle,
+ AppTextKey::AccountFarmDetailsCustomerNoteHelper,
+ &form.customer_note_input,
+ is_textarea_wrap_ready,
+ cx,
+ )),
+ )
+}
+
+fn account_farm_profile_preview_card(cx: &mut Context<HomeView>) -> impl IntoElement + use<> {
+ account_farm_profile_card(
+ app_stack_v(APP_UI_THEME.shells.home_stack_gap_px)
+ .w_full()
+ .child(account_farm_preview_title(
+ AppTextKey::AccountFarmDetailsProfilePreviewTitle,
+ ))
+ .child(account_farm_icon_value_row(
+ IconName::Building2,
+ AppTextKey::AccountFarmDetailsFarmNameValue,
+ AppTextKey::AccountFarmDetailsFarmLocationValue,
+ ))
+ .child(account_farm_profile_summary_row(
+ AppTextKey::AccountFarmDetailsGrowingPracticesSummaryLabel,
+ AppTextKey::AccountFarmDetailsGrowingPracticeRegenerative,
+ ))
+ .child(account_farm_profile_summary_row(
+ AppTextKey::AccountFarmDetailsSeasonSummaryLabel,
+ AppTextKey::AccountFarmDetailsSeasonStartValue,
+ ))
+ .child(account_farm_profile_summary_row(
+ AppTextKey::AccountFarmDetailsOrderDaysSummaryLabel,
+ AppTextKey::AccountFarmDetailsOrderDaysSummaryValue,
+ ))
+ .child(account_farm_profile_summary_row(
+ AppTextKey::AccountFarmDetailsFarmTypeSummaryLabel,
+ AppTextKey::AccountFarmDetailsFarmTypeVegetableFarm,
+ ))
+ .child(action_button_full_width(
+ "account-farm-profile-preview",
+ app_shared_text(AppTextKey::AccountFarmDetailsViewFarmProfileAction),
+ |_, _, _| {},
+ cx,
+ )),
+ )
+}
+
+fn account_farm_fulfillment_card(
+ form: &AccountFarmProfileFormState,
+ is_textarea_wrap_ready: bool,
+ cx: &mut Context<HomeView>,
+) -> impl IntoElement + use<> {
+ account_farm_profile_card(
+ app_stack_v(APP_UI_THEME.shells.home_stack_gap_px)
+ .w_full()
+ .child(account_farm_profile_title_block(
+ AppTextKey::AccountFarmDetailsPickupFulfillmentTitle,
+ AppTextKey::AccountFarmDetailsPickupFulfillmentIntro,
+ ))
+ .child(account_farm_static_chip_group(
+ AppTextKey::AccountFarmDetailsFulfillmentModeLabel,
+ &[
+ AppTextKey::AccountFarmDetailsFulfillmentPickupOnly,
+ AppTextKey::AccountFarmDetailsFulfillmentDelivery,
+ AppTextKey::AccountFarmDetailsFulfillmentBoth,
+ ],
+ 2,
+ ))
+ .child(account_farm_profile_labeled_control_with_helper(
+ AppTextKey::AccountFarmDetailsPrimaryPickupLocationLabel,
+ account_farm_profile_select_input(&form.primary_pickup_location_select),
+ Some(AppTextKey::AccountFarmDetailsPrimaryPickupLocationAddressValue),
+ ))
+ .child(account_farm_profile_text_area_field_with_helper(
+ AppTextKey::AccountFarmDetailsPickupInstructionsLabel,
+ AppTextKey::AccountFarmDetailsPickupInstructionsHelper,
+ &form.pickup_instructions_input,
+ is_textarea_wrap_ready,
+ cx,
+ ))
+ .child(account_farm_pickup_schedule_row(form, cx))
+ .child(account_farm_delivery_radius_row(
+ &form.delivery_radius_input,
+ )),
+ )
+}
+
+fn account_farm_pickup_schedule_row(
+ form: &AccountFarmProfileFormState,
+ cx: &mut Context<HomeView>,
) -> 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))
-}
+ .child(
+ app_stack_v(8.0)
+ .flex_1()
+ .min_w_0()
+ .child(account_farm_field_label(
+ AppTextKey::AccountFarmDetailsPickupWindowsLabel,
+ ))
+ .child(account_farm_pickup_windows_table())
+ .child(div().w(px(180.0)).child(action_button_compact(
+ "account-farm-add-pickup-window",
+ app_shared_text(AppTextKey::AccountFarmDetailsAddPickupWindowAction),
+ |_, _, _| {},
+ cx,
+ ))),
+ )
+ .child(
+ div()
+ .w(px(176.0))
+ .child(account_farm_profile_labeled_control_with_helper(
+ AppTextKey::AccountFarmDetailsOrderCutoffLabel,
+ account_farm_profile_select_input(&form.order_cutoff_select),
+ Some(AppTextKey::AccountFarmDetailsOrderCutoffHelper),
+ )),
+ )
+}
+
+fn account_farm_pickup_windows_table() -> impl IntoElement {
+ app_stack_v(0.0)
+ .w_full()
+ .border_1()
+ .border_color(rgb(APP_UI_THEME.foundation.surfaces.divider))
+ .rounded(px(APP_UI_THEME.foundation.radii.medium_px))
+ .overflow_hidden()
+ .child(account_farm_pickup_window_table_row(
+ AppTextKey::AccountFarmDetailsPickupWindowDayHeader,
+ AppTextKey::AccountFarmDetailsPickupWindowStartHeader,
+ AppTextKey::AccountFarmDetailsPickupWindowEndHeader,
+ false,
+ ))
+ .child(account_farm_pickup_window_table_row(
+ AppTextKey::AccountFarmDetailsPickupWindowWednesday,
+ AppTextKey::AccountFarmDetailsPickupWindowWednesdayStart,
+ AppTextKey::AccountFarmDetailsPickupWindowWednesdayEnd,
+ true,
+ ))
+ .child(account_farm_pickup_window_table_row(
+ AppTextKey::AccountFarmDetailsPickupWindowSaturday,
+ AppTextKey::AccountFarmDetailsPickupWindowSaturdayStart,
+ AppTextKey::AccountFarmDetailsPickupWindowSaturdayEnd,
+ true,
+ ))
+}
+
+fn account_farm_pickup_window_table_row(
+ day_key: AppTextKey,
+ start_key: AppTextKey,
+ end_key: AppTextKey,
+ action: bool,
+) -> impl IntoElement {
+ let bg = if action {
+ APP_UI_THEME.foundation.surfaces.window_background
+ } else {
+ APP_UI_THEME.foundation.surfaces.card_background
+ };
+
+ div()
+ .w_full()
+ .bg(rgb(bg))
+ .px(px(10.0))
+ .py(px(7.0))
+ .flex()
+ .items_center()
+ .gap(px(10.0))
+ .child(account_farm_table_cell(day_key, 1.0))
+ .child(account_farm_table_cell(start_key, 1.0))
+ .child(account_farm_table_cell(end_key, 1.0))
+ .when(action, |this| {
+ this.child(
+ div()
+ .flex_none()
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
+ .child(Icon::new(IconName::Ellipsis).with_size(gpui_component::Size::Small)),
+ )
+ })
+}
+
+fn account_farm_table_cell(label_key: AppTextKey, basis: f32) -> impl IntoElement {
+ div()
+ .flex_basis(relative(basis))
+ .min_w_0()
+ .text_size(px(APP_UI_THEME.foundation.typography.settings_row_text_px))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
+ .child(app_shared_text(label_key))
+}
+
+fn account_farm_delivery_radius_row(input: &Entity<InputState>) -> impl IntoElement {
+ app_stack_v(8.0)
+ .w_full()
+ .pt(px(APP_UI_THEME.shells.home_stack_gap_px))
+ .child(account_farm_profile_title_block(
+ AppTextKey::AccountFarmDetailsDeliveryRadiusTitle,
+ AppTextKey::AccountFarmDetailsDeliveryRadiusHelper,
+ ))
+ .child(
+ div()
+ .w_full()
+ .flex()
+ .items_center()
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
+ .child(account_farm_slider_preview())
+ .child(div().w(px(74.0)).child(account_form_text_input(input)))
+ .child(
+ div()
+ .text_size(px(APP_UI_THEME.foundation.typography.settings_row_text_px))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
+ .child(app_shared_text(
+ AppTextKey::AccountFarmDetailsDeliveryRadiusUnit,
+ )),
+ ),
+ )
+ .child(account_farm_profile_helper_text(
+ AppTextKey::AccountFarmDetailsDeliveryRadiusNote,
+ ))
+}
+
+fn account_farm_slider_preview() -> impl IntoElement {
+ div()
+ .flex_1()
+ .min_w_0()
+ .h(px(4.0))
+ .rounded(px(2.0))
+ .bg(rgb(APP_UI_THEME.foundation.surfaces.divider))
+ .child(div().w(relative(0.38)).h(px(4.0)).rounded(px(2.0)).bg(rgb(
+ APP_UI_THEME.components.app_button.primary_colors.background,
+ )))
+}
+
+fn account_farm_customer_experience_card() -> impl IntoElement {
+ account_farm_profile_card(
+ app_stack_v(APP_UI_THEME.shells.home_stack_gap_px)
+ .w_full()
+ .child(account_farm_preview_title(
+ AppTextKey::AccountFarmDetailsCustomerExperienceTitle,
+ ))
+ .child(account_farm_profile_helper_text(
+ AppTextKey::AccountFarmDetailsCustomerExperienceIntro,
+ ))
+ .child(account_farm_customer_experience_panel(
+ AppTextKey::AccountFarmDetailsCustomerExperiencePickupTitle,
+ AppTextKey::AccountFarmDetailsPrimaryPickupLocationTitleValue,
+ AppTextKey::AccountFarmDetailsPrimaryPickupLocationAddressValue,
+ ))
+ .child(account_farm_customer_experience_panel(
+ AppTextKey::AccountFarmDetailsCustomerExperienceDeliveryTitle,
+ AppTextKey::AccountFarmDetailsCustomerExperienceDeliveryBody,
+ AppTextKey::AccountFarmDetailsServiceAreaValue,
+ )),
+ )
+}
+
+fn account_farm_customer_experience_panel(
+ title_key: AppTextKey,
+ primary_key: AppTextKey,
+ secondary_key: AppTextKey,
+) -> impl IntoElement {
+ div()
+ .w_full()
+ .rounded(px(APP_UI_THEME.foundation.radii.medium_px))
+ .bg(rgb(APP_UI_THEME.foundation.surfaces.card_background))
+ .p(px(10.0))
+ .child(
+ app_stack_v(4.0)
+ .w_full()
+ .child(
+ div()
+ .text_size(px(APP_UI_THEME.foundation.typography.settings_row_text_px))
+ .font_weight(gpui::FontWeight::BOLD)
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
+ .child(app_shared_text(title_key)),
+ )
+ .child(
+ div()
+ .text_size(px(APP_UI_THEME.foundation.typography.settings_row_text_px))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
+ .child(app_shared_text(primary_key)),
+ )
+ .child(
+ div()
+ .text_size(px(APP_UI_THEME.foundation.typography.settings_row_text_px))
+ .line_height(relative(1.25))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
+ .child(app_shared_text(secondary_key)),
+ ),
+ )
+}
+
+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_field_label(label_key: AppTextKey) -> impl IntoElement {
+ div()
+ .w_full()
+ .text_size(px(APP_UI_THEME.foundation.typography.utility_title_text_px))
+ .font_weight(gpui::FontWeight::SEMIBOLD)
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
+ .child(app_shared_text(label_key))
+}
+
+fn account_farm_profile_helper_text(text_key: AppTextKey) -> impl IntoElement {
+ div()
+ .w_full()
+ .line_height(relative(1.3))
+ .text_size(px(APP_UI_THEME.foundation.typography.settings_row_text_px))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
+ .child(app_shared_text(text_key))
+}
+
+fn account_farm_profile_labeled_control_with_helper(
+ label_key: AppTextKey,
+ control: impl IntoElement,
+ helper_key: Option<AppTextKey>,
+) -> impl IntoElement {
+ app_stack_v(6.0)
+ .w_full()
+ .child(account_farm_field_label(label_key))
+ .child(control)
+ .when_some(helper_key, |this, helper_key| {
+ this.child(account_farm_profile_helper_text(helper_key))
+ })
+}
fn account_farm_profile_select_field(
label_key: AppTextKey,
@@ -9765,6 +10411,234 @@ fn account_farm_profile_text_area_field(
)
}
+fn account_farm_profile_text_area_field_with_helper(
+ label_key: AppTextKey,
+ helper_key: AppTextKey,
+ input: &Entity<InputState>,
+ is_wrap_ready: bool,
+ cx: &mut Context<HomeView>,
+) -> impl IntoElement {
+ account_farm_profile_labeled_control_with_helper(
+ label_key,
+ account_form_text_area_input_with_wrapped_preview(input, is_wrap_ready, cx),
+ Some(helper_key),
+ )
+}
+
+fn account_farm_toggle_preview_row(
+ label_key: AppTextKey,
+ helper_key: AppTextKey,
+) -> impl IntoElement {
+ div()
+ .w_full()
+ .flex()
+ .items_start()
+ .gap(px(10.0))
+ .child(
+ div()
+ .flex_none()
+ .w(px(34.0))
+ .h(px(20.0))
+ .rounded(px(10.0))
+ .bg(rgb(APP_UI_THEME.foundation.surfaces.divider))
+ .p(px(2.0))
+ .child(
+ div()
+ .size(px(16.0))
+ .rounded(px(8.0))
+ .bg(rgb(APP_UI_THEME.foundation.surfaces.window_background)),
+ ),
+ )
+ .child(
+ app_stack_v(3.0)
+ .flex_1()
+ .min_w_0()
+ .child(
+ div()
+ .text_size(px(APP_UI_THEME.foundation.typography.settings_row_text_px))
+ .font_weight(gpui::FontWeight::MEDIUM)
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
+ .child(app_shared_text(label_key)),
+ )
+ .child(account_farm_profile_helper_text(helper_key)),
+ )
+}
+
+fn account_farm_preview_title(title_key: AppTextKey) -> impl IntoElement {
+ 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))
+}
+
+fn account_farm_icon_value_row(
+ icon_name: IconName,
+ title_key: AppTextKey,
+ subtitle_key: AppTextKey,
+) -> impl IntoElement {
+ div()
+ .w_full()
+ .flex()
+ .items_center()
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
+ .child(
+ div()
+ .size(px(46.0))
+ .rounded(px(23.0))
+ .bg(rgb(0xA7F3B8))
+ .flex()
+ .items_center()
+ .justify_center()
+ .child(
+ Icon::new(icon_name)
+ .with_size(gpui_component::Size::Size(px(24.0)))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary)),
+ ),
+ )
+ .child(
+ app_stack_v(3.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(title_key)),
+ )
+ .child(
+ div()
+ .text_size(px(APP_UI_THEME.foundation.typography.settings_row_text_px))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
+ .child(app_shared_text(subtitle_key)),
+ ),
+ )
+}
+
+fn account_farm_static_chip_group(
+ label_key: AppTextKey,
+ chips: &[AppTextKey],
+ selected_count: usize,
+) -> impl IntoElement {
+ account_farm_profile_labeled_control_with_helper(
+ label_key,
+ account_farm_chip_wrap(chips, selected_count),
+ None,
+ )
+}
+
+fn account_farm_static_chip_group_with_helper(
+ label_key: AppTextKey,
+ helper_key: AppTextKey,
+ chips: &[AppTextKey],
+ selected_count: usize,
+) -> impl IntoElement {
+ account_farm_profile_labeled_control_with_helper(
+ label_key,
+ account_farm_chip_wrap(chips, selected_count),
+ Some(helper_key),
+ )
+}
+
+fn account_farm_chip_wrap(chips: &[AppTextKey], selected_count: usize) -> impl IntoElement {
+ div().w_full().flex().flex_wrap().gap(px(8.0)).children(
+ chips
+ .iter()
+ .enumerate()
+ .map(|(index, key)| account_farm_chip(*key, index < selected_count).into_any_element()),
+ )
+}
+
+fn account_farm_chip(label_key: AppTextKey, selected: bool) -> impl IntoElement {
+ let border = if selected {
+ APP_UI_THEME.components.app_button.primary_colors.background
+ } else {
+ APP_UI_THEME.foundation.surfaces.divider
+ };
+ let text = if selected {
+ APP_UI_THEME.components.app_button.primary_colors.background
+ } else {
+ APP_UI_THEME.foundation.text.primary
+ };
+
+ div()
+ .rounded(px(APP_UI_THEME.foundation.radii.medium_px))
+ .border_1()
+ .border_color(rgb(border))
+ .bg(rgb(APP_UI_THEME.foundation.surfaces.window_background))
+ .px(px(10.0))
+ .py(px(6.0))
+ .flex()
+ .items_center()
+ .gap(px(6.0))
+ .when(selected, |this| {
+ this.child(
+ Icon::new(IconName::Check)
+ .with_size(gpui_component::Size::Small)
+ .text_color(rgb(text)),
+ )
+ })
+ .child(
+ div()
+ .text_size(px(APP_UI_THEME.foundation.typography.settings_row_text_px))
+ .font_weight(gpui::FontWeight::MEDIUM)
+ .text_color(rgb(text))
+ .child(app_shared_text(label_key)),
+ )
+}
+
+fn account_farm_day_chip_group() -> impl IntoElement {
+ account_farm_static_chip_group(
+ AppTextKey::AccountFarmDetailsOrderDaysLabel,
+ &[
+ AppTextKey::AccountFarmDetailsDayMon,
+ AppTextKey::AccountFarmDetailsDayTue,
+ AppTextKey::AccountFarmDetailsDayWed,
+ AppTextKey::AccountFarmDetailsDayThu,
+ AppTextKey::AccountFarmDetailsDayFri,
+ AppTextKey::AccountFarmDetailsDaySat,
+ AppTextKey::AccountFarmDetailsDaySun,
+ ],
+ 5,
+ )
+}
+
+fn account_farm_date_range_fields(
+ label_key: AppTextKey,
+ start_input: &Entity<InputState>,
+ end_input: &Entity<InputState>,
+) -> impl IntoElement {
+ app_stack_v(6.0)
+ .w_full()
+ .child(account_farm_field_label(label_key))
+ .child(
+ div()
+ .w_full()
+ .flex()
+ .items_center()
+ .gap(px(8.0))
+ .child(
+ div()
+ .flex_1()
+ .min_w_0()
+ .child(account_form_text_input(start_input)),
+ )
+ .child(
+ Icon::new(IconName::ArrowRight)
+ .with_size(gpui_component::Size::Small)
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary)),
+ )
+ .child(
+ div()
+ .flex_1()
+ .min_w_0()
+ .child(account_form_text_input(end_input)),
+ ),
+ )
+}
+
fn account_farm_profile_completeness_card() -> impl IntoElement {
account_farm_profile_card(
app_stack_v(APP_UI_THEME.shells.home_stack_gap_px)
diff --git a/crates/i18n/src/keys.rs b/crates/i18n/src/keys.rs
@@ -108,6 +108,99 @@ define_app_text_keys! {
AccountFarmDetailsFarmTypeNurseryPlantFarm => "account.farm_details.farm_type.nursery_plant_farm",
AccountFarmDetailsFarmTypeMixedFarm => "account.farm_details.farm_type.mixed_farm",
AccountFarmDetailsFarmTypeOther => "account.farm_details.farm_type.other",
+ AccountFarmDetailsLocationTitle => "account.farm_details.location.title",
+ AccountFarmDetailsLocationIntro => "account.farm_details.location.intro",
+ AccountFarmDetailsMapNotImplemented => "account.farm_details.map.not_implemented",
+ AccountFarmDetailsStreetAddressLabel => "account.farm_details.street_address.label",
+ AccountFarmDetailsStreetAddressValue => "account.farm_details.street_address.value",
+ AccountFarmDetailsCityLabel => "account.farm_details.city.label",
+ AccountFarmDetailsCityValue => "account.farm_details.city.value",
+ AccountFarmDetailsProvinceLabel => "account.farm_details.province.label",
+ AccountFarmDetailsProvinceBritishColumbia => "account.farm_details.province.british_columbia",
+ AccountFarmDetailsProvinceAlberta => "account.farm_details.province.alberta",
+ AccountFarmDetailsPostalCodeLabel => "account.farm_details.postal_code.label",
+ AccountFarmDetailsPostalCodeValue => "account.farm_details.postal_code.value",
+ AccountFarmDetailsCountryLabel => "account.farm_details.country.label",
+ AccountFarmDetailsCountryCanada => "account.farm_details.country.canada",
+ AccountFarmDetailsCountryUnitedStates => "account.farm_details.country.united_states",
+ AccountFarmDetailsServiceAreaLabel => "account.farm_details.service_area.label",
+ AccountFarmDetailsServiceAreaValue => "account.farm_details.service_area.value",
+ AccountFarmDetailsServiceAreaHelper => "account.farm_details.service_area.helper",
+ AccountFarmDetailsExactAddressPublicLabel => "account.farm_details.exact_address_public.label",
+ AccountFarmDetailsExactAddressPublicHelper => "account.farm_details.exact_address_public.helper",
+ AccountFarmDetailsLocationPreviewTitle => "account.farm_details.location_preview.title",
+ AccountFarmDetailsLocationPreviewHelper => "account.farm_details.location_preview.helper",
+ AccountFarmDetailsOperatingTitle => "account.farm_details.operating.title",
+ AccountFarmDetailsOperatingIntro => "account.farm_details.operating.intro",
+ AccountFarmDetailsGrowingPracticesLabel => "account.farm_details.growing_practices.label",
+ AccountFarmDetailsGrowingPracticeRegenerative => "account.farm_details.growing_practice.regenerative",
+ AccountFarmDetailsGrowingPracticeOrganic => "account.farm_details.growing_practice.organic",
+ AccountFarmDetailsProductionMethodsLabel => "account.farm_details.production_methods.label",
+ AccountFarmDetailsProductionMethodOrganicPractices => "account.farm_details.production_method.organic_practices",
+ AccountFarmDetailsProductionMethodNoSpray => "account.farm_details.production_method.no_spray",
+ AccountFarmDetailsSeasonDatesLabel => "account.farm_details.season_dates.label",
+ AccountFarmDetailsSeasonStartValue => "account.farm_details.season_start.value",
+ AccountFarmDetailsSeasonEndValue => "account.farm_details.season_end.value",
+ AccountFarmDetailsOrderDaysLabel => "account.farm_details.order_days.label",
+ AccountFarmDetailsOrderDaysSummaryValue => "account.farm_details.order_days.summary.value",
+ AccountFarmDetailsDayMon => "account.farm_details.day.mon",
+ AccountFarmDetailsDayTue => "account.farm_details.day.tue",
+ AccountFarmDetailsDayWed => "account.farm_details.day.wed",
+ AccountFarmDetailsDayThu => "account.farm_details.day.thu",
+ AccountFarmDetailsDayFri => "account.farm_details.day.fri",
+ AccountFarmDetailsDaySat => "account.farm_details.day.sat",
+ AccountFarmDetailsDaySun => "account.farm_details.day.sun",
+ AccountFarmDetailsAboutProductsLabel => "account.farm_details.about_products.label",
+ AccountFarmDetailsAboutProductsValue => "account.farm_details.about_products.value",
+ AccountFarmDetailsCertificationsTitle => "account.farm_details.certifications.title",
+ AccountFarmDetailsCertificationsHelper => "account.farm_details.certifications.helper",
+ AccountFarmDetailsCertificationCertifiedOrganic => "account.farm_details.certification.certified_organic",
+ AccountFarmDetailsCertificationNaturallyGrown => "account.farm_details.certification.naturally_grown",
+ AccountFarmDetailsCertificationSmallFamilyFarm => "account.farm_details.certification.small_family_farm",
+ AccountFarmDetailsCertificationDeliveryAvailable => "account.farm_details.certification.delivery_available",
+ AccountFarmDetailsCustomerNoteTitle => "account.farm_details.customer_note.title",
+ AccountFarmDetailsCustomerNoteHelper => "account.farm_details.customer_note.helper",
+ AccountFarmDetailsCustomerNoteValue => "account.farm_details.customer_note.value",
+ AccountFarmDetailsProfilePreviewTitle => "account.farm_details.profile_preview.title",
+ AccountFarmDetailsGrowingPracticesSummaryLabel => "account.farm_details.summary.growing_practices.label",
+ AccountFarmDetailsSeasonSummaryLabel => "account.farm_details.summary.season.label",
+ AccountFarmDetailsOrderDaysSummaryLabel => "account.farm_details.summary.order_days.label",
+ AccountFarmDetailsPickupFulfillmentTitle => "account.farm_details.pickup_fulfillment.title",
+ AccountFarmDetailsPickupFulfillmentIntro => "account.farm_details.pickup_fulfillment.intro",
+ AccountFarmDetailsFulfillmentModeLabel => "account.farm_details.fulfillment_mode.label",
+ AccountFarmDetailsFulfillmentPickupOnly => "account.farm_details.fulfillment.pickup_only",
+ AccountFarmDetailsFulfillmentDelivery => "account.farm_details.fulfillment.delivery",
+ AccountFarmDetailsFulfillmentBoth => "account.farm_details.fulfillment.both",
+ AccountFarmDetailsPrimaryPickupLocationLabel => "account.farm_details.primary_pickup_location.label",
+ AccountFarmDetailsPrimaryPickupLocationTitleValue => "account.farm_details.primary_pickup_location.title.value",
+ AccountFarmDetailsPrimaryPickupLocationAddressValue => "account.farm_details.primary_pickup_location.address.value",
+ AccountFarmDetailsPickupInstructionsLabel => "account.farm_details.pickup_instructions.label",
+ AccountFarmDetailsPickupInstructionsValue => "account.farm_details.pickup_instructions.value",
+ AccountFarmDetailsPickupInstructionsHelper => "account.farm_details.pickup_instructions.helper",
+ AccountFarmDetailsPickupWindowsLabel => "account.farm_details.pickup_windows.label",
+ AccountFarmDetailsPickupWindowDayHeader => "account.farm_details.pickup_window.day.header",
+ AccountFarmDetailsPickupWindowStartHeader => "account.farm_details.pickup_window.start.header",
+ AccountFarmDetailsPickupWindowEndHeader => "account.farm_details.pickup_window.end.header",
+ AccountFarmDetailsPickupWindowWednesday => "account.farm_details.pickup_window.wednesday",
+ AccountFarmDetailsPickupWindowSaturday => "account.farm_details.pickup_window.saturday",
+ AccountFarmDetailsPickupWindowWednesdayStart => "account.farm_details.pickup_window.wednesday.start",
+ AccountFarmDetailsPickupWindowWednesdayEnd => "account.farm_details.pickup_window.wednesday.end",
+ AccountFarmDetailsPickupWindowSaturdayStart => "account.farm_details.pickup_window.saturday.start",
+ AccountFarmDetailsPickupWindowSaturdayEnd => "account.farm_details.pickup_window.saturday.end",
+ AccountFarmDetailsAddPickupWindowAction => "account.farm_details.add_pickup_window.action",
+ AccountFarmDetailsOrderCutoffLabel => "account.farm_details.order_cutoff.label",
+ AccountFarmDetailsOrderCutoffHelper => "account.farm_details.order_cutoff.helper",
+ AccountFarmDetailsOrderCutoffNoonValue => "account.farm_details.order_cutoff.noon.value",
+ AccountFarmDetailsDeliveryRadiusTitle => "account.farm_details.delivery_radius.title",
+ AccountFarmDetailsDeliveryRadiusHelper => "account.farm_details.delivery_radius.helper",
+ AccountFarmDetailsDeliveryRadiusValue => "account.farm_details.delivery_radius.value",
+ AccountFarmDetailsDeliveryRadiusUnit => "account.farm_details.delivery_radius.unit",
+ AccountFarmDetailsDeliveryRadiusNote => "account.farm_details.delivery_radius.note",
+ AccountFarmDetailsCustomerExperienceTitle => "account.farm_details.customer_experience.title",
+ AccountFarmDetailsCustomerExperienceIntro => "account.farm_details.customer_experience.intro",
+ AccountFarmDetailsCustomerExperiencePickupTitle => "account.farm_details.customer_experience.pickup.title",
+ AccountFarmDetailsCustomerExperienceDeliveryTitle => "account.farm_details.customer_experience.delivery.title",
+ AccountFarmDetailsCustomerExperienceDeliveryBody => "account.farm_details.customer_experience.delivery.body",
AccountSettingsTitle => "account.settings.title",
AccountSettingsNostrRelaysTitle => "account.settings.nostr_relays.title",
AccountSettingsNostrRelaysHelper => "account.settings.nostr_relays.helper",
diff --git a/crates/i18n/src/lib.rs b/crates/i18n/src/lib.rs
@@ -214,6 +214,26 @@ mod tests {
app_text(AppTextKey::AccountFarmDetailsFarmTypeVegetableFarm),
"Vegetable farm"
);
+ assert_eq!(
+ app_text(AppTextKey::AccountFarmDetailsLocationTitle),
+ "Location & service area"
+ );
+ assert_eq!(
+ app_text(AppTextKey::AccountFarmDetailsMapNotImplemented),
+ "not implemented"
+ );
+ assert_eq!(
+ app_text(AppTextKey::AccountFarmDetailsOperatingTitle),
+ "Operating details"
+ );
+ assert_eq!(
+ app_text(AppTextKey::AccountFarmDetailsPickupFulfillmentTitle),
+ "Pickup & fulfilment"
+ );
+ assert_eq!(
+ app_text(AppTextKey::AccountFarmDetailsOrderCutoffNoonValue),
+ "12:00 PM (Noon)"
+ );
assert_eq!(app_text(AppTextKey::AccountSettingsTitle), "Settings");
assert_eq!(
app_text(AppTextKey::AccountSettingsNostrRelaysTitle),
diff --git a/i18n/locales/en/messages.json b/i18n/locales/en/messages.json
@@ -87,6 +87,99 @@
"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",
+ "account.farm_details.location.title": "Location & service area",
+ "account.farm_details.location.intro": "Help customers understand where your farm operates and which local areas you serve.",
+ "account.farm_details.map.not_implemented": "not implemented",
+ "account.farm_details.street_address.label": "Street address *",
+ "account.farm_details.street_address.value": "1234 Beacon Hill Road",
+ "account.farm_details.city.label": "City *",
+ "account.farm_details.city.value": "Victoria",
+ "account.farm_details.province.label": "Province *",
+ "account.farm_details.province.british_columbia": "British Columbia",
+ "account.farm_details.province.alberta": "Alberta",
+ "account.farm_details.postal_code.label": "Postal code *",
+ "account.farm_details.postal_code.value": "V8N 1Z1",
+ "account.farm_details.country.label": "Country *",
+ "account.farm_details.country.canada": "Canada",
+ "account.farm_details.country.united_states": "United States",
+ "account.farm_details.service_area.label": "Service area *",
+ "account.farm_details.service_area.value": "25 km around Victoria, BC",
+ "account.farm_details.service_area.helper": "Customers within this area can discover your farm.",
+ "account.farm_details.exact_address_public.label": "Make exact address public",
+ "account.farm_details.exact_address_public.helper": "Customers see your service area unless pickup is enabled.",
+ "account.farm_details.location_preview.title": "Location preview",
+ "account.farm_details.location_preview.helper": "Customers will see your service area.",
+ "account.farm_details.operating.title": "Operating details",
+ "account.farm_details.operating.intro": "Share how you grow, when products are available, and the standards customers can expect.",
+ "account.farm_details.growing_practices.label": "Growing practices *",
+ "account.farm_details.growing_practice.regenerative": "Regenerative",
+ "account.farm_details.growing_practice.organic": "Organic practices",
+ "account.farm_details.production_methods.label": "Production methods",
+ "account.farm_details.production_method.organic_practices": "Organic practices",
+ "account.farm_details.production_method.no_spray": "No spray",
+ "account.farm_details.season_dates.label": "Typical season dates *",
+ "account.farm_details.season_start.value": "Mar 15",
+ "account.farm_details.season_end.value": "Nov 15",
+ "account.farm_details.order_days.label": "Customer availability / order days *",
+ "account.farm_details.order_days.summary.value": "Mon - Fri",
+ "account.farm_details.day.mon": "Mon",
+ "account.farm_details.day.tue": "Tue",
+ "account.farm_details.day.wed": "Wed",
+ "account.farm_details.day.thu": "Thu",
+ "account.farm_details.day.fri": "Fri",
+ "account.farm_details.day.sat": "Sat",
+ "account.farm_details.day.sun": "Sun",
+ "account.farm_details.about_products.label": "About your products *",
+ "account.farm_details.about_products.value": "We grow a diverse mix of seasonal vegetables and herbs with a focus on flavour, freshness, and soil health.",
+ "account.farm_details.certifications.title": "Certifications & trust signals",
+ "account.farm_details.certifications.helper": "Select the signals that accurately describe your farm.",
+ "account.farm_details.certification.certified_organic": "Certified organic",
+ "account.farm_details.certification.naturally_grown": "Naturally grown",
+ "account.farm_details.certification.small_family_farm": "Small family farm",
+ "account.farm_details.certification.delivery_available": "Delivery available",
+ "account.farm_details.customer_note.title": "What customers should know",
+ "account.farm_details.customer_note.helper": "Share anything important customers should know before ordering.",
+ "account.farm_details.customer_note.value": "We never use synthetic pesticides or herbicides. We prioritize soil health, biodiversity, and growing food the right way.",
+ "account.farm_details.profile_preview.title": "Profile preview",
+ "account.farm_details.summary.growing_practices.label": "Growing practices",
+ "account.farm_details.summary.season.label": "Season",
+ "account.farm_details.summary.order_days.label": "Order days",
+ "account.farm_details.pickup_fulfillment.title": "Pickup & fulfilment",
+ "account.farm_details.pickup_fulfillment.intro": "Set clear pickup and delivery expectations for customers.",
+ "account.farm_details.fulfillment_mode.label": "Fulfilment mode *",
+ "account.farm_details.fulfillment.pickup_only": "Pickup only",
+ "account.farm_details.fulfillment.delivery": "Delivery",
+ "account.farm_details.fulfillment.both": "Both",
+ "account.farm_details.primary_pickup_location.label": "Primary pickup location *",
+ "account.farm_details.primary_pickup_location.title.value": "Farmstand at Tyson's Farm",
+ "account.farm_details.primary_pickup_location.address.value": "1234 Meadow Lane, Victoria, BC V9B 2N1",
+ "account.farm_details.pickup_instructions.label": "Pickup instructions",
+ "account.farm_details.pickup_instructions.value": "Please park in the gravel lot and check in at the farmstand. We'll have your order ready for you.",
+ "account.farm_details.pickup_instructions.helper": "These instructions are shown after a customer places an order.",
+ "account.farm_details.pickup_windows.label": "Standard pickup windows *",
+ "account.farm_details.pickup_window.day.header": "Day",
+ "account.farm_details.pickup_window.start.header": "Start time",
+ "account.farm_details.pickup_window.end.header": "End time",
+ "account.farm_details.pickup_window.wednesday": "Wednesday",
+ "account.farm_details.pickup_window.saturday": "Saturday",
+ "account.farm_details.pickup_window.wednesday.start": "3:00 PM",
+ "account.farm_details.pickup_window.wednesday.end": "6:00 PM",
+ "account.farm_details.pickup_window.saturday.start": "9:00 AM",
+ "account.farm_details.pickup_window.saturday.end": "1:00 PM",
+ "account.farm_details.add_pickup_window.action": "Add pickup window",
+ "account.farm_details.order_cutoff.label": "Order cutoff time *",
+ "account.farm_details.order_cutoff.helper": "Orders placed before this time are prepared for the next pickup window.",
+ "account.farm_details.order_cutoff.noon.value": "12:00 PM (Noon)",
+ "account.farm_details.delivery_radius.title": "Optional delivery radius",
+ "account.farm_details.delivery_radius.helper": "Set how far you are willing to deliver. Leave at 0 km to hide delivery.",
+ "account.farm_details.delivery_radius.value": "25",
+ "account.farm_details.delivery_radius.unit": "km",
+ "account.farm_details.delivery_radius.note": "Customers outside this radius will not see delivery as an option.",
+ "account.farm_details.customer_experience.title": "Customer experience",
+ "account.farm_details.customer_experience.intro": "This is how customers will see pickup and delivery information.",
+ "account.farm_details.customer_experience.pickup.title": "Pickup",
+ "account.farm_details.customer_experience.delivery.title": "Delivery",
+ "account.farm_details.customer_experience.delivery.body": "Delivery available within 25 km from your farm.",
"account.settings.title": "Settings",
"account.settings.nostr_relays.title": "Nostr relays",
"account.settings.nostr_relays.helper": "Manage the relays used to publish and read events.",