1- import { Table , Text } from '@chakra-ui/react' ;
1+ import { Badge , Flex , Icon , Table , Text } from '@chakra-ui/react' ;
22import {
33 ColumnDef ,
44 flexRender ,
55 getCoreRowModel ,
66 useReactTable ,
77} from '@tanstack/react-table' ;
8+ import { FaStar } from 'react-icons/fa' ;
89
910import { useIsMobile } from '~/hooks/useIsMobile' ;
1011import { EpisodeForSeason } from '~/store/tv/types/transformed' ;
1112import dayjs from '~/utils/dayjs' ;
1213
14+ import TableHeader from './TableHeader' ;
15+
1316type Props = {
1417 episodes : EpisodeForSeason [ ] ;
1518} ;
@@ -22,36 +25,71 @@ const EpisodesTable = ({ episodes }: Props) => {
2225 id : 'episodeNumber' ,
2326 accessorKey : 'episodeNumber' ,
2427 size : 40 ,
25- header : ( ) => < Text color = "fg.muted" > #</ Text > ,
28+ header : ( ) => < TableHeader > Number</ TableHeader > ,
29+ cell : ( { row } ) => (
30+ < Text color = "fg.muted" fontSize = "sm" >
31+ { row . original . episodeNumber }
32+ </ Text >
33+ ) ,
2634 } ,
2735 {
2836 id : 'name' ,
2937 accessorKey : 'name' ,
3038 size : 100 ,
31- header : ( ) => < Text color = "fg.muted" > Title</ Text > ,
39+ header : ( ) => < TableHeader > Title</ TableHeader > ,
40+ cell : ( { row } ) => (
41+ < Text fontWeight = "semibold" fontSize = "sm" color = "fg" >
42+ { row . original . name }
43+ </ Text >
44+ ) ,
3245 } ,
3346 {
3447 id : 'airDate' ,
3548 size : 80 ,
3649 accessorFn : row =>
37- row . airDate && dayjs ( row . airDate ) . format ( 'MMMM D, YYYY' ) ,
38- header : ( ) => < Text color = "fg.muted" > Air Date</ Text > ,
50+ row . airDate && dayjs ( row . airDate ) . format ( 'MMM D, YYYY' ) ,
51+ header : ( ) => < TableHeader > Air Date</ TableHeader > ,
52+ cell : ( { getValue } ) => (
53+ < Text fontSize = "sm" whiteSpace = "nowrap" color = "fg.muted" >
54+ { getValue ( ) as string }
55+ </ Text >
56+ ) ,
3957 } ,
4058 {
4159 id : 'voteAverage' ,
4260 size : 50 ,
43- meta : {
44- style : { textAlign : 'center' } ,
61+ header : ( ) => < TableHeader textAlign = "center" > Rating</ TableHeader > ,
62+ cell : ( { row } ) => {
63+ const ratingStr = row . original . voteAverage ;
64+ if ( ! ratingStr || ratingStr === '-' ) {
65+ return (
66+ < Text color = "fg.muted" textAlign = "center" >
67+ -
68+ </ Text >
69+ ) ;
70+ }
71+ const rating = parseFloat ( ratingStr ) ;
72+
73+ return (
74+ < Flex justify = "center" >
75+ < Badge
76+ variant = "subtle"
77+ colorPalette = {
78+ rating >= 8 ? 'green' : rating >= 6.5 ? 'yellow' : 'orange'
79+ }
80+ size = "sm"
81+ borderRadius = "full"
82+ px = "2"
83+ display = "flex"
84+ alignItems = "center"
85+ gap = "1"
86+ >
87+ { rating . toFixed ( 1 ) }
88+ < Icon as = { FaStar } boxSize = "2" />
89+ </ Badge >
90+ </ Flex >
91+ ) ;
4592 } ,
46- accessorFn : row => row . voteAverage ,
47- header : ( ) => (
48- < Text color = "fg.muted" textAlign = "center" >
49- Rating
50- </ Text >
51- ) ,
52- cell : ( { row } ) => (
53- < Text textAlign = "center" > { row . original . voteAverage } </ Text >
54- ) ,
5593 } ,
5694 ] ;
5795
@@ -67,12 +105,16 @@ const EpisodesTable = ({ episodes }: Props) => {
67105 } ) ;
68106
69107 return (
70- < Table . Root size = "sm" >
108+ < Table . Root size = { isMobile ? 'sm' : 'md' } variant = "outline" interactive >
71109 < Table . Header >
72110 { getHeaderGroups ( ) . map ( headerGroup => (
73- < Table . Row key = { headerGroup . id } >
111+ < Table . Row key = { headerGroup . id } borderBottomWidth = "2px" >
74112 { headerGroup . headers . map ( header => (
75- < Table . ColumnHeader key = { header . id } >
113+ < Table . ColumnHeader
114+ key = { header . id }
115+ py = "4"
116+ px = { isMobile ? '2' : '4' }
117+ >
76118 { header . isPlaceholder
77119 ? null
78120 : flexRender (
@@ -87,9 +129,15 @@ const EpisodesTable = ({ episodes }: Props) => {
87129
88130 < Table . Body >
89131 { getRowModel ( ) . rows . map ( row => (
90- < Table . Row key = { row . id } >
132+ < Table . Row
133+ key = { row . id }
134+ _hover = { { bg : 'whiteAlpha.50' } }
135+ transition = "background 0.2s"
136+ borderBottomWidth = "1px"
137+ borderColor = "whiteAlpha.50"
138+ >
91139 { row . getVisibleCells ( ) . map ( cell => (
92- < Table . Cell key = { cell . id } >
140+ < Table . Cell key = { cell . id } py = "4" px = { isMobile ? '2' : '4' } >
93141 { flexRender ( cell . column . columnDef . cell , cell . getContext ( ) ) }
94142 </ Table . Cell >
95143 ) ) }
0 commit comments