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
36 changes: 24 additions & 12 deletions front-end/components/BackBookmark.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import PropTypes from "prop-types";

const BackBookmark = ({ label, targetPage, y, onClick, zIndex, color = "#77425f", stroke = "#5a2f49" }) => {
const BackBookmark = ({ label, targetPage, x, onClick, zIndex, color = "#77425f", stroke = "#5a2f49" }) => {
const handleClick = (e) => {
if (onClick) {
onClick(e, targetPage); // send target page up
Expand All @@ -13,29 +13,41 @@ const BackBookmark = ({ label, targetPage, y, onClick, zIndex, color = "#77425f"
className="bookmark-container back-bookmark"
onClick={handleClick}
style={{
top: y,
right: x,
zIndex: zIndex || 10,
position: "absolute",
right: "auto",
cursor: "pointer",
}}
>
<svg viewBox="0 0 300 100" preserveAspectRatio="none">
<svg viewBox="0 0 120 200" preserveAspectRatio="none">
<defs>
{/* Vertical gradient */}
<linearGradient id="bookmarkGrad" x1="0" x2="0" y1="0" y2="1">
<stop offset="10%" stopColor={color}/>
<stop offset="100%" stopColor={color} stopOpacity=".7"/>
</linearGradient>
</defs>

{/* Main body */}
<polygon
points="300,0 40,0 0,50 40,100 300,100"
points="0,40 0,200 50,160 100,200 100,40"
fill={color}
stroke={stroke}
strokeWidth="1"
/>
{/* Inner dashed border */}
<polygon
points="295,5 45,5 4,50 46,95 295,95"
points="2,42 2,198 52,158 102,198 102,42"
fill="none"
stroke= "white"
strokeWidth="2"
strokeDasharray="8,6"
stroke="#9f814a"

strokeWidth="4"
/>

{/* Text label */}
<text
x="150"
y="58"
x="50"
y="78"
textAnchor="middle"
fill="white"
fontWeight="bold"
Expand All @@ -58,4 +70,4 @@ BackBookmark.propTypes = {
zIndex: PropTypes.number,
};

export default BackBookmark;
export default BackBookmark;
31 changes: 20 additions & 11 deletions front-end/components/Bookmark.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import PropTypes from "prop-types";

const Bookmark = ({ label, targetPage, y, onClick, zIndex, color = "#77425f", stroke = "#5a2f49" }) => {
const Bookmark = ({ label, targetPage, x, onClick, zIndex, color = "#C56BC5", stroke = "#F8D77B" }) => {
const handleClick = (e) => {
if (onClick) {
onClick(e, targetPage); // send target page up
Expand All @@ -13,32 +13,41 @@ const Bookmark = ({ label, targetPage, y, onClick, zIndex, color = "#77425f", st
className="bookmark-container bookmark"
onClick={handleClick}
style={{
top: y,
left: x,
zIndex: zIndex || 10,
position: "absolute",
cursor: "pointer",
}}
>
<svg viewBox="0 0 300 100" preserveAspectRatio="none">
<svg viewBox="0 0 120 200" preserveAspectRatio="none">
<defs>
{/* Vertical gradient */}
<linearGradient id="bookmarkGrad" x1="0" x2="0" y1="0" y2="1">
<stop offset="10%" stopColor={color} stopOpacity=".1"/>
<stop offset="100%" stopColor={stroke} stopOpacity="1"/>
</linearGradient>
</defs>

{/* Main body */}
<polygon
points="0,0 260,0 300,50 260,100 0,100"
points="0,40 0,200 50,160 100,200 100,40"
fill={color}
stroke={stroke}
strokeWidth="1"
/>
{/* Inner dashed border */}
<polygon
points="5,5 255,5 296,50 254,95 5,95"
points="2,42 2,198 50,160 100,200 100,42"
fill="none"
stroke="white"
strokeWidth="2"
strokeDasharray="8,6"
stroke="#9f814a"

strokeWidth="4"
/>

{/* Text label */}
<text
x="150"
y="58"
x="50"
y="78"
textAnchor="middle"
fill="white"
fontWeight="bold"
Expand All @@ -61,4 +70,4 @@ Bookmark.propTypes = {
zIndex: PropTypes.number,
};

export default Bookmark;
export default Bookmark;
131 changes: 90 additions & 41 deletions front-end/components/FlipBook.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import React, { useEffect, useRef, useState } from "react";
import React, { useEffect, useRef, useState, useCallback } from "react";
import FlipPage from "./FlipPage";
import SummaryFront from "./SummaryFront";
import SummaryBack from "./SummaryBack";
import Social from "./Social";
import SearchAndCompare from "./SearchandCompare";
import { color } from "framer-motion";


const FlipBook = () => {
const [pages, setPages] = useState([]);
const [zIndices, setZIndices] = useState([]);
Expand All @@ -10,26 +15,81 @@ const FlipBook = () => {
const [onFirstPage, setOnFirstPage] = useState(true);
const [onLastPage, setOnLastPage] = useState(false);
const [isTurning, setIsTurning] = useState(false);

// Player stats state
const [player1Stats, setPlayer1Stats] = useState({
Games: "150",
WinRate: "60%",
KDA: "100",
CPM: "85",
gold15: "70",
GPM: "60",
DPM: "90"
});

const [player2Stats, setPlayer2Stats] = useState({
Games: "",
WinRate: "",
KDA: "",
CPM: "",
gold15: "",
GPM: "",
DPM: ""
});

const handlePlayer2Found = (stats) => {
setPlayer2Stats(stats);
};

const [searchQuery, setSearchQuery] = useState("");

const pageRefs = useRef([]);

// Mock function to search for player stats
const handleSearch = async () => {
if (!searchQuery.trim()) return;

// TODO: Replace this with actual API call to fetch player stats
// For now, using mock data
const mockPlayerData = {
Games: "",
WinRate: "",
KDA: "",
CPM: "",
gold15: "",
GPM: "",
DPM: ""
};

setPlayer2Stats(mockPlayerData);
};

useEffect(() => {
const pageList = [
{ cover: "green-cover.jpg", frontCover: true },
{ cover: "book_cover.jpg", frontCover: true },
{ front: "test.txt", back: "test.txt" },
{ front: "test.txt", back: "test.txt" },
{ front: "test.txt", back: "test.txt",
bookmark: { label: "Page 3", targetPage: 3, y: "10%", color: "#3b82f6" }
{ front: "test.txt", back: <SummaryBack data={{ region: "Shurima", profile:["Late-Game", "Scaling", "Empire-Building"],
statistics: { gamesPlayed: 120, winRate: "55%", averageKDA: "3.5", cspm: "7.8"},
mostPlayed: [
{ name: "Azir", games: 23 },
{ name: "Sivir", games: 17 },
{ name: "Cassiopeia", games: 12 },],
}}/> },
{ front: <SummaryFront data={{ roles: { top: 2, jg: 19, mid: 10, adc: 8, sup: 5 },
strengths:["Azir", "Sivir", "Cassiopeia"], weaknesses:["Nasus", "Taliyah"] }}/>, back: "test.txt",
bookmark: { label: "Summary", targetPage: 3, x: "12%", color: "#7B4643" }
},
{ front: "test.txt", back: "test.txt" },
{ front: "test.txt", back: "test.txt" },
{ front: "test.txt", back: "test.txt",
bookmark: { label: "Page 6", targetPage: 6, y: "32.5%", color: "#f63b89ff" }
{ front: "test.txt", back: <Social input1={player1Stats} input2={player2Stats} /> },
// Search bar on the front (right page) with Social bookmark
{ front: <SearchAndCompare onPlayer2Found={handlePlayer2Found} player1Stats={player1Stats}/> , back: "text",
bookmark: { label: "Social", targetPage: 6, x: "50%", color: "#354B89" }
},
{ front: "test.txt", back: "test.txt" },
// Player 2's perspective on the front (left page after bookmark)
{ front: "text", back: "test.txt" },
{ front: "test.txt", back: "test.txt" },
{ front: "test.txt", back: "test.txt",
bookmark: { label: "Page 9", targetPage: 9, y: "55%", color: "#2aa51fff" }
bookmark: { label: "Matches", targetPage: 9, x: "75%", color: "#595440" }
},
{ front: "test.txt", back: "test.txt" },
{ cover: "green-cover.jpg" },
Expand All @@ -41,14 +101,12 @@ const FlipBook = () => {
setZIndices(Array.from({ length: total }, (_, i) => total - i + 1));
setFlippedStates(Array(total).fill(false));

// Initialize refs array
pageRefs.current = Array(total)
.fill()
.map((_, i) => pageRefs.current[i] || React.createRef());
}, []);
}, [player1Stats, player2Stats, searchQuery]); // Re-render when stats change

const handleFlip = (pageIndex, isFlipped) => {

const updatedFlipped = [...flippedStates];
updatedFlipped[pageIndex] = isFlipped;
setFlippedStates(updatedFlipped);
Expand All @@ -71,12 +129,11 @@ const FlipBook = () => {
setOnLastPage(!!lastFlipped);
};

const flipToPage = async (targetPage) => {
const flipToPage = async (targetPage) => {
if (targetPage === currentPage) return;
if (isTurning) return; // prevent double clicks
if (isTurning) return;
setIsTurning(true);

// Forward flip
if (targetPage > currentPage) {
for (let i = currentPage; i < targetPage; i++) {
await new Promise((resolve) => {
Expand All @@ -86,9 +143,7 @@ const FlipBook = () => {
}, 800);
});
}
}
// Backward flip
else {
} else {
for (let i = currentPage - 1; i >= targetPage; i--) {
await new Promise((resolve) => {
setTimeout(() => {
Expand All @@ -109,40 +164,34 @@ const FlipBook = () => {
flipToPage(targetPage);
};

// On load intro animation is played — book opens and flips 2 pages + Cover
useEffect(() => {
if (!pages.length) return;

const waitForRefs = async () => {
const total = pages.length;
for (let i = 0; i < total; i++) {
// wait up to a reasonable amount; this loop polls until the ref exists
let tries = 0;
while (!pageRefs.current[i] && tries < 40) { // ~2s max (40 * 50ms)
await new Promise((r) => setTimeout(r, 50));
tries++;
if (!pages.length) return;

const waitForRefs = async () => {
const total = pages.length;
for (let i = 0; i < total; i++) {
let tries = 0;
while (!pageRefs.current[i] && tries < 40) {
await new Promise((r) => setTimeout(r, 50));
tries++;
}
}
}

// Give the browser a frame to paint so initial z / layout are stable
await new Promise((r) => requestAnimationFrame(r));
await new Promise((r) => setTimeout(r, 300)); // small buffer
await new Promise((r) => requestAnimationFrame(r));
await new Promise((r) => setTimeout(r, 300));

// Now run the intro flips
await flipToPage(3);
};
};

waitForRefs();
}, [pages.length]);
waitForRefs();
}, [pages.length]);

return (
<div className="book-frame">
<div className="page-wrapper slideUp-animation">

{pages.map((page, i) => (
<FlipPage
key={i}
ref={(el) => (pageRefs.current[i] = el)} // store ref
ref={(el) => (pageRefs.current[i] = el)}
Front={page.front}
Back={page.back}
Cover={page.cover}
Expand Down
8 changes: 4 additions & 4 deletions front-end/components/FlipPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,34 +86,34 @@ const FlipPage = forwardRef(
<>
<div className="back-page">
<div className="paper">
<p>{Back || "Back content"}</p>
{bookmark && (
<BackBookmark
label={bookmark.label}
targetPage={bookmark.targetPage}
y={bookmark.y}
x={bookmark.x}
onClick={onBookmarkClick}
zIndex={zIndex - 100}
color={bookmark.color}
stroke={bookmark.stroke}
/>
)}
{React.isValidElement(Back) ? Back : <p>{Back || "Back content"}</p>}
</div>
</div>
<div className="front-page">
<div className="paper">
<p>{Front || "Front content"}</p>
{bookmark && (
<Bookmark
label={bookmark.label}
targetPage={bookmark.targetPage}
y={bookmark.y}
x={bookmark.x}
onClick={onBookmarkClick}
zIndex={zIndex + 1}
color={bookmark.color}
stroke={bookmark.stroke}
/>
)}
{React.isValidElement(Front) ? Front : <p>{Front || "Front content"}</p>}
</div>
</div>
</>
Expand Down
Loading