@ossy/booking 1.15.7 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +7 -7
- package/src/AvailabilityEditor.jsx +22 -15
- package/src/BookingForm.jsx +18 -28
- package/src/Definition.js +1 -23
- package/src/SalesSection.jsx +9 -4
- package/src/availability-setup.page.jsx +77 -110
- package/src/availability.page.jsx +25 -23
- package/src/booking-card.component.jsx +24 -33
- package/src/booking-detail.page.jsx +61 -205
- package/src/booking-page.page.jsx +4 -7
- package/src/bookings.page.jsx +32 -22
- package/src/en.translations.json +213 -0
- package/src/home.page.jsx +48 -5
- package/src/public-booking.page.jsx +81 -222
- package/src/services.page.jsx +44 -43
- package/src/sv.translations.json +213 -0
package/src/bookings.page.jsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import React, { useState, useEffect, useCallback } from 'react'
|
|
2
|
-
import { View, Title, Text, Tabs, Alert } from '@ossy/design-system'
|
|
1
|
+
import React, { useState, useEffect, useCallback, useMemo } from 'react'
|
|
2
|
+
import { View, Title, Text, Tabs, Alert, useLocale } from '@ossy/design-system'
|
|
3
3
|
import { Definition } from './Definition.js'
|
|
4
4
|
import { BookingCard } from './booking-card.component.jsx'
|
|
5
5
|
|
|
@@ -11,24 +11,34 @@ export const metadata = {
|
|
|
11
11
|
},
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
const TABS = [
|
|
15
|
-
{ id: 'pending', label: 'Förfrågningar' },
|
|
16
|
-
{ id: 'confirmed', label: 'Bekräftade' },
|
|
17
|
-
{ id: 'all', label: 'Alla' },
|
|
18
|
-
]
|
|
19
|
-
|
|
20
|
-
const EMPTY_MESSAGES = {
|
|
21
|
-
pending: { heading: 'Inga förfrågningar', body: 'Du har inga väntande bokningsförfrågningar just nu.' },
|
|
22
|
-
confirmed: { heading: 'Inga bekräftade bokningar', body: 'Bekräftade bokningar visas här.' },
|
|
23
|
-
all: { heading: 'Inga bokningar', body: 'Bokningar från dina klienter visas här.' },
|
|
24
|
-
}
|
|
25
|
-
|
|
26
14
|
export default function BookingsPage () {
|
|
15
|
+
const { t } = useLocale()
|
|
27
16
|
const [activeTab, setActiveTab] = useState('pending')
|
|
28
17
|
const [bookings, setBookings] = useState([])
|
|
29
18
|
const [loading, setLoading] = useState(true)
|
|
30
19
|
const [error, setError] = useState(null)
|
|
31
20
|
|
|
21
|
+
const TABS = useMemo(() => [
|
|
22
|
+
{ id: 'pending', label: t('booking.bookings.tab.pending') },
|
|
23
|
+
{ id: 'confirmed', label: t('booking.bookings.tab.confirmed') },
|
|
24
|
+
{ id: 'all', label: t('booking.bookings.tab.all') },
|
|
25
|
+
], [t])
|
|
26
|
+
|
|
27
|
+
const EMPTY_MESSAGES = useMemo(() => ({
|
|
28
|
+
pending: {
|
|
29
|
+
heading: t('booking.bookings.empty.pending.heading'),
|
|
30
|
+
body: t('booking.bookings.empty.pending.body'),
|
|
31
|
+
},
|
|
32
|
+
confirmed: {
|
|
33
|
+
heading: t('booking.bookings.empty.confirmed.heading'),
|
|
34
|
+
body: t('booking.bookings.empty.confirmed.body'),
|
|
35
|
+
},
|
|
36
|
+
all: {
|
|
37
|
+
heading: t('booking.bookings.empty.all.heading'),
|
|
38
|
+
body: t('booking.bookings.empty.all.body'),
|
|
39
|
+
},
|
|
40
|
+
}), [t])
|
|
41
|
+
|
|
32
42
|
const loadBookings = useCallback(async () => {
|
|
33
43
|
setLoading(true)
|
|
34
44
|
setError(null)
|
|
@@ -40,7 +50,7 @@ export default function BookingsPage () {
|
|
|
40
50
|
})
|
|
41
51
|
if (!res.ok) {
|
|
42
52
|
const data = await res.json().catch(() => ({}))
|
|
43
|
-
throw new Error(data?.message ??
|
|
53
|
+
throw new Error(data?.message ?? t('booking.bookings.errorStatus', { status: res.status }))
|
|
44
54
|
}
|
|
45
55
|
const data = await res.json()
|
|
46
56
|
setBookings(data)
|
|
@@ -49,7 +59,7 @@ export default function BookingsPage () {
|
|
|
49
59
|
} finally {
|
|
50
60
|
setLoading(false)
|
|
51
61
|
}
|
|
52
|
-
}, [])
|
|
62
|
+
}, [t])
|
|
53
63
|
|
|
54
64
|
useEffect(() => {
|
|
55
65
|
loadBookings()
|
|
@@ -67,7 +77,7 @@ export default function BookingsPage () {
|
|
|
67
77
|
})
|
|
68
78
|
if (!res.ok) {
|
|
69
79
|
const data = await res.json().catch(() => ({}))
|
|
70
|
-
throw new Error(data?.message ?? '
|
|
80
|
+
throw new Error(data?.message ?? t('booking.bookings.errorConfirm'))
|
|
71
81
|
}
|
|
72
82
|
await loadBookings()
|
|
73
83
|
}
|
|
@@ -80,7 +90,7 @@ export default function BookingsPage () {
|
|
|
80
90
|
})
|
|
81
91
|
if (!res.ok) {
|
|
82
92
|
const data = await res.json().catch(() => ({}))
|
|
83
|
-
throw new Error(data?.message ?? '
|
|
93
|
+
throw new Error(data?.message ?? t('booking.bookings.errorDecline'))
|
|
84
94
|
}
|
|
85
95
|
await loadBookings()
|
|
86
96
|
}
|
|
@@ -93,7 +103,7 @@ export default function BookingsPage () {
|
|
|
93
103
|
})
|
|
94
104
|
if (!res.ok) {
|
|
95
105
|
const data = await res.json().catch(() => ({}))
|
|
96
|
-
throw new Error(data?.message ?? '
|
|
106
|
+
throw new Error(data?.message ?? t('booking.bookings.errorCancel'))
|
|
97
107
|
}
|
|
98
108
|
await loadBookings()
|
|
99
109
|
}
|
|
@@ -111,9 +121,9 @@ export default function BookingsPage () {
|
|
|
111
121
|
style={{ padding: 'var(--space-m) var(--space-l)', height: '100%', overflowY: 'auto' }}
|
|
112
122
|
>
|
|
113
123
|
<View inset="s" gap="s">
|
|
114
|
-
<Title>{Definition.title} —
|
|
124
|
+
<Title>{Definition.title} — {t('booking.bookings.titleSuffix')}</Title>
|
|
115
125
|
<Text style={{ maxWidth: '400px' }}>
|
|
116
|
-
|
|
126
|
+
{t('booking.bookings.description')}
|
|
117
127
|
</Text>
|
|
118
128
|
</View>
|
|
119
129
|
|
|
@@ -126,7 +136,7 @@ export default function BookingsPage () {
|
|
|
126
136
|
|
|
127
137
|
{loading ? (
|
|
128
138
|
<Text color="secondary" style={{ textAlign: 'center', padding: 'var(--space-l)' }}>
|
|
129
|
-
|
|
139
|
+
{t('booking.bookings.loading')}
|
|
130
140
|
</Text>
|
|
131
141
|
) : error ? (
|
|
132
142
|
<Alert variant="danger">{error}</Alert>
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
{
|
|
2
|
+
"booking.home.documentTitle": "Booking calendar – Ossy",
|
|
3
|
+
"booking.home.cover.title": "Let clients book time directly",
|
|
4
|
+
"booking.home.cover.text": "Share a link. Clients pick a slot. You focus on the work.",
|
|
5
|
+
"booking.home.cover.ctaPrimary": "Get started free",
|
|
6
|
+
"booking.home.cover.ctaSecondary": "See an example",
|
|
7
|
+
"booking.home.features.page.title": "Your booking page",
|
|
8
|
+
"booking.home.features.page.text": "A personal page at ossy.se/booking/your-name. Share the link with clients — that's all it takes.",
|
|
9
|
+
"booking.home.features.confirmations.title": "Automatic confirmations",
|
|
10
|
+
"booking.home.features.confirmations.text": "Clients get a confirmation with a calendar invite instantly. No manual steps on your side.",
|
|
11
|
+
"booking.home.features.availability.title": "Manage your time",
|
|
12
|
+
"booking.home.features.availability.text": "Set when you're available. We only show open slots — never double-booked.",
|
|
13
|
+
"booking.home.features.email.title": "Email ping-pong",
|
|
14
|
+
"booking.home.features.email.text": "Skip days of back-and-forth just to find a shared slot.",
|
|
15
|
+
"booking.home.features.doubleBook.title": "No double bookings",
|
|
16
|
+
"booking.home.features.doubleBook.text": "One calendar here, one link there — we keep track so the same slot isn't booked twice.",
|
|
17
|
+
"booking.sales.overview": "Overview",
|
|
18
|
+
"booking.sales.features": "Features",
|
|
19
|
+
"booking.bookings.documentTitle": "Bookings",
|
|
20
|
+
"booking.bookings.titleSuffix": "Bookings",
|
|
21
|
+
"booking.bookings.description": "Manage booking requests and confirmed meetings.",
|
|
22
|
+
"booking.bookings.tab.pending": "Requests",
|
|
23
|
+
"booking.bookings.tab.confirmed": "Confirmed",
|
|
24
|
+
"booking.bookings.tab.all": "All",
|
|
25
|
+
"booking.bookings.empty.pending.heading": "No requests",
|
|
26
|
+
"booking.bookings.empty.pending.body": "You have no pending booking requests right now.",
|
|
27
|
+
"booking.bookings.empty.confirmed.heading": "No confirmed bookings",
|
|
28
|
+
"booking.bookings.empty.confirmed.body": "Confirmed bookings appear here.",
|
|
29
|
+
"booking.bookings.empty.all.heading": "No bookings",
|
|
30
|
+
"booking.bookings.empty.all.body": "Bookings from your clients appear here.",
|
|
31
|
+
"booking.bookings.loading": "Loading…",
|
|
32
|
+
"booking.bookings.errorStatus": "Error {status}",
|
|
33
|
+
"booking.bookings.errorConfirm": "Confirmation failed",
|
|
34
|
+
"booking.bookings.errorDecline": "Decline failed",
|
|
35
|
+
"booking.bookings.errorCancel": "Cancellation failed",
|
|
36
|
+
"booking.bookingDetail.documentTitle": "Booking details",
|
|
37
|
+
"booking.bookingDetail.back": "← All bookings",
|
|
38
|
+
"booking.bookingDetail.loading": "Loading…",
|
|
39
|
+
"booking.bookingDetail.notFound": "Booking not found",
|
|
40
|
+
"booking.bookingDetail.errorStatus": "Error {status}",
|
|
41
|
+
"booking.bookingDetail.status.pending": "Awaiting confirmation",
|
|
42
|
+
"booking.bookingDetail.status.confirmed": "Confirmed",
|
|
43
|
+
"booking.bookingDetail.status.cancelled": "Cancelled",
|
|
44
|
+
"booking.bookingDetail.label.dateTime": "Date and time",
|
|
45
|
+
"booking.bookingDetail.label.duration": "Duration",
|
|
46
|
+
"booking.bookingDetail.label.message": "Message",
|
|
47
|
+
"booking.bookingDetail.durationMinutes": "{minutes} minutes",
|
|
48
|
+
"booking.bookingDetail.durationHours": "{hours} hour",
|
|
49
|
+
"booking.bookingDetail.durationHoursMinutes": "{hours} hour {minutes} min",
|
|
50
|
+
"booking.bookingDetail.manageRequest": "Manage request",
|
|
51
|
+
"booking.bookingDetail.manageBooking": "Manage booking",
|
|
52
|
+
"booking.bookingDetail.confirm": "Confirm booking",
|
|
53
|
+
"booking.bookingDetail.confirming": "Confirming…",
|
|
54
|
+
"booking.bookingDetail.errorConfirm": "Confirmation failed",
|
|
55
|
+
"booking.bookingDetail.decline": "Decline request",
|
|
56
|
+
"booking.bookingDetail.declineTitle": "Decline booking request",
|
|
57
|
+
"booking.bookingDetail.declinePlaceholder": "E.g. Unfortunately the requested time is no longer available…",
|
|
58
|
+
"booking.bookingDetail.declineReasonHint": "Reason (optional — sent to the client)",
|
|
59
|
+
"booking.bookingDetail.declineConfirm": "Confirm decline",
|
|
60
|
+
"booking.bookingDetail.declining": "Declining…",
|
|
61
|
+
"booking.bookingDetail.errorDecline": "Decline failed",
|
|
62
|
+
"booking.bookingDetail.cancelMeeting": "Cancel meeting",
|
|
63
|
+
"booking.bookingDetail.cancelTitle": "Cancel confirmed booking",
|
|
64
|
+
"booking.bookingDetail.cancelBody": "The client will be notified by email. This action cannot be undone.",
|
|
65
|
+
"booking.bookingDetail.cancelConfirm": "Confirm cancellation",
|
|
66
|
+
"booking.bookingDetail.cancelling": "Cancelling…",
|
|
67
|
+
"booking.bookingDetail.errorCancel": "Cancellation failed",
|
|
68
|
+
"booking.bookingDetail.cancelButton": "Cancel",
|
|
69
|
+
"booking.availability.documentTitle": "Availability",
|
|
70
|
+
"booking.availability.titleSuffix": "Availability",
|
|
71
|
+
"booking.availability.description": "Set your weekly availability. Clients can only book slots within these windows.",
|
|
72
|
+
"booking.availabilitySetup.documentTitle": "Availability",
|
|
73
|
+
"booking.availabilitySetup.title": "Availability",
|
|
74
|
+
"booking.availabilitySetup.description": "Set when you are available for bookings. Clients can only book times within these windows.",
|
|
75
|
+
"booking.availabilitySetup.loading": "Loading…",
|
|
76
|
+
"booking.availabilitySetup.weeklySchedule": "Weekly schedule",
|
|
77
|
+
"booking.availabilitySetup.day.monday": "Monday",
|
|
78
|
+
"booking.availabilitySetup.day.tuesday": "Tuesday",
|
|
79
|
+
"booking.availabilitySetup.day.wednesday": "Wednesday",
|
|
80
|
+
"booking.availabilitySetup.day.thursday": "Thursday",
|
|
81
|
+
"booking.availabilitySetup.day.friday": "Friday",
|
|
82
|
+
"booking.availabilitySetup.day.saturday": "Saturday",
|
|
83
|
+
"booking.availabilitySetup.day.sunday": "Sunday",
|
|
84
|
+
"booking.availabilitySetup.unavailable": "Unavailable",
|
|
85
|
+
"booking.availabilitySetup.sessionDuration": "Session length",
|
|
86
|
+
"booking.availabilitySetup.sessionDurationHint": "Choose session lengths clients can select.",
|
|
87
|
+
"booking.availabilitySetup.durationMin": "{minutes} min",
|
|
88
|
+
"booking.availabilitySetup.bufferLabel": "Buffer time between bookings",
|
|
89
|
+
"booking.availabilitySetup.bufferNone": "No buffer",
|
|
90
|
+
"booking.availabilitySetup.bufferMinutes": "{minutes} minutes",
|
|
91
|
+
"booking.availabilitySetup.bufferHint": "Automatic pause added after each booking.",
|
|
92
|
+
"booking.availabilitySetup.timezone": "Time zone",
|
|
93
|
+
"booking.availabilitySetup.save": "Save availability",
|
|
94
|
+
"booking.availabilitySetup.saving": "Saving…",
|
|
95
|
+
"booking.availabilitySetup.errorSave": "Could not save ({status})",
|
|
96
|
+
"booking.availabilitySetup.savedTitle": "Availability saved",
|
|
97
|
+
"booking.availabilitySetup.savedBody": "Your booking link is ready to share with clients.",
|
|
98
|
+
"booking.availabilitySetup.copyLink": "Copy link",
|
|
99
|
+
"booking.availabilitySetup.copied": "Copied!",
|
|
100
|
+
"booking.services.documentTitle": "Services",
|
|
101
|
+
"booking.services.titleSuffix": "Services",
|
|
102
|
+
"booking.services.description": "Define what you offer — name, duration, and price. Clients will see these when booking.",
|
|
103
|
+
"booking.services.addService": "Add service",
|
|
104
|
+
"booking.services.yourServices": "Your services",
|
|
105
|
+
"booking.services.example.introCall.name": "Intro call",
|
|
106
|
+
"booking.services.example.introCall.description": "A free 30-minute intro to see if we're a good fit.",
|
|
107
|
+
"booking.services.example.strategy.name": "Strategy session",
|
|
108
|
+
"booking.services.example.strategy.description": "Deep-dive strategy session.",
|
|
109
|
+
"booking.book.documentTitle": "Book a session",
|
|
110
|
+
"booking.book.title": "Book a session",
|
|
111
|
+
"booking.book.description": "Pick a time that works for you and confirm your appointment.",
|
|
112
|
+
"booking.book.form.chooseService": "Choose a service",
|
|
113
|
+
"booking.book.form.loadingServices": "Loading services for workspace {workspaceId}…",
|
|
114
|
+
"booking.book.form.continuePlaceholder": "Continue (placeholder)",
|
|
115
|
+
"booking.book.form.pickTime": "Pick a time",
|
|
116
|
+
"booking.book.form.slotsPlaceholder": "Available slots will appear here.",
|
|
117
|
+
"booking.book.form.back": "Back",
|
|
118
|
+
"booking.book.form.yourDetails": "Your details",
|
|
119
|
+
"booking.book.form.nameLabel": "Name",
|
|
120
|
+
"booking.book.form.namePlaceholder": "Jane Smith",
|
|
121
|
+
"booking.book.form.emailLabel": "Email",
|
|
122
|
+
"booking.book.form.emailPlaceholder": "jane@example.com",
|
|
123
|
+
"booking.book.form.confirmPay": "Confirm & Pay",
|
|
124
|
+
"booking.book.form.confirmed": "Booking confirmed!",
|
|
125
|
+
"booking.book.form.checkEmail": "Check your email for a confirmation.",
|
|
126
|
+
"booking.availabilityEditor.save": "Save availability",
|
|
127
|
+
"booking.availabilityEditor.unavailable": "Unavailable",
|
|
128
|
+
"booking.availabilityEditor.to": "to",
|
|
129
|
+
"booking.availabilityEditor.buffer": "Buffer",
|
|
130
|
+
"booking.availabilityEditor.min": "min",
|
|
131
|
+
"booking.availabilityEditor.day.sun": "Sun",
|
|
132
|
+
"booking.availabilityEditor.day.mon": "Mon",
|
|
133
|
+
"booking.availabilityEditor.day.tue": "Tue",
|
|
134
|
+
"booking.availabilityEditor.day.wed": "Wed",
|
|
135
|
+
"booking.availabilityEditor.day.thu": "Thu",
|
|
136
|
+
"booking.availabilityEditor.day.fri": "Fri",
|
|
137
|
+
"booking.availabilityEditor.day.sat": "Sat",
|
|
138
|
+
"publicBooking.documentTitle": "Book an appointment",
|
|
139
|
+
"publicBooking.title": "Book an appointment",
|
|
140
|
+
"publicBooking.description": "Choose a date and time that works for you.",
|
|
141
|
+
"publicBooking.loadingSlots": "Loading times…",
|
|
142
|
+
"publicBooking.slotsError": "Could not load available times.",
|
|
143
|
+
"publicBooking.noSlots": "No available times for the selected date.",
|
|
144
|
+
"publicBooking.back": "← Back",
|
|
145
|
+
"publicBooking.selectedTime": "Selected time: {datetime}",
|
|
146
|
+
"publicBooking.durationMin": "({minutes} min)",
|
|
147
|
+
"publicBooking.continue": "Continue →",
|
|
148
|
+
"publicBooking.pickDate": "Select a highlighted date in the calendar",
|
|
149
|
+
"publicBooking.form.name": "Your name",
|
|
150
|
+
"publicBooking.form.namePlaceholder": "Anna Svensson",
|
|
151
|
+
"publicBooking.form.email": "Email address",
|
|
152
|
+
"publicBooking.form.emailPlaceholder": "anna@example.com",
|
|
153
|
+
"publicBooking.form.message": "Message (optional)",
|
|
154
|
+
"publicBooking.form.messagePlaceholder": "Tell us what you'd like to discuss…",
|
|
155
|
+
"publicBooking.form.submit": "Send request",
|
|
156
|
+
"publicBooking.form.submitting": "Sending…",
|
|
157
|
+
"publicBooking.form.error": "Booking failed ({status})",
|
|
158
|
+
"publicBooking.pending.title": "Your request has been sent!",
|
|
159
|
+
"publicBooking.pending.body": "The consultant will confirm shortly. You will receive an email with a calendar invite once the booking is confirmed.",
|
|
160
|
+
"publicBooking.pending.requestedTime": "Requested time",
|
|
161
|
+
"publicBooking.pending.duration": "{minutes} minutes",
|
|
162
|
+
"publicBooking.month.january": "January",
|
|
163
|
+
"publicBooking.month.february": "February",
|
|
164
|
+
"publicBooking.month.march": "March",
|
|
165
|
+
"publicBooking.month.april": "April",
|
|
166
|
+
"publicBooking.month.may": "May",
|
|
167
|
+
"publicBooking.month.june": "June",
|
|
168
|
+
"publicBooking.month.july": "July",
|
|
169
|
+
"publicBooking.month.august": "August",
|
|
170
|
+
"publicBooking.month.september": "September",
|
|
171
|
+
"publicBooking.month.october": "October",
|
|
172
|
+
"publicBooking.month.november": "November",
|
|
173
|
+
"publicBooking.month.december": "December",
|
|
174
|
+
"publicBooking.weekday.sun": "Sun",
|
|
175
|
+
"publicBooking.weekday.mon": "Mon",
|
|
176
|
+
"publicBooking.weekday.tue": "Tue",
|
|
177
|
+
"publicBooking.weekday.wed": "Wed",
|
|
178
|
+
"publicBooking.weekday.thu": "Thu",
|
|
179
|
+
"publicBooking.weekday.fri": "Fri",
|
|
180
|
+
"publicBooking.weekday.sat": "Sat",
|
|
181
|
+
"publicBooking.weekdayLong.sun": "Sunday",
|
|
182
|
+
"publicBooking.weekdayLong.mon": "Monday",
|
|
183
|
+
"publicBooking.weekdayLong.tue": "Tuesday",
|
|
184
|
+
"publicBooking.weekdayLong.wed": "Wednesday",
|
|
185
|
+
"publicBooking.weekdayLong.thu": "Thursday",
|
|
186
|
+
"publicBooking.weekdayLong.fri": "Friday",
|
|
187
|
+
"publicBooking.weekdayLong.sat": "Saturday",
|
|
188
|
+
"booking.card.status.pending": "Pending",
|
|
189
|
+
"booking.card.status.confirmed": "Confirmed",
|
|
190
|
+
"booking.card.status.cancelled": "Cancelled",
|
|
191
|
+
"booking.card.view": "View →",
|
|
192
|
+
"booking.card.confirm": "Confirm",
|
|
193
|
+
"booking.card.decline": "Decline",
|
|
194
|
+
"booking.card.cancel": "Cancel",
|
|
195
|
+
"booking.card.waiting": "Waiting…",
|
|
196
|
+
"booking.card.errorGeneric": "Something went wrong",
|
|
197
|
+
"booking/create.label": "Create booking",
|
|
198
|
+
"booking/create.description": "Create a new booking request from a client",
|
|
199
|
+
"booking/get-available-slots.label": "Get available slots",
|
|
200
|
+
"booking/get-available-slots.description": "List bookable time slots for a consultant",
|
|
201
|
+
"booking/get-availability.label": "Get availability",
|
|
202
|
+
"booking/get-availability.description": "Load weekly availability settings for the workspace",
|
|
203
|
+
"booking/save-availability.label": "Save availability",
|
|
204
|
+
"booking/save-availability.description": "Save weekly availability and booking preferences",
|
|
205
|
+
"booking/list.label": "List bookings",
|
|
206
|
+
"booking/list.description": "List all bookings for the current workspace",
|
|
207
|
+
"booking/decline.label": "Decline booking",
|
|
208
|
+
"booking/decline.description": "Decline a pending booking request",
|
|
209
|
+
"booking/confirm.label": "Confirm booking",
|
|
210
|
+
"booking/confirm.description": "Confirm a pending booking request",
|
|
211
|
+
"booking/cancel.label": "Cancel booking",
|
|
212
|
+
"booking/cancel.description": "Cancel a confirmed booking"
|
|
213
|
+
}
|
package/src/home.page.jsx
CHANGED
|
@@ -1,13 +1,56 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import {
|
|
3
|
-
import { features } from './features.js'
|
|
2
|
+
import { useLocale } from '@ossy/design-system'
|
|
4
3
|
import SalesSection from './SalesSection.jsx'
|
|
5
4
|
|
|
6
5
|
export const metadata = {
|
|
7
6
|
id: 'booking/home',
|
|
8
|
-
title: 'Bokningskalender – Ossy',
|
|
9
|
-
description: 'Låt kunder boka tid direkt. Dela en länk, kunder väljer tid, du fokuserar på jobbet.',
|
|
10
7
|
path: { sv: '/boka', en: '/booking' },
|
|
11
8
|
}
|
|
12
9
|
|
|
13
|
-
|
|
10
|
+
function useBookingHomeContent () {
|
|
11
|
+
const { t } = useLocale()
|
|
12
|
+
|
|
13
|
+
const cover = {
|
|
14
|
+
title: t('booking.home.cover.title'),
|
|
15
|
+
text: t('booking.home.cover.text'),
|
|
16
|
+
actions: [
|
|
17
|
+
{ label: t('booking.home.cover.ctaPrimary'), variant: 'cta', href: '/sign-up' },
|
|
18
|
+
{ label: t('booking.home.cover.ctaSecondary'), variant: 'secondary', href: '/boka/demo' },
|
|
19
|
+
],
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const features = [
|
|
23
|
+
{
|
|
24
|
+
title: t('booking.home.features.page.title'),
|
|
25
|
+
icon: 'share',
|
|
26
|
+
text: t('booking.home.features.page.text'),
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
title: t('booking.home.features.confirmations.title'),
|
|
30
|
+
icon: 'check-circle',
|
|
31
|
+
text: t('booking.home.features.confirmations.text'),
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
title: t('booking.home.features.availability.title'),
|
|
35
|
+
icon: 'calendar',
|
|
36
|
+
text: t('booking.home.features.availability.text'),
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
title: t('booking.home.features.email.title'),
|
|
40
|
+
icon: 'mail',
|
|
41
|
+
text: t('booking.home.features.email.text'),
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
title: t('booking.home.features.doubleBook.title'),
|
|
45
|
+
icon: 'warning',
|
|
46
|
+
text: t('booking.home.features.doubleBook.text'),
|
|
47
|
+
},
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
return { cover, features }
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export default function BookingHomePage () {
|
|
54
|
+
const { cover, features } = useBookingHomeContent()
|
|
55
|
+
return <SalesSection cover={cover} features={features} />
|
|
56
|
+
}
|