From 7160259afd4bae300a16b0dd95adadac119698dd Mon Sep 17 00:00:00 2001 From: DMleadgen Date: Fri, 27 Mar 2026 15:57:59 -0600 Subject: [PATCH] deploy: reset public forms and white surfaces --- app/[...slug]/page.tsx | 30 +++-- app/service-areas/page.tsx | 11 +- app/services/moving/page.tsx | 30 ++--- app/vending-machines-[location]/page.tsx | 20 ++-- .../machines-for-sale/page.tsx | 17 ++- app/vending-machines/machines-we-use/page.tsx | 8 +- components/contact-page.tsx | 8 +- components/contact-section.tsx | 113 +++++++++++------- components/forms/contact-form.tsx | 21 ++-- components/forms/form-button.tsx | 4 +- components/forms/form-input.tsx | 2 +- components/forms/form-select.tsx | 2 +- components/forms/form-textarea.tsx | 2 +- components/forms/request-machine-form.tsx | 21 ++-- components/forms/sms-consent-fields.tsx | 41 ++----- components/get-free-machine-cta.tsx | 37 ++++++ components/manuals-page-client.tsx | 8 +- components/public-surface.tsx | 4 +- components/request-machine-section.tsx | 6 +- components/reviews-page.tsx | 4 +- components/site-chat-widget.tsx | 20 ++-- components/ui/button.tsx | 2 +- components/ui/card.tsx | 2 +- components/vending-machines-page.tsx | 7 +- components/who-we-serve-page.tsx | 10 +- 25 files changed, 239 insertions(+), 191 deletions(-) create mode 100644 components/get-free-machine-cta.tsx diff --git a/app/[...slug]/page.tsx b/app/[...slug]/page.tsx index 6d1271e4..1d7f0345 100644 --- a/app/[...slug]/page.tsx +++ b/app/[...slug]/page.tsx @@ -18,7 +18,7 @@ import { ContactPage } from '@/components/contact-page'; import { AboutPage } from '@/components/about-page'; import { WhoWeServePage } from '@/components/who-we-serve-page'; import { PublicPageHeader, PublicSurface } from '@/components/public-surface'; -import { RequestMachineForm } from '@/components/forms/request-machine-form'; +import { GetFreeMachineCta } from '@/components/get-free-machine-cta'; // Required for static export - ensures this route is statically generated export const dynamic = 'force-static'; @@ -346,17 +346,23 @@ function renderLocationPage(locationData: any, locationSlug: string) { - {/* CRM Form */} + {/* Placement CTA */} - -
-

Get Your Free Vending Machine

-

- Tell us about your location and we'll follow up within one business day. -

+
+

Get Your Free Vending Machine

+

+ Open the Rocky placement popup and we'll follow up within one business day with the best next step for your location. +

