alpha01 filetti: web app, crossword service and tor batch
This commit is contained in:
110
webapp/components/crossword-runtime-page.tsx
Normal file
110
webapp/components/crossword-runtime-page.tsx
Normal file
@@ -0,0 +1,110 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { ClueList } from "@/components/clue-list";
|
||||
import { CrosswordPlayer } from "@/components/crossword-player";
|
||||
import { useCrosswordData } from "@/components/use-crossword-data";
|
||||
import type { Locale } from "@/lib/i18n";
|
||||
|
||||
type CrosswordRuntimePageProps = {
|
||||
id: string;
|
||||
locale: Locale;
|
||||
labels: {
|
||||
player: {
|
||||
topic: string;
|
||||
difficulty: string;
|
||||
lexicon: string;
|
||||
};
|
||||
clues: {
|
||||
across: string;
|
||||
down: string;
|
||||
};
|
||||
play: {
|
||||
overviewTitle: string;
|
||||
boardTitle: string;
|
||||
cluesTitle: string;
|
||||
instructions: string;
|
||||
actions: {
|
||||
newCrossword: string;
|
||||
viewSolution: string;
|
||||
};
|
||||
stats: {
|
||||
words: string;
|
||||
intersections: string;
|
||||
filledCells: string;
|
||||
topicWords: string;
|
||||
};
|
||||
};
|
||||
loading: string;
|
||||
errorPrefix: string;
|
||||
};
|
||||
};
|
||||
|
||||
export function CrosswordRuntimePage({ id, locale, labels }: CrosswordRuntimePageProps) {
|
||||
const { crossword, errorMessage, isLoading } = useCrosswordData(id, locale);
|
||||
|
||||
if (errorMessage) {
|
||||
return <p className="form-error">{labels.errorPrefix}: {errorMessage}</p>;
|
||||
}
|
||||
|
||||
if (isLoading || !crossword) {
|
||||
return <p className="muted">{labels.loading}</p>;
|
||||
}
|
||||
|
||||
return (
|
||||
<section className="stack">
|
||||
<div className="card play-overview">
|
||||
<div className="play-overview__header">
|
||||
<div>
|
||||
<span className="hero__badge hero__badge--soft">{crossword.summary.title}</span>
|
||||
<h2>{labels.play.overviewTitle}</h2>
|
||||
<p className="muted">{labels.play.instructions}</p>
|
||||
</div>
|
||||
<div className="play-overview__actions">
|
||||
<Link className="button" href={`/${locale}/new`}>
|
||||
{labels.play.actions.newCrossword}
|
||||
</Link>
|
||||
<Link className="button button--secondary" href={`/${locale}/crosswords/${id}/solution`}>
|
||||
{labels.play.actions.viewSolution}
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="kpi-grid kpi-grid--play">
|
||||
<div className="kpi">
|
||||
<span className="muted">{labels.play.stats.words}</span>
|
||||
<strong>{crossword.summary.total_words}</strong>
|
||||
</div>
|
||||
<div className="kpi">
|
||||
<span className="muted">{labels.play.stats.intersections}</span>
|
||||
<strong>{crossword.summary.intersections}</strong>
|
||||
</div>
|
||||
<div className="kpi">
|
||||
<span className="muted">{labels.play.stats.filledCells}</span>
|
||||
<strong>{crossword.diagnostics.filled_cells}</strong>
|
||||
</div>
|
||||
<div className="kpi">
|
||||
<span className="muted">{labels.play.stats.topicWords}</span>
|
||||
<strong>{crossword.diagnostics.topic_words}</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="card play-stage">
|
||||
<div className="play-stage__header">
|
||||
<h2>{labels.play.boardTitle}</h2>
|
||||
<p className="muted">{crossword.summary.subtitle}</p>
|
||||
</div>
|
||||
<CrosswordPlayer crossword={crossword} labels={labels.player} />
|
||||
</div>
|
||||
|
||||
<section className="card play-sidebar play-sidebar--bottom">
|
||||
<div className="play-stage__header play-stage__header--tight">
|
||||
<h2>{labels.play.cluesTitle}</h2>
|
||||
<p className="muted">{crossword.summary.title}</p>
|
||||
</div>
|
||||
<ClueList crossword={crossword} labels={labels.clues} />
|
||||
</section>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user