(null);
+
+ useEffect(() => {
+ try {
+ const savedBookings = window.localStorage.getItem(bookingStorageKey);
+ if (savedBookings) {
+ setBookings(JSON.parse(savedBookings));
+ }
+ } catch (error) {
+ console.error('Failed to load Bumper Buddies bookings from local storage:', error);
+ }
+ }, []);
+
+ const estimate = useMemo(() => {
+ const selectedServices = serviceOptions.filter((service) => form.services.includes(service.id));
+ const serviceTotal = selectedServices.reduce((total, service) => total + service.price, 0);
+ const mobileCallout = form.serviceLocationType.includes('Mobile') ? 35 : 0;
+
+ return Math.round(serviceTotal * getVehicleMultiplier(form.vehicleType) + mobileCallout);
+ }, [form.serviceLocationType, form.services, form.vehicleType]);
+
+ const selectedBooking =
+ bookings.find((booking) => booking.bookingNumber === selectedBookingNumber) || bookings[0] || null;
+
+ const updateForm = (field: keyof BookingForm, value: string) => {
+ setValidationMessage('');
+ setForm((current) => ({ ...current, [field]: value }));
+ };
+
+ const toggleService = (serviceId: string) => {
+ setValidationMessage('');
+ setForm((current) => {
+ const nextServices = current.services.includes(serviceId)
+ ? current.services.filter((id) => id !== serviceId)
+ : [...current.services, serviceId];
+
+ return { ...current, services: nextServices };
+ });
+ };
+
+ const validateStep = () => {
+ if (activeStep === 1 && (!form.date || !form.time)) {
+ return 'Choose an available date and time to continue.';
+ }
+
+ if (
+ activeStep === 2 &&
+ (!form.make || !form.model || !form.year || !form.registration || !form.vehicleType)
+ ) {
+ return 'Add your vehicle make, model, year, registration and type.';
+ }
+
+ if (activeStep === 3 && form.services.length === 0) {
+ return 'Select at least one service.';
+ }
+
+ if (activeStep === 5 && (!form.fullName || !form.email || !form.phone)) {
+ return 'Add your name, email and phone number.';
+ }
+
+ if (
+ activeStep === 6 &&
+ form.serviceLocationType.includes('Mobile') &&
+ (!form.streetAddress || !form.city || !form.postcode)
+ ) {
+ return 'Add your service address, city and postcode.';
+ }
+
+ return '';
+ };
+
+ const goToNextStep = () => {
+ const error = validateStep();
+ if (error) {
+ setValidationMessage(error);
+ return;
+ }
+
+ setValidationMessage('');
+ setActiveStep((step) => Math.min(step + 1, 8));
+ };
+
+ const confirmBooking = () => {
+ const bookingNumber = `BB-${new Date().getFullYear()}-${Math.floor(1000 + Math.random() * 9000)}`;
+ const booking: BookingRecord = {
+ ...form,
+ bookingNumber,
+ estimate,
+ createdAt: new Date().toISOString(),
+ status: 'Pending confirmation',
};
+ const nextBookings = [booking, ...bookings];
+
+ setBookings(nextBookings);
+ setConfirmedBooking(booking);
+ setSelectedBookingNumber(booking.bookingNumber);
+ setForm(initialForm);
+ setActiveStep(1);
+
+ try {
+ window.localStorage.setItem(bookingStorageKey, JSON.stringify(nextBookings));
+ } catch (error) {
+ console.error('Failed to save Bumper Buddies booking to local storage:', error);
+ }
+ };
+
+ const inputClass =
+ 'w-full rounded-2xl border border-zinc-200 bg-white px-4 py-3 text-sm text-zinc-950 shadow-sm outline-none transition focus:border-red-600 focus:ring-4 focus:ring-red-100';
+ const labelClass = 'mb-2 block text-sm font-semibold text-zinc-800';
+
+ const renderBookingStep = () => {
+ if (activeStep === 1) {
+ return (
+
+
+ Available date
+ updateForm('date', event.target.value)}
+ />
+
+
+ Available time
+ updateForm('time', event.target.value)}
+ >
+ Select a time
+ {['08:00 AM', '10:00 AM', '12:00 PM', '02:00 PM', '04:00 PM'].map((time) => (
+ {time}
+ ))}
+
+
+
+ );
+ }
+
+ if (activeStep === 2) {
+ return (
+
+ {[
+ ['make', 'Vehicle Make', 'Toyota'],
+ ['model', 'Vehicle Model', 'Hilux'],
+ ['year', 'Year', '2021'],
+ ['registration', 'Registration Number', 'ABC123'],
+ ].map(([field, label, placeholder]) => (
+
+ {label}
+ updateForm(field as keyof BookingForm, event.target.value)}
+ />
+
+ ))}
+
+ Vehicle Type
+ updateForm('vehicleType', event.target.value)}
+ >
+ {vehicleTypes.map((vehicle) => (
+ {vehicle.label}
+ ))}
+
+
+
+ );
+ }
+
+ if (activeStep === 3) {
+ return (
+
+ {serviceOptions.map((service) => {
+ const isSelected = form.services.includes(service.id);
+ return (
+ toggleService(service.id)}
+ >
+
+ {service.icon}
+
+ {service.name}
+ From {formatCurrency(service.price)}
+
+ );
+ })}
+
+ );
+ }
+
+ if (activeStep === 4) {
+ return (
+
+
Estimated Total
+
{formatCurrency(estimate)}
+
GST included. Final price confirmed after inspection if required.
+
+ Vehicle: {form.vehicleType}
+ Services: {form.services.length}
+
+ {form.serviceLocationType.includes('Mobile') ? 'Mobile call-out included' : 'Workshop visit'}
+
+
+
+ );
+ }
+
+ if (activeStep === 5) {
+ return (
+
+
+ Full Name
+ updateForm('fullName', event.target.value)}
+ />
+
+
+ Email
+ updateForm('email', event.target.value)}
+ />
+
+
+ Phone Number
+ updateForm('phone', event.target.value)}
+ />
+
+
+ Preferred Contact Method
+ updateForm('contactMethod', event.target.value)}
+ >
+ {['Phone', 'Email', 'Text message'].map((method) => (
+ {method}
+ ))}
+
+
+
+ Special Instructions
+
+
+ );
+ }
+
+ if (activeStep === 6) {
+ return (
+
+
+ Choose service location
+ updateForm('serviceLocationType', event.target.value)}
+ >
+ Mobile Service (Customer Address)
+ Workshop Visit
+
+
+ {form.serviceLocationType.includes('Mobile') ? (
+
+ ) : (
+
+ Workshop visit selected. The Bumper Buddies team will confirm the nearest workshop details.
+
+ )}
+
+ );
+ }
+
+ if (activeStep === 7) {
+ return (
+
+
+ {['Credit Card', 'Debit Card', 'Apple Pay', 'Google Pay', 'Afterpay'].map((method) => (
+ updateForm('paymentMethod', method)}
+ >
+ {method}
+
+ ))}
+
+
+ π Secure checkout preview. Payment gateway wiring is intentionally left off until Stripe/Afterpay account details are confirmed.
+
+
+ );
+ }
+
+ return (
+
+
+
Booking summary
+
+
+
Appointment
+ {form.date} at {form.time}
+
+
+
Vehicle
+ {form.year} {form.make} {form.model} Β· {form.registration}
+
+
+
Services
+ {getServiceNames(form.services)}
+
+
+
Location
+ {form.serviceLocationType}
+
+
+
Payment
+ {form.paymentMethod}
+
+
+
Estimated Total
+ {formatCurrency(estimate)}
+
+
+
+
+ Confirm booking request
+
+
+ );
+ };
return (
-
+ <>
-
{getPageTitle('Starter Page')}
+
{getPageTitle('Mobile Automotive Repairs & Detailing')}
+
-
-
- {contentType === 'image' && contentPosition !== 'background'
- ? imageBlock(illustrationImage)
- : null}
- {contentType === 'video' && contentPosition !== 'background'
- ? videoBlock(illustrationVideo)
- : null}
-
-
-
-
Β© 2026 {title} . All rights reserved
-
- Privacy Policy
-
-
+
+
+
+
+
+
+ Expert mechanics and detailers come to you
+
+
+ Professional Mobile Automotive Repairs & Detailing β We Come To You
+
+
+ From vehicle servicing and mechanical repairs to premium detailing, we bring expert automotive care directly to your home or workplace. Save time while keeping your vehicle in top condition.
+
+
+
+
+ NZ wide-ready
+
+
+ GST included
+
+
+ 8-step booking
+
+
+
+
+
+
+
+
Live estimate
+
{formatCurrency(estimate)}
+
+
Mobile-ready
+
+
+ {serviceOptions.slice(0, 4).map((service) => (
+
+ {service.icon} {service.name}
+ from {formatCurrency(service.price)}
+
+ ))}
+
+
+ Start your booking
+
+
+
+
+
-
+
+
+
+
About Us
+
Dealership-quality workmanship without the dealership wait.
+
+
+
We are committed to providing reliable, affordable and convenient mobile automotive services.
+
Our experienced technicians deliver dealership-quality workmanship with honest pricing and excellent customer service.
+
Customer satisfaction and quality workmanship are our highest priorities.
+
+
+
+
+
+
+
+
Our Services
+
Everything your vehicle needs, delivered professionally.
+
+
+ {marketingServices.map((service, index) => (
+
+
+ {['π§', 'π§°', 'π', 'β¨'][index % 4]}
+
+
{service}
+
+ ))}
+
+
+
+
+
+
+ {whyChooseUs.map((item) => (
+
+
{item.icon}
+
{item.title}
+
{item.copy}
+
+ ))}
+
+
+
+
+
+
+
Booking System
+
Book expert mobile care in minutes.
+
+ Complete the guided flow to calculate a GST-inclusive estimate, generate a booking number and save the appointment into your customer dashboard.
+
+
+ {['Date & time', 'Vehicle details', 'Services', 'Estimate', 'Customer', 'Location', 'Payment', 'Confirmation'].map((step, index) => (
+ setActiveStep(index + 1)}
+ >
+ {index + 1}
+ {step}
+
+ ))}
+
+
+
+
+
+
+
Step {activeStep} of 8
+
+ {['Select Date & Time', 'Vehicle Details', 'Select Services', 'Estimated Price', 'Customer Details', 'Service Location', 'Payment', 'Confirmation'][activeStep - 1]}
+
+
+
+ Estimate
+ {formatCurrency(estimate)}
+
+
+
+ {renderBookingStep()}
+
+ {validationMessage ? (
+
+ {validationMessage}
+
+ ) : null}
+
+ {activeStep < 8 ? (
+
+ setActiveStep((step) => Math.max(step - 1, 1))}
+ >
+ Back
+
+
+ Continue
+
+
+ ) : (
+
setActiveStep(7)}
+ >
+ Back to payment
+
+ )}
+
+
+
+
+ {confirmedBooking ? (
+
+
+
+
Booking confirmed
+
{confirmedBooking.bookingNumber} β confirmation and invoice email queued.
+
+
+ View dashboard
+
+
+
+ ) : null}
+
+
+
+
+
Customer Dashboard
+
Your appointment requests
+
+
+ Owner / worker login
+
+
+
+ {bookings.length === 0 ? (
+
+
No bookings yet.
+
Complete the booking flow above and your appointment summary will appear here.
+
+ Book Now
+
+
+ ) : (
+
+
+ {bookings.map((booking) => (
+ setSelectedBookingNumber(booking.bookingNumber)}
+ >
+ {booking.bookingNumber}
+ {booking.date} Β· {booking.time}
+ {booking.vehicleType} Β· {formatCurrency(booking.estimate)}
+
+ ))}
+
+
+ {selectedBooking ? (
+
+
+
+
Booking detail
+
{selectedBooking.bookingNumber}
+
+
{selectedBooking.status}
+
+
+
+
Appointment
+ {selectedBooking.date} at {selectedBooking.time}
+
+
+
Customer
+ {selectedBooking.fullName} Β· {selectedBooking.phone}
+
+
+
Vehicle
+ {selectedBooking.year} {selectedBooking.make} {selectedBooking.model} ({selectedBooking.registration})
+
+
+
Services
+ {getServiceNames(selectedBooking.services)}
+
+
+
Location
+
+ {selectedBooking.serviceLocationType.includes('Mobile')
+ ? `${selectedBooking.streetAddress}, ${selectedBooking.city} ${selectedBooking.postcode}`
+ : 'Workshop visit'}
+
+
+
+
Payment / invoice
+ {selectedBooking.paymentMethod} Β· Invoice email queued
+
+
+
+
Estimated total, GST included
+
{formatCurrency(selectedBooking.estimate)}
+
+
+ {['Reschedule', 'Cancel', 'Download invoice'].map((action) => (
+ alert(`${action} will be connected in the next workflow iteration.`)}
+ >
+ {action}
+
+ ))}
+
+
+ ) : null}
+
+ )}
+
+
+
+
+ {['Professional, on time and the car looked brand new.', 'The easiest service booking I have ever made.', 'Honest advice, sharp pricing and great workmanship.'].map((quote, index) => (
+
+ β
β
β
β
β
+ β{quote}β
+ Customer testimonial {index + 1}
+
+ ))}
+
+
+
+
+
+
+
FAQ
+
Straight answers before you book.
+
+
+ {faqItems.map((item) => (
+
+
+ {item.question}
+ +
+
+ {item.answer}
+
+ ))}
+
+
+
+
+
+
+
+
+
+
BB
+
+
Bumper Buddies
+
Β© 2026. All rights reserved.
+
+
+
+
+
+
+ >
);
}
-Starter.getLayout = function getLayout(page: ReactElement) {
+BumperBuddiesHome.getLayout = function getLayout(page: ReactElement) {
return {page} ;
};
-