Skip to content

Commit a0ddbbd

Browse files
committed
refactor: simplify leaderboard computation by creating a generic helper function
1 parent 1b826bc commit a0ddbbd

File tree

1 file changed

+37
-48
lines changed

1 file changed

+37
-48
lines changed

frontend/src/views/Dashboard/Leaderboard/LeaderboardView.vue

Lines changed: 37 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,19 @@ import { useQuery } from "@pinia/colada";
4242
import { getAllCompanies } from "@/api/companies";
4343
import { getAllSpeakers } from "@/api/speakers";
4444
import { getAllMembers } from "@/api/members";
45-
import type { Company, CompanyParticipation } from "@/dto/companies";
46-
import type { Speaker, SpeakerParticipation } from "@/dto/speakers";
45+
import type { Company } from "@/dto/companies";
46+
import type { Speaker } from "@/dto/speakers";
4747
import type { Member } from "@/dto/members";
4848
import { useEventStore } from "@/stores/event";
4949
import LeaderboardCard from "@/components/Leaderboard/LeaderboardCard.vue";
5050
import { humanReadableParticipationStatus } from "@/dto";
5151
// icons are used inside LeaderboardCard
5252
53-
const BOT_ACCOUNTS = new Set(["ToolBot!", "zzPartnerships"]);
53+
const BOT_ACCOUNTS = new Set([
54+
"ToolBot!",
55+
"zzPartnerships",
56+
"zzPartnernerships",
57+
]);
5458
5559
const eventStore = useEventStore();
5660
const selectedStatus = ref<string>("");
@@ -105,17 +109,26 @@ function computeRanks(rows: LeaderRow[]): RankedLeaderRow[] {
105109
return ranked;
106110
}
107111
108-
const companyLeaderboard = computed<RankedLeaderRow[]>(() => {
112+
// Generic helper to build leaderboards from any collection (companies or speakers)
113+
function computeLeaderboardFrom<
114+
TItem,
115+
TParticipation extends { event?: number; status?: string; member?: unknown },
116+
>(
117+
items: TItem[],
118+
getParticipations: (it: TItem) => TParticipation[] | undefined,
119+
getName: (it: TItem) => string,
120+
botSet = BOT_ACCOUNTS,
121+
): RankedLeaderRow[] {
109122
const rows = new Map<string, LeaderRow>();
110123
const eventId = eventStore.selectedEvent?.id;
111-
const companies = (companiesData.value?.data || []) as Company[];
112-
companies.forEach((c: Company) => {
113-
(c.participations || []).forEach((p: CompanyParticipation) => {
124+
125+
items.forEach((it: TItem) => {
126+
(getParticipations(it) || []).forEach((p: TParticipation) => {
114127
if (p.event !== eventId) return;
115128
if (selectedStatus.value && p.status !== selectedStatus.value) return;
116129
if (!p.member) return;
117130
const id = p.member as string;
118-
const entry =
131+
const entry: LeaderRow =
119132
rows.get(id) ||
120133
({
121134
memberId: id,
@@ -124,7 +137,7 @@ const companyLeaderboard = computed<RankedLeaderRow[]>(() => {
124137
member: { id, name: "Unknown", img: "", sinfoid: "" } as Member,
125138
} as LeaderRow);
126139
entry.count += 1;
127-
entry.items.push(c.name);
140+
entry.items.push(getName(it));
128141
rows.set(id, entry);
129142
});
130143
});
@@ -141,52 +154,28 @@ const companyLeaderboard = computed<RankedLeaderRow[]>(() => {
141154
const filtered = arr.filter((r) => {
142155
const name = (r.member?.name || "") as string;
143156
const sinfoid = (r.member?.sinfoid || "") as string;
144-
return !BOT_ACCOUNTS.has(name) && !BOT_ACCOUNTS.has(sinfoid);
157+
return !botSet.has(name) && !botSet.has(sinfoid);
145158
});
146159
147160
return computeRanks(filtered);
161+
}
162+
163+
const companyLeaderboard = computed<RankedLeaderRow[]>(() => {
164+
const companies = (companiesData.value?.data || []) as Company[];
165+
return computeLeaderboardFrom(
166+
companies,
167+
(c: Company) => c.participations,
168+
(c: Company) => c.name,
169+
);
148170
});
149171
150172
const speakerLeaderboard = computed<RankedLeaderRow[]>(() => {
151-
const rows = new Map<string, LeaderRow>();
152-
const eventId = eventStore.selectedEvent?.id;
153173
const speakers = (speakersData.value?.data || []) as Speaker[];
154-
speakers.forEach((s: Speaker) => {
155-
(s.participations || []).forEach((p: SpeakerParticipation) => {
156-
if (p.event !== eventId) return;
157-
if (selectedStatus.value && p.status !== selectedStatus.value) return;
158-
if (!p.member) return;
159-
const id = p.member as string;
160-
const entry =
161-
rows.get(id) ||
162-
({
163-
memberId: id,
164-
count: 0,
165-
items: [] as string[],
166-
member: { id, name: "Unknown", img: "", sinfoid: "" } as Member,
167-
} as LeaderRow);
168-
entry.count += 1;
169-
entry.items.push(s.name);
170-
rows.set(id, entry);
171-
});
172-
});
173-
174-
const arr = Array.from(rows.values());
175-
arr.forEach((r) => {
176-
r.member =
177-
membersData.value?.data?.find((m: Member) => m.id === r.memberId) ||
178-
({ id: r.memberId, name: "Unknown", img: "", sinfoid: "" } as Member);
179-
});
180-
181-
// filter out bot accounts by name or sinfoid
182-
const bots = new Set(["ToolBot!", "zzPartnernerships"]);
183-
const filtered = arr.filter((r) => {
184-
const name = (r.member?.name || "") as string;
185-
const sinfoid = (r.member?.sinfoid || "") as string;
186-
return !bots.has(name) && !bots.has(sinfoid);
187-
});
188-
189-
return computeRanks(filtered);
174+
return computeLeaderboardFrom(
175+
speakers,
176+
(s: Speaker) => s.participations,
177+
(s: Speaker) => s.name,
178+
);
190179
});
191180
</script>
192181

0 commit comments

Comments
 (0)