style: align AdminTariffCreate with other admin create pages

Added gap-3 to footer for consistency with AdminCampaignCreate
and AdminBroadcastCreate pages
This commit is contained in:
c0mrade
2026-02-02 01:49:04 +03:00
parent dc17695206
commit 1ca34fa3d1

View File

@@ -46,7 +46,7 @@ const InfinityIcon = () => (
);
const CalendarIcon = () => (
<svg className="h-8 w-8" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
<svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
<path
strokeLinecap="round"
strokeLinejoin="round"
@@ -56,7 +56,7 @@ const CalendarIcon = () => (
);
const SunIcon = () => (
<svg className="h-8 w-8" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
<svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
<path
strokeLinecap="round"
strokeLinejoin="round"
@@ -65,6 +65,22 @@ const SunIcon = () => (
</svg>
);
const RefreshIcon = () => (
<svg
className="h-4 w-4 animate-spin"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth={2}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7M4.031 9.865a8.25 8.25 0 0113.803-3.7l3.181 3.182m0-4.991v4.99"
/>
</svg>
);
type TariffType = 'period' | 'daily' | null;
export default function AdminTariffCreate() {
@@ -131,7 +147,6 @@ export default function AdminTariffCreate() {
refetchOnMount: true,
refetchOnWindowFocus: false,
select: useCallback((data: TariffDetail) => {
// Set form values from tariff
setTariffType(data.is_daily ? 'daily' : 'period');
setName(data.name);
setDescription(data.description || '');
@@ -199,7 +214,6 @@ export default function AdminTariffCreate() {
traffic_reset_mode: trafficResetMode,
};
// Add period tariff specific fields
if (!isDaily) {
data.custom_days_enabled = customDaysEnabled;
data.price_per_day_kopeks = pricePerDayKopeks;
@@ -268,11 +282,11 @@ export default function AdminTariffCreate() {
// Type selection step (only for creation)
if (!isEdit && tariffType === null) {
return (
<div className="animate-fade-in">
<div className="mb-6 flex items-center gap-3">
<div className="space-y-6">
<div className="flex items-center gap-3">
<AdminBackButton />
<div>
<h1 className="text-xl font-semibold text-dark-100">{t('admin.tariffs.selectType')}</h1>
<h1 className="text-xl font-bold text-dark-100">{t('admin.tariffs.selectType')}</h1>
<p className="text-sm text-dark-400">{t('admin.tariffs.selectTypeDesc')}</p>
</div>
</div>
@@ -280,7 +294,7 @@ export default function AdminTariffCreate() {
<div className="grid gap-4 sm:grid-cols-2">
<button
onClick={() => setTariffType('period')}
className="group rounded-xl bg-dark-800 p-6 text-left transition-colors hover:bg-dark-700"
className="card group p-6 text-left transition-colors hover:border-accent-500/50"
>
<div className="flex items-center gap-4">
<div className="rounded-lg bg-accent-500/20 p-3 text-accent-400 group-hover:bg-accent-500/30">
@@ -294,7 +308,7 @@ export default function AdminTariffCreate() {
</button>
<button
onClick={() => setTariffType('daily')}
className="group rounded-xl bg-dark-800 p-6 text-left transition-colors hover:bg-dark-700"
className="card group p-6 text-left transition-colors hover:border-warning-500/50"
>
<div className="flex items-center gap-4">
<div className="rounded-lg bg-warning-500/20 p-3 text-warning-400 group-hover:bg-warning-500/30">
@@ -315,23 +329,23 @@ export default function AdminTariffCreate() {
const accentColor = isDaily ? 'warning' : 'accent';
return (
<div className="animate-fade-in">
<div className="space-y-6">
{/* Header */}
<div className="mb-6 flex items-center gap-3">
<div className="flex items-center gap-3">
<AdminBackButton />
<div className="flex items-center gap-3">
<div className={`rounded-lg bg-${accentColor}-500/20 p-2 text-${accentColor}-400`}>
{isDaily ? <SunIcon /> : <CalendarIcon />}
</div>
<div>
<h1 className="text-xl font-semibold text-dark-100">
<h1 className="text-xl font-bold text-dark-100">
{isEdit
? t('admin.tariffs.editTitle')
: isDaily
? t('admin.tariffs.newDailyTitle')
: t('admin.tariffs.newPeriodTitle')}
</h1>
<p className="text-xs text-dark-500">
<p className="text-sm text-dark-400">
{isDaily ? t('admin.tariffs.dailyDeduction') : t('admin.tariffs.periodPayment')}
</p>
</div>
@@ -340,7 +354,7 @@ export default function AdminTariffCreate() {
{/* Tabs */}
<div
className="scrollbar-hide -mx-4 mb-6 flex gap-2 overflow-x-auto px-4 py-1"
className="scrollbar-hide -mx-4 flex gap-2 overflow-x-auto px-4 py-1"
style={{ WebkitOverflowScrolling: 'touch' }}
>
{(isDaily
@@ -353,7 +367,7 @@ export default function AdminTariffCreate() {
className={`shrink-0 whitespace-nowrap rounded-xl px-4 py-2.5 text-sm font-medium transition-all ${
activeTab === tab
? `bg-${accentColor}-500/15 text-${accentColor}-400 ring-1 ring-${accentColor}-500/30`
: 'bg-dark-800/50 text-dark-400 active:bg-dark-700'
: 'bg-dark-800/50 text-dark-400 hover:bg-dark-700'
}`}
>
{tab === 'basic' && t('admin.tariffs.tabBasic')}
@@ -365,44 +379,40 @@ export default function AdminTariffCreate() {
</div>
{/* Content */}
<div className="space-y-6">
{activeTab === 'basic' && (
<div className="space-y-4">
<div className="card space-y-4">
{/* Name */}
<div className="rounded-xl bg-dark-800 p-4">
<label className="mb-1 block text-sm text-dark-300">
<div>
<label className="mb-2 block text-sm font-medium text-dark-300">
{t('admin.tariffs.nameLabel')}
</label>
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
className="w-full rounded-lg border border-dark-600 bg-dark-700 px-3 py-2 text-dark-100 focus:border-accent-500 focus:outline-none"
className="input"
placeholder={
isDaily
? t('admin.tariffs.nameExampleDaily')
: t('admin.tariffs.nameExamplePeriod')
isDaily ? t('admin.tariffs.nameExampleDaily') : t('admin.tariffs.nameExamplePeriod')
}
/>
</div>
{/* Description */}
<div className="rounded-xl bg-dark-800 p-4">
<label className="mb-1 block text-sm text-dark-300">
<div>
<label className="mb-2 block text-sm font-medium text-dark-300">
{t('admin.tariffs.descriptionLabel')}
</label>
<textarea
value={description}
onChange={(e) => setDescription(e.target.value)}
className="w-full resize-none rounded-lg border border-dark-600 bg-dark-700 px-3 py-2 text-dark-100 focus:border-accent-500 focus:outline-none"
rows={2}
className="input min-h-[80px] resize-none"
placeholder={t('admin.tariffs.descriptionPlaceholder')}
/>
</div>
{/* Daily Price (only for daily tariff) */}
{isDaily && (
<div className="rounded-xl border border-warning-500/30 bg-warning-500/10 p-4">
<div className="rounded-lg border border-warning-500/30 bg-warning-500/10 p-4">
<label className="mb-2 block text-sm font-medium text-warning-400">
{t('admin.tariffs.dailyPriceLabel')}
</label>
@@ -413,21 +423,19 @@ export default function AdminTariffCreate() {
onChange={(e) =>
setDailyPriceKopeks(Math.max(0, parseFloat(e.target.value) || 0) * 100)
}
className="w-32 rounded-lg border border-dark-600 bg-dark-700 px-3 py-2 text-dark-100 focus:border-accent-500 focus:outline-none"
className="input w-32"
min={0}
step={0.1}
/>
<span className="text-dark-400">{t('admin.tariffs.currencyPerDay')}</span>
</div>
<p className="mt-2 text-xs text-dark-500">
{t('admin.tariffs.dailyDeductionDesc')}
</p>
<p className="mt-2 text-xs text-dark-500">{t('admin.tariffs.dailyDeductionDesc')}</p>
</div>
)}
{/* Traffic Limit */}
<div className="rounded-xl bg-dark-800 p-4">
<label className="mb-1 block text-sm text-dark-300">
<div>
<label className="mb-2 block text-sm font-medium text-dark-300">
{t('admin.tariffs.trafficLimitLabel')}
</label>
<div className="flex items-center gap-2">
@@ -435,7 +443,7 @@ export default function AdminTariffCreate() {
type="number"
value={trafficLimitGb}
onChange={(e) => setTrafficLimitGb(Math.max(0, parseInt(e.target.value) || 0))}
className="w-32 rounded-lg border border-dark-600 bg-dark-700 px-3 py-2 text-dark-100 focus:border-accent-500 focus:outline-none"
className="input w-32"
min={0}
/>
<span className="text-dark-400">{t('admin.tariffs.gbUnit')}</span>
@@ -450,22 +458,22 @@ export default function AdminTariffCreate() {
</div>
{/* Device Limit */}
<div className="rounded-xl bg-dark-800 p-4">
<label className="mb-1 block text-sm text-dark-300">
<div>
<label className="mb-2 block text-sm font-medium text-dark-300">
{t('admin.tariffs.deviceLimitLabel')}
</label>
<input
type="number"
value={deviceLimit}
onChange={(e) => setDeviceLimit(Math.max(1, parseInt(e.target.value) || 1))}
className="w-32 rounded-lg border border-dark-600 bg-dark-700 px-3 py-2 text-dark-100 focus:border-accent-500 focus:outline-none"
className="input w-32"
min={1}
/>
</div>
{/* Tier Level */}
<div className="rounded-xl bg-dark-800 p-4">
<label className="mb-1 block text-sm text-dark-300">
<div>
<label className="mb-2 block text-sm font-medium text-dark-300">
{t('admin.tariffs.tierLevelLabel')}
</label>
<input
@@ -474,7 +482,7 @@ export default function AdminTariffCreate() {
onChange={(e) =>
setTierLevel(Math.min(10, Math.max(1, parseInt(e.target.value) || 1)))
}
className="w-32 rounded-lg border border-dark-600 bg-dark-700 px-3 py-2 text-dark-100 focus:border-accent-500 focus:outline-none"
className="input w-32"
min={1}
max={10}
/>
@@ -484,11 +492,11 @@ export default function AdminTariffCreate() {
)}
{activeTab === 'periods' && !isDaily && (
<div className="space-y-4">
<div className="card space-y-4">
<p className="text-sm text-dark-400">{t('admin.tariffs.periodsTabHint')}</p>
{/* Add new period */}
<div className="rounded-xl border border-dashed border-dark-600 bg-dark-800/50 p-4">
<div className="rounded-lg border border-dashed border-dark-600 bg-dark-800/50 p-4">
<h4 className="mb-3 text-sm font-medium text-dark-300">
{t('admin.tariffs.addPeriodTitle')}
</h4>
@@ -501,7 +509,7 @@ export default function AdminTariffCreate() {
type="number"
value={newPeriodDays}
onChange={(e) => setNewPeriodDays(Math.max(1, parseInt(e.target.value) || 1))}
className="w-24 rounded-lg border border-dark-500 bg-dark-600 px-3 py-2 text-dark-100 focus:border-accent-500 focus:outline-none"
className="input w-24"
min={1}
/>
</div>
@@ -513,14 +521,14 @@ export default function AdminTariffCreate() {
type="number"
value={newPeriodPrice}
onChange={(e) => setNewPeriodPrice(Math.max(1, parseInt(e.target.value) || 1))}
className="w-28 rounded-lg border border-dark-500 bg-dark-600 px-3 py-2 text-dark-100 focus:border-accent-500 focus:outline-none"
className="input w-28"
min={1}
/>
</div>
<button
onClick={addPeriod}
disabled={periodPrices.some((p) => p.days === newPeriodDays)}
className="flex items-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-white transition-colors hover:bg-accent-600 disabled:cursor-not-allowed disabled:opacity-50"
className="btn-primary flex items-center gap-2"
>
<PlusIcon />
{t('admin.tariffs.addButton')}
@@ -530,15 +538,13 @@ export default function AdminTariffCreate() {
{/* Period list */}
{periodPrices.length === 0 ? (
<div className="py-8 text-center text-dark-500">
{t('admin.tariffs.noPeriodsHint')}
</div>
<div className="py-8 text-center text-dark-500">{t('admin.tariffs.noPeriodsHint')}</div>
) : (
<div className="space-y-2">
{periodPrices.map((period) => (
<div
key={period.days}
className="flex items-center gap-3 rounded-xl bg-dark-800 p-3"
className="flex items-center gap-3 rounded-lg bg-dark-800 p-3"
>
<div className="w-20 font-medium text-dark-300">
{period.days} {t('admin.tariffs.daysShort')}
@@ -549,7 +555,7 @@ export default function AdminTariffCreate() {
onChange={(e) =>
updatePeriodPrice(period.days, Math.max(0, parseFloat(e.target.value) || 0))
}
className="w-28 rounded-lg border border-dark-500 bg-dark-600 px-3 py-2 text-dark-100 focus:border-accent-500 focus:outline-none"
className="input w-28"
min={0}
step={1}
/>
@@ -569,26 +575,27 @@ export default function AdminTariffCreate() {
)}
{activeTab === 'servers' && (
<div className="space-y-2">
<p className="mb-4 text-sm text-dark-400">{t('admin.tariffs.serversTabHint')}</p>
<div className="card space-y-4">
<p className="text-sm text-dark-400">{t('admin.tariffs.serversTabHint')}</p>
{servers.length === 0 ? (
<p className="py-4 text-center text-dark-500">
{t('admin.tariffs.noServersAvailable')}
</p>
) : (
servers.map((server: ServerInfo) => {
<div className="max-h-64 space-y-2 overflow-y-auto">
{servers.map((server: ServerInfo) => {
const isSelected = selectedSquads.includes(server.squad_uuid);
return (
<div
<button
key={server.id}
type="button"
onClick={() => toggleServer(server.squad_uuid)}
className={`cursor-pointer rounded-xl p-3 transition-colors ${
className={`flex w-full items-center gap-3 rounded-lg p-3 text-left transition-colors ${
isSelected
? `border border-${accentColor}-500/50 bg-${accentColor}-500/20`
: 'border border-transparent bg-dark-800 hover:bg-dark-700'
? `bg-${accentColor}-500/20 text-${accentColor}-300`
: 'bg-dark-800 text-dark-300 hover:bg-dark-700'
}`}
>
<div className="flex items-center gap-3">
<div
className={`flex h-5 w-5 items-center justify-center rounded ${
isSelected ? 'bg-accent-500 text-white' : 'bg-dark-600'
@@ -596,26 +603,25 @@ export default function AdminTariffCreate() {
>
{isSelected && <CheckIcon />}
</div>
<span className="flex-1 text-dark-200">{server.display_name}</span>
<span className="flex-1 text-sm font-medium">{server.display_name}</span>
{server.country_code && (
<span className="text-xs text-dark-500">{server.country_code}</span>
)}
</div>
</div>
</button>
);
})
})}
</div>
)}
</div>
)}
{activeTab === 'extra' && (
<div className="space-y-6">
<div className="space-y-4">
{/* Device addon */}
<div className="rounded-xl bg-dark-800 p-4">
<h4 className="mb-3 text-sm font-medium text-dark-200">
<div className="card space-y-3">
<h4 className="text-sm font-medium text-dark-200">
{t('admin.tariffs.extraDeviceTitle')}
</h4>
<div className="space-y-3">
<div className="flex items-center gap-3">
<span className="w-48 text-sm text-dark-400">
{t('admin.tariffs.devicePriceLabel')}
@@ -626,7 +632,7 @@ export default function AdminTariffCreate() {
onChange={(e) =>
setDevicePriceKopeks(Math.max(0, parseFloat(e.target.value) || 0) * 100)
}
className="w-24 rounded-lg border border-dark-500 bg-dark-600 px-3 py-2 text-dark-100 focus:border-accent-500 focus:outline-none"
className="input w-24"
min={0}
step={1}
/>
@@ -641,36 +647,35 @@ export default function AdminTariffCreate() {
type="number"
value={maxDeviceLimit}
onChange={(e) => setMaxDeviceLimit(Math.max(0, parseInt(e.target.value) || 0))}
className="w-24 rounded-lg border border-dark-500 bg-dark-600 px-3 py-2 text-dark-100 focus:border-accent-500 focus:outline-none"
className="input w-24"
min={0}
/>
</div>
<p className="text-xs text-dark-500">{t('admin.tariffs.noLimitHint')}</p>
</div>
</div>
{/* Traffic topup */}
<div className="rounded-xl bg-dark-800 p-4">
<div className="mb-3 flex items-center justify-between">
<div className="card space-y-3">
<div className="flex items-center justify-between">
<h4 className="text-sm font-medium text-dark-200">
{t('admin.tariffs.extraTrafficTitle')}
</h4>
<button
type="button"
onClick={() => setTrafficTopupEnabled(!trafficTopupEnabled)}
className={`relative h-6 w-10 rounded-full transition-colors ${
trafficTopupEnabled ? `bg-${accentColor}-500` : 'bg-dark-600'
className={`relative h-6 w-11 rounded-full transition-colors ${
trafficTopupEnabled ? 'bg-accent-500' : 'bg-dark-600'
}`}
>
<span
className={`absolute top-1 h-4 w-4 rounded-full bg-white transition-transform ${
trafficTopupEnabled ? 'left-5' : 'left-1'
trafficTopupEnabled ? 'left-6' : 'left-1'
}`}
/>
</button>
</div>
{trafficTopupEnabled && (
<div className="space-y-3">
<>
<div className="flex items-center gap-3">
<span className="w-32 text-sm text-dark-400">
{t('admin.tariffs.trafficMaxLimitLabel')}
@@ -681,15 +686,12 @@ export default function AdminTariffCreate() {
onChange={(e) =>
setMaxTopupTrafficGb(Math.max(0, parseInt(e.target.value) || 0))
}
className="w-24 rounded-lg border border-dark-500 bg-dark-600 px-3 py-2 text-dark-100 focus:border-accent-500 focus:outline-none"
className="input w-24"
min={0}
/>
<span className="text-dark-400">{t('admin.tariffs.gbUnit')}</span>
<span className="text-xs text-dark-500">
{t('admin.tariffs.trafficLimitHint2')}
</span>
</div>
<div className="mt-3">
<div>
<span className="text-sm text-dark-400">
{t('admin.tariffs.trafficPackagesLabel')}
</span>
@@ -709,7 +711,7 @@ export default function AdminTariffCreate() {
[String(gb)]: price,
}));
}}
className="w-20 rounded border border-dark-500 bg-dark-600 px-2 py-1 text-sm text-dark-100 focus:border-accent-500 focus:outline-none"
className="input w-20"
min={0}
step={1}
/>
@@ -718,38 +720,36 @@ export default function AdminTariffCreate() {
))}
</div>
</div>
</div>
</>
)}
</div>
{/* Custom days (period only) */}
{!isDaily && (
<div className="rounded-xl bg-dark-800 p-4">
<div className="mb-3 flex items-center justify-between">
<div className="card space-y-3">
<div className="flex items-center justify-between">
<div>
<h4 className="text-sm font-medium text-dark-200">
{t('admin.tariffs.customDaysTitle')}
</h4>
<p className="mt-1 text-xs text-dark-500">
{t('admin.tariffs.customDaysDesc')}
</p>
<p className="mt-1 text-xs text-dark-500">{t('admin.tariffs.customDaysDesc')}</p>
</div>
<button
type="button"
onClick={() => setCustomDaysEnabled(!customDaysEnabled)}
className={`relative h-6 w-10 rounded-full transition-colors ${
className={`relative h-6 w-11 rounded-full transition-colors ${
customDaysEnabled ? 'bg-accent-500' : 'bg-dark-600'
}`}
>
<span
className={`absolute top-1 h-4 w-4 rounded-full bg-white transition-transform ${
customDaysEnabled ? 'left-5' : 'left-1'
customDaysEnabled ? 'left-6' : 'left-1'
}`}
/>
</button>
</div>
{customDaysEnabled && (
<div className="space-y-3 border-t border-dark-600 pt-2">
<div className="space-y-3 border-t border-dark-700 pt-3">
<div className="flex items-center gap-3">
<span className="w-32 text-sm text-dark-400">
{t('admin.tariffs.pricePerDayLabel')}
@@ -760,7 +760,7 @@ export default function AdminTariffCreate() {
onChange={(e) =>
setPricePerDayKopeks(Math.max(0, parseFloat(e.target.value) || 0) * 100)
}
className="w-24 rounded-lg border border-dark-500 bg-dark-600 px-3 py-2 text-dark-100 focus:border-accent-500 focus:outline-none"
className="input w-24"
min={0}
step={0.1}
/>
@@ -774,7 +774,7 @@ export default function AdminTariffCreate() {
type="number"
value={minDays}
onChange={(e) => setMinDays(Math.max(1, parseInt(e.target.value) || 1))}
className="w-24 rounded-lg border border-dark-500 bg-dark-600 px-3 py-2 text-dark-100 focus:border-accent-500 focus:outline-none"
className="input w-24"
min={1}
/>
</div>
@@ -786,7 +786,7 @@ export default function AdminTariffCreate() {
type="number"
value={maxDays}
onChange={(e) => setMaxDays(Math.max(1, parseInt(e.target.value) || 1))}
className="w-24 rounded-lg border border-dark-500 bg-dark-600 px-3 py-2 text-dark-100 focus:border-accent-500 focus:outline-none"
className="input w-24"
min={1}
/>
</div>
@@ -797,8 +797,8 @@ export default function AdminTariffCreate() {
{/* Custom traffic (period only) */}
{!isDaily && (
<div className="rounded-xl bg-dark-800 p-4">
<div className="mb-3 flex items-center justify-between">
<div className="card space-y-3">
<div className="flex items-center justify-between">
<div>
<h4 className="text-sm font-medium text-dark-200">
{t('admin.tariffs.customTrafficTitle')}
@@ -810,19 +810,19 @@ export default function AdminTariffCreate() {
<button
type="button"
onClick={() => setCustomTrafficEnabled(!customTrafficEnabled)}
className={`relative h-6 w-10 rounded-full transition-colors ${
className={`relative h-6 w-11 rounded-full transition-colors ${
customTrafficEnabled ? 'bg-accent-500' : 'bg-dark-600'
}`}
>
<span
className={`absolute top-1 h-4 w-4 rounded-full bg-white transition-transform ${
customTrafficEnabled ? 'left-5' : 'left-1'
customTrafficEnabled ? 'left-6' : 'left-1'
}`}
/>
</button>
</div>
{customTrafficEnabled && (
<div className="space-y-3 border-t border-dark-600 pt-2">
<div className="space-y-3 border-t border-dark-700 pt-3">
<div className="flex items-center gap-3">
<span className="w-32 text-sm text-dark-400">
{t('admin.tariffs.pricePerGbLabel')}
@@ -835,7 +835,7 @@ export default function AdminTariffCreate() {
Math.max(0, parseFloat(e.target.value) || 0) * 100,
)
}
className="w-24 rounded-lg border border-dark-500 bg-dark-600 px-3 py-2 text-dark-100 focus:border-accent-500 focus:outline-none"
className="input w-24"
min={0}
step={0.1}
/>
@@ -848,10 +848,8 @@ export default function AdminTariffCreate() {
<input
type="number"
value={minTrafficGb}
onChange={(e) =>
setMinTrafficGb(Math.max(1, parseInt(e.target.value) || 1))
}
className="w-24 rounded-lg border border-dark-500 bg-dark-600 px-3 py-2 text-dark-100 focus:border-accent-500 focus:outline-none"
onChange={(e) => setMinTrafficGb(Math.max(1, parseInt(e.target.value) || 1))}
className="input w-24"
min={1}
/>
</div>
@@ -862,10 +860,8 @@ export default function AdminTariffCreate() {
<input
type="number"
value={maxTrafficGb}
onChange={(e) =>
setMaxTrafficGb(Math.max(1, parseInt(e.target.value) || 1))
}
className="w-24 rounded-lg border border-dark-500 bg-dark-600 px-3 py-2 text-dark-100 focus:border-accent-500 focus:outline-none"
onChange={(e) => setMaxTrafficGb(Math.max(1, parseInt(e.target.value) || 1))}
className="input w-24"
min={1}
/>
</div>
@@ -875,98 +871,48 @@ export default function AdminTariffCreate() {
)}
{/* Traffic reset mode */}
<div className="rounded-xl bg-dark-800 p-4">
<h4 className="mb-3 text-sm font-medium text-dark-200">
<div className="card space-y-3">
<h4 className="text-sm font-medium text-dark-200">
{t('admin.tariffs.trafficResetModeTitle')}
</h4>
<p className="mb-3 text-xs text-dark-500">
{t('admin.tariffs.trafficResetModeDesc')}
</p>
<div className="space-y-2">
<p className="text-xs text-dark-500">{t('admin.tariffs.trafficResetModeDesc')}</p>
<div className="grid grid-cols-2 gap-2">
{[
{
value: null,
labelKey: 'admin.tariffs.resetModeGlobal',
descKey: 'admin.tariffs.resetModeGlobalDesc',
emoji: '🌐',
},
{
value: 'DAY',
labelKey: 'admin.tariffs.resetModeDaily',
descKey: 'admin.tariffs.resetModeDailyDesc',
emoji: '📅',
},
{
value: 'WEEK',
labelKey: 'admin.tariffs.resetModeWeekly',
descKey: 'admin.tariffs.resetModeWeeklyDesc',
emoji: '📆',
},
{
value: 'MONTH',
labelKey: 'admin.tariffs.resetModeMonthly',
descKey: 'admin.tariffs.resetModeMonthlyDesc',
emoji: '🗓️',
},
{
value: 'NO_RESET',
labelKey: 'admin.tariffs.resetModeNever',
descKey: 'admin.tariffs.resetModeNeverDesc',
emoji: '🚫',
},
{ value: null, labelKey: 'admin.tariffs.resetModeGlobal', emoji: '🌐' },
{ value: 'DAY', labelKey: 'admin.tariffs.resetModeDaily', emoji: '📅' },
{ value: 'WEEK', labelKey: 'admin.tariffs.resetModeWeekly', emoji: '📆' },
{ value: 'MONTH', labelKey: 'admin.tariffs.resetModeMonthly', emoji: '🗓️' },
{ value: 'NO_RESET', labelKey: 'admin.tariffs.resetModeNever', emoji: '🚫' },
].map((option) => (
<button
key={option.value || 'global'}
type="button"
onClick={() => setTrafficResetMode(option.value)}
className={`w-full rounded-lg p-3 text-left transition-colors ${
className={`rounded-lg p-3 text-left text-sm transition-colors ${
trafficResetMode === option.value
? `border border-${accentColor}-500 bg-${accentColor}-500/20`
: 'border border-dark-500 bg-dark-600 hover:border-dark-400'
? `bg-${accentColor}-500/20 text-${accentColor}-300 ring-1 ring-${accentColor}-500/30`
: 'bg-dark-800 text-dark-300 hover:bg-dark-700'
}`}
>
<div className="flex items-center justify-between">
<div>
<span className="text-sm text-dark-100">
{option.emoji} {t(option.labelKey)}
</span>
<p className="mt-0.5 text-xs text-dark-400">{t(option.descKey)}</p>
</div>
{trafficResetMode === option.value && (
<span className={`text-${accentColor}-400`}>
<CheckIcon />
</span>
)}
</div>
</button>
))}
</div>
</div>
</div>
)}
</div>
{/* Footer */}
<div className="fixed inset-x-0 bottom-0 border-t border-dark-700 bg-dark-900/95 p-4 backdrop-blur-sm">
<div className="mx-auto flex max-w-2xl justify-end gap-3">
<button
onClick={() => navigate('/admin/tariffs')}
className="px-4 py-2 text-dark-300 transition-colors hover:text-dark-100"
>
{t('admin.tariffs.cancelButton')}
</button>
<div className="card flex items-center justify-end gap-3">
<button
onClick={handleSubmit}
disabled={!isValid || isLoading}
className="rounded-lg bg-accent-500 px-4 py-2 text-white transition-colors hover:bg-accent-600 disabled:cursor-not-allowed disabled:opacity-50"
className="btn-primary flex items-center gap-2"
>
{isLoading && <RefreshIcon />}
{isLoading ? t('admin.tariffs.savingButton') : t('admin.tariffs.saveButton')}
</button>
</div>
</div>
{/* Spacer for fixed footer */}
<div className="h-20" />
</div>
);
}