Skip to content
Merged
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
17 changes: 7 additions & 10 deletions components/Book/Page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,9 @@ export default function Page(
) {
return (
<div
className={`overflow-hidden relative bg-white print:bg-none rounded-lg print:rounded-none ${
props.className ?? ""
} ${styles[props.settings.pageSize]} ${
props.onClick && "cursor-pointer"
}`}
className={`overflow-hidden relative bg-white print:bg-none rounded-lg print:rounded-none ${props.className ?? ""
} ${styles[props.settings.pageSize]} ${props.onClick && "cursor-pointer"
}`}
style={{
zIndex: props.className?.includes("turned")
? Math.abs(props.pageNumber)
Expand All @@ -36,11 +34,10 @@ export default function Page(
>
{props.pageNumber !== 0 && (
<div
className={`absolute top-6 ${
props.pageNumber % 2 !== 0
? "left-10 print:left-6"
: "right-10 print:right-6"
} ${props.settings.pageSize === "A5" && "text-sm"}`}
className={`absolute top-6 ${props.pageNumber % 2 !== 0
? "left-10 print:left-6"
: "right-10 print:right-6"
} ${props.settings.pageSize === "A5" && "text-sm"}`}
>
{props.pageNumber}
</div>
Expand Down
62 changes: 36 additions & 26 deletions components/Book/SixGamePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import ContentPage from "./ContentPage";
import MoveListTable from "../Chess/MoveListTable";
import MoveListInline from "../Chess/MoveListInline";

function GameRow(props: { index: number; settings: Settings; game: Game, totalMoveRows: number, fullLength: Boolean }) {
function GameRow(props: { settings: Settings; game: Game, otherGameMoves: number }) {
const moves = props.game.moves.split(" ");

// Find the best variant to use to get the most out the move data.
let size = "text-xs";

return (
<div>
<div className="mb-10">
<ChessBoard game={props.game} className="text-sm" />
<div className="mb-2">
<GameTitle
Expand All @@ -22,12 +22,12 @@ function GameRow(props: { index: number; settings: Settings; game: Game, totalMo
white={props.game.white}
/>
</div>
{props.totalMoveRows > 35 * (Number(props.fullLength) + 1) && moves.length > 40 * (Number(props.fullLength) + 1)
{(props.otherGameMoves + props.game.movesCount) < 65 * 2
? (
<MoveListInline moves={moves} highlightedPly={props.game.board.ply} size={size} />
<MoveListTable moves={moves} highlightedPly={props.game.board.ply} size={size} columns="columns-2 gap-4" />
)
: (
<MoveListTable moves={moves} highlightedPly={props.game.board.ply} size={size} columns="columns-2 gap-4" />
<MoveListInline moves={moves} highlightedPly={props.game.board.ply} size={size} />
)}
</div>
);
Expand All @@ -38,32 +38,42 @@ export default function SixGamePage(props: PageProps & { games: Game[] }) {
return b.movesCount - a.movesCount;
});

const totalMoveRows = sortedByMoveCountGames[0].movesCount + (sortedByMoveCountGames[3]?.movesCount ?? 0) / 2;
const columns: [number, number | undefined][] = [];
const offset = sortedByMoveCountGames.length - 1;

for (let i = 0; i < 3; i++) {
if (!sortedByMoveCountGames[i]) {
break;
}

const newColumn: [number, number | undefined] = [i, undefined];
const key = offset - i;
if (offset - 1 > 2 && sortedByMoveCountGames[key]) {
Copy link

Copilot AI Dec 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The condition checks if offset - 1 > 2 but this logic seems inverted or unclear. When offset (which is sortedByMoveCountGames.length - 1) minus 1 is greater than 2, it means we have at least 4 games. However, the comment says "if offset - 1 > 2" suggests checking if we have enough games for a second column. Consider clarifying this logic or adding a comment explaining the condition, as the relationship between offset and column pairing is not immediately obvious.

Suggested change
if (offset - 1 > 2 && sortedByMoveCountGames[key]) {
// Pair the i-th game with the (length - 1 - i)-th game if there are enough games for a pair in this column
if (sortedByMoveCountGames.length > i * 2 + 1 && sortedByMoveCountGames[key]) {

Copilot uses AI. Check for mistakes.
newColumn[1] = key;
}

let yGap = 'gap-y-4';
if (totalMoveRows < 80) {
yGap = 'gap-y-20';
} else if (totalMoveRows < 160) {
yGap = 'gap-y-12';
} else if (totalMoveRows < 220) {
yGap = 'gap-y-8';
} else {
yGap = 'gap-y-4';
columns.push(newColumn);
}

return (
<ContentPage {...props}>
<div className={`grid grid-cols-3 gap-x-4 ${yGap} ${totalMoveRows}`}>
{sortedByMoveCountGames.map((game, i) => (
<GameRow
index={i}
key={game.id}
settings={props.settings}
game={game}
totalMoveRows={totalMoveRows}
fullLength={props.games.length < 4}
/>
))}
<div className={`grid grid-cols-3 gap-x-4 gap-y-4`}>
{
columns.map((pair) => (<div key={`${pair.join("-")}`}>
<GameRow
key={pair[0]}
settings={props.settings}
game={sortedByMoveCountGames[pair[0]]}
otherGameMoves={pair[1] ? sortedByMoveCountGames[pair[1]].movesCount : 0}
/>
{pair[1] && <GameRow
key={pair[1]}
settings={props.settings}
game={sortedByMoveCountGames[pair[1]]}
otherGameMoves={sortedByMoveCountGames[pair[0]].movesCount}
/>}
</div>))
}
</div>
</ContentPage>
);
Expand Down
99 changes: 99 additions & 0 deletions components/Book/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,53 @@ export default function Book(
</ContentPage>,
);

// Stat Page.
pages.push(
<ContentPage
key="stat-page"
settings={props.data.settings}
className={activePage > pages.length ? "turned" : ""}
onClick={pageClickHandler}
pageNumber={pages.length}
>
<div
className="pt-30 text-center text-2xl"
style={{ zoom: props.data.settings.pageSize === "A5" ? 1 : 1.5 }}
>
<h1 className="font-[Anton] text-4xl pb-12">Stats</h1>
<table className="mx-auto text-left">
<tbody>
<tr>
<th className="p-2 font-normal text-right">Games:</th>
<td className="font-[Anton]">{props.data.games.length.toLocaleString()}</td>
</tr>
<tr>
<th className="p-2 font-normal text-right">Players:</th>
<td className="font-[Anton]">
{Array.from(new Set(props.data.games.flatMap(game => [game.white.name, game.black.name]))).length.toLocaleString()}
</td>
</tr>
</tbody>
</table>

<div className="flex flex-col items-center justify-center mt-16 space-y-4">
<div className="flex items-center justify-center space-x-6">
<h2 className="font-[Anton] text-4xl">The best game</h2>
<span
className="text-[6rem] font-black leading-none"
aria-label="arrow right"
>
</span>
</div>
<p className="text-sm italic opacity-80">
Based on the highest ELO of both players combined.
</p>
</div>
</div>
</ContentPage>,
);

const gamePages = convertGamesToPages(props.data.settings, props.data.games);
for (const gamePage of gamePages) {
if (gamePage.type === 'one') {
Expand Down Expand Up @@ -143,6 +190,23 @@ export default function Book(
}
}

// Notes
for (let i = 0; i < 2; i++) {
pages.push(
<ContentPage
key="notes"
pageNumber={pages.length}
settings={props.data.settings}
className={activePage > pages.length ? "turned" : ""}
onClick={pageClickHandler}
>
<div className="px-20 m-auto text-center font-[Anton] text-4xl">
Notes
</div>
</ContentPage>,
);
}

if (pages.length % 2 === 0) {
pages.push(
<Page
Expand All @@ -155,6 +219,7 @@ export default function Book(
);
}

// Back cover.
pages.push(
<CoverPage
key="back-cover"
Expand Down Expand Up @@ -185,6 +250,40 @@ export default function Book(
</CoverPage>,
);

// Spine
// pages.push(
// <CoverPage
// key="spine"
// settings={props.data.settings}
// className={activePage > pages.length ? "turned" : ""}
// onClick={pageClickHandler}
// pageNumber={-pages.length}
// >
// <div>
// <div
// className="absolute inset-0 bg-cover bg-middle z-0"
// style={{
// backgroundImage: `url(/covers/${cover}.jpg)`,
// }}
// />

// <div className="absolute inset-0 z-5 pointer-events-none shadow-[inset_0_0_40px_20px_rgba(0,0,0,0.3)]" />

// <h1
// className="absolute top-1/2 -mt-7 left-0 right-10 z-10 text-center text-4xl font-bold text-white font-[Anton] tracking-[0.075em] text-shadow-lg text-shadow-black"
// style={{ zoom: props.data.settings.pageSize === "A5" ? 1 : 1.5 }}
// >
// <div className="text-6xl">The {props.data.user.name} Chess Book</div>
// </h1>
// <div className="font-[Anton] text-shadow-lg text-shadow-black text-6xl text-white absolute right-10 pr-0 top-1/2 -translate-y-1/2 text-8xl -rotate-90 origin-center pr-[12px]">
// ♞
// </div>
// </div>
// </CoverPage>,
// );

console.log({ allPages: pages.length });

return (
<div
className={`print:w-auto mx-auto book-container simulate print:block print:mx-0 ${props.data.settings.pageSize === "A4"
Expand Down
2 changes: 2 additions & 0 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ const nextTranslate = require('next-translate-plugin')
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
// output: 'export',
devIndicators: false,
experimental: {
reactCompiler: true,
},
Expand Down
Binary file added public/pieces/background.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 4 additions & 2 deletions styles/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,9 @@ body {
}

.chessboard {
-webkit-print-color-adjust: exact;
background: url(/pieces/background.png?2) top left repeat;

/* -webkit-print-color-adjust: exact;
print-color-adjust: exact;
color-adjust: exact;

Expand All @@ -103,7 +105,7 @@ body {
white 2px,
var(--color-gray-400) 2px,
var(--color-gray-400) 4px
);
); */
}


Expand Down
14 changes: 9 additions & 5 deletions types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@ export type ChessPage = {
games: [Game],
} | {
type: 'three',
games: [Game, Game, Game | undefined],
} | {
type: 'four',
games: [Game, Game, Game, Game],
games: [Game]
| [Game, Game]
| [Game, Game, Game],
} | {
type: 'six',
games: [Game, Game, Game, Game, Game | undefined, Game | undefined],
games: [Game]
| [Game, Game]
| [Game, Game, Game]
| [Game, Game, Game, Game]
| [Game, Game, Game, Game, Game]
| [Game, Game, Game, Game, Game, Game],
}

export type User = {
Expand Down
Loading