@@ -12,19 +12,20 @@ import {
12
12
CarouselPrevious ,
13
13
} from "@/components/ui/carousel"
14
14
15
- // import { cn } from "@/lib/utils/cn"
15
+ import { cn } from "@/lib/utils/cn"
16
+
16
17
import { releasesData } from "@/data/roadmap/releases"
17
18
18
- // const formatReleaseDate = (date: string) => {
19
- // if (/^\d{4}$/.test(date)) {
20
- // return date
21
- // }
22
- // return new Date(date).toLocaleDateString("en-US", {
23
- // month: "long",
24
- // day: "numeric",
25
- // year: "numeric",
26
- // })
27
- // }
19
+ const formatReleaseDate = ( date : string ) => {
20
+ if ( / ^ \d { 4 } $ / . test ( date ) ) {
21
+ return date
22
+ }
23
+ return new Date ( date ) . toLocaleDateString ( "en-US" , {
24
+ month : "long" ,
25
+ day : "numeric" ,
26
+ year : "numeric" ,
27
+ } )
28
+ }
28
29
29
30
const findLatestReleaseIndex = ( ) => {
30
31
const today = new Date ( )
@@ -54,19 +55,26 @@ const findLatestReleaseIndex = () => {
54
55
}
55
56
56
57
const ReleaseCarousel = ( ) => {
58
+ const todayDate = new Date ( )
59
+ const twoMonthsFromNow = new Date ( )
60
+ twoMonthsFromNow . setMonth ( todayDate . getMonth ( ) + 2 )
61
+
57
62
const [ api1 , setApi1 ] = useState < CarouselApi > ( )
58
63
const [ api2 , setApi2 ] = useState < CarouselApi > ( )
64
+ const [ currentIndex , setCurrentIndex ] = useState ( findLatestReleaseIndex ( ) )
59
65
60
66
useEffect ( ( ) => {
61
67
if ( ! api1 || ! api2 ) {
62
68
return
63
69
}
64
70
65
71
api1 . on ( "select" , ( ) => {
72
+ setCurrentIndex ( api1 . selectedScrollSnap ( ) )
66
73
api2 . scrollTo ( api1 . selectedScrollSnap ( ) )
67
74
} )
68
75
69
76
api2 . on ( "select" , ( ) => {
77
+ setCurrentIndex ( api2 . selectedScrollSnap ( ) )
70
78
api1 . scrollTo ( api2 . selectedScrollSnap ( ) )
71
79
} )
72
80
} , [ api1 , api2 ] )
@@ -88,16 +96,105 @@ const ReleaseCarousel = () => {
88
96
} }
89
97
>
90
98
< CarouselContent >
91
- { releasesData . map ( ( release ) => (
92
- < CarouselItem
93
- key = { release . releaseName }
94
- className = "w-full lg:basis-1/3"
95
- >
96
- < div className = "flex w-full flex-col items-center justify-center bg-blue-400" >
97
- < p > { release . releaseName } </ p >
98
- </ div >
99
- </ CarouselItem >
100
- ) ) }
99
+ { releasesData . map ( ( release , index ) => {
100
+ const releaseDate = new Date ( release . releaseDate )
101
+ const nextRelease =
102
+ releaseDate > todayDate && releaseDate <= twoMonthsFromNow
103
+ const labelType =
104
+ releaseDate < todayDate
105
+ ? 1
106
+ : releaseDate < twoMonthsFromNow
107
+ ? 2
108
+ : 3
109
+
110
+ return (
111
+ < CarouselItem
112
+ key = { release . releaseName }
113
+ className = "w-full md:basis-1/3"
114
+ >
115
+ < div className = "flex w-full flex-col items-center justify-center gap-3" >
116
+ < div className = "mb-3 !h-6" >
117
+ { labelType === 1 && (
118
+ < div
119
+ className = { cn (
120
+ "w-fit rounded-lg bg-primary-low-contrast px-2 py-1" ,
121
+ currentIndex !== index && "hidden"
122
+ ) }
123
+ >
124
+ < p className = "text-sm font-bold" > In production</ p >
125
+ </ div >
126
+ ) }
127
+ { labelType === 2 && (
128
+ < div
129
+ className = { cn (
130
+ "w-fit rounded-lg bg-warning-light px-2 py-1" ,
131
+ currentIndex !== index && "hidden"
132
+ ) }
133
+ >
134
+ < p className = "text-sm font-bold" > Coming soon</ p >
135
+ </ div >
136
+ ) }
137
+ { labelType === 3 && (
138
+ < div
139
+ className = { cn (
140
+ "w-fit rounded-lg bg-warning-light px-2 py-1" ,
141
+ currentIndex !== index && "hidden"
142
+ ) }
143
+ >
144
+ < p className = "text-sm font-bold" >
145
+ In development
146
+ </ p >
147
+ </ div >
148
+ ) }
149
+ </ div >
150
+ < div className = "flex w-full items-center justify-center text-center" >
151
+ < div
152
+ className = { cn (
153
+ "flex h-1 flex-1" ,
154
+ index !== 0
155
+ ? nextRelease
156
+ ? "bg-gradient-to-r from-primary to-primary-low-contrast"
157
+ : release . releaseDate <
158
+ new Date ( ) . toISOString ( ) . split ( "T" ) [ 0 ]
159
+ ? "bg-primary"
160
+ : "bg-primary-low-contrast"
161
+ : "bg-transparent"
162
+ ) }
163
+ />
164
+ < div
165
+ className = { cn (
166
+ "h-7 w-7 rounded-full" ,
167
+ release . releaseDate <
168
+ new Date ( ) . toISOString ( ) . split ( "T" ) [ 0 ]
169
+ ? "bg-primary"
170
+ : "bg-primary-low-contrast" ,
171
+ nextRelease &&
172
+ "border-2 border-primary bg-background"
173
+ ) }
174
+ />
175
+ < div
176
+ className = { cn (
177
+ "flex h-1 flex-1" ,
178
+ index !== releasesData . length - 1
179
+ ? index < findLatestReleaseIndex ( )
180
+ ? "bg-primary"
181
+ : "bg-primary-low-contrast"
182
+ : "bg-transparent"
183
+ ) }
184
+ />
185
+ </ div >
186
+ < div className = "flex flex-col items-center justify-center text-center" >
187
+ < p className = "text-md font-bold" >
188
+ { release . releaseName }
189
+ </ p >
190
+ < p className = "font-mono text-sm text-body-medium" >
191
+ { formatReleaseDate ( release . releaseDate ) }
192
+ </ p >
193
+ </ div >
194
+ </ div >
195
+ </ CarouselItem >
196
+ )
197
+ } ) }
101
198
</ CarouselContent >
102
199
< div className = "lg:hidden" >
103
200
< CarouselPrevious />
0 commit comments