6 Commits

Author SHA1 Message Date
56a1d63906 Merge version_8_1783098560292 into main
Merge version_8_1783098560292 into main
2026-07-03 17:14:27 +00:00
kudinDmitriyUp
067aa9c650 Bob AI: Populate the newly-created page at src/pages/MachineWalkthro 2026-07-03 17:13:45 +00:00
kudinDmitriyUp
8d22a47359 Bob AI: Add machine-walkthrough page 2026-07-03 17:10:24 +00:00
f075b114bc Merge version_7_1783075702690 into main
Merge version_7_1783075702690 into main
2026-07-03 10:49:01 +00:00
kudinDmitriyUp
8c5952d938 Bob AI: Add service detail pages (dynamic route /services/:slug) 2026-07-03 10:48:55 +00:00
fb0c1893fc Merge version_6_1783075595252 into main
Merge version_6_1783075595252 into main
2026-07-03 10:48:05 +00:00
5 changed files with 249 additions and 3 deletions

View File

@@ -4,6 +4,7 @@ import HomePage from './pages/HomePage';
import BlogPage from "@/pages/BlogPage";
import ServiceDetailPage from './pages/ServiceDetailPage';
import MachineWalkthroughPage from "@/pages/MachineWalkthroughPage";
export default function App() {
return (
<Routes>
@@ -12,6 +13,7 @@ export default function App() {
<Route path="/blog" element={<BlogPage />} />
</Route>
<Route path="/services/:slug" element={<ServiceDetailPage />} />
<Route path="/machine-walkthrough" element={<MachineWalkthroughPage />} />
</Routes>
);
}

View File

@@ -24,6 +24,8 @@ export default function Layout() {
"href": "#contact"
},
{ name: "Blog", href: "/blog" },
{ name: "Machine Walkthrough", href: "/machine-walkthrough" },
];

View File

