Rocky_Mountain_Vending/app/vending-machines/machines-for-sale/page.tsx

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()
}
}