From 32ccd49d7802bd8ef9292b2112ebf05cf073a20d Mon Sep 17 00:00:00 2001 From: ponzischeme89 Date: Thu, 7 May 2026 07:57:52 +1200 Subject: [PATCH] Remove CTA button from mobile --- DEPLOYMENT.md | 6 +++++ deploy.env.template | 1 + docker-compose.prod.yml | 1 + docker-compose.yml | 1 + src/lib/components/MobileBookBar.svelte | 15 +++++++++++-- src/lib/feature-flags.test.ts | 30 +++++++++++++++++++++++++ src/lib/feature-flags.ts | 21 +++++++++++++++++ src/lib/server/feature-flags.ts | 18 +-------------- 8 files changed, 74 insertions(+), 19 deletions(-) create mode 100644 src/lib/feature-flags.test.ts create mode 100644 src/lib/feature-flags.ts diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index 64caf53..d46a20b 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -75,6 +75,7 @@ It is created from [deploy.env.template](deploy.env.template). Current template ```env APP_VERSION=4.2.3 ENABLE_GENERAL_ENQUIRIES=false +PUBLIC_ENABLE_MOBILE_CTA_BUTTON=false TZ=Pacific/Auckland POSTGRES_DB=goodwalk @@ -100,6 +101,11 @@ After the first deploy, edit `/docker/goodwalk-svelte/.env` on the server and re - `RESEND_API_KEY=replace-me` - `OWNER_EMAIL=replace-me` +Frontend flags: + +- `PUBLIC_ENABLE_MOBILE_CTA_BUTTON=false` keeps the sticky mobile booking CTA hidden. +- Set `PUBLIC_ENABLE_MOBILE_CTA_BUTTON=true` to show it again. + 4. Confirm the shared Docker network already exists: ```bash diff --git a/deploy.env.template b/deploy.env.template index 71a03a3..cf27aa7 100644 --- a/deploy.env.template +++ b/deploy.env.template @@ -13,6 +13,7 @@ CLIENT_BCC=mattcohen0@gmail.com FROM_EMAIL=GoodWalk REPLY_TO=info@goodwalk.co.nz ENABLE_GENERAL_ENQUIRIES=false +PUBLIC_ENABLE_MOBILE_CTA_BUTTON=false FORM_MIN_SECONDS=4 FORM_MAX_SECONDS=7200 diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index eee542a..88ccee0 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -11,6 +11,7 @@ services: NODE_ENV: production PORT: 3000 ENABLE_GENERAL_ENQUIRIES: ${ENABLE_GENERAL_ENQUIRIES:-false} + PUBLIC_ENABLE_MOBILE_CTA_BUTTON: ${PUBLIC_ENABLE_MOBILE_CTA_BUTTON:-false} TZ: ${TZ:-Pacific/Auckland} depends_on: - db diff --git a/docker-compose.yml b/docker-compose.yml index c0e572a..f0714b9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,6 +10,7 @@ services: NODE_ENV: production PORT: ${APP_PORT:-3000} ENABLE_GENERAL_ENQUIRIES: ${ENABLE_GENERAL_ENQUIRIES:-false} + PUBLIC_ENABLE_MOBILE_CTA_BUTTON: ${PUBLIC_ENABLE_MOBILE_CTA_BUTTON:-false} TZ: ${TZ:-Pacific/Auckland} depends_on: - db diff --git a/src/lib/components/MobileBookBar.svelte b/src/lib/components/MobileBookBar.svelte index 895fe82..731bd73 100644 --- a/src/lib/components/MobileBookBar.svelte +++ b/src/lib/components/MobileBookBar.svelte @@ -3,6 +3,7 @@ import { afterNavigate } from '$app/navigation'; import { page } from '$app/stores'; import Icon from '$lib/components/Icon.svelte'; + import { isMobileCtaButtonEnabled } from '$lib/feature-flags'; /* * Sticky bottom CTA shown on mobile only. @@ -20,6 +21,8 @@ * to book while they're already on the form). */ + const mobileCtaButtonEnabled = isMobileCtaButtonEnabled(); + $: pathname = $page.url.pathname; $: hidden = pathname === '/contact-us' || pathname === '/booking'; @@ -41,7 +44,7 @@ } async function setupObservers() { - if (typeof window === 'undefined') { + if (!mobileCtaButtonEnabled || typeof window === 'undefined') { return; } @@ -84,6 +87,10 @@ } afterNavigate(() => { + if (!mobileCtaButtonEnabled) { + return; + } + visible = false; triggerPassed = false; bookingInView = false; @@ -91,6 +98,10 @@ }); onMount(() => { + if (!mobileCtaButtonEnabled) { + return; + } + void setupObservers(); return () => { @@ -99,7 +110,7 @@ }); -{#if !hidden} +{#if mobileCtaButtonEnabled && !hidden}
{ + afterEach(() => { + vi.unstubAllEnvs(); + vi.resetModules(); + }); + + it('defaults the mobile CTA button to disabled', async () => { + const { isMobileCtaButtonEnabled } = await import('./feature-flags'); + + expect(isMobileCtaButtonEnabled()).toBe(false); + }); + + it('enables the mobile CTA button when the public env flag is truthy', async () => { + vi.stubEnv('PUBLIC_ENABLE_MOBILE_CTA_BUTTON', 'enabled'); + + const { isMobileCtaButtonEnabled } = await import('./feature-flags'); + + expect(isMobileCtaButtonEnabled()).toBe(true); + }); + + it('treats explicit false values as disabled', async () => { + vi.stubEnv('PUBLIC_ENABLE_MOBILE_CTA_BUTTON', 'off'); + + const { isMobileCtaButtonEnabled } = await import('./feature-flags'); + + expect(isMobileCtaButtonEnabled()).toBe(false); + }); +}); diff --git a/src/lib/feature-flags.ts b/src/lib/feature-flags.ts new file mode 100644 index 0000000..485cac3 --- /dev/null +++ b/src/lib/feature-flags.ts @@ -0,0 +1,21 @@ +export function parseBooleanFlag(value: string | undefined, defaultValue = false) { + if (value == null) { + return defaultValue; + } + + const normalized = value.trim().toLowerCase(); + + if (['1', 'true', 'yes', 'on', 'enabled'].includes(normalized)) { + return true; + } + + if (['0', 'false', 'no', 'off', 'disabled'].includes(normalized)) { + return false; + } + + return defaultValue; +} + +export function isMobileCtaButtonEnabled() { + return parseBooleanFlag(import.meta.env.PUBLIC_ENABLE_MOBILE_CTA_BUTTON, false); +} diff --git a/src/lib/server/feature-flags.ts b/src/lib/server/feature-flags.ts index 12c27d6..3da3813 100644 --- a/src/lib/server/feature-flags.ts +++ b/src/lib/server/feature-flags.ts @@ -1,20 +1,4 @@ -function parseBooleanFlag(value: string | undefined, defaultValue = false) { - if (value == null) { - return defaultValue; - } - - const normalized = value.trim().toLowerCase(); - - if (['1', 'true', 'yes', 'on', 'enabled'].includes(normalized)) { - return true; - } - - if (['0', 'false', 'no', 'off', 'disabled'].includes(normalized)) { - return false; - } - - return defaultValue; -} +import { parseBooleanFlag } from '$lib/feature-flags'; export function isGeneralEnquiryEnabled() { return parseBooleanFlag(process.env.ENABLE_GENERAL_ENQUIRIES, false);