mirror of
https://github.com/Tria-plc/emaui.git
synced 2026-09-07 21:15:42 +00:00
feat: add configuration UI for license behavior and multi-stage examination fees
This commit is contained in:
@@ -179,9 +179,25 @@ function FeeEditModal({
|
||||
// are real configuration states, not blank fields.
|
||||
const [chargeable, setChargeable] = useState(true);
|
||||
const [sameAsNew, setSameAsNew] = useState(true);
|
||||
// The examined-certificate stages. Held the same way — null means "this stage
|
||||
// is not charged", which is different from a blank box.
|
||||
const [eligibilityFee, setEligibilityFee] = useState<number | ''>('');
|
||||
const [examinationFee, setExaminationFee] = useState<number | ''>('');
|
||||
const [certificateFee, setCertificateFee] = useState<number | ''>('');
|
||||
|
||||
const examined = licenseType?.requiresExamination ?? false;
|
||||
|
||||
useEffect(() => {
|
||||
if (!licenseType) return;
|
||||
setEligibilityFee(
|
||||
licenseType.feeEligibility == null ? '' : Number(licenseType.feeEligibility),
|
||||
);
|
||||
setExaminationFee(
|
||||
licenseType.feeExamination == null ? '' : Number(licenseType.feeExamination),
|
||||
);
|
||||
setCertificateFee(
|
||||
licenseType.feeCertificate == null ? '' : Number(licenseType.feeCertificate),
|
||||
);
|
||||
setChargeable(licenseType.feeNewApplication !== null);
|
||||
setNewFee(
|
||||
licenseType.feeNewApplication === null
|
||||
@@ -221,6 +237,14 @@ function FeeEditModal({
|
||||
feeNewApplication: chargeable ? Number(newFee) : null,
|
||||
feeRenewal: chargeable && !sameAsNew ? Number(renewalFee) : null,
|
||||
feeCurrency: currency.trim() || 'ETB',
|
||||
// Only sent for examined types; otherwise the columns stay untouched.
|
||||
...(examined
|
||||
? {
|
||||
feeEligibility: eligibilityFee === '' ? null : Number(eligibilityFee),
|
||||
feeExamination: examinationFee === '' ? null : Number(examinationFee),
|
||||
feeCertificate: certificateFee === '' ? null : Number(certificateFee),
|
||||
}
|
||||
: {}),
|
||||
}).unwrap();
|
||||
notify.success(
|
||||
t('paymentConfig.modal.updated', {
|
||||
@@ -325,6 +349,68 @@ function FeeEditModal({
|
||||
</>
|
||||
)}
|
||||
|
||||
{examined && (
|
||||
<>
|
||||
<Alert
|
||||
variant="light"
|
||||
color="blue"
|
||||
icon={<IconInfoCircle size={16} />}
|
||||
>
|
||||
<Text size="sm">
|
||||
{t(
|
||||
'paymentConfig.modal.examinedNotice',
|
||||
'This certificate is earned by examination, so it is charged in three stages. Unlike the fees above, these are not fixed at approval — a change applies to candidates already part-way through. Clearing one while candidates are waiting to pay it will be refused.',
|
||||
)}
|
||||
</Text>
|
||||
</Alert>
|
||||
|
||||
<NumberInput
|
||||
label={t('paymentConfig.modal.eligibilityFeeLabel', 'Eligibility assessment fee')}
|
||||
description={t(
|
||||
'paymentConfig.modal.eligibilityFeeHint',
|
||||
'Due on submission, before an officer reviews the application. Leave empty for no charge.',
|
||||
)}
|
||||
value={eligibilityFee}
|
||||
onChange={(v) => setEligibilityFee(v === '' ? '' : Number(v))}
|
||||
min={0}
|
||||
max={9_999_999_999}
|
||||
thousandSeparator=","
|
||||
allowNegative={false}
|
||||
decimalScale={2}
|
||||
/>
|
||||
|
||||
<NumberInput
|
||||
label={t('paymentConfig.modal.examinationFeeLabel', 'Examination fee')}
|
||||
description={t(
|
||||
'paymentConfig.modal.examinationFeeHint',
|
||||
'Due once eligibility is approved, and again for a retake.',
|
||||
)}
|
||||
value={examinationFee}
|
||||
onChange={(v) => setExaminationFee(v === '' ? '' : Number(v))}
|
||||
min={0}
|
||||
max={9_999_999_999}
|
||||
thousandSeparator=","
|
||||
allowNegative={false}
|
||||
decimalScale={2}
|
||||
/>
|
||||
|
||||
<NumberInput
|
||||
label={t('paymentConfig.modal.certificateFeeLabel', 'Certificate fee')}
|
||||
description={t(
|
||||
'paymentConfig.modal.certificateFeeHint',
|
||||
'Due after a pass, before the certificate is issued.',
|
||||
)}
|
||||
value={certificateFee}
|
||||
onChange={(v) => setCertificateFee(v === '' ? '' : Number(v))}
|
||||
min={0}
|
||||
max={9_999_999_999}
|
||||
thousandSeparator=","
|
||||
allowNegative={false}
|
||||
decimalScale={2}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
<ModalFooter mt="xs">
|
||||
<Button variant="default" onClick={onClose} disabled={isLoading}>
|
||||
{t('paymentConfig.modal.cancel', 'Cancel')}
|
||||
|
||||
Reference in New Issue
Block a user