1- "use client"
1+ "use client" ;
22
3- import type React from "react"
4- import { useMemo , useState } from "react"
5- import Image from "next/image"
6- import Link from "next/link"
7- import CodevBadge from "@/components/CodevBadge"
8- import type { Codev , InternalStatus } from "@/types/home/codev"
9- import { AnimatePresence , motion , useMotionValue , useSpring , useTransform } from "framer-motion"
3+ import type { Codev , InternalStatus } from "@/types/home/codev" ;
4+ import type React from "react" ;
5+ import { useMemo , useState } from "react" ;
6+ import Image from "next/image" ;
7+ import Link from "next/link" ;
8+ import CodevBadge from "@/components/CodevBadge" ;
9+ import {
10+ AnimatePresence ,
11+ motion ,
12+ useMotionValue ,
13+ useSpring ,
14+ useTransform ,
15+ } from "framer-motion" ;
16+ import { BookOpenIcon } from "lucide-react" ;
1017
11- import { cn } from "@codevs/ui"
12- import { BookOpenIcon } from "lucide-react"
13- import { Button } from "@codevs/ui/button"
14- import { Tooltip , TooltipContent , TooltipProvider , TooltipTrigger } from "@codevs/ui/tooltip"
15- import { CodevHireCodevButton } from "./CodevHireCodevButton"
18+ import { cn } from "@codevs/ui" ;
19+ import { Button } from "@codevs/ui/button" ;
20+ import {
21+ Tooltip ,
22+ TooltipContent ,
23+ TooltipProvider ,
24+ TooltipTrigger ,
25+ } from "@codevs/ui/tooltip" ;
26+
27+ import { CodevHireCodevButton } from "./CodevHireCodevButton" ;
1628
1729interface Props {
18- codev : Codev
19- color : string
30+ codev : Codev ;
31+ color : string ;
2032}
2133
22- const STATUS_CONFIG : Record < InternalStatus , { label : string ; className : string } > = {
34+ const STATUS_CONFIG : Record <
35+ InternalStatus ,
36+ { label : string ; className : string }
37+ > = {
2338 TRAINING : {
2439 label : "Training" ,
2540 className : "bg-status-training text-status-training-text" ,
@@ -44,60 +59,75 @@ const STATUS_CONFIG: Record<InternalStatus, { label: string; className: string }
4459 label : "Deployed" ,
4560 className : "bg-status-deployed text-status-deployed-text" ,
4661 } ,
47- }
62+ } ;
4863
4964const CodevCard = ( { codev, color } : Props ) => {
50- const [ hovered , setHovered ] = useState ( false )
51- const springConfig = { stiffness : 100 , damping : 5 }
52- const x = useMotionValue ( 0 )
53- const rotate = useSpring ( useTransform ( x , [ - 100 , 100 ] , [ - 45 , 45 ] ) , springConfig )
54- const translateX = useSpring ( useTransform ( x , [ - 100 , 100 ] , [ - 50 , 50 ] ) , springConfig )
65+ const [ hovered , setHovered ] = useState ( false ) ;
66+ const springConfig = { stiffness : 100 , damping : 5 } ;
67+ const x = useMotionValue ( 0 ) ;
68+ const rotate = useSpring (
69+ useTransform ( x , [ - 100 , 100 ] , [ - 45 , 45 ] ) ,
70+ springConfig ,
71+ ) ;
72+ const translateX = useSpring (
73+ useTransform ( x , [ - 100 , 100 ] , [ - 50 , 50 ] ) ,
74+ springConfig ,
75+ ) ;
5576
5677 const handleMouseMove = ( event : React . MouseEvent ) => {
57- const halfWidth = ( event . target as HTMLElement ) . offsetWidth / 2
58- x . set ( event . nativeEvent . offsetX - halfWidth )
59- }
78+ const halfWidth = ( event . target as HTMLElement ) . offsetWidth / 2 ;
79+ x . set ( event . nativeEvent . offsetX - halfWidth ) ;
80+ } ;
6081
61- const internalStatus = codev . internal_status || "MENTOR"
62- const statusConfig = STATUS_CONFIG [ internalStatus as InternalStatus ] || STATUS_CONFIG . MENTOR
82+ const internalStatus = codev . internal_status || "MENTOR" ;
83+ const statusConfig =
84+ STATUS_CONFIG [ internalStatus as InternalStatus ] || STATUS_CONFIG . MENTOR ;
6385
6486 const filteredLevel = useMemo ( ( ) => {
65- return codev . level && codev . codev_points && Array . isArray ( codev . codev_points )
66- ? Object . fromEntries (
67- Object . entries ( codev . level )
68- . filter ( ( [ skillCategoryId , levelValue ] ) => {
69- return (
70- levelValue > 0 &&
71- codev . codev_points ! . some ( ( point ) => point ?. skill_category_id === skillCategoryId )
72- ) ;
73- } )
74- . sort ( ( [ skillCategoryIdA ] , [ skillCategoryIdB ] ) => {
75- const pointsA = codev . codev_points ! . find (
76- ( point ) => point ?. skill_category_id === skillCategoryIdA
77- ) ?. points || 0 ;
78- const pointsB = codev . codev_points ! . find (
79- ( point ) => point ?. skill_category_id === skillCategoryIdB
80- ) ?. points || 0 ;
81- return pointsB - pointsA ;
82- } )
83- )
84- : { } ;
85- } , [ codev . level , codev . codev_points ] ) ;
87+ return codev . level &&
88+ codev . codev_points &&
89+ Array . isArray ( codev . codev_points )
90+ ? Object . fromEntries (
91+ Object . entries ( codev . level )
92+ . filter ( ( [ skillCategoryId , levelValue ] ) => {
93+ return (
94+ levelValue > 0 &&
95+ codev . codev_points ! . some (
96+ ( point ) => point ?. skill_category_id === skillCategoryId ,
97+ )
98+ ) ;
99+ } )
100+ . sort ( ( [ skillCategoryIdA ] , [ skillCategoryIdB ] ) => {
101+ const pointsA =
102+ codev . codev_points ! . find (
103+ ( point ) => point ?. skill_category_id === skillCategoryIdA ,
104+ ) ?. points || 0 ;
105+ const pointsB =
106+ codev . codev_points ! . find (
107+ ( point ) => point ?. skill_category_id === skillCategoryIdB ,
108+ ) ?. points || 0 ;
109+ return pointsB - pointsA ;
110+ } ) ,
111+ )
112+ : { } ;
113+ } , [ codev . level , codev . codev_points ] ) ;
86114
87115 return (
88116 < div
89117 className = "h-64"
90118 onMouseEnter = { ( ) => setHovered ( true ) }
91119 onMouseLeave = { ( ) => setHovered ( false ) }
92120 >
93- < div className = "bg-black-500 flex h-full w-full flex-col items-center justify-between rounded-lg p-4 shadow-2xl hover:bg-black-800 " >
94- < div className = "w-full grid grid-cols-4 gap-2" >
121+ < div className = "bg-black-500 hover:bg-black-800 flex h-full w-full flex-col items-center justify-between rounded-lg p-4 shadow-2xl" >
122+ < div className = "grid w-full grid-cols-4 gap-2" >
95123 < div className = "col-span-1" />
96- < div className = "col-span-2 relative flex justify-center" >
124+ < div className = "relative col-span-2 flex justify-center" >
97125 < Image
98126 alt = { `${ codev . first_name } Avatar` }
99127 src = {
100- codev . image_url && ( codev . image_url . startsWith ( "http" ) || codev . image_url . startsWith ( "/" ) )
128+ codev . image_url &&
129+ ( codev . image_url . startsWith ( "http" ) ||
130+ codev . image_url . startsWith ( "/" ) )
101131 ? codev . image_url
102132 : "/assets/svgs/icon-codebility-black.svg"
103133 }
@@ -106,10 +136,11 @@ const CodevCard = ({ codev, color }: Props) => {
106136 className = { `${ color } h-[70px] w-[70px] rounded-full bg-cover object-cover p-0.5` }
107137 onMouseMove = { handleMouseMove }
108138 onError = { ( e ) => {
109- console . error ( `Failed to load image for ${ codev . first_name } : ${ codev . image_url } ` )
110- e . currentTarget . src = "/assets/svgs/icon-codebility-black.svg"
139+ console . error (
140+ `Failed to load image for ${ codev . first_name } : ${ codev . image_url } ` ,
141+ ) ;
142+ e . currentTarget . src = "/assets/svgs/icon-codebility-black.svg" ;
111143 } }
112-
113144 />
114145 < AnimatePresence >
115146 { hovered && internalStatus && (
@@ -136,7 +167,9 @@ const CodevCard = ({ codev, color }: Props) => {
136167 statusConfig . className ,
137168 ) }
138169 >
139- < div className = "relative z-30 text-base" > { statusConfig . label } </ div >
170+ < div className = "relative z-30 text-base" >
171+ { statusConfig . label }
172+ </ div >
140173 </ motion . div >
141174 ) }
142175 </ AnimatePresence >
@@ -153,16 +186,19 @@ const CodevCard = ({ codev, color }: Props) => {
153186 < TooltipProvider >
154187 < Tooltip delayDuration = { 100 } >
155188 < TooltipTrigger asChild >
156- < Link
157- href = { `/profiles/${ codev . id } ` }
158- target = "_blank"
159- >
160- < Button variant = "outline" size = "icon" className = "h-8 w-8 rounded-full bg-black-500" >
189+ < Link href = { `/profiles/${ codev . id } ` } target = "_blank" >
190+ < Button
191+ variant = "outline"
192+ size = "icon"
193+ className = "bg-black-500 h-8 w-8 rounded-full"
194+ >
161195 < BookOpenIcon className = "h-3.5 w-3.5" />
162196 </ Button >
163197 </ Link >
164198 </ TooltipTrigger >
165- < TooltipContent className = "bg-slate-700 text-xs px-2 py-1" > Read Bio</ TooltipContent >
199+ < TooltipContent className = "bg-slate-700 px-2 py-1 text-xs" >
200+ Read Bio
201+ </ TooltipContent >
166202 </ Tooltip >
167203 </ TooltipProvider >
168204 </ div >
@@ -173,22 +209,24 @@ const CodevCard = ({ codev, color }: Props) => {
173209 { codev . first_name } { codev . last_name }
174210 </ p >
175211 { codev . display_position ? (
176- < p className = "text-gray text-sm " > { codev . display_position } </ p >
212+ < p className = "text-sm text-gray-300 " > { codev . display_position } </ p >
177213 ) : (
178214 < div className = "text-sm lg:text-base" > </ div >
179215 ) }
180216 </ div >
181217 </ div >
182218 < div className = "flex min-h-[20px] items-center justify-center" >
183219 { filteredLevel && Object . keys ( filteredLevel ) . length > 0 ? (
184- < CodevBadge level = { filteredLevel } className = "transition-transform group-hover:scale-100" />
220+ < CodevBadge
221+ level = { filteredLevel }
222+ className = "transition-transform group-hover:scale-100"
223+ />
185224 ) : null }
186225 </ div >
187226 < CodevHireCodevButton codevId = { codev . id } hovered = { hovered } />
188227 </ div >
189228 </ div >
190- )
191- }
192-
193- export default CodevCard
229+ ) ;
230+ } ;
194231
232+ export default CodevCard ;
0 commit comments