@@ -7,9 +7,9 @@ export interface Service {
}
export const services: Service[] = [
{"slug":"item-dd0sy","question":"Where is your primary service area?","answer":"We specialize in the Northern Cape mining and industrial regions, ensuring rapid local deployment.","body":"In today's crowded market, a strong brand is your most valuable asset. Our strategic brand consulting service digs deep into your company's core identity, market positioning, and target audience to uncover what truly sets you apart. We do not just look at logos and colors; we analyze your entire customer journey to ensure every touchpoint resonates with your unique value proposition.\n\nThrough a series of collaborative workshops and in-depth market research, our strategists build a comprehensive roadmap for your brand. You will receive actionable insights and a clear framework for future growth, empowering your team to communicate with confidence and consistency.","specs":[{"label":"Duration","value":"4-6 Weeks"},{"label":"Deliverable","value":"Strategy Playbook"},{"label":"Format","value":"Remote or In-person"},{"label":"Best For","value":"Rebrands and Startups"}]},
{"slug":"item-7zqu9","question":"Do you provide OEM maintenance?","answer":"Yes, we adhere strictly to OEM standards for all mechanical maintenance and repairs.","body":"Your website is the digital storefront of your business, and it needs to perform flawlessly across all devices. Our custom web development service delivers high-performance, secure, and scalable websites tailored specifically to your operational needs. We write clean, modern code that ensures lightning-fast load times and seamless user experiences, keeping your visitors engaged and driving conversions.\n\nWe specialize in integrating complex third-party APIs, custom content management systems, and robust e-commerce architectures. From the initial technical discovery phase to post-launch maintenance, our dedicated development team works closely with you to ensure your digital infrastructure is built to handle future growth and evolving market demands.","specs":[{"label":"Tech Stack","value":"React, Node.js, Python"},{"label":"Timeline","value":"8-12 Weeks"},{"label":"Support","value":"90 Days Post-launch"},{"label":"Hosting","value":"AWS or Vercel"}]},
{"slug":"item-qgrhu","question":"How do we request a project consultation?","answer":"Simply fill out our contact form below or call our office during business hours.","body":"Visibility is everything in the digital landscape. Our SEO and content optimization service is designed to elevate your search rankings and drive highly targeted organic traffic to your website. We start with a comprehensive technical audit to identify and fix underlying crawl issues, followed by deep keyword research to uncover high-intent search terms your competitors are missing.\n\nBeyond technical fixes, we revitalize your existing content and map out a strategic editorial calendar. By aligning your website's copy with proven search intent and optimizing on-page elements, we help you build sustainable, long-term authority in your industry. Watch your organic reach grow as we turn your website into a reliable lead generation engine.","specs":[{"label":"Audit Timeframe","value":"14 Days"},{"label":"Reporting","value":"Monthly Dashboard"},{"label":"Focus","value":"On-page & Technical SEO"},{"label":"Contract","value":"6-Month Minimum"}]},
{"slug":"item-9f9u9","question":"Where is your primary service area?","answer":"We specialize in the Northern Cape mining and industrial regions, ensuring rapid local deployment.","body":"Our Item 1 service is designed to provide comprehensive strategic oversight for your most complex business challenges. We embed our senior consultants directly into your daily operations, ensuring a seamless integration of industry best practices with your unique company culture. This hands-on approach allows us to identify hidden bottlenecks and unlock new avenues for sustainable growth.\n\nBy leveraging proprietary analytics and decades of market experience, we transform raw data into actionable roadmaps. You will receive dedicated support throughout the entire implementation phase, minimizing downtime and maximizing your return on investment. Our team remains on call to refine these strategies as your market landscape evolves.","specs":[{"label":"Duration","value":"3-6 Months"},{"label":"Delivery Method","value":"Hybrid"},{"label":"Dedicated Experts","value":"2 Senior Consultants"},{"label":"Reporting","value":"Weekly Dashboards"}]},
{"slug":"item-f6ct8","question":"Do you provide OEM maintenance?","answer":"Yes, we adhere strictly to OEM standards for all mechanical maintenance and repairs.","body":"Item 2 delivers robust, scalable technical solutions tailored to modern enterprise environments. We focus on building resilient infrastructure that grows alongside your business, utilizing the latest frameworks to guarantee optimal performance and security. Every deployment is rigorously tested against industry standards to ensure flawless operation from day one.\n\nOur development lifecycle prioritizes transparency and continuous feedback. You will have full visibility into our progress through regular milestone reviews and open communication channels. Once the initial build is complete, we provide comprehensive training sessions to empower your internal teams and facilitate a smooth handover.\n\nBeyond the initial launch, this service includes proactive monitoring and maintenance. We preemptively address potential vulnerabilities and apply critical updates, giving you total peace of mind and allowing your staff to focus on core business objectives.","specs":[{"label":"Tech Stack","value":"React & Node.js"},{"label":"Uptime Guarantee","value":"99.9%"},{"label":"Support SLA","value":"24/7 Priority"},{"label":"Training Included","value":"10 Hours"}]},
{"slug":"item-tqcwk","question":"How do we request a project consultation?","answer":"Simply fill out our contact form below or call our office during business hours.","body":"Maximize your market penetration with Item 3, our fully managed growth and outreach service. We take a holistic view of your target audience, crafting highly personalized campaigns that resonate across multiple digital touchpoints. By aligning our creative assets with your core brand identity, we drive measurable engagement and foster long-term customer loyalty.\n\nContinuous optimization is at the heart of our methodology. We employ advanced split testing and real-time behavioral tracking to refine our messaging on the fly. This data-driven agility ensures that your budget is always allocated to the highest-performing channels, dramatically reducing acquisition costs over time.","specs":[{"label":"Campaign Types","value":"Omnichannel"},{"label":"Optimization","value":"Daily"},{"label":"Asset Creation","value":"Included"},{"label":"Contract Length","value":"Annual Minimum"},{"label":"Account Manager","value":"Dedicated"}]},
];
export function findService(slug: string): Service | undefined {

View File

@@ -0,0 +1,241 @@
import { useState } from "react";
import { motion, AnimatePresence } from "motion/react";
import { routes } from "@/routes";
import { Info, MapPin, ChevronLeft } from "lucide-react";
import { cls } from "@/lib/utils";
type ViewKey = 'exterior' | 'cab' | 'machinery' | 'electrical' | 'boom' | 'maintenance';
type Hotspot =
| { id: string; x: number; y: number; label: string; type: 'nav'; target: ViewKey }
| { id: string; x: number; y: number; label: string; type: 'info'; info: string };
type View = {
title: string;
imageSrc: string;
hotspots: Hotspot[];
};
const VIEWS: Record<ViewKey, View> = {
exterior: {
title: "P&H 4200 Exterior",
imageSrc: "https://picsum.photos/seed/1329000375/1200/800",
hotspots: [
{ id: 'enter', x: 50, y: 60, label: "Enter the Machine", target: 'cab', type: 'nav' }
]
},
cab: {
title: "Operator's Cab",
imageSrc: "https://picsum.photos/seed/1496099219/1200/800",
hotspots: [
{ id: 'controls', x: 40, y: 50, label: "Dual Joystick Controls", info: "Ergonomic control center with panoramic visibility.", type: 'info' },
{ id: 'display', x: 60, y: 45, label: "Diagnostic Displays", info: "Real-time operational data and payload monitoring.", type: 'info' }
]
},
machinery: {
title: "Machinery House",
imageSrc: "https://picsum.photos/seed/1110967395/1200/800",
hotspots: [
{ id: 'hoist', x: 30, y: 60, label: "Hoist Motors", info: "Massive hoist motors designed for continuous high-torque output.", type: 'info' },
{ id: 'swing', x: 70, y: 55, label: "Swing Transmissions", info: "Planetary gearboxes for smooth, rapid swing cycles.", type: 'info' }
]
},
electrical: {
title: "Electrical Room",
imageSrc: "https://picsum.photos/seed/1776604305/1200/800",
hotspots: [
{ id: 'ac', x: 50, y: 40, label: "AC Drive Systems", info: "Advanced IGBT AC drives for precise motor control.", type: 'info' },
{ id: 'panels', x: 20, y: 50, label: "Power Distribution", info: "Climate-controlled electronics bays.", type: 'info' }
]
},
boom: {
title: "Boom & Dipper",
imageSrc: "https://picsum.photos/seed/691466050/1200/800",
hotspots: [
{ id: 'dipper', x: 50, y: 70, label: "High-Capacity Dipper", info: "Engineered for maximum payload and optimal dig geometry.", type: 'info' },
{ id: 'crowd', x: 50, y: 30, label: "Crowd Machinery", info: "Rack and pinion crowd for positive digging force.", type: 'info' }
]
},
maintenance: {
title: "Maintenance Deck",
imageSrc: "https://picsum.photos/seed/429735176/1200/800",
hotspots: [
{ id: 'lube', x: 40, y: 60, label: "Auto-Lube System", info: "Centralized lubrication for all major pivot points.", type: 'info' },
{ id: 'access', x: 80, y: 50, label: "Safe Access", info: "Wide walkways and tie-off points for maintenance personnel.", type: 'info' }
]
}
};
export default function MachineWalkthroughPage() {
const [currentView, setCurrentView] = useState<ViewKey>('exterior');
const [activeInfo, setActiveInfo] = useState<string | null>(null);
const [isTransitioning, setIsTransitioning] = useState(false);
const handleNavigate = (target: ViewKey) => {
setIsTransitioning(true);
setActiveInfo(null);
setTimeout(() => {
setCurrentView(target);
setIsTransitioning(false);
}, 800);
};
const view = VIEWS[currentView];
return (
<div
className="min-h-svh flex flex-col font-sans bg-background text-foreground"
style={{
'--background': '#09090b',
'--foreground': '#f4f4f5',
'--card': '#18181b',
'--primary-cta': '#18181b',
'--primary-cta-text': '#f97316',
'--secondary-cta': '#27272a',
'--secondary-cta-text': '#f4f4f5',
'--accent': '#f97316',
'--background-accent': '#c2410c',
} as React.CSSProperties}
>
<main className="relative flex-grow h-[calc(100vh-5rem)] mt-20 overflow-hidden bg-background">
<AnimatePresence mode="wait">
<motion.div
key={currentView}
initial={{ opacity: 0, scale: 1.1 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 1.2 }}
transition={{ duration: 0.8, ease: "easeInOut" }}
className="absolute inset-0"
>
<img
src={view.imageSrc}
alt={view.title}
className="w-full h-full object-cover opacity-60"
/>
{currentView === 'exterior' && (
<motion.img
src={view.imageSrc}
alt={view.title}
initial={{ scale: 1 }}
animate={{ scale: 1.1 }}
transition={{ duration: 20, repeat: Infinity, repeatType: "reverse", ease: "linear" }}
className="absolute inset-0 w-full h-full object-cover opacity-50 mix-blend-overlay"
/>
)}
</motion.div>
</AnimatePresence>
<div className="absolute inset-0 bg-gradient-to-t from-background via-background/40 to-transparent pointer-events-none" />
<div className="absolute inset-0 z-10">
<AnimatePresence>
{!isTransitioning && view.hotspots.map((hotspot) => (
<motion.div
key={hotspot.id}
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, scale: 0.9 }}
transition={{ delay: 0.5 }}
className="absolute -translate-x-1/2 -translate-y-1/2 flex flex-col items-center gap-2"
style={{ left: `${hotspot.x}%`, top: `${hotspot.y}%` }}
>
{hotspot.type === 'nav' ? (
<button
onClick={() => handleNavigate(hotspot.target)}
className="group relative flex items-center justify-center w-16 h-16 rounded-full bg-accent/20 border-2 border-accent text-accent hover:bg-accent hover:text-background transition-all duration-300 shadow-lg shadow-accent/40 hover:shadow-xl hover:shadow-accent/60"
>
<MapPin className="w-6 h-6" />
<span className="absolute top-full mt-3 whitespace-nowrap text-sm font-bold tracking-wider uppercase text-accent group-hover:text-accent/80 drop-shadow-md">
{hotspot.label}
</span>
</button>
) : (
<div className="relative">
<button
onClick={() => setActiveInfo(activeInfo === hotspot.id ? null : hotspot.id)}
className={cls(
"group relative flex items-center justify-center w-10 h-10 rounded-full border-2 transition-all duration-300",
activeInfo === hotspot.id
? "bg-accent border-accent text-background shadow-lg shadow-accent/60"
: "bg-card/80 border-accent/50 text-accent hover:border-accent hover:bg-accent/20"
)}
>
<Info className="w-5 h-5" />
</button>
<AnimatePresence>
{activeInfo === hotspot.id && (
<motion.div
initial={{ opacity: 0, y: 10, scale: 0.95 }}
animate={{ opacity: 1, y: 0, scale: 1 }}
exit={{ opacity: 0, y: 10, scale: 0.95 }}
className="absolute top-full left-1/2 -translate-x-1/2 mt-4 w-64 p-4 rounded-lg bg-card/95 border border-foreground/10 shadow-2xl backdrop-blur-sm"
>
<h4 className="text-accent font-bold mb-2">{hotspot.label}</h4>
<p className="text-sm text-foreground/80 leading-relaxed">{hotspot.info}</p>
</motion.div>
)}
</AnimatePresence>
</div>
)}
</motion.div>
))}
</AnimatePresence>
</div>
<AnimatePresence>
{currentView !== 'exterior' && (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: 20 }}
className="absolute bottom-8 left-1/2 -translate-x-1/2 z-20 flex flex-col items-center gap-6 w-full max-w-content-width px-4"
>
<div className="flex flex-wrap justify-center gap-2 p-2 rounded-theme bg-card/80 backdrop-blur-md border border-foreground/10 shadow-2xl">
{(Object.keys(VIEWS) as ViewKey[]).filter(k => k !== 'exterior').map((key) => (
<button
key={key}
onClick={() => handleNavigate(key)}
className={cls(
"px-4 py-2 rounded-xl text-sm font-medium transition-all duration-300",
currentView === key
? "bg-accent text-background shadow-md shadow-accent/40"
: "text-foreground/60 hover:text-accent hover:bg-background/50"
)}
>
{VIEWS[key].title}
</button>
))}
</div>
<button
onClick={() => handleNavigate('exterior')}
className="flex items-center gap-2 px-6 py-3 rounded-full bg-card/80 border border-foreground/20 text-foreground/80 hover:text-foreground hover:border-foreground/50 transition-all backdrop-blur-md"
>
<ChevronLeft className="w-4 h-4" />
Back to Exterior
</button>
</motion.div>
)}
</AnimatePresence>
<div className="absolute top-8 left-8 z-20">
<motion.div
key={currentView}
initial={{ opacity: 0, x: -20 }}
animate={{ opacity: 1, x: 0 }}
className="flex flex-col gap-1"
>
<span className="text-accent text-sm font-bold tracking-widest uppercase">
{currentView === 'exterior' ? 'Virtual Tour' : 'Interior Compartment'}
</span>
<h1 className="text-4xl md:text-5xl font-bold text-white drop-shadow-lg">
{view.title}
</h1>
</motion.div>
</div>
</main>
</div>
);
}

View File

@@ -7,4 +7,5 @@ export interface Route {
export const routes: Route[] = [
{ path: '/', label: 'Home', pageFile: 'HomePage' },
{ path: '/blog', label: 'Blog', pageFile: 'BlogPage' },
{ path: '/machine-walkthrough', label: 'Machine Walkthrough', pageFile: 'MachineWalkthroughPage' },
];