fix(web): флаги стран, FormDatePicker и плоские таблицы без двойной рамки

SVG-флаги через flagcdn и resolveCountryCode; поле «Оплачено до» — компактный Popover+Calendar на русском; DataGridCard без вложенной обводки.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Denozordec
2026-06-27 01:59:50 +07:00
co-authored by Cursor
parent 4c7dfc45d6
commit f681f72e8c
8 changed files with 329 additions and 102 deletions
+65
View File
@@ -0,0 +1,65 @@
import type { DateSelectorI18nConfig } from '@/components/reui/date-selector'
/** Русская локализация ReUI DateSelector (фильтры, не формы). */
export const RU_DATE_SELECTOR_I18N: DateSelectorI18nConfig = {
selectDate: 'Выберите дату',
apply: 'Применить',
cancel: 'Отмена',
clear: 'Очистить',
today: 'Сегодня',
filterTypes: {
is: 'равно',
before: 'до',
after: 'после',
between: 'между',
},
periodTypes: {
day: 'День',
month: 'Месяц',
quarter: 'Квартал',
halfYear: 'Полгода',
year: 'Год',
},
months: [
'Январь',
'Февраль',
'Март',
'Апрель',
'Май',
'Июнь',
'Июль',
'Август',
'Сентябрь',
'Октябрь',
'Ноябрь',
'Декабрь',
],
monthsShort: [
'Янв',
'Фев',
'Мар',
'Апр',
'Май',
'Июн',
'Июл',
'Авг',
'Сен',
'Окт',
'Ноя',
'Дек',
],
quarters: ['1 кв.', '2 кв.', '3 кв.', '4 кв.'],
halfYears: ['1 пол.', '2 пол.'],
weekdays: [
'воскресенье',
'понедельник',
'вторник',
'среда',
'четверг',
'пятница',
'суббота',
],
weekdaysShort: ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'],
placeholder: 'Выберите дату…',
rangePlaceholder: 'Выберите период…',
}
+29 -3
View File
@@ -1,4 +1,9 @@
import type { Settings, RatesData, Vps, Provider } from '@/types/entities'
import { COUNTRIES, COUNTRY_BY_CODE, COUNTRY_BY_NAME_RU } from '@cfdm/shared/geo'
const COUNTRY_BY_NAME_EN: Record<string, { code: string }> = Object.fromEntries(
COUNTRIES.map((c) => [c.nameEn.toLowerCase(), c]),
)
export function uid(): string {
if (typeof crypto !== 'undefined' && crypto.randomUUID) return crypto.randomUUID()
@@ -30,11 +35,32 @@ const COUNTRY_CODE_BY_NAME: Record<string, string> = {
canada: 'CA', brazil: 'BR', turkey: 'TR', georgia: 'GE', kazakhstan: 'KZ',
}
/** ISO 3166-1 alpha-2 по русскому/английскому названию или коду. */
export function resolveCountryCode(country?: string): string | undefined {
if (!country) return undefined
const normalized = country.trim()
const lower = normalized.toLowerCase()
if (/^[a-z]{2}$/i.test(normalized)) {
const upper = normalized.toUpperCase()
if (COUNTRY_BY_CODE[upper]) return upper
}
return (
COUNTRY_BY_NAME_RU[lower]?.code
?? COUNTRY_BY_NAME_EN[lower]?.code
?? COUNTRY_CODE_BY_NAME[lower]
)
}
/** URL SVG-флага (flagcdn). */
export function getCountryFlagUrl(code?: string): string | undefined {
if (!code || code.length !== 2) return undefined
return `https://flagcdn.com/${code.toLowerCase()}.svg`
}
export function getCountryFlagEmoji(country?: string): string {
if (!country) return '🌐'
const code = COUNTRY_CODE_BY_NAME[country.trim().toLowerCase()]
const code = resolveCountryCode(country)
if (!code) return '🌐'
return code.toUpperCase().split('').map((c) => String.fromCodePoint(127397 + c.charCodeAt(0))).join('')
return getCountryFlagEmojiByCode(code)
}
/** Флаг по ISO 3166-1 alpha-2 коду страны. */