1+ import { useSponsors } from "@/hooks/useSponsors" ;
12import { useTranslation } from "@/hooks/useTranslation" ;
3+ import { remainingSponsorships } from "@/utils/remainingSponsorships" ;
24import { FaLinkedin , FaYoutube } from "react-icons/fa" ;
35import { Link } from "react-router-dom" ;
46
57const TIERS = [
68 {
79 name : { fr : "Or" , en : "Gold" } ,
10+ level : "or" ,
811 color : "bg-yellow-500" ,
912 price : "3 000" ,
1013 available : 3 ,
@@ -13,6 +16,7 @@ const TIERS = [
1316 } ,
1417 {
1518 name : { fr : "Argent" , en : "Silver" } ,
19+ level : "argent" ,
1620 color : "bg-gray-400" ,
1721 price : "2 000" ,
1822 available : 4 ,
@@ -21,6 +25,7 @@ const TIERS = [
2125 } ,
2226 {
2327 name : { fr : "Bronze" , en : "Bronze" } ,
28+ level : "bronze" ,
2429 color : "bg-amber-700" ,
2530 price : "750" ,
2631 available : 5 ,
@@ -61,6 +66,15 @@ const PERKS = [
6166
6267export default function SponsorshipPage ( ) {
6368 const { t } = useTranslation ( ) ;
69+ const { allSponsors } = useSponsors ( ) ;
70+
71+ const tiers = TIERS . map ( ( tier ) => ( {
72+ ...tier ,
73+ remaining : remainingSponsorships (
74+ tier . available ,
75+ allSponsors . filter ( ( sponsor ) => sponsor . level === tier . level ) . length ,
76+ ) ,
77+ } ) ) ;
6478
6579 return (
6680 < div className = "container mx-auto px-4 py-8" >
@@ -90,7 +104,7 @@ export default function SponsorshipPage() {
90104 < thead >
91105 < tr >
92106 < th className = "p-4 text-left" />
93- { TIERS . map ( ( tier ) => (
107+ { tiers . map ( ( tier ) => (
94108 < th key = { t ( tier . name ) } className = "p-4 text-center" >
95109 < span
96110 className = { `inline-block px-6 py-2 rounded-full text-white font-bold text-lg ${ tier . color } ` }
@@ -106,20 +120,23 @@ export default function SponsorshipPage() {
106120 < td className = "p-4 font-medium text-gray-700" >
107121 { t ( { fr : "Disponibles" , en : "Available" } ) }
108122 </ td >
109- { TIERS . map ( ( tier ) => (
123+ { tiers . map ( ( tier ) => (
110124 < td
111125 key = { t ( tier . name ) }
112126 className = "p-4 text-center text-gray-600"
113127 >
114- { tier . available }
128+ < AvailabilityLabel
129+ total = { tier . available }
130+ remaining = { tier . remaining }
131+ />
115132 </ td >
116133 ) ) }
117134 </ tr >
118135 < tr className = "border-t border-gray-200 bg-gray-50" >
119136 < td className = "p-4 font-medium text-gray-700" >
120137 { t ( { fr : "Prix ($ CAD)" , en : "Price ($ CAD)" } ) }
121138 </ td >
122- { TIERS . map ( ( tier ) => (
139+ { tiers . map ( ( tier ) => (
123140 < td
124141 key = { t ( tier . name ) }
125142 className = "p-4 text-center font-bold text-xl text-primary"
@@ -135,7 +152,7 @@ export default function SponsorshipPage() {
135152 en : "Conference tickets included" ,
136153 } ) }
137154 </ td >
138- { TIERS . map ( ( tier ) => (
155+ { tiers . map ( ( tier ) => (
139156 < td
140157 key = { t ( tier . name ) }
141158 className = "p-4 text-center text-gray-600"
@@ -150,11 +167,8 @@ export default function SponsorshipPage() {
150167 className = { `border-t border-gray-200 ${ perkIndex % 2 === 0 ? "bg-gray-50" : "" } ` }
151168 >
152169 < td className = "p-4 font-medium text-gray-700" > { t ( perk ) } </ td >
153- { TIERS . map ( ( tier ) => (
154- < td
155- key = { t ( tier . name ) }
156- className = "p-4 text-center text-xl"
157- >
170+ { tiers . map ( ( tier ) => (
171+ < td key = { t ( tier . name ) } className = "p-4 text-center text-xl" >
158172 { tier . perks [ perkIndex ] ? (
159173 < span className = "text-green-600" > ✓</ span >
160174 ) : (
@@ -170,22 +184,25 @@ export default function SponsorshipPage() {
170184
171185 { /* Mobile cards */ }
172186 < div className = "md:hidden space-y-8" >
173- { TIERS . map ( ( tier ) => (
187+ { tiers . map ( ( tier ) => (
174188 < div
175189 key = { t ( tier . name ) }
176190 className = "border rounded-lg shadow-md overflow-hidden"
177191 >
178- < div
179- className = { `${ tier . color } text-white text-center py-4 px-6` }
180- >
192+ < div className = { `${ tier . color } text-white text-center py-4 px-6` } >
181193 < h3 className = "text-2xl font-bold" > { t ( tier . name ) } </ h3 >
182194 < p className = "text-3xl font-bold mt-1" > ${ tier . price } </ p >
183195 < p className = "text-sm opacity-90" > CAD</ p >
184196 </ div >
185197 < div className = "p-6 space-y-3" >
186198 < div className = "flex justify-between text-gray-700 pb-3 border-b border-gray-200" >
187199 < span > { t ( { fr : "Disponibles" , en : "Available" } ) } </ span >
188- < span className = "font-medium" > { tier . available } </ span >
200+ < span className = "font-medium" >
201+ < AvailabilityLabel
202+ total = { tier . available }
203+ remaining = { tier . remaining }
204+ />
205+ </ span >
189206 </ div >
190207 < div className = "flex justify-between text-gray-700 pb-3 border-b border-gray-200" >
191208 < span >
@@ -301,3 +318,44 @@ export default function SponsorshipPage() {
301318 </ div >
302319 ) ;
303320}
321+
322+ function AvailabilityLabel ( {
323+ total,
324+ remaining,
325+ } : {
326+ total : number ;
327+ remaining : number ;
328+ } ) {
329+ const { t } = useTranslation ( ) ;
330+
331+ if ( remaining <= 0 ) {
332+ return (
333+ < span className = "text-gray-500" >
334+ { t ( { fr : "Complet" , en : "Sold out" } ) }
335+ </ span >
336+ ) ;
337+ }
338+
339+ // No sponsor at this tier yet: a struck-through total would just be noise.
340+ if ( remaining >= total ) {
341+ return < span className = "font-semibold text-gray-700" > { remaining } </ span > ;
342+ }
343+
344+ return (
345+ < span
346+ className = "inline-flex items-baseline gap-1.5"
347+ aria-label = { t ( {
348+ fr : `${ remaining } sur ${ total } disponibles` ,
349+ en : `${ remaining } of ${ total } available` ,
350+ } ) }
351+ >
352+ < span aria-hidden className = "relative inline-block text-gray-500" >
353+ { total }
354+ < span className = "absolute left-1/2 top-1/2 h-[1.5px] w-[130%] -translate-x-1/2 -translate-y-1/2 -rotate-12 bg-red-500" />
355+ </ span >
356+ < span aria-hidden className = "font-semibold text-gray-700" >
357+ { remaining }
358+ </ span >
359+ </ span >
360+ ) ;
361+ }
0 commit comments