mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 09:30:45 +00:00
Make clan tag warning clickable (#4163)
> **Before opening a PR:** discuss new features on [Discord](https://discord.gg/K9zernJB5z) first, and file bugs or small improvements as [issues](https://github.com/openfrontio/OpenFrontIO/issues/new/choose). You must be assigned to an `approved` issue — unsolicited PRs will be auto-closed. **Add approved & assigned issue number here:** Resolves #4154 ## Description: Adds a join path from reserved clan tag warnings to the clan detail modal. https://github.com/user-attachments/assets/cc0f4cb8-be8e-414a-8147-7a744069999e ## 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 ## Please put your Discord username so you can be contacted if a bug or regression is found: aotumuri
This commit is contained in:
@@ -674,7 +674,7 @@
|
||||
"tag_too_short": "Clan tag must be 2-5 alphanumeric characters.",
|
||||
"tag_too_long": "Clan tag cannot exceed 5 characters.",
|
||||
"tag_invalid_chars": "Clan tag can only contain letters and numbers.",
|
||||
"tag_not_member": "Join the {tag} clan before using its tag.",
|
||||
"tag_not_member": "Join the {tag} clan before using its tag. Click this message to join it.",
|
||||
"tag_check_failed": "Couldn't verify clan tag. Try again or remove it."
|
||||
},
|
||||
"host_modal": {
|
||||
|
||||
@@ -233,6 +233,9 @@ export async function joinClan(
|
||||
if (res.status === 429) {
|
||||
return { error: "clan_modal.error_rate_limited_generic" };
|
||||
}
|
||||
if (res.status === 401) {
|
||||
return { error: "clan_modal.sign_in_for_clans" };
|
||||
}
|
||||
if (res.status === 403) {
|
||||
const body = await res.json().catch(() => ({}));
|
||||
const b = body as { code?: string; reason?: string | null };
|
||||
|
||||
+14
-3
@@ -203,8 +203,12 @@ export class ClanModal extends BaseModal {
|
||||
});
|
||||
}
|
||||
|
||||
protected onOpen(): void {
|
||||
this.loadMyClans();
|
||||
protected onOpen(args?: Record<string, unknown>): void {
|
||||
const targetTag = typeof args?.tag === "string" ? args.tag : "";
|
||||
if (targetTag) {
|
||||
this.openDetail(targetTag.toUpperCase());
|
||||
}
|
||||
this.loadMyClans({ allowGuest: Boolean(targetTag) });
|
||||
}
|
||||
|
||||
protected onClose(): void {
|
||||
@@ -219,12 +223,19 @@ export class ClanModal extends BaseModal {
|
||||
this.gameHistoryCache = null;
|
||||
}
|
||||
|
||||
private async loadMyClans() {
|
||||
private async loadMyClans(opts: { allowGuest?: boolean } = {}) {
|
||||
this.loading = true;
|
||||
try {
|
||||
const me = await getUserMe();
|
||||
if (!this.isModalOpen) return;
|
||||
if (!me || Object.keys(me.user).length === 0) {
|
||||
if (opts.allowGuest) {
|
||||
this.myPublicId = null;
|
||||
this.myPendingRequests = [];
|
||||
this.myClanRoles = new Map();
|
||||
this.myClans = [];
|
||||
return;
|
||||
}
|
||||
window.dispatchEvent(
|
||||
new CustomEvent("show-message", {
|
||||
detail: {
|
||||
|
||||
@@ -174,18 +174,46 @@ export class UsernameInput extends LitElement {
|
||||
${this.validationError}
|
||||
</div>`
|
||||
: this.clanTagOwnershipError
|
||||
? html`<div
|
||||
id="clan-tag-validation-error"
|
||||
class="absolute top-full left-0 z-50 mt-1 px-3 py-2 text-sm font-medium border border-red-500/50 rounded-lg bg-red-900/90 text-red-200 backdrop-blur-md shadow-lg whitespace-nowrap"
|
||||
>
|
||||
${translateText(this.clanTagOwnershipError, {
|
||||
tag: this.clanTag,
|
||||
})}
|
||||
</div>`
|
||||
? this.renderClanTagOwnershipError()
|
||||
: null}
|
||||
`;
|
||||
}
|
||||
|
||||
private renderClanTagOwnershipError() {
|
||||
const content = translateText(this.clanTagOwnershipError, {
|
||||
tag: this.clanTag,
|
||||
});
|
||||
const className =
|
||||
"absolute top-full left-0 z-50 mt-1 px-3 py-2 text-sm font-medium border border-red-500/50 rounded-lg bg-red-900/90 text-red-200 backdrop-blur-md shadow-lg whitespace-nowrap";
|
||||
|
||||
if (this.clanTagOwnershipError !== "username.tag_not_member") {
|
||||
return html`<div id="clan-tag-validation-error" class=${className}>
|
||||
${content}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
const tag = this.clanTag;
|
||||
return html`<button
|
||||
id="clan-tag-validation-error"
|
||||
type="button"
|
||||
class="${className} underline decoration-red-200/50 underline-offset-2 hover:bg-red-800/90 focus:outline-none focus:ring-2 focus:ring-red-200/70"
|
||||
@click=${() => this.openClanJoinModal(tag)}
|
||||
>
|
||||
${content}
|
||||
</button>`;
|
||||
}
|
||||
|
||||
private openClanJoinModal(tag: string) {
|
||||
window.showPage?.("page-clan");
|
||||
void customElements.whenDefined("clan-modal").then(() => {
|
||||
document
|
||||
.querySelector<
|
||||
HTMLElement & { open: (args: { tag: string }) => void }
|
||||
>("clan-modal")
|
||||
?.open({ tag });
|
||||
});
|
||||
}
|
||||
|
||||
private handleClanTagChange(e: Event) {
|
||||
const input = e.target as HTMLInputElement;
|
||||
const originalValue = input.value;
|
||||
|
||||
@@ -254,6 +254,9 @@ export class ClanDetailView extends LitElement {
|
||||
try {
|
||||
const result = await joinClan(this.selectedClan.tag);
|
||||
if ("error" in result) {
|
||||
if (result.error === "clan_modal.sign_in_for_clans") {
|
||||
window.showPage?.("page-account");
|
||||
}
|
||||
showToast(
|
||||
result.reason
|
||||
? translateText(result.error, { reason: result.reason })
|
||||
|
||||
Reference in New Issue
Block a user