forked from overextended/overextended.github.io
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDisplayMembers.tsx
95 lines (76 loc) · 2.55 KB
/
DisplayMembers.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import { useState, useEffect } from 'react';
import MemberLink from './MemberLink';
interface GithubMember {
login: string;
avatar_url: string;
}
interface MemberData {
data: GithubMember[];
etag: string | null;
timestamp: number;
}
const cacheKey = 'overextendedMembers';
const cacheExpiry = 24 * 60 * 60 * 1000;
const sponsor = {
thelindat: 'thelindat',
LukeWasTakenn: 'lukewastaken',
DokaDoka: 'dokadoka',
juddisjudd: 'ohitsjudd',
jag3dagster: `jag3dagster`,
'tom-osborne': `stanocs5`,
};
const priorityOrder = ['thelindat', 'LukeWasTakenn'];
async function FetchMembers() {
const raw = localStorage.getItem(cacheKey);
const members: MemberData = raw ? JSON.parse(raw) : {};
const isCacheExpired = members.timestamp ? new Date().getTime() - members.timestamp > cacheExpiry : true;
if (!isCacheExpired) {
console.log('Using cached members data:', members.data);
return members;
}
const headers: Record<string, string> = {};
if (members.etag) headers['If-None-Match'] = members.etag;
const response = await fetch(`https://api.github.com/orgs/overextended/members`, { headers });
if (response.status === 304) return members;
members.data = await response.json();
members.etag = response.headers.get('ETag');
members.timestamp = new Date().getTime();
members.data = [
...priorityOrder
.map((login) => {
const foundMember = members.data.find((member) => member.login === login);
if (!foundMember) {
console.warn(`Member ${login} not found in API response`);
}
return foundMember;
})
.filter((member): member is GithubMember => !!member),
...members.data.filter((member) => !priorityOrder.includes(member.login)),
];
console.log('Sorted members data:', members.data);
localStorage.setItem(cacheKey, JSON.stringify(members));
console.log(`Fetched, sorted, and cached data (etag ${members.etag})`, members.timestamp);
return members;
}
const DisplayMembers = () => {
const [members, setMembers] = useState<MemberData | null>(null);
useEffect(() => {
(async () => setMembers(await FetchMembers()))();
}, []);
return (
<>
{members?.data && (
<div className="mt-4 grid grid-cols-1 place-items-center gap-16 md:grid-cols-3 lg:grid-cols-3 xl:grid-cols-4">
{members.data.map((member) =>
MemberLink({
image: member.avatar_url,
name: member.login,
sponsor: sponsor[member.login],
})
)}
</div>
)}
</>
);
};
export default DisplayMembers;