feat: unify tariff package price rows
This commit is contained in:
@@ -32,16 +32,6 @@
|
|||||||
}));
|
}));
|
||||||
$: defaultCurrencyKey = normalizeCurrencyKey(tariffsCatalog?.default_currency || "rub");
|
$: defaultCurrencyKey = normalizeCurrencyKey(tariffsCatalog?.default_currency || "rub");
|
||||||
$: defaultCurrencyCode = defaultCurrencyKey.toUpperCase();
|
$: defaultCurrencyCode = defaultCurrencyKey.toUpperCase();
|
||||||
$: currencyPackageLabel = at(
|
|
||||||
"tariff_btn_package_currency",
|
|
||||||
{ currency: defaultCurrencyCode },
|
|
||||||
`Пакет ${defaultCurrencyCode}`
|
|
||||||
);
|
|
||||||
$: currencyPaymentLabel = at(
|
|
||||||
"payment_default_currency",
|
|
||||||
{ currency: defaultCurrencyCode },
|
|
||||||
`Оплата ${defaultCurrencyCode}`
|
|
||||||
);
|
|
||||||
$: currencyPriceColumnLabel = at(
|
$: currencyPriceColumnLabel = at(
|
||||||
"tariff_col_price_currency",
|
"tariff_col_price_currency",
|
||||||
{ currency: defaultCurrencyCode },
|
{ currency: defaultCurrencyCode },
|
||||||
@@ -413,103 +403,71 @@
|
|||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="admin-editor-section-actions">
|
<div class="admin-editor-section-actions">
|
||||||
<AdminButton
|
|
||||||
size="sm"
|
|
||||||
onclick={() => tariffsStore.addDraftRow("premiumTopupRubRows", { gb: 10, price: "" })}
|
|
||||||
><Plus size={12} /> {currencyPackageLabel}</AdminButton
|
|
||||||
>
|
|
||||||
<AdminButton
|
<AdminButton
|
||||||
size="sm"
|
size="sm"
|
||||||
onclick={() =>
|
onclick={() =>
|
||||||
tariffsStore.addDraftRow("premiumTopupStarsRows", { gb: 10, price: "" })}
|
tariffsStore.addDraftRow("premiumTopupRows", { gb: 10, price: "", stars: "" })}
|
||||||
><Plus size={12} /> {at("tariff_btn_package_stars", {}, "Пакет ⭐")}</AdminButton
|
><Plus size={12} /> {at("tariff_btn_package", {}, "Пакет")}</AdminButton
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<div class="admin-package-columns">
|
{#if tariffDraft.premiumTopupRows.length}
|
||||||
<div class="admin-row-editor">
|
<div class="admin-row-editor">
|
||||||
<span class="admin-row-editor-caption">{currencyPaymentLabel}</span>
|
<div class="admin-row-editor-line admin-row-editor-drag admin-row-editor-header">
|
||||||
{#if tariffDraft.premiumTopupRubRows.length}
|
<span></span>
|
||||||
<div class="admin-row-editor-line admin-row-editor-header">
|
<span>{at("tariff_col_volume_gb", {}, "Объём, GB")}</span>
|
||||||
<span>{at("tariff_col_volume_gb", {}, "Объём, GB")}</span>
|
<span>{currencyPriceColumnLabel}</span>
|
||||||
<span>{currencyPriceColumnLabel}</span>
|
<span>{at("tariff_col_price_stars_full", {}, "Цена, ⭐ Stars")}</span>
|
||||||
<span></span>
|
<span></span>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
<Sortable
|
||||||
{#each tariffDraft.premiumTopupRubRows as row, index}
|
items={tariffDraft.premiumTopupRows}
|
||||||
<div class="admin-row-editor-line">
|
class="admin-row-editor-line admin-row-editor-drag"
|
||||||
<Input
|
handleLabel={at("tariff_package_reorder", {}, "Перетащите, чтобы изменить порядок")}
|
||||||
class="input"
|
onReorder={(from, to) => tariffsStore.moveDraftRow("premiumTopupRows", from, to)}
|
||||||
type="number"
|
let:item={row}
|
||||||
min="0.1"
|
let:index
|
||||||
step="0.1"
|
|
||||||
placeholder="10"
|
|
||||||
bind:value={row.gb}
|
|
||||||
aria-label={at("tariff_col_volume_gb", {}, "Объём premium-пакета в GB")}
|
|
||||||
/>
|
|
||||||
<Input
|
|
||||||
class="input"
|
|
||||||
type="number"
|
|
||||||
min="0"
|
|
||||||
step="0.01"
|
|
||||||
placeholder="199"
|
|
||||||
bind:value={row.price}
|
|
||||||
aria-label={currencyPriceAriaLabel}
|
|
||||||
/>
|
|
||||||
<AdminButton
|
|
||||||
size="sm"
|
|
||||||
variant="danger"
|
|
||||||
onclick={() => tariffsStore.removeDraftRow("premiumTopupRubRows", index)}
|
|
||||||
aria-label={at("btn_delete", {}, "Удалить")}><Trash2 size={13} /></AdminButton
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
<div class="admin-row-editor">
|
|
||||||
<span class="admin-row-editor-caption"
|
|
||||||
>{at("payment_stars", {}, "Оплата Telegram Stars")}</span
|
|
||||||
>
|
>
|
||||||
{#if tariffDraft.premiumTopupStarsRows.length}
|
<Input
|
||||||
<div class="admin-row-editor-line admin-row-editor-header">
|
class="input"
|
||||||
<span>{at("tariff_col_volume_gb", {}, "Объём, GB")}</span>
|
type="number"
|
||||||
<span>{at("tariff_col_price_stars", {}, "Цена, ⭐")}</span>
|
min="0.1"
|
||||||
<span></span>
|
step="0.1"
|
||||||
</div>
|
placeholder="10"
|
||||||
{/if}
|
bind:value={row.gb}
|
||||||
{#each tariffDraft.premiumTopupStarsRows as row, index}
|
aria-label={at("tariff_col_volume_gb", {}, "Объём premium-пакета в GB")}
|
||||||
<div class="admin-row-editor-line">
|
/>
|
||||||
<Input
|
<Input
|
||||||
class="input"
|
class="input"
|
||||||
type="number"
|
type="number"
|
||||||
min="0.1"
|
min="0"
|
||||||
step="0.1"
|
step="0.01"
|
||||||
placeholder="10"
|
placeholder="199"
|
||||||
bind:value={row.gb}
|
bind:value={row.price}
|
||||||
aria-label={at("tariff_col_volume_gb", {}, "Объём premium-пакета в GB")}
|
aria-label={currencyPriceAriaLabel}
|
||||||
/>
|
/>
|
||||||
<Input
|
<Input
|
||||||
class="input"
|
class="input"
|
||||||
type="number"
|
type="number"
|
||||||
min="0"
|
min="0"
|
||||||
step="1"
|
step="1"
|
||||||
placeholder="100"
|
placeholder="100"
|
||||||
bind:value={row.price}
|
bind:value={row.stars}
|
||||||
aria-label={at(
|
aria-label={at(
|
||||||
"tariff_label_price_stars",
|
"tariff_label_price_stars",
|
||||||
{},
|
{},
|
||||||
"Цена premium-пакета в Telegram Stars"
|
"Цена premium-пакета в Telegram Stars"
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<AdminButton
|
<AdminButton
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="danger"
|
variant="danger"
|
||||||
onclick={() => tariffsStore.removeDraftRow("premiumTopupStarsRows", index)}
|
onclick={() => tariffsStore.removeDraftRow("premiumTopupRows", index)}
|
||||||
aria-label={at("btn_delete", {}, "Удалить")}><Trash2 size={13} /></AdminButton
|
aria-label={at("btn_delete", {}, "Удалить")}><Trash2 size={13} /></AdminButton
|
||||||
>
|
>
|
||||||
</div>
|
</Sortable>
|
||||||
{/each}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{/if}
|
||||||
</section>
|
</section>
|
||||||
</Tabs.Content>
|
</Tabs.Content>
|
||||||
|
|
||||||
@@ -641,32 +599,26 @@
|
|||||||
<div class="admin-editor-section-actions">
|
<div class="admin-editor-section-actions">
|
||||||
<AdminButton
|
<AdminButton
|
||||||
size="sm"
|
size="sm"
|
||||||
onclick={() => tariffsStore.addDraftRow("trafficRubRows", { gb: 10, price: "" })}
|
onclick={() =>
|
||||||
><Plus size={12} /> {currencyPackageLabel}</AdminButton
|
tariffsStore.addDraftRow("trafficRows", { gb: 10, price: "", stars: "" })}
|
||||||
>
|
><Plus size={12} /> {at("tariff_btn_package", {}, "Пакет")}</AdminButton
|
||||||
<AdminButton
|
|
||||||
size="sm"
|
|
||||||
onclick={() => tariffsStore.addDraftRow("trafficStarsRows", { gb: 10, price: "" })}
|
|
||||||
><Plus size={12} /> {at("tariff_btn_package_stars", {}, "Пакет ⭐")}</AdminButton
|
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<div class="admin-package-columns">
|
{#if tariffDraft.trafficRows.length}
|
||||||
<div class="admin-row-editor">
|
<div class="admin-row-editor">
|
||||||
<span class="admin-row-editor-caption">{currencyPaymentLabel}</span>
|
<div class="admin-row-editor-line admin-row-editor-drag admin-row-editor-header">
|
||||||
{#if tariffDraft.trafficRubRows.length}
|
<span></span>
|
||||||
<div class="admin-row-editor-line admin-row-editor-drag admin-row-editor-header">
|
<span>{at("tariff_col_volume_gb", {}, "Объём, GB")}</span>
|
||||||
<span></span>
|
<span>{currencyPriceColumnLabel}</span>
|
||||||
<span>{at("tariff_col_volume_gb", {}, "Объём, GB")}</span>
|
<span>{at("tariff_col_price_stars_full", {}, "Цена, ⭐ Stars")}</span>
|
||||||
<span>{currencyPriceColumnLabel}</span>
|
<span></span>
|
||||||
<span></span>
|
</div>
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
<Sortable
|
<Sortable
|
||||||
items={tariffDraft.trafficRubRows}
|
items={tariffDraft.trafficRows}
|
||||||
class="admin-row-editor-line admin-row-editor-drag"
|
class="admin-row-editor-line admin-row-editor-drag"
|
||||||
handleLabel={at("tariff_package_reorder", {}, "Перетащите, чтобы изменить порядок")}
|
handleLabel={at("tariff_package_reorder", {}, "Перетащите, чтобы изменить порядок")}
|
||||||
onReorder={(from, to) => tariffsStore.moveDraftRow("trafficRubRows", from, to)}
|
onReorder={(from, to) => tariffsStore.moveDraftRow("trafficRows", from, to)}
|
||||||
let:item={row}
|
let:item={row}
|
||||||
let:index
|
let:index
|
||||||
>
|
>
|
||||||
@@ -688,61 +640,24 @@
|
|||||||
bind:value={row.price}
|
bind:value={row.price}
|
||||||
aria-label={currencyPriceAriaLabel}
|
aria-label={currencyPriceAriaLabel}
|
||||||
/>
|
/>
|
||||||
<AdminButton
|
|
||||||
size="sm"
|
|
||||||
variant="danger"
|
|
||||||
onclick={() => tariffsStore.removeDraftRow("trafficRubRows", index)}
|
|
||||||
aria-label={at("btn_delete", {}, "Удалить")}><Trash2 size={13} /></AdminButton
|
|
||||||
>
|
|
||||||
</Sortable>
|
|
||||||
</div>
|
|
||||||
<div class="admin-row-editor">
|
|
||||||
<span class="admin-row-editor-caption"
|
|
||||||
>{at("payment_stars", {}, "Оплата Telegram Stars")}</span
|
|
||||||
>
|
|
||||||
{#if tariffDraft.trafficStarsRows.length}
|
|
||||||
<div class="admin-row-editor-line admin-row-editor-drag admin-row-editor-header">
|
|
||||||
<span></span>
|
|
||||||
<span>{at("tariff_col_volume_gb", {}, "Объём, GB")}</span>
|
|
||||||
<span>{at("tariff_col_price_stars", {}, "Цена, ⭐")}</span>
|
|
||||||
<span></span>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
<Sortable
|
|
||||||
items={tariffDraft.trafficStarsRows}
|
|
||||||
class="admin-row-editor-line admin-row-editor-drag"
|
|
||||||
handleLabel={at("tariff_package_reorder", {}, "Перетащите, чтобы изменить порядок")}
|
|
||||||
onReorder={(from, to) => tariffsStore.moveDraftRow("trafficStarsRows", from, to)}
|
|
||||||
let:item={row}
|
|
||||||
let:index
|
|
||||||
>
|
|
||||||
<Input
|
|
||||||
class="input"
|
|
||||||
type="number"
|
|
||||||
min="0.1"
|
|
||||||
step="0.1"
|
|
||||||
placeholder="50"
|
|
||||||
bind:value={row.gb}
|
|
||||||
aria-label={at("tariff_col_volume_gb", {}, "Объём пакета в GB")}
|
|
||||||
/>
|
|
||||||
<Input
|
<Input
|
||||||
class="input"
|
class="input"
|
||||||
type="number"
|
type="number"
|
||||||
min="0"
|
min="0"
|
||||||
step="1"
|
step="1"
|
||||||
placeholder="150"
|
placeholder="150"
|
||||||
bind:value={row.price}
|
bind:value={row.stars}
|
||||||
aria-label={at("tariff_label_price_stars", {}, "Цена пакета в Telegram Stars")}
|
aria-label={at("tariff_label_price_stars", {}, "Цена пакета в Telegram Stars")}
|
||||||
/>
|
/>
|
||||||
<AdminButton
|
<AdminButton
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="danger"
|
variant="danger"
|
||||||
onclick={() => tariffsStore.removeDraftRow("trafficStarsRows", index)}
|
onclick={() => tariffsStore.removeDraftRow("trafficRows", index)}
|
||||||
aria-label={at("btn_delete", {}, "Удалить")}><Trash2 size={13} /></AdminButton
|
aria-label={at("btn_delete", {}, "Удалить")}><Trash2 size={13} /></AdminButton
|
||||||
>
|
>
|
||||||
</Sortable>
|
</Sortable>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{/if}
|
||||||
</section>
|
</section>
|
||||||
{/if}
|
{/if}
|
||||||
</Tabs.Content>
|
</Tabs.Content>
|
||||||
@@ -766,96 +681,65 @@
|
|||||||
<div class="admin-editor-section-actions">
|
<div class="admin-editor-section-actions">
|
||||||
<AdminButton
|
<AdminButton
|
||||||
size="sm"
|
size="sm"
|
||||||
onclick={() => tariffsStore.addDraftRow("topupRubRows", { gb: 10, price: "" })}
|
onclick={() =>
|
||||||
><Plus size={12} /> {currencyPackageLabel}</AdminButton
|
tariffsStore.addDraftRow("topupRows", { gb: 10, price: "", stars: "" })}
|
||||||
>
|
><Plus size={12} /> {at("tariff_btn_package", {}, "Пакет")}</AdminButton
|
||||||
<AdminButton
|
|
||||||
size="sm"
|
|
||||||
onclick={() => tariffsStore.addDraftRow("topupStarsRows", { gb: 10, price: "" })}
|
|
||||||
><Plus size={12} /> {at("tariff_btn_package_stars", {}, "Пакет ⭐")}</AdminButton
|
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<div class="admin-package-columns">
|
{#if tariffDraft.topupRows.length}
|
||||||
<div class="admin-row-editor">
|
<div class="admin-row-editor">
|
||||||
<span class="admin-row-editor-caption">{currencyPaymentLabel}</span>
|
<div class="admin-row-editor-line admin-row-editor-drag admin-row-editor-header">
|
||||||
{#if tariffDraft.topupRubRows.length}
|
<span></span>
|
||||||
<div class="admin-row-editor-line admin-row-editor-header">
|
<span>{at("tariff_col_volume_gb", {}, "Объём, GB")}</span>
|
||||||
<span>{at("tariff_col_volume_gb", {}, "Объём, GB")}</span>
|
<span>{currencyPriceColumnLabel}</span>
|
||||||
<span>{currencyPriceColumnLabel}</span>
|
<span>{at("tariff_col_price_stars_full", {}, "Цена, ⭐ Stars")}</span>
|
||||||
<span></span>
|
<span></span>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
<Sortable
|
||||||
{#each tariffDraft.topupRubRows as row, index}
|
items={tariffDraft.topupRows}
|
||||||
<div class="admin-row-editor-line">
|
class="admin-row-editor-line admin-row-editor-drag"
|
||||||
<Input
|
handleLabel={at("tariff_package_reorder", {}, "Перетащите, чтобы изменить порядок")}
|
||||||
class="input"
|
onReorder={(from, to) => tariffsStore.moveDraftRow("topupRows", from, to)}
|
||||||
type="number"
|
let:item={row}
|
||||||
min="0.1"
|
let:index
|
||||||
step="0.1"
|
|
||||||
placeholder="20"
|
|
||||||
bind:value={row.gb}
|
|
||||||
aria-label={at("tariff_col_volume_gb", {}, "Объём пакета в GB")}
|
|
||||||
/>
|
|
||||||
<Input
|
|
||||||
class="input"
|
|
||||||
type="number"
|
|
||||||
min="0"
|
|
||||||
step="0.01"
|
|
||||||
placeholder="149"
|
|
||||||
bind:value={row.price}
|
|
||||||
aria-label={currencyPriceAriaLabel}
|
|
||||||
/>
|
|
||||||
<AdminButton
|
|
||||||
size="sm"
|
|
||||||
variant="danger"
|
|
||||||
onclick={() => tariffsStore.removeDraftRow("topupRubRows", index)}
|
|
||||||
aria-label={at("btn_delete", {}, "Удалить")}><Trash2 size={13} /></AdminButton
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
<div class="admin-row-editor">
|
|
||||||
<span class="admin-row-editor-caption"
|
|
||||||
>{at("payment_stars", {}, "Оплата Telegram Stars")}</span
|
|
||||||
>
|
>
|
||||||
{#if tariffDraft.topupStarsRows.length}
|
<Input
|
||||||
<div class="admin-row-editor-line admin-row-editor-header">
|
class="input"
|
||||||
<span>{at("tariff_col_volume_gb", {}, "Объём, GB")}</span>
|
type="number"
|
||||||
<span>{at("tariff_col_price_stars", {}, "Цена, ⭐")}</span>
|
min="0.1"
|
||||||
<span></span>
|
step="0.1"
|
||||||
</div>
|
placeholder="20"
|
||||||
{/if}
|
bind:value={row.gb}
|
||||||
{#each tariffDraft.topupStarsRows as row, index}
|
aria-label={at("tariff_col_volume_gb", {}, "Объём пакета в GB")}
|
||||||
<div class="admin-row-editor-line">
|
/>
|
||||||
<Input
|
<Input
|
||||||
class="input"
|
class="input"
|
||||||
type="number"
|
type="number"
|
||||||
min="0.1"
|
min="0"
|
||||||
step="0.1"
|
step="0.01"
|
||||||
placeholder="20"
|
placeholder="149"
|
||||||
bind:value={row.gb}
|
bind:value={row.price}
|
||||||
aria-label={at("tariff_col_volume_gb", {}, "Объём пакета в GB")}
|
aria-label={currencyPriceAriaLabel}
|
||||||
/>
|
/>
|
||||||
<Input
|
<Input
|
||||||
class="input"
|
class="input"
|
||||||
type="number"
|
type="number"
|
||||||
min="0"
|
min="0"
|
||||||
step="1"
|
step="1"
|
||||||
placeholder="75"
|
placeholder="75"
|
||||||
bind:value={row.price}
|
bind:value={row.stars}
|
||||||
aria-label={at("tariff_label_price_stars", {}, "Цена пакета в Telegram Stars")}
|
aria-label={at("tariff_label_price_stars", {}, "Цена пакета в Telegram Stars")}
|
||||||
/>
|
/>
|
||||||
<AdminButton
|
<AdminButton
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="danger"
|
variant="danger"
|
||||||
onclick={() => tariffsStore.removeDraftRow("topupStarsRows", index)}
|
onclick={() => tariffsStore.removeDraftRow("topupRows", index)}
|
||||||
aria-label={at("btn_delete", {}, "Удалить")}><Trash2 size={13} /></AdminButton
|
aria-label={at("btn_delete", {}, "Удалить")}><Trash2 size={13} /></AdminButton
|
||||||
>
|
>
|
||||||
</div>
|
</Sortable>
|
||||||
{/each}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{/if}
|
||||||
</section>
|
</section>
|
||||||
{:else}
|
{:else}
|
||||||
<p class="admin-muted">
|
<p class="admin-muted">
|
||||||
@@ -890,104 +774,69 @@
|
|||||||
<div class="admin-editor-section-actions">
|
<div class="admin-editor-section-actions">
|
||||||
<AdminButton
|
<AdminButton
|
||||||
size="sm"
|
size="sm"
|
||||||
onclick={() => tariffsStore.addDraftRow("hwidRubRows", { count: 1, price: "" })}
|
onclick={() =>
|
||||||
><Plus size={12} /> {currencyPackageLabel}</AdminButton
|
tariffsStore.addDraftRow("hwidRows", { count: 1, price: "", stars: "" })}
|
||||||
>
|
><Plus size={12} /> {at("tariff_btn_package", {}, "Пакет")}</AdminButton
|
||||||
<AdminButton
|
|
||||||
size="sm"
|
|
||||||
onclick={() => tariffsStore.addDraftRow("hwidStarsRows", { count: 1, price: "" })}
|
|
||||||
><Plus size={12} /> {at("tariff_btn_package_stars", {}, "Пакет ⭐")}</AdminButton
|
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<div class="admin-package-columns">
|
{#if tariffDraft.hwidRows.length}
|
||||||
<div class="admin-row-editor">
|
<div class="admin-row-editor">
|
||||||
<span class="admin-row-editor-caption">{currencyPaymentLabel}</span>
|
<div class="admin-row-editor-line admin-row-editor-drag admin-row-editor-header">
|
||||||
{#if tariffDraft.hwidRubRows.length}
|
<span></span>
|
||||||
<div class="admin-row-editor-line admin-row-editor-header">
|
<span>{at("tariff_col_hwid_count", {}, "+ устройств")}</span>
|
||||||
<span>{at("tariff_col_hwid_count", {}, "+ устройств")}</span>
|
<span>{currencyPriceColumnLabel}</span>
|
||||||
<span>{currencyPriceColumnLabel}</span>
|
<span>{at("tariff_col_price_stars_full", {}, "Цена, ⭐ Stars")}</span>
|
||||||
<span></span>
|
<span></span>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
<Sortable
|
||||||
{#each tariffDraft.hwidRubRows as row, index}
|
items={tariffDraft.hwidRows}
|
||||||
<div class="admin-row-editor-line">
|
class="admin-row-editor-line admin-row-editor-drag"
|
||||||
<Input
|
handleLabel={at("tariff_package_reorder", {}, "Перетащите, чтобы изменить порядок")}
|
||||||
class="input"
|
onReorder={(from, to) => tariffsStore.moveDraftRow("hwidRows", from, to)}
|
||||||
type="number"
|
let:item={row}
|
||||||
min="1"
|
let:index
|
||||||
step="1"
|
|
||||||
placeholder="1"
|
|
||||||
bind:value={row.count}
|
|
||||||
aria-label={at(
|
|
||||||
"tariff_label_hwid_count_full",
|
|
||||||
{},
|
|
||||||
"Сколько устройств добавляет пакет"
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<Input
|
|
||||||
class="input"
|
|
||||||
type="number"
|
|
||||||
min="0"
|
|
||||||
step="0.01"
|
|
||||||
placeholder="99"
|
|
||||||
bind:value={row.price}
|
|
||||||
aria-label={currencyPriceAriaLabel}
|
|
||||||
/>
|
|
||||||
<AdminButton
|
|
||||||
size="sm"
|
|
||||||
variant="danger"
|
|
||||||
onclick={() => tariffsStore.removeDraftRow("hwidRubRows", index)}
|
|
||||||
aria-label={at("btn_delete", {}, "Удалить")}><Trash2 size={13} /></AdminButton
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
<div class="admin-row-editor">
|
|
||||||
<span class="admin-row-editor-caption"
|
|
||||||
>{at("payment_stars", {}, "Оплата Telegram Stars")}</span
|
|
||||||
>
|
>
|
||||||
{#if tariffDraft.hwidStarsRows.length}
|
<Input
|
||||||
<div class="admin-row-editor-line admin-row-editor-header">
|
class="input"
|
||||||
<span>{at("tariff_col_hwid_count", {}, "+ устройств")}</span>
|
type="number"
|
||||||
<span>{at("tariff_col_price_stars", {}, "Цена, ⭐")}</span>
|
min="1"
|
||||||
<span></span>
|
step="1"
|
||||||
</div>
|
placeholder="1"
|
||||||
{/if}
|
bind:value={row.count}
|
||||||
{#each tariffDraft.hwidStarsRows as row, index}
|
aria-label={at(
|
||||||
<div class="admin-row-editor-line">
|
"tariff_label_hwid_count_full",
|
||||||
<Input
|
{},
|
||||||
class="input"
|
"Сколько устройств добавляет пакет"
|
||||||
type="number"
|
)}
|
||||||
min="1"
|
/>
|
||||||
step="1"
|
<Input
|
||||||
placeholder="1"
|
class="input"
|
||||||
bind:value={row.count}
|
type="number"
|
||||||
aria-label={at(
|
min="0"
|
||||||
"tariff_label_hwid_count_full",
|
step="0.01"
|
||||||
{},
|
placeholder="99"
|
||||||
"Сколько устройств добавляет пакет"
|
bind:value={row.price}
|
||||||
)}
|
aria-label={currencyPriceAriaLabel}
|
||||||
/>
|
/>
|
||||||
<Input
|
<Input
|
||||||
class="input"
|
class="input"
|
||||||
type="number"
|
type="number"
|
||||||
min="0"
|
min="0"
|
||||||
step="1"
|
step="1"
|
||||||
placeholder="50"
|
placeholder="50"
|
||||||
bind:value={row.price}
|
bind:value={row.stars}
|
||||||
aria-label={at("tariff_label_price_stars", {}, "Цена пакета в Telegram Stars")}
|
aria-label={at("tariff_label_price_stars", {}, "Цена пакета в Telegram Stars")}
|
||||||
/>
|
/>
|
||||||
<AdminButton
|
<AdminButton
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="danger"
|
variant="danger"
|
||||||
onclick={() => tariffsStore.removeDraftRow("hwidStarsRows", index)}
|
onclick={() => tariffsStore.removeDraftRow("hwidRows", index)}
|
||||||
aria-label={at("btn_delete", {}, "Удалить")}><Trash2 size={13} /></AdminButton
|
aria-label={at("btn_delete", {}, "Удалить")}><Trash2 size={13} /></AdminButton
|
||||||
>
|
>
|
||||||
</div>
|
</Sortable>
|
||||||
{/each}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{/if}
|
||||||
</section>
|
</section>
|
||||||
</Tabs.Content>
|
</Tabs.Content>
|
||||||
</Tabs.Root>
|
</Tabs.Root>
|
||||||
|
|||||||
@@ -24,17 +24,13 @@ export function emptyTariffDraft() {
|
|||||||
{ months: 6, rub: 1200, stars: "", referral_inviter: 15, referral_referee: 7 },
|
{ months: 6, rub: 1200, stars: "", referral_inviter: 15, referral_referee: 7 },
|
||||||
{ months: 12, rub: 2400, stars: "", referral_inviter: 30, referral_referee: 15 },
|
{ months: 12, rub: 2400, stars: "", referral_inviter: 30, referral_referee: 15 },
|
||||||
],
|
],
|
||||||
topupRubRows: [],
|
topupRows: [],
|
||||||
topupStarsRows: [],
|
premiumTopupRows: [],
|
||||||
premiumTopupRubRows: [],
|
trafficRows: [
|
||||||
premiumTopupStarsRows: [],
|
{ gb: 10, price: 199, stars: "" },
|
||||||
trafficRubRows: [
|
{ gb: 50, price: 799, stars: "" },
|
||||||
{ gb: 10, price: 199 },
|
|
||||||
{ gb: 50, price: 799 },
|
|
||||||
],
|
],
|
||||||
trafficStarsRows: [],
|
hwidRows: [],
|
||||||
hwidRubRows: [],
|
|
||||||
hwidStarsRows: [],
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,6 +62,50 @@ export function rowsFromPackages(packageSet, currency, valueKey) {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function packageValueSignature(value) {
|
||||||
|
const num = Number(value);
|
||||||
|
return Number.isFinite(num) ? String(num) : String(value || "");
|
||||||
|
}
|
||||||
|
|
||||||
|
export function packageRowsFromPackageSet(packageSet, currency, valueKey) {
|
||||||
|
const currencyRows = rowsFromPackages(packageSet, currency, valueKey);
|
||||||
|
const starsRows = rowsFromPackages(packageSet, "stars", valueKey);
|
||||||
|
const usedStars = new Set();
|
||||||
|
|
||||||
|
const rows = currencyRows.map((row) => {
|
||||||
|
const rowSignature = packageValueSignature(row[valueKey]);
|
||||||
|
const starsIndex = starsRows.findIndex(
|
||||||
|
(starsRow, index) =>
|
||||||
|
!usedStars.has(index) && packageValueSignature(starsRow[valueKey]) === rowSignature
|
||||||
|
);
|
||||||
|
const starsRow = starsIndex >= 0 ? starsRows[starsIndex] : null;
|
||||||
|
if (starsIndex >= 0) usedStars.add(starsIndex);
|
||||||
|
|
||||||
|
return {
|
||||||
|
[valueKey]: row[valueKey],
|
||||||
|
price: row.price,
|
||||||
|
stars: starsRow?.price ?? "",
|
||||||
|
prices: row.prices,
|
||||||
|
min_price: row.min_price,
|
||||||
|
stars_prices: starsRow?.prices,
|
||||||
|
stars_min_price: starsRow?.min_price ?? "",
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
starsRows.forEach((starsRow, index) => {
|
||||||
|
if (usedStars.has(index)) return;
|
||||||
|
rows.push({
|
||||||
|
[valueKey]: starsRow[valueKey],
|
||||||
|
price: "",
|
||||||
|
stars: starsRow.price,
|
||||||
|
stars_prices: starsRow.prices,
|
||||||
|
stars_min_price: starsRow.min_price ?? "",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
|
||||||
export function draftFromTariff(tariff, defaultCurrency = "rub") {
|
export function draftFromTariff(tariff, defaultCurrency = "rub") {
|
||||||
const currency = normalizeCurrencyKey(defaultCurrency);
|
const currency = normalizeCurrencyKey(defaultCurrency);
|
||||||
const defaultPrices = tariff.prices?.[currency] || {};
|
const defaultPrices = tariff.prices?.[currency] || {};
|
||||||
@@ -109,14 +149,10 @@ export function draftFromTariff(tariff, defaultCurrency = "rub") {
|
|||||||
hwid_device_limit: tariff.hwid_device_limit ?? "",
|
hwid_device_limit: tariff.hwid_device_limit ?? "",
|
||||||
conversion_rate_rub_per_gb: tariff.conversion_rate_rub_per_gb ?? "",
|
conversion_rate_rub_per_gb: tariff.conversion_rate_rub_per_gb ?? "",
|
||||||
periodRows: periodRows.length ? periodRows : emptyTariffDraft().periodRows,
|
periodRows: periodRows.length ? periodRows : emptyTariffDraft().periodRows,
|
||||||
topupRubRows: rowsFromPackages(tariff.topup_packages, currency, "gb"),
|
topupRows: packageRowsFromPackageSet(tariff.topup_packages, currency, "gb"),
|
||||||
topupStarsRows: rowsFromPackages(tariff.topup_packages, "stars", "gb"),
|
premiumTopupRows: packageRowsFromPackageSet(tariff.premium_topup_packages, currency, "gb"),
|
||||||
premiumTopupRubRows: rowsFromPackages(tariff.premium_topup_packages, currency, "gb"),
|
trafficRows: packageRowsFromPackageSet(tariff.traffic_packages, currency, "gb"),
|
||||||
premiumTopupStarsRows: rowsFromPackages(tariff.premium_topup_packages, "stars", "gb"),
|
hwidRows: packageRowsFromPackageSet(tariff.hwid_device_packages, currency, "count"),
|
||||||
trafficRubRows: rowsFromPackages(tariff.traffic_packages, currency, "gb"),
|
|
||||||
trafficStarsRows: rowsFromPackages(tariff.traffic_packages, "stars", "gb"),
|
|
||||||
hwidRubRows: rowsFromPackages(tariff.hwid_device_packages, currency, "count"),
|
|
||||||
hwidStarsRows: rowsFromPackages(tariff.hwid_device_packages, "stars", "count"),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,10 +192,34 @@ export function packagesFromRows(rows, valueKey) {
|
|||||||
.filter((row) => row[valueKey] > 0 && row.price !== null && row.price >= 0);
|
.filter((row) => row[valueKey] > 0 && row.price !== null && row.price >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function packageSetFromRows(rubRows, starsRows, valueKey, defaultCurrency = "rub") {
|
export function packagesFromPackageRows(rows, valueKey, priceKey, options = {}) {
|
||||||
|
const pricesKey = options.pricesKey || "prices";
|
||||||
|
const minPriceKey = options.minPriceKey || "min_price";
|
||||||
|
return (rows || [])
|
||||||
|
.map((row) => {
|
||||||
|
const pkg = {
|
||||||
|
[valueKey]: parseNumber(row[valueKey]),
|
||||||
|
price: parseNumber(row[priceKey]),
|
||||||
|
};
|
||||||
|
if (row[pricesKey] && typeof row[pricesKey] === "object") {
|
||||||
|
pkg.prices = structuredCloneSafe(row[pricesKey]);
|
||||||
|
}
|
||||||
|
const minPrice = parseNumber(row[minPriceKey]);
|
||||||
|
if (minPrice !== null) {
|
||||||
|
pkg.min_price = minPrice;
|
||||||
|
}
|
||||||
|
return pkg;
|
||||||
|
})
|
||||||
|
.filter((row) => row[valueKey] > 0 && row.price !== null && row.price >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function packageSetFromRows(rows, valueKey, defaultCurrency = "rub") {
|
||||||
const currency = normalizeCurrencyKey(defaultCurrency);
|
const currency = normalizeCurrencyKey(defaultCurrency);
|
||||||
const defaultCurrencyPackages = packagesFromRows(rubRows, valueKey);
|
const defaultCurrencyPackages = packagesFromPackageRows(rows, valueKey, "price");
|
||||||
const stars = packagesFromRows(starsRows, valueKey);
|
const stars = packagesFromPackageRows(rows, valueKey, "stars", {
|
||||||
|
pricesKey: "stars_prices",
|
||||||
|
minPriceKey: "stars_min_price",
|
||||||
|
});
|
||||||
if (!defaultCurrencyPackages.length && !stars.length) return null;
|
if (!defaultCurrencyPackages.length && !stars.length) return null;
|
||||||
return {
|
return {
|
||||||
...(defaultCurrencyPackages.length ? { [currency]: defaultCurrencyPackages } : {}),
|
...(defaultCurrencyPackages.length ? { [currency]: defaultCurrencyPackages } : {}),
|
||||||
@@ -200,21 +260,11 @@ export function tariffFromDraft(draft, fallbackCurrency = "rub") {
|
|||||||
|
|
||||||
const hwidLimit = parseIntNumber(draft.hwid_device_limit);
|
const hwidLimit = parseIntNumber(draft.hwid_device_limit);
|
||||||
if (hwidLimit !== null) tariff.hwid_device_limit = hwidLimit;
|
if (hwidLimit !== null) tariff.hwid_device_limit = hwidLimit;
|
||||||
const hwidPackages = packageSetFromRows(
|
const hwidPackages = packageSetFromRows(draft.hwidRows, "count", defaultCurrency);
|
||||||
draft.hwidRubRows,
|
|
||||||
draft.hwidStarsRows,
|
|
||||||
"count",
|
|
||||||
defaultCurrency
|
|
||||||
);
|
|
||||||
if (hwidPackages) tariff.hwid_device_packages = hwidPackages;
|
if (hwidPackages) tariff.hwid_device_packages = hwidPackages;
|
||||||
const premiumMonthlyGb = parseNumber(draft.premium_monthly_gb);
|
const premiumMonthlyGb = parseNumber(draft.premium_monthly_gb);
|
||||||
if (premiumMonthlyGb !== null) tariff.premium_monthly_gb = premiumMonthlyGb;
|
if (premiumMonthlyGb !== null) tariff.premium_monthly_gb = premiumMonthlyGb;
|
||||||
const premiumTopupPackages = packageSetFromRows(
|
const premiumTopupPackages = packageSetFromRows(draft.premiumTopupRows, "gb", defaultCurrency);
|
||||||
draft.premiumTopupRubRows,
|
|
||||||
draft.premiumTopupStarsRows,
|
|
||||||
"gb",
|
|
||||||
defaultCurrency
|
|
||||||
);
|
|
||||||
if (premiumTopupPackages) tariff.premium_topup_packages = premiumTopupPackages;
|
if (premiumTopupPackages) tariff.premium_topup_packages = premiumTopupPackages;
|
||||||
|
|
||||||
if (tariff.billing_model === "period") {
|
if (tariff.billing_model === "period") {
|
||||||
@@ -254,20 +304,10 @@ export function tariffFromDraft(draft, fallbackCurrency = "rub") {
|
|||||||
.filter((row) => row.referral_referee !== null)
|
.filter((row) => row.referral_referee !== null)
|
||||||
.map((row) => [String(row.months), row.referral_referee])
|
.map((row) => [String(row.months), row.referral_referee])
|
||||||
);
|
);
|
||||||
const topupPackages = packageSetFromRows(
|
const topupPackages = packageSetFromRows(draft.topupRows, "gb", defaultCurrency);
|
||||||
draft.topupRubRows,
|
|
||||||
draft.topupStarsRows,
|
|
||||||
"gb",
|
|
||||||
defaultCurrency
|
|
||||||
);
|
|
||||||
if (topupPackages) tariff.topup_packages = topupPackages;
|
if (topupPackages) tariff.topup_packages = topupPackages;
|
||||||
} else {
|
} else {
|
||||||
const trafficPackages = packageSetFromRows(
|
const trafficPackages = packageSetFromRows(draft.trafficRows, "gb", defaultCurrency);
|
||||||
draft.trafficRubRows,
|
|
||||||
draft.trafficStarsRows,
|
|
||||||
"gb",
|
|
||||||
defaultCurrency
|
|
||||||
);
|
|
||||||
if (trafficPackages) tariff.traffic_packages = trafficPackages;
|
if (trafficPackages) tariff.traffic_packages = trafficPackages;
|
||||||
const conversion = parseNumber(draft.conversion_rate_rub_per_gb);
|
const conversion = parseNumber(draft.conversion_rate_rub_per_gb);
|
||||||
if (conversion !== null) tariff.conversion_rate_rub_per_gb = conversion;
|
if (conversion !== null) tariff.conversion_rate_rub_per_gb = conversion;
|
||||||
|
|||||||
@@ -3581,13 +3581,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.admin-row-editor-line.admin-row-editor-drag {
|
.admin-row-editor-line.admin-row-editor-drag {
|
||||||
grid-template-columns: 24px minmax(90px, 1fr) minmax(110px, 1fr) 32px;
|
grid-template-columns: 24px minmax(90px, 1fr) minmax(110px, 1fr) minmax(110px, 1fr)
|
||||||
}
|
32px;
|
||||||
|
|
||||||
.admin-package-columns {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
||||||
gap: 12px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-dialog-actions {
|
.admin-dialog-actions {
|
||||||
@@ -3799,7 +3794,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.admin-form-row.admin-form-row-3,
|
.admin-form-row.admin-form-row-3,
|
||||||
.admin-package-columns,
|
|
||||||
.admin-row-editor-line,
|
.admin-row-editor-line,
|
||||||
.admin-row-editor-line.admin-row-editor-4,
|
.admin-row-editor-line.admin-row-editor-4,
|
||||||
.admin-row-editor-line.admin-row-editor-6,
|
.admin-row-editor-line.admin-row-editor-6,
|
||||||
|
|||||||
Reference in New Issue
Block a user