Skip to content

Commit e901324

Browse files
committed
feat: about card in stories
1 parent 62bde4d commit e901324

File tree

7 files changed

+161
-24
lines changed

7 files changed

+161
-24
lines changed

public/stories/README.md

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -44,33 +44,23 @@ The `books.piml` file is a PIML document that, when parsed, results in an object
4444
(bookId) 1
4545
(bookTitle) Book One: The Shadowed Path
4646
(episodes)
47-
> (item)
47+
> (episode)
4848
(id) 1
4949
(filename) book-one/episode1.txt
5050
(title) Episode 1: The Whispering Woods
5151
(author) fezcode
52-
> (item)
52+
(date) 2025-11-14
53+
(updated) 2025-11-14
54+
> (episode)
5355
(id) 2
5456
(filename) book-one/episode2.txt
5557
(title) Episode 2: The Goblin Ambush
5658
(author) fezcode
59+
(date) 2025-11-14
60+
(updated) 2025-11-14
5761
(overlay) red
5862
5963
> (book)
60-
(bookId) 2
61-
(bookTitle) Book Two: Separated Riches
62-
(episodes)
63-
> (item)
64-
(id) 1
65-
(filename) book-one/episode1.txt
66-
(title) Episode 1: The Whispering Woods
67-
(author) fezcode
68-
> (item)
69-
(id) 2
70-
(filename) book-one/episode2.txt
71-
(title) Episode 2: The Goblin Ambush
72-
(author) fezcode
73-
(overlay) blue
7464
# ... more book objects
7565
```
7666

@@ -97,5 +87,7 @@ The `books.piml` file is a PIML document that, when parsed, results in an object
9787
* `filename` (String): The relative path to the plain text file containing the episode's content. This path is relative to the `public/stories/` directory (e.g., `book-one/episode1.txt`).
9888
* `title` (String): The title of the episode.
9989
* `author` (String): The author of the episode.
90+
* `date` (String): The original release date of the episode.
91+
* `updated` (String): The last update date of the episode.
10092

10193
This structure allows the application to dynamically load and display story content, organizing it into books and episodes with associated metadata, and also provides a central place for author information.

public/stories/books.piml

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,62 +8,78 @@
88
(bookId) 1
99
(bookTitle) Book One: The Shadowed Path
1010
(episodes)
11-
> (item)
11+
> (episode)
1212
(id) 1
1313
(filename) book-one/episode1.txt
1414
(title) Episode 1: The Whispering Woods
1515
(author) fezcode
16-
> (item)
16+
(date) 2025-11-14
17+
(updated) 2025-11-14
18+
> (episode)
1719
(id) 2
1820
(filename) book-one/episode2.txt
1921
(title) Episode 2: The Goblin Ambush
2022
(author) fezcode
23+
(date) 2025-11-14
24+
(updated) 2025-11-14
2125
(overlay) red
2226

2327
> (book)
2428
(bookId) 2
2529
(bookTitle) Book Two: Separated Riches
2630
(episodes)
27-
> (item)
31+
> (episode)
2832
(id) 1
2933
(filename) book-one/episode1.txt
3034
(title) Episode 1: The Whispering Woods
3135
(author) fezcode
32-
> (item)
36+
(date) 2025-11-14
37+
(updated) 2025-11-14
38+
> (episode)
3339
(id) 2
3440
(filename) book-one/episode2.txt
3541
(title) Episode 2: The Goblin Ambush
3642
(author) fezcode
43+
(date) 2025-11-14
44+
(updated) 2025-11-14
3745
(overlay) blue
3846

3947
> (book)
4048
(bookId) 3
4149
(bookTitle) Book Three: Separated Riches
4250
(episodes)
43-
> (item)
51+
> (episode)
4452
(id) 1
4553
(filename) book-one/episode1.txt
4654
(title) Episode 1: The Whispering Woods
4755
(author) fezcode
48-
> (item)
56+
(date) 2025-11-14
57+
(updated) 2025-11-14
58+
> (episode)
4959
(id) 2
5060
(filename) book-one/episode2.txt
5161
(title) Episode 2: The Goblin Ambush
5262
(author) fezcode
63+
(date) 2025-11-14
64+
(updated) 2025-11-14
5365
(overlay) black
5466

5567
> (book)
5668
(bookId) 4
5769
(bookTitle) Book Four: Separated Riches
5870
(episodes)
59-
> (item)
71+
> (episode)
6072
(id) 1
6173
(filename) book-one/episode1.txt
6274
(title) Episode 1: The Whispering Woods
6375
(author) fezcode
64-
> (item)
76+
(date) 2025-11-14
77+
(updated) 2025-11-14
78+
> (episode)
6579
(id) 2
6680
(filename) book-one/episode2.txt
6781
(title) Episode 2: The Goblin Ambush
6882
(author) fezcode
83+
(date) 2025-11-14
84+
(updated) 2025-11-14
6985
(overlay) green

src/components/AnimatedRoutes.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import DndNotFoundPage from '../pages/dnd/DndNotFoundPage';
1616
import DndEpisodePage from '../pages/dnd/DndEpisodePage';
1717
import DndLorePage from '../pages/dnd/DndLorePage';
1818
import DndBookPage from '../pages/dnd/DndBookPage';
19+
import DndAuthorsPage from '../pages/dnd/DndAuthorsPage'; // Import DndAuthorsPage
1920
import AppPage from '../pages/AppPage';
2021
import IpPage from '../pages/apps/IpPage';
2122
import WordCounterPage from '../pages/apps/WordCounterPage';
@@ -294,6 +295,21 @@ function AnimatedRoutes() {
294295
</motion.div>
295296
}
296297
/>
298+
{/* D&D Authors Page */}
299+
<Route
300+
path="/stories/authors"
301+
element={
302+
<motion.div
303+
initial="initial"
304+
animate="in"
305+
exit="out"
306+
variants={pageVariants}
307+
transition={pageTransition}
308+
>
309+
<DndAuthorsPage />
310+
</motion.div>
311+
}
312+
/>
297313
<Route
298314
path="/random"
299315
element={

src/pages/dnd/DndAuthorsPage.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import React from 'react';
2+
import { motion } from 'framer-motion';
3+
import '../../styles/dnd.css';
4+
import useSeo from "../../hooks/useSeo";
5+
6+
const pageVariants = {
7+
initial: {
8+
opacity: 0,
9+
},
10+
in: {
11+
opacity: 1,
12+
},
13+
out: {
14+
opacity: 0,
15+
},
16+
};
17+
18+
const pageTransition = {
19+
type: 'tween',
20+
ease: 'easeInOut',
21+
duration: 0.3,
22+
};
23+
24+
function DndAuthorsPage() {
25+
useSeo({
26+
title: 'Authors | From Serfs and Frauds',
27+
description: 'Meet the authors behind the Dungeons & Dragons campaign, From Serfs and Frauds.',
28+
keywords: ['Fezcodex', 'd&d', 'dnd', 'from serfs and frauds', 'authors'],
29+
ogTitle: 'Authors | From Serfs and Frauds',
30+
ogDescription: 'Meet the authors behind the Dungeons & Dragons campaign, From Serfs and Frauds.',
31+
ogImage: 'https://fezcode.github.io/logo512.png',
32+
twitterCard: 'summary_large_image',
33+
twitterTitle: 'Authors | From Serfs and Frauds',
34+
twitterDescription: 'Meet the authors behind the Dungeons & Dragons campaign, From Serfs and Frauds.',
35+
twitterImage: 'https://fezcode.github.io/logo512.png'
36+
});
37+
38+
return (
39+
<motion.div
40+
initial="initial"
41+
animate="in"
42+
exit="out"
43+
variants={pageVariants}
44+
transition={pageTransition}
45+
className="dnd-page-container"
46+
>
47+
<div className="dnd-hero" style={{ backgroundImage: `url(${process.env.PUBLIC_URL}/images/stories/border-large.jpg)` }}>
48+
<h1 className="dnd-title-box">
49+
<span className="dnd-hero-title-white">Authors</span>
50+
</h1>
51+
<div className="dnd-content-box" style={{ zIndex: 1 }}>
52+
<p>This is the Authors page. Details about authors will be displayed here.</p>
53+
</div>
54+
</div>
55+
</motion.div>
56+
);
57+
}
58+
59+
export default DndAuthorsPage;

src/pages/dnd/DndEpisodePage.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ function DndEpisodePage() {
3434
const [episodeContent, setEpisodeContent] = useState('');
3535
const [episodeTitle, setEpisodeTitle] = useState('');
3636
const [book, setBook] = useState(null); // State to store the current book
37+
const [currentEpisode, setCurrentEpisode] = useState(null); // State to store the current episode
3738
const [bgImage, setBgImage] = useState(''); // State for background image
3839

3940
useSeo({
@@ -84,6 +85,7 @@ function DndEpisodePage() {
8485
const currentEpisodeIndex = foundBook.episodes.findIndex(ep => ep.id === parseInt(episodeId));
8586
if (currentEpisodeIndex !== -1) {
8687
const currentEpisode = foundBook.episodes[currentEpisodeIndex];
88+
setCurrentEpisode(currentEpisode); // Set the current episode
8789
setEpisodeTitle(currentEpisode.title);
8890
setBreadcrumbs([
8991
{ label: 'S&F', path: '/stories' },
@@ -143,6 +145,16 @@ function DndEpisodePage() {
143145
<h1 className="dnd-title-box">
144146
<span className="dnd-hero-title-white">{episodeTitle}</span>
145147
</h1>
148+
149+
{book && currentEpisode && (
150+
<div className="dnd-about-card">
151+
<h3>About this Episode</h3>
152+
<p><span className="dnd-author-label">Author:</span> {currentEpisode.author}</p>
153+
<p><span className="dnd-author-label">Date:</span> {currentEpisode.date}</p>
154+
{currentEpisode.updated && <p><span className="dnd-author-label">Updated:</span> {currentEpisode.updated}</p>}
155+
</div>
156+
)}
157+
146158
<div className="dnd-content-box" style={{ zIndex: 1 }}>
147159
<ReactMarkdown rehypePlugins={[rehypeRaw]}>
148160
{episodeContent}

src/pages/dnd/DndPage.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,13 @@ const DndPage = () => {
4848
backgroundImage={`${process.env.PUBLIC_URL}/images/stories/parchment.png`}
4949
className="dnd-card-parchment" // Add the new class
5050
/>
51+
<DndCard
52+
title="Authors"
53+
description="Meet the creators of the tales."
54+
link="/stories/authors"
55+
backgroundImage={`${process.env.PUBLIC_URL}/images/stories/parchment.png`}
56+
className="dnd-card-parchment"
57+
/>
5158
</div>
5259
</div>
5360
</div>

src/styles/dnd.css

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,41 @@
8383
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8); /* Add text shadow */
8484
}
8585

86+
.dnd-about-card {
87+
background-color: rgba(50, 30, 30, 0.8);
88+
padding: 1.5rem 2rem;
89+
width: 90%;
90+
max-width: 800px; /* Smaller max-width than content box */
91+
margin: 2rem auto;
92+
border: 1px solid rgba(255, 255, 255, 0.1);
93+
border-radius: 8px;
94+
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.4);
95+
color: #E8E0B0;
96+
line-height: 1.6;
97+
position: relative;
98+
z-index: 1; /* Ensure it's above the background overlay */
99+
text-align: center; /* Align text to the center */
100+
}
101+
102+
.dnd-about-card h3 {
103+
color: #FFFACD;
104+
font-size: 1.5rem;
105+
margin-bottom: 0.8rem;
106+
text-shadow: 1px 1px 3px rgba(0, 0, 0, 1);
107+
text-align: center;
108+
}
109+
110+
.dnd-about-card p {
111+
font-size: 1.2rem;
112+
margin-bottom: 0.5rem;
113+
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8);
114+
}
115+
116+
.dnd-author-label {
117+
color: #ff6b6b; /* A tone of red */
118+
font-weight: bold;
119+
}
120+
86121
.dnd-content-box ul,
87122
.dnd-content-box ol {
88123
margin-left: 3rem; /* Indent lists */

0 commit comments

Comments
 (0)