popsite-ui 1.0.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.
Files changed (87) hide show
  1. package/App.jsx +95 -0
  2. package/README.md +92 -0
  3. package/components/layout/PortalHeader.jsx +18 -0
  4. package/components/layout/SystemSidebar.jsx +33 -0
  5. package/components/modules/AnalyticsDashboardModule.jsx +17 -0
  6. package/components/modules/ChatMessagingModule.jsx +17 -0
  7. package/components/modules/EcommerceStoreModule.jsx +17 -0
  8. package/components/modules/EventTicketBookingModule.jsx +17 -0
  9. package/components/modules/FlightBookingModule.jsx +17 -0
  10. package/components/modules/FoodOrderingModule.jsx +17 -0
  11. package/components/modules/HospitalAppointmentModule.jsx +17 -0
  12. package/components/modules/HotelBookingModule.jsx +17 -0
  13. package/components/modules/InvoiceBillingModule.jsx +17 -0
  14. package/components/modules/LibraryManagementModule.jsx +17 -0
  15. package/components/modules/ModuleContentDeck.jsx +44 -0
  16. package/components/modules/MovieBookingModule.jsx +17 -0
  17. package/components/modules/QuizExamModule.jsx +17 -0
  18. package/components/modules/StudentRegistrationModule.jsx +17 -0
  19. package/components/modules/SystemModuleRenderer.jsx +19 -0
  20. package/components/modules/SystemModuleTemplate.jsx +62 -0
  21. package/components/modules/SystemVisualWidget.jsx +123 -0
  22. package/components/modules/moduleContentMap.js +238 -0
  23. package/components/modules/moduleEnhancementsMap.js +439 -0
  24. package/components/modules/systemModuleMap.js +31 -0
  25. package/components/system/DynamicSystemForm.jsx +154 -0
  26. package/components/system/SystemHero.jsx +21 -0
  27. package/components/system/SystemSummaryCard.jsx +53 -0
  28. package/data/systems/analyticsDashboard.js +48 -0
  29. package/data/systems/chatMessaging.js +43 -0
  30. package/data/systems/ecommerceStore.js +50 -0
  31. package/data/systems/eventTicketBooking.js +50 -0
  32. package/data/systems/flightBooking.js +38 -0
  33. package/data/systems/foodOrdering.js +48 -0
  34. package/data/systems/hospitalAppointment.js +50 -0
  35. package/data/systems/hotelBooking.js +38 -0
  36. package/data/systems/index.js +31 -0
  37. package/data/systems/invoiceBilling.js +50 -0
  38. package/data/systems/libraryManagement.js +43 -0
  39. package/data/systems/movieBooking.js +48 -0
  40. package/data/systems/quizExam.js +38 -0
  41. package/data/systems/studentRegistration.js +43 -0
  42. package/dist/popsite-ui.es.js +4368 -0
  43. package/dist/popsite-ui.umd.js +60 -0
  44. package/dist/style.css +1 -0
  45. package/index.html +13 -0
  46. package/library/index.js +20 -0
  47. package/main.jsx +15 -0
  48. package/package.json +40 -0
  49. package/src/App.jsx +12 -0
  50. package/src/components/modules/AnalyticsDashboardModule.jsx +224 -0
  51. package/src/components/modules/ChatMessagingModule.jsx +294 -0
  52. package/src/components/modules/EcommerceStoreModule.jsx +405 -0
  53. package/src/components/modules/EventTicketBookingModule.jsx +253 -0
  54. package/src/components/modules/FlightBookingModule.jsx +399 -0
  55. package/src/components/modules/FoodOrderingModule.jsx +316 -0
  56. package/src/components/modules/HospitalAppointmentModule.jsx +267 -0
  57. package/src/components/modules/HotelBookingModule.jsx +317 -0
  58. package/src/components/modules/InvoiceBillingModule.jsx +302 -0
  59. package/src/components/modules/LandingPageModule.jsx +185 -0
  60. package/src/components/modules/LibraryManagementModule.jsx +189 -0
  61. package/src/components/modules/MovieBookingModule.jsx +337 -0
  62. package/src/components/modules/QuizExamModule.jsx +255 -0
  63. package/src/components/modules/StudentRegistrationModule.jsx +292 -0
  64. package/src/components/system/SystemHero.jsx +44 -0
  65. package/src/components/system/SystemSummaryCard.jsx +29 -0
  66. package/src/components/system/Toast.jsx +69 -0
  67. package/src/data/systems/analyticsDashboard.js +32 -0
  68. package/src/data/systems/chatMessaging.js +59 -0
  69. package/src/data/systems/ecommerceStore.js +84 -0
  70. package/src/data/systems/eventBooking.js +33 -0
  71. package/src/data/systems/flightBooking.js +59 -0
  72. package/src/data/systems/foodOrdering.js +48 -0
  73. package/src/data/systems/hospitalAppointment.js +48 -0
  74. package/src/data/systems/hotelBooking.js +59 -0
  75. package/src/data/systems/invoiceBilling.js +19 -0
  76. package/src/data/systems/landingPage.js +29 -0
  77. package/src/data/systems/libraryManagement.js +17 -0
  78. package/src/data/systems/movieBooking.js +49 -0
  79. package/src/data/systems/quizExam.js +31 -0
  80. package/src/data/systems/studentRegistration.js +9 -0
  81. package/src/index.js +22 -0
  82. package/src/main.jsx +10 -0
  83. package/src/styles.css +296 -0
  84. package/styles.css +820 -0
  85. package/utils/systemEngine.js +128 -0
  86. package/vite.config.js +8 -0
  87. package/vite.lib.config.js +27 -0
