Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion resources/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@
"role_officer": "Officer",
"save_changes": "Save Changes",
"saving": "Saving...",
"search_members_placeholder": "Filter current page by ID or role...",
"search_members_placeholder": "Search by exact ID, username, or role...",
"search_placeholder": "Search by clan tag...",
"search_requests_placeholder": "Search by player public ID...",
"select_new_leader": "Select a new leader",
Expand Down
3 changes: 3 additions & 0 deletions src/client/ClanApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,13 +194,16 @@ export async function fetchClanMembers(
limit = 20,
sort: ClanMemberSort = "default",
order?: ClanMemberOrder,
search?: string,
): Promise<ClanMembersResponse | false> {
try {
const params = new URLSearchParams();
params.set("page", String(page));
params.set("limit", String(limit));
if (sort !== "default") params.set("sort", sort);
if (order) params.set("order", order);
const normalizedSearch = search?.trim();
if (normalizedSearch) params.set("search", normalizedSearch);
const res = await clanFetch(
`/clans/${encodeURIComponent(tag)}/members?${params}`,
);
Expand Down
37 changes: 24 additions & 13 deletions src/client/components/clan/ClanDetailView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,25 +237,35 @@ export class ClanDetailView extends LitElement {
}
}

private async loadMemberPage(page: number) {
private async loadMemberPage(page: number, search = this.memberSearch) {
if (!this.selectedClan) return;
const res = await fetchClanMembers(
this.selectedClan.tag,
page,
this.membersPerPage,
this.memberSort,
this.memberOrder,
);
const res = search
? await fetchClanMembers(
this.selectedClan.tag,
page,
this.membersPerPage,
this.memberSort,
this.memberOrder,
search,
)
: await fetchClanMembers(
this.selectedClan.tag,
page,
this.membersPerPage,
this.memberSort,
this.memberOrder,
);
if (search !== this.memberSearch) return;
Comment thread
ryanbarlow97 marked this conversation as resolved.
Outdated
if (!res) return;
if (res.results.length === 0 && page > 1) {
await this.loadMemberPage(1);
await this.loadMemberPage(1, search);
return;
}
this.members = res.results;
this.membersTotal = res.total;
this.memberPage = page;
this.pendingRequestCount = res.pendingRequests ?? 0;
if (this.selectedClan.memberCount !== res.total) {
if (!search && this.selectedClan.memberCount !== res.total) {
this.selectedClan = { ...this.selectedClan, memberCount: res.total };
}
}
Expand Down Expand Up @@ -344,11 +354,12 @@ export class ClanDetailView extends LitElement {
}

private onSearchInput(e: Event) {
const val = (e.target as HTMLInputElement).value;
const search = (e.target as HTMLInputElement).value.trim();
if (this.memberSearchDebounce) clearTimeout(this.memberSearchDebounce);
this.memberSearchDebounce = setTimeout(() => {
this.memberSearch = val;
this.requestUpdate();
if (search === this.memberSearch) return;
this.memberSearch = search;
void this.loadMemberPage(1, search);
Comment thread
ryanbarlow97 marked this conversation as resolved.
Outdated
}, 200);
}

Expand Down
40 changes: 28 additions & 12 deletions src/client/components/clan/ClanManageView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,28 +77,42 @@ export class ClanManageView extends LitElement {
super.disconnectedCallback();
}

private async loadMembers(page: number) {
private async loadMembers(page: number, search = this.memberSearch) {
if (this.members.length === 0) this.loading = true;
const res = await fetchClanMembers(
this.clanTag,
page,
this.membersPerPage,
this.memberSort,
this.memberOrder,
);
const res = search
? await fetchClanMembers(
this.clanTag,
page,
this.membersPerPage,
this.memberSort,
this.memberOrder,
search,
)
: await fetchClanMembers(
this.clanTag,
page,
this.membersPerPage,
this.memberSort,
this.memberOrder,
);
if (search !== this.memberSearch) return;
if (!res) {
this.loading = false;
return;
}
if (res.results.length === 0 && page > 1) {
await this.loadMembers(1);
await this.loadMembers(1, search);
return;
}
this.members = res.results;
this.membersTotal = res.total;
this.memberPage = page;
this.pendingRequestCount = res.pendingRequests ?? 0;
if (this.selectedClan && this.selectedClan.memberCount !== res.total) {
if (
!search &&
this.selectedClan &&
this.selectedClan.memberCount !== res.total
) {
this.dispatchEvent(
new CustomEvent("clan-updated", {
detail: { memberCount: res.total },
Expand Down Expand Up @@ -254,10 +268,12 @@ export class ClanManageView extends LitElement {
}

private onSearchInput(e: Event) {
const search = (e.target as HTMLInputElement).value.trim();
if (this.memberSearchDebounce) clearTimeout(this.memberSearchDebounce);
this.memberSearchDebounce = setTimeout(() => {
this.memberSearch = (e.target as HTMLInputElement).value;
this.requestUpdate();
if (search === this.memberSearch) return;
this.memberSearch = search;
void this.loadMembers(1, search);
Comment thread
ryanbarlow97 marked this conversation as resolved.
Outdated
}, 200);
}

Expand Down
24 changes: 18 additions & 6 deletions src/client/components/clan/ClanTransferView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,25 @@ export class ClanTransferView extends LitElement {
super.disconnectedCallback();
}

private async loadMembers(page: number) {
if (page === 1) this.loading = true;
const res = await fetchClanMembers(this.clanTag, page, this.membersPerPage);
private async loadMembers(page: number, search = this.memberSearch) {
if (this.members.length === 0) this.loading = true;
const res = search
? await fetchClanMembers(
this.clanTag,
page,
this.membersPerPage,
"default",
undefined,
search,
)
: await fetchClanMembers(this.clanTag, page, this.membersPerPage);
if (search !== this.memberSearch) return;
if (!res) {
this.loading = false;
return;
}
if (res.results.length === 0 && page > 1) {
await this.loadMembers(1);
await this.loadMembers(1, search);
return;
}
this.members = res.results;
Expand Down Expand Up @@ -98,10 +108,12 @@ export class ClanTransferView extends LitElement {
}

private onSearchInput(e: Event) {
const search = (e.target as HTMLInputElement).value.trim();
if (this.memberSearchDebounce) clearTimeout(this.memberSearchDebounce);
this.memberSearchDebounce = setTimeout(() => {
this.memberSearch = (e.target as HTMLInputElement).value;
this.requestUpdate();
if (search === this.memberSearch) return;
this.memberSearch = search;
void this.loadMembers(1, search);
}, 200);
}

Expand Down
18 changes: 18 additions & 0 deletions tests/client/clan/ClanApiQueries.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,24 @@ describe("fetchClanMembers", () => {
expect(url.searchParams.get("limit")).toBe("50");
});

it("passes a trimmed member search with pagination and sorting", async () => {
const fetchSpy = vi.fn(
(_input: string | URL | Request, _init?: RequestInit) =>
Promise.resolve(okJson(membersResponse)),
);
vi.stubGlobal("fetch", fetchSpy);

await fetchClanMembers("TEST", 3, 50, "winsTotal", "desc", " d3G1QO8Z ");

const calledUrl = fetchSpy.mock.calls[0]![0] as string;
const url = new URL(calledUrl);
expect(url.searchParams.get("page")).toBe("3");
expect(url.searchParams.get("limit")).toBe("50");
expect(url.searchParams.get("sort")).toBe("winsTotal");
expect(url.searchParams.get("order")).toBe("desc");
expect(url.searchParams.get("search")).toBe("d3G1QO8Z");
});

it("includes the optional pendingRequests field", async () => {
mockFetch(() => okJson({ ...membersResponse, pendingRequests: 5 }));
const result = await fetchClanMembers("TEST");
Expand Down
Loading
Loading