more-apartments-astro-integration 1.0.1
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/.more-apartments/availability.json +36 -0
- package/.more-apartments/booking-response.json +15 -0
- package/.more-apartments/categories.json +11 -0
- package/.more-apartments/locations.json +3 -0
- package/.more-apartments/pages.json +46 -0
- package/.more-apartments/posts.json +3 -0
- package/.more-apartments/properties.json +1761 -0
- package/.more-apartments/settings-booking.json +13 -0
- package/.more-apartments/settings-main.json +32 -0
- package/.more-apartments/settings-properties.json +36 -0
- package/.more-apartments/settings-theme.json +78 -0
- package/README.md +982 -0
- package/dist/cli/index.js +1010 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/index.d.mts +2732 -0
- package/dist/index.d.ts +2732 -0
- package/dist/index.js +1009 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +964 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +75 -0
- package/routes/availability.js +40 -0
- package/routes/bookings.js +66 -0
- package/routes/locations.js +28 -0
- package/routes/page.js +27 -0
- package/routes/pages.js +27 -0
- package/routes/post.js +27 -0
- package/routes/posts.js +32 -0
- package/routes/properties.js +31 -0
- package/routes/property.js +27 -0
- package/routes/settings.js +50 -0
- package/src/components/PropertyBookingWidget.astro +169 -0
- package/src/components/PropertySearchGrid.astro +315 -0
- package/src/pages/booking-complete.astro +155 -0
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { generateBookingUrl } from '../index.js';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
propertyExternalId: number;
|
|
6
|
+
propertyName?: string;
|
|
7
|
+
basePrice?: number;
|
|
8
|
+
arrival?: string;
|
|
9
|
+
departure?: string;
|
|
10
|
+
guests?: number;
|
|
11
|
+
buttonText?: string;
|
|
12
|
+
className?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const {
|
|
16
|
+
propertyExternalId,
|
|
17
|
+
propertyName,
|
|
18
|
+
basePrice,
|
|
19
|
+
arrival,
|
|
20
|
+
departure,
|
|
21
|
+
guests = 2,
|
|
22
|
+
buttonText = 'Book Now',
|
|
23
|
+
className = ''
|
|
24
|
+
} = Astro.props;
|
|
25
|
+
|
|
26
|
+
// Generate booking URL if dates are provided
|
|
27
|
+
let bookingUrl: string | null = null;
|
|
28
|
+
if (arrival && departure) {
|
|
29
|
+
bookingUrl = generateBookingUrl(propertyExternalId, arrival, departure, guests);
|
|
30
|
+
}
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
<div class={`property-booking-widget ${className}`.trim()}>
|
|
34
|
+
{propertyName && <h3 class="widget-title">{propertyName}</h3>}
|
|
35
|
+
|
|
36
|
+
<div class="booking-info">
|
|
37
|
+
{basePrice && (
|
|
38
|
+
<div class="price-info">
|
|
39
|
+
<span class="price">${basePrice}</span>
|
|
40
|
+
<span class="price-label">per night</span>
|
|
41
|
+
</div>
|
|
42
|
+
)}
|
|
43
|
+
|
|
44
|
+
<div class="guest-info">
|
|
45
|
+
<span class="guests">{guests} guest{guests !== 1 ? 's' : ''}</span>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<div class="booking-action">
|
|
50
|
+
{bookingUrl ? (
|
|
51
|
+
<a
|
|
52
|
+
href={bookingUrl}
|
|
53
|
+
class="booking-button booking-button--available"
|
|
54
|
+
data-property-id={propertyExternalId}
|
|
55
|
+
data-arrival={arrival}
|
|
56
|
+
data-departure={departure}
|
|
57
|
+
data-guests={guests}
|
|
58
|
+
>
|
|
59
|
+
{buttonText}
|
|
60
|
+
</a>
|
|
61
|
+
) : (
|
|
62
|
+
<button
|
|
63
|
+
class="booking-button booking-button--select-dates"
|
|
64
|
+
onclick="alert('Please select arrival and departure dates to book this property')"
|
|
65
|
+
data-property-id={propertyExternalId}
|
|
66
|
+
>
|
|
67
|
+
Select Dates to Book
|
|
68
|
+
</button>
|
|
69
|
+
)}
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
{arrival && departure && (
|
|
73
|
+
<div class="selected-dates">
|
|
74
|
+
<small>
|
|
75
|
+
{new Date(arrival).toLocaleDateString()} - {new Date(departure).toLocaleDateString()}
|
|
76
|
+
</small>
|
|
77
|
+
</div>
|
|
78
|
+
)}
|
|
79
|
+
</div>
|
|
80
|
+
|
|
81
|
+
<style>
|
|
82
|
+
.property-booking-widget {
|
|
83
|
+
border: 1px solid #e1e5e9;
|
|
84
|
+
border-radius: 8px;
|
|
85
|
+
padding: 1.5rem;
|
|
86
|
+
background: white;
|
|
87
|
+
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.widget-title {
|
|
91
|
+
margin: 0 0 1rem 0;
|
|
92
|
+
font-size: 1.25rem;
|
|
93
|
+
font-weight: 600;
|
|
94
|
+
color: #1f2937;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.booking-info {
|
|
98
|
+
display: flex;
|
|
99
|
+
justify-content: space-between;
|
|
100
|
+
align-items: center;
|
|
101
|
+
margin-bottom: 1.5rem;
|
|
102
|
+
padding-bottom: 1rem;
|
|
103
|
+
border-bottom: 1px solid #e5e7eb;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.price-info {
|
|
107
|
+
display: flex;
|
|
108
|
+
align-items: baseline;
|
|
109
|
+
gap: 0.5rem;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.price {
|
|
113
|
+
font-size: 1.5rem;
|
|
114
|
+
font-weight: 700;
|
|
115
|
+
color: #1f2937;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.price-label {
|
|
119
|
+
color: #6b7280;
|
|
120
|
+
font-size: 0.875rem;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.guest-info {
|
|
124
|
+
color: #6b7280;
|
|
125
|
+
font-size: 0.875rem;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.booking-action {
|
|
129
|
+
margin-bottom: 1rem;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.booking-button {
|
|
133
|
+
width: 100%;
|
|
134
|
+
padding: 0.875rem 1.5rem;
|
|
135
|
+
border-radius: 6px;
|
|
136
|
+
font-weight: 600;
|
|
137
|
+
font-size: 1rem;
|
|
138
|
+
text-decoration: none;
|
|
139
|
+
text-align: center;
|
|
140
|
+
display: inline-block;
|
|
141
|
+
cursor: pointer;
|
|
142
|
+
border: none;
|
|
143
|
+
transition: all 0.2s;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.booking-button--available {
|
|
147
|
+
background-color: #059669;
|
|
148
|
+
color: white;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.booking-button--available:hover {
|
|
152
|
+
background-color: #047857;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.booking-button--select-dates {
|
|
156
|
+
background-color: #f3f4f6;
|
|
157
|
+
color: #4b5563;
|
|
158
|
+
border: 1px solid #d1d5db;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.booking-button--select-dates:hover {
|
|
162
|
+
background-color: #e5e7eb;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.selected-dates {
|
|
166
|
+
text-align: center;
|
|
167
|
+
color: #6b7280;
|
|
168
|
+
}
|
|
169
|
+
</style>
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { searchProperties } from '../index.js';
|
|
3
|
+
import PropertyBookingWidget from './PropertyBookingWidget.astro';
|
|
4
|
+
import client from 'virtual:more-apartments/client';
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
// Search parameters
|
|
8
|
+
arrival?: string;
|
|
9
|
+
departure?: string;
|
|
10
|
+
guests?: number;
|
|
11
|
+
destination?: string;
|
|
12
|
+
segment?: string;
|
|
13
|
+
|
|
14
|
+
// Display options
|
|
15
|
+
showBookingWidgets?: boolean;
|
|
16
|
+
maxResults?: number;
|
|
17
|
+
className?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const {
|
|
21
|
+
arrival,
|
|
22
|
+
departure,
|
|
23
|
+
guests,
|
|
24
|
+
destination,
|
|
25
|
+
segment,
|
|
26
|
+
showBookingWidgets = false,
|
|
27
|
+
maxResults,
|
|
28
|
+
className = ''
|
|
29
|
+
} = Astro.props;
|
|
30
|
+
|
|
31
|
+
// Build search parameters
|
|
32
|
+
const searchParams: any = {};
|
|
33
|
+
if (arrival) searchParams.arrival = arrival;
|
|
34
|
+
if (departure) searchParams.departure = departure;
|
|
35
|
+
if (guests) searchParams.guests = guests;
|
|
36
|
+
if (destination) searchParams.destination = destination;
|
|
37
|
+
if (segment) searchParams.segment = segment;
|
|
38
|
+
|
|
39
|
+
// Search for properties
|
|
40
|
+
let properties = await searchProperties(client, searchParams);
|
|
41
|
+
|
|
42
|
+
// Apply maxResults limit if specified
|
|
43
|
+
if (maxResults && properties.length > maxResults) {
|
|
44
|
+
properties = properties.slice(0, maxResults);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const hasSearchParams = Object.keys(searchParams).length > 0;
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
<div class={`property-search-grid ${className}`.trim()}>
|
|
51
|
+
{hasSearchParams && (
|
|
52
|
+
<div class="search-summary">
|
|
53
|
+
<h2>Search Results</h2>
|
|
54
|
+
<div class="search-details">
|
|
55
|
+
{destination && <span class="search-param">📍 {destination}</span>}
|
|
56
|
+
{arrival && departure && (
|
|
57
|
+
<span class="search-param">
|
|
58
|
+
📅 {new Date(arrival).toLocaleDateString()} - {new Date(departure).toLocaleDateString()}
|
|
59
|
+
</span>
|
|
60
|
+
)}
|
|
61
|
+
{guests && <span class="search-param">👥 {guests} guest{guests !== 1 ? 's' : ''}</span>}
|
|
62
|
+
</div>
|
|
63
|
+
<p class="results-count">
|
|
64
|
+
{properties.length === 0 ? 'No properties found' : `${properties.length} propert${properties.length !== 1 ? 'ies' : 'y'} found`}
|
|
65
|
+
</p>
|
|
66
|
+
</div>
|
|
67
|
+
)}
|
|
68
|
+
|
|
69
|
+
{properties.length === 0 ? (
|
|
70
|
+
<div class="no-results">
|
|
71
|
+
<div class="no-results-content">
|
|
72
|
+
<h3>No Properties Found</h3>
|
|
73
|
+
<p>Try adjusting your search criteria:</p>
|
|
74
|
+
<ul>
|
|
75
|
+
<li>Check different dates</li>
|
|
76
|
+
<li>Try a different destination</li>
|
|
77
|
+
<li>Adjust the number of guests</li>
|
|
78
|
+
</ul>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
) : (
|
|
82
|
+
<div class="properties-grid">
|
|
83
|
+
{properties.map((property) => (
|
|
84
|
+
<div class="property-card" key={property.id}>
|
|
85
|
+
<div class="property-header">
|
|
86
|
+
<h3 class="property-name">
|
|
87
|
+
<a href={`/properties/${property.slug}`}>
|
|
88
|
+
{property.name}
|
|
89
|
+
</a>
|
|
90
|
+
</h3>
|
|
91
|
+
<p class="property-type">{property.type}</p>
|
|
92
|
+
</div>
|
|
93
|
+
|
|
94
|
+
<div class="property-details">
|
|
95
|
+
<div class="location">
|
|
96
|
+
<span class="city">{property.city}</span>
|
|
97
|
+
{property.country && <span class="country">, {property.country}</span>}
|
|
98
|
+
</div>
|
|
99
|
+
|
|
100
|
+
<div class="occupancy">
|
|
101
|
+
<span>Up to {property.max_occupancy} guests</span>
|
|
102
|
+
</div>
|
|
103
|
+
|
|
104
|
+
{property.description && (
|
|
105
|
+
<p class="description">
|
|
106
|
+
{property.description.length > 150
|
|
107
|
+
? `${property.description.substring(0, 150)}...`
|
|
108
|
+
: property.description
|
|
109
|
+
}
|
|
110
|
+
</p>
|
|
111
|
+
)}
|
|
112
|
+
</div>
|
|
113
|
+
|
|
114
|
+
{showBookingWidgets && arrival && departure && (
|
|
115
|
+
<div class="booking-widget-container">
|
|
116
|
+
<PropertyBookingWidget
|
|
117
|
+
propertyExternalId={property.external_id || property.id}
|
|
118
|
+
propertyName={property.name}
|
|
119
|
+
arrival={arrival}
|
|
120
|
+
departure={departure}
|
|
121
|
+
guests={guests || 2}
|
|
122
|
+
buttonText="Book Now"
|
|
123
|
+
className="compact-widget"
|
|
124
|
+
/>
|
|
125
|
+
</div>
|
|
126
|
+
)}
|
|
127
|
+
|
|
128
|
+
{!showBookingWidgets && (
|
|
129
|
+
<div class="property-actions">
|
|
130
|
+
<a href={`/properties/${property.slug}`} class="view-details-btn">
|
|
131
|
+
View Details
|
|
132
|
+
</a>
|
|
133
|
+
</div>
|
|
134
|
+
)}
|
|
135
|
+
</div>
|
|
136
|
+
))}
|
|
137
|
+
</div>
|
|
138
|
+
)}
|
|
139
|
+
</div>
|
|
140
|
+
|
|
141
|
+
<style>
|
|
142
|
+
.property-search-grid {
|
|
143
|
+
max-width: 1200px;
|
|
144
|
+
margin: 0 auto;
|
|
145
|
+
padding: 1rem;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.search-summary {
|
|
149
|
+
margin-bottom: 2rem;
|
|
150
|
+
padding: 1.5rem;
|
|
151
|
+
background: #f8fafc;
|
|
152
|
+
border-radius: 8px;
|
|
153
|
+
border-left: 4px solid #3b82f6;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.search-summary h2 {
|
|
157
|
+
margin: 0 0 1rem 0;
|
|
158
|
+
color: #1f2937;
|
|
159
|
+
font-size: 1.5rem;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.search-details {
|
|
163
|
+
display: flex;
|
|
164
|
+
flex-wrap: wrap;
|
|
165
|
+
gap: 1rem;
|
|
166
|
+
margin-bottom: 0.5rem;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.search-param {
|
|
170
|
+
background: white;
|
|
171
|
+
padding: 0.25rem 0.75rem;
|
|
172
|
+
border-radius: 20px;
|
|
173
|
+
font-size: 0.875rem;
|
|
174
|
+
border: 1px solid #e5e7eb;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.results-count {
|
|
178
|
+
margin: 0;
|
|
179
|
+
color: #6b7280;
|
|
180
|
+
font-weight: 500;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.no-results {
|
|
184
|
+
display: flex;
|
|
185
|
+
justify-content: center;
|
|
186
|
+
align-items: center;
|
|
187
|
+
min-height: 300px;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.no-results-content {
|
|
191
|
+
text-align: center;
|
|
192
|
+
max-width: 400px;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.no-results-content h3 {
|
|
196
|
+
color: #374151;
|
|
197
|
+
margin-bottom: 1rem;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.no-results-content ul {
|
|
201
|
+
text-align: left;
|
|
202
|
+
color: #6b7280;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.properties-grid {
|
|
206
|
+
display: grid;
|
|
207
|
+
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
|
|
208
|
+
gap: 1.5rem;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.property-card {
|
|
212
|
+
background: white;
|
|
213
|
+
border: 1px solid #e5e7eb;
|
|
214
|
+
border-radius: 8px;
|
|
215
|
+
padding: 1.5rem;
|
|
216
|
+
transition: box-shadow 0.2s;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.property-card:hover {
|
|
220
|
+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.property-header {
|
|
224
|
+
margin-bottom: 1rem;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.property-name {
|
|
228
|
+
margin: 0 0 0.25rem 0;
|
|
229
|
+
font-size: 1.25rem;
|
|
230
|
+
font-weight: 600;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.property-name a {
|
|
234
|
+
color: #1f2937;
|
|
235
|
+
text-decoration: none;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.property-name a:hover {
|
|
239
|
+
color: #3b82f6;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
.property-type {
|
|
243
|
+
margin: 0;
|
|
244
|
+
color: #6b7280;
|
|
245
|
+
font-size: 0.875rem;
|
|
246
|
+
text-transform: capitalize;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.property-details {
|
|
250
|
+
margin-bottom: 1.5rem;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.location {
|
|
254
|
+
margin-bottom: 0.5rem;
|
|
255
|
+
color: #4b5563;
|
|
256
|
+
font-size: 0.875rem;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
.occupancy {
|
|
260
|
+
margin-bottom: 1rem;
|
|
261
|
+
color: #6b7280;
|
|
262
|
+
font-size: 0.875rem;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.description {
|
|
266
|
+
margin: 0;
|
|
267
|
+
color: #4b5563;
|
|
268
|
+
line-height: 1.5;
|
|
269
|
+
font-size: 0.875rem;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
.booking-widget-container {
|
|
273
|
+
margin-top: 1rem;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
:global(.compact-widget) {
|
|
277
|
+
padding: 1rem;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
:global(.compact-widget .widget-title) {
|
|
281
|
+
font-size: 1rem;
|
|
282
|
+
margin-bottom: 0.75rem;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
.property-actions {
|
|
286
|
+
display: flex;
|
|
287
|
+
justify-content: flex-end;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
.view-details-btn {
|
|
291
|
+
background: #3b82f6;
|
|
292
|
+
color: white;
|
|
293
|
+
padding: 0.5rem 1rem;
|
|
294
|
+
border-radius: 4px;
|
|
295
|
+
text-decoration: none;
|
|
296
|
+
font-size: 0.875rem;
|
|
297
|
+
font-weight: 500;
|
|
298
|
+
transition: background-color 0.2s;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
.view-details-btn:hover {
|
|
302
|
+
background: #2563eb;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
@media (max-width: 768px) {
|
|
306
|
+
.properties-grid {
|
|
307
|
+
grid-template-columns: 1fr;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.search-details {
|
|
311
|
+
flex-direction: column;
|
|
312
|
+
align-items: flex-start;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
</style>
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
---
|
|
2
|
+
// This is an example booking complete page
|
|
3
|
+
// Users can copy this to their Astro project's src/pages/ directory
|
|
4
|
+
const title = 'Booking Complete';
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<html lang="en">
|
|
8
|
+
<head>
|
|
9
|
+
<meta charset="UTF-8">
|
|
10
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
11
|
+
<title>{title}</title>
|
|
12
|
+
<style>
|
|
13
|
+
body {
|
|
14
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
15
|
+
background: #f9fafb;
|
|
16
|
+
margin: 0;
|
|
17
|
+
padding: 0;
|
|
18
|
+
}
|
|
19
|
+
.container {
|
|
20
|
+
max-width: 600px;
|
|
21
|
+
margin: 0 auto;
|
|
22
|
+
padding: 2rem 1rem;
|
|
23
|
+
text-align: center;
|
|
24
|
+
}
|
|
25
|
+
.success-card {
|
|
26
|
+
background: white;
|
|
27
|
+
border-radius: 12px;
|
|
28
|
+
padding: 3rem 2rem;
|
|
29
|
+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
30
|
+
}
|
|
31
|
+
.success-icon {
|
|
32
|
+
width: 64px;
|
|
33
|
+
height: 64px;
|
|
34
|
+
background: #10b981;
|
|
35
|
+
border-radius: 50%;
|
|
36
|
+
margin: 0 auto 1.5rem;
|
|
37
|
+
display: flex;
|
|
38
|
+
align-items: center;
|
|
39
|
+
justify-content: center;
|
|
40
|
+
}
|
|
41
|
+
.success-icon svg {
|
|
42
|
+
width: 32px;
|
|
43
|
+
height: 32px;
|
|
44
|
+
color: white;
|
|
45
|
+
}
|
|
46
|
+
.success-title {
|
|
47
|
+
font-size: 2rem;
|
|
48
|
+
font-weight: 700;
|
|
49
|
+
color: #111827;
|
|
50
|
+
margin: 0 0 1rem 0;
|
|
51
|
+
}
|
|
52
|
+
.success-message {
|
|
53
|
+
color: #6b7280;
|
|
54
|
+
font-size: 1.125rem;
|
|
55
|
+
line-height: 1.6;
|
|
56
|
+
margin: 0 0 2rem 0;
|
|
57
|
+
}
|
|
58
|
+
.next-steps {
|
|
59
|
+
text-align: left;
|
|
60
|
+
margin: 2rem 0;
|
|
61
|
+
padding: 1.5rem;
|
|
62
|
+
background: #f3f4f6;
|
|
63
|
+
border-radius: 8px;
|
|
64
|
+
}
|
|
65
|
+
.next-steps h3 {
|
|
66
|
+
margin: 0 0 1rem 0;
|
|
67
|
+
color: #374151;
|
|
68
|
+
}
|
|
69
|
+
.next-steps ul {
|
|
70
|
+
margin: 0;
|
|
71
|
+
padding-left: 1.5rem;
|
|
72
|
+
color: #4b5563;
|
|
73
|
+
}
|
|
74
|
+
.next-steps li {
|
|
75
|
+
margin-bottom: 0.5rem;
|
|
76
|
+
}
|
|
77
|
+
.button-group {
|
|
78
|
+
display: flex;
|
|
79
|
+
gap: 1rem;
|
|
80
|
+
justify-content: center;
|
|
81
|
+
flex-wrap: wrap;
|
|
82
|
+
}
|
|
83
|
+
.button {
|
|
84
|
+
padding: 0.75rem 1.5rem;
|
|
85
|
+
border-radius: 6px;
|
|
86
|
+
font-weight: 600;
|
|
87
|
+
text-decoration: none;
|
|
88
|
+
display: inline-block;
|
|
89
|
+
transition: all 0.2s;
|
|
90
|
+
}
|
|
91
|
+
.button-primary {
|
|
92
|
+
background: #2563eb;
|
|
93
|
+
color: white;
|
|
94
|
+
}
|
|
95
|
+
.button-primary:hover {
|
|
96
|
+
background: #1d4ed8;
|
|
97
|
+
}
|
|
98
|
+
.button-secondary {
|
|
99
|
+
background: white;
|
|
100
|
+
color: #374151;
|
|
101
|
+
border: 1px solid #d1d5db;
|
|
102
|
+
}
|
|
103
|
+
.button-secondary:hover {
|
|
104
|
+
background: #f9fafb;
|
|
105
|
+
}
|
|
106
|
+
.contact-info {
|
|
107
|
+
margin-top: 2rem;
|
|
108
|
+
padding-top: 2rem;
|
|
109
|
+
border-top: 1px solid #e5e7eb;
|
|
110
|
+
font-size: 0.875rem;
|
|
111
|
+
color: #6b7280;
|
|
112
|
+
}
|
|
113
|
+
</style>
|
|
114
|
+
</head>
|
|
115
|
+
<body>
|
|
116
|
+
<div class="container">
|
|
117
|
+
<div class="success-card">
|
|
118
|
+
<div class="success-icon">
|
|
119
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
120
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
|
|
121
|
+
</svg>
|
|
122
|
+
</div>
|
|
123
|
+
|
|
124
|
+
<h1 class="success-title">Booking Confirmed!</h1>
|
|
125
|
+
|
|
126
|
+
<p class="success-message">
|
|
127
|
+
Thank you for your reservation! Your booking has been successfully processed and confirmed.
|
|
128
|
+
You should receive a confirmation email shortly with all the details of your stay.
|
|
129
|
+
</p>
|
|
130
|
+
|
|
131
|
+
<div class="next-steps">
|
|
132
|
+
<h3>What happens next?</h3>
|
|
133
|
+
<ul>
|
|
134
|
+
<li>You'll receive a confirmation email within the next few minutes</li>
|
|
135
|
+
<li>Check-in instructions will be sent 24 hours before your arrival</li>
|
|
136
|
+
<li>If you have any questions, don't hesitate to contact us</li>
|
|
137
|
+
</ul>
|
|
138
|
+
</div>
|
|
139
|
+
|
|
140
|
+
<div class="button-group">
|
|
141
|
+
<a href="/" class="button button-primary">
|
|
142
|
+
Return to Home
|
|
143
|
+
</a>
|
|
144
|
+
<a href="/properties" class="button button-secondary">
|
|
145
|
+
View More Properties
|
|
146
|
+
</a>
|
|
147
|
+
</div>
|
|
148
|
+
|
|
149
|
+
<div class="contact-info">
|
|
150
|
+
<p>Need help? Contact us at support@more-apartments.com</p>
|
|
151
|
+
</div>
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
</body>
|
|
155
|
+
</html>
|