1
- import { type HeadersFunction , type LoaderFunctionArgs , type ActionFunctionArgs , json } from "@remix-run/node" ;
2
- import { type MetaFunction , useLoaderData , isRouteErrorResponse , useRouteError , type ShouldRevalidateFunction } from "@remix-run/react" ;
3
- import { Avatar , AvatarFallback , AvatarImage } from "#app/components/ui/avatar"
4
- import { Button } from "#app/components/ui/button" ;
5
- import { Card } from "#app/components/ui/card" ;
6
-
1
+ import {
2
+ type HeadersFunction ,
3
+ type LoaderFunctionArgs ,
4
+ type ActionFunctionArgs ,
5
+ json ,
6
+ } from '@remix-run/node'
7
+ import {
8
+ type MetaFunction ,
9
+ useLoaderData ,
10
+ isRouteErrorResponse ,
11
+ useRouteError ,
12
+ type ShouldRevalidateFunction ,
13
+ } from '@remix-run/react'
14
+ import { Avatar , AvatarFallback , AvatarImage } from '#app/components/ui/avatar'
15
+ import { Card } from '#app/components/ui/card'
16
+ import {
17
+ Tabs ,
18
+ TabsContent ,
19
+ TabsList ,
20
+ TabsTrigger ,
21
+ } from '#app/components/ui/tabs'
7
22
8
23
interface VCActivityType {
9
- id : number
10
- activeFlag : string
11
- status : string
12
- playerFirstName : string
13
- playerLastName : string
14
- playerPosition : string
15
- playerWeightLbs : number
16
- playerHeightInches : number
17
- playerEligibilityYear : string
24
+ id : number
25
+ activeFlag : string
26
+ status : string
27
+ playerFirstName : string
28
+ playerLastName : string
29
+ playerPosition : string
30
+ playerWeightLbs : number
31
+ playerHeightInches : number
32
+ playerEligibilityYear : string
18
33
}
19
34
20
35
export const meta : MetaFunction = ( { data } ) => [
36
+ { title : data ? 'lucasb.dev | BucNation' : 'Error | lucasb.dev' } ,
37
+ {
38
+ name : 'description' ,
39
+ content : `A page dedicated to East Tennessee State Basketball` ,
40
+ } ,
41
+ ]
21
42
22
- { title : data ? 'lucasb.dev | BucNation' : 'Error | lucasb.dev' } ,
23
- {
24
- name : 'description' ,
25
- content : `A page dedicated to East Tennessee State Basketball` ,
26
- } ,
27
-
28
- ] ;
29
-
30
- export const headers : HeadersFunction = ( ) => (
31
- {
32
- // your headers here
33
- }
34
- ) ;
43
+ export const headers : HeadersFunction = ( ) => ( {
44
+ // your headers here
45
+ } )
35
46
36
47
export const loader = async ( { request } : LoaderFunctionArgs ) => {
37
- const reqHeaders = {
38
- Pb : "MV7mOE51zp9clOm7" ,
39
- " User-Agent" :
40
- " Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36" ,
41
- } ;
48
+ const reqHeaders = {
49
+ Pb : 'iKi6oAQ2TmqZBqDc' ,
50
+ ' User-Agent' :
51
+ ' Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36' ,
52
+ }
42
53
43
- const response = await fetch ( "https://api.verbalcommits.com/vc/schools/chart/etsu" , {
44
- headers : reqHeaders ,
45
- } ) ;
46
- const data = await response . json ( ) as VCActivityType [ ] ;
47
- const filteredResults = data . filter ( ( d ) => d . status === 'ENROLLMENT' ) ;
54
+ const response = await fetch (
55
+ 'https://api.verbalcommits.com/vc/schools/chart/etsu' ,
56
+ {
57
+ headers : reqHeaders ,
58
+ } ,
59
+ )
60
+ const data = ( await response . json ( ) ) as VCActivityType [ ]
61
+ const filteredResults = data . filter ( d => d . status === 'ENROLLMENT' )
48
62
49
- return json ( { roster : filteredResults } ) ;
50
- } ;
63
+ return json ( { roster : filteredResults } )
64
+ }
51
65
52
66
export const action = async ( { request } : ActionFunctionArgs ) => {
53
- return null ;
54
- } ;
67
+ return null
68
+ }
55
69
56
70
const heightFromInches = ( total : number ) => {
57
- const feet = Math . floor ( total / 12 ) ;
58
- const inches = total % 12 ;
59
- return `${ feet } '${ inches } "` ;
71
+ const feet = Math . floor ( total / 12 )
72
+ const inches = total % 12
73
+ return `${ feet } '${ inches } "`
60
74
}
61
75
62
- export default function BucNation ( ) {
63
- const data = useLoaderData < typeof loader > ( ) ;
76
+ const games = [
77
+ {
78
+ opponent : 'TBD' ,
79
+ date : 'November 18, 2024' ,
80
+ score : {
81
+ home : 0 ,
82
+ away : 0 ,
83
+ } ,
84
+ image : 'https://generated.vusercontent.net/placeholder.svg' ,
85
+ } ,
86
+ ] ;
87
+
88
+ export default function BucNation ( ) {
89
+ const data = useLoaderData < typeof loader > ( )
64
90
65
- /* const games = [
66
- {
67
- opponent: "Los Angeles Lakers",
68
- date: "October 18, 2023",
69
- score: {
70
- home: 112,
71
- away: 104,
72
- },
73
- image: "/opponent1.jpg",
74
- }]; */
91
+ return (
92
+ < Tabs
93
+ defaultValue = "roster"
94
+ className = "mx-auto w-full max-w-6xl px-4 py-8 md:px-6"
95
+ >
96
+ < header className = "mb-8 flex flex-col sm:flex-row items-center justify-between" >
97
+ < div className = "flex items-center gap-4" >
98
+ < img
99
+ src = "https://upload.wikimedia.org/wikipedia/commons/thumb/a/ab/East_Tennessee_State_Buccaneers_logo.svg/400px-East_Tennessee_State_Buccaneers_logo.svg.png"
100
+ alt = "ETSU Team Logo"
101
+ width = { 40 }
102
+ height = { 40 }
103
+ className = "h-10 w-10"
104
+ />
105
+ < h1 className = "text-2xl font-bold" >
106
+ East Tennessee State{ ' ' }
107
+ < span className = "text-yellow-500" > Buccaneers</ span > Basketball
108
+ </ h1 >
109
+ </ div >
110
+ < TabsList className = 'mt-4 sm:mt-0' >
111
+ < TabsTrigger value = "roster" > Roster</ TabsTrigger >
112
+ < TabsTrigger value = "schedule" > Schedule</ TabsTrigger >
113
+ < TabsTrigger value = "stats" > Stats</ TabsTrigger >
114
+ </ TabsList >
115
+ </ header >
75
116
76
- return (
77
- < div className = "w-full max-w-6xl mx-auto py-8 px-4 md:px-6" >
78
- < header className = "flex items-center justify-between mb-8" >
79
- < div className = "flex items-center gap-4" >
80
- < img src = "https://upload.wikimedia.org/wikipedia/commons/thumb/a/ab/East_Tennessee_State_Buccaneers_logo.svg/400px-East_Tennessee_State_Buccaneers_logo.svg.png" alt = "ETSU Team Logo" width = { 40 } height = { 40 } className = "w-10 h-10" />
81
- < h1 className = "text-2xl font-bold" > East Tennessee State < span className = "text-yellow-500" > Buccaneers</ span > Basketball</ h1 >
82
- </ div >
83
- < div className = "flex items-center gap-4" >
84
- < Button variant = "outline" size = "sm" >
85
- Schedule
86
- </ Button >
87
- < Button variant = "outline" size = "sm" >
88
- Stats
89
- </ Button >
90
- </ div >
91
- </ header >
92
- < div className = "grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6" >
93
- { data . roster . map ( ( r ) => {
94
- return (
95
- < Card className = "p-4" key = { r . id } >
96
- < div className = "flex items-center gap-4" >
97
- < Avatar >
98
- < AvatarImage src = "/placeholder.svg" alt = { `${ r . playerFirstName } ${ r . playerLastName } ` } />
99
- < AvatarFallback > { r . playerFirstName [ 0 ] . toUpperCase ( ) } { r . playerLastName [ 0 ] . toUpperCase ( ) } </ AvatarFallback >
100
- </ Avatar >
101
- < div >
102
- < h3 className = "text-lg font-semibold" > { r . playerFirstName } { r . playerLastName } </ h3 >
103
- < p className = "text-gray-500 dark:text-gray-400" > { r . playerPosition } | { heightFromInches ( r . playerHeightInches ) } | { r . playerWeightLbs } Lbs</ p >
104
- </ div >
105
- </ div >
106
- </ Card >
107
- )
108
- } ) }
109
- </ div >
110
- { /*<h2 className="my-8 text-xl font-bold">Schedule</h2>
111
- <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
112
- {games.map((game, index) => (
113
- <Card key={index} className="p-4">
114
- <div className="flex flex-col gap-4">
115
- <div className="flex items-center justify-between">
116
- <div className="flex items-center gap-4">
117
- <img
118
- src="/placeholder.svg"
119
- alt={`Opponent ${index + 1}`}
120
- width={40}
121
- height={40}
122
- className="w-10 h-10 rounded-full"
123
- />
124
- <div>
125
- <h3 className="text-lg font-semibold">{game.opponent}</h3>
126
- <p className="text-gray-500 dark:text-gray-400">{game.date}</p>
127
- </div>
128
- </div>
129
- <div className="flex items-center gap-2">
130
- <div className="text-lg font-semibold">{game.score.home}</div>
131
- <div className="text-lg font-semibold">{game.score.away}</div>
132
- </div>
133
- </div>
134
- </div>
135
- </Card>
136
- ))}
137
- </div>*/ }
138
- </ div >
139
- ) ;
117
+ < TabsContent value = "roster" >
118
+ < h2 className = "my-8 text-xl font-bold text-center sm:text-left" > Roster</ h2 >
119
+ < div className = "grid grid-cols-1 gap-6 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4" >
120
+ { data . roster . map ( r => {
121
+ return (
122
+ < Card className = "p-4" key = { r . id } >
123
+ < div className = "flex items-center gap-4" >
124
+ < Avatar >
125
+ < AvatarImage
126
+ src = "/placeholder.svg"
127
+ alt = { `${ r . playerFirstName } ${ r . playerLastName } ` }
128
+ />
129
+ < AvatarFallback >
130
+ { r . playerFirstName [ 0 ] . toUpperCase ( ) }
131
+ { r . playerLastName [ 0 ] . toUpperCase ( ) }
132
+ </ AvatarFallback >
133
+ </ Avatar >
134
+ < div >
135
+ < h3 className = "text-lg font-semibold" >
136
+ { r . playerFirstName } { r . playerLastName }
137
+ </ h3 >
138
+ < p className = "text-gray-500 dark:text-gray-400" >
139
+ { r . playerPosition } |{ ' ' }
140
+ { heightFromInches ( r . playerHeightInches ) } |{ ' ' }
141
+ { r . playerWeightLbs } Lbs
142
+ </ p >
143
+ </ div >
144
+ </ div >
145
+ </ Card >
146
+ )
147
+ } ) }
148
+ </ div >
149
+ </ TabsContent >
150
+ < TabsContent value = "schedule" >
151
+ < h2 className = "my-8 text-xl font-bold text-center sm:text-left" > Schedule</ h2 >
152
+ < p > Coming soon..</ p >
153
+ < div className = "grid grid-cols-1 gap-6 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4" >
154
+ { games . map ( ( game , index ) => (
155
+ < Card key = { index } className = "p-4" >
156
+ < div className = "flex flex-col gap-4" >
157
+ < div className = "flex items-center justify-between" >
158
+ < div className = "flex items-center gap-4" >
159
+ < img
160
+ src = "https://generated.vusercontent.net/placeholder.svg"
161
+ alt = { `Opponent ${ index + 1 } ` }
162
+ width = { 40 }
163
+ height = { 40 }
164
+ className = "h-10 w-10 rounded-full"
165
+ />
166
+ < div >
167
+ < h3 className = "text-lg font-semibold" > { game . opponent } </ h3 >
168
+ < p className = "text-gray-500 dark:text-gray-400" >
169
+ { game . date }
170
+ </ p >
171
+ </ div >
172
+ </ div >
173
+ < div className = "flex items-center gap-2" >
174
+ < div className = "text-lg font-semibold" >
175
+ { game . score . home }
176
+ </ div >
177
+ < div className = "text-lg font-semibold" >
178
+ { game . score . away }
179
+ </ div >
180
+ </ div >
181
+ </ div >
182
+ </ div >
183
+ </ Card >
184
+ ) ) }
185
+ </ div >
186
+ </ TabsContent >
187
+ < TabsContent value = 'stats' >
188
+ < h2 className = "my-8 text-xl font-bold text-center sm:text-left" > Stats</ h2 >
189
+ < p > Coming soon..</ p >
190
+ </ TabsContent >
191
+ </ Tabs >
192
+ )
140
193
}
141
194
142
- export function ErrorBoundary ( ) {
143
- const error = useRouteError ( ) ;
144
- if ( isRouteErrorResponse ( error ) ) {
145
- return < div />
146
- }
147
- return < div />
195
+ export function ErrorBoundary ( ) {
196
+ const error = useRouteError ( )
197
+ if ( isRouteErrorResponse ( error ) ) {
198
+ return < div />
199
+ }
200
+ return < div />
148
201
}
149
202
150
203
export const shouldRevalidate : ShouldRevalidateFunction = ( ) => {
151
- return true ;
152
- } ;
204
+ return true
205
+ }
0 commit comments