feat(appointment): add percentage shortcuts for patient share in payment rows

This commit is contained in:
hamed
2026-08-10 10:38:56 +03:30
parent a8699065b8
commit 505ab412a3
2 changed files with 109 additions and 1 deletions
@@ -5,7 +5,7 @@ import { UserCircleIcon, PlusIcon, TrashIcon } from '@heroicons/react/24/outline
import { api } from '../../lib/api';
import type { ApiResponse } from '../../lib/api';
import type { BankAccount, Pos } from '../../hooks/usePaymentMethods';
import { formatRial, rialToToman, tomanToRial } from '../../lib/utils';
import { formatNumber, formatRial, rialToToman, tomanToRial } from '../../lib/utils';
import { DEFAULT_SERVICE_CATEGORY } from '../../lib/insuranceShares';
import { useAppointmentInsurance } from '../../hooks/useAppointmentInsurance';
import Modal from '../ui/Modal';
@@ -13,6 +13,9 @@ import PriceInput from '../ui/PriceInput';
import SearchableSelect from '../ui/SearchableSelect';
import Stepper from '../ui/Stepper';
/** میان‌بُرهای مبلغ روی هر ردیف پرداخت — درصدی از سهم بیمار. */
const PAYMENT_PERCENTS = [20, 50, 70, 100];
/** همان چهار روشِ SessionPayment::METHODS در بک‌اند. */
const METHOD_OPTIONS = [
{ value: 'cash', label: 'پرداخت نقدی' },
@@ -254,6 +257,11 @@ export default function ConfirmAppointmentModal({
patchRow(id, { method, methodUuid: '', reference: '' });
}
/** درصدِ سهم بیمار روی همان ردیف می‌نشیند؛ ردیف‌های دیگر دست‌نخورده می‌مانند. */
function applyPercent(id: number, percent: number) {
patchRow(id, { amountToman: rialToToman(Math.round((payable * percent) / 100)) });
}
function addRow() {
setTouched(true);
// ردیفِ جدید پیش‌فرض با باقی‌مانده پر می‌شود تا تسویه سریع‌تر باشد.
@@ -492,6 +500,39 @@ export default function ConfirmAppointmentModal({
)}
</div>
{/* میان‌بُرهای درصدی — پرداخت جزئی رایج است و تایپ دستیِ مبلغ خطا می‌آورد. */}
{payable > 0 && (
<div style={{ display: 'flex', alignItems: 'center', gap: 6, flexWrap: 'wrap' }}>
{PAYMENT_PERCENTS.map((percent) => {
const active = tomanToRial(r.amountToman) === Math.round((payable * percent) / 100);
return (
<button
key={percent}
type="button"
className="btn sm"
onClick={() => applyPercent(r.id, percent)}
title={formatRial(Math.round((payable * percent) / 100))}
style={{
height: 30,
padding: '0 12px',
fontSize: 12,
borderRadius: 'var(--r-pill)',
border: `1px solid ${active ? 'var(--primary)' : 'var(--border)'}`,
background: active ? 'var(--primary-soft)' : 'var(--surface)',
color: active ? 'var(--primary)' : 'var(--text-2)',
fontWeight: active ? 700 : 500,
}}
>
{formatNumber(percent)}٪
</button>
);
})}
<span style={{ fontSize: 12, color: 'var(--text-3)' }}>
از {formatRial(payable)}
</span>
</div>
)}
{/* جزئیاتِ کارت‌خوان: انتخاب دستگاهِ ثبت‌شده + شناسه تراکنش */}
{r.method === 'pos' && (
<div style={{ display: 'flex', gap: 10 }}>