Rocky_Mountain_Vending/app/services/parts/page.tsx

1018 lines
46 KiB
TypeScript

import { notFound } from "next/navigation"
import Link from "next/link"
import { loadImageMapping, cleanHtmlEntities } from "@/lib/wordpress-content"
import { generateRegistryMetadata, generateRegistryStructuredData } from "@/lib/seo"
import { getPageBySlug } from "@/lib/wordpress-data-loader"
import { cleanWordPressContent } from "@/lib/clean-wordPress-content"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Separator } from "@/components/ui/separator"
import { Button } from "@/components/ui/button"
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion"
import {
CheckCircle2,
Package,
Wrench,
Phone,
ShoppingCart,
ArrowRight,
MapPin,
Truck,
Award,
Users,
DollarSign,
Search,
CreditCard,
} from "lucide-react"
import { FAQSection } from "@/components/faq-section"
import { Breadcrumbs } from "@/components/breadcrumbs"
import {
PublicPageHeader,
PublicSectionHeader,
PublicSurface,
} from "@/components/public-surface"
import type { Metadata } from "next"
const WORDPRESS_SLUG = "parts-and-support"
export async function generateMetadata(): Promise<Metadata> {
const page = getPageBySlug(WORDPRESS_SLUG)
if (!page) {
return {
title: "Vending Machine Parts & Support | Rocky Mountain Vending",
description:
"Vending machine parts and support services in Utah. Replacement parts for all major vending machine brands.",
}
}
return generateRegistryMetadata("parts", {
date: page.date,
modified: page.modified,
image: page.images?.[0]?.localPath,
})
}
export default async function PartsPage() {
try {
const page = getPageBySlug(WORDPRESS_SLUG)
if (!page) {
notFound()
}
let imageMapping: any = {}
try {
imageMapping = loadImageMapping()
} catch (e) {
imageMapping = {}
}
// Extract FAQs from content (similar to repairs page)
const faqs: Array<{ question: string; answer: string }> = []
let contentWithoutFAQs = page.content || ""
let contentWithoutBrands = ""
if (page.content) {
const contentStr = String(page.content)
// Simple FAQ extraction - adjust regex based on content structure
const questionMatches = contentStr.matchAll(
/<h[2-4][^>]*>([^<]+?)<\/h[2-4]>/gi
)
const potentialAnswers = contentStr
.split(/<h[2-4][^>]*>/)
.map((section, index) => {
if (index > 0 && section.trim()) {
return section.split(/<h[2-4][^>]*>/)[0].trim()
}
return null
})
.filter(Boolean)
// Basic matching - this may need refinement based on actual content
const questions = Array.from(questionMatches)
.map((m) => m[1].trim())
.filter(
(q) =>
q.toLowerCase().includes("?") ||
q.includes("What") ||
q.includes("How")
)
questions
.slice(0, Math.min(questions.length, potentialAnswers.length))
.forEach((question, index) => {
if (potentialAnswers[index]) {
const cleanQuestion = question
.replace(/&#039;/g, "'")
.replace(/&quot;/g, '"')
.trim()
faqs.push({
question: cleanQuestion,
answer: potentialAnswers[index],
})
}
})
// Remove FAQ-like sections if found
if (faqs.length > 0) {
contentWithoutFAQs = contentStr
.replace(
/<h[2-4][^>]*>.*?Questions.*?<\/h[2-4]>([\s\S]*?)(?=<h[2-4]|$)/i,
""
)
.trim()
}
// Remove brands sections from content (we'll show them in accordion instead)
// Match various patterns for brands sections
const brandsPatterns = [
/<h[2-4][^>]*>.*?Compatible.*?Brands.*?<\/h[2-4]>[\s\S]*?(?=<h[2-4]|$)/gi,
/<h[2-4][^>]*>.*?Vending.*?Machine.*?Brands.*?<\/h[2-4]>[\s\S]*?(?=<h[2-4]|$)/gi,
/<h[2-4][^>]*>.*?Card.*?Reader.*?Brands.*?<\/h[2-4]>[\s\S]*?(?=<h[2-4]|$)/gi,
/<h[2-4][^>]*>.*?Bill.*?Validator.*?<\/h[2-4]>[\s\S]*?(?=<h[2-4]|$)/gi,
/<h[2-4][^>]*>.*?Coin.*?Mechanism.*?<\/h[2-4]>[\s\S]*?(?=<h[2-4]|$)/gi,
]
contentWithoutBrands = contentWithoutFAQs
brandsPatterns.forEach((pattern) => {
contentWithoutBrands = contentWithoutBrands.replace(pattern, "").trim()
})
// Remove "Available Parts Include" section (we'll show it in a card)
// Match various patterns - heading, paragraph, lists, etc. - be very aggressive
const availablePartsPatterns = [
// Match heading followed by content until next heading or end
/<h[1-6][^>]*>.*?Available.*?Parts.*?Include.*?<\/h[1-6]>[\s\S]*?(?=<h[1-6]|$)/gi,
// Match paragraph with the text
/<p[^>]*>.*?Available.*?Parts.*?Include.*?<\/p>[\s\S]*?(?=<h[1-6]|$)/gi,
// Match the text anywhere followed by parts list
/Available Parts Include:?[\s\S]*?(?=Don.*?see|Compatible|Why Choose|Local Expertise|Fast Delivery|<h[1-6]|$)/gi,
// Match any div/section containing the parts list items
/<div[^>]*>[\s\S]*?Bill validators and coin mechanisms[\s\S]*?Card readers for cashless payments[\s\S]*?<\/div>/gi,
/<section[^>]*>[\s\S]*?Bill validators and coin mechanisms[\s\S]*?Card readers for cashless payments[\s\S]*?<\/section>/gi,
]
availablePartsPatterns.forEach((pattern) => {
contentWithoutBrands = contentWithoutBrands.replace(pattern, "").trim()
})
// Remove individual parts list items if they appear as separate elements
const partsItems = [
"Bill validators and coin mechanisms",
"Card readers for cashless payments",
"Refrigeration components",
"Keypads and control boards",
"Motors and actuators",
"Vending machine locks and security components",
"Shelves, trays, and spirals for product dispensing",
"LED lighting upgrades",
"Replacement doors and panels",
"Electrical components",
]
// Remove any list items or paragraphs containing these specific parts
partsItems.forEach((item) => {
const itemPattern = new RegExp(
`<li[^>]*>.*?${item.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}.*?<\/li>`,
"gi"
)
contentWithoutBrands = contentWithoutBrands
.replace(itemPattern, "")
.trim()
const paraPattern = new RegExp(
`<p[^>]*>.*?${item.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}.*?<\/p>`,
"gi"
)
contentWithoutBrands = contentWithoutBrands
.replace(paraPattern, "")
.trim()
})
// Remove "Don't see the part you need?" paragraph if it's standalone
contentWithoutBrands = contentWithoutBrands
.replace(
/<p[^>]*>.*?Don.*?see.*?part.*?need.*?contact.*?us.*?<\/p>/gi,
""
)
.trim()
// Remove "Why Choose" section (we have it as a card below)
const whyChoosePatterns = [
/<h[1-6][^>]*>.*?Why.*?Choose.*?Rocky.*?Mountain.*?Vending.*?<\/h[1-6]>[\s\S]*?(?=<h[1-6]|$)/gi,
/<h[1-6][^>]*>.*?Why.*?Choose.*?<\/h[1-6]>[\s\S]*?(?=<h[1-6]|$)/gi,
/Why Choose Rocky Mountain Vending[\s\S]*?(?=Local Expertise|Fast Delivery|Quality|Expert|Competitive|Custom|<h[1-6]|$)/gi,
]
whyChoosePatterns.forEach((pattern) => {
contentWithoutBrands = contentWithoutBrands.replace(pattern, "").trim()
})
// Remove the benefits list items if they appear
const benefitsItems = [
"Local Expertise",
"Fast Delivery",
"Quality Assurance",
"Expert Support",
"Competitive Pricing",
"Custom Solutions",
]
benefitsItems.forEach((item) => {
const benefitPattern = new RegExp(
`<li[^>]*>.*?${item.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}.*?<\/li>`,
"gi"
)
contentWithoutBrands = contentWithoutBrands
.replace(benefitPattern, "")
.trim()
const paraPattern = new RegExp(
`<p[^>]*>.*?${item.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}.*?<\/p>`,
"gi"
)
contentWithoutBrands = contentWithoutBrands
.replace(paraPattern, "")
.trim()
})
// Remove duplicate opening paragraph that matches excerpt/description
// This removes the intro paragraph that duplicates what's in the hero section
// Match the exact paragraph with ellipsis entity and variations
const duplicateIntroPatterns = [
// Match paragraph with ellipsis entity [&hellip;]
/<p[^>]*>.*?Vending Machine Parts.*?Rocky Mountain Vending.*?trusted source.*?high-quality.*?vending machine parts.*?Salt Lake City.*?surrounding areas.*?Whether you need replacement components.*?\[&hellip;\].*?<\/p>/gi,
/<p[^>]*>.*?Vending Machine Parts.*?Rocky Mountain Vending.*?trusted source.*?high-quality.*?vending machine parts.*?Salt Lake City.*?\[&hellip;\].*?<\/p>/gi,
// Match without "Vending Machine Parts" prefix but with same content
/<p[^>]*>.*?Rocky Mountain Vending.*?trusted source.*?high-quality.*?vending machine parts.*?Salt Lake City.*?surrounding areas.*?Whether you need replacement components.*?\[&hellip;\].*?<\/p>/gi,
/<p[^>]*>.*?Rocky Mountain Vending.*?trusted source.*?high-quality.*?vending machine parts.*?Salt Lake City.*?Whether you need replacement components.*?\[&hellip;\].*?<\/p>/gi,
// Match without ellipsis but with full text
/<p[^>]*>.*?Vending Machine Parts.*?Rocky Mountain Vending.*?trusted source.*?high-quality.*?vending machine parts.*?Salt Lake City.*?surrounding areas.*?Whether you need replacement components.*?repairs or upgrades.*?we.*?got you covered.*?<\/p>/gi,
/<p[^>]*>.*?Rocky Mountain Vending.*?trusted source.*?high-quality.*?vending machine parts.*?Salt Lake City.*?surrounding areas.*?Whether you need replacement components.*?repairs or upgrades.*?we.*?got you covered.*?<\/p>/gi,
// Match with "about us've got you covered" typo
/<p[^>]*>.*?Rocky Mountain Vending.*?trusted source.*?high-quality.*?vending machine parts.*?Salt Lake City.*?surrounding areas.*?Whether you need replacement components.*?about us.*?got you covered.*?<\/p>/gi,
// Match with minimal overlap
/<p[^>]*>.*?Vending Machine Parts.*?Rocky Mountain Vending.*?trusted source.*?Whether you need replacement components.*?<\/p>/gi,
/<p[^>]*>.*?Rocky Mountain Vending.*?trusted source.*?Whether you need replacement components.*?<\/p>/gi,
]
duplicateIntroPatterns.forEach((pattern) => {
contentWithoutBrands = contentWithoutBrands.replace(pattern, "").trim()
})
// Remove redundant "Vending Machine Parts" heading if it's just a duplicate of the page title
contentWithoutBrands = contentWithoutBrands
.replace(
/<h[1-6][^>]*>.*?Vending Machine Parts.*?<\/h[1-6]>\s*(?=<p[^>]*>.*?Rocky Mountain Vending.*?trusted source)/gi,
""
)
.trim()
contentWithoutBrands = contentWithoutBrands
.replace(/<h[1-6][^>]*>.*?Vending Machine Parts.*?<\/h[1-6]>\s*$/gi, "")
.trim()
// Remove image references that are just placeholders or duplicates
contentWithoutBrands = contentWithoutBrands
.replace(/<img[^>]*alt=["']Vending machine image["'][^>]*>/gi, "")
.trim()
contentWithoutBrands = contentWithoutBrands
.replace(
/<figure[^>]*>[\s\S]*?Vending machine image[\s\S]*?<\/figure>/gi,
""
)
.trim()
contentWithoutBrands = contentWithoutBrands
.replace(/<div[^>]*>[\s\S]*?Vending machine image[\s\S]*?<\/div>/gi, "")
.trim()
// Remove any remaining empty paragraphs or divs
contentWithoutBrands = contentWithoutBrands
.replace(/<p[^>]*>\s*<\/p>/gi, "")
.trim()
contentWithoutBrands = contentWithoutBrands
.replace(/<div[^>]*>\s*<\/div>/gi, "")
.trim()
// Clean up multiple consecutive line breaks
contentWithoutBrands = contentWithoutBrands
.replace(/\n\s*\n\s*\n/g, "\n\n")
.trim()
// Remove ellipsis entities and other HTML entities that shouldn't be displayed
contentWithoutBrands = contentWithoutBrands
.replace(/\[&hellip;\]/gi, "")
.trim()
contentWithoutBrands = contentWithoutBrands
.replace(/&hellip;/gi, "")
.trim()
// Remove any remaining HTML tags that are just showing as text (malformed)
// This handles cases where HTML tags are being displayed as text instead of being rendered
contentWithoutBrands = contentWithoutBrands
.replace(/&lt;p&gt;/gi, "")
.trim()
contentWithoutBrands = contentWithoutBrands
.replace(/&lt;\/p&gt;/gi, "")
.trim()
contentWithoutBrands = contentWithoutBrands
.replace(/&lt;\/?[^&]+&gt;/gi, "")
.trim()
} else {
contentWithoutBrands = contentWithoutFAQs
}
// Only show content if there's meaningful content (more than just whitespace and minimal text)
const hasMeaningfulContent =
contentWithoutBrands &&
contentWithoutBrands.trim().length > 100 &&
!contentWithoutBrands.match(/^[\s\n\r]*$/)
const content = hasMeaningfulContent ? (
<div className="max-w-none">
{cleanWordPressContent(String(contentWithoutBrands), {
imageMapping,
pageTitle: page.title,
})}
</div>
) : null
const structuredData = generateRegistryStructuredData("parts", {
datePublished: page.date,
dateModified: page.modified || page.date,
})
const cleanExcerpt = page.excerpt
? cleanHtmlEntities(page.excerpt)
.replace(/&hellip;/g, "...")
.replace(/\[&hellip;\]/g, "...")
.replace(/\[\.\.\.\]/g, "...")
.replace(/\[\.\.\./g, "...")
.replace(/\.\.\.\]/g, "...")
.replace(/\[\.\.\./g, "...")
.replace(/\[\.\./g, "...")
.replace(/\.\.\]/g, "...")
.trim()
: ""
const surfaceCardClass =
"rounded-[var(--public-surface-radius)] border border-border/70 bg-[linear-gradient(180deg,rgba(255,255,255,0.98),rgba(255,251,243,0.96))] shadow-[var(--public-surface-shadow)]"
const insetCardClass =
"rounded-[var(--public-inset-radius)] border border-border/60 bg-white/95 shadow-[0_10px_28px_rgba(15,23,42,0.06)]"
return (
<>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(structuredData) }}
/>
{/* Hero Section */}
<section className="py-12 md:py-16 bg-background">
<div className="container mx-auto px-4 max-w-4xl">
<Breadcrumbs
className="mb-6"
items={[
{ label: "Services", href: "/services" },
{ label: "Parts", href: "/services/parts" },
]}
/>
<PublicPageHeader
align="center"
eyebrow="Parts & Support"
title={page.title || "Vending Machine Parts & Support"}
description={
cleanExcerpt ||
"Replacement parts, documentation, and support for the brands and payment systems Rocky Mountain Vending works with most."
}
/>
</div>
</section>
{/* Main Content - Only show if there's meaningful content beyond the intro */}
{content && (
<section className="py-12 md:py-16 bg-muted/30">
<div className="container mx-auto px-4 max-w-4xl">
<PublicSurface as="article">
<div className="prose prose-lg max-w-none text-pretty leading-relaxed prose-headings:text-foreground prose-p:text-muted-foreground prose-a:text-foreground prose-a:hover:text-secondary prose-a:transition-colors prose-headings:font-bold prose-headings:tracking-tight prose-img:rounded-lg prose-img:shadow-md">
{content}
</div>
</PublicSurface>
</div>
</section>
)}
{content && <Separator className="my-0" />}
{/* Services Section */}
<section className="py-12 md:py-16">
<div className="container mx-auto px-4 max-w-6xl">
<PublicSectionHeader
eyebrow="Service Scope"
title="Parts & support services"
description="Comprehensive parts and technical support to keep your vending machines operational."
className="mx-auto mb-8 max-w-3xl text-center md:mb-12"
/>
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
<Card className={`${insetCardClass} h-full hover:border-primary/30`}>
<CardContent className="p-6">
<div className="mb-4 inline-flex h-12 w-12 items-center justify-center rounded-lg bg-primary/10">
<Package className="h-6 w-6 text-primary" />
</div>
<h3 className="text-xl font-semibold mb-2">
Replacement Parts
</h3>
<p className="text-muted-foreground text-sm leading-relaxed">
Replacement parts for all major vending machine brands
</p>
</CardContent>
</Card>
<Card className={`${insetCardClass} h-full hover:border-primary/30`}>
<CardContent className="p-6">
<div className="mb-4 inline-flex h-12 w-12 items-center justify-center rounded-lg bg-primary/10">
<ShoppingCart className="h-6 w-6 text-primary" />
</div>
<h3 className="text-xl font-semibold mb-2">
Payment Components
</h3>
<p className="text-muted-foreground text-sm leading-relaxed">
Coin and bill mechanism components for reliable transactions
</p>
</CardContent>
</Card>
<Card className={`${insetCardClass} h-full hover:border-primary/30`}>
<CardContent className="p-6">
<div className="mb-4 inline-flex h-12 w-12 items-center justify-center rounded-lg bg-primary/10">
<Wrench className="h-6 w-6 text-primary" />
</div>
<h3 className="text-xl font-semibold mb-2">
Cooling Systems
</h3>
<p className="text-muted-foreground text-sm leading-relaxed">
Refrigeration and cooling system parts to keep products
fresh
</p>
</CardContent>
</Card>
<Card className={`${insetCardClass} h-full hover:border-primary/30`}>
<CardContent className="p-6">
<div className="mb-4 inline-flex h-12 w-12 items-center justify-center rounded-lg bg-primary/10">
<CreditCard className="h-6 w-6 text-primary" />
</div>
<h3 className="text-xl font-semibold mb-2">
Payment Upgrades
</h3>
<p className="text-muted-foreground text-sm leading-relaxed">
Card readers and payment system upgrades for modern
convenience
</p>
</CardContent>
</Card>
<Card className={`${insetCardClass} h-full hover:border-primary/30`}>
<CardContent className="p-6">
<div className="mb-4 inline-flex h-12 w-12 items-center justify-center rounded-lg bg-primary/10">
<Wrench className="h-6 w-6 text-primary" />
</div>
<h3 className="text-xl font-semibold mb-2">
Electrical Components
</h3>
<p className="text-muted-foreground text-sm leading-relaxed">
Electrical and wiring components for reliable machine
operation
</p>
</CardContent>
</Card>
<Card className={`${insetCardClass} h-full hover:border-primary/30`}>
<CardContent className="p-6">
<div className="mb-4 inline-flex h-12 w-12 items-center justify-center rounded-lg bg-primary/10">
<Package className="h-6 w-6 text-primary" />
</div>
<h3 className="text-xl font-semibold mb-2">
Dispensing Systems
</h3>
<p className="text-muted-foreground text-sm leading-relaxed">
Vending coils, motors, and dispensers for smooth product
delivery
</p>
</CardContent>
</Card>
</div>
</div>
</section>
{/* Available Parts Section */}
<section className="py-12 md:py-16 bg-muted/30">
<div className="container mx-auto px-4 max-w-6xl">
<PublicSectionHeader
eyebrow="Inventory"
title="Available parts include"
description="We stock a comprehensive inventory of vending machine parts to keep your equipment running smoothly."
className="mx-auto mb-8 max-w-3xl text-center md:mb-12"
/>
<Card className={surfaceCardClass}>
<CardHeader>
<CardTitle className="text-2xl md:text-3xl">
Parts Inventory
</CardTitle>
</CardHeader>
<CardContent className="px-6 pb-6 pt-2">
<div className="grid gap-4 md:grid-cols-2">
<ul className="space-y-3">
<li className="flex items-start gap-3">
<CheckCircle2 className="w-5 h-5 text-primary flex-shrink-0 mt-0.5" />
<span className="text-foreground">
Bill validators and coin mechanisms
</span>
</li>
<li className="flex items-start gap-3">
<CheckCircle2 className="w-5 h-5 text-primary flex-shrink-0 mt-0.5" />
<span className="text-foreground">
Card readers for cashless payments
</span>
</li>
<li className="flex items-start gap-3">
<CheckCircle2 className="w-5 h-5 text-primary flex-shrink-0 mt-0.5" />
<span className="text-foreground">
Refrigeration components (compressors, evaporators, and
thermostats)
</span>
</li>
<li className="flex items-start gap-3">
<CheckCircle2 className="w-5 h-5 text-primary flex-shrink-0 mt-0.5" />
<span className="text-foreground">
Keypads and control boards
</span>
</li>
<li className="flex items-start gap-3">
<CheckCircle2 className="w-5 h-5 text-primary flex-shrink-0 mt-0.5" />
<span className="text-foreground">
Motors and actuators
</span>
</li>
</ul>
<ul className="space-y-3">
<li className="flex items-start gap-3">
<CheckCircle2 className="w-5 h-5 text-primary flex-shrink-0 mt-0.5" />
<span className="text-foreground">
Vending machine locks and security components
</span>
</li>
<li className="flex items-start gap-3">
<CheckCircle2 className="w-5 h-5 text-primary flex-shrink-0 mt-0.5" />
<span className="text-foreground">
Shelves, trays, and spirals for product dispensing
</span>
</li>
<li className="flex items-start gap-3">
<CheckCircle2 className="w-5 h-5 text-primary flex-shrink-0 mt-0.5" />
<span className="text-foreground">
LED lighting upgrades
</span>
</li>
<li className="flex items-start gap-3">
<CheckCircle2 className="w-5 h-5 text-primary flex-shrink-0 mt-0.5" />
<span className="text-foreground">
Replacement doors and panels
</span>
</li>
<li className="flex items-start gap-3">
<CheckCircle2 className="w-5 h-5 text-primary flex-shrink-0 mt-0.5" />
<span className="text-foreground">
Electrical components (fuses, wiring harnesses, and
switches)
</span>
</li>
</ul>
</div>
<div className="mt-8 pt-6 border-t border-border/50">
<p className="text-muted-foreground leading-relaxed text-center">
Don't see the part you need?{" "}
<Link
href="/contact-us"
className="text-primary hover:text-secondary font-medium transition-colors"
>
Contact us
</Link>
! We can source specialty parts or recommend alternatives
for your specific vending machine model.
</p>
</div>
</CardContent>
</Card>
</div>
</section>
{/* Compatible Brands Section */}
<section className="py-12 md:py-16 bg-background">
<div className="container mx-auto px-4 max-w-6xl">
<div className="text-center mb-8 md:mb-12">
<h2 className="text-3xl font-bold tracking-tight md:text-4xl lg:text-5xl mb-4 text-balance">
Compatible Vending Machine Brands
</h2>
<p className="text-lg text-muted-foreground max-w-2xl mx-auto text-pretty leading-relaxed">
We carry parts for the same major vending machine brands we
service, ensuring seamless compatibility and performance. If
your brand isn't listed, get in touchwe may still have the
parts you need or can source them for you.
</p>
</div>
<Accordion type="single" collapsible className="w-full space-y-4">
<AccordionItem
value="vending-brands"
className={`${insetCardClass} rounded-[1.5rem] px-6 py-2 transition-all hover:border-primary/30`}
>
<AccordionTrigger className="text-xl font-semibold hover:no-underline py-4">
Vending Machine Brands
</AccordionTrigger>
<AccordionContent className="pt-0 pb-6">
<div className="grid gap-3 md:grid-cols-2">
<ul className="space-y-2">
<li className="flex items-start gap-2">
<CheckCircle2 className="w-4 h-4 text-primary flex-shrink-0 mt-1" />
<span className="text-foreground">
AMS (Automated Merchandising Systems)
</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2 className="w-4 h-4 text-primary flex-shrink-0 mt-1" />
<span className="text-foreground">Dixie-Narco</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2 className="w-4 h-4 text-primary flex-shrink-0 mt-1" />
<span className="text-foreground">Royal Vendors</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2 className="w-4 h-4 text-primary flex-shrink-0 mt-1" />
<span className="text-foreground">Vendo</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2 className="w-4 h-4 text-primary flex-shrink-0 mt-1" />
<span className="text-foreground">
Crane National Vendors
</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2 className="w-4 h-4 text-primary flex-shrink-0 mt-1" />
<span className="text-foreground">Seaga</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2 className="w-4 h-4 text-primary flex-shrink-0 mt-1" />
<span className="text-foreground">
USI (United Standard Industries)
</span>
</li>
</ul>
<ul className="space-y-2">
<li className="flex items-start gap-2">
<CheckCircle2 className="w-4 h-4 text-primary flex-shrink-0 mt-1" />
<span className="text-foreground">
HealthyYOU Vending
</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2 className="w-4 h-4 text-primary flex-shrink-0 mt-1" />
<span className="text-foreground">
AP (Automatic Products)
</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2 className="w-4 h-4 text-primary flex-shrink-0 mt-1" />
<span className="text-foreground">
National Vendors
</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2 className="w-4 h-4 text-primary flex-shrink-0 mt-1" />
<span className="text-foreground">
CPI (Crane Payment Innovations)
</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2 className="w-4 h-4 text-primary flex-shrink-0 mt-1" />
<span className="text-foreground">
Quick Fresh Vending
</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2 className="w-4 h-4 text-primary flex-shrink-0 mt-1" />
<span className="text-foreground">
GPL (General Products Limited)
</span>
</li>
</ul>
</div>
</AccordionContent>
</AccordionItem>
<AccordionItem
value="card-reader-brands"
className={`${insetCardClass} rounded-[1.5rem] px-6 py-2 transition-all hover:border-primary/30`}
>
<AccordionTrigger className="text-xl font-semibold hover:no-underline py-4">
Compatible Card Reader Brands
</AccordionTrigger>
<AccordionContent className="pt-0 pb-6">
<p className="text-foreground mb-4 leading-relaxed">
Upgrade or replace your cashless payment systems with our
reliable card reader parts:
</p>
<ul className="space-y-2">
<li className="flex items-start gap-2">
<CheckCircle2 className="w-4 h-4 text-primary flex-shrink-0 mt-1" />
<span className="text-foreground">Nayax</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2 className="w-4 h-4 text-primary flex-shrink-0 mt-1" />
<span className="text-foreground">
USA Technologies/Cantaloupe
</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2 className="w-4 h-4 text-primary flex-shrink-0 mt-1" />
<span className="text-foreground">
Parlevel/365 Markets
</span>
</li>
</ul>
</AccordionContent>
</AccordionItem>
<AccordionItem
value="payment-brands"
className={`${insetCardClass} rounded-[1.5rem] px-6 py-2 transition-all hover:border-primary/30`}
>
<AccordionTrigger className="text-xl font-semibold hover:no-underline py-4">
Compatible Bill Validator and Coin Mechanism Brands
</AccordionTrigger>
<AccordionContent className="pt-0 pb-6">
<p className="text-foreground mb-4 leading-relaxed">
Keep your payment systems operational with our high-quality
bill validator and coin mechanism parts:
</p>
<ul className="space-y-2">
<li className="flex items-start gap-2">
<CheckCircle2 className="w-4 h-4 text-primary flex-shrink-0 mt-1" />
<span className="text-foreground">
MEI (Mars Electronics International)
</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2 className="w-4 h-4 text-primary flex-shrink-0 mt-1" />
<span className="text-foreground">
Coinco (Coin Acceptors Inc.)
</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2 className="w-4 h-4 text-primary flex-shrink-0 mt-1" />
<span className="text-foreground">Conlux</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2 className="w-4 h-4 text-primary flex-shrink-0 mt-1" />
<span className="text-foreground">
ICT (Innovative Concepts in Technology)
</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2 className="w-4 h-4 text-primary flex-shrink-0 mt-1" />
<span className="text-foreground">Currenza</span>
</li>
</ul>
</AccordionContent>
</AccordionItem>
</Accordion>
</div>
</section>
{/* How to Order Parts */}
<section className="py-12 md:py-16 bg-background">
<div className="container mx-auto px-4 max-w-6xl">
<div className="text-center mb-8 md:mb-12">
<h2 className="text-3xl font-bold tracking-tight md:text-4xl lg:text-5xl mb-4 text-balance">
How to Order Parts
</h2>
<p className="text-lg text-muted-foreground max-w-2xl mx-auto text-pretty leading-relaxed">
Simple steps to get the parts you need quickly and efficiently
</p>
</div>
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-4">
<Card className={`${insetCardClass} h-full hover:border-primary/30`}>
<CardContent className="pt-8">
<div className="mb-6">
<div className="inline-flex items-center justify-center h-16 w-16 rounded-full bg-primary/10 text-primary text-2xl font-bold">
<Search className="h-8 w-8" />
</div>
</div>
<h3 className="text-xl font-semibold mb-3">
Identify Your Part
</h3>
<p className="text-muted-foreground text-sm leading-relaxed">
Use your machine's manual or contact us with model details
to identify the exact part number you need.
</p>
</CardContent>
</Card>
<Card className={`${insetCardClass} h-full hover:border-primary/30`}>
<CardContent className="pt-8">
<div className="mb-6">
<div className="inline-flex items-center justify-center h-16 w-16 rounded-full bg-primary/10 text-primary">
<Phone className="h-8 w-8" />
</div>
</div>
<h3 className="text-xl font-semibold mb-3">
Contact Our Team
</h3>
<p className="text-muted-foreground text-sm leading-relaxed">
Reach out via phone, email, or our contact form. We'll
confirm availability and provide a quote.
</p>
</CardContent>
</Card>
<Card className={`${insetCardClass} h-full hover:border-primary/30`}>
<CardContent className="pt-8">
<div className="mb-6">
<div className="inline-flex items-center justify-center h-16 w-16 rounded-full bg-primary/10 text-primary">
<ShoppingCart className="h-8 w-8" />
</div>
</div>
<h3 className="text-xl font-semibold mb-3">
Place Your Order
</h3>
<p className="text-muted-foreground text-sm leading-relaxed">
Once confirmed, we'll process your order and arrange fast
shipping or local pickup.
</p>
</CardContent>
</Card>
<Card className={`${insetCardClass} h-full hover:border-primary/30`}>
<CardContent className="pt-8">
<div className="mb-6">
<div className="inline-flex items-center justify-center h-16 w-16 rounded-full bg-primary/10 text-primary">
<Wrench className="h-8 w-8" />
</div>
</div>
<h3 className="text-xl font-semibold mb-3">
Get Expert Installation Support
</h3>
<p className="text-muted-foreground text-sm leading-relaxed">
Need help installing? Our team provides guidance or on-site
installation services.
</p>
</CardContent>
</Card>
</div>
</div>
</section>
{/* Why Choose Us / Benefits Section */}
<section className="py-12 md:py-16 bg-muted/30">
<div className="container mx-auto px-4 max-w-6xl">
<div className="text-center mb-8 md:mb-12">
<h2 className="text-3xl font-bold tracking-tight md:text-4xl lg:text-5xl mb-4 text-balance">
Why Choose Rocky Mountain Vending for Parts?
</h2>
<p className="text-lg text-muted-foreground max-w-2xl mx-auto text-pretty leading-relaxed">
Trusted by businesses across Utah for reliable parts and
exceptional service
</p>
</div>
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
<Card className={`${insetCardClass} h-full hover:border-primary/30`}>
<CardContent className="pt-6">
<div className="mb-4 inline-flex h-12 w-12 items-center justify-center rounded-lg bg-primary/10">
<MapPin className="h-6 w-6 text-primary" />
</div>
<h3 className="text-lg font-semibold mb-2">
Local Expertise
</h3>
<p className="text-sm text-muted-foreground leading-relaxed">
Serving Salt Lake City, Davis County, and Utah County for
over 10 years.
</p>
</CardContent>
</Card>
<Card className={`${insetCardClass} h-full hover:border-primary/30`}>
<CardContent className="pt-6">
<div className="mb-4 inline-flex h-12 w-12 items-center justify-center rounded-lg bg-primary/10">
<Truck className="h-6 w-6 text-primary" />
</div>
<h3 className="text-lg font-semibold mb-2">Fast Delivery</h3>
<p className="text-sm text-muted-foreground leading-relaxed">
Quick shipping or local pickup to minimize downtime for your
vending machines.
</p>
</CardContent>
</Card>
<Card className={`${insetCardClass} h-full hover:border-primary/30`}>
<CardContent className="pt-6">
<div className="mb-4 inline-flex h-12 w-12 items-center justify-center rounded-lg bg-primary/10">
<Award className="h-6 w-6 text-primary" />
</div>
<h3 className="text-lg font-semibold mb-2">
Quality Assurance
</h3>
<p className="text-sm text-muted-foreground leading-relaxed">
We source parts from trusted manufacturers to ensure
reliability and longevity.
</p>
</CardContent>
</Card>
<Card className={`${insetCardClass} h-full hover:border-primary/30`}>
<CardContent className="pt-6">
<div className="mb-4 inline-flex h-12 w-12 items-center justify-center rounded-lg bg-primary/10">
<Users className="h-6 w-6 text-primary" />
</div>
<h3 className="text-lg font-semibold mb-2">Expert Support</h3>
<p className="text-sm text-muted-foreground leading-relaxed">
Our technicians can guide you on selecting the right parts
or assist with installation.
</p>
</CardContent>
</Card>
<Card className={`${insetCardClass} h-full hover:border-primary/30`}>
<CardContent className="pt-6">
<div className="mb-4 inline-flex h-12 w-12 items-center justify-center rounded-lg bg-primary/10">
<DollarSign className="h-6 w-6 text-primary" />
</div>
<h3 className="text-lg font-semibold mb-2">
Competitive Pricing
</h3>
<p className="text-sm text-muted-foreground leading-relaxed">
Affordable parts tailored to your budget, with no compromise
on quality.
</p>
</CardContent>
</Card>
<Card className={`${insetCardClass} h-full hover:border-primary/30`}>
<CardContent className="pt-6">
<div className="mb-4 inline-flex h-12 w-12 items-center justify-center rounded-lg bg-primary/10">
<Search className="h-6 w-6 text-primary" />
</div>
<h3 className="text-lg font-semibold mb-2">
Custom Solutions
</h3>
<p className="text-sm text-muted-foreground leading-relaxed">
Need a hard-to-find part? We'll work with you to source or
recommend alternatives.
</p>
</CardContent>
</Card>
</div>
</div>
</section>
{/* FAQ Section */}
{faqs.length > 0 && <FAQSection faqs={faqs} />}
{/* Call to Action */}
<section className="py-12 md:py-16 bg-background">
<div className="container mx-auto px-4 max-w-4xl">
<Card className={`${surfaceCardClass} border-primary/20`}>
<CardContent className="p-6 md:p-8 text-center">
<div className="mb-6 inline-flex h-16 w-16 items-center justify-center rounded-full bg-primary/10">
<Phone className="h-8 w-8 text-primary" />
</div>
<h2 className="text-3xl md:text-4xl font-bold mb-4 tracking-tight text-balance">
Need Parts or Technical Support?
</h2>
<p className="text-lg text-muted-foreground mb-8 text-pretty leading-relaxed max-w-2xl mx-auto">
Our inventory is stocked with everything you need. Contact us
today for expert assistance and fast delivery.
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<Link href="/contact-us">
<Button size="lg" className="group">
Get Help Now
<Phone className="ml-2 h-4 w-4 group-hover:translate-x-1 transition-transform" />
</Button>
</Link>
<Link href="/services">
<Button size="lg" variant="outline" className="group">
View All Services
<ArrowRight className="ml-2 h-4 w-4 group-hover:translate-x-1 transition-transform" />
</Button>
</Link>
</div>
</CardContent>
</Card>
</div>
</section>
</>
)
} catch (error) {
if (process.env.NODE_ENV === "development") {
console.error("Error rendering Parts page:", error)
}
notFound()
}
}