const decodeBookingData = () => {
const params = new URLSearchParams(window.location.search);
const d = params.get('d');
if (!d) return null;
try {
const decoded = atob(d.replace(/-/g, '+').replace(/_/g, '/'));
const str = decodeURIComponent(decoded.split('').map(c =>
'%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
).join(''));
const [name, date, time, guests, table] = str.split('|');
return { name, date, time, guests: +guests, table };
} catch (e) {
return null;
}
};
// Форматирование даты
const formatDate = (dateStr) => {
if (!dateStr) return '';
const months = ['января', 'февраля', 'марта', 'апреля', 'мая', 'июня',
'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря'];
const d = new Date(dateStr);
return `${d.getDate()} ${months[d.getMonth()]}`;
};
export default function WhiteRabbitBooking() {
const [booking, setBooking] = useState({
name: 'Алина',
date: '6 ноября',
time: '20:00',
guests: 2,
table: '12',
status: 'confirmed'
});
const [showEditModal, setShowEditModal] = useState(false);
const [showCancelModal, setShowCancelModal] = useState(false);
useEffect(() => {
const data = decodeBookingData();
if (data) {
setBooking({
name: data.name,
date: formatDate(data.date) || data.date,
time: data.time,
guests: data.guests,
table: data.table,
status: 'confirmed'
});
}
}, []);
return (
{/* Header */}
{/* Events Slider */}
{[1, 2, 3].map((_, i) => (
))}
{/* Main Content */}
{/* Booking Card */}
{/* Status Badge */}
✓ Подтверждено
{/* Booking Info */}
{/* Name */}
Имя {booking.name}
{/* Date & Time Row */}
Дата {booking.date}
{booking.time}
{/* Guests Row */}
Время Гостей
{/* Action Buttons */}
{/* Navigation Links */}
{/* Feedback Card */}
Написать руководителю ???? ????
Столкнулись с неприятной ситуацией?
{/* Edit Modal */}
{showEditModal && (
setShowEditModal(false)}> {
setBooking({ ...booking, ...updated });
setShowEditModal(false);
}}
onCancel={() => setShowCancelModal(true)}
/>
)}
{/* Cancel Modal */}
{showCancelModal && (
setShowCancelModal(false)}> {
setBooking({ ...booking, status: 'cancelled' });
setShowCancelModal(false);
setShowEditModal(false);
}}
onBack={() => setShowCancelModal(false)}
/>
)}
);
}
// Navigation Link Component
const NavLink = ({ icon, text }) => (
{icon} {text} ›
);
// Modal Component
const Modal = ({ children, onClose }) => (
e.stopPropagation()}>
{children}
);
// Edit Booking Form
const EditBookingForm = ({ booking, onSave, onCancel }) => {
const [form, setForm] = useState({
name: booking.name,
date: booking.date,
time: booking.time,
guests: booking.guests
});
return (
White Rabbit
Изменить бронирование
В ресторане размещение происходит по факту прибытия.
setForm({ ...form, name: e.target.value })}
/>
setForm({ ...form, date: e.target.value })}
/>
);
};
// Cancel Confirmation
const CancelConfirmation = ({ onConfirm, onBack }) => (
Отменить бронирование?
Это действие нельзя отменить. Вы уверены?
);
// Styles
const styles = {
container: {
minHeight: '100vh',
background: '#f3f3f3',
fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, sans-serif",
},
// Header
header: {
position: 'fixed',
top: 0,
left: 0,
right: 0,
height: 61,
background: '#ffffff',
zIndex: 990,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
},
headerContent: {
display: 'flex',
alignItems: 'center',
gap: 8,
},
logo: {
height: 52,
width: 'auto',
},
star: {
width: 25,
height: 24,
},
// Events Section
eventsSection: {
paddingTop: 70,
paddingBottom: 8,
overflow: 'hidden',
},
eventsScroll: {
display: 'flex',
gap: 14,
padding: '0 10px',
overflowX: 'auto',
scrollbarWidth: 'none',
msOverflowStyle: 'none',
},
eventCard: {
flexShrink: 0,
width: 263,
height: 98,
background: '#ffffff',
borderRadius: 17,
padding: '15px 20px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
},
eventTitle: {
fontSize: 17,
fontWeight: 700,
color: '#ffffff',
background: 'linear-gradient(135deg, #1a1a2e 0%, #16213e 100%)',
padding: '2px 8px',
borderRadius: 4,
alignSelf: 'flex-start',
},
eventDate: {
fontSize: 10,
color: '#000',
letterSpacing: 0.5,
},
eventDetails: {
display: 'flex',
alignItems: 'flex-end',
gap: 8,
},
eventDay: {
fontSize: 44,
fontWeight: 600,
color: '#8e1010',
lineHeight: 1,
},
eventLabel: {
fontSize: 10,
color: '#000',
},
eventChef: {
fontSize: 17,
fontWeight: 600,
color: '#8e1010',
},
// Main
main: {
padding: '8px 10px 100px',
},
// Booking Card
bookingCard: {
background: '#e4ebf0',
borderRadius: 18,
padding: 16,
marginBottom: 10,
border: '1px solid #d7e2ea',
},
statusBadge: {
background: 'linear-gradient(90deg, #23d0d2 0%, #5adf01 100%)',
borderRadius: 6,
padding: '4px 12px',
display: 'inline-flex',
alignItems: 'center',
gap: 6,
marginBottom: 12,
},
statusIcon: {
color: '#fff',
fontSize: 12,
},
statusText: {
color: '#fff',
fontSize: 10,
fontWeight: 600,
},
bookingInfo: {
background: 'linear-gradient(180deg, #f3f3ea 0%, rgba(255,255,255,0.59) 100%)',
borderRadius: 13,
padding: 12,
marginBottom: 12,
},
infoRow: {
marginBottom: 8,
},
infoLabel: {
display: 'block',
fontSize: 9,
color: '#7b858c',
marginBottom: 2,
},
infoValue: {
fontSize: 12,
fontWeight: 700,
color: '#3c4f5d',
},
dateTimeRow: {
display: 'flex',
gap: 8,
marginTop: 8,
},
dateBox: {
flex: 1,
},
timeBox: {
flex: 1,
display: 'flex',
alignItems: 'flex-end',
},
guestsBox: {
width: 33,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
},
guestsIcon: {
width: 32,
height: 21,
},
guestsRow: {
display: 'flex',
gap: 8,
marginTop: 4,
},
actionButtons: {
display: 'flex',
gap: 10,
},
changeButton: {
flex: 1,
height: 30,
background: 'linear-gradient(180deg, #f7f5f5 0%, rgba(247,245,245,0) 100%)',
border: '1px solid #ffffff',
borderRadius: 15,
fontSize: 9,
fontWeight: 700,
color: '#3c4f5d',
cursor: 'pointer',
},
payButton: {
flex: 1,
height: 30,
background: 'linear-gradient(180deg, #f7f5f5 0%, rgba(247,245,245,0) 100%)',
border: '1px solid #ffffff',
borderRadius: 15,
fontSize: 9,
fontWeight: 700,
color: '#3c4f5d',
cursor: 'pointer',
},
// Nav Links
navLinks: {
display: 'grid',
gridTemplateColumns: '1fr 1fr',
gap: 8,
marginBottom: 10,
},
navLink: {
background: 'radial-gradient(circle at center, #fff 63%, rgba(243,243,234,0.38) 100%)',
border: '1px solid #fff',
borderRadius: 11,
padding: '12px 16px',
display: 'flex',
alignItems: 'center',
gap: 8,
cursor: 'pointer',
},
navIcon: {
fontSize: 16,
},
navText: {
fontSize: 11,
fontWeight: 600,
color: '#3c4f5d',
flex: 1,
},
navArrow: {
fontSize: 16,
color: '#7b858c',
},
// Feedback Card
feedbackCard: {
background: 'radial-gradient(circle at center, #fff 63%, rgba(243,243,234,0.38) 100%)',
border: '1px solid #fff',
borderRadius: 17,
padding: 16,
},
feedbackHeader: {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 8,
},
feedbackTitle: {
fontSize: 13,
fontWeight: 600,
color: '#3c4f5d',
},
feedbackIcons: {
display: 'flex',
gap: 8,
},
feedbackIcon: {
width: 40,
height: 40,
background: '#f3f3f3',
borderRadius: 8,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: 18,
},
feedbackText: {
fontSize: 9,
color: '#1fac92',
margin: 0,
},
// Modal
modalOverlay: {
position: 'fixed',
inset: 0,
background: 'rgba(243,243,243,0.9)',
backdropFilter: 'blur(4px)',
display: 'flex',
alignItems: 'flex-end',
justifyContent: 'center',
zIndex: 1000,
},
modal: {
width: '100%',
maxWidth: 520,
background: '#ffffff',
borderRadius: '31px 31px 0 0',
padding: '24px 20px 40px',
position: 'relative',
maxHeight: '90vh',
overflow: 'auto',
},
modalClose: {
position: 'absolute',
top: 16,
right: 16,
background: 'none',
border: 'none',
cursor: 'pointer',
padding: 8,
},
modalSubtitle: {
fontSize: 14,
color: '#303b36',
margin: '0 0 4px',
},
modalTitle: {
fontSize: 17,
fontWeight: 700,
color: '#303b36',
margin: '0 0 8px',
},
modalDescription: {
fontSize: 11,
color: '#303b36',
margin: '0 0 24px',
lineHeight: 1.4,
},
// Form
editForm: {
paddingTop: 20,
},
formGroup: {
marginBottom: 16,
},
formLabel: {
display: 'block',
fontSize: 11,
color: '#7b858c',
marginBottom: 6,
},
formInput: {
width: '100%',
padding: '12px 16px',
border: '1px solid #d7e2ea',
borderRadius: 10,
fontSize: 14,
fontFamily: 'inherit',
background: '#f8f9fa',
boxSizing: 'border-box',
},
formRow: {
display: 'grid',
gridTemplateColumns: '1fr 1fr 80px',
gap: 12,
},
saveButton: {
width: '100%',
padding: '16px',
background: 'linear-gradient(135deg, #23d0d2 0%, #5adf01 100%)',
border: 'none',
borderRadius: 12,
fontSize: 14,
fontWeight: 600,
color: '#fff',
cursor: 'pointer',
marginTop: 8,
},
cancelLink: {
width: '100%',
padding: '16px',
background: 'transparent',
border: 'none',
fontSize: 13,
color: '#e17055',
cursor: 'pointer',
marginTop: 8,
},
// Cancel Confirmation
cancelConfirm: {
textAlign: 'center',
padding: '40px 20px',
},
cancelButtons: {
display: 'flex',
gap: 12,
marginTop: 24,
},
backButton: {
flex: 1,
padding: '14px',
background: '#f3f3f3',
border: 'none',
borderRadius: 12,
fontSize: 14,
fontWeight: 600,
color: '#3c4f5d',
cursor: 'pointer',
},
confirmCancelButton: {
flex: 1,
padding: '14px',
background: '#e17055',
border: 'none',
borderRadius: 12,
fontSize: 14,
fontWeight: 600,
color: '#fff',
cursor: 'pointer',
},
};