193 lines
6.6 KiB
React
193 lines
6.6 KiB
React
import { useEffect, useMemo } from "react";
|
|
import Head from "next/head";
|
|
import ReaderNav from "../../components/reader/ReaderNav";
|
|
import ReaderFooter from "../../components/reader/ReaderFooter";
|
|
import WorkflowBlock from "../../components/reader/WorkflowBlock";
|
|
import ChapterOutline from "../../components/reader/ChapterOutline";
|
|
import useActivation from "../../components/reader/useActivation";
|
|
import { CHAPTER, RECIPES, buildOutline } from "../../data/sample-chapter";
|
|
|
|
const RECIPE_IDS = RECIPES.map((r) => r.id);
|
|
const ESSAY_KEYS = ["stakes", "constraints", "practice"];
|
|
|
|
function Essay({ id, heading, paragraphs }) {
|
|
return (
|
|
<section className="essay" id={id}>
|
|
<h2>{heading}</h2>
|
|
{paragraphs.map((p) => (
|
|
<p key={p}>{p}</p>
|
|
))}
|
|
</section>
|
|
);
|
|
}
|
|
|
|
export default function RealEstateChapter() {
|
|
const { complete, toggle, count, total } = useActivation(RECIPE_IDS);
|
|
const [first, second] = RECIPES;
|
|
const outline = useMemo(() => buildOutline(CHAPTER, RECIPES), []);
|
|
const essayGroup = outline.find((g) => g.label === "Essay");
|
|
const workflowGroup = outline.find((g) => g.label === "Workflows");
|
|
|
|
useEffect(() => {
|
|
const hash = window.location.hash;
|
|
if (!hash) return;
|
|
const el = document.getElementById(hash.slice(1));
|
|
if (el) el.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
}, []);
|
|
|
|
return (
|
|
<>
|
|
<Head>
|
|
<title>{CHAPTER.title} · AIBook.fun reading demo</title>
|
|
<meta name="description" content={CHAPTER.promise} />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
</Head>
|
|
|
|
<ReaderNav chapterName={CHAPTER.vertical} />
|
|
|
|
<main>
|
|
<article className="chapter-page">
|
|
<div className="wrap chapter-shell">
|
|
<ChapterOutline
|
|
groups={outline}
|
|
complete={complete}
|
|
count={count}
|
|
total={total}
|
|
/>
|
|
|
|
<div className="chapter-col">
|
|
<span className="spec demo-chip">Reading demo · not the live book</span>
|
|
<p className="spec chapter-kicker">
|
|
{CHAPTER.vertical} · {CHAPTER.edition} edition
|
|
</p>
|
|
<h1 className="chapter-title">{CHAPTER.title}</h1>
|
|
<p className="chapter-by">{CHAPTER.authors}</p>
|
|
|
|
<ChapterOutline
|
|
variant="mobile"
|
|
groups={outline}
|
|
complete={complete}
|
|
count={count}
|
|
total={total}
|
|
/>
|
|
|
|
<p className="chapter-promise">{CHAPTER.promise}</p>
|
|
|
|
<section className="chapter-map" aria-label="What's in this chapter">
|
|
<h2 className="chapter-map-title">What's in this chapter</h2>
|
|
<div className="chapter-map-block">
|
|
<p className="spec">Essay</p>
|
|
<ul>
|
|
{essayGroup.items.map((item) => (
|
|
<li key={item.id}>
|
|
<a href={`#${item.id}`}>{item.label}</a>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
<div className="chapter-map-block">
|
|
<p className="spec">Workflows</p>
|
|
<ul>
|
|
{workflowGroup.items.map((item) => (
|
|
<li key={item.id}>
|
|
<a href={`#${item.id}`}>
|
|
{item.recipeId} · {item.shortTitle} · {item.time}
|
|
</a>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
</section>
|
|
|
|
<div className="skip-row">
|
|
<span className="skip-label">Skip to a Try-it</span>
|
|
{RECIPES.map((r) => (
|
|
<a key={r.id} className="skip-chip" href={`#${r.anchor}`}>
|
|
{r.id}
|
|
<span className="skip-chip-job">{r.shortTitle}</span>
|
|
</a>
|
|
))}
|
|
</div>
|
|
|
|
{ESSAY_KEYS.map((key) => (
|
|
<Essay
|
|
key={key}
|
|
id={CHAPTER[key].id}
|
|
heading={CHAPTER[key].heading}
|
|
paragraphs={CHAPTER[key].paragraphs}
|
|
/>
|
|
))}
|
|
|
|
<p className="spec workflow-kicker">
|
|
Workflow 1 of {RECIPES.length} in this chapter
|
|
</p>
|
|
<WorkflowBlock
|
|
recipe={first}
|
|
index={1}
|
|
total={RECIPES.length}
|
|
complete={!!complete[first.id]}
|
|
onToggleComplete={toggle}
|
|
/>
|
|
|
|
<Essay
|
|
id={CHAPTER.between.id}
|
|
heading={CHAPTER.between.heading}
|
|
paragraphs={CHAPTER.between.paragraphs}
|
|
/>
|
|
|
|
<p className="spec workflow-kicker">
|
|
Workflow 2 of {RECIPES.length} in this chapter
|
|
</p>
|
|
<WorkflowBlock
|
|
recipe={second}
|
|
index={2}
|
|
total={RECIPES.length}
|
|
complete={!!complete[second.id]}
|
|
onToggleComplete={toggle}
|
|
/>
|
|
|
|
<section className="end-matter" id="further">
|
|
<h2>Further workflows in this vertical</h2>
|
|
<ul className="further-list">
|
|
{CHAPTER.further.map((item) => (
|
|
<li key={item.id}>
|
|
{item.coming ? (
|
|
<>
|
|
<span className="recipe-id">
|
|
<b>{item.id}</b>
|
|
</span>{" "}
|
|
{item.title}
|
|
</>
|
|
) : (
|
|
<>
|
|
<a href={item.href}>
|
|
<span className="recipe-id">
|
|
<b>{item.id}</b>
|
|
</span>
|
|
</a>{" "}
|
|
{item.title}
|
|
</>
|
|
)}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</section>
|
|
|
|
<section className="end-sources" id="sources">
|
|
<h2>Sources</h2>
|
|
<ul className="further-list">
|
|
{CHAPTER.sources.map((s) => (
|
|
<li key={s}>{s}</li>
|
|
))}
|
|
</ul>
|
|
<p className="chapter-updated">Last updated: {CHAPTER.lastUpdated}</p>
|
|
</section>
|
|
</div>
|
|
</div>
|
|
</article>
|
|
</main>
|
|
<ReaderFooter />
|
|
</>
|
|
);
|
|
}
|