Skip to content

Commit 1248abf

Browse files
committed
timeline carousel implemented
1 parent d962e8e commit 1248abf

File tree

1 file changed

+118
-21
lines changed

1 file changed

+118
-21
lines changed

app/[locale]/roadmap/_components/ReleaseCarousel.tsx

Lines changed: 118 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,20 @@ import {
1212
CarouselPrevious,
1313
} from "@/components/ui/carousel"
1414

15-
// import { cn } from "@/lib/utils/cn"
15+
import { cn } from "@/lib/utils/cn"
16+
1617
import { releasesData } from "@/data/roadmap/releases"
1718

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+
}
2829

2930
const findLatestReleaseIndex = () => {
3031
const today = new Date()
@@ -54,19 +55,26 @@ const findLatestReleaseIndex = () => {
5455
}
5556

5657
const ReleaseCarousel = () => {
58+
const todayDate = new Date()
59+
const twoMonthsFromNow = new Date()
60+
twoMonthsFromNow.setMonth(todayDate.getMonth() + 2)
61+
5762
const [api1, setApi1] = useState<CarouselApi>()
5863
const [api2, setApi2] = useState<CarouselApi>()
64+
const [currentIndex, setCurrentIndex] = useState(findLatestReleaseIndex())
5965

6066
useEffect(() => {
6167
if (!api1 || !api2) {
6268
return
6369
}
6470

6571
api1.on("select", () => {
72+
setCurrentIndex(api1.selectedScrollSnap())
6673
api2.scrollTo(api1.selectedScrollSnap())
6774
})
6875

6976
api2.on("select", () => {
77+
setCurrentIndex(api2.selectedScrollSnap())
7078
api1.scrollTo(api2.selectedScrollSnap())
7179
})
7280
}, [api1, api2])
@@ -88,16 +96,105 @@ const ReleaseCarousel = () => {
8896
}}
8997
>
9098
<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+
})}
101198
</CarouselContent>
102199
<div className="lg:hidden">
103200
<CarouselPrevious />

0 commit comments

Comments
 (0)