Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions components/tables/PlayerAwardsTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import {
createColumnHelper,
getCoreRowModel,
getSortedRowModel,
useReactTable,
} from '@tanstack/react-table';
import { useMemo } from 'react';

import { InternalPlayerAchievement } from '../../typings/portalApi';

import { Table } from './Table';
import { AWARD_TABLE_FLAGS } from './tableBehavioralFlags';
import { TableHeader } from './TableHeader';

const columnHelper = createColumnHelper<InternalPlayerAchievement>();

export const PlayerAwards = ({
playerAwards,
}: {
playerAwards: InternalPlayerAchievement[];
}) => {
const columns = useMemo(
() => [
columnHelper.accessor('seasonID', {
header: () => <TableHeader title="Season">Season</TableHeader>,
enableGlobalFilter: true,
}),
columnHelper.accessor(
(row) => {
const result = row.isAward ? (row.won ? 'Won' : 'Nom') : '';
return `${row.achievementName}${result ? ` - ${result}` : ''}`;
},
{
id: 'awardResult',
header: () => <TableHeader title="Award">Award</TableHeader>,
enableGlobalFilter: true,
},
),
columnHelper.accessor('teamID', {
header: () => <TableHeader title="Team">Team</TableHeader>, //Figure out way to put team Abbr or logo here
enableGlobalFilter: true,
}),
],
[],
);

const table = useReactTable({
columns,
data: playerAwards,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
initialState: {
sorting: [{ id: 'seasonID', desc: true }],
},
});

return (
<Table<InternalPlayerAchievement>
table={table}
tableBehavioralFlags={AWARD_TABLE_FLAGS()}
label="player_awards"
/>
);
};
9 changes: 9 additions & 0 deletions components/tables/tableBehavioralFlags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ export const SKATER_TABLE_FLAGS = ({
showTableFilterOptions: playerType !== 'goalie',
});

export const AWARD_TABLE_FLAGS = (): TableBehavioralFlags => ({
stickyFirstColumn: false,
showTableFooter: false,
showCSVExportButton: false,
enablePagination: false,
enableFiltering: false,
showTableFilterOptions: false,
});

export interface TableBehavioralFlags {
stickyFirstColumn: boolean;
showTableFooter: boolean;
Expand Down
54 changes: 51 additions & 3 deletions pages/[league]/player/[id].tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { ExternalLinkIcon } from '@chakra-ui/icons';
import {
Link,
Spinner,
Tab,
TabList,
Expand All @@ -8,11 +10,16 @@ import {
} from '@chakra-ui/react';
import { dehydrate, QueryClient, useQuery } from '@tanstack/react-query';
import classnames from 'classnames';
import { PlayerAwards } from 'components/tables/PlayerAwardsTable';
import { GetServerSideProps } from 'next';
import { useRouter } from 'next/router';
import { NextSeo } from 'next-seo';
import { useTheme } from 'next-themes';
import { useEffect, useRef } from 'react';
import {
InternalIndexPlayerID,
InternalPlayerAchievement,
} from 'typings/portalApi';

import { Footer } from '../../../components/Footer';
import { Header } from '../../../components/Header';
Expand All @@ -31,7 +38,7 @@ import {
PlayerWithAdvancedStats,
} from '../../../typings/api';
import { League, leagueNameToId } from '../../../utils/leagueHelpers';
import { query } from '../../../utils/query';
import { portalQuery, query } from '../../../utils/query';
import { seasonTypeToApiFriendlyParam } from '../../../utils/seasonTypeHelpers';
import { GoalieRatings } from '../../api/v1/goalies/ratings/[id]';
import { SkaterRatings as PlayerRatings } from '../../api/v1/players/ratings/[id]';
Expand All @@ -49,6 +56,20 @@ const fetchPlayerName = (league: League, playerId: string) =>
)}&playerId=${playerId}`,
);

const fetchPlayerAwards = (league: League, playerId: string) =>
portalQuery(
`api/v1/history/player?leagueID=${leagueNameToId(
league,
)}&fhmID=${playerId}`,
);

const fetchPortalID = (league: League, playerId: string) =>
portalQuery(
`api/v1/player/index-ids?leagueID=${leagueNameToId(
league,
)}&indexID=${playerId}`,
);

export default ({ playerId, league }: { playerId: string; league: League }) => {
const router = useRouter();

Expand Down Expand Up @@ -94,6 +115,16 @@ export default ({ playerId, league }: { playerId: string; league: League }) => {
enabled: !!playerTypeInfo,
});

const { data: playerAwards } = useQuery<InternalPlayerAchievement[]>({
queryKey: ['playerAwards', league, playerId],
queryFn: () => fetchPlayerAwards(league, playerId),
});

const { data: playerPortalID } = useQuery<InternalIndexPlayerID[]>({
queryKey: ['playerPortalID', league, playerId],
queryFn: () => fetchPortalID(league, playerId),
});

const { data: playerRatings } = useQuery<PlayerRatings[] | GoalieRatings[]>({
queryKey: ['playerRatings', league, playerId, playerTypeInfo?.playerType],
queryFn: () => {
Expand All @@ -105,7 +136,7 @@ export default ({ playerId, league }: { playerId: string; league: League }) => {
)}`,
);
},
enabled: !!playerTypeInfo?.playerType ,
enabled: !!playerTypeInfo?.playerType,
});

