fix(a11y): label associations for AdminPromocodeCreate fields

Add htmlFor/id pairs for code, type, balance bonus, days count, tariff, promo group,
discount percent, discount validity, max uses and valid-until inputs (WCAG 1.3.1).
This commit is contained in:
c0mrade
2026-05-26 10:37:01 +03:00
parent 6f66cb6759
commit a635ca2316

View File

@@ -236,11 +236,12 @@ export default function AdminPromocodeCreate() {
<div className="card space-y-4"> <div className="card space-y-4">
{/* Code */} {/* Code */}
<div> <div>
<label className="mb-2 block text-sm font-medium text-dark-300"> <label htmlFor="pc-code" className="mb-2 block text-sm font-medium text-dark-300">
{t('admin.promocodes.form.code')} {t('admin.promocodes.form.code')}
<span className="text-error-400">*</span> <span className="text-error-400">*</span>
</label> </label>
<input <input
id="pc-code"
type="text" type="text"
value={code} value={code}
onChange={(e) => setCode(e.target.value.toUpperCase())} onChange={(e) => setCode(e.target.value.toUpperCase())}
@@ -252,10 +253,11 @@ export default function AdminPromocodeCreate() {
{/* Type */} {/* Type */}
<div> <div>
<label className="mb-2 block text-sm font-medium text-dark-300"> <label htmlFor="pc-type" className="mb-2 block text-sm font-medium text-dark-300">
{t('admin.promocodes.form.type')} {t('admin.promocodes.form.type')}
</label> </label>
<select <select
id="pc-type"
value={type} value={type}
onChange={(e) => setType(e.target.value as PromoCodeType)} onChange={(e) => setType(e.target.value as PromoCodeType)}
className="input" className="input"
@@ -275,12 +277,16 @@ export default function AdminPromocodeCreate() {
{/* Type-specific fields */} {/* Type-specific fields */}
{type === 'balance' && ( {type === 'balance' && (
<div> <div>
<label className="mb-2 block text-sm font-medium text-dark-300"> <label
htmlFor="pc-balance-bonus"
className="mb-2 block text-sm font-medium text-dark-300"
>
{t('admin.promocodes.form.bonusAmount')} {t('admin.promocodes.form.bonusAmount')}
<span className="text-error-400">*</span> <span className="text-error-400">*</span>
</label> </label>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<input <input
id="pc-balance-bonus"
type="number" type="number"
value={balanceBonusRubles} value={balanceBonusRubles}
onChange={createNumberInputHandler(setBalanceBonusRubles, 0)} onChange={createNumberInputHandler(setBalanceBonusRubles, 0)}
@@ -296,12 +302,13 @@ export default function AdminPromocodeCreate() {
{(type === 'subscription_days' || type === 'trial_subscription') && ( {(type === 'subscription_days' || type === 'trial_subscription') && (
<div> <div>
<label className="mb-2 block text-sm font-medium text-dark-300"> <label htmlFor="pc-sub-days" className="mb-2 block text-sm font-medium text-dark-300">
{t('admin.promocodes.form.daysCount')} {t('admin.promocodes.form.daysCount')}
<span className="text-error-400">*</span> <span className="text-error-400">*</span>
</label> </label>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<input <input
id="pc-sub-days"
type="number" type="number"
value={subscriptionDays} value={subscriptionDays}
onChange={createNumberInputHandler(setSubscriptionDays, 0)} onChange={createNumberInputHandler(setSubscriptionDays, 0)}
@@ -316,10 +323,11 @@ export default function AdminPromocodeCreate() {
{type === 'trial_subscription' && ( {type === 'trial_subscription' && (
<div> <div>
<label className="mb-2 block text-sm font-medium text-dark-300"> <label htmlFor="pc-tariff" className="mb-2 block text-sm font-medium text-dark-300">
{t('admin.promocodes.form.tariff', 'Тариф')} {t('admin.promocodes.form.tariff', 'Тариф')}
</label> </label>
<select <select
id="pc-tariff"
value={tariffId || ''} value={tariffId || ''}
onChange={(e) => setTariffId(e.target.value ? parseInt(e.target.value) : null)} onChange={(e) => setTariffId(e.target.value ? parseInt(e.target.value) : null)}
className="input" className="input"
@@ -350,11 +358,15 @@ export default function AdminPromocodeCreate() {
{type === 'promo_group' && ( {type === 'promo_group' && (
<div> <div>
<label className="mb-2 block text-sm font-medium text-dark-300"> <label
htmlFor="pc-promo-group"
className="mb-2 block text-sm font-medium text-dark-300"
>
{t('admin.promocodes.form.discountGroup')} {t('admin.promocodes.form.discountGroup')}
<span className="text-error-400">*</span> <span className="text-error-400">*</span>
</label> </label>
<select <select
id="pc-promo-group"
value={promoGroupId || ''} value={promoGroupId || ''}
onChange={(e) => setPromoGroupId(e.target.value ? parseInt(e.target.value) : null)} onChange={(e) => setPromoGroupId(e.target.value ? parseInt(e.target.value) : null)}
className="input" className="input"
@@ -372,12 +384,16 @@ export default function AdminPromocodeCreate() {
{type === 'discount' && ( {type === 'discount' && (
<> <>
<div> <div>
<label className="mb-2 block text-sm font-medium text-dark-300"> <label
htmlFor="pc-discount-percent"
className="mb-2 block text-sm font-medium text-dark-300"
>
{t('admin.promocodes.form.discountPercent')} {t('admin.promocodes.form.discountPercent')}
<span className="text-error-400">*</span> <span className="text-error-400">*</span>
</label> </label>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<input <input
id="pc-discount-percent"
type="number" type="number"
value={balanceBonusRubles} value={balanceBonusRubles}
onChange={(e) => { onChange={(e) => {
@@ -400,12 +416,16 @@ export default function AdminPromocodeCreate() {
</p> </p>
</div> </div>
<div> <div>
<label className="mb-2 block text-sm font-medium text-dark-300"> <label
htmlFor="pc-discount-validity"
className="mb-2 block text-sm font-medium text-dark-300"
>
{t('admin.promocodes.form.validityPeriod')} {t('admin.promocodes.form.validityPeriod')}
<span className="text-error-400">*</span> <span className="text-error-400">*</span>
</label> </label>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<input <input
id="pc-discount-validity"
type="number" type="number"
value={subscriptionDays} value={subscriptionDays}
onChange={(e) => { onChange={(e) => {
@@ -431,11 +451,12 @@ export default function AdminPromocodeCreate() {
{/* Max Uses */} {/* Max Uses */}
<div> <div>
<label className="mb-2 block text-sm font-medium text-dark-300"> <label htmlFor="pc-max-uses" className="mb-2 block text-sm font-medium text-dark-300">
{t('admin.promocodes.form.maxUses')} {t('admin.promocodes.form.maxUses')}
</label> </label>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<input <input
id="pc-max-uses"
type="number" type="number"
value={maxUses} value={maxUses}
onChange={createNumberInputHandler(setMaxUses, 0)} onChange={createNumberInputHandler(setMaxUses, 0)}
@@ -451,10 +472,11 @@ export default function AdminPromocodeCreate() {
{/* Valid Until */} {/* Valid Until */}
<div> <div>
<label className="mb-2 block text-sm font-medium text-dark-300"> <label htmlFor="pc-valid-until" className="mb-2 block text-sm font-medium text-dark-300">
{t('admin.promocodes.form.validUntil')} {t('admin.promocodes.form.validUntil')}
</label> </label>
<input <input
id="pc-valid-until"
type="date" type="date"
value={validUntil} value={validUntil}
onChange={(e) => setValidUntil(e.target.value)} onChange={(e) => setValidUntil(e.target.value)}