Skip to content

Commit 793605e

Browse files
committed
content: reading order of the books
1 parent b5aca15 commit 793605e

File tree

3 files changed

+148
-0
lines changed

3 files changed

+148
-0
lines changed

public/stories/reading-order.json

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
{
2+
"readingOrder": [
3+
{
4+
"id": 1,
5+
"title": "Phase I: The Streets of Thornus",
6+
"description": "Foundation and Atmosphere",
7+
"books": [
8+
{ "id": 1, "title": "The Broken Path" },
9+
{ "id": 9, "title": "The Diplomat's Journal" },
10+
{ "id": 10, "title": "The Whispering Rats" }
11+
]
12+
},
13+
{
14+
"id": 2,
15+
"title": "Phase II: The Cost of Sin",
16+
"description": "Escalation and History",
17+
"books": [
18+
{ "id": 4, "title": "The Sins of Glareach" },
19+
{ "id": 14, "title": "The Fredsound Legacy" },
20+
{ "id": 5, "title": "The Chronomancer's Dust" }
21+
]
22+
},
23+
{
24+
"id": 3,
25+
"title": "Phase III: The RedLink Arc",
26+
"description": "The Core Mystery & Revelations",
27+
"books": [
28+
{ "id": 11, "title": "The Petals of Predymesh" },
29+
{ "id": 2, "title": "The Tales of Doctor Blade" },
30+
{ "id": 6, "title": "The Sanity Ward" },
31+
{ "id": 7, "title": "The Roots of Silence" },
32+
{ "id": 8, "title": "The Architecture of Ghosts" }
33+
]
34+
},
35+
{
36+
"id": 4,
37+
"title": "Phase IV: The Resistance",
38+
"description": "The Aftermath",
39+
"books": [
40+
{ "id": 12, "title": "The Harvest of Silence" },
41+
{ "id": 3, "title": "The Butterfly's Jest" },
42+
{ "id": 13, "title": "The Cat of Craninal" }
43+
]
44+
}
45+
]
46+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import React, { useState, useEffect } from 'react';
2+
import { CaretDown, CaretUp } from '@phosphor-icons/react';
3+
4+
const StoryReadingOrder = () => {
5+
const [readingOrder, setReadingOrder] = useState([]);
6+
const [loading, setLoading] = useState(true);
7+
const [expandedPhase, setExpandedPhase] = useState(0);
8+
9+
useEffect(() => {
10+
const fetchReadingOrder = async () => {
11+
try {
12+
const response = await fetch('/stories/reading-order.json');
13+
if (response.ok) {
14+
const data = await response.json();
15+
if (data.readingOrder) {
16+
setReadingOrder(data.readingOrder);
17+
}
18+
} else {
19+
console.error('Failed to fetch reading-order.json:', response.status);
20+
}
21+
} catch (error) {
22+
console.error('Error fetching reading order:', error);
23+
} finally {
24+
setLoading(false);
25+
}
26+
};
27+
fetchReadingOrder();
28+
}, []);
29+
30+
if (loading || readingOrder.length === 0) return null;
31+
32+
return (
33+
<section className="py-24 max-w-5xl mx-auto">
34+
<div className="flex flex-col items-center mb-16">
35+
<div className="h-px w-32 bg-dnd-gold/40 mb-6" />
36+
<h2 className="text-4xl md:text-6xl font-playfairDisplay italic font-black dnd-gold-gradient-text uppercase tracking-tighter text-center">
37+
Chronological Order
38+
</h2>
39+
<p className="mt-4 font-arvo text-gray-400 italic text-center">
40+
"The sequence of souls and the path of the mountain."
41+
</p>
42+
</div>
43+
44+
<div className="space-y-6">
45+
{readingOrder.map((phase, idx) => (
46+
<div key={phase.id} className="relative group">
47+
{/* Phase Decorative Border */}
48+
<div className="absolute -inset-0.5 bg-gradient-to-r from-dnd-gold/20 via-dnd-crimson/10 to-dnd-gold/20 rounded-lg blur opacity-30 group-hover:opacity-100 transition duration-1000" />
49+
50+
<div className="relative bg-[#1a0f0a] border-2 border-dnd-gold/30 rounded-lg overflow-hidden">
51+
<button
52+
onClick={() => setExpandedPhase(expandedPhase === idx ? -1 : idx)}
53+
className="w-full p-8 flex items-center justify-between text-left hover:bg-white/[0.02] transition-colors"
54+
>
55+
<div className="flex flex-col gap-2">
56+
<span className="font-mono text-[10px] text-dnd-gold-light uppercase tracking-[0.4em] font-bold">
57+
{phase.title.split(':')[0]}
58+
</span>
59+
<h3 className="text-2xl md:text-3xl font-playfairDisplay italic font-bold text-white group-hover:text-dnd-gold transition-colors">
60+
{phase.title.split(':')[1] || phase.title}
61+
</h3>
62+
<p className="text-sm text-gray-400 font-arvo italic tracking-wide">
63+
{phase.description}
64+
</p>
65+
</div>
66+
<div className="text-dnd-gold/50 group-hover:text-dnd-gold transition-colors">
67+
{expandedPhase === idx ? <CaretUp size={28} weight="bold" /> : <CaretDown size={28} weight="bold" />}
68+
</div>
69+
</button>
70+
71+
{expandedPhase === idx && (
72+
<div className="px-8 pb-8 grid grid-cols-1 md:grid-cols-2 gap-4 animate-in fade-in slide-in-from-top-2 duration-500">
73+
{phase.books.map((book) => (
74+
<div key={book.id} className="p-5 border-2 border-dnd-gold/10 bg-black/40 rounded flex items-center gap-5 group/item hover:border-dnd-gold/40 transition-all">
75+
<div className="w-10 h-10 flex items-center justify-center border-2 border-dnd-gold/20 rounded-full text-dnd-gold-light group-hover/item:border-dnd-gold group-hover/item:bg-dnd-gold/10 transition-all shrink-0">
76+
<span className="font-mono text-xs font-bold">{book.id}</span>
77+
</div>
78+
<div className="flex flex-col min-w-0">
79+
<span className="text-xs font-playfairDisplay font-black uppercase tracking-widest text-white group-hover/item:text-dnd-gold-light transition-colors truncate">
80+
{book.title}
81+
</span>
82+
<div className="flex items-center gap-2 mt-1">
83+
<div className="h-px w-4 bg-dnd-crimson/40" />
84+
<span className="text-[9px] font-arvo text-gray-500 uppercase tracking-[0.2em]">Book Entry</span>
85+
</div>
86+
</div>
87+
</div>
88+
))}
89+
</div>
90+
)}
91+
</div>
92+
</div>
93+
))}
94+
</div>
95+
</section>
96+
);
97+
};
98+
99+
export default StoryReadingOrder;

src/pages/dnd/DndPage.jsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { motion } from 'framer-motion';
33
import { DndContext } from '../../context/DndContext';
44
import DndCard from '../../components/dnd/DndCard';
55
import DndLayout from '../../components/dnd/DndLayout';
6+
import StoryReadingOrder from '../../components/StoryReadingOrder';
67
import useSeo from '../../hooks/useSeo';
78
import { useAchievements } from '../../context/AchievementContext';
89
import { BookOpen, Scroll, UsersThree, MapTrifold, Sword } from '@phosphor-icons/react';
@@ -89,6 +90,8 @@ const DndPage = () => {
8990
icon={<BookOpen size={48} weight="duotone" />}
9091
/>
9192
</div>
93+
94+
<StoryReadingOrder />
9295
</div>
9396
</DndLayout>
9497
);

0 commit comments

Comments
 (0)