const { data: playerStats } = useQuery<PlayerWithAdvancedStats[] | Goalie[]>({
Expand Down Expand Up @@ -184,9 +215,23 @@ export default ({ playerId, league }: { playerId: string; league: League }) => {
teamAbbreviation={playerInfo[0]?.team}
className="mt-10 size-40 md:mt-2.5"
/>
<div className="text-3xl font-bold uppercase">
<div className="group flex items-center gap-2 text-3xl font-bold uppercase">
{playerNameInfo?.name ?? 'Player'}
</div>
<div>
{playerPortalID && playerPortalID.length > 0 && (
<Link
className="!text-blue600"
href={`https://portal.simulationhockey.com/player/${playerPortalID[0].playerUpdateID}`}
isExternal
//Need to figure out system of when 2 players are on the same ID.
// Is it fix it in the db? Would be the best way. Need to talk with Grok
// Biggest glare is IIHF and WJC Files. Then sometimes SMJHL as well
>
View in portal <ExternalLinkIcon />
</Link>
)}
</div>
<div className="text-center font-mont text-lg uppercase">
{'position' in playerInfo[0] ? playerInfo[0].position : 'G'} |{' '}
{Math.floor(playerInfo[0].height / 12)} ft{' '}
Expand Down Expand Up @@ -282,6 +327,9 @@ export default ({ playerId, league }: { playerId: string; league: League }) => {
</TabPanel>
</TabPanels>
</Tabs>
{playerAwards && playerAwards.length > 0 && (
<PlayerAwards playerAwards={playerAwards} />
)}
</div>
)}
</div>
Expand Down
21 changes: 21 additions & 0 deletions typings/portalApi.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export type InternalPlayerAchievement = {
playerUpdateID: number | null;
playerName: string;
userID: number | null;
fhmID: number;
leagueID: number;
seasonID: number;
teamID: number;
achievement: number;
achievementName: string;
achievementDescription: string;
isAward: boolean;
won: boolean;
};

export type InternalIndexPlayerID = {
playerUpdateID: number;
leagueID: number;
indexID: number;
startSeason: number;
};
9 changes: 9 additions & 0 deletions utils/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,12 @@ export const query = async (uri: string) => {
}
return response.json();
};

export const portalQuery = async (uri: string) => {
const response = await fetch(`https://portal.simulationhockey.com/${uri}`);

if (!response.ok) {
throw new Error('Network request failed');
}
return response.json();
};