chore: improve tariff admin layout
This commit is contained in:
@@ -211,9 +211,24 @@
|
||||
}
|
||||
|
||||
$: catalogCurrencyKey = normalizeCurrencyKey(tariffsCatalog.default_currency || "rub");
|
||||
$: defaultCurrencyDraft = catalogCurrencyKey.toUpperCase();
|
||||
$: catalogCurrencyCode = catalogCurrencyKey.toUpperCase();
|
||||
$: defaultCurrencyDraft = catalogCurrencyCode;
|
||||
$: defaultCurrencyDraftKey = normalizeCurrencyKey(defaultCurrencyDraft || "rub");
|
||||
$: defaultCurrencyDirty = defaultCurrencyDraftKey !== catalogCurrencyKey;
|
||||
$: providerSupportSummary = (providerCurrencySupport || []).reduce(
|
||||
(summary, provider) => {
|
||||
const enabled = Boolean(provider.enabled);
|
||||
const configured = Boolean(provider.configured);
|
||||
const supportsDefault = Boolean(provider.supports_default_currency);
|
||||
summary.total += 1;
|
||||
if (enabled) summary.enabled += 1;
|
||||
if (enabled && configured) summary.configured += 1;
|
||||
if (enabled && configured && supportsDefault) summary.available += 1;
|
||||
if (enabled && configured && !supportsDefault) summary.blocked += 1;
|
||||
return summary;
|
||||
},
|
||||
{ total: 0, enabled: 0, configured: 0, available: 0, blocked: 0 }
|
||||
);
|
||||
|
||||
async function saveDefaultCurrency() {
|
||||
await tariffsStore.setDefaultCurrency(defaultCurrencyDraft);
|
||||
@@ -222,7 +237,8 @@
|
||||
function providerCurrencyLabel(provider) {
|
||||
if (provider.accepts_any_currency) return at("tariff_provider_any_currency", {}, "Любая");
|
||||
return (
|
||||
(provider.currencies || []).join(", ") || at("tariff_provider_not_declared", {}, "Не задано")
|
||||
(provider.currencies || []).map((currency) => String(currency).toUpperCase()).join(", ") ||
|
||||
at("tariff_provider_not_declared", {}, "Не задано")
|
||||
);
|
||||
}
|
||||
|
||||
@@ -231,6 +247,13 @@
|
||||
return provider.supports_default_currency ? "success" : "warning";
|
||||
}
|
||||
|
||||
function providerCurrencyStatus(provider) {
|
||||
if (!provider.enabled) return at("disabled", {}, "Отключен");
|
||||
if (!provider.configured) return at("status_not_configured", {}, "Не настроен");
|
||||
if (provider.supports_default_currency) return at("tariff_currency_supported", {}, "Доступен");
|
||||
return at("tariff_currency_unsupported", {}, "Заблокирован");
|
||||
}
|
||||
|
||||
function removeTrialSquad(uuid) {
|
||||
setCsvList(
|
||||
"TRIAL_SQUAD_UUIDS",
|
||||
@@ -654,185 +677,258 @@
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article class="admin-card">
|
||||
<header class="admin-card-head">
|
||||
<div>
|
||||
<h3>{at("tariffs_title", {}, "Каталог тарифов")}</h3>
|
||||
<small>{tariffsPath || "data/tariffs.json"}</small>
|
||||
</div>
|
||||
<div class="admin-editor-section-actions">
|
||||
<AdminButton
|
||||
size="sm"
|
||||
onclick={tariffsStore.loadTariffs}
|
||||
disabled={tariffsLoading || tariffsSaving}
|
||||
>
|
||||
<RefreshCw size={13} />
|
||||
{at("btn_refresh", {}, "Обновить")}
|
||||
</AdminButton>
|
||||
<AdminButton
|
||||
size="sm"
|
||||
variant="primary"
|
||||
onclick={tariffsStore.openCreateTariff}
|
||||
disabled={tariffsLoading || tariffsSaving}
|
||||
>
|
||||
<Plus size={13} />
|
||||
{at("btn_create_tariff", {}, "Создать тариф")}
|
||||
</AdminButton>
|
||||
</div>
|
||||
</header>
|
||||
<div class="admin-card-body">
|
||||
<div class="admin-tariff-catalog-bar">
|
||||
<label class="admin-field-label-compact">
|
||||
<span>{at("tariff_default_currency", {}, "Валюта оплаты")}</span>
|
||||
<Input
|
||||
class="input admin-currency-input"
|
||||
type="text"
|
||||
maxlength="12"
|
||||
value={defaultCurrencyDraft}
|
||||
oninput={(event) => (defaultCurrencyDraft = event.currentTarget.value.toUpperCase())}
|
||||
onkeydown={(event) => {
|
||||
if (event.key === "Enter" && defaultCurrencyDirty) saveDefaultCurrency();
|
||||
}}
|
||||
/>
|
||||
</label>
|
||||
<AdminBadge variant="muted">{catalogCurrencyKey.toUpperCase()}</AdminBadge>
|
||||
{#if defaultCurrencyDirty}
|
||||
<div class="admin-tariff-management">
|
||||
<div class="admin-tariff-overview-grid">
|
||||
<article class="admin-card admin-tariff-currency-card">
|
||||
<header class="admin-card-head admin-tariff-panel-head">
|
||||
<div>
|
||||
<h3>{at("tariffs_currency_title", {}, "Валюта каталога")}</h3>
|
||||
<small>
|
||||
{at(
|
||||
"tariffs_currency_subtitle",
|
||||
{},
|
||||
"Цены тарифов и платёжные провайдеры проверяются по этой валюте."
|
||||
)}
|
||||
</small>
|
||||
</div>
|
||||
<AdminBadge variant="muted">{catalogCurrencyCode}</AdminBadge>
|
||||
</header>
|
||||
<div class="admin-card-body admin-tariff-currency-body">
|
||||
<div class="admin-tariff-currency-current">
|
||||
<span>{at("tariffs_currency_current", {}, "Текущая валюта")}</span>
|
||||
<strong>{catalogCurrencyCode}</strong>
|
||||
</div>
|
||||
<div class="admin-tariff-catalog-bar">
|
||||
<label class="admin-field-label-compact admin-tariff-currency-field">
|
||||
<span>{at("tariff_default_currency", {}, "Валюта оплаты")}</span>
|
||||
<Input
|
||||
class="input admin-currency-input"
|
||||
type="text"
|
||||
maxlength="12"
|
||||
value={defaultCurrencyDraft}
|
||||
oninput={(event) =>
|
||||
(defaultCurrencyDraft = event.currentTarget.value.toUpperCase())}
|
||||
onkeydown={(event) => {
|
||||
if (event.key === "Enter" && defaultCurrencyDirty) saveDefaultCurrency();
|
||||
}}
|
||||
/>
|
||||
</label>
|
||||
{#if defaultCurrencyDirty}
|
||||
<AdminButton
|
||||
size="sm"
|
||||
variant="primary"
|
||||
onclick={saveDefaultCurrency}
|
||||
disabled={tariffsSaving}
|
||||
>
|
||||
<Save size={13} />
|
||||
{tariffsSaving
|
||||
? at("btn_saving", {}, "Сохранение...")
|
||||
: at("btn_save", {}, "Сохранить")}
|
||||
</AdminButton>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article class="admin-card admin-tariff-providers-card">
|
||||
<header class="admin-card-head admin-tariff-panel-head">
|
||||
<div>
|
||||
<h3>{at("tariffs_provider_title", {}, "Платёжные провайдеры")}</h3>
|
||||
<small>
|
||||
{at(
|
||||
"tariffs_provider_subtitle",
|
||||
{},
|
||||
"Здесь видно, какие провайдеры смогут принять текущую валюту каталога."
|
||||
)}
|
||||
</small>
|
||||
</div>
|
||||
<div class="admin-provider-summary">
|
||||
<AdminBadge variant="success">
|
||||
{at(
|
||||
"tariffs_provider_available_count",
|
||||
{ count: providerSupportSummary.available },
|
||||
"Доступно: {count}"
|
||||
)}
|
||||
</AdminBadge>
|
||||
<AdminBadge variant="muted">
|
||||
{at(
|
||||
"tariffs_provider_enabled_count",
|
||||
{ count: providerSupportSummary.enabled },
|
||||
"Включено: {count}"
|
||||
)}
|
||||
</AdminBadge>
|
||||
{#if providerSupportSummary.blocked}
|
||||
<AdminBadge variant="warning">
|
||||
{at(
|
||||
"tariffs_provider_blocked_count",
|
||||
{ count: providerSupportSummary.blocked },
|
||||
"Не подходят: {count}"
|
||||
)}
|
||||
</AdminBadge>
|
||||
{/if}
|
||||
</div>
|
||||
</header>
|
||||
<div class="admin-card-body">
|
||||
{#if providerCurrencySupport?.length}
|
||||
<div class="admin-provider-currency-grid">
|
||||
{#each providerCurrencySupport as provider}
|
||||
<div
|
||||
class="admin-provider-currency"
|
||||
class:is-supported={provider.supports_default_currency &&
|
||||
provider.enabled &&
|
||||
provider.configured}
|
||||
class:is-unavailable={!provider.supports_default_currency ||
|
||||
!provider.enabled ||
|
||||
!provider.configured}
|
||||
>
|
||||
<div class="admin-provider-currency-main">
|
||||
<strong>{provider.label}</strong>
|
||||
<small>{providerCurrencyLabel(provider)}</small>
|
||||
</div>
|
||||
<AdminBadge variant={providerCurrencyVariant(provider)}>
|
||||
{providerCurrencyStatus(provider)}
|
||||
</AdminBadge>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
<AdminEmptyState>
|
||||
{at("tariffs_provider_empty", {}, "Данные по провайдерам пока не загружены.")}
|
||||
</AdminEmptyState>
|
||||
{/if}
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<article class="admin-card admin-tariff-list-card">
|
||||
<header class="admin-card-head admin-tariff-list-head">
|
||||
<div>
|
||||
<h3>{at("tariffs_title", {}, "Каталог тарифов")}</h3>
|
||||
<small>
|
||||
{at("tariffs_catalog_subtitle", {}, "Периоды, цены, трафик и доступы пользователей.")}
|
||||
</small>
|
||||
<code class="admin-tariff-path">{tariffsPath || "data/tariffs.json"}</code>
|
||||
</div>
|
||||
<div class="admin-editor-section-actions">
|
||||
<AdminButton
|
||||
size="sm"
|
||||
onclick={tariffsStore.loadTariffs}
|
||||
disabled={tariffsLoading || tariffsSaving}
|
||||
>
|
||||
<RefreshCw size={13} />
|
||||
{at("btn_refresh", {}, "Обновить")}
|
||||
</AdminButton>
|
||||
<AdminButton
|
||||
size="sm"
|
||||
variant="primary"
|
||||
onclick={saveDefaultCurrency}
|
||||
disabled={tariffsSaving}
|
||||
onclick={tariffsStore.openCreateTariff}
|
||||
disabled={tariffsLoading || tariffsSaving}
|
||||
>
|
||||
<Save size={13} />
|
||||
{tariffsSaving
|
||||
? at("btn_saving", {}, "Сохранение...")
|
||||
: at("btn_save", {}, "Сохранить")}
|
||||
<Plus size={13} />
|
||||
{at("btn_create_tariff", {}, "Создать тариф")}
|
||||
</AdminButton>
|
||||
</div>
|
||||
</header>
|
||||
<div class="admin-card-body">
|
||||
{#if !tariffsCatalog.tariffs.length}
|
||||
<AdminEmptyState>
|
||||
{at(
|
||||
"tariffs_catalog_empty",
|
||||
{},
|
||||
"Каталог пуст. Добавьте первый тариф, после сохранения будет создан JSON-файл каталога."
|
||||
)}
|
||||
</AdminEmptyState>
|
||||
{:else}
|
||||
<div class="admin-tariff-grid">
|
||||
{#each tariffsCatalog.tariffs as tariff}
|
||||
<article class="admin-tariff-card" class:is-disabled={tariff.enabled === false}>
|
||||
<div class="admin-tariff-top">
|
||||
<div>
|
||||
<div class="admin-tariff-title">
|
||||
<strong>{tariffName(tariff)}</strong>
|
||||
{#if tariff.key === tariffsCatalog.default_tariff}
|
||||
<AdminBadge variant="success"
|
||||
>{at("status_default", {}, "Default")}</AdminBadge
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
<code>{tariff.key}</code>
|
||||
</div>
|
||||
{#if tariff.enabled === false}
|
||||
<AdminBadge variant="muted">{at("status_disabled", {}, "Выключен")}</AdminBadge>
|
||||
{:else}
|
||||
<AdminBadge variant="success">{at("status_active", {}, "Активен")}</AdminBadge>
|
||||
{/if}
|
||||
</div>
|
||||
<p>
|
||||
{tariff.descriptions?.ru ||
|
||||
tariff.descriptions?.en ||
|
||||
at("no_description", {}, "Без описания")}
|
||||
</p>
|
||||
<div class="admin-tariff-facts">
|
||||
<span
|
||||
>{tariff.billing_model === "traffic"
|
||||
? at("tariff_model_traffic", {}, "Трафик")
|
||||
: at("tariff_model_periods", {}, "Периоды")}</span
|
||||
>
|
||||
<span>{tariffPriceSummary(tariff)}</span>
|
||||
<span
|
||||
>{at("tariff_squads", {}, "Squads")}: {(tariff.squad_uuids || []).length}</span
|
||||
>
|
||||
<span
|
||||
>{at("tariff_premium", {}, "Premium")}: {(tariff.premium_squad_uuids || [])
|
||||
.length
|
||||
? `${tariff.premium_monthly_gb || 0} GB`
|
||||
: "—"}</span
|
||||
>
|
||||
<span
|
||||
>{at("tariff_devices", {}, "Устройства")}: {tariff.hwid_device_limit ??
|
||||
"env"}</span
|
||||
>
|
||||
</div>
|
||||
<div class="admin-tariff-actions">
|
||||
<AdminButton size="sm" onclick={() => tariffsStore.openEditTariff(tariff)}>
|
||||
{at("btn_configure", {}, "Настроить")}
|
||||
</AdminButton>
|
||||
<AdminButton
|
||||
size="sm"
|
||||
onclick={() => tariffsStore.toggleTariffEnabled(tariff)}
|
||||
disabled={tariffsSaving}
|
||||
>
|
||||
{tariff.enabled === false
|
||||
? at("btn_enable", {}, "Включить")
|
||||
: at("btn_disable", {}, "Выключить")}
|
||||
</AdminButton>
|
||||
<AdminButton
|
||||
size="sm"
|
||||
onclick={() => tariffsStore.setDefaultTariff(tariff.key)}
|
||||
disabled={tariffsSaving ||
|
||||
tariff.enabled === false ||
|
||||
tariff.key === tariffsCatalog.default_tariff}
|
||||
>
|
||||
{at("btn_set_default", {}, "По умолчанию")}
|
||||
</AdminButton>
|
||||
<AdminButton
|
||||
size="sm"
|
||||
variant="danger"
|
||||
onclick={() =>
|
||||
tariffsStore.updateState({
|
||||
tariffDeleteTarget: tariff,
|
||||
tariffDeleteOpen: true,
|
||||
})}
|
||||
disabled={tariffsSaving}
|
||||
aria-label={at("btn_delete_tariff", {}, "Удалить тариф")}
|
||||
>
|
||||
<Trash2 size={13} />
|
||||
</AdminButton>
|
||||
</div>
|
||||
</article>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{#if providerCurrencySupport?.length}
|
||||
<div class="admin-provider-currency-grid">
|
||||
{#each providerCurrencySupport as provider}
|
||||
<div
|
||||
class="admin-provider-currency"
|
||||
class:is-supported={provider.supports_default_currency && provider.enabled}
|
||||
class:is-unavailable={!provider.supports_default_currency || !provider.enabled}
|
||||
>
|
||||
<div>
|
||||
<strong>{provider.label}</strong>
|
||||
<small>{providerCurrencyLabel(provider)}</small>
|
||||
</div>
|
||||
<AdminBadge variant={providerCurrencyVariant(provider)}>
|
||||
{#if !provider.enabled}
|
||||
{at("disabled", {}, "Отключен")}
|
||||
{:else if !provider.configured}
|
||||
{at("status_not_configured", {}, "Не настроен")}
|
||||
{:else if provider.supports_default_currency}
|
||||
{at("tariff_currency_supported", {}, "Доступен")}
|
||||
{:else}
|
||||
{at("tariff_currency_unsupported", {}, "Заблокирован")}
|
||||
{/if}
|
||||
</AdminBadge>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
{#if !tariffsCatalog.tariffs.length}
|
||||
<AdminEmptyState>
|
||||
{at(
|
||||
"tariffs_catalog_empty",
|
||||
{},
|
||||
"Каталог пуст. Добавьте первый тариф, после сохранения будет создан JSON-файл каталога."
|
||||
)}
|
||||
</AdminEmptyState>
|
||||
{:else}
|
||||
<div class="admin-tariff-grid">
|
||||
{#each tariffsCatalog.tariffs as tariff}
|
||||
<article class="admin-tariff-card" class:is-disabled={tariff.enabled === false}>
|
||||
<div class="admin-tariff-top">
|
||||
<div>
|
||||
<div class="admin-tariff-title">
|
||||
<strong>{tariffName(tariff)}</strong>
|
||||
{#if tariff.key === tariffsCatalog.default_tariff}
|
||||
<AdminBadge variant="success"
|
||||
>{at("status_default", {}, "Default")}</AdminBadge
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
<code>{tariff.key}</code>
|
||||
</div>
|
||||
{#if tariff.enabled === false}
|
||||
<AdminBadge variant="muted">{at("status_disabled", {}, "Выключен")}</AdminBadge>
|
||||
{:else}
|
||||
<AdminBadge variant="success">{at("status_active", {}, "Активен")}</AdminBadge>
|
||||
{/if}
|
||||
</div>
|
||||
<p>
|
||||
{tariff.descriptions?.ru ||
|
||||
tariff.descriptions?.en ||
|
||||
at("no_description", {}, "Без описания")}
|
||||
</p>
|
||||
<div class="admin-tariff-facts">
|
||||
<span
|
||||
>{tariff.billing_model === "traffic"
|
||||
? at("tariff_model_traffic", {}, "Трафик")
|
||||
: at("tariff_model_periods", {}, "Периоды")}</span
|
||||
>
|
||||
<span>{tariffPriceSummary(tariff)}</span>
|
||||
<span>{at("tariff_squads", {}, "Squads")}: {(tariff.squad_uuids || []).length}</span
|
||||
>
|
||||
<span
|
||||
>{at("tariff_premium", {}, "Premium")}: {(tariff.premium_squad_uuids || []).length
|
||||
? `${tariff.premium_monthly_gb || 0} GB`
|
||||
: "—"}</span
|
||||
>
|
||||
<span
|
||||
>{at("tariff_devices", {}, "Устройства")}: {tariff.hwid_device_limit ??
|
||||
"env"}</span
|
||||
>
|
||||
</div>
|
||||
<div class="admin-tariff-actions">
|
||||
<AdminButton size="sm" onclick={() => tariffsStore.openEditTariff(tariff)}>
|
||||
{at("btn_configure", {}, "Настроить")}
|
||||
</AdminButton>
|
||||
<AdminButton
|
||||
size="sm"
|
||||
onclick={() => tariffsStore.toggleTariffEnabled(tariff)}
|
||||
disabled={tariffsSaving}
|
||||
>
|
||||
{tariff.enabled === false
|
||||
? at("btn_enable", {}, "Включить")
|
||||
: at("btn_disable", {}, "Выключить")}
|
||||
</AdminButton>
|
||||
<AdminButton
|
||||
size="sm"
|
||||
onclick={() => tariffsStore.setDefaultTariff(tariff.key)}
|
||||
disabled={tariffsSaving ||
|
||||
tariff.enabled === false ||
|
||||
tariff.key === tariffsCatalog.default_tariff}
|
||||
>
|
||||
{at("btn_set_default", {}, "По умолчанию")}
|
||||
</AdminButton>
|
||||
<AdminButton
|
||||
size="sm"
|
||||
variant="danger"
|
||||
onclick={() =>
|
||||
tariffsStore.updateState({
|
||||
tariffDeleteTarget: tariff,
|
||||
tariffDeleteOpen: true,
|
||||
})}
|
||||
disabled={tariffsSaving}
|
||||
aria-label={at("btn_delete_tariff", {}, "Удалить тариф")}
|
||||
>
|
||||
<Trash2 size={13} />
|
||||
</AdminButton>
|
||||
</div>
|
||||
</article>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</article>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<Accordion.Root
|
||||
type="multiple"
|
||||
|
||||
+205
-69
@@ -3125,6 +3125,169 @@
|
||||
}
|
||||
}
|
||||
|
||||
.admin-tariff-management {
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.admin-tariff-overview-grid {
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.admin-tariff-overview-grid > .admin-card {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
@media (min-width: 980px) {
|
||||
.admin-tariff-overview-grid {
|
||||
grid-template-columns: minmax(260px, 0.82fr) minmax(0, 1.6fr);
|
||||
align-items: stretch;
|
||||
}
|
||||
}
|
||||
|
||||
.admin-tariff-panel-head > div,
|
||||
.admin-tariff-list-head > div {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.admin-tariff-panel-head small,
|
||||
.admin-tariff-list-head small {
|
||||
max-width: 72ch;
|
||||
}
|
||||
|
||||
.admin-tariff-path {
|
||||
display: block;
|
||||
width: fit-content;
|
||||
max-width: 100%;
|
||||
margin-top: 6px;
|
||||
overflow: hidden;
|
||||
color: var(--admin-dim);
|
||||
font-family: var(--font-mono);
|
||||
font-size: 11px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.admin-tariff-currency-body {
|
||||
display: grid;
|
||||
align-content: start;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.admin-tariff-currency-current {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
min-width: 0;
|
||||
padding: 12px;
|
||||
border: 1px solid var(--admin-border);
|
||||
border-radius: 8px;
|
||||
background: var(--admin-surface-2);
|
||||
}
|
||||
|
||||
.admin-tariff-currency-current span {
|
||||
color: var(--admin-muted);
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.admin-tariff-currency-current strong {
|
||||
color: var(--admin-text);
|
||||
font-family: var(--font-mono);
|
||||
font-size: 18px;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
.admin-tariff-catalog-bar {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
align-items: end;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.admin-tariff-currency-field {
|
||||
display: grid;
|
||||
min-width: 0;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.admin-tariff-currency-field > span {
|
||||
color: var(--admin-text);
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.admin-currency-input {
|
||||
width: 100%;
|
||||
max-width: 160px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.admin-provider-summary {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.admin-provider-currency-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.admin-provider-currency {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
min-width: 0;
|
||||
padding: 10px 12px;
|
||||
border: 1px solid var(--admin-border);
|
||||
border-radius: 8px;
|
||||
background: var(--admin-surface-2);
|
||||
}
|
||||
|
||||
.admin-provider-currency.is-supported {
|
||||
border-color: color-mix(in srgb, var(--success-border) 70%, var(--admin-border));
|
||||
}
|
||||
|
||||
.admin-provider-currency.is-unavailable {
|
||||
opacity: 0.74;
|
||||
}
|
||||
|
||||
.admin-provider-currency-main {
|
||||
display: grid;
|
||||
gap: 3px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.admin-provider-currency-main strong,
|
||||
.admin-provider-currency-main small {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.admin-provider-currency-main strong {
|
||||
color: var(--admin-text);
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.admin-provider-currency-main small {
|
||||
color: var(--admin-muted);
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.admin-provider-currency > .admin-badge {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.admin-tariff-grid {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
@@ -3145,6 +3308,7 @@
|
||||
|
||||
.admin-tariff-card {
|
||||
display: grid;
|
||||
align-content: start;
|
||||
gap: 12px;
|
||||
min-width: 0;
|
||||
border: 1px solid var(--admin-border);
|
||||
@@ -3168,6 +3332,11 @@
|
||||
|
||||
.admin-tariff-top {
|
||||
justify-content: space-between;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.admin-tariff-top > div {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.admin-tariff-title {
|
||||
@@ -3204,79 +3373,13 @@
|
||||
|
||||
.admin-tariff-facts span {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.admin-tariff-actions {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.admin-tariff-catalog-bar {
|
||||
display: flex;
|
||||
align-items: end;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.admin-currency-input {
|
||||
width: 120px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.admin-provider-currency-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||
gap: 8px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
.admin-provider-currency {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
min-width: 0;
|
||||
padding: 9px 10px;
|
||||
border: 1px solid var(--admin-border);
|
||||
border-radius: 8px;
|
||||
background: var(--admin-surface-2);
|
||||
}
|
||||
|
||||
.admin-provider-currency.is-supported {
|
||||
border-color: color-mix(in srgb, var(--success-border) 70%, var(--admin-border));
|
||||
}
|
||||
|
||||
.admin-provider-currency.is-unavailable {
|
||||
opacity: 0.72;
|
||||
}
|
||||
|
||||
.admin-provider-currency div {
|
||||
display: grid;
|
||||
gap: 2px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.admin-provider-currency strong,
|
||||
.admin-provider-currency small {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.admin-provider-currency strong {
|
||||
color: var(--admin-text);
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.admin-provider-currency small {
|
||||
color: var(--admin-muted);
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.admin-tariff-settings-card {
|
||||
margin-top: 14px;
|
||||
}
|
||||
@@ -3614,6 +3717,33 @@
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
.admin-tariff-panel-head,
|
||||
.admin-tariff-list-head {
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.admin-provider-summary {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.admin-tariff-catalog-bar {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.admin-currency-input {
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.admin-provider-currency {
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.admin-provider-currency-main strong,
|
||||
.admin-provider-currency-main small {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.admin-tariff-card {
|
||||
padding: 12px;
|
||||
}
|
||||
@@ -3626,12 +3756,18 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
.admin-tariff-actions {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.admin-tariff-actions .admin-btn {
|
||||
flex: 1 1 calc(50% - 4px);
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.admin-tariff-actions .admin-btn[aria-label] {
|
||||
flex: 0 0 auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* (legacy three-row user-row layout removed in favour of the compact
|
||||
|
||||
Reference in New Issue
Block a user