Setting the file. One moment.
Service Facts · Wix Vibe Headless · wix/skills · Skills Docs
ContentsBack to the top of the page 22.10
Post Detail
Next
Reference Service Detail
references/bookings/app/lib/ serviceFacts.js
JavaScript · 95 lines · 4 KB
12
const
c
=
service?.schedule?.availabilityConstraints;
13 return c?.sessionDurations?.[ 0 ] ?? c?.durations?.[ 0 ]?.minutes ?? null ;
14 }
15
16 /**
17 * Price label for every rateType. Reading payment.fixed alone renders nothing at all for a VARIED or
18 * NO_FEE service, which is why this branches instead.
19 * FIXED -> "€95.00" (formattedValue when present, else built from value+currency)
20 * VARIED -> "From €85.00" (payment.varied.minPrice, falling back to defaultPrice)
21 * NO_FEE -> "Free"
22 * CUSTOM -> "" (business sets a price at booking time — nothing to show)
23 * SUBSCRIPTION-> "" (paid via a pricing plan, not a per-booking price)
24 * @param {object} service
25 * @returns {string}
26 */
27 export function servicePriceLabel ( service ) {
28 const payment = service?.payment;
29 const money = ( m ) => m?.formattedValue
30 || (m?.currency && new Intl. NumberFormat ( undefined , { style: "currency" , currency: m.currency }). format ( Number (m.value)));
31 switch (payment?.rateType) {
32 case "FIXED" :
33 return money (payment.fixed?.price) || "" ;
34 case "VARIED" : {
35 const from = money (payment.varied?.minPrice ?? payment.varied?.defaultPrice);
36 return from ? `From ${ from }` : "" ;
37 }
38 case "NO_FEE" :
39 return "Free" ;
40 default :
41 return "" ; // CUSTOM / SUBSCRIPTION — no single number to show
42 }
43 }
44
45 /**
46 * "1-to-1" for a single-person service, "Up to N" otherwise. defaultCapacity is the service's own
47 * cap — for a CLASS this is usually the room/session size, for an APPOINTMENT usually 1.
48 * @param {object} service
49 * @returns {string|null}
50 */
51 export function serviceCapacityLabel ( service ) {
52 const cap = service?.defaultCapacity;
53 if ( ! cap) return null ;
54 return cap === 1 ? "1-to-1" : `Up to ${ cap }` ;
55 }
56
57 /**
58 * Where the service happens, from locations[].type — NOT from payment.options, which says how a
59 * customer may *pay* (`online` there means "can pay online", not "happens online"). A video service
60 * is flagged by conferencing.enabled. `calculatedAddress` is present on BUSINESS/CUSTOM locations
61 * and empty for CUSTOMER; when it's there, prefer the actual place name.
62 * BUSINESS -> the business's address ("At Serene Spa" / "In person")
63 * CUSTOMER -> the customer's address ("At your location")
64 * CUSTOM -> a specific address for this service
65 * @param {object} service
66 * @returns {string}
67 */
68 export function serviceLocationLabel ( service ) {
69 if (service?.conferencing?.enabled) return "Online" ;
70 const types = new Set ((service?.locations || []). map (( l ) => l?.type). filter (Boolean));
71 const named = (service?.locations || [])
72 . map (( l ) => l?.calculatedAddress?.formatted || l?.business?.name)
73 . find (Boolean);
74 if (named) return named;
75 if (types. has ( "CUSTOMER" )) return "At your location" ;
76 if (types. has ( "BUSINESS" ) || types. has ( "CUSTOM" )) return "In person" ;
77 return "" ;
78 }
79
80 /**
81 * The reschedule footnote, e.g. "Free to reschedule up to 24 hours before." `enabled` without
82 * `limitLatestReschedule` means any time; with it, the window is latestRescheduleInMinutes. Empty
83 * when rescheduling is off, so the page shows no promise rather than a wrong one.
84 * @param {object} service
85 * @returns {string}
86 */
87 export function serviceRescheduleNote ( service ) {
88 const p = service?.bookingPolicy?.reschedulePolicy;
89 if ( ! p?.enabled) return "" ;
90 if ( ! p.limitLatestReschedule) return "Free to reschedule any time before your appointment." ;
91 const hours = Math. round ((p.latestRescheduleInMinutes ?? 0 ) / 60 );
92 return hours > 0
93 ? `Free to reschedule up to ${ hours } hour${ hours === 1 ? "" : "s"} before.`
94 : "Free to reschedule right up until your appointment." ;
95 }