Skip to content

Commit 8914039

Browse files
committed
feat: add global ranking for ecosystems based on actors_core_total
- Implemented a ranking system for ecosystems in EcosystemsPageClient, EcosystemRank, and EcosystemManagementTable components. - Introduced useMemo hooks to create a map of ecosystem names to their global ranks, enhancing data presentation. - Updated UI to display global ranks instead of absolute indices for improved clarity and user experience.
1 parent da2e1b2 commit 8914039

4 files changed

Lines changed: 253 additions & 123 deletions

File tree

.eslintcache

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/app/ecosystems/EcosystemsPageClient.tsx

Lines changed: 73 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
'use client';
1+
"use client";
22

3-
import {
4-
Card, CardHeader, Input, Pagination,
5-
} from "@nextui-org/react";
3+
import { Card, CardHeader, Input, Pagination } from "@nextui-org/react";
64
import { Search, Warehouse, Database, Users, Code2, Zap } from "lucide-react";
75
import { useState, useMemo, useEffect } from "react";
86
import { motion, AnimatePresence } from "framer-motion";
@@ -13,7 +11,11 @@ import { EcosystemTypeFilter } from "$/ecosystem-type-filter";
1311
import type { EcoRankRecord } from "~/api/typing";
1412
import MetricCard, { type MetricCardProps } from "$/controls/metric-card";
1513
import TableHeader from "$/controls/table-header";
16-
import { staggerContainer, staggerItemScale, fadeInUp } from "@/utils/animations";
14+
import {
15+
staggerContainer,
16+
staggerItemScale,
17+
fadeInUp,
18+
} from "@/utils/animations";
1719

