1
1
import {
2
- type HeadersFunction ,
3
2
type LoaderFunctionArgs ,
4
3
type ActionFunctionArgs ,
5
4
json ,
@@ -20,16 +19,50 @@ import {
20
19
TabsTrigger ,
21
20
} from '#app/components/ui/tabs'
22
21
23
- interface VCActivityType {
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
22
+ interface RosterItem {
23
+ name : string
24
+ position : string
25
+ height : string
26
+ weight : string
27
+ year : string
28
+ headshot : string
29
+ }
30
+
31
+ interface RosterApiRes {
32
+ type : string
33
+ roster : RosterItem [ ]
34
+ }
35
+
36
+ interface ScheduleItem {
37
+ opponent : string
38
+ vsat : string
39
+ date : string
40
+ time : string
41
+ result : string
42
+ score : string
43
+ opponentLogo : string
44
+ }
45
+
46
+ interface ScheduleApiRes {
47
+ type : string
48
+ schedule : ScheduleItem [ ]
49
+ }
50
+
51
+ interface StatsItem {
52
+ assists : string
53
+ firstName : string
54
+ lastName : string
55
+ minutes : string
56
+ points : string
57
+ rebounds : string
58
+ steals : string
59
+ fgPercent : string
60
+ threePercent : string
61
+ }
62
+
63
+ interface StatsApiRes {
64
+ type : string
65
+ stats : StatsItem [ ]
33
66
}
34
67
35
68
export const meta : MetaFunction = ( { data } ) => [
@@ -40,100 +73,38 @@ export const meta: MetaFunction = ({ data }) => [
40
73
} ,
41
74
]
42
75
43
- export const headers : HeadersFunction = ( ) => ( {
44
- // your headers here
45
- } )
46
-
47
76
export const loader = async ( { request } : LoaderFunctionArgs ) => {
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
- }
77
+ const hoopsApi = process . env . HOOPS_API ;
78
+ const responsePromises = await Promise . all ( [
79
+ fetch ( `${ hoopsApi } /api/etsu/roster` ) ,
80
+ fetch ( `${ hoopsApi } /api/etsu/schedule` ) ,
81
+ fetch ( `${ hoopsApi } /api/etsu/stats` ) ,
82
+ ] )
53
83
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' )
84
+ const responseData = ( await Promise . all (
85
+ responsePromises . map ( response => response . json ( ) ) ,
86
+ ) ) as [ RosterApiRes , ScheduleApiRes , StatsApiRes ]
87
+ // console.log('LOG: loaderData', responseData)
62
88
63
- return json ( { roster : filteredResults } )
89
+ return json ( {
90
+ roster : responseData [ 0 ] ,
91
+ schedule : responseData [ 1 ] ,
92
+ stats : responseData [ 2 ] ,
93
+ } )
64
94
}
65
95
66
96
export const action = async ( { request } : ActionFunctionArgs ) => {
67
97
return null
68
98
}
69
99
70
- const heightFromInches = ( total : number ) => {
100
+ export const heightFromInches = ( total : number ) => {
71
101
const feet = Math . floor ( total / 12 )
72
102
const inches = total % 12
73
103
return `${ feet } '${ inches } "`
74
104
}
75
105
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
- const stats = [
89
- {
90
- firstName : 'Tester' ,
91
- lastName : 'McNester' ,
92
- position : 'SF' ,
93
- height : '6\'9"' ,
94
- points : 27.4 ,
95
- rebounds : 7.8 ,
96
- assists : 7.2 ,
97
- blocks : 1.1 ,
98
- steals : 1.3 ,
99
- } ,
100
- {
101
- firstName : 'Tester' ,
102
- lastName : 'McNester' ,
103
- position : 'SF' ,
104
- height : '6\'9"' ,
105
- points : 27.4 ,
106
- rebounds : 7.8 ,
107
- assists : 7.2 ,
108
- blocks : 1.1 ,
109
- steals : 1.3 ,
110
- } ,
111
- {
112
- firstName : 'Tester' ,
113
- lastName : 'McNester' ,
114
- position : 'SF' ,
115
- height : '6\'9"' ,
116
- points : 27.4 ,
117
- rebounds : 7.8 ,
118
- assists : 7.2 ,
119
- blocks : 1.1 ,
120
- steals : 1.3 ,
121
- } ,
122
- {
123
- firstName : 'Tester' ,
124
- lastName : 'McNester' ,
125
- position : 'SF' ,
126
- height : '6\'9"' ,
127
- points : 27.4 ,
128
- rebounds : 7.8 ,
129
- assists : 7.2 ,
130
- blocks : 1.1 ,
131
- steals : 1.3 ,
132
- } ,
133
- ]
134
-
135
106
export default function BucNation ( ) {
136
- const data = useLoaderData < typeof loader > ( )
107
+ const { roster , schedule , stats } = useLoaderData < typeof loader > ( )
137
108
138
109
return (
139
110
< Tabs
@@ -166,28 +137,22 @@ export default function BucNation() {
166
137
Roster
167
138
</ h2 >
168
139
< div className = "grid grid-cols-1 gap-6 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4" >
169
- { data . roster . map ( r => {
140
+ { roster . roster . map ( r => {
170
141
return (
171
- < Card className = "p-4" key = { r . id } >
142
+ < Card className = "p-4" key = { r . name } >
172
143
< div className = "flex items-center gap-4" >
173
144
< Avatar >
174
145
< AvatarImage
175
- src = "/placeholder.svg"
176
- alt = { `${ r . playerFirstName } ${ r . playerLastName } ` }
146
+ src = { `https://etsubucs.com/ ${ r . headshot } ` }
147
+ alt = { `${ r . name } ` }
177
148
/>
178
- < AvatarFallback >
179
- { r . playerFirstName [ 0 ] . toUpperCase ( ) }
180
- { r . playerLastName [ 0 ] . toUpperCase ( ) }
181
- </ AvatarFallback >
149
+ < AvatarFallback > { r . name [ 0 ] . toUpperCase ( ) } </ AvatarFallback >
182
150
</ Avatar >
183
151
< div >
184
- < h3 className = "text-lg font-semibold" >
185
- { r . playerFirstName } { r . playerLastName }
186
- </ h3 >
152
+ < h3 className = "text-lg font-semibold" > { r . name } </ h3 >
187
153
< p className = "text-gray-500 dark:text-gray-400" >
188
- { r . playerPosition } |{ ' ' }
189
- { heightFromInches ( r . playerHeightInches ) } |{ ' ' }
190
- { r . playerWeightLbs } Lbs
154
+ { r . position } | { r . height }
155
+ { r . weight }
191
156
</ p >
192
157
</ div >
193
158
</ div >
@@ -198,35 +163,31 @@ export default function BucNation() {
198
163
</ TabsContent >
199
164
< TabsContent value = "schedule" >
200
165
< h2 className = "my-8 text-center text-xl font-bold sm:text-left" >
201
- Schedule (coming soon..)
166
+ Schedule
202
167
</ h2 >
203
- < div className = "grid grid-cols-1 gap-6 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 " >
204
- { games . map ( ( game , index ) => (
168
+ < div className = "grid grid-cols-1 gap-6 sm:grid-cols-2 md:grid-cols-3" >
169
+ { schedule . schedule . map ( ( item , index : number ) => (
205
170
< Card key = { index } className = "p-4" >
206
171
< div className = "flex flex-col gap-4" >
207
172
< div className = "flex items-center justify-between" >
208
173
< div className = "flex items-center gap-4" >
209
- < img
210
- src = "https://generated.vusercontent.net/placeholder.svg"
211
- alt = { `Opponent ${ index + 1 } ` }
212
- width = { 40 }
213
- height = { 40 }
214
- className = "h-10 w-10 rounded-full"
215
- / >
174
+ < Avatar >
175
+ < AvatarImage
176
+ src = { `https://etsubucs.com/ ${ item . opponentLogo } ` }
177
+ alt = { ` ${ item . opponent } ` }
178
+ />
179
+ < AvatarFallback > { item . vsat } </ AvatarFallback >
180
+ </ Avatar >
216
181
< div >
217
- < h3 className = "text-lg font-semibold" > { game . opponent } </ h3 >
182
+ < h3 className = "text-lg font-semibold" > { item . vsat } { item . opponent } </ h3 >
218
183
< p className = "text-gray-500 dark:text-gray-400" >
219
- { game . date }
184
+ { item . date }
220
185
</ p >
221
186
</ div >
222
187
</ div >
223
188
< div className = "flex items-center gap-2" >
224
- < div className = "text-lg font-semibold" >
225
- { game . score . home }
226
- </ div >
227
- < div className = "text-lg font-semibold" >
228
- { game . score . away }
229
- </ div >
189
+ < div className = "text-lg font-semibold" > { item . result } </ div >
190
+ < div className = "text-lg font-semibold" > { item . score } </ div >
230
191
</ div >
231
192
</ div >
232
193
</ div >
@@ -236,21 +197,21 @@ export default function BucNation() {
236
197
</ TabsContent >
237
198
< TabsContent value = "stats" >
238
199
< h2 className = "my-8 text-center text-xl font-bold sm:text-left" >
239
- Player Stats (coming soon)
200
+ Player Stats
240
201
</ h2 >
241
- < div className = "grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 " >
242
- { stats . map ( ( player , index ) => (
202
+ < div className = "grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3" >
203
+ { stats . stats . map ( ( player , index : number ) => (
243
204
< div
244
205
key = { index }
245
206
className = "flex flex-col gap-6 rounded-lg bg-white p-6 shadow-md dark:bg-gray-950"
246
207
>
247
208
< div className = "flex items-center justify-between" >
248
209
< div className = "flex items-center gap-4" >
249
210
< h3 className = "text-xl font-bold" >
250
- { player . firstName [ 0 ] . toUpperCase ( ) } . { player . lastName }
211
+ { player . firstName [ 0 ] } . { player . lastName }
251
212
</ h3 >
252
213
< span className = "text-sm text-gray-500 dark:text-gray-400" >
253
- { player . position } | { player . height }
214
+ { `MPG: $ {player . minutes } ` }
254
215
</ span >
255
216
</ div >
256
217
</ div >
@@ -259,41 +220,30 @@ export default function BucNation() {
259
220
< span className = "text-sm text-gray-500 dark:text-gray-400" >
260
221
Pts
261
222
</ span >
262
- < span className = "font-medium" >
263
- { player . points . toFixed ( 1 ) }
264
- </ span >
223
+ < span className = "font-medium" > { player . points } </ span >
265
224
</ div >
266
225
< div className = "flex flex-col items-end" >
267
226
< span className = "text-sm text-gray-500 dark:text-gray-400" >
268
227
Reb
269
228
</ span >
270
- < span className = "font-medium" >
271
- { player . rebounds . toFixed ( 1 ) }
272
- </ span >
229
+ < span className = "font-medium" > { player . rebounds } </ span >
273
230
</ div >
274
231
< div className = "flex flex-col items-end" >
275
232
< span className = "text-sm text-gray-500 dark:text-gray-400" >
276
233
Ast
277
234
</ span >
278
- < span className = "font-medium" >
279
- { player . assists . toFixed ( 1 ) }
280
- </ span >
235
+ < span className = "font-medium" > { player . assists } </ span >
281
236
</ div >
282
237
< div className = "flex flex-col items-end" >
283
238
< span className = "text-sm text-gray-500 dark:text-gray-400" >
284
- Blk
239
+ 3pt%
285
240
</ span >
286
- < span className = "font-medium" >
287
- { player . blocks . toFixed ( 1 ) }
288
- </ span >
289
- </ div >
290
- < div className = "flex flex-col items-end" >
241
+ < span className = "font-medium" > { player . threePercent } </ span >
242
+ </ div > < div className = "flex flex-col items-end" >
291
243
< span className = "text-sm text-gray-500 dark:text-gray-400" >
292
- Stl
293
- </ span >
294
- < span className = "font-medium" >
295
- { player . steals . toFixed ( 1 ) }
244
+ Fg%
296
245
</ span >
246
+ < span className = "font-medium" > { player . fgPercent } </ span >
297
247
</ div >
298
248
</ div >
299
249
</ div >
0 commit comments