11import React from "react"
2- import { Box , Flex , Text , useColorModeValue , HStack , Link , VStack , Divider , Tag } from "@chakra-ui/react"
2+ import Link from "next/link"
3+ import { Box , Flex , Text , useColorModeValue , HStack , VStack , Divider , Tag } from "@chakra-ui/react"
34import { motion } from "framer-motion"
45import { ArrowRight , ArrowUpRight } from "lucide-react"
56import { useTranslations } from "next-intl"
@@ -8,11 +9,12 @@ import { getYearColor } from "@/utils/degree"
89
910interface CourseCardProps {
1011 data : CourseDegree
12+ isSearchResult ?: boolean
1113}
1214
1315const MotionBox = motion ( Box )
1416
15- const CourseCard : React . FC < CourseCardProps > = ( { data } ) => {
17+ const CourseCard : React . FC < CourseCardProps > = ( { data, isSearchResult = false } ) => {
1618 const t = useTranslations ( "degrees" )
1719 const { course, year, semester } = data
1820
@@ -24,144 +26,160 @@ const CourseCard: React.FC<CourseCardProps> = ({ data }) => {
2426 const overlayText = useColorModeValue ( "gray.800" , "gray.100" )
2527
2628 return (
27- < MotionBox
28- role = "group"
29- border = "1px solid"
30- borderColor = { border }
31- rounded = "lg"
32- overflow = "hidden"
33- cursor = "pointer"
34- whileHover = { { y : - 4 } }
35- transition = { { duration : 0.2 } }
36- position = "relative"
37- _hover = { { shadow : "md" } }
38- bg = { useColorModeValue ( "gray.50" , "gray.700" ) }
39- w = { { base : "full" , md : "178px" } }
40- h = { { base : "72px" , md : "160px" } }
41- p = { 4 }
42- >
43- { /* Mobile: titolo + chevron */ }
44- < HStack w = "full" h = "full" align = "center" justify = "space-between" display = { { base : "flex" , md : "none" } } >
45- < Text fontWeight = "semibold" fontSize = "md" noOfLines = { 2 } color = { titleColor } >
46- { course . name }
47- </ Text >
48- < Box >
49- < ArrowRight size = { 18 } strokeWidth = { 2 } />
50- </ Box >
51- </ HStack >
52-
53- { /* Desktop: titolo fino a 3 righe */ }
54- < Flex
55- direction = "column"
56- justify = "center"
57- align = "flex-start"
58- w = "full"
59- h = "full"
60- display = { { base : "none" , md : "flex" } }
61- p = { 2 }
62- opacity = { 1 }
63- transition = "opacity 0.3s ease"
64- _groupHover = { { opacity : 0 } }
29+ < Link href = { course . group ?. invite_link ?? "" } >
30+ < MotionBox
31+ role = "group"
32+ border = "1px solid"
33+ borderColor = { border }
34+ rounded = "lg"
35+ overflow = "hidden"
36+ cursor = "pointer"
37+ whileHover = { { y : - 4 } }
38+ transition = { { duration : 0.2 } }
39+ position = "relative"
40+ _hover = { { shadow : "md" } }
41+ bg = { useColorModeValue ( "gray.50" , "gray.700" ) }
42+ w = { { base : "full" , md : "178px" } }
43+ h = { { base : "72px" , md : "160px" } }
44+ p = { 4 }
6545 >
66- < Text fontWeight = "bold" fontSize = "md" noOfLines = { 4 } >
67- { course . name }
68- </ Text >
69- </ Flex >
46+ { /* Mobile title + chevron */ }
47+ < HStack w = "full" h = "full" align = "center" justify = "space-between" display = { { base : "flex" , md : "none" } } >
48+ < Text fontWeight = "semibold" fontSize = "md" noOfLines = { 2 } color = { titleColor } >
49+ { course . name }
50+ </ Text >
51+ < Box >
52+ < ArrowRight size = { 18 } strokeWidth = { 2 } />
53+ </ Box >
54+ </ HStack >
7055
71- { /* Tag anno */ }
72- < Tag
73- display = { { base : "none" , md : "flex" } }
74- position = "absolute"
75- bottom = { 2 }
76- left = "50%"
77- transform = "translateX(-50%)"
78- size = "sm"
79- rounded = "full"
80- px = { 3 }
81- bg = { year === - 2 ? "gray.100" : getYearColor ( year , isDark ) }
82- color = { useColorModeValue ( "gray.700" , "gray.500" ) }
83- fontWeight = "medium"
84- >
85- { year !== - 2 ? t ( "courseCard.yearTag" , { year } ) : t ( "courseCard.complementary" ) }
86- </ Tag >
56+ { /* Desktop title */ }
57+ < Flex
58+ direction = "column"
59+ justify = "center"
60+ align = "flex-start"
61+ w = "full"
62+ h = "full"
63+ display = { { base : "none" , md : "flex" } }
64+ p = { 2 }
65+ opacity = { 1 }
66+ transition = "opacity 0.3s ease"
67+ _groupHover = { { opacity : 0 } }
68+ >
69+ < Text fontWeight = "bold" fontSize = "md" noOfLines = { 4 } >
70+ { course . name }
71+ </ Text >
72+ </ Flex >
8773
88- { /* Icona in alto a destra (desktop, solo hover) */ }
89- < Box
90- position = "absolute"
91- top = { 3 }
92- right = { 3 }
93- opacity = { 0 }
94- _groupHover = { { opacity : 1 } }
95- transition = "opacity 0.2s ease"
96- zIndex = { 10 }
97- display = { { base : "none" , md : "block" } }
98- >
99- < ArrowUpRight size = { 18 } strokeWidth = { 2 } />
100- </ Box >
74+ { /* Year */ }
75+ { ! isSearchResult && (
76+ < Tag
77+ display = { { base : "none" , md : "flex" } }
78+ position = "absolute"
79+ bottom = { 2 }
80+ left = "50%"
81+ transform = "translateX(-50%)"
82+ size = "sm"
83+ rounded = "full"
84+ px = { 3 }
85+ bg = { year === - 2 ? "gray.100" : getYearColor ( year , isDark ) }
86+ color = { useColorModeValue ( "gray.700" , "gray.500" ) }
87+ fontWeight = "medium"
88+ >
89+ { year !== - 2 ? t ( "courseCard.yearTag" , { year } ) : t ( "courseCard.complementary" ) }
90+ </ Tag >
91+ ) }
10192
102- { /* Overlay info corso */ }
103- < Box
104- position = "absolute"
105- top = { 0 }
106- left = { 0 }
107- right = { 0 }
108- bottom = { 0 }
109- w = "100%"
110- h = "100%"
111- bg = { overlayBg }
112- display = { { base : "none" , md : "flex" } }
113- flexDir = "column"
114- justifyContent = "center"
115- alignItems = "center"
116- textAlign = "center"
117- p = { 6 }
118- opacity = { 0 }
119- transition = "opacity 0.3s ease"
120- _groupHover = { { opacity : 1 } }
121- zIndex = { 2 }
122- >
123- < VStack spacing = { 3 } w = "full" >
124- { /* Docente */ }
125- { course . professor && (
126- < Link href = { course . professor . url } target = "_blank" fontWeight = "semibold" color = "blue.500" fontSize = "sm" noOfLines = { 1 } >
127- 🧑🔬 { course . professor . first_name [ 0 ] } . { course . professor . last_name }
128- </ Link >
129- ) }
93+ < Box
94+ position = "absolute"
95+ top = { 3 }
96+ right = { 3 }
97+ opacity = { 0 }
98+ _groupHover = { { opacity : 1 } }
99+ transition = "opacity 0.2s ease"
100+ zIndex = { 10 }
101+ display = { { base : "none" , md : "block" } }
102+ >
103+ < ArrowUpRight size = { 18 } strokeWidth = { 2 } />
104+ </ Box >
105+
106+ { /* Overlay */ }
107+ < Box
108+ position = "absolute"
109+ top = { 0 }
110+ left = { 0 }
111+ right = { 0 }
112+ bottom = { 0 }
113+ w = "100%"
114+ h = "100%"
115+ bg = { overlayBg }
116+ display = { { base : "none" , md : "flex" } }
117+ flexDir = "column"
118+ justifyContent = "center"
119+ alignItems = "center"
120+ textAlign = "center"
121+ p = { 6 }
122+ opacity = { 0 }
123+ transition = "opacity 0.3s ease"
124+ _groupHover = { { opacity : 1 } }
125+ zIndex = { 2 }
126+ >
127+ < VStack spacing = { 3 } w = "full" >
128+ { /* Professor */ }
129+ { course . professor && (
130+ < Box
131+ onClick = { ( e ) => {
132+ e . preventDefault ( )
133+ e . stopPropagation ( )
134+ window . open ( course . professor ?. url , "_blank" )
135+ } }
136+ cursor = "pointer"
137+ fontWeight = "semibold"
138+ color = "blue.500"
139+ fontSize = "sm"
140+ whiteSpace = "nowrap"
141+ overflow = "hidden"
142+ textOverflow = "ellipsis"
143+ >
144+ 🧑🔬 { course . professor . first_name [ 0 ] } . { course . professor . last_name }
145+ </ Box >
146+ ) }
130147
131- { course . professor && < Divider /> }
148+ { course . professor && < Divider /> }
132149
133- { /* Dati corso */ }
134- < HStack spacing = { 6 } justify = "center" w = "full" >
135- { year !== - 2 && (
150+ { /* Course */ }
151+ < HStack spacing = { 6 } justify = "center" w = "full" >
152+ { year !== - 2 && (
153+ < VStack spacing = { 0 } >
154+ < Text fontSize = "xs" color = { overlayText } >
155+ { t ( "courseCard.year" ) }
156+ </ Text >
157+ < Text fontWeight = "bold" fontSize = "sm" color = { overlayText } >
158+ { year }
159+ </ Text >
160+ </ VStack >
161+ ) }
136162 < VStack spacing = { 0 } >
137163 < Text fontSize = "xs" color = { overlayText } >
138- { t ( "courseCard.year " ) }
164+ { t ( "courseCard.semester " ) }
139165 </ Text >
140166 < Text fontWeight = "bold" fontSize = "sm" color = { overlayText } >
141- { year }
167+ { semester }
142168 </ Text >
143169 </ VStack >
144- ) }
145- < VStack spacing = { 0 } >
146- < Text fontSize = "xs" color = { overlayText } >
147- { t ( "courseCard.semester" ) }
148- </ Text >
149- < Text fontWeight = "bold" fontSize = "sm" color = { overlayText } >
150- { semester }
151- </ Text >
152- </ VStack >
153- < VStack spacing = { 0 } >
154- < Text fontSize = "xs" color = { overlayText } >
155- { t ( "courseCard.cfu" ) }
156- </ Text >
157- < Text fontWeight = "bold" fontSize = "sm" color = { overlayText } >
158- { course . cfu }
159- </ Text >
160- </ VStack >
161- </ HStack >
162- </ VStack >
163- </ Box >
164- </ MotionBox >
170+ < VStack spacing = { 0 } >
171+ < Text fontSize = "xs" color = { overlayText } >
172+ { t ( "courseCard.cfu" ) }
173+ </ Text >
174+ < Text fontWeight = "bold" fontSize = "sm" color = { overlayText } >
175+ { course . cfu }
176+ </ Text >
177+ </ VStack >
178+ </ HStack >
179+ </ VStack >
180+ </ Box >
181+ </ MotionBox >
182+ </ Link >
165183 )
166184}
167185
0 commit comments