diff --git a/package.json b/package.json
index 6d2daf917..38dcc1d08 100644
--- a/package.json
+++ b/package.json
@@ -38,8 +38,8 @@
"csslint": "npx stylelint Synergism.css",
"csslint:fix": "npx stylelint Synergism.css --fix",
"htmllint": "npx htmlhint index.html",
- "build:esbuild": "npx esbuild src/Synergism.ts --bundle --minify --target=\"chrome58,firefox57,safari11,edge29\" --outfile=\"./dist/out.js\"",
- "watch:esbuild": "npx esbuild src/Synergism.ts --bundle --minify --target=\"chrome58,firefox57,safari11,edge29\" --outfile=\"./dist/out.js\" --watch --sourcemap",
+ "build:esbuild": "npx esbuild src/Synergism.ts --bundle --minify --target=\"chrome58,firefox57,safari11,edge29\" --outfile=\"./dist/out.js\" --define:PROD=true",
+ "watch:esbuild": "npx esbuild src/Synergism.ts --bundle --minify --target=\"chrome58,firefox57,safari11,edge29\" --outfile=\"./dist/out.js\" --watch --sourcemap --define:PROD=false",
"check:tsc": "npx -p typescript tsc",
"watch:tsc": "npx -p typescript tsc --watch",
"prepare": "husky install",
diff --git a/scripts/update-last-updated.js b/scripts/update-last-updated.js
index 4da248eda..d7fd6fe8a 100644
--- a/scripts/update-last-updated.js
+++ b/scripts/update-last-updated.js
@@ -26,14 +26,3 @@ try {
console.error(e)
process.exit(1)
}
-
-try {
- console.log('Update like prod, maaaan')
- const config = readFileSync(`${__dirname}/../src/Config.ts`, 'utf-8')
- .replace('const prod: boolean = false', 'const prod: boolean = true')
-
- writeFileSync(`${__dirname}/../src/Config.ts`, config)
-} catch (e) {
- console.log('maaaaaan that sucks!', e)
- process.exit(1)
-}
diff --git a/src/Calculate.ts b/src/Calculate.ts
index 881b2de2b..0fed84a29 100644
--- a/src/Calculate.ts
+++ b/src/Calculate.ts
@@ -2780,7 +2780,7 @@ export const calculateAscensionScore = () => {
? 1
: 0
bonusLevel += +player.singularityChallenges.oneChallengeCap.rewards.freeCorruptionLevel
-
+
// Init Arrays with challenge values :)
const challengeScoreArrays1 = [0, 8, 10, 12, 15, 20, 60, 80, 120, 180, 300]
const challengeScoreArrays2 = [0, 10, 12, 15, 20, 30, 80, 120, 180, 300, 450]
diff --git a/src/Config.ts b/src/Config.ts
index a372d0be7..b10999af2 100644
--- a/src/Config.ts
+++ b/src/Config.ts
@@ -1,3 +1,5 @@
+declare const PROD: boolean | undefined
+
export const version = '3.1.1 January 15, 2025 pt 1.4: The Bakery Update'
/**
@@ -13,4 +15,4 @@ export const lastUpdated = new Date('##LAST_UPDATED##')
/**
* CHANGE THIS ONE INSTEAD
*/
-export const prod: boolean = false
+export const prod = typeof PROD === 'undefined' ? false : PROD
diff --git a/src/PseudoCoinUpgrades.ts b/src/PseudoCoinUpgrades.ts
index adbb77ff4..30301ad27 100644
--- a/src/PseudoCoinUpgrades.ts
+++ b/src/PseudoCoinUpgrades.ts
@@ -1,6 +1,7 @@
import i18next from 'i18next'
import { displayProperLoadoutCount } from './BlueberryUpgrades'
import { corruptionLoadoutTableCreate, updateCorruptionLoadoutNames } from './Corruptions'
+import { CartTab } from './purchases/CartTab'
import { format } from './Synergism'
export type PseudoCoinUpgradeNames =
@@ -20,28 +21,6 @@ export type PseudoCoinUpgradeNames =
export type PseudoCoinUpgrades = Record
export type PseudoCoinUpgradeEffects = Record
-interface Upgrades {
- upgradeId: number
- maxLevel: number
- name: string
- description: string
- internalName: string
- level: number
- cost: number
-}
-
-interface PlayerUpgrades {
- level: number
- upgradeId: number
- internalName: PseudoCoinUpgradeNames
-}
-
-interface UpgradesResponse {
- coins: number
- upgrades: Upgrades[]
- playerUpgrades: PlayerUpgrades[]
-}
-
// TODO?: Something more robust to injections?
export const PCoinUpgrades: PseudoCoinUpgrades = {
@@ -75,8 +54,7 @@ export const PCoinUpgradeEffects: PseudoCoinUpgradeEffects = {
}
export const initializePCoinCache = async () => {
- const response = await fetch('https://synergism.cc/stripe/upgrades')
- const upgradesList = await response.json() as UpgradesResponse
+ const upgradesList = await CartTab.fetchUpgrades()
// Reset Cache
for (const key of Object.keys(PCoinUpgrades)) {
diff --git a/src/SingularityChallenges.ts b/src/SingularityChallenges.ts
index d85a8b087..9aad8f6fa 100644
--- a/src/SingularityChallenges.ts
+++ b/src/SingularityChallenges.ts
@@ -347,8 +347,7 @@ export const singularityChallengeData: Record<
singularityRequirement: (baseReq: number, completions: number) => {
if (completions < 10) {
return baseReq + 13 * completions
- }
- else {
+ } else {
return baseReq + 13 * 9 + 10 * (completions - 9)
}
},
diff --git a/src/Statistics.ts b/src/Statistics.ts
index bd75e8a59..55747cf39 100644
--- a/src/Statistics.ts
+++ b/src/Statistics.ts
@@ -1,4 +1,5 @@
import Decimal from 'break_infinity.js'
+import i18next from 'i18next'
import { DOMCacheGetOrSet } from './Cache/DOM'
import {
calculateAllCubeMultiplier,
@@ -43,9 +44,8 @@ import {
import { calculateSingularityDebuff } from './singularity'
import { format, formatTimeShort, player } from './Synergism'
import type { GlobalVariables } from './types/Synergism'
-import { Globals as G } from './Variables'
import { sumContents } from './Utility'
-import i18next from 'i18next'
+import { Globals as G } from './Variables'
const associated = new Map([
['kMisc', 'miscStats'],
@@ -1780,7 +1780,7 @@ export const loadStatisticsAmbrosiaGeneration = () => {
9: { acc: 4, desc: 'No Ambrosia Upgrades EXALT' },
10: { acc: 4, desc: 'Cube Upgrade Cx26' },
11: { acc: 4, desc: 'Cash-Grab ULTIMATE' },
- 12: { acc: 4, desc: 'Event Bonus' },
+ 12: { acc: 4, desc: 'Event Bonus' }
}
for (let i = 0; i < arr.length; i++) {
const statAGenMi = DOMCacheGetOrSet(`statAGenM${i + 1}`)
diff --git a/src/Tabs.ts b/src/Tabs.ts
index 55f75bbd6..e19d6a9f9 100644
--- a/src/Tabs.ts
+++ b/src/Tabs.ts
@@ -285,22 +285,29 @@ const subtabInfo: Record = {
},
buttonID: 'cartSubTab1'
},
+ {
+ subTabID: 'subscriptionContainer',
+ get unlocked () {
+ return isLoggedIn() || !prod
+ },
+ buttonID: 'cartSubTab2'
+ },
{
subTabID: 'upgradesContainer',
unlocked: true,
- buttonID: 'cartSubTab2'
+ buttonID: 'cartSubTab3'
},
{
subTabID: 'cartContainer',
get unlocked () {
return isLoggedIn() || !prod
},
- buttonID: 'cartSubTab3'
+ buttonID: 'cartSubTab4'
},
{
subTabID: 'merchContainer',
unlocked: true,
- buttonID: 'cartSubTab4'
+ buttonID: 'cartSubTab5'
}
]
}
diff --git a/src/UpdateVisuals.ts b/src/UpdateVisuals.ts
index 223f7aa2b..84d3b4142 100644
--- a/src/UpdateVisuals.ts
+++ b/src/UpdateVisuals.ts
@@ -1633,7 +1633,7 @@ export const visualUpdateAmbrosia = () => {
}
)
- if (player.cubeUpgrades[76] > 0) {
+ if (player.cubeUpgrades[76] > 0) {
DOMCacheGetOrSet('cubeUpgradeThresholds').style.display = 'block'
DOMCacheGetOrSet('cubeUpgradeThresholds').innerHTML = i18next.t(
'ambrosia.cubeUpgradeThresholds',
@@ -1642,8 +1642,7 @@ export const visualUpdateAmbrosia = () => {
percent: player.cubeUpgrades[76] * calculateNumberOfThresholds()
}
)
- }
- else {
+ } else {
DOMCacheGetOrSet('cubeUpgradeThresholds').style.display = 'none'
}
@@ -1656,8 +1655,7 @@ export const visualUpdateAmbrosia = () => {
luck: format(Math.min(100, player.cubeUpgradeRedBarFilled / 50), 2, true)
}
)
- }
- else {
+ } else {
DOMCacheGetOrSet('cubeUpgradeRedBarFills').style.display = 'none'
}
}
diff --git a/src/purchases/CartTab.ts b/src/purchases/CartTab.ts
index b8c21d6b9..4d8ec962c 100644
--- a/src/purchases/CartTab.ts
+++ b/src/purchases/CartTab.ts
@@ -8,20 +8,29 @@ import { setEmptyProductMap } from './CartUtil'
import { clearCheckoutTab, toggleCheckoutTab } from './CheckoutTab'
import { clearMerchSubtab, toggleMerchSubtab } from './MerchTab'
import { clearProductPage, toggleProductPage } from './ProductSubtab'
-import { clearUpgradeSubtab, toggleUpgradeSubtab } from './UpgradesSubtab'
+import { clearSubscriptionPage, toggleSubscriptionPage } from './SubscriptionsSubtab'
+import { clearUpgradeSubtab, toggleUpgradeSubtab, type UpgradesResponse } from './UpgradesSubtab'
export type Product = {
name: string
- id: number
+ id: string
price: number
coins: number
+ subscription: boolean
+ description: string
}
+export const products: Product[] = []
+export let coinProducts: Product[] = []
+export let subscriptionProducts: Product[] = []
+export let upgradeResponse: UpgradesResponse
+
const cartSubTabs = {
Coins: 0,
- Upgrades: 1,
- Checkout: 2,
- Merch: 3
+ Subscriptions: 1,
+ Upgrades: 2,
+ Checkout: 3,
+ Merch: 4
} as const
const tab = document.getElementById('pseudoCoins')!
@@ -34,9 +43,9 @@ function* yieldQuerySelectorAll (selector: string) {
}
}
-class CartTab {
+export class CartTab {
static #productsFetch: DeferredPromise | undefined
- static #products: Product[] = []
+ static #upgradesFetch: DeferredPromise | undefined
constructor () {
this.#updateSubtabs()
@@ -49,18 +58,45 @@ class CartTab {
CartTab.#productsFetch = createDeferredPromise()
+ const url = !prod ? 'https://synergism.cc/stripe/test/products' : 'https://synergism.cc/stripe/products'
+
// TODO: move this fetch to the products page.
- fetch('https://synergism.cc/stripe/products')
- .then((response) => response.json() as Promise)
- .then((products) => {
- CartTab.#products.push(...products)
- setEmptyProductMap(products)
+ fetch(url)
+ .then((response) => response.json())
+ .then((productsList: Product[]) => {
+ products.push(...productsList)
+ setEmptyProductMap(productsList)
+ coinProducts = products.filter((product) => !product.subscription)
+ subscriptionProducts = products.filter((product) => product.subscription)
+
+ // The Subscriptions do not naturally sort themselves by price
+ subscriptionProducts.sort((a, b) => a.price - b.price)
CartTab.#productsFetch?.resolve(undefined)
}, CartTab.#productsFetch.reject)
return CartTab.#productsFetch.promise
}
+ static fetchUpgrades () {
+ if (CartTab.#upgradesFetch) {
+ return CartTab.#upgradesFetch.promise
+ }
+
+ CartTab.#upgradesFetch = createDeferredPromise()
+
+ const url = !prod ? 'https://synergism.cc/stripe/test/upgrades' : 'https://synergism.cc/stripe/upgrades'
+
+ // TODO: move this fetch to the products page.
+ fetch(url)
+ .then((response) => response.json())
+ .then((upgrades: UpgradesResponse) => {
+ CartTab.#upgradesFetch!.resolve(upgrades)
+ upgradeResponse = upgrades
+ }, CartTab.#upgradesFetch.reject)
+
+ return CartTab.#upgradesFetch.promise
+ }
+
static applySubtabListeners () {
for (const [index, element] of yieldQuerySelectorAll('.subtabSwitcher button')) {
element.addEventListener('click', () => {
@@ -83,6 +119,7 @@ class CartTab {
}
clearProductPage()
+ clearSubscriptionPage()
clearUpgradeSubtab()
clearCheckoutTab()
clearMerchSubtab()
@@ -91,17 +128,28 @@ class CartTab {
case cartSubTabs.Coins:
CartTab.fetchProducts().then(() => {
if (player.subtabNumber === cartSubTabs.Coins) {
- toggleProductPage(CartTab.#products)
+ toggleProductPage()
+ }
+ })
+ break
+ case cartSubTabs.Subscriptions:
+ CartTab.fetchProducts().then(() => {
+ if (player.subtabNumber === cartSubTabs.Subscriptions) {
+ toggleSubscriptionPage()
}
})
break
case cartSubTabs.Upgrades:
- toggleUpgradeSubtab()
+ CartTab.fetchUpgrades().then(() => {
+ if (player.subtabNumber === cartSubTabs.Upgrades) {
+ toggleUpgradeSubtab()
+ }
+ })
break
case cartSubTabs.Checkout:
CartTab.fetchProducts().then(() => {
if (player.subtabNumber === cartSubTabs.Checkout) {
- toggleCheckoutTab(CartTab.#products)
+ toggleCheckoutTab()
}
})
break
diff --git a/src/purchases/CartUtil.ts b/src/purchases/CartUtil.ts
index 8e9de05c4..8bfe88800 100644
--- a/src/purchases/CartUtil.ts
+++ b/src/purchases/CartUtil.ts
@@ -1,7 +1,7 @@
import type { Product } from './CartTab'
/** A map of all products in the cart. */
-const cartMap = new Map }>()
+const cartMap = new Map }>()
/** Total number of items in the cart */
let inCart = 0
@@ -36,7 +36,7 @@ export const setEmptyProductMap = (products: Product[]) => {
}
}
-export const addToCart = (id: number) => {
+export const addToCart = (id: string) => {
const itemInCart = cartMap.get(id)!
itemInCart.quantity++
inCart++
@@ -44,7 +44,7 @@ export const addToCart = (id: number) => {
updateInCartCount()
}
-export const removeFromCart = (id: number) => {
+export const removeFromCart = (id: string) => {
const itemInCart = cartMap.get(id)!
itemInCart.quantity--
inCart--
@@ -67,7 +67,7 @@ export const getPrice = () => {
return totalPrice
}
-export const getQuantity = (id: number) => {
+export const getQuantity = (id: string) => {
return cartMap.get(id)!.quantity
}
diff --git a/src/purchases/CheckoutTab.ts b/src/purchases/CheckoutTab.ts
index 880b95ac1..a25c1e9b5 100644
--- a/src/purchases/CheckoutTab.ts
+++ b/src/purchases/CheckoutTab.ts
@@ -1,7 +1,8 @@
+import { prod } from '../Config'
import { changeSubTab, Tabs } from '../Tabs'
import { Alert, Notification } from '../UpdateHTML'
import { memoize } from '../Utility'
-import type { Product } from './CartTab'
+import { products, subscriptionProducts } from './CartTab'
import { addToCart, getPrice, getProductsInCart, getQuantity, removeFromCart } from './CartUtil'
const tab = document.querySelector('#pseudoCoins > #cartContainer')!
@@ -19,7 +20,7 @@ const formatter = Intl.NumberFormat('en-US', {
currency: 'USD'
})
-export const initializeCheckoutTab = memoize((products: Product[]) => {
+export const initializeCheckoutTab = memoize(() => {
closeCart?.addEventListener('click', () => {
changeSubTab(Tabs.Purchase, { page: 0 })
})
@@ -35,7 +36,7 @@ export const initializeCheckoutTab = memoize((products: Product[]) => {
@@ -52,14 +53,18 @@ export const initializeCheckoutTab = memoize((products: Product[]) => {
const fd = new FormData()
for (const product of getProductsInCart()) {
- fd.set(`product-${product.id}`, `${product.quantity}`)
+ fd.set(product.id, `${product.quantity}`)
}
fd.set('tosAgree', tosAgreed ? 'on' : 'off')
checkout.setAttribute('disabled', '')
- fetch('https://synergism.cc/stripe/create-checkout-session', {
+ const url = !prod
+ ? 'https://synergism.cc/stripe/test/create-checkout-session'
+ : 'https://synergism.cc/stripe/create-checkout-session'
+
+ fetch(url, {
method: 'POST',
body: fd
}).then((response) => response.json())
@@ -79,11 +84,14 @@ export const initializeCheckoutTab = memoize((products: Product[]) => {
function addItem (e: MouseEvent) {
e.preventDefault()
- const key = Number((e.target as HTMLButtonElement).closest('div[key]')?.getAttribute('key'))
+ const key = (e.target as HTMLButtonElement).closest('div[key]')?.getAttribute('key')
- if (Number.isNaN(key) || !Number.isSafeInteger(key)) {
+ if (key == null || !products.some((product) => product.id === key)) {
Alert('Stop fucking touching the html! We do server-side validation!')
return
+ } else if (subscriptionProducts.some((product) => getQuantity(product.id) !== 0)) {
+ Alert('You can only subscribe to 1 subscription tier!')
+ return
}
addToCart(key)
@@ -94,9 +102,9 @@ function addItem (e: MouseEvent) {
function removeItem (e: MouseEvent) {
e.preventDefault()
- const key = Number((e.target as HTMLButtonElement).closest('div[key]')?.getAttribute('key'))
+ const key = (e.target as HTMLButtonElement).closest('div[key]')?.getAttribute('key')
- if (Number.isNaN(key) || !Number.isSafeInteger(key)) {
+ if (key == null || !products.some((product) => product.id === key)) {
Alert('Stop fucking touching the html! We do server-side validation!')
return
}
@@ -118,7 +126,7 @@ function updateItemList () {
${product.quantity > 0 ? `x${product.quantity}` : ''}
-
+
`)).join('')
@@ -128,8 +136,8 @@ function updateItemList () {
})
}
-export const toggleCheckoutTab = (products: Product[]) => {
- initializeCheckoutTab(products)
+export const toggleCheckoutTab = () => {
+ initializeCheckoutTab()
updateTotalPriceInCart()
updateItemList()
diff --git a/src/purchases/ProductSubtab.ts b/src/purchases/ProductSubtab.ts
index 5d4738c89..f4d455b35 100644
--- a/src/purchases/ProductSubtab.ts
+++ b/src/purchases/ProductSubtab.ts
@@ -1,7 +1,7 @@
import { format } from '../Synergism'
import { Alert, Notification } from '../UpdateHTML'
import { memoize } from '../Utility'
-import type { Product } from './CartTab'
+import { coinProducts } from './CartTab'
import { addToCart } from './CartUtil'
const productContainer = document.querySelector('#pseudoCoins > #productContainer')
@@ -12,10 +12,10 @@ const formatter = Intl.NumberFormat('en-US', {
})
const clickHandler = (e: HTMLElementEventMap['click']) => {
- const productId = Number((e.target as HTMLButtonElement).getAttribute('data-id'))
+ const productId = (e.target as HTMLButtonElement).getAttribute('data-id')
const productName = (e.target as HTMLButtonElement).getAttribute('data-name')
- if (Number.isNaN(productId) || !Number.isSafeInteger(productId)) {
+ if (productId === null || !coinProducts.some((product) => product.id === productId)) {
Alert('Stop fucking touching the html! We do server-side validation!')
return
}
@@ -24,11 +24,11 @@ const clickHandler = (e: HTMLElementEventMap['click']) => {
Notification(`Added ${productName} to the cart!`)
}
-export const initializeProductPage = memoize((products: Product[]) => {
- productContainer!.innerHTML = products.map((product) => (`
+export const initializeProductPage = memoize(() => {
+ productContainer!.innerHTML = coinProducts.map((product) => (`
-
+
${product.name} [${format(product.coins)} PseudoCoins]
@@ -50,7 +50,7 @@ export const clearProductPage = () => {
productContainer!.style.display = 'none'
}
-export const toggleProductPage = (products: Product[]) => {
- initializeProductPage(products)
+export const toggleProductPage = () => {
+ initializeProductPage()
productContainer!.style.display = 'grid'
}
diff --git a/src/purchases/SubscriptionsSubtab.ts b/src/purchases/SubscriptionsSubtab.ts
new file mode 100644
index 000000000..2f9febfd2
--- /dev/null
+++ b/src/purchases/SubscriptionsSubtab.ts
@@ -0,0 +1,184 @@
+import { prod } from '../Config'
+import { Alert, Confirm, Notification } from '../UpdateHTML'
+import { memoize } from '../Utility'
+import { type Product, subscriptionProducts, upgradeResponse } from './CartTab'
+import { addToCart, getQuantity } from './CartUtil'
+
+const subscriptionsContainer = document.querySelector
('#pseudoCoins > #subscriptionsContainer')!
+const subscriptionSectionHolder = subscriptionsContainer.querySelector('#sub-section-holder')!
+
+const formatter = Intl.NumberFormat('en-US', {
+ style: 'currency',
+ currency: 'USD'
+})
+
+const tierCosts = [0, 300, 600, 1000, 2000]
+
+async function changeSubscription (productId: string, type: 'upgrade' | 'downgrade') {
+ const tier = upgradeResponse.tier
+ const existingCosts = tierCosts[tier] ?? 0
+ const newSub = subscriptionProducts.find((v) => v.id === productId)
+ const newSubPrice = newSub!.price
+ const newSubName = newSub!.name
+ const confirm = (type === 'downgrade')
+ ? await Confirm(
+ `You are downgrading to ${newSubName}, which costs ${
+ formatter.format((existingCosts - newSubPrice) / 100)
+ } less per month. New cost: ${
+ formatter.format(newSubPrice / 100)
+ } per month. Downgrading takes effect immediately!`
+ )
+ : await Confirm(
+ `You are upgrading to ${newSubName}, which costs ${
+ formatter.format((newSubPrice - existingCosts) / 100)
+ } more per month. New cost: ${formatter.format(newSubPrice / 100)} per month`
+ )
+
+ if (!confirm) {
+ return
+ }
+
+ const link = !prod
+ ? `https://synergism.cc/stripe/test/subscription/${type}`
+ : `https://synergism.cc/stripe/subscription/${type}`
+ const url = new URL(link)
+ url.searchParams.set('key', productId)
+
+ const response = await fetch(url, {
+ method: 'POST'
+ })
+ console.log(response, response.text())
+ return Alert(`You are now subscribed to ${newSubName}!`)
+}
+
+function clickHandler (this: HTMLButtonElement, e: HTMLElementEventMap['click']) {
+ const productId = (e.target as HTMLButtonElement).getAttribute('data-id')
+ const productName = (e.target as HTMLButtonElement).getAttribute('data-name')
+
+ if (productId === null || !subscriptionProducts.some((product) => product.id === productId)) {
+ Alert('Stop fucking touching the html! We do server-side validation!')
+ return
+ } else if (subscriptionProducts.some((product) => getQuantity(product.id) !== 0)) {
+ Alert('You can only subscribe to 1 subscription tier!')
+ return
+ }
+
+ if (upgradeResponse.tier !== 0) {
+ if (this.hasAttribute('data-downgrade')) {
+ changeSubscription(productId, 'downgrade')
+ return
+ } else if (this.hasAttribute('data-upgrade')) {
+ changeSubscription(productId, 'upgrade')
+ return
+ }
+ }
+
+ addToCart(productId)
+ Notification(`Added ${productName} to the cart!`)
+}
+
+const constructDescriptions = (description: string) => {
+ const [firstLine, secondLine] = description.split(' and ')
+ // capitalize the first letter of the second line
+ const secondLineCap = secondLine.charAt(0).toUpperCase() + secondLine.slice(1)
+
+ return `${firstLine}
+
+ ${secondLineCap}`
+}
+
+export const createIndividualSubscriptionHTML = (product: Product, existingCosts: number) => {
+ if (product.price < existingCosts) {
+ return `
+
+
+
+
+ ${product.name.split(' - ').join('
')}
+
+
+ ${constructDescriptions(product.description)}
+
+
+
+
+ `
+ } else if (product.price === existingCosts) {
+ return `
+
+
+
+
+ ${product.name.split(' - ').join('
')}
+
+
+ ${constructDescriptions(product.description)}
+
+
+
+
+ `
+ } else {
+ return `
+
+
+
+
+ ${product.name.split(' - ').join('
')}
+
+
+ ${constructDescriptions(product.description)}
+
+
+
+
+ `
+ }
+}
+
+export const initializeSubscriptionPage = memoize(() => {
+ // Manage subscription button
+ {
+ const form = document.createElement('form')
+ form.action = !prod
+ ? 'https://synergism.cc/stripe/test/manage-subscription'
+ : 'https://synergism.cc/stripe/manage-subscription'
+
+ const submit = document.createElement('input')
+ submit.type = 'submit'
+ submit.value = 'Manage Subscription'
+ form.appendChild(submit)
+
+ subscriptionsContainer.prepend(form)
+ }
+
+ const tier = upgradeResponse.tier
+ const existingCosts = tierCosts[tier] ?? 0
+
+ subscriptionSectionHolder.innerHTML = subscriptionProducts.map((product) =>
+ createIndividualSubscriptionHTML(product, existingCosts)
+ ).join('')
+
+ subscriptionSectionHolder!.style.display = 'grid'
+
+ document.querySelectorAll('.subscriptionContainer > div > button[data-id]').forEach(
+ (element) => {
+ element.addEventListener('click', clickHandler)
+ }
+ )
+})
+
+export const clearSubscriptionPage = () => {
+ subscriptionsContainer.style.display = 'none'
+}
+
+export const toggleSubscriptionPage = () => {
+ initializeSubscriptionPage()
+ subscriptionsContainer.style.display = 'flex'
+}
diff --git a/src/purchases/UpgradesSubtab.ts b/src/purchases/UpgradesSubtab.ts
index f9bec6860..be1e63ab6 100644
--- a/src/purchases/UpgradesSubtab.ts
+++ b/src/purchases/UpgradesSubtab.ts
@@ -9,6 +9,7 @@ import {
} from '../PseudoCoinUpgrades'
import { Alert } from '../UpdateHTML'
import { memoize } from '../Utility'
+import { upgradeResponse } from './CartTab'
interface Upgrades {
upgradeId: number
@@ -32,10 +33,11 @@ type UpgradesList = Omit & {
playerLevel: number
}
-interface UpgradesResponse {
+export interface UpgradesResponse {
coins: number
upgrades: Upgrades[]
playerUpgrades: PlayerUpgrades[]
+ tier: number
}
interface CoinsResponse {
@@ -137,67 +139,62 @@ async function purchaseUpgrade (upgrades: Map) {
}
const initializeUpgradeSubtab = memoize(() => {
- ;(async () => {
- const response = await fetch('https://synergism.cc/stripe/upgrades')
- const upgradesList = await response.json() as UpgradesResponse
-
- DOMCacheGetOrSet('currentCoinBalance').innerHTML = `${
- i18next.t('pseudoCoins.coinCount', { amount: Intl.NumberFormat().format(upgradesList.coins) })
- }`
- const grouped = upgradesList.upgrades.reduce((map, upgrade) => {
- const current = map.get(upgrade.upgradeId)
- const playerUpgrade = upgradesList.playerUpgrades.find((v) => v.upgradeId === upgrade.upgradeId)
-
- if (!current) {
- map.set(upgrade.upgradeId, {
- ...upgrade,
- cost: [upgrade.cost],
- level: [upgrade.level],
- playerLevel: playerUpgrade?.level ?? 0
- })
- } else {
- current.maxLevel = Math.max(current.maxLevel, upgrade.maxLevel)
- current.cost.push(upgrade.cost)
- current.level.push(upgrade.level)
+ DOMCacheGetOrSet('currentCoinBalance').innerHTML = `${
+ i18next.t('pseudoCoins.coinCount', { amount: Intl.NumberFormat().format(upgradeResponse.coins) })
+ }`
+ const grouped = upgradeResponse.upgrades.reduce((map, upgrade) => {
+ const current = map.get(upgrade.upgradeId)
+ const playerUpgrade = upgradeResponse.playerUpgrades.find((v) => v.upgradeId === upgrade.upgradeId)
+
+ if (!current) {
+ map.set(upgrade.upgradeId, {
+ ...upgrade,
+ cost: [upgrade.cost],
+ level: [upgrade.level],
+ playerLevel: playerUpgrade?.level ?? 0
+ })
+ } else {
+ current.maxLevel = Math.max(current.maxLevel, upgrade.maxLevel)
+ current.cost.push(upgrade.cost)
+ current.level.push(upgrade.level)
+ }
+
+ return map
+ }, new Map())
+
+ tab.querySelector('#upgradeGrid')!.innerHTML = [...grouped.values()].map((u) => `
+
+
+
${u.playerLevel}/${u.maxLevel}
+ ${u.playerLevel === u.maxLevel ? '
✔️
' : '
'}
+
+ `).join('')
+
+ const upgradesInGrid = tab.querySelectorAll('#upgradeGrid > div[data-id]')
+ upgradesInGrid.forEach((element) => {
+ element.addEventListener('click', (e) => {
+ const upgradeId = Number((e.target as HTMLElement).closest('div')?.getAttribute('data-id'))
+
+ if (Number.isNaN(upgradeId) || !Number.isSafeInteger(upgradeId)) {
+ Alert('Stop touching the fucking html! We do server-side validations!')
+ return
}
- return map
- }, new Map())
-
- tab.querySelector('#upgradeGrid')!.innerHTML = [...grouped.values()].map((u) => `
-
-
-
${u.playerLevel}/${u.maxLevel}
- ${u.playerLevel === u.maxLevel ? '
✔️
' : '
'}
-
- `).join('')
-
- const upgradesInGrid = tab.querySelectorAll('#upgradeGrid > div[data-id]')
- upgradesInGrid.forEach((element) => {
- element.addEventListener('click', (e) => {
- const upgradeId = Number((e.target as HTMLElement).closest('div')?.getAttribute('data-id'))
-
- if (Number.isNaN(upgradeId) || !Number.isSafeInteger(upgradeId)) {
- Alert('Stop touching the fucking html! We do server-side validations!')
- return
- }
-
- setActiveUpgrade([...grouped.values()].find((u) => u.upgradeId === upgradeId))
-
- // Setting an active class here turns the border white due to a CSS rule
- upgradesInGrid.forEach((u) => u.classList.remove('active'))
- element.classList.add('active')
- })
- })
+ setActiveUpgrade([...grouped.values()].find((u) => u.upgradeId === upgradeId))
- DOMCacheGetOrSet('buy').addEventListener('click', () => {
- purchaseUpgrade(grouped)
+ // Setting an active class here turns the border white due to a CSS rule
+ upgradesInGrid.forEach((u) => u.classList.remove('active'))
+ element.classList.add('active')
})
- })()
+ })
+
+ DOMCacheGetOrSet('buy').addEventListener('click', () => {
+ purchaseUpgrade(grouped)
+ })
})
export const toggleUpgradeSubtab = () => {
diff --git a/src/singularity.ts b/src/singularity.ts
index d0875f848..349a4868c 100644
--- a/src/singularity.ts
+++ b/src/singularity.ts
@@ -1945,7 +1945,7 @@ export const singularityPerks: SingularityPerk[] = [
218,
228,
238,
- 248,
+ 248
],
description: (n: number, levels: number[]) => {
for (let i = levels.length - 1; i >= 0; i--) {
diff --git a/translations/en.json b/translations/en.json
index 8aa2c5176..f42405c7f 100644
--- a/translations/en.json
+++ b/translations/en.json
@@ -2537,6 +2537,7 @@
},
"pseudocoins": {
"buy": "Purchase Coins",
+ "subscriptions": "Subscriptions",
"upgrades": "Buy Upgrades",
"merch": "Purchase Merch"
}