feat(ui): заменить все нативные date-инпуты на DateField

Тёмный DateField теперь везде, где был браузерный <input type="date">: фильтр
периода в Трафике, диапазон дат в Платежах и Аудит-логе, срок действия промокода.
Единый вид во всём кабинете. (datetime-local не трогал — там нужно ещё и время.)
This commit is contained in:
c0mrade
2026-06-02 16:17:10 +03:00
parent edd2d25024
commit 016da9f638
4 changed files with 27 additions and 31 deletions

View File

@@ -1,5 +1,6 @@
import { useTranslation } from 'react-i18next';
import { CalendarIcon, XIcon } from '../TrafficIcons';
import { DateField } from '../../../DateField';
// ──────────────────────────────────────────────────────────────────
// PeriodSelector — switches between fixed period tabs (1/3/7/14/30
@@ -44,22 +45,18 @@ export function PeriodSelector({
<div className="flex items-center gap-2">
<CalendarIcon className="h-4 w-4" />
<span className="text-xs text-dark-400">{t('admin.trafficUsage.dateFrom')}</span>
<input
type="date"
<DateField
value={customStart}
min={minDate}
max={customEnd || today}
onChange={(e) => onCustomStartChange(e.target.value)}
className="rounded-lg border border-dark-700 bg-dark-800 px-2 py-1 text-xs text-dark-200 focus:border-dark-600 focus:outline-none"
onChange={onCustomStartChange}
/>
<span className="text-xs text-dark-400">{t('admin.trafficUsage.dateTo')}</span>
<input
type="date"
<DateField
value={customEnd}
min={customStart || minDate}
max={today}
onChange={(e) => onCustomEndChange(e.target.value)}
className="rounded-lg border border-dark-700 bg-dark-800 px-2 py-1 text-xs text-dark-200 focus:border-dark-600 focus:outline-none"
onChange={onCustomEndChange}
/>
<button
onClick={onToggleDateMode}

View File

@@ -5,6 +5,7 @@ import { useTranslation } from 'react-i18next';
import type { TFunction } from 'i18next';
import { rbacApi, AuditLogEntry, AuditLogFilters } from '@/api/rbac';
import { PermissionGate } from '@/components/auth/PermissionGate';
import { DateField } from '@/components/DateField';
import { usePlatform } from '@/platform/hooks/usePlatform';
import {
BackIcon,
@@ -704,12 +705,11 @@ export default function AdminAuditLog() {
>
{t('admin.auditLog.filters.dateFrom')}
</label>
<input
id="filter-date-from"
type="date"
<DateField
value={filters.dateFrom}
onChange={(e) => setFilters((prev) => ({ ...prev, dateFrom: e.target.value }))}
className="w-full rounded-lg border border-dark-600 bg-dark-900 px-3 py-2 text-sm text-dark-100 outline-none transition-colors focus:border-accent-500"
max={filters.dateTo}
onChange={(v) => setFilters((prev) => ({ ...prev, dateFrom: v }))}
className="flex w-full items-center gap-2 rounded-lg border border-dark-600 bg-dark-900 px-3 py-2 text-sm text-dark-100 transition-colors hover:border-accent-500"
/>
</div>
@@ -721,12 +721,11 @@ export default function AdminAuditLog() {
>
{t('admin.auditLog.filters.dateTo')}
</label>
<input
id="filter-date-to"
type="date"
<DateField
value={filters.dateTo}
onChange={(e) => setFilters((prev) => ({ ...prev, dateTo: e.target.value }))}
className="w-full rounded-lg border border-dark-600 bg-dark-900 px-3 py-2 text-sm text-dark-100 outline-none transition-colors focus:border-accent-500"
min={filters.dateFrom}
onChange={(v) => setFilters((prev) => ({ ...prev, dateTo: v }))}
className="flex w-full items-center gap-2 rounded-lg border border-dark-600 bg-dark-900 px-3 py-2 text-sm text-dark-100 transition-colors hover:border-accent-500"
/>
</div>
</div>

View File

@@ -3,6 +3,7 @@ import { useNavigate } from 'react-router';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';
import { adminPaymentsApi, type SearchStats } from '../api/adminPayments';
import { DateField } from '../components/DateField';
import { useCurrency } from '../hooks/useCurrency';
import type { PendingPayment, PaginatedResponse } from '../types';
import { usePlatform } from '../platform/hooks/usePlatform';
@@ -327,20 +328,20 @@ export default function AdminPayments() {
<label className="mb-1 block text-xs text-dark-400">
{t('admin.payments.dateFrom')}
</label>
<input
type="date"
<DateField
value={dateFrom}
onChange={(e) => setDateFrom(e.target.value)}
className="w-full rounded-lg border border-dark-700 bg-dark-800 px-3 py-2 text-sm text-dark-100 focus:border-accent-500 focus:outline-none"
max={dateTo}
onChange={setDateFrom}
className="flex w-full items-center gap-2 rounded-lg border border-dark-700 bg-dark-800 px-3 py-2 text-sm text-dark-100 transition-colors hover:border-accent-500"
/>
</div>
<div className="flex-1">
<label className="mb-1 block text-xs text-dark-400">{t('admin.payments.dateTo')}</label>
<input
type="date"
<DateField
value={dateTo}
onChange={(e) => setDateTo(e.target.value)}
className="w-full rounded-lg border border-dark-700 bg-dark-800 px-3 py-2 text-sm text-dark-100 focus:border-accent-500 focus:outline-none"
min={dateFrom}
onChange={setDateTo}
className="flex w-full items-center gap-2 rounded-lg border border-dark-700 bg-dark-800 px-3 py-2 text-sm text-dark-100 transition-colors hover:border-accent-500"
/>
</div>
<button onClick={() => refetch()} className="btn-primary px-4 py-2 text-sm">

View File

@@ -2,6 +2,7 @@ import { useState, useCallback } from 'react';
import { useNavigate, useParams } from 'react-router';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';
import { DateField } from '../components/DateField';
import { createNumberInputHandler } from '../utils/inputHelpers';
import {
promocodesApi,
@@ -447,12 +448,10 @@ export default function AdminPromocodeCreate() {
<label htmlFor="pc-valid-until" className="mb-2 block text-sm font-medium text-dark-300">
{t('admin.promocodes.form.validUntil')}
</label>
<input
id="pc-valid-until"
type="date"
<DateField
value={validUntil}
onChange={(e) => setValidUntil(e.target.value)}
className="input"
onChange={setValidUntil}
className="flex w-full items-center gap-2 rounded-xl border border-dark-700/50 bg-dark-800/50 px-4 py-3 text-sm text-dark-100 transition-colors hover:border-accent-500/50"
/>
<p className="mt-1 text-xs text-dark-500">{t('admin.promocodes.form.validUntilHint')}</p>
</div>