top of page

A world of sparkling self expression awaits you.

We exist to help you unleash your creativity and
SHINE.

Let's create something wild & magical together.

 

17856324995754719.jpg

import { bookings } from 'wix-bookings.v2'; import { services } from 'wix-bookings.v2'; // Custom error class for better error handling class BookingServiceError extends Error { constructor(message, code, originalError) { super(message); this.name = 'BookingServiceError'; this.code = code; this.originalError = originalError; } } // Validate booking data before creating function validateBookingData(bookingData) { const required = ['customerName', 'customerEmail', 'startDate', 'endDate', 'serviceId']; const missing = required.filter(field => !bookingData[field]); if (missing.length) { throw new BookingServiceError( `Missing required fields: ${missing.join(', ')}`, 'VALIDATION_ERROR' ); } // Validate email format const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!emailRegex.test(bookingData.customerEmail)) { throw new BookingServiceError('Invalid email format', 'INVALID_EMAIL'); } // Validate dates const start = new Date(bookingData.startDate); const end = new Date(bookingData.endDate); if (isNaN(start.getTime()) || isNaN(end.getTime())) { throw new BookingServiceError('Invalid date format', 'INVALID_DATE'); } if (end <= start) { throw new BookingServiceError('End date must be after start date', 'INVALID_DATE_RANGE'); } } export async function createBooking(bookingData) { try { // Validate input data validateBookingData(bookingData); const booking = { totalParticipants: 1, contactDetails: { firstName: bookingData.customerName, email: bookingData.customerEmail, phone: bookingData.customerPhone }, bookedEntity: { slot: { startDate: bookingData.startDate, endDate: bookingData.endDate, serviceId: bookingData.serviceId, location: { locationType: "OWNER_BUSINESS" }, resource: bookingData.service?.staffMemberIds?.[0] ? { id: bookingData.service.staffMemberIds[0] } : undefined } }, // Add notification preferences participantNotification: { notifyParticipants: true, message: "Thank you for your booking!" }, // Add status control flowControlSettings: { skipAvailabilityValidation: false } }; const result = await bookings.createBooking(booking); console.log('Booking created successfully:', result); return result; } catch (error) { console.error('Booking creation failed:', { error, data: bookingData, message: error.message, details: error.details }); throw new BookingServiceError( error.message || 'Failed to create booking', error.code || 'BOOKING_CREATION_ERROR', error ); } } export async function cancelBooking(bookingId) { try { if (!bookingId) { throw new BookingServiceError('Booking ID is required', 'MISSING_BOOKING_ID'); } const result = await bookings.updateBookingStatus({ bookingId: bookingId, status: 'CANCELED', notifyParticipants: true }); console.log('Booking cancelled successfully:', result); return result; } catch (error) { console.error('Cancel booking failed:', error); throw new BookingServiceError( error.message || 'Failed to cancel booking', error.code || 'BOOKING_CANCELLATION_ERROR', error ); } } export async function getBookings() { try { const response = await bookings.queryBookings({ filter: {}, paging: { limit: 50, offset: 0 }, sort: [{ fieldName: "startDate", order: "DESC" }] }); if (!response || !Array.isArray(response.bookings)) { throw new BookingServiceError('Invalid response format', 'INVALID_RESPONSE'); } return response.bookings; } catch (error) { console.error('Get bookings failed:', error); throw new BookingServiceError( error.message || 'Failed to fetch bookings', error.code || 'FETCH_BOOKINGS_ERROR', error ); } } export async function getLocations() { try { // Query services to get available locations const servicesResponse = await services.queryServices({ query: { filter: {}, paging: { limit: 50, offset: 0 } } }); // Extract unique locations from services const locationsMap = new Map(); servicesResponse.services.forEach(service => { service.locations?.forEach(location => { if (location.business) { locationsMap.set(location.business.id, { id: location.business.id, name: location.business.name, address: location.business.address, phone: location.business.phone, email: location.business.email }); } }); }); return Array.from(locationsMap.values()); } catch (error) { console.error('Get locations failed:', error); throw new BookingServiceError( error.message || 'Failed to fetch locations', error.code || 'FETCH_LOCATIONS_ERROR', error ); } } export async function queryServices() { try { const response = await services.queryServices({ query: { filter: { type: ["APPOINTMENT", "CLASS", "COURSE"] }, paging: { limit: 50, offset: 0 }, sort: [{ fieldName: "name", order: "ASC" }] } }); if (!response || !Array.isArray(response.services)) { throw new BookingServiceError('Invalid services response format', 'INVALID_RESPONSE'); } return response.services; } catch (error) { console.error('Query services failed:', error); throw new BookingServiceError( error.message || 'Failed to fetch services', error.code || 'FETCH_SERVICES_ERROR', error ); } }

Our Services

We offer a range of services to suit all needs - hit the link to see more!

Kids Facepaint

Airbrush Face & Body Painting

Add flair and colour to any event with our airbrush face and body painting. From intricate designs to bold statements, we tailor our artistry to suit your theme or outfit. Perfect for festivals, birthdays, and corporate gatherings.

Face paint

Braiding

Transform your look with our vibrant braiding services, including festival-ready styles and coloured extensions to match your vibe. We offer single bookings, braid parties, and festival services, starting from $60.

Festival Braids

Face Painting for Kids

Bring magical moments to life with our kids' face painting service, featuring enchanting designs like rainbows, unicorns, and superheroes. Ideal for children under 12, we create art that turns every face into a masterpiece.

Creating Magic In Every Moment

Aristotle

Biodegradable Glitter

Shine Sustainably With Eco-Friendly Glitter

We believe in creating magic without harming the planet. Sustainability is at the heart of everything we do, and that’s why all our glitter is 100% biodegradable, made from eucalyptus trees, and even vegan-friendly!

Our eco-friendly glitter takes just six weeks to decompose in soil and breaks down even faster in water, ensuring it leaves no harmful trace. We’re proud to be as friendly to the planet as we are to our customers, and to provide a way for both you and the earth to shine!

CONTACT

Thanks for submitting!

Subscribe Form

Thanks for subscribing!

"Bring the Joy of Creativity to Your Life with OceanSoulSparkles Facepainting!"

  • alt.text.label.Instagram
  • alt.text.label.Facebook

©2023 by OceanSoulSparkles. Proudly created with Wix.com

bottom of page