(function() { //#region node_modules/svelte/src/internal/shared/utils.js var is_array = Array.isArray; var index_of = Array.prototype.indexOf; var includes = Array.prototype.includes; var array_from = Array.from; var define_property = Object.defineProperty; var get_descriptor = Object.getOwnPropertyDescriptor; var get_descriptors = Object.getOwnPropertyDescriptors; var object_prototype = Object.prototype; var array_prototype = Array.prototype; var get_prototype_of = Object.getPrototypeOf; var is_extensible = Object.isExtensible; /** * @param {any} thing * @returns {thing is Function} */ function is_function(thing) { return typeof thing === "function"; } var noop = () => {}; /** @param {Function} fn */ function run(fn) { return fn(); } /** @param {Array<() => void>} arr */ function run_all(arr) { for (var i = 0; i < arr.length; i++) arr[i](); } /** * TODO replace with Promise.withResolvers once supported widely enough * @template [T=void] */ function deferred() { /** @type {(value: T) => void} */ var resolve; /** @type {(reason: any) => void} */ var reject; return { promise: new Promise((res, rej) => { resolve = res; reject = rej; }), resolve, reject }; } /** * When encountering a situation like `let [a, b, c] = $derived(blah())`, * we need to stash an intermediate value that `a`, `b`, and `c` derive * from, in case it's an iterable * @template T * @param {ArrayLike | Iterable} value * @param {number} [n] * @returns {Array} */ function to_array(value, n) { if (Array.isArray(value)) return value; if (n === void 0 || !(Symbol.iterator in value)) return Array.from(value); /** @type {T[]} */ const array = []; for (const element of value) { array.push(element); if (array.length === n) break; } return array; } //#endregion //#region node_modules/svelte/src/internal/client/constants.js /** * An effect that does not destroy its child effects when it reruns. * Runs as part of render effects, i.e. not eagerly as part of tree traversal or effect flushing. */ var MANAGED_EFFECT = 1 << 24; var CLEAN = 1024; var DIRTY = 2048; var MAYBE_DIRTY = 4096; var INERT = 8192; var DESTROYED = 16384; /** Set once a reaction has run for the first time */ var REACTION_RAN = 32768; /** Effect is in the process of getting destroyed. Can be observed in child teardown functions */ var DESTROYING = 1 << 25; /** * 'Transparent' effects do not create a transition boundary. * This is on a block effect 99% of the time but may also be on a branch effect if its parent block effect was pruned */ var EFFECT_TRANSPARENT = 65536; var HEAD_EFFECT = 1 << 18; var EFFECT_PRESERVED = 1 << 19; var USER_EFFECT = 1 << 20; var EFFECT_OFFSCREEN = 1 << 25; /** * Tells that we marked this derived and its reactions as visited during the "mark as (maybe) dirty"-phase. * Will be lifted during execution of the derived and during checking its dirty state (both are necessary * because a derived might be checked but not executed). This is a pure performance optimization flag and * should not be used for any other purpose! */ var WAS_MARKED = 65536; var REACTION_IS_UPDATING = 1 << 21; var ASYNC = 1 << 22; var ERROR_VALUE = 1 << 23; var STATE_SYMBOL = Symbol("$state"); var LEGACY_PROPS = Symbol("legacy props"); var LOADING_ATTR_SYMBOL = Symbol(""); /** allow users to ignore aborted signal errors if `reason.name === 'StaleReactionError` */ var STALE_REACTION = new class StaleReactionError extends Error { name = "StaleReactionError"; message = "The reaction that called `getAbortSignal()` was re-run or destroyed"; }(); var IS_XHTML = !!globalThis.document?.contentType && /* @__PURE__ */ globalThis.document.contentType.includes("xml"); /** * `%name%(...)` can only be used during component initialisation * @param {string} name * @returns {never} */ function lifecycle_outside_component(name) { throw new Error(`https://svelte.dev/e/lifecycle_outside_component`); } //#endregion //#region node_modules/svelte/src/internal/client/errors.js /** * Cannot create a `$derived(...)` with an `await` expression outside of an effect tree * @returns {never} */ function async_derived_orphan() { throw new Error(`https://svelte.dev/e/async_derived_orphan`); } /** * Keyed each block has duplicate key `%value%` at indexes %a% and %b% * @param {string} a * @param {string} b * @param {string | undefined | null} [value] * @returns {never} */ function each_key_duplicate(a, b, value) { throw new Error(`https://svelte.dev/e/each_key_duplicate`); } /** * `%rune%` cannot be used inside an effect cleanup function * @param {string} rune * @returns {never} */ function effect_in_teardown(rune) { throw new Error(`https://svelte.dev/e/effect_in_teardown`); } /** * Effect cannot be created inside a `$derived` value that was not itself created inside an effect * @returns {never} */ function effect_in_unowned_derived() { throw new Error(`https://svelte.dev/e/effect_in_unowned_derived`); } /** * `%rune%` can only be used inside an effect (e.g. during component initialisation) * @param {string} rune * @returns {never} */ function effect_orphan(rune) { throw new Error(`https://svelte.dev/e/effect_orphan`); } /** * Maximum update depth exceeded. This typically indicates that an effect reads and writes the same piece of state * @returns {never} */ function effect_update_depth_exceeded() { throw new Error(`https://svelte.dev/e/effect_update_depth_exceeded`); } /** * Cannot do `bind:%key%={undefined}` when `%key%` has a fallback value * @param {string} key * @returns {never} */ function props_invalid_value(key) { throw new Error(`https://svelte.dev/e/props_invalid_value`); } /** * Property descriptors defined on `$state` objects must contain `value` and always be `enumerable`, `configurable` and `writable`. * @returns {never} */ function state_descriptors_fixed() { throw new Error(`https://svelte.dev/e/state_descriptors_fixed`); } /** * Cannot set prototype of `$state` object * @returns {never} */ function state_prototype_fixed() { throw new Error(`https://svelte.dev/e/state_prototype_fixed`); } /** * Updating state inside `$derived(...)`, `$inspect(...)` or a template expression is forbidden. If the value should not be reactive, declare it without `$state` * @returns {never} */ function state_unsafe_mutation() { throw new Error(`https://svelte.dev/e/state_unsafe_mutation`); } /** * A `` `reset` function cannot be called while an error is still being handled * @returns {never} */ function svelte_boundary_reset_onerror() { throw new Error(`https://svelte.dev/e/svelte_boundary_reset_onerror`); } //#endregion //#region node_modules/svelte/src/constants.js var HYDRATION_ERROR = {}; var UNINITIALIZED = Symbol(); var NAMESPACE_HTML = "http://www.w3.org/1999/xhtml"; var NAMESPACE_SVG = "http://www.w3.org/2000/svg"; /** * Reading a derived belonging to a now-destroyed effect may result in stale values */ function derived_inert() { console.warn(`https://svelte.dev/e/derived_inert`); } /** * Hydration failed because the initial UI does not match what was rendered on the server. The error occurred near %location% * @param {string | undefined | null} [location] */ function hydration_mismatch(location) { console.warn(`https://svelte.dev/e/hydration_mismatch`); } /** * The `value` property of a ``); function Input($$anchor, $$props) { push($$props, false); let value = prop($$props, "value", 12, ""); let type = prop($$props, "type", 8, "text"); let placeholder = prop($$props, "placeholder", 8, ""); let inputmode = prop($$props, "inputmode", 8, void 0); let maxlength = prop($$props, "maxlength", 8, void 0); let autocomplete = prop($$props, "autocomplete", 8, void 0); let disabled = prop($$props, "disabled", 8, false); let className = prop($$props, "class", 8, ""); init(); var input = root$5(); remove_input_defaults(input); template_effect(($0) => { set_class(input, 1, $0); set_attribute(input, "type", type()); set_attribute(input, "placeholder", placeholder()); set_attribute(input, "inputmode", inputmode()); set_attribute(input, "maxlength", maxlength()); set_attribute(input, "autocomplete", autocomplete()); input.disabled = disabled(); }, [() => clsx((deep_read_state(cn), deep_read_state(className()), untrack(() => cn("input", className()))))]); bind_value(input, value); append($$anchor, input); pop(); } //#endregion //#region bot/app/web/frontend/src/preview/BackTitle.svelte var root$4 = /* @__PURE__ */ from_html(`

`); function BackTitle($$anchor, $$props) { let title = prop($$props, "title", 8, ""); let subtitle = prop($$props, "subtitle", 8, ""); var header = root$4(); var button = child(header); Arrow_left(child(button), { size: 18 }); reset(button); var div = sibling(button, 2); var h1 = child(div); var text = child(h1, true); reset(h1); var p = sibling(h1, 2); var text_1 = child(p, true); reset(p); reset(div); next(2); reset(header); template_effect(() => { set_text(text, title()); set_text(text_1, subtitle()); }); append($$anchor, header); } //#endregion //#region bot/app/web/frontend/src/preview/PhoneFrame.svelte var root$3 = /* @__PURE__ */ from_html(`

`); function PhoneFrame($$anchor, $$props) { let number = prop($$props, "number", 8, ""); let label = prop($$props, "label", 8, ""); let wide = prop($$props, "wide", 8, false); var section = root$3(); let classes; var h2 = child(section); var span = child(h2); var text = child(span); reset(span); var text_1 = sibling(span); reset(h2); var div = sibling(h2, 2); slot(child(div), $$props, "default", {}, null); reset(div); reset(section); template_effect(() => { classes = set_class(section, 1, "preview-phone-wrap", null, classes, { wide: wide() }); set_text(text, `${number() ?? ""}.`); set_text(text_1, ` ${label() ?? ""}`); }); append($$anchor, section); } //#endregion //#region bot/app/web/frontend/src/preview/PreviewMethods.svelte var root_1$1 = /* @__PURE__ */ from_html(`
`); var root$2 = /* @__PURE__ */ from_html(`
`); function PreviewMethods($$anchor, $$props) { let methods = prop($$props, "methods", 24, () => []); const icons = [ Credit_card, Send, Wallet_cards, Wallet_cards ]; function note(index) { if (index === 0) return "Visa, Mastercard"; if (index === 1) return "Быстро и удобно"; if (index === 2) return "USDT, BTC, ETH"; return "ЮMoney, СБП и др."; } var div = root$2(); each(div, 5, methods, index, ($$anchor, method, index) => { var div_1 = root_1$1(); set_class(div_1, 1, "method-card", null, {}, { active: index === 1 }); var node = child(div_1); component(node, () => icons[index] || Wallet_cards, ($$anchor, $$component) => { $$component($$anchor, { size: 18 }); }); var span = sibling(node, 2); var strong = child(span); var text = child(strong, true); reset(strong); var small = sibling(strong, 2); var text_1 = child(small, true); reset(small); reset(span); reset(div_1); template_effect(($0) => { set_text(text, (get(method), untrack(() => get(method).name))); set_text(text_1, $0); }, [() => untrack(() => note(index))]); append($$anchor, div_1); }); reset(div); append($$anchor, div); } //#endregion //#region bot/app/web/frontend/src/preview/PreviewNav.svelte var root$1 = /* @__PURE__ */ from_html(``); function PreviewNav($$anchor, $$props) { let active = prop($$props, "active", 8, "home"); var nav = root$1(); var button = child(nav); let classes; House(child(button), { size: 20 }); next(); reset(button); var button_1 = sibling(button, 2); let classes_1; Gift(child(button_1), { size: 20 }); next(); reset(button_1); var button_2 = sibling(button_1, 2); let classes_2; Settings(child(button_2), { size: 20 }); next(); reset(button_2); reset(nav); template_effect(() => { classes = set_class(button, 1, "", null, classes, { active: active() === "home" }); classes_1 = set_class(button_1, 1, "", null, classes_1, { active: active() === "invite" }); classes_2 = set_class(button_2, 1, "", null, classes_2, { active: active() === "settings" }); }); append($$anchor, nav); } //#endregion //#region bot/app/web/frontend/src/PreviewBoard.svelte var root_2 = /* @__PURE__ */ from_html(`

Подписка активна

`); var root_3$1 = /* @__PURE__ */ from_html(`
Использовано трафика
18%
`, 1); var root_4$1 = /* @__PURE__ */ from_html(`Установить и настроить`, 1); var root_5$1 = /* @__PURE__ */ from_html(`Продлить`, 1); var root_6$1 = /* @__PURE__ */ from_html(`Сменить тариф`, 1); var root_1 = /* @__PURE__ */ from_html(`
`); var root_8$1 = /* @__PURE__ */ from_html(`
`); var root_11 = /* @__PURE__ */ from_html(`Далее `, 1); var root_7$1 = /* @__PURE__ */ from_html(`
`, 1); var root_13$1 = /* @__PURE__ */ from_html(`
`); var root_15$1 = /* @__PURE__ */ from_html(`Итого
К оплате
790 ₽`, 1); var root_16$1 = /* @__PURE__ */ from_html(`Оплатить 790 ₽ `, 1); var root_12$1 = /* @__PURE__ */ from_html(`
`, 1); var root_18$1 = /* @__PURE__ */ from_html(`
`); var root_20 = /* @__PURE__ */ from_html(`Итого
К оплате
990 ₽`, 1); var root_21$1 = /* @__PURE__ */ from_html(`Оплатить 990 ₽ `, 1); var root_17$1 = /* @__PURE__ */ from_html(`
`, 1); var root_23$1 = /* @__PURE__ */ from_html(`Далее `, 1); var root_22$1 = /* @__PURE__ */ from_html(`
ПодпискаБезлимитный трафикДоплата 190 ₽
ТрафикПакеты гигабайтДоплата не требуется
ПремиумМаксимальная скоростьДоплата 390 ₽
Сменить тариф без доплаты?

Остаток 12 дней будет пересчитан по новому тарифу.

`, 1); var root_28$1 = /* @__PURE__ */ from_html(`Копировать `, 1); var root_27$1 = /* @__PURE__ */ from_html(`
Ваша реферальная ссылка
https://minishop.app/ref/ABCD1234
`, 1); var root_29$1 = /* @__PURE__ */ from_html(`
Ваш бонус+7 дней за каждого друга

Друг получит +3 дня к подписке.

`, 1); var root_30$1 = /* @__PURE__ */ from_html(`Активировать промокод`, 1); var root_26$1 = /* @__PURE__ */ from_html(`
`, 1); var root_33$1 = /* @__PURE__ */ from_html(`Аватар пользователя`); var root_32$1 = /* @__PURE__ */ from_html(`
`, 1); var root_35$1 = /* @__PURE__ */ from_html(`
`); var root_31$1 = /* @__PURE__ */ from_html(`
`, 1); var root_38$1 = /* @__PURE__ */ from_html(`Получить код`, 1); var root_39 = /* @__PURE__ */ from_html(`Войти через Telegram`, 1); var root_37 = /* @__PURE__ */ from_html(`
Вход по email
или
`, 1); var root_36$1 = /* @__PURE__ */ from_html(`
Нет аккаунта? Создать
`, 1); var root_41$1 = /* @__PURE__ */ from_html(` `); var root_40 = /* @__PURE__ */ from_html(`
`, 1); var root = /* @__PURE__ */ from_html(`
`); function PreviewBoard($$anchor, $$props) { push($$props, false); let config = prop($$props, "config", 24, () => ({})); let mockData = prop($$props, "mockData", 24, () => ({})); const title = config().title || "/minishop"; const logoEmoji = config().logoEmoji || "🫥"; const plans = mockData().plans || []; const sub = mockData().subscription || {}; const methods = mockData().payment_methods || []; const user = mockData().user || {}; const tariffs = [ [ "subscription", "Подписка", "Безлимитный трафик", "Идеально для постоянного использования", Zap ], [ "traffic", "Трафик", "Пакеты гигабайт", "Платите только за нужный объем", Database ], [ "premium", "Премиум", "Максимальная скорость", "Приоритетные серверы и поддержка", Crown ] ]; const traffic = [ [20, 290], [50, 590], [100, 990], [300, 2190] ]; const settingsRows = [ [ Earth, "Язык интерфейса", "Русский" ], [ Send, "Привязка Telegram", user.telegram_linked ? `@${user.username || "username"}` : "Не привязан" ], [ Mail, "Привязка почты", user.email || "Не привязана" ], [ User_round, "Выйти", "Завершить сессию" ] ]; const previewTelegramName = user.first_name || (user.username ? `@${user.username}` : "Telegram не привязан"); const previewEmail = user.email || "Почта не привязана"; const previewTelegramId = user.telegram_id ? `TG ID ${user.telegram_id}` : "TG ID не привязан"; const previewAvatar = user.telegram_photo_url || ""; function money(value) { return `${value} ₽`; } init(); var div = root(); var node = child(div); PhoneFrame(node, { number: "1", label: "Главный экран", children: ($$anchor, $$slotProps) => { var main = root_1(); var div_1 = child(main); var div_2 = child(div_1); var span = child(div_2); var text = child(span, true); reset(span); reset(div_2); var h1 = sibling(div_2, 2); var text_1 = child(h1, true); reset(h1); reset(div_1); var div_3 = sibling(div_1, 2); var node_1 = child(div_3); Card(node_1, { class: "status-card", children: ($$anchor, $$slotProps) => { var div_4 = root_2(); var node_2 = child(div_4); Circle_check(node_2, { size: 23 }); var div_5 = sibling(node_2, 2); var p = sibling(child(div_5)); var text_2 = child(p); reset(p); reset(div_5); reset(div_4); template_effect(() => set_text(text_2, `до ${untrack(() => sub.end_date_text) ?? ""}`)); append($$anchor, div_4); }, $$slots: { default: true } }); var node_3 = sibling(node_1, 2); Card(node_3, { children: ($$anchor, $$slotProps) => { var fragment = root_3$1(); var div_6 = first_child(fragment); var strong = sibling(child(div_6)); var text_3 = child(strong); reset(strong); reset(div_6); next(4); template_effect(() => set_text(text_3, `${untrack(() => sub.traffic_used) ?? ""} из ${untrack(() => sub.traffic_limit) ?? ""}`)); append($$anchor, fragment); }, $$slots: { default: true } }); var div_7 = sibling(node_3, 2); var node_4 = child(div_7); Button(node_4, { class: "wide", children: ($$anchor, $$slotProps) => { var fragment_1 = root_4$1(); Download(first_child(fragment_1), { size: 17 }); next(); append($$anchor, fragment_1); }, $$slots: { default: true } }); var node_6 = sibling(node_4, 2); Button(node_6, { variant: "secondary", class: "wide", children: ($$anchor, $$slotProps) => { var fragment_2 = root_5$1(); Refresh_cw(first_child(fragment_2), { size: 17 }); next(); append($$anchor, fragment_2); }, $$slots: { default: true } }); Button(sibling(node_6, 2), { variant: "secondary", class: "wide", children: ($$anchor, $$slotProps) => { var fragment_3 = root_6$1(); Repeat_2(first_child(fragment_3), { size: 17 }); next(); append($$anchor, fragment_3); }, $$slots: { default: true } }); reset(div_7); reset(div_3); PreviewNav(sibling(div_3, 2), { active: "home" }); reset(main); template_effect(() => { set_text(text, logoEmoji); set_text(text_1, title); }); append($$anchor, main); }, $$slots: { default: true } }); var node_11 = sibling(node, 2); PhoneFrame(node_11, { number: "2", label: "Выбор тарифа", children: ($$anchor, $$slotProps) => { var fragment_4 = root_7$1(); var div_8 = first_child(fragment_4); var div_9 = child(div_8); var div_10 = child(div_9); var span_1 = child(div_10); var text_4 = child(span_1, true); reset(span_1); reset(div_10); var strong_1 = sibling(div_10); var text_5 = child(strong_1, true); reset(strong_1); reset(div_9); reset(div_8); var div_11 = sibling(div_8, 2); each(div_11, 5, () => tariffs, index, ($$anchor, tariff, index) => { var div_12 = root_8$1(); set_class(div_12, 1, "select-card", null, {}, { active: index === 0 }); var span_2 = child(div_12); component(child(span_2), () => get(tariff)[4], ($$anchor, $$component) => { $$component($$anchor, { size: 24 }); }); reset(span_2); var span_3 = sibling(span_2, 2); var strong_2 = child(span_3); var text_6 = child(strong_2, true); reset(strong_2); var small = sibling(strong_2); var text_7 = child(small, true); reset(small); var em = sibling(small); var text_8 = child(em, true); reset(em); reset(span_3); var node_13 = sibling(span_3, 2); var consequent = ($$anchor) => { Circle_check($$anchor, { size: 21 }); }; var alternate = ($$anchor) => { Circle($$anchor, { size: 21 }); }; if_block(node_13, ($$render) => { if (index === 0) $$render(consequent); else $$render(alternate, -1); }); reset(div_12); template_effect(() => { set_text(text_6, (get(tariff), untrack(() => get(tariff)[1]))); set_text(text_7, (get(tariff), untrack(() => get(tariff)[2]))); set_text(text_8, (get(tariff), untrack(() => get(tariff)[3]))); }); append($$anchor, div_12); }); reset(div_11); Button(sibling(div_11, 2), { class: "wide bottom-action", children: ($$anchor, $$slotProps) => { next(); var fragment_7 = root_11(); Arrow_right(sibling(first_child(fragment_7)), { size: 17 }); append($$anchor, fragment_7); }, $$slots: { default: true } }); template_effect(() => { set_text(text_4, logoEmoji); set_text(text_5, title); }); append($$anchor, fragment_4); }, $$slots: { default: true } }); var node_16 = sibling(node_11, 2); PhoneFrame(node_16, { number: "3", label: "Оплата тарифа — подписка", wide: true, children: ($$anchor, $$slotProps) => { var fragment_8 = root_12$1(); var node_17 = first_child(fragment_8); BackTitle(node_17, { title: "Подписка", subtitle: "Выберите срок подписки" }); var div_13 = sibling(node_17, 2); each(div_13, 5, () => plans, index, ($$anchor, plan, index) => { var div_14 = root_13$1(); set_class(div_14, 1, "period-card", null, {}, { active: index === 1 }); var strong_3 = child(div_14); var text_9 = child(strong_3, true); reset(strong_3); var span_4 = sibling(strong_3); var text_10 = child(span_4, true); reset(span_4); var small_1 = sibling(span_4); var text_11 = child(small_1); reset(small_1); var node_18 = sibling(small_1, 2); var consequent_1 = ($$anchor) => { Circle_check($$anchor, { size: 18 }); }; if_block(node_18, ($$render) => { if (index === 1) $$render(consequent_1); }); reset(div_14); template_effect(($0, $1) => { set_text(text_9, (get(plan), untrack(() => get(plan).title))); set_text(text_10, $0); set_text(text_11, `${$1 ?? ""}/мес`); }, [() => (get(plan), untrack(() => money(get(plan).price))), () => (get(plan), untrack(() => money(Math.round(get(plan).price / get(plan).months))))]); append($$anchor, div_14); }); reset(div_13); var node_19 = sibling(div_13, 2); Card(node_19, { class: "total-card", children: ($$anchor, $$slotProps) => { var fragment_10 = root_15$1(); next(); append($$anchor, fragment_10); }, $$slots: { default: true } }); var node_20 = sibling(node_19, 2); PreviewMethods(node_20, { get methods() { return methods; } }); Button(sibling(node_20, 2), { class: "wide bottom-action", children: ($$anchor, $$slotProps) => { next(); var fragment_11 = root_16$1(); Lock_keyhole(sibling(first_child(fragment_11)), { size: 16 }); append($$anchor, fragment_11); }, $$slots: { default: true } }); append($$anchor, fragment_8); }, $$slots: { default: true } }); var node_23 = sibling(node_16, 2); PhoneFrame(node_23, { number: "4", label: "Оплата тарифа — трафик", wide: true, children: ($$anchor, $$slotProps) => { var fragment_12 = root_17$1(); var node_24 = first_child(fragment_12); BackTitle(node_24, { title: "Трафик", subtitle: "Выберите пакет трафика" }); var div_15 = sibling(node_24, 2); each(div_15, 5, () => traffic, index, ($$anchor, pack, index) => { var div_16 = root_18$1(); set_class(div_16, 1, "period-card", null, {}, { active: index === 2 }); var strong_4 = child(div_16); var text_12 = child(strong_4); reset(strong_4); var span_5 = sibling(strong_4); var text_13 = child(span_5, true); reset(span_5); var small_2 = sibling(span_5); var text_14 = child(small_2); reset(small_2); var node_25 = sibling(small_2, 2); var consequent_2 = ($$anchor) => { Circle_check($$anchor, { size: 18 }); }; if_block(node_25, ($$render) => { if (index === 2) $$render(consequent_2); }); reset(div_16); template_effect(($0, $1) => { set_text(text_12, `${(get(pack), untrack(() => get(pack)[0])) ?? ""} ГБ`); set_text(text_13, $0); set_text(text_14, `${$1 ?? ""}/ГБ`); }, [() => (get(pack), untrack(() => money(get(pack)[1]))), () => (get(pack), untrack(() => money(Math.round(get(pack)[1] / get(pack)[0]))))]); append($$anchor, div_16); }); reset(div_15); var node_26 = sibling(div_15, 2); Card(node_26, { class: "total-card", children: ($$anchor, $$slotProps) => { var fragment_14 = root_20(); next(); append($$anchor, fragment_14); }, $$slots: { default: true } }); var node_27 = sibling(node_26, 2); PreviewMethods(node_27, { get methods() { return methods; } }); Button(sibling(node_27, 2), { class: "wide bottom-action", children: ($$anchor, $$slotProps) => { next(); var fragment_15 = root_21$1(); Lock_keyhole(sibling(first_child(fragment_15)), { size: 16 }); append($$anchor, fragment_15); }, $$slots: { default: true } }); append($$anchor, fragment_12); }, $$slots: { default: true } }); var node_30 = sibling(node_23, 2); PhoneFrame(node_30, { number: "5", label: "Смена тарифа", children: ($$anchor, $$slotProps) => { var fragment_16 = root_22$1(); var node_31 = first_child(fragment_16); BackTitle(node_31, { title: "Смена тарифа", subtitle: "Остаток 12 дней будет пересчитан" }); var div_17 = sibling(node_31, 2); var div_18 = child(div_17); Circle(sibling(child(div_18), 2), { size: 20 }); reset(div_18); var div_19 = sibling(div_18, 2); Circle_check(sibling(child(div_19), 2), { size: 20 }); reset(div_19); var div_20 = sibling(div_19, 2); Circle(sibling(child(div_20), 2), { size: 20 }); reset(div_20); reset(div_17); var node_35 = sibling(div_17, 2); Button(node_35, { class: "wide bottom-action", children: ($$anchor, $$slotProps) => { next(); var fragment_17 = root_23$1(); Arrow_right(sibling(first_child(fragment_17)), { size: 17 }); append($$anchor, fragment_17); }, $$slots: { default: true } }); var div_21 = sibling(node_35, 2); var node_37 = child(div_21); Repeat_2(node_37, { size: 30 }); var node_38 = sibling(node_37, 6); Button(node_38, { children: ($$anchor, $$slotProps) => { next(); append($$anchor, text("Да, сменить")); }, $$slots: { default: true } }); Button(sibling(node_38, 2), { variant: "secondary", children: ($$anchor, $$slotProps) => { next(); append($$anchor, text("Отмена")); }, $$slots: { default: true } }); reset(div_21); append($$anchor, fragment_16); }, $$slots: { default: true } }); var node_40 = sibling(node_30, 2); PhoneFrame(node_40, { number: "6", label: "Пригласить друга", children: ($$anchor, $$slotProps) => { var fragment_18 = root_26$1(); var div_22 = first_child(fragment_18); var div_23 = child(div_22); var div_24 = child(div_23); var span_6 = child(div_24); var text_17 = child(span_6, true); reset(span_6); reset(div_24); var strong_5 = sibling(div_24); var text_18 = child(strong_5, true); reset(strong_5); reset(div_23); reset(div_22); var node_41 = sibling(div_22, 2); Card(node_41, { children: ($$anchor, $$slotProps) => { var fragment_19 = root_27$1(); var div_25 = sibling(first_child(fragment_19), 2); Button(sibling(child(div_25)), { children: ($$anchor, $$slotProps) => { next(); var fragment_20 = root_28$1(); Copy(sibling(first_child(fragment_20)), { size: 16 }); append($$anchor, fragment_20); }, $$slots: { default: true } }); reset(div_25); append($$anchor, fragment_19); }, $$slots: { default: true } }); var node_44 = sibling(node_41, 2); Card(node_44, { class: "bonus-card", children: ($$anchor, $$slotProps) => { var fragment_21 = root_29$1(); Gift(first_child(fragment_21), { size: 42 }); next(); append($$anchor, fragment_21); }, $$slots: { default: true } }); Button(sibling(node_44, 2), { variant: "outline", class: "wide", children: ($$anchor, $$slotProps) => { var fragment_22 = root_30$1(); Ticket(first_child(fragment_22), { size: 18 }); next(); append($$anchor, fragment_22); }, $$slots: { default: true } }); template_effect(() => { set_text(text_17, logoEmoji); set_text(text_18, title); }); append($$anchor, fragment_18); }, $$slots: { default: true } }); var node_48 = sibling(node_40, 2); PhoneFrame(node_48, { number: "7", label: "Настройки", children: ($$anchor, $$slotProps) => { var fragment_23 = root_31$1(); var div_26 = first_child(fragment_23); var div_27 = child(div_26); var div_28 = child(div_27); var span_7 = child(div_28); var text_19 = child(span_7, true); reset(span_7); reset(div_28); var strong_6 = sibling(div_28); var text_20 = child(strong_6, true); reset(strong_6); reset(div_27); reset(div_26); var node_49 = sibling(div_26, 2); Card(node_49, { class: "settings-profile", children: ($$anchor, $$slotProps) => { var fragment_24 = root_32$1(); var div_29 = first_child(fragment_24); var node_50 = child(div_29); var consequent_3 = ($$anchor) => { var img = root_33$1(); template_effect(() => set_attribute(img, "src", previewAvatar)); append($$anchor, img); }; var alternate_1 = ($$anchor) => { User_round($$anchor, { size: 27 }); }; if_block(node_50, ($$render) => { if (previewAvatar) $$render(consequent_3); else $$render(alternate_1, -1); }); reset(div_29); var div_30 = sibling(div_29, 2); var strong_7 = child(div_30); var text_21 = child(strong_7, true); reset(strong_7); var small_3 = sibling(strong_7, 2); var text_22 = child(small_3, true); reset(small_3); var small_4 = sibling(small_3, 2); var text_23 = child(small_4, true); reset(small_4); reset(div_30); template_effect(() => { set_text(text_21, previewTelegramName); set_text(text_22, previewEmail); set_text(text_23, previewTelegramId); }); append($$anchor, fragment_24); }, $$slots: { default: true } }); var div_31 = sibling(node_49, 2); each(div_31, 5, () => settingsRows, index, ($$anchor, row) => { var div_32 = root_35$1(); var node_51 = child(div_32); component(node_51, () => get(row)[0], ($$anchor, $$component) => { $$component($$anchor, { size: 20 }); }); var span_8 = sibling(node_51, 2); var strong_8 = child(span_8); var text_24 = child(strong_8, true); reset(strong_8); var small_5 = sibling(strong_8); var text_25 = child(small_5, true); reset(small_5); reset(span_8); Arrow_right(sibling(span_8, 2), { size: 16 }); reset(div_32); template_effect(() => { set_text(text_24, (get(row), untrack(() => get(row)[1]))); set_text(text_25, (get(row), untrack(() => get(row)[2]))); }); append($$anchor, div_32); }); reset(div_31); template_effect(() => { set_text(text_19, logoEmoji); set_text(text_20, title); }); append($$anchor, fragment_23); }, $$slots: { default: true } }); var node_53 = sibling(node_48, 2); PhoneFrame(node_53, { number: "8", label: "Логин", wide: true, children: ($$anchor, $$slotProps) => { var fragment_26 = root_36$1(); var div_33 = first_child(fragment_26); var div_34 = child(div_33); var span_9 = child(div_34); var text_26 = child(span_9, true); reset(span_9); reset(div_34); var h1_1 = sibling(div_34, 2); var text_27 = child(h1_1, true); reset(h1_1); next(); reset(div_33); Card(sibling(div_33, 2), { class: "auth-card", children: ($$anchor, $$slotProps) => { var fragment_27 = root_37(); var div_35 = sibling(first_child(fragment_27), 2); Button(sibling(child(div_35)), { variant: "outline", children: ($$anchor, $$slotProps) => { var fragment_28 = root_38$1(); Mail(first_child(fragment_28), { size: 17 }); next(); append($$anchor, fragment_28); }, $$slots: { default: true } }); reset(div_35); Button(sibling(div_35, 4), { variant: "telegram", class: "wide", children: ($$anchor, $$slotProps) => { var fragment_29 = root_39(); Send(first_child(fragment_29), { size: 18 }); next(); append($$anchor, fragment_29); }, $$slots: { default: true } }); append($$anchor, fragment_27); }, $$slots: { default: true } }); next(2); template_effect(() => { set_text(text_26, logoEmoji); set_text(text_27, title); }); append($$anchor, fragment_26); }, $$slots: { default: true } }); PhoneFrame(sibling(node_53, 2), { number: "9", label: "Подтверждение по коду", wide: true, children: ($$anchor, $$slotProps) => { var fragment_30 = root_40(); var node_60 = first_child(fragment_30); BackTitle(node_60, { title: "Подтверждение по email", subtitle: "Мы отправили код на user@example.com" }); var div_36 = sibling(node_60, 2); each(div_36, 4, () => [ 1, 2, 3, 4, 5, 6 ], index, ($$anchor, digit) => { var span_10 = root_41$1(); var text_28 = child(span_10, true); reset(span_10); template_effect(() => set_text(text_28, digit)); append($$anchor, span_10); }); reset(div_36); var node_61 = sibling(div_36, 2); Button(node_61, { class: "wide bottom-action", children: ($$anchor, $$slotProps) => { next(); append($$anchor, text("Подтвердить")); }, $$slots: { default: true } }); var button = sibling(node_61, 2); Refresh_cw(child(button), { size: 15 }); next(); reset(button); append($$anchor, fragment_30); }, $$slots: { default: true } }); reset(div); template_effect(() => set_style(div, (deep_read_state(config()), untrack(() => `--accent: ${config().primaryColor || "#00fe7a"};`)))); append($$anchor, div); pop(); } //#endregion //#region bot/app/web/frontend/src/App.svelte var root_5 = /* @__PURE__ */ from_html(``); var root_6 = /* @__PURE__ */ from_html(` `); var root_4 = /* @__PURE__ */ from_html(`
Загрузка...
`); var root_10 = /* @__PURE__ */ from_html(` `); var root_12 = /* @__PURE__ */ from_html(`
`); var root_8 = /* @__PURE__ */ from_html(`

Подтверждение по email

Мы отправили код на

`, 1); var root_14 = /* @__PURE__ */ from_html(``); var root_15 = /* @__PURE__ */ from_html(` `); var root_18 = /* @__PURE__ */ from_html(` Код`, 1); var root_17 = /* @__PURE__ */ from_html(`
Вход по email
`); var root_21 = /* @__PURE__ */ from_html(` Войти через Telegram`, 1); var root_22 = /* @__PURE__ */ from_html(`
`); var root_19 = /* @__PURE__ */ from_html(`
Вход через Telegram
`); var root_23 = /* @__PURE__ */ from_html(`
`); var root_16 = /* @__PURE__ */ from_html(`
`, 1); var root_13 = /* @__PURE__ */ from_html(`
Нет аккаунта? Создать
`); var root_7 = /* @__PURE__ */ from_html(`
`); var root_26 = /* @__PURE__ */ from_html(``); var root_27 = /* @__PURE__ */ from_html(` `); var root_25 = /* @__PURE__ */ from_html(`
`); var root_29 = /* @__PURE__ */ from_html(``); var root_30 = /* @__PURE__ */ from_html(` `); var root_31 = /* @__PURE__ */ from_html(`

`); var root_32 = /* @__PURE__ */ from_html(`
Использовано трафика
`, 1); var root_33 = /* @__PURE__ */ from_html(` Установить и настроить`, 1); var root_34 = /* @__PURE__ */ from_html(` Продлить`, 1); var root_35 = /* @__PURE__ */ from_html(` Сменить тариф`, 1); var root_28 = /* @__PURE__ */ from_html(`
`); var root_38 = /* @__PURE__ */ from_html(``); var root_41 = /* @__PURE__ */ from_html(`Далее `, 1); var root_36 = /* @__PURE__ */ from_html(`

Выбор тарифа

Экраны тарифов пока сверстаны без подключения

`); var root_45 = /* @__PURE__ */ from_html(` `); var root_44 = /* @__PURE__ */ from_html(``); var root_47 = /* @__PURE__ */ from_html(`Итого
К оплате
`, 1); var root_49 = /* @__PURE__ */ from_html(``); var root_52 = /* @__PURE__ */ from_html(` `, 1); var root_42 = /* @__PURE__ */ from_html(`

Подписка

Выберите срок подписки

`); var root_55 = /* @__PURE__ */ from_html(``); var root_57 = /* @__PURE__ */ from_html(`Итого
К оплате
`, 1); var root_58 = /* @__PURE__ */ from_html(``); var root_59 = /* @__PURE__ */ from_html(` `, 1); var root_53 = /* @__PURE__ */ from_html(`

Трафик

Выберите пакет трафика

`); var root_62 = /* @__PURE__ */ from_html(``); var root_65 = /* @__PURE__ */ from_html(`Далее `, 1); var root_60 = /* @__PURE__ */ from_html(`

Смена тарифа

Остаток 12 дней будет пересчитан

`); var root_68 = /* @__PURE__ */ from_html(`Копировать `, 1); var root_67 = /* @__PURE__ */ from_html(`
Ваша реферальная ссылка
`, 1); var root_69 = /* @__PURE__ */ from_html(`
Ваш бонус +7 дней за каждого друга

Друг получит +3 дня к подписке после регистрации.

`, 1); var root_71 = /* @__PURE__ */ from_html(` Активировать`, 1); var root_72 = /* @__PURE__ */ from_html(`

`); var root_70 = /* @__PURE__ */ from_html(`
Промокод
`, 1); var root_66 = /* @__PURE__ */ from_html(`
`); var root_75 = /* @__PURE__ */ from_html(`Аватар пользователя`); var root_74 = /* @__PURE__ */ from_html(`
`, 1); var root_73 = /* @__PURE__ */ from_html(`
`); var root_77 = /* @__PURE__ */ from_html(``); var root_24 = /* @__PURE__ */ from_html(`
`); var root_78 = /* @__PURE__ */ from_html(`
`); var root_81 = /* @__PURE__ */ from_html(`
`); var root_3 = /* @__PURE__ */ from_html(`
`); function App($$anchor, $$props) { push($$props, false); const brandTitle = /* @__PURE__ */ mutable_source(); const brandEmoji = /* @__PURE__ */ mutable_source(); const accent = /* @__PURE__ */ mutable_source(); const plans = /* @__PURE__ */ mutable_source(); const methods = /* @__PURE__ */ mutable_source(); const subscription = /* @__PURE__ */ mutable_source(); const user = /* @__PURE__ */ mutable_source(); const referral = /* @__PURE__ */ mutable_source(); const userLanguage = /* @__PURE__ */ mutable_source(); const telegramProfileName = /* @__PURE__ */ mutable_source(); const profileEmail = /* @__PURE__ */ mutable_source(); const profileTelegramId = /* @__PURE__ */ mutable_source(); const profileAvatarUrl = /* @__PURE__ */ mutable_source(); const TELEGRAM_LOGIN_WIDGET_URL = "https://telegram.org/js/telegram-widget.js?23"; const TELEGRAM_LOGIN_WIDGET_RENDER_TIMEOUT_MS = 8e3; const MANUAL_LOGOUT_FLAG_KEY = "rw_webapp_manual_logout"; const LANGUAGE_LABELS = { ru: "Русский", en: "English", de: "Deutsch", es: "Español", fr: "Français", tr: "Türkçe", uk: "Українська" }; const DEV_MOCK = { config: { title: "/minishop", primaryColor: "#00fe7a", logoUrl: "", logoEmoji: "🫥", apiBase: "/api", supportUrl: "https://t.me/support", privacyPolicyUrl: "https://example.com/privacy", userAgreementUrl: "https://example.com/agreement", currency: "RUB", language: "ru", emailAuthEnabled: true, telegramLoginBotUsername: "preview_bot" }, data: { ok: true, user: { id: 100200300, username: "username", email: "user@example.com", email_verified: true, telegram_id: 100200300, telegram_linked: true, telegram_photo_url: "", first_name: "Preview", language_code: "ru" }, subscription: { active: true, status: "ACTIVE", remaining_text: "25 д. 8 ч.", end_date_text: "24.05.2026", days_left: 25, config_link: "https://sub.example.com/sub/preview-token", connect_url: "https://sub.example.com/connect/preview-token", traffic_used: "18.4 GB", traffic_limit: "100 GB", traffic_used_bytes: 19756849561, traffic_limit_bytes: 107374182400 }, plans: [ { months: 1, price: 290, currency: "RUB", title: "1 месяц" }, { months: 3, price: 790, currency: "RUB", title: "3 месяца" }, { months: 6, price: 1490, currency: "RUB", title: "6 месяцев" }, { months: 12, price: 2690, currency: "RUB", title: "12 месяцев" } ], payment_methods: [ { id: "yookassa", name: "Карта" }, { id: "platega_sbp", name: "Telegram Pay" }, { id: "cryptopay", name: "Криптовалюта" }, { id: "freekassa", name: "Другие способы" } ], referral: { code: "ABCD1234", bot_link: "https://t.me/preview_bot?start=ref_uABCD1234", webapp_link: "https://minishop.app/ref/ABCD1234", invited_count: 4, purchased_count: 2, bonus_details: [{ months: 1, title: "1 месяц", inviter_days: 7, friend_days: 3 }, { months: 3, title: "3 месяца", inviter_days: 14, friend_days: 7 }] }, settings: { support_url: "https://t.me/support", traffic_mode: false, email_auth_enabled: true } } }; const demoTariffs = [ { id: "subscription", title: "Подписка", caption: "Безлимитный трафик", details: "Идеально для постоянного использования", icon: "infinity", billing: "period" }, { id: "traffic", title: "Трафик", caption: "Пакеты гигабайт", details: "Платите только за нужный объем", icon: "database", billing: "traffic" }, { id: "premium", title: "Премиум", caption: "Максимальная скорость", details: "Приоритетные серверы и поддержка", icon: "crown", billing: "period" } ]; const trafficPackages = [ { gb: 20, price: 290 }, { gb: 50, price: 590 }, { gb: 100, price: 990 }, { gb: 300, price: 2190 } ]; const changeTariffs = [ { ...demoTariffs[0], recalculation: "Доплата 190 ₽" }, { ...demoTariffs[1], recalculation: "Доплата не требуется" }, { ...demoTariffs[2], recalculation: "Доплата 390 ₽" } ]; const isPreviewBoard = new URLSearchParams(window.location.search).get("preview") === "all"; const injectedConfig = readJsonScript("webapp-config"); const isLocalShell = window.location.protocol === "file:" || [ "", "localhost", "127.0.0.1" ].includes(window.location.hostname); const MOCK = !injectedConfig && isLocalShell ? DEV_MOCK : null; const CFG = { ...DEV_MOCK.config, ...MOCK ? MOCK.config : {}, ...injectedConfig || {} }; const tg = window.Telegram && window.Telegram.WebApp ? window.Telegram.WebApp : null; let mode = /* @__PURE__ */ mutable_source(isPreviewBoard ? "preview" : "loading"); let activeTab = /* @__PURE__ */ mutable_source("home"); let screen = /* @__PURE__ */ mutable_source("home"); let data = /* @__PURE__ */ mutable_source(isPreviewBoard ? structuredCloneSafe(DEV_MOCK.data) : null); let selectedTariff = /* @__PURE__ */ mutable_source("subscription"); let selectedChangeTariff = /* @__PURE__ */ mutable_source("traffic"); let selectedPlan = /* @__PURE__ */ mutable_source(null); let selectedTrafficPackage = /* @__PURE__ */ mutable_source(trafficPackages[2]); let selectedMethod = /* @__PURE__ */ mutable_source(""); let payBusy = /* @__PURE__ */ mutable_source(false); let promoCode = /* @__PURE__ */ mutable_source(""); let promoBusy = /* @__PURE__ */ mutable_source(false); let promoStatus = /* @__PURE__ */ mutable_source(""); let promoIsError = /* @__PURE__ */ mutable_source(false); let toastText = /* @__PURE__ */ mutable_source(""); let toastTimer = null; let authMode = /* @__PURE__ */ mutable_source(CFG.emailAuthEnabled === false ? "telegram" : "email"); let authStatus = /* @__PURE__ */ mutable_source(""); let authIsError = /* @__PURE__ */ mutable_source(false); let authBusy = /* @__PURE__ */ mutable_source(false); let email = /* @__PURE__ */ mutable_source(""); let pendingEmail = /* @__PURE__ */ mutable_source(""); let emailCode = /* @__PURE__ */ mutable_source(""); let emailAvatarUrl = /* @__PURE__ */ mutable_source(""); let avatarHashToken = /* @__PURE__ */ mutable_source(""); let loginTelegramNode = /* @__PURE__ */ mutable_source(); let token = MOCK ? "local-preview" : localStorage.getItem("rw_webapp_token") || ""; let csrfToken = MOCK ? "" : readCookie("rw_webapp_csrf") || ""; let confirmTariffOpen = /* @__PURE__ */ mutable_source(false); onMount(() => { if (isPreviewBoard) return; boot(); }); function readJsonScript(id) { const node = document.getElementById(id); if (!node || !node.textContent) return null; try { return JSON.parse(node.textContent); } catch (error) { console.warn(`Failed to parse JSON config from #${id}`, error); return null; } } function structuredCloneSafe(value) { try { return structuredClone(value); } catch { return JSON.parse(JSON.stringify(value)); } } async function boot() { set(mode, "loading"); if (tg) try { tg.ready(); tg.expand(); } catch {} if (MOCK) { await loadData(); return; } const magicToken = readMagicLoginToken(); if (magicToken && await finalizeMagicLogin(magicToken)) return; if (isManuallyLoggedOut()) { showLogin(); return; } const widgetAuthData = readTelegramLoginWidgetAuthData(); if (widgetAuthData && await finalizeTelegramAuth(widgetAuthData, "auth_data")) return; if (tg?.initData) try { if (await finalizeTelegramAuth(tg.initData, "init_data")) return; } catch {} if (token || csrfToken) try { await loadData(); return; } catch { clearToken(); } showLogin(); } async function loadData() { const payload = await api("/me"); if (!payload.ok) throw new Error(payload.error || "load_failed"); set(data, payload); set(selectedPlan, payload.plans?.[Math.min(1, payload.plans.length - 1)] || payload.plans?.[0] || null); set(selectedMethod, payload.payment_methods?.[0]?.id || ""); set(screen, "home"); set(mode, "app"); } function showLogin() { set(mode, "login"); set(screen, "login"); set(activeTab, "home"); renderTelegramWidgetWhenNeeded(); } async function api(path, options = {}) { if (MOCK) return mockApi(path, options); const method = String(options.method || "GET").toUpperCase(); const headers = { ...options.headers || {} }; if (token) headers.Authorization = `Bearer ${token}`; const csrf = csrfToken || readCookie("rw_webapp_csrf") || ""; if (csrf && [ "POST", "PUT", "PATCH", "DELETE" ].includes(method)) headers["X-CSRF-Token"] = csrf; if (options.body && !headers["Content-Type"]) headers["Content-Type"] = "application/json"; const response = await fetch(`${CFG.apiBase}${path}`, { ...options, headers }); const payload = await response.json().catch(() => ({})); if (response.status === 401) { clearToken(); showLogin(); } return payload; } async function publicApi(path, payload = {}) { if (MOCK) return mockApi(path, { method: "POST", body: JSON.stringify(payload) }); return (await fetch(`${CFG.apiBase}${path}`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload) })).json(); } async function mockApi(path, options = {}) { await new Promise((resolve) => window.setTimeout(resolve, 120)); if (path === "/me") return structuredCloneSafe(DEV_MOCK.data); if (path === "/auth/email/request") return { ok: true }; if (path === "/auth/email/verify" || path === "/auth/email/magic") return { ok: true, token: "local-preview", csrf_token: "local-preview-csrf" }; if (path === "/auth/token") return { ok: true, token: "local-preview", csrf_token: "local-preview-csrf" }; if (path === "/promo/apply") return { ok: true, end_date_text: "31.05.2026" }; if (path === "/auth/logout") return { ok: true }; if (path === "/payments" && String(options.method || "").toUpperCase() === "POST") return { ok: true, action: "open_link", payment_url: "https://example.com/payment-preview", payment_id: 10001 }; return { ok: false, error: "not_found" }; } function readCookie(name) { const prefix = `${name}=`; const cookie = document.cookie.split("; ").find((part) => part.startsWith(prefix)); return cookie ? decodeURIComponent(cookie.slice(prefix.length)) : ""; } function setToken(nextToken, nextCsrf = "") { clearManualLogoutFlag(); token = nextToken || ""; csrfToken = nextCsrf || readCookie("rw_webapp_csrf") || ""; if (token && !MOCK) localStorage.setItem("rw_webapp_token", token); } function clearToken() { token = ""; csrfToken = ""; localStorage.removeItem("rw_webapp_token"); } function markManualLogout() { try { localStorage.setItem(MANUAL_LOGOUT_FLAG_KEY, "1"); } catch {} } function clearManualLogoutFlag() { try { localStorage.removeItem(MANUAL_LOGOUT_FLAG_KEY); } catch {} } function isManuallyLoggedOut() { try { return localStorage.getItem(MANUAL_LOGOUT_FLAG_KEY) === "1"; } catch { return false; } } function readReferralParam() { const params = new URLSearchParams(window.location.search); const fromQuery = params.get("ref") || params.get("start") || params.get("start_param") || ""; const fromTelegram = tg?.initDataUnsafe?.start_param || ""; const value = String(fromTelegram || fromQuery || "").trim(); if (value) { localStorage.setItem("rw_webapp_referral", value); return value; } return localStorage.getItem("rw_webapp_referral") || ""; } function readMagicLoginToken() { return (new URLSearchParams(window.location.search).get("login_token") || "").trim() || null; } function readTelegramLoginWidgetAuthData() { const params = new URLSearchParams(window.location.search); const keys = [ "id", "first_name", "last_name", "username", "photo_url", "auth_date", "hash" ]; const authData = {}; let hasAuthValue = false; keys.forEach((key) => { if (!params.has(key)) return; authData[key] = params.get(key) || ""; hasAuthValue = true; }); if (!hasAuthValue || !authData.id || !authData.auth_date || !authData.hash) return null; return authData; } function clearAuthQuery() { const url = new URL(window.location.href); [ "login_token", "login_purpose", "id", "first_name", "last_name", "username", "photo_url", "auth_date", "hash" ].forEach((key) => url.searchParams.delete(key)); window.history?.replaceState?.({}, document.title, url.pathname + url.search + url.hash); } async function finalizeMagicLogin(loginToken) { if (get(authBusy)) return false; set(authBusy, true); setAuthStatus("Проверяем вход..."); try { const payload = { token: loginToken }; const referralParam = readReferralParam(); if (referralParam) payload.referral_code = referralParam; const response = await publicApi("/auth/email/magic", payload); if (response.ok && response.token) { setToken(response.token, response.csrf_token); clearAuthQuery(); await loadData(); return true; } setAuthStatus("Не удалось подтвердить вход", true); } catch { setAuthStatus("Не удалось подтвердить вход", true); } finally { set(authBusy, false); } return false; } async function finalizeTelegramAuth(authData, source = "auth_data") { if (get(authBusy)) return false; set(authBusy, true); setAuthStatus("Проверяем Telegram..."); try { const payload = source === "init_data" ? { init_data: authData } : { auth_data: authData }; const referralParam = readReferralParam(); if (referralParam) payload.referral_code = referralParam; const response = await publicApi("/auth/token", payload); if (response.ok && response.token) { setToken(response.token, response.csrf_token); clearAuthQuery(); setAuthStatus(""); await loadData(); return true; } setAuthStatus(response.error === "banned" ? "Доступ запрещен" : "Telegram-вход не подтвержден", true); } catch { setAuthStatus("Telegram-вход сейчас недоступен", true); } finally { set(authBusy, false); } return false; } async function requestEmailCode() { const normalized = get(email).trim().toLowerCase(); if (!normalized || !normalized.includes("@")) { setAuthStatus("Введите корректный email", true); return; } set(authBusy, true); setAuthStatus("Отправляем код..."); try { const payload = { email: normalized, language: "ru" }; const referralParam = readReferralParam(); if (referralParam) payload.referral_code = referralParam; const response = await publicApi("/auth/email/request", payload); if (!response.ok) throw response; set(pendingEmail, normalized); set(emailCode, ""); set(screen, "code"); set(mode, "login"); setAuthStatus(""); } catch (error) { setAuthStatus(emailError(error, "Не удалось отправить код"), true); } finally { set(authBusy, false); } } async function verifyEmailCode() { const code = get(emailCode).replace(/\D/g, "").slice(0, 6); if (code.length !== 6) { setAuthStatus("Введите 6 цифр из письма", true); return; } set(authBusy, true); setAuthStatus("Проверяем код..."); try { const payload = { email: get(pendingEmail), code }; const referralParam = readReferralParam(); if (referralParam) payload.referral_code = referralParam; const response = await publicApi("/auth/email/verify", payload); if (!response.ok || !response.token) throw response; setToken(response.token, response.csrf_token); await loadData(); setAuthStatus(""); } catch (error) { setAuthStatus(emailError(error, "Неверный код"), true); } finally { set(authBusy, false); } } function emailError(error, fallback) { if (error?.error === "rate_limited") return `Повторная отправка через ${error.retry_after || 60} сек.`; if (error?.error === "invalid_email") return "Введите корректный email"; if (error?.error === "expired_code") return "Код устарел"; if (error?.error === "invalid_code" || error?.error === "too_many_attempts") return "Неверный код"; return fallback; } function setAuthStatus(message, isError = false) { set(authStatus, message); set(authIsError, isError); } async function renderTelegramWidgetWhenNeeded() { await tick(); if (get(authMode) !== "telegram" || !get(loginTelegramNode)) return; mutate(loginTelegramNode, get(loginTelegramNode).innerHTML = ""); if (tg?.initData) return; const botUsername = String(CFG.telegramLoginBotUsername || "").trim(); if (!botUsername) { setAuthStatus("Telegram Login Widget не настроен", true); return; } window.onTelegramAuth = async (telegramUser) => { await finalizeTelegramAuth(telegramUser, "auth_data"); }; appendTelegramLoginWidget(get(loginTelegramNode), botUsername, "onTelegramAuth", () => setAuthStatus("Telegram Login Widget сейчас недоступен", true)); } function appendTelegramLoginWidget(container, botUsername, callbackName, onUnavailable) { const script = document.createElement("script"); let unavailableShown = false; const showUnavailable = () => { if (unavailableShown) return; unavailableShown = true; onUnavailable(); }; script.async = true; script.src = TELEGRAM_LOGIN_WIDGET_URL; script.setAttribute("data-telegram-login", botUsername); script.setAttribute("data-size", "large"); script.setAttribute("data-userpic", "true"); script.setAttribute("data-request-access", "write"); script.setAttribute("data-onauth", `${callbackName}(user)`); script.onerror = showUnavailable; script.onload = () => { window.setTimeout(() => { if (!container.contains(script) || container.querySelector("iframe")) return; showUnavailable(); }, TELEGRAM_LOGIN_WIDGET_RENDER_TIMEOUT_MS); }; container.appendChild(script); } async function openTelegramLogin() { set(authMode, "telegram"); if (tg?.initData) { await finalizeTelegramAuth(tg.initData, "init_data"); return; } renderTelegramWidgetWhenNeeded(); } async function createPayment() { if (!get(selectedPlan) || !get(selectedMethod) || get(payBusy)) return; set(payBusy, true); try { const response = await api("/payments", { method: "POST", body: JSON.stringify({ months: get(selectedPlan).months, method: get(selectedMethod) }) }); if (!response.ok || !response.payment_url) throw response; showToast("Платеж создан"); openExternalLink(response.payment_url); } catch (error) { showToast(error?.message || "Не удалось создать платеж"); } finally { set(payBusy, false); } } function openExternalLink(url) { if (!url) return; if (tg?.openLink) tg.openLink(url); else window.open(url, "_blank", "noopener"); } function openConnectLink() { const url = get(subscription)?.connect_url || get(subscription)?.config_link; if (!url) { showToast("Ссылка для подключения пока недоступна"); return; } openExternalLink(url); } async function copyText(value, success = "Скопировано") { if (!value) { showToast("Пока недоступно"); return; } try { await navigator.clipboard.writeText(value); } catch { const area = document.createElement("textarea"); area.value = value; document.body.appendChild(area); area.select(); document.execCommand("copy"); area.remove(); } showToast(success); } async function applyPromo() { const code = get(promoCode).trim(); if (!code) { set(promoStatus, "Введите промокод"); set(promoIsError, true); return; } set(promoBusy, true); set(promoStatus, ""); try { const response = await api("/promo/apply", { method: "POST", body: JSON.stringify({ code }) }); if (!response.ok) throw response; set(promoCode, ""); set(promoStatus, response.end_date_text ? `Промокод активирован. Подписка до ${response.end_date_text}` : "Промокод активирован"); set(promoIsError, false); await loadData(); } catch (error) { set(promoStatus, error?.message || "Не удалось активировать промокод"); set(promoIsError, true); } finally { set(promoBusy, false); } } async function logout() { markManualLogout(); clearToken(); try { await publicApi("/auth/logout", { keepalive: true }); } catch {} showLogin(); } function showToast(message) { set(toastText, message); if (toastTimer) window.clearTimeout(toastTimer); toastTimer = window.setTimeout(() => { set(toastText, ""); }, 2400); } function goHome() { set(activeTab, "home"); set(screen, "home"); } function goInvite() { set(activeTab, "invite"); set(screen, "invite"); } function goSettings() { set(activeTab, "settings"); set(screen, "settings"); } function methodMeta(method) { const id = String(method?.id || "").toLowerCase(); if (id.includes("yookassa") || id.includes("card")) return { title: method.name || "Карта", note: "Visa, Mastercard", icon: Credit_card }; if (id.includes("platega") || id.includes("sbp")) return { title: method.name || "СБП", note: "Быстро и удобно", icon: Send }; if (id.includes("crypto")) return { title: method.name || "Криптовалюта", note: "USDT, BTC, ETH", icon: Wallet_cards }; if (id.includes("stars")) return { title: "Telegram Stars", note: "Оплата звездами", icon: Zap }; return { title: method.name || "Другие способы", note: "ЮMoney, СБП и др.", icon: Wallet_cards }; } function formatMoney(value, currency = CFG.currency || "RUB") { const numeric = Number(value || 0); return `${Number.isInteger(numeric) ? String(numeric) : numeric.toFixed(2)} ${currency === "RUB" ? "₽" : currency}`; } function trafficPercent(sub) { const used = Number(sub?.traffic_used_bytes || 0); const limit = Number(sub?.traffic_limit_bytes || 0); if (!limit || limit <= 0) return 100; return Math.max(0, Math.min(100, Math.round(used / limit * 100))); } function trafficLabel(sub) { if (!sub?.traffic_limit_bytes || Number(sub.traffic_limit_bytes) <= 0) return "Безлимитный трафик"; return `${sub.traffic_used || "0 GB"} из ${sub.traffic_limit || "0 GB"}`; } function normalizedEmail(value) { return String(value || "").trim().toLowerCase(); } function languageName(code) { const key = String(code || "").trim().toLowerCase(); if (!key) return "Русский"; return LANGUAGE_LABELS[key] || key.toUpperCase(); } function telegramName(profile) { const first = String(profile?.first_name || "").trim(); const last = String(profile?.last_name || "").trim(); if (first || last) return `${first} ${last}`.trim(); const username = String(profile?.username || "").trim(); if (username) return `@${username}`; return "Telegram не привязан"; } function bytesToHex(buffer) { return Array.from(new Uint8Array(buffer), (byte) => byte.toString(16).padStart(2, "0")).join(""); } async function sha256Hex(value) { const data = new TextEncoder().encode(value); return bytesToHex(await window.crypto.subtle.digest("SHA-256", data)); } async function buildGravatarUrl(emailValue) { if (!emailValue || !window.crypto?.subtle) return ""; try { return `https://www.gravatar.com/avatar/${await sha256Hex(emailValue)}?d=mp&s=160`; } catch { return ""; } } function tariffIcon(id) { if (id === "traffic") return Database; if (id === "premium") return Crown; return Zap; } legacy_pre_effect(() => {}, () => { set(brandTitle, CFG.title || "/minishop"); }); legacy_pre_effect(() => {}, () => { set(brandEmoji, CFG.logoEmoji || "🫥"); }); legacy_pre_effect(() => {}, () => { set(accent, CFG.primaryColor || "#00fe7a"); }); legacy_pre_effect(() => get(data), () => { set(plans, get(data)?.plans?.length ? get(data).plans : DEV_MOCK.data.plans); }); legacy_pre_effect(() => get(data), () => { set(methods, get(data)?.payment_methods?.length ? get(data).payment_methods : []); }); legacy_pre_effect(() => get(data), () => { set(subscription, get(data)?.subscription || DEV_MOCK.data.subscription); }); legacy_pre_effect(() => get(data), () => { set(user, get(data)?.user || {}); }); legacy_pre_effect(() => get(data), () => { set(referral, get(data)?.referral || DEV_MOCK.data.referral); }); legacy_pre_effect(() => get(user), () => { set(userLanguage, languageName(get(user)?.language_code || CFG.language || "ru")); }); legacy_pre_effect(() => get(user), () => { set(telegramProfileName, telegramName(get(user))); }); legacy_pre_effect(() => get(user), () => { set(profileEmail, get(user)?.email || "Почта не привязана"); }); legacy_pre_effect(() => get(user), () => { set(profileTelegramId, get(user)?.telegram_id ? `TG ID ${get(user).telegram_id}` : "TG ID не привязан"); }); legacy_pre_effect(() => (get(user), get(avatarHashToken)), () => { const emailKey = normalizedEmail(get(user)?.email); if (!emailKey) { set(avatarHashToken, ""); set(emailAvatarUrl, ""); } else if (get(avatarHashToken) !== emailKey) { set(avatarHashToken, emailKey); buildGravatarUrl(emailKey).then((url) => { if (get(avatarHashToken) === emailKey) set(emailAvatarUrl, url); }); } }); legacy_pre_effect(() => (get(user), get(emailAvatarUrl)), () => { set(profileAvatarUrl, get(user)?.telegram_photo_url || get(emailAvatarUrl) || ""); }); legacy_pre_effect(() => (get(selectedPlan), get(plans)), () => { if (!get(selectedPlan) && get(plans).length) set(selectedPlan, get(plans)[Math.min(1, get(plans).length - 1)]); }); legacy_pre_effect(() => (get(selectedMethod), get(methods)), () => { if (!get(selectedMethod) && get(methods).length) set(selectedMethod, get(methods)[0].id); }); legacy_pre_effect_reset(); init(); var fragment = comment(); head("150dgq4", ($$anchor) => { deferred_template_effect(() => { $document.title = get(brandTitle) ?? ""; }); }); var node_1 = first_child(fragment); var consequent = ($$anchor) => { PreviewBoard($$anchor, { get config() { return CFG; }, get mockData() { return untrack(() => DEV_MOCK.data); } }); }; var alternate_12 = ($$anchor) => { var div = root_3(); var node_2 = child(div); var consequent_2 = ($$anchor) => { var div_1 = root_4(); var div_2 = child(div_1); var node_3 = child(div_2); var consequent_1 = ($$anchor) => { var img = root_5(); template_effect(() => set_attribute(img, "src", untrack(() => CFG.logoUrl))); append($$anchor, img); }; var alternate = ($$anchor) => { var span = root_6(); var text = child(span, true); reset(span); template_effect(() => set_text(text, get(brandEmoji))); append($$anchor, span); }; if_block(node_3, ($$render) => { if (untrack(() => CFG.logoUrl)) $$render(consequent_1); else $$render(alternate, -1); }); reset(div_2); next(2); reset(div_1); append($$anchor, div_1); }; var consequent_9 = ($$anchor) => { var div_3 = root_7(); var node_4 = child(div_3); var consequent_4 = ($$anchor) => { var fragment_2 = root_8(); var header = first_child(fragment_2); var node_5 = child(header); Button(node_5, { variant: "icon", size: "icon", onclick: () => set(screen, "login"), "aria-label": "Назад", children: ($$anchor, $$slotProps) => { Arrow_left($$anchor, { size: 19 }); }, $$slots: { default: true } }); var div_4 = sibling(node_5, 2); var p = sibling(child(div_4), 2); var strong = sibling(child(p)); var text_1 = child(strong, true); reset(strong); reset(p); reset(div_4); next(2); reset(header); var div_5 = sibling(header, 2); var label = child(div_5); var input = child(label); remove_input_defaults(input); var span_1 = sibling(input, 2); each(span_1, 4, () => untrack(() => Array.from({ length: 6 })), index, ($$anchor, _, index) => { var span_2 = root_10(); let classes; var text_2 = child(span_2, true); reset(span_2); template_effect(() => { classes = set_class(span_2, 1, "", null, classes, { filled: get(emailCode)[index] }); set_text(text_2, (get(emailCode), untrack(() => get(emailCode)[index] || ""))); }); append($$anchor, span_2); }); reset(span_1); reset(label); var node_6 = sibling(label, 2); Button(node_6, { class: "wide", onclick: verifyEmailCode, get disabled() { return get(authBusy); }, children: ($$anchor, $$slotProps) => { next(); append($$anchor, text("Подтвердить")); }, $$slots: { default: true } }); var node_7 = sibling(node_6, 2); var consequent_3 = ($$anchor) => { var div_6 = root_12(); let classes_1; var text_4 = child(div_6, true); reset(div_6); template_effect(() => { classes_1 = set_class(div_6, 1, "status-line", null, classes_1, { error: get(authIsError) }); set_text(text_4, get(authStatus)); }); append($$anchor, div_6); }; if_block(node_7, ($$render) => { if (get(authStatus)) $$render(consequent_3); }); var button = sibling(node_7, 2); Refresh_cw(child(button), { size: 15 }); next(); reset(button); reset(div_5); template_effect(() => { set_text(text_1, get(pendingEmail)); button.disabled = get(authBusy); }); bind_value(input, () => get(emailCode), ($$value) => set(emailCode, $$value)); event("click", button, requestEmailCode); append($$anchor, fragment_2); }; var alternate_4 = ($$anchor) => { var div_7 = root_13(); var div_8 = child(div_7); var div_9 = child(div_8); var node_9 = child(div_9); var consequent_5 = ($$anchor) => { var img_1 = root_14(); template_effect(() => set_attribute(img_1, "src", untrack(() => CFG.logoUrl))); append($$anchor, img_1); }; var alternate_1 = ($$anchor) => { var span_3 = root_15(); var text_5 = child(span_3, true); reset(span_3); template_effect(() => set_text(text_5, get(brandEmoji))); append($$anchor, span_3); }; if_block(node_9, ($$render) => { if (untrack(() => CFG.logoUrl)) $$render(consequent_5); else $$render(alternate_1, -1); }); reset(div_9); var h1 = sibling(div_9, 2); var text_6 = child(h1, true); reset(h1); next(2); reset(div_8); Card(sibling(div_8, 2), { class: "auth-card", children: ($$anchor, $$slotProps) => { var fragment_4 = root_16(); var div_10 = first_child(fragment_4); var button_1 = child(div_10); let classes_2; var button_2 = sibling(button_1, 2); let classes_3; reset(div_10); var node_11 = sibling(div_10, 2); var consequent_6 = ($$anchor) => { var div_11 = root_17(); var div_12 = sibling(child(div_11), 2); var node_12 = child(div_12); Input(node_12, { type: "email", placeholder: "Email", autocomplete: "email", get value() { return get(email); }, set value($$value) { set(email, $$value); }, $$legacy: true }); Button(sibling(node_12, 2), { variant: "outline", onclick: requestEmailCode, get disabled() { return get(authBusy); }, children: ($$anchor, $$slotProps) => { var fragment_5 = root_18(); Mail(first_child(fragment_5), { size: 18 }); next(); append($$anchor, fragment_5); }, $$slots: { default: true } }); reset(div_12); reset(div_11); append($$anchor, div_11); }; var alternate_3 = ($$anchor) => { var div_13 = root_19(); var node_15 = sibling(child(div_13), 2); var consequent_7 = ($$anchor) => { Button($$anchor, { variant: "telegram", onclick: openTelegramLogin, get disabled() { return get(authBusy); }, children: ($$anchor, $$slotProps) => { var fragment_7 = root_21(); Send(first_child(fragment_7), { size: 19 }); next(); append($$anchor, fragment_7); }, $$slots: { default: true } }); }; var alternate_2 = ($$anchor) => { var div_14 = root_22(); bind_this(div_14, ($$value) => set(loginTelegramNode, $$value), () => get(loginTelegramNode)); append($$anchor, div_14); }; if_block(node_15, ($$render) => { if (untrack(() => tg?.initData)) $$render(consequent_7); else $$render(alternate_2, -1); }); reset(div_13); append($$anchor, div_13); }; if_block(node_11, ($$render) => { if (get(authMode) === "email") $$render(consequent_6); else $$render(alternate_3, -1); }); var node_17 = sibling(node_11, 2); var consequent_8 = ($$anchor) => { var div_15 = root_23(); let classes_4; var text_7 = child(div_15, true); reset(div_15); template_effect(() => { classes_4 = set_class(div_15, 1, "status-line", null, classes_4, { error: get(authIsError) }); set_text(text_7, get(authStatus)); }); append($$anchor, div_15); }; if_block(node_17, ($$render) => { if (get(authStatus)) $$render(consequent_8); }); template_effect(() => { classes_2 = set_class(button_1, 1, "", null, classes_2, { active: get(authMode) === "email" }); classes_3 = set_class(button_2, 1, "", null, classes_3, { active: get(authMode) === "telegram" }); }); event("click", button_1, () => set(authMode, "email")); event("click", button_2, openTelegramLogin); append($$anchor, fragment_4); }, $$slots: { default: true } }); next(2); reset(div_7); template_effect(() => set_text(text_6, get(brandTitle))); append($$anchor, div_7); }; if_block(node_4, ($$render) => { if (get(screen) === "code") $$render(consequent_4); else $$render(alternate_4, -1); }); reset(div_3); append($$anchor, div_3); }; var alternate_11 = ($$anchor) => { var div_16 = root_24(); var node_18 = child(div_16); var consequent_11 = ($$anchor) => { var header_1 = root_25(); var div_17 = child(header_1); var div_18 = child(div_17); var node_19 = child(div_18); var consequent_10 = ($$anchor) => { var img_2 = root_26(); template_effect(() => set_attribute(img_2, "src", untrack(() => CFG.logoUrl))); append($$anchor, img_2); }; var alternate_5 = ($$anchor) => { var span_4 = root_27(); var text_8 = child(span_4, true); reset(span_4); template_effect(() => set_text(text_8, get(brandEmoji))); append($$anchor, span_4); }; if_block(node_19, ($$render) => { if (untrack(() => CFG.logoUrl)) $$render(consequent_10); else $$render(alternate_5, -1); }); reset(div_18); var strong_1 = sibling(div_18, 2); var text_9 = child(strong_1, true); reset(strong_1); reset(div_17); reset(header_1); template_effect(() => set_text(text_9, get(brandTitle))); append($$anchor, header_1); }; if_block(node_18, ($$render) => { if (get(screen) === "invite" || get(screen) === "settings") $$render(consequent_11); }); var node_20 = sibling(node_18, 2); var consequent_13 = ($$anchor) => { var main = root_28(); var div_19 = child(main); var div_20 = child(div_19); var node_21 = child(div_20); var consequent_12 = ($$anchor) => { var img_3 = root_29(); template_effect(() => set_attribute(img_3, "src", untrack(() => CFG.logoUrl))); append($$anchor, img_3); }; var alternate_6 = ($$anchor) => { var span_5 = root_30(); var text_10 = child(span_5, true); reset(span_5); template_effect(() => set_text(text_10, get(brandEmoji))); append($$anchor, span_5); }; if_block(node_21, ($$render) => { if (untrack(() => CFG.logoUrl)) $$render(consequent_12); else $$render(alternate_6, -1); }); reset(div_20); var h1_1 = sibling(div_20, 2); var text_11 = child(h1_1, true); reset(h1_1); reset(div_19); var div_21 = sibling(div_19, 2); var node_22 = child(div_21); Card(node_22, { class: "status-card", children: ($$anchor, $$slotProps) => { var div_22 = root_31(); var node_23 = child(div_22); Circle_check(node_23, { size: 23 }); var div_23 = sibling(node_23, 2); var h2 = child(div_23); var text_12 = child(h2, true); reset(h2); var p_1 = sibling(h2, 2); var text_13 = child(p_1, true); reset(p_1); reset(div_23); reset(div_22); template_effect(() => { set_text(text_12, (get(subscription), untrack(() => get(subscription).active ? "Подписка активна" : "Подписка не активна"))); set_text(text_13, (get(subscription), untrack(() => get(subscription).end_date_text ? `до ${get(subscription).end_date_text}` : get(subscription).remaining_text))); }); append($$anchor, div_22); }, $$slots: { default: true } }); var node_24 = sibling(node_22, 2); Card(node_24, { children: ($$anchor, $$slotProps) => { var fragment_8 = root_32(); var div_24 = first_child(fragment_8); var strong_2 = sibling(child(div_24), 2); var text_14 = child(strong_2, true); reset(strong_2); reset(div_24); var div_25 = sibling(div_24, 2); var span_6 = child(div_25); reset(div_25); var div_26 = sibling(div_25, 2); var text_15 = child(div_26); reset(div_26); template_effect(($0, $1, $2) => { set_text(text_14, $0); set_style(span_6, $1); set_text(text_15, `${$2 ?? ""}%`); }, [ () => (get(subscription), untrack(() => trafficLabel(get(subscription)))), () => (get(subscription), untrack(() => `width: ${trafficPercent(get(subscription))}%`)), () => (get(subscription), untrack(() => trafficPercent(get(subscription)))) ]); append($$anchor, fragment_8); }, $$slots: { default: true } }); var div_27 = sibling(node_24, 2); var node_25 = child(div_27); Button(node_25, { class: "wide", onclick: openConnectLink, children: ($$anchor, $$slotProps) => { var fragment_9 = root_33(); Download(first_child(fragment_9), { size: 18 }); next(); append($$anchor, fragment_9); }, $$slots: { default: true } }); var node_27 = sibling(node_25, 2); Button(node_27, { variant: "secondary", class: "wide", onclick: () => set(screen, "payment"), children: ($$anchor, $$slotProps) => { var fragment_10 = root_34(); Refresh_cw(first_child(fragment_10), { size: 18 }); next(); append($$anchor, fragment_10); }, $$slots: { default: true } }); Button(sibling(node_27, 2), { variant: "secondary", class: "wide", onclick: () => set(screen, "change-tariff"), children: ($$anchor, $$slotProps) => { var fragment_11 = root_35(); Repeat_2(first_child(fragment_11), { size: 18 }); next(); append($$anchor, fragment_11); }, $$slots: { default: true } }); reset(div_27); reset(div_21); reset(main); template_effect(() => set_text(text_11, get(brandTitle))); append($$anchor, main); }; var consequent_15 = ($$anchor) => { var main_1 = root_36(); var header_2 = child(main_1); Button(child(header_2), { variant: "icon", size: "icon", onclick: goHome, "aria-label": "Назад", children: ($$anchor, $$slotProps) => { Arrow_left($$anchor, { size: 19 }); }, $$slots: { default: true } }); next(4); reset(header_2); var div_28 = sibling(header_2, 2); each(div_28, 5, () => demoTariffs, index, ($$anchor, tariff) => { var button_3 = root_38(); let classes_5; var span_7 = child(button_3); component(child(span_7), () => tariffIcon(get(tariff).id), ($$anchor, $$component) => { $$component($$anchor, { size: 25 }); }); reset(span_7); var span_8 = sibling(span_7, 2); var strong_3 = child(span_8); var text_16 = child(strong_3, true); reset(strong_3); var small = sibling(strong_3, 2); var text_17 = child(small, true); reset(small); var em = sibling(small, 2); var text_18 = child(em, true); reset(em); reset(span_8); var node_33 = sibling(span_8, 2); var consequent_14 = ($$anchor) => { Circle_check($$anchor, { size: 22 }); }; var alternate_7 = ($$anchor) => { Circle($$anchor, { size: 22 }); }; if_block(node_33, ($$render) => { if (get(selectedTariff), get(tariff), untrack(() => get(selectedTariff) === get(tariff).id)) $$render(consequent_14); else $$render(alternate_7, -1); }); reset(button_3); template_effect(() => { classes_5 = set_class(button_3, 1, "select-card", null, classes_5, { active: get(selectedTariff) === get(tariff).id }); set_text(text_16, (get(tariff), untrack(() => get(tariff).title))); set_text(text_17, (get(tariff), untrack(() => get(tariff).caption))); set_text(text_18, (get(tariff), untrack(() => get(tariff).details))); }); event("click", button_3, () => set(selectedTariff, get(tariff).id)); append($$anchor, button_3); }); reset(div_28); Button(sibling(div_28, 2), { class: "wide bottom-action", onclick: () => showToast("Тарифы пока не подключены"), children: ($$anchor, $$slotProps) => { next(); var fragment_15 = root_41(); Arrow_right(sibling(first_child(fragment_15)), { size: 18 }); append($$anchor, fragment_15); }, $$slots: { default: true } }); reset(main_1); append($$anchor, main_1); }; var consequent_19 = ($$anchor) => { var main_2 = root_42(); var header_3 = child(main_2); Button(child(header_3), { variant: "icon", size: "icon", onclick: goHome, "aria-label": "Назад", children: ($$anchor, $$slotProps) => { Arrow_left($$anchor, { size: 19 }); }, $$slots: { default: true } }); next(4); reset(header_3); var div_29 = sibling(header_3, 2); each(div_29, 5, () => get(plans), index, ($$anchor, plan) => { var button_4 = root_44(); let classes_6; var strong_4 = child(button_4); var text_19 = child(strong_4, true); reset(strong_4); var span_9 = sibling(strong_4, 2); var text_20 = child(span_9, true); reset(span_9); var node_37 = sibling(span_9, 2); var consequent_16 = ($$anchor) => { var small_1 = root_45(); var text_21 = child(small_1); reset(small_1); template_effect(($0) => set_text(text_21, `${$0 ?? ""}/мес`), [() => (get(plan), untrack(() => formatMoney(get(plan).price / get(plan).months, get(plan).currency)))]); append($$anchor, small_1); }; if_block(node_37, ($$render) => { if (get(plan), untrack(() => get(plan).months > 1)) $$render(consequent_16); }); var node_38 = sibling(node_37, 2); var consequent_17 = ($$anchor) => { Circle_check($$anchor, { size: 18 }); }; if_block(node_38, ($$render) => { if (get(selectedPlan), get(plan), untrack(() => get(selectedPlan)?.months === get(plan).months)) $$render(consequent_17); }); reset(button_4); template_effect(($0) => { classes_6 = set_class(button_4, 1, "period-card", null, classes_6, { active: get(selectedPlan)?.months === get(plan).months }); set_text(text_19, (get(plan), untrack(() => get(plan).title))); set_text(text_20, $0); }, [() => (get(plan), untrack(() => formatMoney(get(plan).price, get(plan).currency)))]); event("click", button_4, () => set(selectedPlan, get(plan))); append($$anchor, button_4); }); reset(div_29); var node_39 = sibling(div_29, 2); Card(node_39, { class: "total-card", children: ($$anchor, $$slotProps) => { var fragment_18 = root_47(); var strong_5 = sibling(first_child(fragment_18), 2); var text_22 = child(strong_5, true); reset(strong_5); template_effect(($0) => set_text(text_22, $0), [() => (get(selectedPlan), untrack(() => get(selectedPlan) ? formatMoney(get(selectedPlan).price, get(selectedPlan).currency) : "..."))]); append($$anchor, fragment_18); }, $$slots: { default: true } }); var div_30 = sibling(node_39, 2); var node_40 = child(div_30); var consequent_18 = ($$anchor) => { var fragment_19 = comment(); each(first_child(fragment_19), 1, () => get(methods), index, ($$anchor, method) => { const meta = /* @__PURE__ */ derived_safe_equal(() => (get(method), untrack(() => methodMeta(get(method))))); var button_5 = root_49(); let classes_7; var node_42 = child(button_5); component(node_42, () => get(meta).icon, ($$anchor, $$component) => { $$component($$anchor, { size: 19 }); }); var span_10 = sibling(node_42, 2); var strong_6 = child(span_10); var text_23 = child(strong_6, true); reset(strong_6); var small_2 = sibling(strong_6, 2); var text_24 = child(small_2, true); reset(small_2); reset(span_10); reset(button_5); template_effect(() => { classes_7 = set_class(button_5, 1, "method-card", null, classes_7, { active: get(selectedMethod) === get(method).id }); set_text(text_23, (deep_read_state(get(meta)), untrack(() => get(meta).title))); set_text(text_24, (deep_read_state(get(meta)), untrack(() => get(meta).note))); }); event("click", button_5, () => set(selectedMethod, get(method).id)); append($$anchor, button_5); }); append($$anchor, fragment_19); }; var alternate_8 = ($$anchor) => { Card($$anchor, { class: "empty-card", children: ($$anchor, $$slotProps) => { next(); append($$anchor, text("Способы оплаты пока не настроены")); }, $$slots: { default: true } }); }; if_block(node_40, ($$render) => { if (get(methods), untrack(() => get(methods).length)) $$render(consequent_18); else $$render(alternate_8, -1); }); reset(div_30); var node_43 = sibling(div_30, 2); { let $0 = /* @__PURE__ */ derived_safe_equal(() => (get(methods), get(payBusy), untrack(() => !get(methods).length || get(payBusy)))); Button(node_43, { class: "wide bottom-action", onclick: createPayment, get disabled() { return get($0); }, children: ($$anchor, $$slotProps) => { next(); var fragment_21 = root_52(); var text_26 = first_child(fragment_21); Lock_keyhole(sibling(text_26), { size: 17 }); template_effect(($0) => set_text(text_26, `Оплатить ${$0 ?? ""} `), [() => (get(selectedPlan), untrack(() => get(selectedPlan) ? formatMoney(get(selectedPlan).price, get(selectedPlan).currency) : ""))]); append($$anchor, fragment_21); }, $$slots: { default: true } }); } reset(main_2); append($$anchor, main_2); }; var consequent_21 = ($$anchor) => { var main_3 = root_53(); var header_4 = child(main_3); Button(child(header_4), { variant: "icon", size: "icon", onclick: goHome, "aria-label": "Назад", children: ($$anchor, $$slotProps) => { Arrow_left($$anchor, { size: 19 }); }, $$slots: { default: true } }); next(4); reset(header_4); var div_31 = sibling(header_4, 2); each(div_31, 5, () => trafficPackages, index, ($$anchor, pack) => { var button_6 = root_55(); let classes_8; var strong_7 = child(button_6); var text_27 = child(strong_7); reset(strong_7); var span_11 = sibling(strong_7, 2); var text_28 = child(span_11, true); reset(span_11); var small_3 = sibling(span_11, 2); var text_29 = child(small_3); reset(small_3); var node_46 = sibling(small_3, 2); var consequent_20 = ($$anchor) => { Circle_check($$anchor, { size: 18 }); }; if_block(node_46, ($$render) => { if (get(selectedTrafficPackage), get(pack), untrack(() => get(selectedTrafficPackage).gb === get(pack).gb)) $$render(consequent_20); }); reset(button_6); template_effect(($0, $1) => { classes_8 = set_class(button_6, 1, "period-card", null, classes_8, { active: get(selectedTrafficPackage).gb === get(pack).gb }); set_text(text_27, `${(get(pack), untrack(() => get(pack).gb)) ?? ""} ГБ`); set_text(text_28, $0); set_text(text_29, `${$1 ?? ""}/ГБ`); }, [() => (get(pack), untrack(() => formatMoney(get(pack).price))), () => (get(pack), untrack(() => formatMoney(get(pack).price / get(pack).gb)))]); event("click", button_6, () => set(selectedTrafficPackage, get(pack))); append($$anchor, button_6); }); reset(div_31); var node_47 = sibling(div_31, 2); Card(node_47, { class: "total-card", children: ($$anchor, $$slotProps) => { var fragment_24 = root_57(); var strong_8 = sibling(first_child(fragment_24), 2); var text_30 = child(strong_8, true); reset(strong_8); template_effect(($0) => set_text(text_30, $0), [() => (get(selectedTrafficPackage), untrack(() => formatMoney(get(selectedTrafficPackage).price)))]); append($$anchor, fragment_24); }, $$slots: { default: true } }); var div_32 = sibling(node_47, 2); each(div_32, 5, () => untrack(() => DEV_MOCK.data.payment_methods), index, ($$anchor, method) => { const meta = /* @__PURE__ */ derived_safe_equal(() => (get(method), untrack(() => methodMeta(get(method))))); var button_7 = root_58(); var node_48 = child(button_7); component(node_48, () => get(meta).icon, ($$anchor, $$component) => { $$component($$anchor, { size: 19 }); }); var span_12 = sibling(node_48, 2); var strong_9 = child(span_12); var text_31 = child(strong_9, true); reset(strong_9); var small_4 = sibling(strong_9, 2); var text_32 = child(small_4, true); reset(small_4); reset(span_12); reset(button_7); template_effect(() => { set_text(text_31, (deep_read_state(get(meta)), untrack(() => get(meta).title))); set_text(text_32, (deep_read_state(get(meta)), untrack(() => get(meta).note))); }); append($$anchor, button_7); }); reset(div_32); Button(sibling(div_32, 2), { class: "wide bottom-action", onclick: () => showToast("Пакеты трафика пока не подключены"), children: ($$anchor, $$slotProps) => { next(); var fragment_25 = root_59(); var text_33 = first_child(fragment_25); Lock_keyhole(sibling(text_33), { size: 17 }); template_effect(($0) => set_text(text_33, `Оплатить ${$0 ?? ""} `), [() => (get(selectedTrafficPackage), untrack(() => formatMoney(get(selectedTrafficPackage).price)))]); append($$anchor, fragment_25); }, $$slots: { default: true } }); reset(main_3); append($$anchor, main_3); }; var consequent_23 = ($$anchor) => { var main_4 = root_60(); var header_5 = child(main_4); Button(child(header_5), { variant: "icon", size: "icon", onclick: goHome, "aria-label": "Назад", children: ($$anchor, $$slotProps) => { Arrow_left($$anchor, { size: 19 }); }, $$slots: { default: true } }); next(4); reset(header_5); var div_33 = sibling(header_5, 2); each(div_33, 5, () => changeTariffs, index, ($$anchor, tariff) => { var button_8 = root_62(); let classes_9; var span_13 = child(button_8); var strong_10 = child(span_13); var text_34 = child(strong_10, true); reset(strong_10); var small_5 = sibling(strong_10, 2); var text_35 = child(small_5, true); reset(small_5); reset(span_13); var em_1 = sibling(span_13, 2); var text_36 = child(em_1, true); reset(em_1); var node_52 = sibling(em_1, 2); var consequent_22 = ($$anchor) => { Circle_check($$anchor, { size: 20 }); }; var alternate_9 = ($$anchor) => { Circle($$anchor, { size: 20 }); }; if_block(node_52, ($$render) => { if (get(selectedChangeTariff), get(tariff), untrack(() => get(selectedChangeTariff) === get(tariff).id)) $$render(consequent_22); else $$render(alternate_9, -1); }); reset(button_8); template_effect(() => { classes_9 = set_class(button_8, 1, "select-card", null, classes_9, { active: get(selectedChangeTariff) === get(tariff).id }); set_text(text_34, (get(tariff), untrack(() => get(tariff).title))); set_text(text_35, (get(tariff), untrack(() => get(tariff).caption))); set_text(text_36, (get(tariff), untrack(() => get(tariff).recalculation))); }); event("click", button_8, () => set(selectedChangeTariff, get(tariff).id)); append($$anchor, button_8); }); reset(div_33); Button(sibling(div_33, 2), { class: "wide bottom-action", onclick: () => get(selectedChangeTariff) === "traffic" ? set(confirmTariffOpen, true) : showToast("Оплата смены тарифа пока не подключена"), children: ($$anchor, $$slotProps) => { next(); var fragment_29 = root_65(); Arrow_right(sibling(first_child(fragment_29)), { size: 18 }); append($$anchor, fragment_29); }, $$slots: { default: true } }); reset(main_4); append($$anchor, main_4); }; var consequent_25 = ($$anchor) => { var main_5 = root_66(); var node_55 = child(main_5); Card(node_55, { children: ($$anchor, $$slotProps) => { var fragment_30 = root_67(); var div_34 = sibling(first_child(fragment_30), 2); var code_1 = child(div_34); var text_37 = child(code_1, true); reset(code_1); Button(sibling(code_1, 2), { onclick: () => copyText(get(referral).webapp_link || get(referral).bot_link, "Ссылка скопирована"), children: ($$anchor, $$slotProps) => { next(); var fragment_31 = root_68(); Copy(sibling(first_child(fragment_31)), { size: 17 }); append($$anchor, fragment_31); }, $$slots: { default: true } }); reset(div_34); template_effect(() => set_text(text_37, (get(referral), untrack(() => get(referral).webapp_link || get(referral).bot_link || "Ссылка пока недоступна")))); append($$anchor, fragment_30); }, $$slots: { default: true } }); var node_58 = sibling(node_55, 2); Card(node_58, { class: "bonus-card", children: ($$anchor, $$slotProps) => { var fragment_32 = root_69(); Gift(first_child(fragment_32), { size: 42 }); next(2); append($$anchor, fragment_32); }, $$slots: { default: true } }); Card(sibling(node_58, 2), { children: ($$anchor, $$slotProps) => { var fragment_33 = root_70(); var div_35 = sibling(first_child(fragment_33), 2); var node_61 = child(div_35); Input(node_61, { placeholder: "PROMO2026", get value() { return get(promoCode); }, set value($$value) { set(promoCode, $$value); }, $$legacy: true }); Button(sibling(node_61, 2), { variant: "outline", onclick: applyPromo, get disabled() { return get(promoBusy); }, children: ($$anchor, $$slotProps) => { var fragment_34 = root_71(); Ticket(first_child(fragment_34), { size: 17 }); next(); append($$anchor, fragment_34); }, $$slots: { default: true } }); reset(div_35); var node_64 = sibling(div_35, 2); var consequent_24 = ($$anchor) => { var p_2 = root_72(); let classes_10; var text_38 = child(p_2, true); reset(p_2); template_effect(() => { classes_10 = set_class(p_2, 1, "status-line", null, classes_10, { error: get(promoIsError) }); set_text(text_38, get(promoStatus)); }); append($$anchor, p_2); }; if_block(node_64, ($$render) => { if (get(promoStatus)) $$render(consequent_24); }); append($$anchor, fragment_33); }, $$slots: { default: true } }); reset(main_5); append($$anchor, main_5); }; var consequent_27 = ($$anchor) => { var main_6 = root_73(); var node_65 = child(main_6); Card(node_65, { class: "settings-profile", children: ($$anchor, $$slotProps) => { var fragment_35 = root_74(); var div_36 = first_child(fragment_35); var node_66 = child(div_36); var consequent_26 = ($$anchor) => { var img_4 = root_75(); template_effect(() => set_attribute(img_4, "src", get(profileAvatarUrl))); append($$anchor, img_4); }; var alternate_10 = ($$anchor) => { User_round($$anchor, { size: 30 }); }; if_block(node_66, ($$render) => { if (get(profileAvatarUrl)) $$render(consequent_26); else $$render(alternate_10, -1); }); reset(div_36); var div_37 = sibling(div_36, 2); var strong_11 = child(div_37); var text_39 = child(strong_11, true); reset(strong_11); var small_6 = sibling(strong_11, 2); var text_40 = child(small_6, true); reset(small_6); var small_7 = sibling(small_6, 2); var text_41 = child(small_7, true); reset(small_7); reset(div_37); template_effect(() => { set_text(text_39, get(telegramProfileName)); set_text(text_40, get(profileEmail)); set_text(text_41, get(profileTelegramId)); }); append($$anchor, fragment_35); }, $$slots: { default: true } }); var div_38 = sibling(node_65, 2); var button_9 = child(div_38); var node_67 = child(button_9); Earth(node_67, { size: 21 }); var span_14 = sibling(node_67, 2); var small_8 = sibling(child(span_14)); var text_42 = child(small_8, true); reset(small_8); reset(span_14); Arrow_right(sibling(span_14, 2), { size: 17 }); reset(button_9); var button_10 = sibling(button_9, 2); var node_69 = child(button_10); Send(node_69, { size: 21 }); var span_15 = sibling(node_69, 2); var small_9 = sibling(child(span_15)); var text_43 = child(small_9, true); reset(small_9); reset(span_15); Arrow_right(sibling(span_15, 2), { size: 17 }); reset(button_10); var button_11 = sibling(button_10, 2); var node_71 = child(button_11); Mail(node_71, { size: 21 }); var span_16 = sibling(node_71, 2); var small_10 = sibling(child(span_16)); var text_44 = child(small_10, true); reset(small_10); reset(span_16); Arrow_right(sibling(span_16, 2), { size: 17 }); reset(button_11); var button_12 = sibling(button_11, 2); var node_73 = child(button_12); User_round(node_73, { size: 21 }); Arrow_right(sibling(node_73, 4), { size: 17 }); reset(button_12); reset(div_38); reset(main_6); template_effect(() => { set_text(text_42, get(userLanguage)); set_text(text_43, (get(user), untrack(() => get(user).telegram_linked ? `@${get(user).username || "username"}` : "Не привязан"))); set_text(text_44, (get(user), untrack(() => get(user).email || "Не привязана"))); }); event("click", button_12, logout); append($$anchor, main_6); }; if_block(node_20, ($$render) => { if (get(screen) === "home") $$render(consequent_13); else if (get(screen) === "tariff-select") $$render(consequent_15, 1); else if (get(screen) === "payment") $$render(consequent_19, 2); else if (get(screen) === "traffic-payment") $$render(consequent_21, 3); else if (get(screen) === "change-tariff") $$render(consequent_23, 4); else if (get(screen) === "invite") $$render(consequent_25, 5); else if (get(screen) === "settings") $$render(consequent_27, 6); }); var node_75 = sibling(node_20, 2); var consequent_28 = ($$anchor) => { var nav = root_77(); var button_13 = child(nav); let classes_11; House(child(button_13), { size: 21 }); next(2); reset(button_13); var button_14 = sibling(button_13, 2); let classes_12; Gift(child(button_14), { size: 21 }); next(2); reset(button_14); var button_15 = sibling(button_14, 2); let classes_13; Settings(child(button_15), { size: 21 }); next(2); reset(button_15); reset(nav); template_effect(() => { classes_11 = set_class(button_13, 1, "", null, classes_11, { active: get(activeTab) === "home" }); classes_12 = set_class(button_14, 1, "", null, classes_12, { active: get(activeTab) === "invite" }); classes_13 = set_class(button_15, 1, "", null, classes_13, { active: get(activeTab) === "settings" }); }); event("click", button_13, goHome); event("click", button_14, goInvite); event("click", button_15, goSettings); append($$anchor, nav); }; if_block(node_75, ($$render) => { if (get(screen) === "home" || get(screen) === "invite" || get(screen) === "settings") $$render(consequent_28); }); reset(div_16); append($$anchor, div_16); }; if_block(node_2, ($$render) => { if (get(mode) === "loading") $$render(consequent_2); else if (get(mode) === "login") $$render(consequent_9, 1); else $$render(alternate_11, -1); }); var node_79 = sibling(node_2, 2); Dialog(node_79, { get open() { return get(confirmTariffOpen); }, title: "Сменить тариф без доплаты?", description: "Остаток 12 дней будет пересчитан по новому тарифу.", onclose: () => set(confirmTariffOpen, false), children: ($$anchor, $$slotProps) => { var div_39 = root_78(); var node_80 = child(div_39); Button(node_80, { onclick: () => { set(confirmTariffOpen, false); showToast("Смена тарифа пока не подключена"); }, children: ($$anchor, $$slotProps) => { next(); append($$anchor, text("Да, сменить")); }, $$slots: { default: true } }); Button(sibling(node_80, 2), { variant: "secondary", onclick: () => set(confirmTariffOpen, false), children: ($$anchor, $$slotProps) => { next(); append($$anchor, text("Отмена")); }, $$slots: { default: true } }); reset(div_39); append($$anchor, div_39); }, $$slots: { default: true } }); var node_82 = sibling(node_79, 2); var consequent_29 = ($$anchor) => { var div_40 = root_81(); var text_47 = child(div_40, true); reset(div_40); template_effect(() => set_text(text_47, get(toastText))); append($$anchor, div_40); }; if_block(node_82, ($$render) => { if (get(toastText)) $$render(consequent_29); }); reset(div); template_effect(() => set_style(div, `--accent: ${get(accent)};`)); append($$anchor, div); }; if_block(node_1, ($$render) => { if (isPreviewBoard) $$render(consequent); else $$render(alternate_12, -1); }); append($$anchor, fragment); pop(); } //#endregion //#region bot/app/web/frontend/src/main.js var target = document.getElementById("app"); if (target) mount(App, { target }); //#endregion })();