|
| 1 | +import { clsx } from "clsx" |
1 | 2 | import { ScheduleSession } from "@/app/conf/2023/types"
|
2 |
| -import clsx from "clsx" |
| 3 | +import { Tag } from "@/app/conf/_design-system/tag" |
| 4 | +import { Button } from "@/app/conf/_design-system/button" |
| 5 | +import { CalendarIcon } from "@/app/conf/_design-system/pixelarticons/calendar-icon" |
| 6 | +import { PinIcon } from "@/app/conf/_design-system/pixelarticons/pin-icon" |
| 7 | +import ClockIcon from "@/app/conf/_design-system/pixelarticons/clock.svg?svgr" |
| 8 | +import PlusIcon from "@/app/conf/_design-system/pixelarticons/plus.svg?svgr" |
| 9 | +import PlayIcon from "@/app/conf/_design-system/pixelarticons/play.svg?svgr" |
3 | 10 |
|
4 | 11 | export interface LongSessionCardProps
|
5 | 12 | extends React.HTMLAttributes<HTMLDivElement> {
|
6 | 13 | session: ScheduleSession
|
7 |
| - year: `20${number}` |
| 14 | + variant?: "current" | "previous" |
| 15 | + eventColors?: Record<string, string> |
| 16 | +} |
| 17 | + |
| 18 | +function formatTime(dateString: string): string { |
| 19 | + return new Date(dateString).toLocaleTimeString("en-US", { |
| 20 | + hour: "2-digit", |
| 21 | + minute: "2-digit", |
| 22 | + hour12: false, |
| 23 | + }) |
| 24 | +} |
| 25 | + |
| 26 | +function formatDate(dateString: string): string { |
| 27 | + return new Date(dateString).toLocaleDateString("en-US", { |
| 28 | + day: "numeric", |
| 29 | + month: "long", |
| 30 | + }) |
8 | 31 | }
|
9 | 32 |
|
10 | 33 | export function LongSessionCard({
|
11 | 34 | session,
|
| 35 | + variant = "current", |
| 36 | + eventColors = {}, |
12 | 37 | className,
|
13 |
| - year, |
14 |
| - ...rest |
| 38 | + ...props |
15 | 39 | }: LongSessionCardProps) {
|
| 40 | + const eventType = session.event_type.endsWith("s") |
| 41 | + ? session.event_type.slice(0, -1) |
| 42 | + : session.event_type |
| 43 | + |
| 44 | + const formattedDate = formatDate(session.event_start) |
| 45 | + const formattedTime = formatTime(session.event_start) |
| 46 | + |
| 47 | + if (variant === "previous") { |
| 48 | + return ( |
| 49 | + <div |
| 50 | + className={clsx( |
| 51 | + "border border-neu-200 bg-neu-0 p-6 shadow-sm", |
| 52 | + className, |
| 53 | + )} |
| 54 | + {...props} |
| 55 | + > |
| 56 | + <div className="mb-6 flex flex-col gap-6"> |
| 57 | + <div className="flex items-center justify-between gap-6"> |
| 58 | + <Tag color={eventColors[session.event_type]}>{eventType}</Tag> |
| 59 | + <div className="flex items-center gap-2 border border-neu-400 bg-neu-100 px-2 py-1"> |
| 60 | + <span className="typography-menu text-neu-900"> |
| 61 | + graphql conf 2024 |
| 62 | + </span> |
| 63 | + </div> |
| 64 | + </div> |
| 65 | + <div className="flex flex-col gap-2"> |
| 66 | + <div className="min-h-[120px]"> |
| 67 | + <h3 className="typography-h3 text-neu-900">{session.name}</h3> |
| 68 | + </div> |
| 69 | + <div className="flex items-center justify-between gap-2"> |
| 70 | + <span className="typography-body-sm text-neu-600"> |
| 71 | + {session.speakers?.[0]?.name || "Speaker"} |
| 72 | + </span> |
| 73 | + <div className="flex items-center gap-0.5"> |
| 74 | + <ClockIcon className="size-3 text-neu-600" /> |
| 75 | + <span className="typography-body-xs text-neu-600">25 min</span> |
| 76 | + </div> |
| 77 | + </div> |
| 78 | + </div> |
| 79 | + </div> |
| 80 | + <Button href="#" variant="primary" className="w-full"> |
| 81 | + Watch |
| 82 | + <PlayIcon className="size-3" /> |
| 83 | + </Button> |
| 84 | + </div> |
| 85 | + ) |
| 86 | + } |
| 87 | + |
16 | 88 | return (
|
17 |
| - <div className={clsx(className)} {...rest}> |
18 |
| - LongSessionCard {year} |
| 89 | + <div |
| 90 | + className={clsx( |
| 91 | + "flex flex-col gap-6 border border-neu-200 bg-neu-0 p-6 shadow-sm backdrop-blur-md", |
| 92 | + className, |
| 93 | + )} |
| 94 | + {...props} |
| 95 | + > |
| 96 | + <div className="flex flex-col gap-6"> |
| 97 | + <div className="flex items-center justify-between gap-6"> |
| 98 | + <Tag color={eventColors[session.event_type]}>{eventType}</Tag> |
| 99 | + </div> |
| 100 | + <div className="flex flex-col gap-2"> |
| 101 | + <div className="min-h-[120px]"> |
| 102 | + <h3 className="typography-h3 text-neu-900">{session.name}</h3> |
| 103 | + </div> |
| 104 | + <div className="flex gap-2"> |
| 105 | + <span className="typography-body-sm text-neu-600"> |
| 106 | + {session.speakers?.[0]?.name || "Speaker"} |
| 107 | + </span> |
| 108 | + </div> |
| 109 | + </div> |
| 110 | + </div> |
| 111 | + <div className="flex items-center"> |
| 112 | + <div className="flex flex-1 items-center gap-6 border-r border-neu-200 pr-6"> |
| 113 | + <div className="flex items-center gap-0.5"> |
| 114 | + <CalendarIcon className="size-3 text-sec-base" /> |
| 115 | + <span className="typography-body-xs text-neu-600"> |
| 116 | + {formattedDate} |
| 117 | + </span> |
| 118 | + </div> |
| 119 | + <div className="flex items-center gap-0.5"> |
| 120 | + <ClockIcon className="size-3 text-sec-base" /> |
| 121 | + <span className="typography-body-xs text-neu-600"> |
| 122 | + {formattedTime} |
| 123 | + </span> |
| 124 | + </div> |
| 125 | + <div className="flex items-center gap-0.5"> |
| 126 | + <PinIcon className="size-3 text-sec-base" /> |
| 127 | + <span className="typography-body-xs text-neu-600"> |
| 128 | + {session.venue} |
| 129 | + </span> |
| 130 | + </div> |
| 131 | + </div> |
| 132 | + <div className="flex flex-col items-center justify-center gap-6 pl-6"> |
| 133 | + <button className="flex items-center gap-0.5 text-neu-600 hover:text-neu-900"> |
| 134 | + <PlusIcon className="size-3 text-sec-base" /> |
| 135 | + <span className="typography-body-xs">Add to calendar</span> |
| 136 | + </button> |
| 137 | + </div> |
| 138 | + </div> |
19 | 139 | </div>
|
20 | 140 | )
|
21 | 141 | }
|
0 commit comments