1820
interface EcosystemsPageProps {
1921
ecosystems: EcoRankRecord[];
@@ -43,7 +45,8 @@ function resolveMetrics(dataSource: {
4345
value: Number(dataSource.totalDevelopers).toLocaleString(),
4446
icon: <Users size={20} className="text-primary" />,
4547
iconBgClassName: "bg-primary/10",
46-
tooltip: "Developers with activity (star not included) in this ecosystem (all time)",
48+
tooltip:
49+
"Developers with activity (star not included) in this ecosystem (all time)",
4750
},
4851
{
4952
label: "Ecosystems",
@@ -75,25 +78,39 @@ export default function EcosystemsPageClient({
7578

7679
// Filtering state
7780
const [filterValue, setFilterValue] = useState("");
78-
const [selectedType, setSelectedType] = useState<EcosystemType>(EcosystemType.PUBLIC_CHAIN);
81+
const [selectedType, setSelectedType] = useState<EcosystemType>(
82+
EcosystemType.PUBLIC_CHAIN,
83+
);
7984

8085
// Reset page when ecosystem type changes
8186
useEffect(() => {
8287
setPage(1);
8388
}, [selectedType]);
8489

90+
// First, create a map of ecosystem names to their global ranks (based on actors_core_total)
91+
const ecosystemRanks = useMemo(() => {
92+
const sorted = [...ecosystems].sort((a, b) => {
93+
return Number(b.actors_core_total) - Number(a.actors_core_total);
94+
});
95+
const rankMap = new Map<string, number>();
96+
sorted.forEach((eco, index) => {
97+
rankMap.set(eco.eco_name, index + 1);
98+
});
99+
return rankMap;
100+
}, [ecosystems]);
101+
85102
// Filter ecosystems based on search query and type
86103
const filteredItems = useMemo(() => {
87104
let filtered = [...ecosystems];
88105

89106
if (filterValue) {
90-
filtered = filtered.filter(ecosystem =>
107+
filtered = filtered.filter((ecosystem) =>
91108
ecosystem.eco_name.toLowerCase().includes(filterValue.toLowerCase()),
92109
);
93110
}
94111

95112
// Filter by ecosystem type using the kind field
96-
filtered = filtered.filter(ecosystem =>
113+
filtered = filtered.filter((ecosystem) =>
97114
getFilterForType(selectedType, ecosystem.kind),
98115
);
99116

@@ -129,10 +146,12 @@ export default function EcosystemsPageClient({
129146
<div className="p-2 rounded-lg bg-primary/10">
130147
<Warehouse size={20} className="text-primary" />
131148
</div>
132-
<h1 className="text-3xl font-bold text-gray-900 dark:text-white">All Ecosystems</h1>
149+
<h1 className="text-3xl font-bold text-gray-900 dark:text-white">
150+
All Ecosystems
151+
</h1>
133152
</div>
134153
<p className="text-lg text-gray-600 dark:text-gray-300 max-w-3xl">
135-
Compare metrics across all blockchain and Web3 ecosystems
154+
Compare metrics across all blockchain and Web3 ecosystems
136155
</p>
137156
</motion.div>
138157

@@ -143,7 +162,12 @@ export default function EcosystemsPageClient({
143162
animate="visible"
144163
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 md:gap-6 mb-10"
145164
>
146-
{resolveMetrics({ totalCoreDevelopers, totalDevelopers, totalEcosystems, totalRepositories }).map((metric) => (
165+
{resolveMetrics({
166+
totalCoreDevelopers,
167+
totalDevelopers,
168+
totalEcosystems,
169+
totalRepositories,
170+
}).map((metric) => (
147171
<motion.div
148172
key={metric.label.replaceAll(" ", "")}
149173
variants={staggerItemScale}
@@ -179,26 +203,51 @@ export default function EcosystemsPageClient({
179203
<div className="p-2 rounded-lg bg-primary/10">
180204
<Warehouse size={18} className="text-primary" />
181205
</div>
182-
<h3 className="text-lg font-medium text-gray-900 dark:text-white">Ecosystem Analytics</h3>
206+
<h3 className="text-lg font-medium text-gray-900 dark:text-white">
207+
Ecosystem Analytics
208+
</h3>
183209
</div>
184210
</CardHeader>
185211

186212
<div className="overflow-x-auto">
187213
<table className="w-full">
188214
<thead>
189215
<tr className="border-t border-border dark:border-border-dark bg-surface dark:bg-surface-dark">
190-
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-500 uppercase tracking-wider w-12">#</th>
216+
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-500 uppercase tracking-wider w-12">
217+
#
218+
</th>
191219
<TableHeader>Ecosystem</TableHeader>
192-
<TableHeader align="right" tooltip="Developers with pull requests and push events in the past year">Devs</TableHeader>
193-
<TableHeader align="right" tooltip="Developers with activity (star not included) in this ecosystem (all time)">Contributors</TableHeader>
194-
<TableHeader align="right" tooltip="Developers with first activity in past 90 days">New</TableHeader>
195-
<TableHeader align="right" tooltip="Total repositories in this ecosystem">Repos</TableHeader>
220+
<TableHeader
221+
align="right"
222+
tooltip="Developers with pull requests and push events in the past year"
223+
>
224+
Devs
225+
</TableHeader>
226+
<TableHeader
227+
align="right"
228+
tooltip="Developers with activity (star not included) in this ecosystem (all time)"
229+
>
230+
Contributors
231+
</TableHeader>
232+
<TableHeader
233+
align="right"
234+
tooltip="Developers with first activity in past 90 days"
235+
>
236+
New
237+
</TableHeader>
238+
<TableHeader
239+
align="right"
240+
tooltip="Total repositories in this ecosystem"
241+
>
242+
Repos
243+
</TableHeader>
196244
</tr>
197245
</thead>
198246
<tbody className="divide-y divide-border dark:divide-border-dark">
199247
<AnimatePresence mode="wait">
200248
{paginatedItems.map((ecosystem, index) => {
201-
const absoluteIndex = (page - 1) * rowsPerPage + index + 1;
249+
const globalRank =
250+
ecosystemRanks.get(ecosystem.eco_name) || 0;
202251
return (
203252
<motion.tr
204253
key={ecosystem.eco_name}
@@ -209,8 +258,10 @@ export default function EcosystemsPageClient({
209258
>
210259
<td className="px-6 py-4 whitespace-nowrap">
211260
<div className="flex items-center">
212-
<span className={`inline-flex items-center justify-center w-7 h-7 rounded-full text-xs font-medium transition-all duration-200 group-hover:scale-110 bg-gray-50 dark:bg-surface-dark text-gray-500 dark:text-gray-500`}>
213-
{absoluteIndex}
261+
<span
262+
className={`inline-flex items-center justify-center w-7 h-7 rounded-full text-xs font-medium transition-all duration-200 group-hover:scale-110 bg-gray-50 dark:bg-surface-dark text-gray-500 dark:text-gray-500`}
263+
>
264+
{globalRank}
214265
</span>
215266
</div>
216267
</td>
@@ -252,11 +303,7 @@ export default function EcosystemsPageClient({
252303

253304
{pages > 1 && (
254305
<div className="px-6 py-4 border-t border-border dark:border-border-dark flex justify-center">
255-
<Pagination
256-
page={page}
257-
total={pages}
258-
onChange={setPage}
259-
/>
306+
<Pagination page={page} total={pages} onChange={setPage} />
260307
</div>
261308
)}
262309
</Card>

0 commit comments

Comments
 (0)