@@ -71,6 +71,55 @@ export const Route = createFileRoute('/_libraries/partners')({
7171 } ) ,
7272} )
7373
74+ function ContributionDonut ( {
75+ score,
76+ totalScore,
77+ } : {
78+ score : number
79+ totalScore : number
80+ } ) {
81+ const normalizedScore = totalScore > 0 ? score / totalScore : 0
82+ const percentage = normalizedScore * 100
83+ const radius = 16
84+ const circumference = 2 * Math . PI * radius
85+ const strokeDashoffset = circumference - normalizedScore * circumference
86+
87+ return (
88+ < div className = "flex items-center gap-2" >
89+ < svg width = "40" height = "40" viewBox = "0 0 40 40" className = "shrink-0" >
90+ < circle
91+ cx = "20"
92+ cy = "20"
93+ r = { radius }
94+ fill = "none"
95+ stroke = "currentColor"
96+ strokeWidth = "5"
97+ className = "text-gray-200 dark:text-gray-700"
98+ />
99+ < circle
100+ cx = "20"
101+ cy = "20"
102+ r = { radius }
103+ fill = "none"
104+ stroke = "currentColor"
105+ strokeWidth = "5"
106+ strokeDasharray = { circumference }
107+ strokeDashoffset = { strokeDashoffset }
108+ strokeLinecap = "round"
109+ className = "text-blue-500"
110+ transform = "rotate(-90 20 20)"
111+ />
112+ </ svg >
113+ < div className = "flex flex-col" >
114+ < span className = "text-sm font-semibold" > { percentage . toFixed ( 1 ) } %</ span >
115+ < span className = "text-[10px] text-gray-500 dark:text-gray-400" >
116+ current support
117+ </ span >
118+ </ div >
119+ </ div >
120+ )
121+ }
122+
74123interface FilterProps {
75124 selectedLibraries : Library [ 'id' ] [ ] | undefined
76125 selectedStatus : 'active' | 'inactive' | undefined
@@ -307,6 +356,11 @@ function RouteComp() {
307356 return true
308357 } )
309358
359+ const totalScore = filteredPartners . reduce (
360+ ( sum , partner ) => sum + ( partner . score ?? 0 ) ,
361+ 0 ,
362+ )
363+
310364 const hasStatusFilter = search . status
311365 const hasLibraryFilter = search . libraries && search . libraries . length > 0
312366 const hasResults = filteredPartners . length > 0
@@ -394,6 +448,14 @@ function RouteComp() {
394448 < h3 className = "text-center text-xl font-semibold mb-4" >
395449 { partner . name }
396450 </ h3 >
451+ { partner . score != null && ! isShowingPrevious && (
452+ < div className = "flex justify-center mb-4" >
453+ < ContributionDonut
454+ score = { partner . score }
455+ totalScore = { totalScore }
456+ />
457+ </ div >
458+ ) }
397459 < div className = "text-sm" >
398460 { isShowingPrevious ? (
399461 < >
@@ -464,25 +526,25 @@ function RouteComp() {
464526
465527 < div className = "text-center py-8 border-t border-gray-200 dark:border-gray-700" >
466528 < a
467- href = "#total -support-share"
529+ href = "#lifetime -support-share"
468530 className = "anchor-heading *:scroll-my-20 *:lg:scroll-my-4"
469531 >
470532 < h2
471- id = "total -support-share"
533+ id = "lifetime -support-share"
472534 className = "text-2xl font-semibold mb-4"
473535 >
474- Total Support Share
536+ Lifetime Support Share
475537 </ h2 >
476538 </ a >
477539 < p className = "text-gray-600 dark:text-gray-400 mb-6 max-w-xl mx-auto" >
478- This chart is a percentage-based visualization of the total support
479- each partner has rendered to TanStack ever . It is updated every 6
540+ This chart is a percentage-based visualization of the lifetime
541+ support each partner has rendered to TanStack. It is updated every 6
480542 months.
481543 </ p >
482544 < div className = "flex justify-center" >
483545 < img
484546 src = "/images/total-support-share.png"
485- alt = "Total Support Share chart showing percentage-based contribution of partners to TanStack"
547+ alt = "Lifetime Support Share chart showing percentage-based contribution of partners to TanStack"
486548 className = "rounded-lg shadow-lg"
487549 width = { 600 }
488550 height = { 706 }
0 commit comments