feat: přehlednější zobrazení QR kódů, oprava zobrazení na stránce objednání
CI / Generate TypeScript types (push) Successful in 10s
CI / Server unit tests (push) Successful in 21s
CI / Build server (push) Successful in 30s
CI / Build client (push) Successful in 37s
CI / Playwright E2E tests (push) Successful in 1m20s
CI / Build and push Docker image (push) Successful in 46s
CI / Notify (push) Successful in 3s
CI / Generate TypeScript types (push) Successful in 10s
CI / Server unit tests (push) Successful in 21s
CI / Build server (push) Successful in 30s
CI / Build client (push) Successful in 37s
CI / Playwright E2E tests (push) Successful in 1m20s
CI / Build and push Docker image (push) Successful in 46s
CI / Notify (push) Successful in 3s
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { useState } from 'react';
|
||||
import { Button } from 'react-bootstrap';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { Button, Modal } from 'react-bootstrap';
|
||||
import { PendingQr, dismissQr } from '../../../types';
|
||||
import { formatDateString } from '../Utils';
|
||||
import ConfirmModal from './modals/ConfirmModal';
|
||||
@@ -13,31 +13,75 @@ type Props = {
|
||||
|
||||
// Sekce "Nevyřízené platby" – zobrazí QR kódy neuhrazených plateb přihlášeného uživatele
|
||||
// včetně tlačítka "Zaplatil jsem" a potvrzovacího dialogu. Sdíleno hlavní stránkou i stránkou objednávek.
|
||||
// Při příchodu nových nevyřízených plateb se navíc automaticky otevře modální dialog,
|
||||
// aby si uživatel QR kódů určitě všiml (často si jich nevšimnou, protože sekce je dole na stránce).
|
||||
export default function PendingPayments({ pendingQrs, login, onDismissed }: Readonly<Props>) {
|
||||
const [dismissQrId, setDismissQrId] = useState<string | null>(null);
|
||||
const [modalOpen, setModalOpen] = useState(false);
|
||||
|
||||
// ID QR kódů, pro které už byl v rámci tohoto načtení stránky automaticky zobrazen
|
||||
// modální dialog. Drží se jen v paměti (ne v sessionStorage), takže se při každém
|
||||
// ručním přenačtení stránky vynuluje a dialog se znovu otevře, dokud uživatel platby
|
||||
// neuhradí. Zároveň se nepřekrývá při pouhém obnovení dat či příchodu už zobrazeného QR.
|
||||
const autoShownQrIds = useRef<Set<string>>(new Set());
|
||||
|
||||
const qrIdsKey = (pendingQrs ?? []).map(qr => qr.id).join(',');
|
||||
|
||||
// Automaticky otevřeme modální dialog, jakmile přijdou nové (dosud nezobrazené) platby.
|
||||
useEffect(() => {
|
||||
const ids = (pendingQrs ?? []).map(qr => qr.id);
|
||||
if (ids.length === 0) return;
|
||||
const unseen = ids.filter(id => !autoShownQrIds.current.has(id));
|
||||
if (unseen.length > 0) {
|
||||
setModalOpen(true);
|
||||
unseen.forEach(id => autoShownQrIds.current.add(id));
|
||||
}
|
||||
}, [qrIdsKey, pendingQrs]);
|
||||
|
||||
if (!pendingQrs || pendingQrs.length === 0) return null;
|
||||
|
||||
// Vykreslení jednoho QR kódu i s tlačítkem "Zaplatil jsem" – sdíleno sekcí i modálem.
|
||||
const renderQr = (qr: PendingQr) => (
|
||||
<div key={qr.id} className='qr-code mb-3'>
|
||||
<p>
|
||||
<strong>{formatDateString(qr.date)}</strong> — {qr.creator} ({qr.totalPrice / 100} Kč)
|
||||
{qr.purpose && <><br /><span className="text-muted">{qr.purpose}</span></>}
|
||||
</p>
|
||||
<img src={`/api/qr?login=${login}&id=${qr.id}`} alt='QR kód' />
|
||||
<div className='mt-2'>
|
||||
<Button variant="success" onClick={() => setDismissQrId(qr.id)}>
|
||||
Zaplatil jsem
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className='pizza-section fade-in mt-4'>
|
||||
<h3>Nevyřízené platby</h3>
|
||||
<p>Máte neuhrazené platby.</p>
|
||||
{pendingQrs.map(qr => (
|
||||
<div key={qr.id} className='qr-code mb-3'>
|
||||
<p>
|
||||
<strong>{formatDateString(qr.date)}</strong> — {qr.creator} ({qr.totalPrice / 100} Kč)
|
||||
{qr.purpose && <><br /><span className="text-muted">{qr.purpose}</span></>}
|
||||
</p>
|
||||
<img src={`/api/qr?login=${login}&id=${qr.id}`} alt='QR kód' />
|
||||
<div className='mt-2'>
|
||||
<Button variant="success" onClick={() => setDismissQrId(qr.id)}>
|
||||
Zaplatil jsem
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
<p>
|
||||
Máte neuhrazené platby.{' '}
|
||||
<Button variant="link" className="p-0 align-baseline" onClick={() => setModalOpen(true)}>
|
||||
Zobrazit QR kódy
|
||||
</Button>
|
||||
</p>
|
||||
{pendingQrs.map(renderQr)}
|
||||
</div>
|
||||
<Modal show={modalOpen} onHide={() => setModalOpen(false)} centered scrollable>
|
||||
<Modal.Header closeButton>
|
||||
<Modal.Title>Nevyřízené platby</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
<p>Máte neuhrazené platby. Naskenujte QR kód pro zaplacení.</p>
|
||||
{pendingQrs.map(renderQr)}
|
||||
</Modal.Body>
|
||||
<Modal.Footer>
|
||||
<Button variant="secondary" onClick={() => setModalOpen(false)}>
|
||||
Zavřít
|
||||
</Button>
|
||||
</Modal.Footer>
|
||||
</Modal>
|
||||
<ConfirmModal
|
||||
isOpen={dismissQrId !== null}
|
||||
title="Potvrzení platby"
|
||||
|
||||
Reference in New Issue
Block a user