367 lines
15 KiB
TypeScript
367 lines
15 KiB
TypeScript
import { notFound } from "next/navigation"
|
|
import type { Metadata } from "next"
|
|
import Image from "next/image"
|
|
import Link from "next/link"
|
|
import {
|
|
CheckCircle2,
|
|
CreditCard,
|
|
Refrigerator,
|
|
ShoppingCart,
|
|
} from "lucide-react"
|
|
import { generateSEOMetadata, generateStructuredData } from "@/lib/seo"
|
|
import { getPageBySlug } from "@/lib/wordpress-data-loader"
|
|
import {
|
|
PublicInset,
|
|
PublicPageHeader,
|
|
PublicSectionHeader,
|
|
PublicSurface,
|
|
} from "@/components/public-surface"
|
|
import { GetFreeMachineCta } from "@/components/get-free-machine-cta"
|
|
import { Breadcrumbs } from "@/components/breadcrumbs"
|
|
import { Button } from "@/components/ui/button"
|
|
|
|
const WORDPRESS_SLUG = "vending-machines-for-sale-in-utah"
|
|
|
|
const machineHighlights = [
|
|
"Snack, drink, combo, and card-reader-ready equipment options",
|
|
"New and used machine guidance based on traffic, budget, and product mix",
|
|
"Local help with payment hardware, installation planning, and next-step questions",
|
|
]
|
|
|
|
const machineOptions = [
|
|
{
|
|
title: "Snack and drink machines",
|
|
description:
|
|
"Traditional snack, beverage, and combo machines for breakrooms, customer spaces, and mixed-traffic locations.",
|
|
icon: ShoppingCart,
|
|
},
|
|
{
|
|
title: "Cashless payment hardware",
|
|
description:
|
|
"Card reader and mobile-payment options that help modernize older machines or support new installs.",
|
|
icon: CreditCard,
|
|
},
|
|
{
|
|
title: "Refrigerated equipment",
|
|
description:
|
|
"Cold drink and refrigerated machine options for workplaces that need dependable temperature-controlled service.",
|
|
icon: Refrigerator,
|
|
},
|
|
]
|
|
|
|
const buyingSteps = [
|
|
{
|
|
title: "Tell us about the location",
|
|
body: "We learn about traffic, available space, product needs, and whether you are comparing free placement with a direct purchase.",
|
|
},
|
|
{
|
|
title: "Compare the right machine options",
|
|
body: "We help narrow down machine styles, payment hardware, and new-versus-used tradeoffs so you are looking at realistic fits.",
|
|
},
|
|
{
|
|
title: "Plan install and support",
|
|
body: "Once you know what you want, we can talk through delivery, setup, payment configuration, and any follow-up service needs.",
|
|
},
|
|
]
|
|
|
|
function normalizeWpImageUrl(url?: string) {
|
|
if (!url) return null
|
|
return url.replace("https:///", "https://rockymountainvending.com/")
|
|
}
|
|
|
|
export async function generateMetadata(): Promise<Metadata> {
|
|
const page = getPageBySlug(WORDPRESS_SLUG)
|
|
|
|
if (!page) {
|
|
return {
|
|
title: "Page Not Found | Rocky Mountain Vending",
|
|
}
|
|
}
|
|
|
|
return generateSEOMetadata({
|
|
title: page.title || "Vending Machines for Sale in Utah",
|
|
description: page.seoDescription || page.excerpt || "",
|
|
excerpt: page.excerpt,
|
|
date: page.date,
|
|
modified: page.modified,
|
|
image: page.images?.[0]?.localPath,
|
|
path: "/vending-machines/machines-for-sale",
|
|
})
|
|
}
|
|
|
|
export default async function MachinesForSalePage() {
|
|
try {
|
|
const page = getPageBySlug(WORDPRESS_SLUG)
|
|
|
|
if (!page) {
|
|
notFound()
|
|
}
|
|
|
|
const structuredData = (() => {
|
|
try {
|
|
return generateStructuredData({
|
|
title: page.title || "Vending Machines for Sale in Utah",
|
|
description: page.seoDescription || page.excerpt || "",
|
|
url:
|
|
page.link ||
|
|
page.urlPath ||
|
|
"https://rockymountainvending.com/vending-machines/machines-for-sale/",
|
|
datePublished: page.date,
|
|
dateModified: page.modified || page.date,
|
|
type: "WebPage",
|
|
})
|
|
} catch {
|
|
return {
|
|
"@context": "https://schema.org",
|
|
"@type": "WebPage",
|
|
headline: page.title || "Vending Machines for Sale in Utah",
|
|
description: page.seoDescription || "",
|
|
url: "https://rockymountainvending.com/vending-machines/machines-for-sale/",
|
|
}
|
|
}
|
|
})()
|
|
|
|
const heroImage =
|
|
normalizeWpImageUrl(page.images?.[0]?.url) ??
|
|
"https://rockymountainvending.com/wp-content/uploads/2024/01/EH0A1551-HDR.webp"
|
|
const comboImage =
|
|
normalizeWpImageUrl(page.images?.[1]?.url) ??
|
|
"https://rockymountainvending.com/wp-content/uploads/2022/06/Seage-HY900-Combo.webp"
|
|
const paymentImage =
|
|
normalizeWpImageUrl(page.images?.[2]?.url) ??
|
|
"https://rockymountainvending.com/wp-content/uploads/2024/01/Parlevel-Pay-Plus.jpg"
|
|
|
|
return (
|
|
<>
|
|
<script
|
|
type="application/ld+json"
|
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(structuredData) }}
|
|
/>
|
|
<div className="container mx-auto px-4 py-10 md:py-14">
|
|
<Breadcrumbs
|
|
className="mb-6"
|
|
items={[
|
|
{ label: "Vending Machines", href: "/vending-machines" },
|
|
{
|
|
label: "Machines for Sale",
|
|
href: "/vending-machines/machines-for-sale",
|
|
},
|
|
]}
|
|
/>
|
|
<PublicPageHeader
|
|
align="center"
|
|
eyebrow="Machine Sales"
|
|
title="Compare vending machines, payment hardware, and purchase options with a local Utah team."
|
|
description="If you are looking at buying equipment instead of free placement, we can help you compare machine styles, payment systems, and next-step support without sending you through a generic catalog dump."
|
|
>
|
|
<div className="flex flex-col items-center justify-center gap-3 sm:flex-row">
|
|
<Button asChild size="lg" className="min-h-11 rounded-full px-6">
|
|
<Link href="/contact-us#contact-form">Ask About Sales</Link>
|
|
</Button>
|
|
<Button
|
|
asChild
|
|
size="lg"
|
|
variant="outline"
|
|
className="min-h-11 rounded-full px-6"
|
|
>
|
|
<Link href="/products">Browse Product Listings</Link>
|
|
</Button>
|
|
</div>
|
|
</PublicPageHeader>
|
|
|
|
<section className="mt-10 grid gap-6 xl:grid-cols-[1.05fr_0.95fr]">
|
|
<PublicSurface className="flex h-full flex-col justify-center">
|
|
<p className="text-xs font-semibold uppercase tracking-[0.2em] text-primary/80">
|
|
Sales Overview
|
|
</p>
|
|
<h2 className="mt-3 text-3xl font-semibold tracking-tight text-balance">
|
|
Buying a machine should feel clear before you spend money.
|
|
</h2>
|
|
<p className="mt-4 text-base leading-7 text-muted-foreground md:text-lg md:leading-8">
|
|
We help Utah businesses sort through machine type, payment
|
|
hardware, and install considerations so you can decide whether a
|
|
direct purchase is the right move for your location.
|
|
</p>
|
|
<ul className="mt-6 space-y-3">
|
|
{machineHighlights.map((highlight) => (
|
|
<li key={highlight} className="flex items-start gap-3">
|
|
<CheckCircle2 className="mt-0.5 h-5 w-5 shrink-0 text-primary" />
|
|
<span className="text-sm leading-6 text-foreground md:text-base">
|
|
{highlight}
|
|
</span>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</PublicSurface>
|
|
<div className="relative min-h-[320px] overflow-hidden rounded-[var(--public-surface-radius)] border border-border/65 bg-[linear-gradient(180deg,rgba(255,255,255,0.98),rgba(255,249,240,0.96))] p-3 shadow-[0_20px_52px_rgba(15,23,42,0.075)]">
|
|
<Image
|
|
src={heroImage}
|
|
alt="Vending machine option available for sale in Utah"
|
|
fill
|
|
className="rounded-[calc(var(--public-surface-radius)-0.45rem)] object-cover"
|
|
sizes="(max-width: 1280px) 100vw, 560px"
|
|
priority
|
|
/>
|
|
</div>
|
|
</section>
|
|
|
|
<section className="mt-12">
|
|
<PublicSectionHeader
|
|
eyebrow="Machine Options"
|
|
title="What businesses usually want help comparing"
|
|
description="Most sales conversations come down to the machine type, payment setup, and whether a direct purchase makes more sense than placement."
|
|
className="mx-auto mb-8 max-w-3xl text-center"
|
|
/>
|
|
<div className="grid gap-4 lg:grid-cols-3">
|
|
{machineOptions.map((option) => {
|
|
const Icon = option.icon
|
|
return (
|
|
<PublicInset key={option.title} className="h-full p-5 md:p-6">
|
|
<div className="flex h-11 w-11 items-center justify-center rounded-full bg-primary/10 text-primary">
|
|
<Icon className="h-5 w-5" />
|
|
</div>
|
|
<h3 className="mt-4 text-xl font-semibold tracking-tight text-foreground">
|
|
{option.title}
|
|
</h3>
|
|
<p className="mt-3 text-sm leading-6 text-muted-foreground md:text-base">
|
|
{option.description}
|
|
</p>
|
|
</PublicInset>
|
|
)
|
|
})}
|
|
</div>
|
|
</section>
|
|
|
|
<section className="mt-12 grid gap-6 lg:grid-cols-[0.98fr_1.02fr]">
|
|
<PublicSurface className="overflow-hidden p-0">
|
|
<div className="grid gap-0 md:grid-cols-2">
|
|
<div className="relative min-h-[260px]">
|
|
<Image
|
|
src={comboImage}
|
|
alt="Combo vending machine for sale"
|
|
fill
|
|
className="object-cover"
|
|
sizes="(max-width: 768px) 100vw, 360px"
|
|
/>
|
|
</div>
|
|
<div className="flex flex-col justify-center p-5 md:p-6">
|
|
<p className="text-xs font-semibold uppercase tracking-[0.2em] text-primary/80">
|
|
New vs. Used
|
|
</p>
|
|
<h2 className="mt-3 text-2xl font-semibold tracking-tight text-balance">
|
|
We can help you sort through budget, features, and condition.
|
|
</h2>
|
|
<p className="mt-3 text-sm leading-6 text-muted-foreground md:text-base">
|
|
Some buyers need dependable starter equipment. Others need a
|
|
cleaner, more modern machine with stronger payment support.
|
|
We can talk through both without pushing you into the wrong
|
|
setup.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</PublicSurface>
|
|
<PublicSurface className="overflow-hidden p-0">
|
|
<div className="grid gap-0 md:grid-cols-2">
|
|
<div className="order-2 flex flex-col justify-center p-5 md:order-1 md:p-6">
|
|
<p className="text-xs font-semibold uppercase tracking-[0.2em] text-primary/80">
|
|
Payment Hardware
|
|
</p>
|
|
<h2 className="mt-3 text-2xl font-semibold tracking-tight text-balance">
|
|
Card readers and cashless upgrades are often part of the decision.
|
|
</h2>
|
|
<p className="mt-3 text-sm leading-6 text-muted-foreground md:text-base">
|
|
If you are trying to modernize how people pay, we can help
|
|
you think through card readers, mobile payments, and
|
|
compatibility before you commit to a machine.
|
|
</p>
|
|
</div>
|
|
<div className="relative order-1 min-h-[260px] md:order-2">
|
|
<Image
|
|
src={paymentImage}
|
|
alt="Cashless payment hardware for vending machines"
|
|
fill
|
|
className="object-cover"
|
|
sizes="(max-width: 768px) 100vw, 360px"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</PublicSurface>
|
|
</section>
|
|
|
|
<section className="mt-12">
|
|
<PublicSectionHeader
|
|
eyebrow="Buying Process"
|
|
title="A simpler way to move from questions to a real option"
|
|
description="You do not need to have the exact model picked out before you reach out. Most of the work is narrowing to the right fit."
|
|
className="mx-auto mb-8 max-w-3xl text-center"
|
|
/>
|
|
<div className="grid gap-4 lg:grid-cols-3">
|
|
{buyingSteps.map((step, index) => (
|
|
<PublicInset key={step.title} className="h-full p-5 md:p-6">
|
|
<div className="flex h-12 w-12 items-center justify-center rounded-full bg-primary text-lg font-semibold text-primary-foreground">
|
|
{index + 1}
|
|
</div>
|
|
<h3 className="mt-4 text-xl font-semibold tracking-tight text-foreground">
|
|
{step.title}
|
|
</h3>
|
|
<p className="mt-3 text-sm leading-6 text-muted-foreground md:text-base">
|
|
{step.body}
|
|
</p>
|
|
</PublicInset>
|
|
))}
|
|
</div>
|
|
</section>
|
|
|
|
<section className="mt-12 grid gap-6 lg:grid-cols-[0.95fr_1.05fr]">
|
|
<PublicSurface>
|
|
<p className="text-xs font-semibold uppercase tracking-[0.2em] text-primary/80">
|
|
Free Placement
|
|
</p>
|
|
<h2 className="mt-3 text-3xl font-semibold tracking-tight text-balance">
|
|
Need a free machine instead of buying one?
|
|
</h2>
|
|
<p className="mt-3 text-base leading-relaxed text-muted-foreground">
|
|
If you are a business looking for placement instead of a
|
|
purchase, we can help you figure out whether your location is a
|
|
fit before you spend money on equipment.
|
|
</p>
|
|
<div className="mt-6">
|
|
<GetFreeMachineCta buttonLabel="Get Free Placement" />
|
|
</div>
|
|
</PublicSurface>
|
|
<PublicSurface className="flex items-center justify-center text-center">
|
|
<div className="max-w-xl">
|
|
<p className="text-sm font-semibold uppercase tracking-[0.18em] text-primary/80">
|
|
Need Sales Help?
|
|
</p>
|
|
<h3 className="mt-3 text-2xl font-semibold tracking-tight text-balance">
|
|
Talk through machine sales, placement, or payment questions.
|
|
</h3>
|
|
<p className="mt-3 text-sm leading-relaxed text-muted-foreground">
|
|
We can help with new vs. used options, payment hardware, and
|
|
whether free placement or a direct purchase makes more sense
|
|
for your location.
|
|
</p>
|
|
<div className="mt-6">
|
|
<Button
|
|
asChild
|
|
size="lg"
|
|
variant="outline"
|
|
className="min-h-11 rounded-full px-6"
|
|
>
|
|
<Link href="/contact-us#contact-form">Talk to Sales</Link>
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</PublicSurface>
|
|
</section>
|
|
</div>
|
|
</>
|
|
)
|
|
} catch (error) {
|
|
if (process.env.NODE_ENV === "development") {
|
|
console.error("Error rendering Machines for Sale page:", error)
|
|
}
|
|
notFound()
|
|
}
|
|
}
|