feat: deposit module — QR flow, PayDepositPage, BookingDetailPanel widget
- Backend: GET /api/pay/:slug (public) — returns active hold confirmation URL - PayDepositPage: public page /:slug/pay for guests (no login required) - DepositSettingsPage: QR code section with print button - BookingDetailPanel: DepositWidget in payment tab - Наличными / ЮКасса (QR) buttons - hold_created: copy link + refresh - hold_confirmed: release form (вернуть / списать) - Final status badges Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { Save, Eye, EyeOff, Loader2, ShieldCheck } from 'lucide-react'
|
||||
import { Save, Eye, EyeOff, Loader2, ShieldCheck, Printer } from 'lucide-react'
|
||||
import { QRCodeSVG } from 'qrcode.react'
|
||||
import { api, type DepositSettings } from '../lib/api'
|
||||
import { useAuth } from '../contexts/AuthContext'
|
||||
import { cn } from '../lib/utils'
|
||||
@@ -172,6 +173,52 @@ export function DepositSettingsPage() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* QR code section — only when shopId is configured */}
|
||||
{shopId && (
|
||||
<div className="border-t border-slate-100 dark:border-slate-700 pt-4">
|
||||
<p className="font-medium text-slate-800 dark:text-slate-200 text-sm mb-1">QR-код для гостей</p>
|
||||
<p className="text-xs text-slate-500 dark:text-slate-400 mb-4">
|
||||
Распечатайте и разместите на стойке ресепшена. Гость сканирует код и оплачивает депозит картой.
|
||||
</p>
|
||||
<div className="print-qr-section flex flex-col items-center gap-4">
|
||||
<div className="p-4 bg-white rounded-xl border border-slate-200 dark:border-slate-600 inline-block">
|
||||
<QRCodeSVG
|
||||
value={`https://app.hotelsync.ru/${slug}/pay`}
|
||||
size={160}
|
||||
level="M"
|
||||
/>
|
||||
</div>
|
||||
<p className="text-xs text-slate-400 font-mono break-all text-center">
|
||||
https://app.hotelsync.ru/{slug}/pay
|
||||
</p>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => window.print()}
|
||||
className="btn-secondary flex items-center gap-2"
|
||||
>
|
||||
<Printer size={15} />
|
||||
Распечатать QR-код
|
||||
</button>
|
||||
</div>
|
||||
<style>{`
|
||||
@media print {
|
||||
body > * { display: none !important; }
|
||||
.print-qr-section,
|
||||
.print-qr-section * { display: flex !important; }
|
||||
.print-qr-section {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
button { display: none !important; }
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user