Set territory pattern on purchase (#1932)

## Description:

When purchasing a territory pattern, set it after successful purchase

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

evan
This commit is contained in:
evanpelle
2025-08-25 14:06:11 -07:00
committed by GitHub
parent 1d8484843f
commit beddcfeef6
6 changed files with 32 additions and 18 deletions
+8 -3
View File
@@ -30,7 +30,12 @@ export async function fetchPatterns(
return patterns;
}
export async function handlePurchase(priceId: string) {
export async function handlePurchase(pattern: Pattern) {
if (pattern.product === null) {
alert("This pattern is not available for purchase.");
return;
}
const response = await fetch(
`${getApiBase()}/stripe/create-checkout-session`,
{
@@ -40,8 +45,8 @@ export async function handlePurchase(priceId: string) {
authorization: getAuthHeader(),
},
body: JSON.stringify({
priceId: priceId,
successUrl: `${window.location.origin}#purchase-completed=true`,
priceId: pattern.product.priceId,
successUrl: `${window.location.origin}#purchase-completed=true&pattern=${pattern.name}`,
cancelUrl: `${window.location.origin}#purchase-completed=false`,
}),
},
+17 -8
View File
@@ -89,6 +89,7 @@ class Client {
private joinModal: JoinPrivateLobbyModal;
private publicLobby: PublicLobby;
private userSettings: UserSettings = new UserSettings();
private patternsModal: TerritoryPatternsModal;
constructor() {}
@@ -205,19 +206,19 @@ class Client {
flagInputModal.open();
});
const territoryModal = document.querySelector(
this.patternsModal = document.querySelector(
"territory-patterns-modal",
) as TerritoryPatternsModal;
const patternButton = document.getElementById(
"territory-patterns-input-preview-button",
);
territoryModal instanceof TerritoryPatternsModal;
this.patternsModal instanceof TerritoryPatternsModal;
if (patternButton === null)
throw new Error("territory-patterns-input-preview-button");
territoryModal.previewButton = patternButton;
territoryModal.refresh();
this.patternsModal.previewButton = patternButton;
this.patternsModal.refresh();
patternButton.addEventListener("click", () => {
territoryModal.open();
this.patternsModal.open();
});
loginDiscordButton.addEventListener("click", discordLogin);
@@ -303,7 +304,7 @@ class Client {
loginDiscordButton.hidden = false;
loginDiscordButton.translationKey = "main.login_discord";
logoutDiscordButton.hidden = true;
territoryModal.onUserMe(null);
this.patternsModal.onUserMe(null);
} else {
// Authorized
console.log(
@@ -312,7 +313,7 @@ class Client {
);
loginDiscordButton.translationKey = "main.logged_in";
loginDiscordButton.hidden = true;
territoryModal.onUserMe(userMeResponse);
this.patternsModal.onUserMe(userMeResponse);
}
};
@@ -429,7 +430,15 @@ class Client {
if (hash.startsWith("#")) {
const params = new URLSearchParams(hash.slice(1));
if (params.get("purchase-completed") === "true") {
alertAndStrip("purchase succeeded");
const patternName = params.get("pattern");
if (patternName === null) {
alert("Something went wrong. Please contact support.");
console.error("purchase-completed=true but no pattern name");
return;
}
alertAndStrip(`purchase succeeded: ${patternName}`);
this.userSettings.setSelectedPatternName(patternName ?? undefined);
this.patternsModal.refresh();
return;
} else if (params.get("purchase-completed") === "false") {
alertAndStrip("purchase failed");
+1 -1
View File
@@ -97,7 +97,7 @@ export class TerritoryPatternsModal extends LitElement {
<pattern-button
.pattern=${pattern}
.onSelect=${(p: Pattern | null) => this.selectPattern(p)}
.onPurchase=${(priceId: string) => handlePurchase(priceId)}
.onPurchase=${(p: Pattern) => handlePurchase(p)}
></pattern-button>
`);
}
+2 -2
View File
@@ -16,7 +16,7 @@ export class PatternButton extends LitElement {
onSelect?: (pattern: Pattern | null) => void;
@property({ type: Function })
onPurchase?: (priceId: string) => void;
onPurchase?: (pattern: Pattern) => void;
createRenderRoot() {
return this;
@@ -40,7 +40,7 @@ export class PatternButton extends LitElement {
private handlePurchase(e: Event) {
e.stopPropagation();
if (this.pattern?.product) {
this.onPurchase?.(this.pattern.product.priceId);
this.onPurchase?.(this.pattern);
}
}
+1 -1
View File
@@ -126,7 +126,7 @@ export class WinModal extends LitElement implements Layer {
<pattern-button
.pattern=${pattern}
.onSelect=${(p: Pattern | null) => {}}
.onPurchase=${(priceId: string) => handlePurchase(priceId)}
.onPurchase=${(p: Pattern) => handlePurchase(p)}
></pattern-button>
`;
}
+3 -3
View File
@@ -120,11 +120,11 @@ export class UserSettings {
return localStorage.getItem(PATTERN_KEY) ?? undefined;
}
setSelectedPatternName(base64: string | undefined): void {
if (base64 === undefined) {
setSelectedPatternName(patternName: string | undefined): void {
if (patternName === undefined) {
localStorage.removeItem(PATTERN_KEY);
} else {
localStorage.setItem(PATTERN_KEY, base64);
localStorage.setItem(PATTERN_KEY, patternName);
}
}
}