mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-30 10:27:49 +00:00
feat(ui): заменить все нативные date-инпуты на DateField
Тёмный DateField теперь везде, где был браузерный <input type="date">: фильтр периода в Трафике, диапазон дат в Платежах и Аудит-логе, срок действия промокода. Единый вид во всём кабинете. (datetime-local не трогал — там нужно ещё и время.)
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { CalendarIcon, XIcon } from '../TrafficIcons';
|
import { CalendarIcon, XIcon } from '../TrafficIcons';
|
||||||
|
import { DateField } from '../../../DateField';
|
||||||
|
|
||||||
// ──────────────────────────────────────────────────────────────────
|
// ──────────────────────────────────────────────────────────────────
|
||||||
// PeriodSelector — switches between fixed period tabs (1/3/7/14/30
|
// 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">
|
<div className="flex items-center gap-2">
|
||||||
<CalendarIcon className="h-4 w-4" />
|
<CalendarIcon className="h-4 w-4" />
|
||||||
<span className="text-xs text-dark-400">{t('admin.trafficUsage.dateFrom')}</span>
|
<span className="text-xs text-dark-400">{t('admin.trafficUsage.dateFrom')}</span>
|
||||||
<input
|
<DateField
|
||||||
type="date"
|
|
||||||
value={customStart}
|
value={customStart}
|
||||||
min={minDate}
|
min={minDate}
|
||||||
max={customEnd || today}
|
max={customEnd || today}
|
||||||
onChange={(e) => onCustomStartChange(e.target.value)}
|
onChange={onCustomStartChange}
|
||||||
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"
|
|
||||||
/>
|
/>
|
||||||
<span className="text-xs text-dark-400">{t('admin.trafficUsage.dateTo')}</span>
|
<span className="text-xs text-dark-400">{t('admin.trafficUsage.dateTo')}</span>
|
||||||
<input
|
<DateField
|
||||||
type="date"
|
|
||||||
value={customEnd}
|
value={customEnd}
|
||||||
min={customStart || minDate}
|
min={customStart || minDate}
|
||||||
max={today}
|
max={today}
|
||||||
onChange={(e) => onCustomEndChange(e.target.value)}
|
onChange={onCustomEndChange}
|
||||||
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"
|
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
onClick={onToggleDateMode}
|
onClick={onToggleDateMode}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import type { TFunction } from 'i18next';
|
import type { TFunction } from 'i18next';
|
||||||
import { rbacApi, AuditLogEntry, AuditLogFilters } from '@/api/rbac';
|
import { rbacApi, AuditLogEntry, AuditLogFilters } from '@/api/rbac';
|
||||||
import { PermissionGate } from '@/components/auth/PermissionGate';
|
import { PermissionGate } from '@/components/auth/PermissionGate';
|
||||||
|
import { DateField } from '@/components/DateField';
|
||||||
import { usePlatform } from '@/platform/hooks/usePlatform';
|
import { usePlatform } from '@/platform/hooks/usePlatform';
|
||||||
import {
|
import {
|
||||||
BackIcon,
|
BackIcon,
|
||||||
@@ -704,12 +705,11 @@ export default function AdminAuditLog() {
|
|||||||
>
|
>
|
||||||
{t('admin.auditLog.filters.dateFrom')}
|
{t('admin.auditLog.filters.dateFrom')}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<DateField
|
||||||
id="filter-date-from"
|
|
||||||
type="date"
|
|
||||||
value={filters.dateFrom}
|
value={filters.dateFrom}
|
||||||
onChange={(e) => setFilters((prev) => ({ ...prev, dateFrom: e.target.value }))}
|
max={filters.dateTo}
|
||||||
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"
|
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>
|
</div>
|
||||||
|
|
||||||
@@ -721,12 +721,11 @@ export default function AdminAuditLog() {
|
|||||||
>
|
>
|
||||||
{t('admin.auditLog.filters.dateTo')}
|
{t('admin.auditLog.filters.dateTo')}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<DateField
|
||||||
id="filter-date-to"
|
|
||||||
type="date"
|
|
||||||
value={filters.dateTo}
|
value={filters.dateTo}
|
||||||
onChange={(e) => setFilters((prev) => ({ ...prev, dateTo: e.target.value }))}
|
min={filters.dateFrom}
|
||||||
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"
|
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>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { useNavigate } from 'react-router';
|
|||||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { adminPaymentsApi, type SearchStats } from '../api/adminPayments';
|
import { adminPaymentsApi, type SearchStats } from '../api/adminPayments';
|
||||||
|
import { DateField } from '../components/DateField';
|
||||||
import { useCurrency } from '../hooks/useCurrency';
|
import { useCurrency } from '../hooks/useCurrency';
|
||||||
import type { PendingPayment, PaginatedResponse } from '../types';
|
import type { PendingPayment, PaginatedResponse } from '../types';
|
||||||
import { usePlatform } from '../platform/hooks/usePlatform';
|
import { usePlatform } from '../platform/hooks/usePlatform';
|
||||||
@@ -327,20 +328,20 @@ export default function AdminPayments() {
|
|||||||
<label className="mb-1 block text-xs text-dark-400">
|
<label className="mb-1 block text-xs text-dark-400">
|
||||||
{t('admin.payments.dateFrom')}
|
{t('admin.payments.dateFrom')}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<DateField
|
||||||
type="date"
|
|
||||||
value={dateFrom}
|
value={dateFrom}
|
||||||
onChange={(e) => setDateFrom(e.target.value)}
|
max={dateTo}
|
||||||
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"
|
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>
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<label className="mb-1 block text-xs text-dark-400">{t('admin.payments.dateTo')}</label>
|
<label className="mb-1 block text-xs text-dark-400">{t('admin.payments.dateTo')}</label>
|
||||||
<input
|
<DateField
|
||||||
type="date"
|
|
||||||
value={dateTo}
|
value={dateTo}
|
||||||
onChange={(e) => setDateTo(e.target.value)}
|
min={dateFrom}
|
||||||
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"
|
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>
|
</div>
|
||||||
<button onClick={() => refetch()} className="btn-primary px-4 py-2 text-sm">
|
<button onClick={() => refetch()} className="btn-primary px-4 py-2 text-sm">
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { useState, useCallback } from 'react';
|
|||||||
import { useNavigate, useParams } from 'react-router';
|
import { useNavigate, useParams } from 'react-router';
|
||||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { DateField } from '../components/DateField';
|
||||||
import { createNumberInputHandler } from '../utils/inputHelpers';
|
import { createNumberInputHandler } from '../utils/inputHelpers';
|
||||||
import {
|
import {
|
||||||
promocodesApi,
|
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">
|
<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
|
<DateField
|
||||||
id="pc-valid-until"
|
|
||||||
type="date"
|
|
||||||
value={validUntil}
|
value={validUntil}
|
||||||
onChange={(e) => setValidUntil(e.target.value)}
|
onChange={setValidUntil}
|
||||||
className="input"
|
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>
|
<p className="mt-1 text-xs text-dark-500">{t('admin.promocodes.form.validUntilHint')}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user