+ - - +
@@ -404,9 +410,7 @@ function renderLocationPage(locationData: any, locationSlug: string) {
- +
diff --git a/app/service-areas/page.tsx b/app/service-areas/page.tsx index 10a410f0..6d565d50 100644 --- a/app/service-areas/page.tsx +++ b/app/service-areas/page.tsx @@ -6,6 +6,7 @@ import { businessConfig } from "@/lib/seo-config" import { MapPin, Phone, ArrowRight, Wrench, Clock } from "lucide-react" import { Button } from "@/components/ui/button" import { PublicInset, PublicPageHeader, PublicSurface } from "@/components/public-surface" +import { GetFreeMachineCta } from "@/components/get-free-machine-cta" export const metadata: Metadata = { title: "Service Areas | Vending Machines Across Utah | Rocky Mountain Vending", @@ -135,9 +136,7 @@ export default function ServiceAreasPage() {

We'll confirm delivery range, support availability, and the best intake path for your location.

- +
@@ -247,9 +246,9 @@ export default function ServiceAreasPage() { ))} - +
+ +
diff --git a/app/services/moving/page.tsx b/app/services/moving/page.tsx index 8dfd9dbf..fdebd8c8 100644 --- a/app/services/moving/page.tsx +++ b/app/services/moving/page.tsx @@ -2,10 +2,10 @@ import type { Metadata } from "next"; import Image from "next/image"; import { Card, CardContent } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; -import { PageWrapper, PageHeader } from "@/components/page-wrapper"; import { businessConfig } from "@/lib/seo-config"; import { Phone, CheckCircle2, Shield, Clock, MapPin } from "lucide-react"; import Link from "next/link"; +import { PublicPageHeader, PublicSurface } from "@/components/public-surface"; export const metadata: Metadata = { title: "Vending Machine Moving & Relocation Services | Rocky Mountain Vending", @@ -32,10 +32,12 @@ export const metadata: Metadata = { export default function MovingServicesPage() { return ( - - + {/* Introduction Section */} @@ -248,7 +250,7 @@ export default function MovingServicesPage() { {/* Why Choose Us Section */}

Why Choose Us for Your Vending Move?

- +
  • @@ -291,29 +293,27 @@ export default function MovingServicesPage() { {/* CTA Section */}
    - - -

    + +

    Ready to Schedule a Hassle-Free Vending Machine Move?

    -

    +

    Contact us today for a custom quote based on machine type, pickup/drop-off locations, access challenges, and any stairs or special requirements involved. We're here to make your relocation simple and stress-free!

    - -
    - - +

    - + ); } diff --git a/app/vending-machines-[location]/page.tsx b/app/vending-machines-[location]/page.tsx index 920d9aee..fd544a83 100644 --- a/app/vending-machines-[location]/page.tsx +++ b/app/vending-machines-[location]/page.tsx @@ -7,7 +7,7 @@ import { Card, CardContent } from "@/components/ui/card"; import { ReviewsSection } from "@/components/reviews-section"; import { Button } from "@/components/ui/button"; import Link from "next/link"; -import { RequestMachineForm } from "@/components/forms/request-machine-form"; +import { GetFreeMachineCta } from "@/components/get-free-machine-cta"; import { PublicInset, PublicPageHeader, PublicSurface } from "@/components/public-surface"; interface LocationPageProps { @@ -346,19 +346,27 @@ export default async function LocationPage({ params }: LocationPageProps) { - {/* CRM Form */} + {/* Placement CTA */}

    Get Your Free Vending Machine

    - Tell us about your location and we'll follow up within one business day to talk through the best machine mix. + Open the free placement popup and we'll follow up within one business day to talk through the best machine mix for your location.

    Free placement is for qualifying business locations. Share your foot traffic, preferred machine types, and any site constraints so our team can recommend the right setup. - +
@@ -406,9 +414,7 @@ export default async function LocationPage({ params }: LocationPageProps) {
- +
diff --git a/app/vending-machines/machines-for-sale/page.tsx b/app/vending-machines/machines-for-sale/page.tsx index 80fd165a..5bd84248 100644 --- a/app/vending-machines/machines-for-sale/page.tsx +++ b/app/vending-machines/machines-for-sale/page.tsx @@ -5,7 +5,7 @@ import { getPageBySlug } from '@/lib/wordpress-data-loader' import { cleanWordPressContent } from '@/lib/clean-wordPress-content' import type { Metadata } from 'next' import { PublicPageHeader, PublicSurface } from '@/components/public-surface' -import { RequestMachineForm } from '@/components/forms/request-machine-form' +import { GetFreeMachineCta } from '@/components/get-free-machine-cta' const WORDPRESS_SLUG = 'vending-machines-for-sale-in-utah' @@ -83,11 +83,20 @@ export default async function MachinesForSalePage() {

Free Placement

Need a free machine instead of buying one?

- If you're a business looking for placement rather than a purchase, use the request form here and we'll help you sort out the right next step. + If you're a business looking for placement rather than a purchase, open the free placement popup and we'll help you sort out the right next step.

+
+ +
- - + +
+

Need Sales Help?

+

Talk through machine sales, placement, or feature questions.

+

+ We can help with new vs. used options, payment hardware, and whether free placement or a direct purchase makes more sense for your location. +

+
diff --git a/app/vending-machines/machines-we-use/page.tsx b/app/vending-machines/machines-we-use/page.tsx index 0a162dca..9a0bb9b6 100644 --- a/app/vending-machines/machines-we-use/page.tsx +++ b/app/vending-machines/machines-we-use/page.tsx @@ -3,7 +3,7 @@ import { VendingMachinesShowcase } from '@/components/vending-machines-showcase' import { FeatureCard } from '@/components/feature-card' import type { Metadata } from 'next' import { PublicPageHeader, PublicSurface } from '@/components/public-surface' -import { RequestMachineForm } from '@/components/forms/request-machine-form' +import { GetFreeMachineCta } from '@/components/get-free-machine-cta' export async function generateMetadata(): Promise { return generateSEOMetadata({ @@ -88,10 +88,10 @@ export default async function MachinesWeUsePage() {

Free Placement

Want this kind of setup at your location?

- Use the request form here if you want free placement for a qualifying business and we'll help map out the best machine mix. + If you want free placement for a qualifying business, open the Rocky intake popup and we'll help map out the best machine mix without dropping the full form into this page.

-
- +
+
diff --git a/components/contact-page.tsx b/components/contact-page.tsx index ee95dc0b..76465a01 100644 --- a/components/contact-page.tsx +++ b/components/contact-page.tsx @@ -38,8 +38,8 @@ export function ContactPage() {
-
+
-
+
-
+
@@ -278,7 +278,7 @@ export function ContactForm({ onSubmit, className, defaultIntent = "" }: Contact
-
+
-
+
setValue("serviceTextConsent", checked, { shouldValidate: true })} - onMarketingChange={(checked) => setValue("marketingTextConsent", checked, { shouldValidate: true })} serviceError={errors.serviceTextConsent?.message} - marketingError={errors.marketingTextConsent?.message} />
-
+

Need a faster handoff?

@@ -330,14 +327,14 @@ export function ContactForm({ onSubmit, className, defaultIntent = "" }: Contact
Call Text Photos diff --git a/components/forms/form-button.tsx b/components/forms/form-button.tsx index c14c6c59..489c2d1e 100644 --- a/components/forms/form-button.tsx +++ b/components/forms/form-button.tsx @@ -16,7 +16,7 @@ const buttonVariants = cva( destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", outline: - "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50", + "border bg-white shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50", secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80", ghost: @@ -66,4 +66,4 @@ const FormButton = React.forwardRef( ) FormButton.displayName = "FormButton" -export { FormButton, buttonVariants } \ No newline at end of file +export { FormButton, buttonVariants } diff --git a/components/forms/form-input.tsx b/components/forms/form-input.tsx index 44a262b5..5f6fabce 100644 --- a/components/forms/form-input.tsx +++ b/components/forms/form-input.tsx @@ -27,7 +27,7 @@ const FormInput = React.forwardRef( type={type} data-slot="input" className={cn( - "h-12 w-full min-w-0 rounded-xl border border-border/70 bg-background/85 px-4 text-base text-foreground shadow-sm transition outline-none", + "h-12 w-full min-w-0 rounded-xl border border-border/70 bg-white px-4 text-base text-foreground shadow-sm transition outline-none", "placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground", "focus:border-primary focus:ring-4 focus:ring-primary/15 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", error ? "border-destructive focus:ring-destructive/10" : "", diff --git a/components/forms/form-select.tsx b/components/forms/form-select.tsx index 122b5842..19696544 100644 --- a/components/forms/form-select.tsx +++ b/components/forms/form-select.tsx @@ -34,7 +34,7 @@ const FormSelect = React.forwardRef( id={selectId} ref={ref} className={cn( - "h-12 w-full appearance-none rounded-xl border border-border/70 bg-background/85 px-4 pr-11 text-base text-foreground shadow-sm transition outline-none", + "h-12 w-full appearance-none rounded-xl border border-border/70 bg-white px-4 pr-11 text-base text-foreground shadow-sm transition outline-none", "focus:border-primary focus:ring-4 focus:ring-primary/15 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", error ? "border-destructive focus:ring-destructive/10" : "", className, diff --git a/components/forms/form-textarea.tsx b/components/forms/form-textarea.tsx index 202a882c..b1daf109 100644 --- a/components/forms/form-textarea.tsx +++ b/components/forms/form-textarea.tsx @@ -26,7 +26,7 @@ const FormTextarea = React.forwardRef( id={textareaId} data-slot="textarea" className={cn( - "min-h-[136px] w-full rounded-xl border border-border/70 bg-background/85 px-4 py-3 text-base text-foreground shadow-sm transition outline-none", + "min-h-[136px] w-full rounded-xl border border-border/70 bg-white px-4 py-3 text-base text-foreground shadow-sm transition outline-none", "placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground", "focus:border-primary focus:ring-4 focus:ring-primary/15 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", error ? "border-destructive focus:ring-destructive/10" : "", diff --git a/components/forms/request-machine-form.tsx b/components/forms/request-machine-form.tsx index 9f3504fe..b1d5a355 100644 --- a/components/forms/request-machine-form.tsx +++ b/components/forms/request-machine-form.tsx @@ -191,7 +191,7 @@ export function RequestMachineForm({ onSubmit, className }: RequestMachineFormPr
-
+
-
+
-
+
{MACHINE_TYPE_OPTIONS.map((option) => { const isChecked = selectedMachineTypes.includes(option.value) return (
+
Free placement intake @@ -332,7 +332,7 @@ export function RequestMachineForm({ onSubmit, className }: RequestMachineFormPr
-
+
-
+
setValue("serviceTextConsent", checked, { shouldValidate: true })} - onMarketingChange={(checked) => setValue("marketingTextConsent", checked, { shouldValidate: true })} serviceError={errors.serviceTextConsent?.message} - marketingError={errors.marketingTextConsent?.message} />
@@ -383,7 +380,7 @@ export function RequestMachineForm({ onSubmit, className }: RequestMachineFormPr Call diff --git a/components/forms/sms-consent-fields.tsx b/components/forms/sms-consent-fields.tsx index 13312191..10583596 100644 --- a/components/forms/sms-consent-fields.tsx +++ b/components/forms/sms-consent-fields.tsx @@ -32,10 +32,10 @@ function PolicyLinks() { type SmsConsentFieldsProps = { idPrefix: string - marketingChecked: boolean + marketingChecked?: boolean marketingError?: string mode?: "chat" | "forms" - onMarketingChange: (checked: boolean) => void + onMarketingChange?: (checked: boolean) => void onServiceChange: (checked: boolean) => void serviceChecked: boolean serviceError?: string @@ -43,17 +43,17 @@ type SmsConsentFieldsProps = { export function SmsConsentFields({ idPrefix, - marketingChecked, - marketingError, + marketingChecked: _marketingChecked, + marketingError: _marketingError, mode = "forms", - onMarketingChange, + onMarketingChange: _onMarketingChange, onServiceChange, serviceChecked, serviceError, }: SmsConsentFieldsProps) { return (
-
+
- I agree to receive conversational SMS from {businessConfig.legalName} about my inquiry, scheduling, - support, repairs, moving, and follow-up. Message frequency varies. Message and data rates may apply. - Reply STOP to opt out and HELP for help. Consent is not a condition of purchase. + I agree to Terms & Conditions provided by {businessConfig.legalName}. By providing my phone number, I agree + to receive text messages about my inquiry, scheduling, support, repairs, moving, and follow-up. Message + frequency varies. Message and data rates may apply. Reply STOP to opt out and HELP for help.
{serviceError ?

{serviceError}

: null} - - {mode === "forms" ? ( - <> -
- onMarketingChange(Boolean(checked))} - className="mt-0.5" - /> - -
- {marketingError ?

{marketingError}

: null} - - ) : null}
) } diff --git a/components/get-free-machine-cta.tsx b/components/get-free-machine-cta.tsx new file mode 100644 index 00000000..3c81de5f --- /dev/null +++ b/components/get-free-machine-cta.tsx @@ -0,0 +1,37 @@ +"use client" + +import { useState } from "react" +import { Button } from "@/components/ui/button" +import { GetFreeMachineModal } from "@/components/get-free-machine-modal" +import { cn } from "@/lib/utils" + +type GetFreeMachineCtaProps = { + buttonLabel?: string + className?: string + size?: "default" | "sm" | "lg" + variant?: "default" | "outline" | "secondary" | "ghost" | "link" | "brand" +} + +export function GetFreeMachineCta({ + buttonLabel = "Get Free Machine", + className, + size = "lg", + variant = "default", +}: GetFreeMachineCtaProps) { + const [isOpen, setIsOpen] = useState(false) + + return ( + <> + + + + ) +} diff --git a/components/manuals-page-client.tsx b/components/manuals-page-client.tsx index 1ca4d6f6..6ff387a6 100644 --- a/components/manuals-page-client.tsx +++ b/components/manuals-page-client.tsx @@ -565,7 +565,7 @@ export function ManualsPageClient({ placeholder="Search manuals by name, manufacturer, or category..." value={searchTerm} onChange={(e) => setSearchTerm(e.target.value)} - className="h-12 rounded-xl border-border/70 bg-background/85 pl-10 shadow-sm" + className="h-12 rounded-xl border-border/70 bg-white pl-10 shadow-sm" />
@@ -588,7 +588,7 @@ export function ManualsPageClient({ } }} > - + @@ -614,7 +614,7 @@ export function ManualsPageClient({ }} disabled={!selectedManufacturer && filteredCategories.length === categories.length} > - + @@ -665,7 +665,7 @@ export function ManualsPageClient({
View: -
+
- +
diff --git a/components/who-we-serve-page.tsx b/components/who-we-serve-page.tsx index c529909a..8b65ea63 100644 --- a/components/who-we-serve-page.tsx +++ b/components/who-we-serve-page.tsx @@ -3,6 +3,7 @@ import { ReactNode } from "react" import { Card, CardContent } from "@/components/ui/card" import { Button } from "@/components/ui/button" +import { GetFreeMachineCta } from "@/components/get-free-machine-cta" import Link from "next/link" import { CheckCircle2 } from "lucide-react" @@ -127,9 +128,11 @@ export function WhoWeServePage({ title, content }: WhoWeServePageProps) { - +
@@ -137,4 +140,3 @@ export function WhoWeServePage({ title, content }: WhoWeServePageProps) {
) } -