Commit 6968c5da authored by Kantz's avatar Kantz
Browse files

subsection keys update

parent a2044e3f
......@@ -79,11 +79,12 @@ You can open a socratic chat directly with URL query parameters:
Example:
`http://localhost:5173/chat?orchestrator=socratic&subsection_key=quadratische%20gleichungen`
`http://localhost:5173/chat?orchestrator=socratic&subsection_key=quadratische-gleichungen`
Notes:
- `subsection_key` must match an existing subsection entry from the task catalog.
- The links use hyphenated subsection slugs in the URL, while the app resolves them back to the catalog key.
- The socratic subsection list in the UI is built from `backend/sources/tasks/_subsection_map.json` and the `subsections` arrays in the task files.
- If the link is invalid, the frontend falls back to `/select-socratic`.
- The socratic dialog is not locked by deep link, so users can still switch subsections afterwards.
......
......@@ -14,6 +14,7 @@ import { selectSubsection, selectTask } from "../api/taskApi";
import { t } from "../i18n";
import { createSessionId, useTutorSession } from "../state/tutorSession";
import { getSelectionRouteForOrchestrator, isSocraticOrchestrator } from "../utils/orchestratorRoutes";
import { normalizeSubsectionKey } from "../utils/subsectionKey";
import sumintLogo from "../../SuMINT-Logo.png";
const initialMessages: ChatMessage[] = [];
......@@ -232,7 +233,7 @@ export default function ChatPage() {
/^\d{1,2}$/.test(rawTaskId) && rawTaskId.length < 2
? rawTaskId.padStart(2, "0")
: rawTaskId;
const subsectionKey = rawSubsectionKey;
const subsectionKey = rawSubsectionKey ? normalizeSubsectionKey(rawSubsectionKey) : "";
const hasFileId = Boolean(fileId);
const hasTaskId = Boolean(taskId);
const hasSubsectionKey = Boolean(subsectionKey);
......
......@@ -6,6 +6,7 @@ import OrchestratorSelect from "../components/Orchestrator/OrchestratorSelect";
import { t } from "../i18n";
import { useTutorSession } from "../state/tutorSession";
import { getSelectionRouteForOrchestrator } from "../utils/orchestratorRoutes";
import { subsectionKeyToSlug } from "../utils/subsectionKey";
import "../styles/theme.css";
import sumintLogo from "../../SuMINT-Logo.png";
......@@ -18,6 +19,7 @@ type SocraticLinkGroup = {
type SocraticLinkEntry = {
subsectionKey: string;
slug: string;
label: string;
summary: string;
refsText: string;
......@@ -83,10 +85,11 @@ export default function SocraticSelectionPage() {
const refsText = option.refs.map((ref) => ref.join(":")).join(", ");
const entry: SocraticLinkEntry = {
subsectionKey: option.subsection_key,
slug: subsectionKeyToSlug(option.subsection_key),
label: option.label || option.subsection_key,
summary: option.summary || "",
refsText,
href: buildSocraticHref(option.subsection_key),
href: buildSocraticHref(subsectionKeyToSlug(option.subsection_key)),
};
const existing = groupIndex.get(groupKey);
......@@ -274,7 +277,7 @@ export default function SocraticSelectionPage() {
{group.entries.map((entry) => (
<Link key={entry.subsectionKey} className="socratic-link-item" to={entry.href}>
<span className="socratic-link-item-title">{entry.label}</span>
<span className="socratic-link-item-key">{entry.subsectionKey}</span>
<span className="socratic-link-item-key">{entry.slug}</span>
{entry.refsText ? (
<span className="socratic-link-item-meta">{entry.refsText}</span>
) : null}
......
const collapseWhitespace = (value: string): string => value.replace(/\s+/g, " ").trim();
export const normalizeSubsectionKey = (value: string): string =>
collapseWhitespace(String(value).replace(/[-_]+/g, " ").toLowerCase());
export const subsectionKeyToSlug = (value: string): string =>
normalizeSubsectionKey(value).replace(/\s+/g, "-");
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment