The weeb for the next gen discord boat - Wamellow wamellow.com
bot discord
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: dynamic donors (#68)

* feat: dynamic donors

* fix: personalize comment avatar alt text

authored by

Luna Seemann and committed by
GitHub
8a9bb172 03212fef

+53 -87
+15
app/(home)/team/api.ts
··· 1 + import { defaultFetchOptions } from "@/lib/api"; 2 + import type { ApiError } from "@/typings"; 3 + 4 + export async function getBillingDonators(): Promise<string[] | ApiError | null> { 5 + const res = await fetch( 6 + `${process.env.NEXT_PUBLIC_API}/billing/donations/donors`, 7 + { 8 + ...defaultFetchOptions, 9 + next: { revalidate: 60 } 10 + } 11 + ); 12 + 13 + if (!res.ok) return null; 14 + return res.json(); 15 + }
+1 -71
app/(home)/team/constants.ts
··· 16 16 Donator = "donator" 17 17 } 18 18 19 - export const members = [ 19 + export const developers = [ 20 20 { 21 21 id: "821472922140803112", 22 22 team: TeamType.Developer, 23 23 social: "https://ko-fi.com/mwlica" 24 24 }, 25 - 26 25 { 27 26 id: "362224559459532800", 28 27 team: TeamType.AdditionalProgramming, ··· 32 31 id: "903534295652663326", 33 32 team: TeamType.AdditionalProgramming, 34 33 social: "https://ismcserver.online" 35 - }, 36 - 37 - { 38 - id: "301482272497074189", 39 - team: TeamType.Donator 40 - }, 41 - { 42 - id: "797012765352001557", 43 - team: TeamType.Donator, 44 - social: "https://crni.xyz" 45 - }, 46 - { 47 - id: "1044032607207301160", 48 - team: TeamType.Donator, 49 - social: "https://notifyme.bot" 50 - }, 51 - { 52 - id: "742224557632389160", 53 - team: TeamType.Donator 54 - }, 55 - { 56 - id: "340243638892101646", 57 - team: TeamType.Donator, 58 - social: "https://sattler.dev" 59 - }, 60 - { 61 - id: "911823996767600730", 62 - team: TeamType.Donator, 63 - social: "https://ibcheechy.com" 64 - }, 65 - { 66 - id: "748968886237397036", 67 - team: TeamType.Donator, 68 - social: "https://www.tiktok.com/@.noxern" 69 - }, 70 - { 71 - id: "313711746550595594", 72 - team: TeamType.Donator, 73 - social: "https://discord.gg/RmAF3DkQXd" 74 - }, 75 - { 76 - id: "452848052810547201", 77 - team: TeamType.Donator, 78 - social: "https://z1.gg" 79 - }, 80 - { 81 - id: "77755087602065408", 82 - team: TeamType.Donator, 83 - social: "https://notswayze.stream" 84 - }, 85 - { 86 - id: "354390108918644739", 87 - team: TeamType.Donator 88 - }, 89 - { 90 - id: "202042394428964865", 91 - team: TeamType.Donator 92 - }, 93 - { 94 - id: "657078394063945758", 95 - team: TeamType.Donator 96 - }, 97 - { 98 - id: "1118157956387700857", 99 - team: TeamType.Donator 100 - }, 101 - { 102 - id: "1322077071920336897", 103 - team: TeamType.Donator 104 34 } 105 35 ] as const;
+26 -5
app/(home)/team/page.tsx
··· 3 3 import type { Metadata } from "next"; 4 4 import { BsDiscord, BsGithub } from "react-icons/bs"; 5 5 6 - import { members, repos } from "./constants"; 6 + import { getBillingDonators } from "./api"; 7 + import { developers, repos, TeamType } from "./constants"; 7 8 import { DiscordServer } from "./discord.component"; 8 9 import { Person } from "./person.component"; 9 10 import { Repository } from "./repository.component"; 10 11 11 12 export const revalidate = 3_600; 13 + 14 + function formatTeamName(team: string) { 15 + return team 16 + .split("-") 17 + .map((str) => str.replace(/^\w/, (char) => char.toUpperCase())) 18 + .join(" "); 19 + } 12 20 13 21 export const generateMetadata = (): Metadata => { 14 22 const title = "Team"; ··· 43 51 }; 44 52 }; 45 53 46 - export default function Home() { 54 + export default async function Home() { 55 + const donors = await getBillingDonators() 56 + .then((donors) => ( 57 + Array.isArray(donors) 58 + ? donors.map((id) => ({ 59 + id, 60 + team: TeamType.Donator 61 + })) 62 + : [] 63 + )); 64 + 65 + const members = [...developers, ...donors]; 66 + const teams = filterDuplicates(members.map((member) => member.team)); 67 + 47 68 return ( 48 69 <div> 49 70 <h2 className="text-2xl font-medium text-neutral-200">Team 👋</h2> ··· 52 73 </div> 53 74 54 75 <div className="relative mb-10"> 55 - {filterDuplicates(members.map((member) => member.team)).map((team) => ( 76 + {teams.map((team) => ( 56 77 <div 57 78 key={team} 58 79 className="py-3" 59 80 > 60 81 <h3 className="text-lg font-medium text-neutral-200"> 61 - {team.split("-").map((str) => str.replace(/^\w/, (char) => char.toUpperCase())).join(" ")} 82 + {formatTeamName(team)} 62 83 </h3> 63 84 64 85 <div className="mt-2 flex flex-wrap gap-3"> ··· 68 89 <Person 69 90 key={member.id} 70 91 id={member.id} 71 - social={"social" in member ? member.social as string : undefined} 92 + social={"social" in member ? member.social : undefined} 72 93 /> 73 94 )) 74 95 }
+3 -3
app/(home)/team/person.component.tsx
··· 22 22 return ( 23 23 <Component 24 24 className={cn( 25 - "flex items-center gap-3 h-14 px-2 pl-[5px] pr-4 hover:bg-wamellow rounded-full cursor-default", 25 + "flex items-center gap-3 h-14 px-2 pl-1.25 pr-4 hover:bg-wamellow rounded-full cursor-default", 26 26 social && "duration-100 outline-violet-500 hover:outline-solid cursor-pointer" 27 27 )} 28 28 href={social} ··· 37 37 /> 38 38 39 39 <div className="mr-2"> 40 - <div className="text-lg text-neutral-200 font-medium -mb-1.5">{user.globalName || user.username}</div> 41 - <span className="opacity-75">{user.username}</span> 40 + <div className="text-lg text-neutral-200 font-semibold -mb-1.5">{user.globalName || user.username}</div> 41 + <span className="text-muted-foreground">{user.username}</span> 42 42 </div> 43 43 </Component> 44 44 );
+8 -8
components/comment.tsx
··· 23 23 <div className="flex gap-4 items-center mb-2"> 24 24 <span className="flex items-center gap-3"> 25 25 <Image 26 - alt="users's profile picture" 27 - className="w-12 h-12 rounded-full" 26 + alt={`${username}'s profile picture`} 27 + className="size-12 rounded-full" 28 28 height={64} 29 29 src={avatar} 30 30 width={64} 31 31 /> 32 32 <div> 33 - <span className="text-xl font-medium dark:text-neutral-200 text-neutral-800"> 33 + <p className="text-xl font-semibold text-foreground -mb-0.5"> 34 34 {username} 35 - </span> <br /> 36 - <span className="dark:text-neutral-300 text-neutral-700"> 35 + </p> 36 + <p className="text-muted-foreground"> 37 37 {bio} 38 - </span> 38 + </p> 39 39 </div> 40 40 </span> 41 - <HiChevronRight className="w-8 h-8" /> 41 + <HiChevronRight className="size-8 text-muted-foreground" /> 42 42 </div> 43 - <span className={cn(handwritten.className, "text-2xl break-words")}> 43 + <span className={cn(handwritten.className, "text-2xl wrap-break-words")}> 44 44 „{content}“ 45 45 </span> 46 46 </div>