mirror of
https://github.com/ershisan99/www.git
synced 2026-01-29 12:35:47 +00:00
show transcripts in a modal instead of a pop-up
This commit is contained in:
@@ -2,6 +2,12 @@
|
|||||||
|
|
||||||
import { Badge } from '@/components/ui/badge'
|
import { Badge } from '@/components/ui/badge'
|
||||||
import { Button } from '@/components/ui/button'
|
import { Button } from '@/components/ui/button'
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
} from '@/components/ui/dialog'
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
TableBody,
|
TableBody,
|
||||||
@@ -41,24 +47,8 @@ function getTranscript(gameNumber: number) {
|
|||||||
`https://api.neatqueue.com/api/transcript/1226193436521267223/${gameNumber}`
|
`https://api.neatqueue.com/api/transcript/1226193436521267223/${gameNumber}`
|
||||||
).then((res) => res.json())
|
).then((res) => res.json())
|
||||||
}
|
}
|
||||||
function openTranscript(gameNumber: number): void {
|
// This function is now moved inside the GamesTable component
|
||||||
getTranscript(gameNumber)
|
const useColumns = (openTranscriptFn?: (gameNumber: number) => void) => {
|
||||||
.then((html: string) => {
|
|
||||||
const newWindow = window.open('', '_blank')
|
|
||||||
if (newWindow) {
|
|
||||||
newWindow.document.write(html)
|
|
||||||
newWindow.document.close()
|
|
||||||
} else {
|
|
||||||
console.error(
|
|
||||||
'Failed to open new window - popup blocker may be enabled'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.error('Failed to load transcript:', err)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
const useColumns = () => {
|
|
||||||
const format = useFormatter()
|
const format = useFormatter()
|
||||||
const timeZone = useTimeZone()
|
const timeZone = useTimeZone()
|
||||||
const session = useSession()
|
const session = useSession()
|
||||||
@@ -186,7 +176,9 @@ const useColumns = () => {
|
|||||||
cell: (info) => (
|
cell: (info) => (
|
||||||
<Button
|
<Button
|
||||||
size={'sm'}
|
size={'sm'}
|
||||||
onClick={() => openTranscript(info.getValue())}
|
onClick={() =>
|
||||||
|
openTranscriptFn ? openTranscriptFn(info.getValue()) : null
|
||||||
|
}
|
||||||
type={'button'}
|
type={'button'}
|
||||||
variant={'ghost'}
|
variant={'ghost'}
|
||||||
>
|
>
|
||||||
@@ -204,7 +196,28 @@ const useColumns = () => {
|
|||||||
|
|
||||||
export function GamesTable({ games }: { games: SelectGames[] }) {
|
export function GamesTable({ games }: { games: SelectGames[] }) {
|
||||||
const [sorting, setSorting] = useState<SortingState>([])
|
const [sorting, setSorting] = useState<SortingState>([])
|
||||||
const columns = useColumns()
|
const [isDialogOpen, setIsDialogOpen] = useState(false)
|
||||||
|
const [transcriptContent, setTranscriptContent] = useState<string>('')
|
||||||
|
const [transcriptGameNumber, setTranscriptGameNumber] = useState<
|
||||||
|
number | null
|
||||||
|
>(null)
|
||||||
|
|
||||||
|
// New openTranscript function that sets state instead of opening a new window
|
||||||
|
const openTranscript = (gameNumber: number): void => {
|
||||||
|
setTranscriptGameNumber(gameNumber)
|
||||||
|
getTranscript(gameNumber)
|
||||||
|
.then((html: string) => {
|
||||||
|
setTranscriptContent(html)
|
||||||
|
setIsDialogOpen(true)
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error('Failed to load transcript:', err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pass the openTranscript function to useColumns
|
||||||
|
const columns = useColumns(openTranscript)
|
||||||
|
|
||||||
const table = useReactTable({
|
const table = useReactTable({
|
||||||
data: games,
|
data: games,
|
||||||
columns,
|
columns,
|
||||||
@@ -218,68 +231,92 @@ export function GamesTable({ games }: { games: SelectGames[] }) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='rounded-md border'>
|
<>
|
||||||
<Table>
|
<div className='rounded-md border'>
|
||||||
<TableHeader>
|
<Table>
|
||||||
{table.getHeaderGroups().map((headerGroup) => (
|
<TableHeader>
|
||||||
<TableRow key={headerGroup.id}>
|
{table.getHeaderGroups().map((headerGroup) => (
|
||||||
{headerGroup.headers.map((header) => {
|
<TableRow key={headerGroup.id}>
|
||||||
const sortDirection = header.column.getIsSorted()
|
{headerGroup.headers.map((header) => {
|
||||||
return (
|
const sortDirection = header.column.getIsSorted()
|
||||||
<TableHead key={header.id} className={'px-0'}>
|
return (
|
||||||
<span
|
<TableHead key={header.id} className={'px-0'}>
|
||||||
className={cn(
|
<span
|
||||||
'flex w-full items-center',
|
|
||||||
(header.column.columnDef.meta as any)?.className
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
className={cn(
|
className={cn(
|
||||||
header.column.getCanSort() &&
|
'flex w-full items-center',
|
||||||
'cursor-pointer select-none',
|
(header.column.columnDef.meta as any)?.className
|
||||||
(
|
|
||||||
header.column.columnDef.meta as any
|
|
||||||
)?.className?.includes('justify-end') &&
|
|
||||||
'flex-row-reverse'
|
|
||||||
)}
|
)}
|
||||||
size={'table'}
|
|
||||||
variant='ghost'
|
|
||||||
onClick={header.column.getToggleSortingHandler()}
|
|
||||||
>
|
>
|
||||||
{flexRender(
|
<Button
|
||||||
header.column.columnDef.header,
|
className={cn(
|
||||||
header.getContext()
|
header.column.getCanSort() &&
|
||||||
)}
|
'cursor-pointer select-none',
|
||||||
{sortDirection ? (
|
(
|
||||||
<ArrowUp
|
header.column.columnDef.meta as any
|
||||||
className={cn(
|
)?.className?.includes('justify-end') &&
|
||||||
'transition-transform',
|
'flex-row-reverse'
|
||||||
sortDirection === 'asc' ? 'rotate-180' : ''
|
)}
|
||||||
)}
|
size={'table'}
|
||||||
/>
|
variant='ghost'
|
||||||
) : (
|
onClick={header.column.getToggleSortingHandler()}
|
||||||
<div className={'h-4 w-4'} />
|
>
|
||||||
)}
|
{flexRender(
|
||||||
</Button>
|
header.column.columnDef.header,
|
||||||
</span>
|
header.getContext()
|
||||||
</TableHead>
|
)}
|
||||||
)
|
{sortDirection ? (
|
||||||
})}
|
<ArrowUp
|
||||||
</TableRow>
|
className={cn(
|
||||||
))}
|
'transition-transform',
|
||||||
</TableHeader>
|
sortDirection === 'asc' ? 'rotate-180' : ''
|
||||||
<TableBody>
|
)}
|
||||||
{table.getRowModel().rows.map((row) => (
|
/>
|
||||||
<TableRow key={row.id}>
|
) : (
|
||||||
{row.getVisibleCells().map((cell) => (
|
<div className={'h-4 w-4'} />
|
||||||
<TableCell key={cell.id}>
|
)}
|
||||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
</Button>
|
||||||
</TableCell>
|
</span>
|
||||||
))}
|
</TableHead>
|
||||||
</TableRow>
|
)
|
||||||
))}
|
})}
|
||||||
</TableBody>
|
</TableRow>
|
||||||
</Table>
|
))}
|
||||||
</div>
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
|
{table.getRowModel().rows.map((row) => (
|
||||||
|
<TableRow key={row.id}>
|
||||||
|
{row.getVisibleCells().map((cell) => (
|
||||||
|
<TableCell key={cell.id}>
|
||||||
|
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||||
|
</TableCell>
|
||||||
|
))}
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Transcript Dialog */}
|
||||||
|
<Dialog open={isDialogOpen} onOpenChange={setIsDialogOpen}>
|
||||||
|
<DialogContent className='max-h-[80vh] w-full overflow-y-auto sm:max-w-[calc(100%-2rem)] '>
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>
|
||||||
|
{transcriptGameNumber
|
||||||
|
? `Game Transcript #${transcriptGameNumber}`
|
||||||
|
: 'Game Transcript'}
|
||||||
|
</DialogTitle>
|
||||||
|
</DialogHeader>
|
||||||
|
{/* Use iframe to isolate the transcript content and prevent style leakage */}
|
||||||
|
<div className='!h-[60vh] mt-4 w-full'>
|
||||||
|
<iframe
|
||||||
|
srcDoc={transcriptContent}
|
||||||
|
title={`Game Transcript #${transcriptGameNumber || ''}`}
|
||||||
|
className='h-full w-full border-0'
|
||||||
|
sandbox='allow-same-origin'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user