@@ -0,0 +1,399 @@
1
+ import React, { useState, useEffect } from 'react';
2
+ import { flightBookingMockData } from '../../data/systems/flightBooking';
3
+ import { useToast } from '../system/Toast';
4
+
5
+ export function FlightBookingModule() {
6
+ const [currentView, setCurrentView] = useState('search'); // search, results, passenger, pass
7
+
8
+ const [searchParams, setSearchParams] = useState({
9
+ from: flightBookingMockData.airports[0],
10
+ to: flightBookingMockData.airports[1],
11
+ date: new Date().toISOString().split('T')[0],
12
+ passengers: 1
13
+ });
14
+
15
+ const [selectedFlight, setSelectedFlight] = useState(null);
16
+ const [selectedClass, setSelectedClass] = useState('economy'); // economy, business
17
+ const [baggageCount, setBaggageCount] = useState(0);
18
+ const [passengerDetails, setPassengerDetails] = useState({ firstName: '', lastName: '', passport: '' });
19
+ const [bookedFlight, setBookedFlight] = useState(null);
20
+ const [isLoading, setIsLoading] = useState(false);
21
+
22
+ const { showToast, ToastContainer } = useToast();
23
+
24
+ // Simulated persisted state
25
+ useEffect(() => {
26
+ const saved = localStorage.getItem('popsite_flight');
27
+ if (saved) {
28
+ try { setBookedFlight(JSON.parse(saved)); } catch (e) {}
29
+ }
30
+ }, []);
31
+
32
+ useEffect(() => {
33
+ if (bookedFlight) {
34
+ localStorage.setItem('popsite_flight', JSON.stringify(bookedFlight));
35
+ }
36
+ }, [bookedFlight]);
37
+
38
+ const withDelay = (callback, delay = 1500) => {
39
+ setIsLoading(true);
40
+ setTimeout(() => {
41
+ setIsLoading(false);
42
+ callback();
43
+ }, delay);
44
+ };
45
+
46
+ const handleSearch = (e) => {
47
+ e.preventDefault();
48
+ if (searchParams.from === searchParams.to) {
49
+ showToast('Destination cannot be the same as origin', 'error');
50
+ return;
51
+ }
52
+ withDelay(() => {
53
+ setCurrentView('results');
54
+ showToast('Flights loaded successfully', 'success');
55
+ });
56
+ };
57
+
58
+ const handleSelectFlight = (flight) => {
59
+ setSelectedFlight(flight);
60
+ setCurrentView('passenger');
61
+ };
62
+
63
+ const calculateTotal = () => {
64
+ if (!selectedFlight) return 0;
65
+ const basePrice = selectedClass === 'business' ? selectedFlight.businessPrice : selectedFlight.price;
66
+ const baggageTotal = baggageCount * flightBookingMockData.addOns.checkedBag;
67
+ return (basePrice * searchParams.passengers) + baggageTotal;
68
+ };
69
+
70
+ const handleBook = (e) => {
71
+ e.preventDefault();
72
+ if (!passengerDetails.firstName || !passengerDetails.lastName || !passengerDetails.passport) {
73
+ showToast('Please fill out all passenger details', 'error');
74
+ return;
75
+ }
76
+
77
+ withDelay(() => {
78
+ const ticket = {
79
+ bookingRef: `PNR${Math.random().toString(36).substring(2, 8).toUpperCase()}`,
80
+ flight: selectedFlight,
81
+ seatClass: selectedClass,
82
+ baggage: baggageCount,
83
+ passenger: passengerDetails,
84
+ date: searchParams.date,
85
+ total: calculateTotal()
86
+ };
87
+ setBookedFlight(ticket);
88
+ setCurrentView('pass');
89
+ showToast('Booking confirmed!', 'success');
90
+ }, 2000);
91
+ };
92
+
93
+ const renderSearch = () => (
94
+ <div className="pk-container animate-fade-in" style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', minHeight: '80vh' }}>
95
+ <div style={{ textAlign: 'center', marginBottom: '3rem' }}>
96
+ <h1 className="pk-heading-xl" style={{ marginBottom: '1rem' }}>{flightBookingMockData.airlineName}</h1>
97
+ <p className="pk-text-body" style={{ fontSize: '1.25rem' }}>Where will your next adventure take you?</p>
98
+ </div>
99
+
100
+ <div className="pk-card pk-glass" style={{ width: '100%', maxWidth: '900px', padding: '3rem' }}>
101
+ <form onSubmit={handleSearch} className="pk-grid" style={{ gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: '1.5rem', alignItems: 'end' }}>
102
+ <div className="pk-input-group" style={{ margin: 0 }}>
103
+ <label className="pk-label">From</label>
104
+ <select
105
+ className="pk-input"
106
+ value={searchParams.from}
107
+ onChange={e => setSearchParams({...searchParams, from: e.target.value})}
108
+ >
109
+ {flightBookingMockData.airports.map(apt => <option key={apt} value={apt}>{apt}</option>)}
110
+ </select>
111
+ </div>
112
+
113
+ <div className="pk-input-group" style={{ margin: 0 }}>
114
+ <label className="pk-label">To</label>
115
+ <select
116
+ className="pk-input"
117
+ value={searchParams.to}
118
+ onChange={e => setSearchParams({...searchParams, to: e.target.value})}
119
+ >
120
+ {flightBookingMockData.airports.map(apt => <option key={apt} value={apt}>{apt}</option>)}
121
+ </select>
122
+ </div>
123
+
124
+ <div className="pk-input-group" style={{ margin: 0 }}>
125
+ <label className="pk-label">Departure Date</label>
126
+ <input
127
+ type="date"
128
+ className="pk-input"
129
+ value={searchParams.date}
130
+ onChange={e => setSearchParams({...searchParams, date: e.target.value})}
131
+ />
132
+ </div>
133
+
134
+ <div className="pk-input-group" style={{ margin: 0 }}>
135
+ <label className="pk-label">Passengers</label>
136
+ <input
137
+ type="number"
138
+ min="1" max="9"
139
+ className="pk-input"
140
+ value={searchParams.passengers}
141
+ onChange={e => setSearchParams({...searchParams, passengers: parseInt(e.target.value) || 1})}
142
+ />
143
+ </div>
144
+
145
+ <button type="submit" className="pk-btn pk-btn-primary" style={{ padding: '1.25rem', height: '100%' }}>
146
+ Search Flights
147
+ </button>
148
+ </form>
149
+ </div>
150
+
151
+ {bookedFlight && (
152
+ <button className="pk-btn pk-btn-outline" style={{ marginTop: '2rem' }} onClick={() => setCurrentView('pass')}>
153
+ View Upcoming Trip ({bookedFlight.bookingRef})
154
+ </button>
155
+ )}
156
+ </div>
157
+ );
158
+
159
+ const renderResults = () => {
160
+ // For demo: Fuzzy filter flights where 'from' and 'to' partially match
161
+ const flights = flightBookingMockData.flights.filter(f =>
162
+ f.from.includes(searchParams.from.split(' ')[0]) ||
163
+ f.to.includes(searchParams.to.split(' ')[0]) ||
164
+ true // Just return all so demo looks populated
165
+ );
166
+
167
+ return (
168
+ <div className="pk-container animate-fade-in">
169
+ <div className="pk-flex pk-justify-between pk-items-center" style={{ marginBottom: '2rem' }}>
170
+ <div>
171
+ <h2 className="pk-heading-lg">Select Departure Flight</h2>
172
+ <p className="pk-text-body">{searchParams.from} → {searchParams.to} | {searchParams.date} | {searchParams.passengers} Passenger(s)</p>
173
+ </div>
174
+ <button className="pk-btn pk-btn-outline" onClick={() => setCurrentView('search')}>Edit Search</button>
175
+ </div>
176
+
177
+ <div className="pk-flex pk-flex-col pk-gap-6">
178
+ {flights.map(flight => (
179
+ <div key={flight.id} className="pk-card pk-card-interactive" style={{ padding: '2rem', display: 'flex', flexWrap: 'wrap', gap: '2rem', alignItems: 'center' }}>
180
+ <div style={{ flex: '1 1 300px' }}>
181
+ <div className="pk-flex pk-justify-between pk-items-center" style={{ marginBottom: '1rem' }}>
182
+ <span className="pk-badge">{flight.flightNumber}</span>
183
+ <span className="pk-text-sm" style={{ color: 'var(--pk-primary)', fontWeight: 600 }}>{flight.duration}</span>
184
+ </div>
185
+
186
+ {/* Timeline Visualizer */}
187
+ <div className="pk-flex pk-justify-between pk-items-center">
188
+ <div className="pk-text-center">
189
+ <h3 className="pk-heading-md">{flight.departureTime}</h3>
190
+ <p className="pk-text-muted">{flight.from.split(' ')[0]}</p>
191
+ </div>
192
+ <div style={{ flex: 1, margin: '0 1rem', display: 'flex', alignItems: 'center', justifyItems: 'center' }}>
193
+ <div style={{ height: '2px', background: 'var(--pk-border)', flex: 1 }}></div>
194
+ <span style={{ margin: '0 1rem', fontSize: '1.5rem', opacity: 0.5 }}>✈️</span>
195
+ <div style={{ height: '2px', background: 'var(--pk-border)', flex: 1 }}></div>
196
+ </div>
197
+ <div className="pk-text-center">
198
+ <h3 className="pk-heading-md">{flight.arrivalTime}</h3>
199
+ <p className="pk-text-muted">{flight.to.split(' ')[0]}</p>
200
+ </div>
201
+ </div>
202
+ </div>
203
+
204
+ <div style={{ width: '1px', background: 'var(--pk-border)', height: '100px', alignSelf: 'stretch' }} className="pk-hidden-mobile"></div>
205
+
206
+ <div style={{ flex: '0 0 auto', display: 'flex', flexDirection: 'column', gap: '1rem', minWidth: '150px' }}>
207
+ <div className="pk-text-center">
208
+ <span className="pk-text-sm pk-text-muted">Economy from</span>
209
+ <h3 className="pk-heading-lg" style={{ color: 'var(--pk-secondary)' }}>${flight.price}</h3>
210
+ </div>
211
+ <button className="pk-btn pk-btn-outline" onClick={() => { setSelectedClass('economy'); handleSelectFlight(flight); }}>
212
+ Select Economy
213
+ </button>
214
+ </div>
215
+
216
+ <div style={{ flex: '0 0 auto', display: 'flex', flexDirection: 'column', gap: '1rem', minWidth: '150px' }}>
217
+ <div className="pk-text-center">
218
+ <span className="pk-text-sm pk-text-muted">Business from</span>
219
+ <h3 className="pk-heading-lg" style={{ color: 'var(--pk-primary)' }}>${flight.businessPrice}</h3>
220
+ </div>
221
+ <button className="pk-btn pk-btn-primary" onClick={() => { setSelectedClass('business'); handleSelectFlight(flight); }}>
222
+ Select Business
223
+ </button>
224
+ </div>
225
+ </div>
226
+ ))}
227
+ </div>
228
+ </div>
229
+ );
230
+ };
231
+
232
+ const renderPassenger = () => (
233
+ <div className="pk-container animate-fade-in">
234
+ <button className="pk-btn pk-btn-outline" style={{ marginBottom: '2rem' }} onClick={() => setCurrentView('results')}>← Back to Flights</button>
235
+
236
+ <div className="pk-grid" style={{ gridTemplateColumns: 'minmax(300px, 2fr) minmax(300px, 1fr)' }}>
237
+ <div className="pk-flex pk-flex-col pk-gap-6">
238
+ <div className="pk-card" style={{ padding: '2rem' }}>
239
+ <h2 className="pk-heading-md" style={{ marginBottom: '1.5rem', borderBottom: '1px solid var(--pk-border)', paddingBottom: '0.5rem' }}>Primary Passenger</h2>
240
+ <form onSubmit={handleBook} id="booking-form">
241
+ <div className="pk-grid" style={{ gridTemplateColumns: '1fr 1fr' }}>
242
+ <div className="pk-input-group">
243
+ <label className="pk-label">First Name</label>
244
+ <input type="text" className="pk-input" value={passengerDetails.firstName} onChange={e => setPassengerDetails({...passengerDetails, firstName: e.target.value})} required />
245
+ </div>
246
+ <div className="pk-input-group">
247
+ <label className="pk-label">Last Name</label>
248
+ <input type="text" className="pk-input" value={passengerDetails.lastName} onChange={e => setPassengerDetails({...passengerDetails, lastName: e.target.value})} required />
249
+ </div>
250
+ </div>
251
+ <div className="pk-input-group">
252
+ <label className="pk-label">Passport Number</label>
253
+ <input type="text" className="pk-input" value={passengerDetails.passport} onChange={e => setPassengerDetails({...passengerDetails, passport: e.target.value})} required />
254
+ </div>
255
+ </form>
256
+ </div>
257
+
258
+ <div className="pk-card" style={{ padding: '2rem' }}>
259
+ <h2 className="pk-heading-md" style={{ marginBottom: '1.5rem', borderBottom: '1px solid var(--pk-border)', paddingBottom: '0.5rem' }}>Customize Your Trip</h2>
260
+
261
+ <div className="pk-flex pk-items-center pk-justify-between" style={{ padding: '1rem', background: 'var(--pk-bg-main)', borderRadius: 'var(--pk-radius-md)', marginBottom: '1rem' }}>
262
+ <div>
263
+ <h4 className="pk-label">Checked Baggage</h4>
264
+ <p className="pk-text-sm">Up to 23kg per bag (${flightBookingMockData.addOns.checkedBag} each)</p>
265
+ </div>
266
+ <div className="pk-flex pk-items-center pk-gap-4">
267
+ <button type="button" className="pk-btn pk-btn-outline" style={{ padding: '0.5rem', borderRadius: '50%', width: 40, height: 40 }} onClick={() => setBaggageCount(Math.max(0, baggageCount - 1))}>-</button>
268
+ <span className="pk-heading-md">{baggageCount}</span>
269
+ <button type="button" className="pk-btn pk-btn-outline" style={{ padding: '0.5rem', borderRadius: '50%', width: 40, height: 40 }} onClick={() => setBaggageCount(baggageCount + 1)}>+</button>
270
+ </div>
271
+ </div>
272
+ </div>
273
+ </div>
274
+
275
+ <div>
276
+ <div className="pk-card" style={{ position: 'sticky', top: '100px' }}>
277
+ <div className="pk-card-header bg-gradient" style={{ background: 'linear-gradient(135deg, var(--pk-bg-main), var(--pk-primary-light))', padding: '2rem' }}>
278
+ <span className="pk-badge" style={{ marginBottom: '1rem', display: 'inline-block' }}>{selectedClass.toUpperCase()}</span>
279
+ <h3 className="pk-heading-md">{selectedFlight.from.split(' ')[0]} ✈ {selectedFlight.to.split(' ')[0]}</h3>
280
+ <p className="pk-text-sm">{searchParams.date}</p>
281
+ </div>
282
+ <div className="pk-card-body pk-flex pk-flex-col pk-gap-4">
283
+ <div className="pk-flex pk-justify-between">
284
+ <span className="pk-text-body">1x Ticket</span>
285
+ <span style={{ fontWeight: 600 }}>${selectedClass === 'business' ? selectedFlight.businessPrice : selectedFlight.price}</span>
286
+ </div>
287
+ {baggageCount > 0 && (
288
+ <div className="pk-flex pk-justify-between">
289
+ <span className="pk-text-body">{baggageCount}x Checked Bag</span>
290
+ <span style={{ fontWeight: 600 }}>${baggageCount * flightBookingMockData.addOns.checkedBag}</span>
291
+ </div>
292
+ )}
293
+ <hr style={{ border: 0, borderTop: '1px solid var(--pk-border)' }} />
294
+ <div className="pk-flex pk-justify-between pk-items-center">
295
+ <span className="pk-heading-md">Total</span>
296
+ <span className="pk-heading-lg" style={{ color: 'var(--pk-primary)' }}>${calculateTotal()}</span>
297
+ </div>
298
+
299
+ <button type="submit" form="booking-form" className="pk-btn pk-btn-primary pk-w-full" style={{ marginTop: '1rem', padding: '1.25rem' }}>
300
+ Confirm & Pay
301
+ </button>
302
+ </div>
303
+ </div>
304
+ </div>
305
+ </div>
306
+ </div>
307
+ );
308
+
309
+ const renderPass = () => {
310
+ if (!bookedFlight) return null;
311
+
312
+ return (
313
+ <div className="pk-container animate-fade-in pk-flex pk-justify-center pk-items-center" style={{ minHeight: '80vh' }}>
314
+ <div className="pk-card" style={{ width: '100%', maxWidth: '400px', overflow: 'hidden', boxShadow: 'var(--pk-shadow-xl)' }}>
315
+ <div style={{ background: 'var(--pk-primary)', color: 'white', padding: '2rem', textAlign: 'center', position: 'relative' }}>
316
+ <h2 className="pk-heading-md" style={{ opacity: 0.9 }}>{flightBookingMockData.airlineName}</h2>
317
+ <h1 className="pk-heading-xl" style={{ margin: '1rem 0' }}>BOARDING</h1>
318
+ <p style={{ letterSpacing: '2px', opacity: 0.8 }}>PASS</p>
319
+
320
+ {/* Visual cutout effect */}
321
+ <div style={{ position: 'absolute', bottom: '-10px', left: '-10px', width: '20px', height: '20px', background: 'var(--pk-bg-main)', borderRadius: '50%' }}></div>
322
+ <div style={{ position: 'absolute', bottom: '-10px', right: '-10px', width: '20px', height: '20px', background: 'var(--pk-bg-main)', borderRadius: '50%' }}></div>
323
+ </div>
324
+
325
+ <div className="pk-card-body" style={{ padding: '2rem', position: 'relative' }}>
326
+ <div className="pk-flex pk-justify-between pk-items-center" style={{ marginBottom: '2rem', borderBottom: '1px solid var(--pk-border)', paddingBottom: '1rem' }}>
327
+ <div className="pk-text-center">
328
+ <h2 className="pk-heading-xl" style={{ color: 'var(--pk-text-main)' }}>{bookedFlight.flight.from.split(' ')[0]}</h2>
329
+ <p className="pk-text-sm pk-text-muted">{bookedFlight.flight.departureTime}</p>
330
+ </div>
331
+ <span style={{ fontSize: '2rem', color: 'var(--pk-primary)' }}>✈️</span>
332
+ <div className="pk-text-center">
333
+ <h2 className="pk-heading-xl" style={{ color: 'var(--pk-text-main)' }}>{bookedFlight.flight.to.split(' ')[0]}</h2>
334
+ <p className="pk-text-sm pk-text-muted">{bookedFlight.flight.arrivalTime}</p>
335
+ </div>
336
+ </div>
337
+
338
+ <div className="pk-grid" style={{ gridTemplateColumns: '1fr 1fr', gap: '1.5rem', marginBottom: '2rem' }}>
339
+ <div>
340
+ <p className="pk-label pk-text-muted">Passenger</p>
341
+ <p className="pk-heading-sm" style={{ fontWeight: 600 }}>{bookedFlight.passenger.firstName} {bookedFlight.passenger.lastName}</p>
342
+ </div>
343
+ <div>
344
+ <p className="pk-label pk-text-muted">Flight</p>
345
+ <p className="pk-heading-sm" style={{ fontWeight: 600 }}>{bookedFlight.flight.flightNumber}</p>
346
+ </div>
347
+ <div>
348
+ <p className="pk-label pk-text-muted">Date</p>
349
+ <p className="pk-heading-sm" style={{ fontWeight: 600 }}>{bookedFlight.date}</p>
350
+ </div>
351
+ <div>
352
+ <p className="pk-label pk-text-muted">Class</p>
353
+ <p className="pk-heading-sm" style={{ fontWeight: 600, textTransform: 'capitalize' }}>{bookedFlight.seatClass}</p>
354
+ </div>
355
+ <div>
356
+ <p className="pk-label pk-text-muted">Seat</p>
357
+ <p className="pk-heading-sm" style={{ fontWeight: 800, color: 'var(--pk-primary)', fontSize: '1.5rem' }}>12A</p>
358
+ </div>
359
+ <div>
360
+ <p className="pk-label pk-text-muted">Gate</p>
361
+ <p className="pk-heading-sm" style={{ fontWeight: 800, fontSize: '1.5rem' }}>G4</p>
362
+ </div>
363
+ </div>
364
+
365
+ <div style={{ textAlign: 'center', marginTop: '2rem' }}>
366
+ {/* Mock QR Code */}
367
+ <div style={{ display: 'inline-block', padding: '10px', border: '2px solid var(--pk-border)', borderRadius: '12px' }}>
368
+ <div style={{ width: '120px', height: '120px', background: 'repeating-linear-gradient(45deg, #000, #000 10px, transparent 10px, transparent 20px), repeating-linear-gradient(135deg, #000, #000 10px, transparent 10px, transparent 20px)' }}></div>
369
+ </div>
370
+ <p className="pk-text-sm" style={{ marginTop: '0.5rem', letterSpacing: '4px', fontFamily: 'monospace' }}>{bookedFlight.bookingRef}</p>
371
+ </div>
372
+ </div>
373
+
374
+ <div className="pk-card-footer pk-flex pk-justify-center" style={{ gap: '1rem', background: 'var(--pk-primary-light)' }}>
375
+ <button className="pk-btn pk-btn-outline" style={{ background: 'white' }} onClick={() => setCurrentView('search')}>New Booking</button>
376
+ </div>
377
+ </div>
378
+ </div>
379
+ );
380
+ };
381
+
382
+ return (
383
+ <div style={{ position: 'relative', minHeight: '100vh', backgroundColor: 'var(--pk-bg-main)' }}>
384
+ {isLoading && (
385
+ <div style={{ position: 'fixed', inset: 0, backgroundColor: 'rgba(255,255,255,0.7)', zIndex: 100, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', backdropFilter: 'blur(4px)' }}>
386
+ <div className="pk-skeleton" style={{ width: '80px', height: '80px', borderRadius: '50%', marginBottom: '1rem' }}></div>
387
+ <h3 className="pk-heading-md">Searching Global Skies...</h3>
388
+ </div>
389
+ )}
390
+
391
+ {currentView === 'search' && renderSearch()}
392
+ {currentView === 'results' && renderResults()}
393
+ {currentView === 'passenger' && renderPassenger()}
394
+ {currentView === 'pass' && renderPass()}
395
+
396
+ <ToastContainer />
397
+ </div>
398
+ );
399
+ }