Rocky_Mountain_Vending/app/service-areas/page.tsx

346 lines
13 KiB
TypeScript

import type { Metadata } from "next"
import Link from "next/link"
import Image from "next/image"
import { getAllLocations } from "@/lib/location-data"
import { generateSEOMetadata } from "@/lib/seo"
import { businessConfig } from "@/lib/seo-config"
import { MapPin, Phone, ArrowRight, Wrench, Clock } from "lucide-react"
import {
PublicInset,
PublicPageHeader,
PublicSurface,
} from "@/components/public-surface"
import { GetFreeMachineCta } from "@/components/get-free-machine-cta"
export const metadata: Metadata = generateSEOMetadata({
title: "Utah Service Areas | Rocky Mountain Vending",
description:
"See the Utah cities and counties Rocky Mountain Vending serves for free placement, machine sales, repairs, moving, parts, and ongoing vending service.",
path: "/service-areas",
keywords: [
"Utah vending service areas",
"vending machine service areas Utah",
"Salt Lake City vending company",
],
})
function LocationCard({
city,
zipCode,
href,
neighborhoods,
}: {
city: string
zipCode: string
href: string
neighborhoods: string[]
}) {
return (
<Link href={href} className="group block h-full">
<PublicSurface className="h-full p-5 transition-all hover:-translate-y-0.5 hover:shadow-[0_26px_65px_rgba(0,0,0,0.12)] md:p-6">
<div className="flex items-start justify-between gap-4">
<div className="space-y-1">
<h3 className="text-xl font-semibold text-foreground transition-colors group-hover:text-primary">
{city}
</h3>
<p className="text-sm text-muted-foreground">{zipCode}</p>
</div>
<div className="rounded-full border border-border/60 bg-background/90 p-2 text-muted-foreground transition-all group-hover:border-primary/30 group-hover:text-primary group-hover:translate-x-0.5">
<ArrowRight className="h-4 w-4" />
</div>
</div>
<PublicInset className="mt-5">
<p className="text-xs font-semibold uppercase tracking-[0.18em] text-primary/75">
Popular Areas
</p>
<p className="mt-2 text-sm leading-relaxed text-muted-foreground">
{neighborhoods.slice(0, 2).join(", ")}
</p>
</PublicInset>
</PublicSurface>
</Link>
)
}
export default function ServiceAreasPage() {
const locations = getAllLocations()
const state = "Utah"
const saltLakeCounty = locations.filter((loc) =>
[
"salt-lake-city-utah",
"sandy-utah",
"draper-utah",
"murray-utah",
"midvale-utah",
"south-salt-lake-utah",
"west-valley-city-utah",
"west-jordan-utah",
"south-jordan-utah",
"riverton-utah",
"herriman-utah",
"holladay-utah",
"millcreek-utah",
"cottonwood-heights-utah",
].includes(loc.slug)
)
const davisCounty = locations.filter((loc) =>
[
"ogden-utah",
"layton-utah",
"clearfield-utah",
"syracuse-utah",
"clinton-utah",
].includes(loc.slug)
)
const utahCounty = locations.filter((loc) =>
["provo-utah"].includes(loc.slug)
)
return (
<div className="container mx-auto px-4 py-10 md:py-14">
<PublicPageHeader
align="center"
eyebrow="Service Coverage"
title="Utah locations we serve with vending, repairs, parts, and machine service."
description="Rocky Mountain Vending currently runs service routes across Salt Lake, Davis, and Utah counties, with free placement for qualifying locations, machine sales, repairs, parts, and ongoing restocking and service."
/>
<div className="mt-10 grid gap-6 lg:grid-cols-[1.1fr_0.9fr]">
<PublicSurface>
<div className="relative aspect-[926/1024] overflow-hidden rounded-[1.5rem] bg-[radial-gradient(circle_at_top_left,rgba(196,154,52,0.16),transparent_55%),linear-gradient(180deg,rgba(247,244,236,0.7),rgba(255,255,255,0.96))]">
<Image
src="/images/rocky-mountain-vending-service-area-926x1024.webp"
alt="Rocky Mountain Vending service area map covering Salt Lake City, Ogden, Provo and surrounding Utah cities"
fill
className="object-cover"
/>
</div>
</PublicSurface>
<PublicSurface className="flex flex-col justify-between">
<div>
<p className="text-xs font-semibold uppercase tracking-[0.2em] text-primary/80">
Need Coverage Confirmation?
</p>
<h2 className="mt-3 text-3xl font-semibold tracking-tight text-balance text-foreground">
Don&apos;t see your city yet?
</h2>
<p className="mt-3 text-base leading-relaxed text-muted-foreground">
If you&apos;re close to one of our current routes, we may still
be able to help. Reach out and we&apos;ll confirm whether your
location fits our current coverage and service schedule.
</p>
</div>
<div className="mt-6 space-y-4">
<PublicInset>
<a
href={businessConfig.phoneUrl}
className="flex items-center gap-3 text-base font-semibold text-foreground transition hover:text-primary"
>
<Phone className="h-5 w-5 text-primary" />
{businessConfig.phone}
</a>
<p className="mt-2 text-sm text-muted-foreground">
Tell us where you&apos;re located and what kind of vending help
you need, and we&apos;ll let you know what coverage looks like
for your area.
</p>
</PublicInset>
<GetFreeMachineCta
buttonLabel="See If My Location Qualifies"
className="h-11 px-5"
/>
</div>
</PublicSurface>
</div>
<section className="mt-12">
<PublicSurface>
<div className="text-center">
<p className="text-xs font-semibold uppercase tracking-[0.2em] text-primary/80">
Core Services
</p>
<h2 className="mt-3 text-3xl font-semibold tracking-tight text-balance md:text-4xl">
Our vending machine services across {state}
</h2>
<p className="mx-auto mt-3 max-w-2xl text-base leading-relaxed text-muted-foreground">
From free placement and machine sales to repairs, moving, and
parts help, we help Utah businesses keep vending available
without having to manage the machines themselves.
</p>
</div>
<div className="mt-8 grid gap-5 md:grid-cols-3">
{[
{
icon: Wrench,
title: "Repairs",
body: "Expert repair and maintenance for snack, beverage, food, and combo machines.",
href: "/services/repairs",
cta: "See repair service",
},
{
icon: MapPin,
title: "Parts",
body: "Replacement parts, manuals, and machine resources for major vending brands.",
href: "/services/parts",
cta: "Shop parts",
},
{
icon: Clock,
title: "Moving",
body: "Professional machine moving for vending machines and related equipment across Utah.",
href: "/services/moving",
cta: "Moving services",
},
].map((service) => (
<PublicInset
key={service.title}
className="h-full p-5 text-center"
>
<div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-primary/10 text-primary">
<service.icon className="h-6 w-6" />
</div>
<h3 className="mt-4 text-xl font-semibold">{service.title}</h3>
<p className="mt-2 text-sm leading-relaxed text-muted-foreground">
{service.body}
</p>
<Link
href={service.href}
className="mt-5 inline-flex items-center gap-2 text-sm font-medium text-primary hover:underline"
>
{service.cta}
<ArrowRight className="h-4 w-4" />
</Link>
</PublicInset>
))}
</div>
</PublicSurface>
</section>
<section className="mt-12 space-y-12">
{[
{
title: "Salt Lake County",
description:
"Serving a wide range of offices, schools, gyms, and workplaces across the Salt Lake County route.",
items: saltLakeCounty,
},
{
title: "Davis County",
description:
"Serving businesses from Ogden to Layton with reliable vending service and repairs.",
items: davisCounty,
},
{
title: "Utah County",
description:
"Serving Provo and nearby Utah County locations with vending placement, service, and repairs.",
items: utahCounty,
},
].map((section) => (
<div key={section.title} className="space-y-5">
<div>
<p className="text-xs font-semibold uppercase tracking-[0.2em] text-primary/80">
Coverage Area
</p>
<h2 className="mt-2 text-3xl font-semibold tracking-tight text-balance">
{section.title}
</h2>
<p className="mt-2 max-w-3xl text-base leading-relaxed text-muted-foreground">
{section.description}
</p>
</div>
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
{section.items.map((location) => (
<LocationCard
key={location.slug}
city={location.city}
zipCode={location.zipCode}
href={`/vending-machines-${location.slug}`}
neighborhoods={location.neighborhoods}
/>
))}
</div>
</div>
))}
</section>
<section className="mt-12 grid gap-6 lg:grid-cols-[1.15fr_0.85fr]">
<PublicSurface>
<h2 className="text-3xl font-semibold tracking-tight text-balance">
Why businesses choose Rocky Mountain Vending
</h2>
<div className="mt-6 grid gap-5 md:grid-cols-2">
{[
[
"Free placement for qualifying locations",
"If the location qualifies, we can place and service machines without charging upfront machine or installation fees.",
],
[
"Delivery and installation",
"Within our current routes, we handle setup, stocking, and launch so the machines are ready to use.",
],
[
"Repairs and routine service",
"We keep machines running, stocked, and clean so your team deals with fewer interruptions.",
],
[
"Healthy and traditional options",
"We match the product mix to the people who will actually use the machines every day.",
],
].map(([title, body]) => (
<PublicInset key={title}>
<h3 className="text-lg font-semibold text-foreground">
{title}
</h3>
<p className="mt-2 text-sm leading-relaxed text-muted-foreground">
{body}
</p>
</PublicInset>
))}
</div>
<div className="mt-6">
<GetFreeMachineCta
buttonLabel="See If Your Location Qualifies"
className="h-11 px-5"
/>
</div>
</PublicSurface>
<PublicSurface>
<h2 className="text-3xl font-semibold tracking-tight text-balance">
The types of locations we commonly serve
</h2>
<div className="mt-6 space-y-4">
{[
[
"For businesses",
"Offices, warehouses, auto shops, and other workplaces that want reliable on-site vending.",
],
[
"For schools",
"Snacks and drinks for students and staff with service that does not add more work to school staff.",
],
[
"For gyms and fitness spaces",
"Protein bars, sports drinks, and post-workout options that match the traffic and audience at the location.",
],
].map(([title, body]) => (
<PublicInset key={title}>
<h3 className="text-lg font-semibold">{title}</h3>
<p className="mt-2 text-sm leading-relaxed text-muted-foreground">
{body}
</p>
</PublicInset>
))}
</div>
</PublicSurface>
</section>
</div>
)
}