feat: add TechLog project decision authoring

This commit is contained in:
DongHyeonka
2026-08-17 17:23:42 +09:00
parent 79e9aa8328
commit 0355b644a0
16 changed files with 532 additions and 33 deletions
@@ -21,6 +21,8 @@ type ReferencePublicRenderModel =
components["schemas"]["ReferencePublicRenderModel"];
type QuestionPublicRenderModel =
components["schemas"]["QuestionPublicRenderModel"];
type ProjectDecisionPublicRenderModel =
components["schemas"]["ProjectDecisionPublicRenderModel"];
type RenderDependencies = {
resolveEvidenceAsset: ResolveEvidenceAsset;
@@ -31,6 +33,7 @@ const kindLabels = {
CASE: "Case",
REFERENCE: "Reference",
QUESTION: "Open Question",
PROJECT_DECISION: "Decision",
} as const;
function assertNever(value: never): never {
@@ -52,7 +55,8 @@ function publishedLabel(
function explorePath(kind: PublicRenderModelBase["kind"]) {
if (kind === "CASE") return "/explore/cases";
if (kind === "REFERENCE") return "/explore/references";
return "/explore/questions";
if (kind === "QUESTION") return "/explore/questions";
return "/projects";
}
function TargetLink({
@@ -438,6 +442,71 @@ function QuestionDocument({
);
}
function ProjectDecisionDocument({
model,
embedded,
}: {
model: ProjectDecisionPublicRenderModel;
embedded: boolean;
}) {
const Root = embedded ? "div" : "main";
const evidence = publicRelations(model.relations);
return (
<Root
id={embedded ? undefined : "main-content"}
className={`shell project-page${embedded ? " public-record-embedded" : ""}`}
>
<nav className="case-breadcrumb" aria-label="문서 경로">
<Link to="/projects">Project</Link>
{model.project?.publicPath ? (
<>
<span aria-hidden="true">/</span>
<Link to={model.project.publicPath}>{model.project.label}</Link>
<span aria-hidden="true">/</span>
<Link to={`${model.project.publicPath}/decisions`}>Decision</Link>
</>
) : null}
</nav>
<ol className="project-decision-list">
<li>
<article id={model.slug}>
<header>
<div>
<span>{model.status}</span>
<time dateTime={model.decidedOn}>{displayDate(model.decidedOn)}</time>
</div>
<h2>{model.title}</h2>
<p>{model.statement}</p>
</header>
<section>
<h3> </h3>
<p>{model.rationale}</p>
</section>
<section>
<h3></h3>
<OrderedItems items={model.consequences} />
</section>
<section>
<h3> </h3>
{evidence.length ? (
<ul>
{evidence.map((item) => (
<li key={item.path}>
<Link to={item.path}>{item.title}</Link>
</li>
))}
</ul>
) : (
<p> .</p>
)}
</section>
</article>
</li>
</ol>
</Root>
);
}
export function PublicRecordRenderer({
model,
embedded = false,
@@ -481,6 +550,10 @@ export function PublicRecordRenderer({
resolvePublishedLabel={resolvePublishedLabel}
/>
);
case "PROJECT_DECISION":
return (
<ProjectDecisionDocument model={model} embedded={embedded} />
);
default:
return assertNever(model);
}