diff --git a/apps/tpanel/src/routes/panel/price/+page.svelte b/apps/tpanel/src/routes/panel/price/+page.svelte
index 04db53e..de4f2a2 100644
--- a/apps/tpanel/src/routes/panel/price/+page.svelte
+++ b/apps/tpanel/src/routes/panel/price/+page.svelte
@@ -1,20 +1,20 @@
{#each package_combinations as package_combination}
{@const price = get_price(package_combination)}
- {@const default_price = get_offer_price(empty_offer, package_combination)}
+ {@const default_price = get_statt_price_string(package_combination)}
- {package_combination.join(', ')} = {@html price.jahr.toFixed(2)} (default: {@html default_price.jahr.toFixed(
- 2
- )}) => {@html price.monat.toFixed(2)}
+ {package_combination.join(', ')} = {@html price.jahr.toFixed(2)}
+ {#if default_price}
+ (statt: {@html default_price})
+ {/if}, monat: {@html price.monat.toFixed(2)}
{@html get_offer_note(package_combination)}
diff --git a/packages/asset_library/assets/packages.ts b/packages/asset_library/assets/packages.ts
index 65113a4..3733cde 100644
--- a/packages/asset_library/assets/packages.ts
+++ b/packages/asset_library/assets/packages.ts
@@ -21,7 +21,8 @@ const packages_image_location = '/images/assets/packages/';
export const packages_assets = [
{
id: 'entertainment',
- price: { jahr: 16.5, monat: 19, singular: 0 },
+ // price: { jahr: 16.5, monat: 19, singular: 0 },
+ price: { jahr: 18.5, monat: 19, singular: 0 },
name: 'Entertainment',
note: 'Exklusives Entertainment ohne Ende.',
image: {
@@ -45,7 +46,8 @@ export const packages_assets = [
},
{
id: 'entertainmentplus',
- price: { jahr: 21.5, monat: 27.5, singular: 0 },
+ // price: { jahr: 21.5, monat: 27.5, singular: 0 },
+ price: { jahr: 27.5, monat: 27.5, singular: 0 },
name: 'Entertainment Plus',
note: 'Alle Sky Serien und Netflix.',
image: {
diff --git a/packages/asset_library/prices.ts b/packages/asset_library/prices.ts
index 1d51f11..f854df2 100644
--- a/packages/asset_library/prices.ts
+++ b/packages/asset_library/prices.ts
@@ -1,67 +1,49 @@
-import type { package_id } from "./assets/packages";
-import { indexed_priceable_assets } from "./priceable_asset";
-import type { Price } from "./priceable_asset_types";
-import type { priceable_asset_id } from "./asset_types";
-import {
- map_entries,
- typed_entries,
- typed_from_entries,
-} from "functional-utilities";
-import {
- clone,
- intersection as intersect,
- isEqual,
- minBy,
- sortBy,
- sum,
-} from "lodash-es";
-import {
- empty_offer,
- indexed_offers,
- offer_applicable,
- offer_ids,
-} from "./offer_description";
-import type { offer_id, offer_description_type } from "./offer_description";
-import { asset_sets } from "./sets";
-import { zubuchoption_ids } from "./assets/zubuchoptionen";
-import type { zubuchoption_id } from "./assets/zubuchoptionen";
+import type { package_id } from './assets/packages';
+import { indexed_priceable_assets } from './priceable_asset';
+import type { Price } from './priceable_asset_types';
+import type { priceable_asset_id } from './asset_types';
+import { map_entries, typed_entries, typed_from_entries } from 'functional-utilities';
+import { clone, intersection as intersect, isEqual, minBy, sortBy, sum } from 'lodash-es';
+import { empty_offer, indexed_offers, offer_applicable, offer_ids } from './offer_description';
+import type { offer_id, offer_description_type } from './offer_description';
+import { asset_sets } from './sets';
+import { zubuchoption_ids } from './assets/zubuchoptionen';
+import type { zubuchoption_id } from './assets/zubuchoptionen';
export function to_price_string(v: number, escaped: boolean = true): string {
- let str = `€${escaped ? " " : " "}` + v.toFixed(2).replace(".", ",");
- if (str.endsWith(",00")) {
+ let str = `€${escaped ? ' ' : ' '}` + v.toFixed(2).replace('.', ',');
+ if (str.endsWith(',00')) {
str = str.slice(0, -3);
}
return str;
}
+const well_defined_combinations = [
+ ['entertainment', 'sport', 'bundesliga', 'cinema'],
+ ['entertainmentplus', 'sport', 'bundesliga', 'cinema']
+] satisfies ReadonlyArray
>;
+
export const aktivierung = 0 as number;
export const aktivierung_string = to_price_string(aktivierung);
export const bonus = 20 as number;
-export const bonus_string = (escaped: boolean = true) =>
- to_price_string(bonus, escaped);
+export const bonus_string = (escaped: boolean = true) => to_price_string(bonus, escaped);
-const price_table = map_entries(indexed_priceable_assets, ([key, value]) => [
- key,
- value.price,
-]);
+const price_table = map_entries(indexed_priceable_assets, ([key, value]) => [key, value.price]);
export function get_offer_price(
offer: offer_description_type,
assets: ReadonlyArray,
- exclude_overwrite?: boolean,
+ exclude_overwrite?: boolean
): Price {
const current_price_table = clone(price_table);
for (const overwrite of offer.overwrites) {
const matches = (id: priceable_asset_id) =>
- zubuchoption_ids.includes(id as zubuchoption_id) || id === "kids";
+ zubuchoption_ids.includes(id as zubuchoption_id) || id === 'kids';
const filtered_zubuchoptionen = assets.filter(matches);
const other_assets = assets.filter((id) => !matches(id));
- if (
- isEqual(sortBy(overwrite[0]), sortBy(other_assets)) &&
- !exclude_overwrite
- ) {
+ if (isEqual(sortBy(overwrite[0]), sortBy(other_assets)) && !exclude_overwrite) {
const price = (() => {
if (isEqual(empty_offer, offer)) {
return get_offer_price(empty_offer, assets, true);
@@ -69,10 +51,7 @@ export function get_offer_price(
return get_offer_price(empty_offer, assets, false);
}
})();
- const zubuchoptionen_price = get_offer_price(
- empty_offer,
- filtered_zubuchoptionen,
- );
+ const zubuchoptionen_price = get_offer_price(empty_offer, filtered_zubuchoptionen);
for (const [timeframe, value] of typed_entries(overwrite[1])) {
price[timeframe] = value + zubuchoptionen_price[timeframe];
}
@@ -90,28 +69,51 @@ export function get_offer_price(
current_price_table[asset_id] = typed_from_entries(
typed_entries(current_price_table[asset_id]).map(([key, value]) => [
key,
- key === "jahr"
- ? operation(action.value[key], value as number)
- : value,
- ]),
+ key === 'jahr' ? operation(action.value[key], value as number) : value
+ ])
);
});
});
return typed_from_entries(
- (["singular", "monat", "jahr"] as const).map((key) => [
+ (['singular', 'monat', 'jahr'] as const).map((key) => [
key,
- sum(assets.map((asset_id) => current_price_table[asset_id][key])),
- ]),
+ sum(assets.map((asset_id) => current_price_table[asset_id][key]))
+ ])
);
}
-function chose_offer(
- assets: ReadonlyArray,
-): offer_id | undefined {
- const offers = offer_ids.filter((offer_id) =>
- offer_applicable(offer_id, assets),
- );
+function are_same_assets(
+ a: ReadonlyArray,
+ b: ReadonlyArray
+) {
+ return isEqual([...a].sort(), [...b].sort());
+}
+
+function get_statt_price(assets: ReadonlyArray): number | undefined {
+ const base_price = get_offer_price(empty_offer, assets).jahr;
+ const ideal_price = get_price(assets).jahr;
+ if (
+ ideal_price < base_price &&
+ well_defined_combinations.some((combination) => are_same_assets(assets, combination))
+ ) {
+ return base_price;
+ }
+ return undefined;
+}
+
+export function get_statt_price_string(
+ assets: ReadonlyArray
+): string | undefined {
+ const statt_price = get_statt_price(assets);
+ if (statt_price === undefined) {
+ return undefined;
+ }
+ return `${to_price_string(statt_price)}`;
+}
+
+function chose_offer(assets: ReadonlyArray): offer_id | undefined {
+ const offers = offer_ids.filter((offer_id) => offer_applicable(offer_id, assets));
if (offers.length === 0) {
return undefined;
}
@@ -119,11 +121,8 @@ function chose_offer(
(offer_id) =>
[
offer_id,
- get_offer_price(
- offer_id ? indexed_offers[offer_id] : empty_offer,
- assets,
- ),
- ] as const,
+ get_offer_price(offer_id ? indexed_offers[offer_id] : empty_offer, assets)
+ ] as const
);
const base_price = get_offer_price(empty_offer, assets);
const min = minBy(prices, ([, price]) => price.jahr);
@@ -134,11 +133,11 @@ function chose_offer(
}
export function get_price(assets: ReadonlyArray): Price {
- const chosen_offer = 'opt1'
+ const chosen_offer = 'opt1';
const offer = chosen_offer ? indexed_offers[chosen_offer] : empty_offer;
const offer_price = get_offer_price(offer, assets);
if (offer_price === undefined) {
- throw new Error("Internal Error, chose invalid offer");
+ throw new Error('Internal Error, chose invalid offer');
} else {
return offer_price;
}
@@ -147,36 +146,29 @@ export function get_price(assets: ReadonlyArray): Price {
export function get_price_string(
assets: ReadonlyArray,
subscription_time: keyof Price,
- escaped: boolean = true,
+ escaped: boolean = true
): string {
return to_price_string(get_price(assets)[subscription_time], escaped);
}
-export function sort_by_price(
- lst: ReadonlyArray,
-): Array {
+export function sort_by_price(lst: ReadonlyArray): Array {
return [...lst].sort(
- (a, b) =>
- indexed_priceable_assets[b].price.jahr -
- indexed_priceable_assets[a].price.jahr,
+ (a, b) => indexed_priceable_assets[b].price.jahr - indexed_priceable_assets[a].price.jahr
);
}
function get_offer_savings_string(
offer: offer_description_type,
- ids: ReadonlyArray,
+ ids: ReadonlyArray
): string {
const actual_savings =
- (get_offer_price(empty_offer, ids).jahr -
- get_offer_price(offer, ids).jahr) *
- 12 +
- 60;
+ (get_offer_price(empty_offer, ids).jahr - get_offer_price(offer, ids).jahr) * 12;
const overwrites: [package_id[], number][] = [
// [['entertainment', 'cinema', 'sport', 'bundesliga'], 240],
// [['entertainmentplus', 'cinema', 'sport', 'bundesliga'], 288]
];
const savings = overwrites.find(([packages]) =>
- isEqual(sort_by_price(packages), sort_by_price(ids)),
+ isEqual(sort_by_price(packages), sort_by_price(ids))
);
if (savings) {
return to_price_string(savings[1]);
@@ -184,9 +176,7 @@ function get_offer_savings_string(
return to_price_string(actual_savings);
}
-export function get_savings_string(
- ids: ReadonlyArray,
-): string {
+export function get_savings_string(ids: ReadonlyArray): string {
const chosen_offer = chose_offer(ids);
if (chosen_offer === undefined) {
return to_price_string(0);
@@ -194,19 +184,15 @@ export function get_savings_string(
return get_offer_savings_string(indexed_offers[chosen_offer], ids);
}
-export function get_offer_note(
- packages: ReadonlyArray,
- long = false,
-): string {
+export function get_offer_note(packages: ReadonlyArray, long = false): string {
const chosen_offer = chose_offer(packages);
- if (chosen_offer === undefined) {
- return "";
+ if (
+ chosen_offer !== undefined &&
+ well_defined_combinations.some((combination) => are_same_assets(packages, combination))
+ ) {
+ const offer = indexed_offers[chosen_offer];
+ const text = long ? offer.long_text : offer.short_text;
+ return text.replaceAll('{savings}', get_offer_savings_string(offer, packages));
}
- return ""
- const offer = indexed_offers[chosen_offer];
- const text = long ? offer.long_text : offer.short_text;
- return text.replaceAll(
- "{savings}",
- get_offer_savings_string(offer, packages),
- );
+ return '';
}
diff --git a/packages/components/complete/package_table.svelte b/packages/components/complete/package_table.svelte
index 3a54892..5cf2061 100644
--- a/packages/components/complete/package_table.svelte
+++ b/packages/components/complete/package_table.svelte
@@ -1,10 +1,5 @@
@@ -71,8 +70,8 @@
12 Monate nur {@html to_price_string(primary_price)} mtl.*
- {#if base_price > primary_price}
- statt {@html to_price_string(base_price)} mtl.
+ {#if base_price}
+ statt {@html base_price} mtl.
{/if}
(im Jahres-Abo, danach {@html get_price_string(price_asset_ids, 'monat')} mtl.* im Monats-Abo)
diff --git a/packages/config/global.scss b/packages/config/global.scss
index 7d0d26c..38272db 100644
--- a/packages/config/global.scss
+++ b/packages/config/global.scss
@@ -39,17 +39,16 @@ body {
@media screen and (max-width: 970px) {
.showcase_size {
- height: 950px
+ height: 950px;
}
}
@media screen and (max-width: 500px) {
.showcase_size {
- height: 1000px
+ height: 1000px;
}
}
-
$gradient-safezone: 5px;
.gradient_text {
@@ -62,12 +61,12 @@ $gradient-safezone: 5px;
.color_text {
background: linear-gradient(
- 142deg,
- rgb(253, 122, 29) 0%,
- rgb(253, 29, 29) 21%,
- rgb(194, 64, 159) 51%,
- rgb(106, 92, 186) 77%,
- rgb(29, 162, 253) 100%
+ to right,
+ rgb(245, 100, 0) 0%,
+ rgb(255, 0, 0) 25%,
+ rgb(181, 0, 125) 50%,
+ rgb(33, 66, 156) 75%,
+ rgb(0, 113, 255) 100%
);
-webkit-background-clip: text;
background-clip: text;