Commit 4053103d authored by Kantz's avatar Kantz
Browse files

änderungen in der auswahl sauber entfernt

parent 09b170b8
...@@ -85,7 +85,7 @@ Notes: ...@@ -85,7 +85,7 @@ Notes:
- `subsection_key` must match an existing subsection entry from the task catalog. - `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 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. - The fallback `/select-socratic` page only shows the subsection dropdown and start button.
- If the link is invalid, the frontend falls back to `/select-socratic`. - 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. - The socratic dialog is not locked by deep link, so users can still switch subsections afterwards.
......
...@@ -74,13 +74,9 @@ ...@@ -74,13 +74,9 @@
taskSelectionSubtitle: "Choose a task and start a tutor session", taskSelectionSubtitle: "Choose a task and start a tutor session",
socraticSelectionTitle: "Select a Subsection", socraticSelectionTitle: "Select a Subsection",
socraticSelectionSubtitle: "Choose a subsection and start a socratic session", socraticSelectionSubtitle: "Choose a subsection and start a socratic session",
socraticDeepLinkList: "Direct socratic links",
socraticDeepLinkListSubtitle:
"Open a socratic dialog directly for any available subsection.",
subsection: "Subsection", subsection: "Subsection",
taskFile: "Task Set", taskFile: "Task Set",
taskId: "Task ID", taskId: "Task ID",
subsectionFile: "Subsection Set",
subsectionKey: "Subsection Key", subsectionKey: "Subsection Key",
solveWithTutor: "Solve with Tutor", solveWithTutor: "Solve with Tutor",
startSocratic: "Start Socratic", startSocratic: "Start Socratic",
...@@ -181,13 +177,9 @@ ...@@ -181,13 +177,9 @@
taskSelectionSubtitle: "Wähle eine Aufgabe und starte den Tutor-Chat", taskSelectionSubtitle: "Wähle eine Aufgabe und starte den Tutor-Chat",
socraticSelectionTitle: "Unterabschnitt auswählen", socraticSelectionTitle: "Unterabschnitt auswählen",
socraticSelectionSubtitle: "Wähle einen Unterabschnitt und starte den sokratischen Chat", socraticSelectionSubtitle: "Wähle einen Unterabschnitt und starte den sokratischen Chat",
socraticDeepLinkList: "Direkte sokratische Links",
socraticDeepLinkListSubtitle:
"Öffne einen sokratischen Dialog direkt für jeden verfügbaren Unterabschnitt.",
subsection: "Unterabschnitt", subsection: "Unterabschnitt",
taskFile: "Aufgabenset", taskFile: "Aufgabenset",
taskId: "Aufgaben-ID", taskId: "Aufgaben-ID",
subsectionFile: "Unterabschnitt-Set",
subsectionKey: "Unterabschnitt-Schlüssel", subsectionKey: "Unterabschnitt-Schlüssel",
solveWithTutor: "Mit Tutor lösen", solveWithTutor: "Mit Tutor lösen",
startSocratic: "Sokratischen Dialog führen", startSocratic: "Sokratischen Dialog führen",
......
import { useEffect, useMemo, useRef } from "react"; import { useEffect, useMemo, useRef } from "react";
import { Link, useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import type { OrchestratorName } from "../api/orchestratorApi"; import type { OrchestratorName } from "../api/orchestratorApi";
import { selectSubsection } from "../api/taskApi"; import { selectSubsection } from "../api/taskApi";
import OrchestratorSelect from "../components/Orchestrator/OrchestratorSelect"; import OrchestratorSelect from "../components/Orchestrator/OrchestratorSelect";
import { t } from "../i18n"; import { t } from "../i18n";
import { useTutorSession } from "../state/tutorSession"; import { useTutorSession } from "../state/tutorSession";
import { getSelectionRouteForOrchestrator } from "../utils/orchestratorRoutes"; import { getSelectionRouteForOrchestrator } from "../utils/orchestratorRoutes";
import { subsectionKeyToSlug } from "../utils/subsectionKey";
import "../styles/theme.css"; import "../styles/theme.css";
import sumintLogo from "../../SuMINT-Logo.png"; import sumintLogo from "../../SuMINT-Logo.png";
type SocraticLinkGroup = {
key: string;
title: string;
fileId: string;
entries: SocraticLinkEntry[];
};
type SocraticLinkEntry = {
subsectionKey: string;
slug: string;
label: string;
summary: string;
refsText: string;
href: string;
};
const buildSocraticHref = (subsectionKey: string): string =>
`/chat?orchestrator=socratic&subsection_key=${encodeURIComponent(subsectionKey)}`;
export default function SocraticSelectionPage() { export default function SocraticSelectionPage() {
const navigate = useNavigate(); const navigate = useNavigate();
const { const {
...@@ -38,7 +18,6 @@ export default function SocraticSelectionPage() { ...@@ -38,7 +18,6 @@ export default function SocraticSelectionPage() {
switchOrchestrator, switchOrchestrator,
isOrchestratorSelectable, isOrchestratorSelectable,
orchestratorError, orchestratorError,
taskFiles,
subsections, subsections,
selectedSubsectionRef, selectedSubsectionRef,
selectedSubsection, selectedSubsection,
...@@ -50,77 +29,6 @@ export default function SocraticSelectionPage() { ...@@ -50,77 +29,6 @@ export default function SocraticSelectionPage() {
} = useTutorSession(); } = useTutorSession();
const subsectionDisplayRef = useRef<HTMLDivElement | null>(null); const subsectionDisplayRef = useRef<HTMLDivElement | null>(null);
const socraticLinkGroups = useMemo<SocraticLinkGroup[]>(() => {
const groupIndex = new Map<string, SocraticLinkGroup>();
const globalOrder = new Map<string, number>();
subsections.forEach((option, index) => {
globalOrder.set(option.subsection_key, index);
});
const fileBySubsectionKey = new Map<
string,
{
fileId: string;
title: string;
}
>();
taskFiles.forEach((file) => {
const title = file.title || file.file_id;
(file.subsection_options || []).forEach((option) => {
if (!fileBySubsectionKey.has(option.subsection_key)) {
fileBySubsectionKey.set(option.subsection_key, {
fileId: file.file_id,
title,
});
}
});
});
subsections.forEach((option) => {
const source = fileBySubsectionKey.get(option.subsection_key);
const groupKey = source?.fileId || "__ungrouped__";
const groupTitle = source?.title || t("subsectionFile");
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(subsectionKeyToSlug(option.subsection_key)),
};
const existing = groupIndex.get(groupKey);
if (existing) {
existing.entries.push(entry);
return;
}
groupIndex.set(groupKey, {
key: groupKey,
title: groupTitle,
fileId: source?.fileId || "",
entries: [entry],
});
});
return [...groupIndex.values()]
.map((group) => ({
...group,
entries: group.entries.sort((a, b) => {
const aOrder = globalOrder.get(a.subsectionKey) ?? Number.MAX_SAFE_INTEGER;
const bOrder = globalOrder.get(b.subsectionKey) ?? Number.MAX_SAFE_INTEGER;
if (aOrder !== bOrder) {
return aOrder - bOrder;
}
return a.label.localeCompare(b.label);
}),
}))
.sort((a, b) => a.title.localeCompare(b.title));
}, [subsections, taskFiles]);
const subsectionMenuOptions = useMemo( const subsectionMenuOptions = useMemo(
() => () =>
subsections.map((option) => ({ subsections.map((option) => ({
......
...@@ -938,110 +938,6 @@ body { ...@@ -938,110 +938,6 @@ body {
padding: 18px; padding: 18px;
} }
.socratic-link-section {
display: flex;
flex-direction: column;
gap: 10px;
margin-top: 4px;
padding-top: 12px;
border-top: 1px solid #e2ded5;
}
.socratic-link-subtitle {
margin: 0;
color: #6f675d;
font-size: 13px;
}
.socratic-link-groups {
display: flex;
flex-direction: column;
gap: 12px;
}
.socratic-link-group {
display: flex;
flex-direction: column;
gap: 10px;
padding: 12px;
border: 1px solid #e2ded5;
border-radius: 14px;
background: #fffdf8;
}
.socratic-link-group-header {
display: flex;
justify-content: space-between;
gap: 12px;
align-items: baseline;
}
.socratic-link-group-title {
font-weight: 600;
font-size: 14px;
}
.socratic-link-group-meta {
color: #6f675d;
font-size: 12px;
white-space: nowrap;
}
.socratic-link-items {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 10px;
}
.socratic-link-item {
display: flex;
flex-direction: column;
gap: 4px;
min-height: 100%;
padding: 12px;
border-radius: 12px;
border: 1px solid #d8d1c4;
background: linear-gradient(180deg, #fff 0%, #fff8eb 100%);
color: inherit;
text-decoration: none;
transition:
transform 0.12s ease,
box-shadow 0.12s ease,
border-color 0.12s ease;
}
.socratic-link-item:hover,
.socratic-link-item:focus-visible {
transform: translateY(-1px);
border-color: #b9b2a4;
box-shadow: 0 10px 22px rgba(29, 27, 22, 0.08);
outline: none;
}
.socratic-link-item-title {
font-weight: 600;
}
.socratic-link-item-key,
.socratic-link-item-meta,
.socratic-link-item-summary {
font-size: 12px;
color: #6f675d;
}
.socratic-link-item-summary {
white-space: pre-line;
}
.task-panel-empty {
padding: 8px 10px;
border-radius: 10px;
background: #fff;
border: 1px dashed #d8d1c4;
color: #6f675d;
font-size: 12px;
}
.task-select-title { .task-select-title {
margin: 0; margin: 0;
font-size: 20px; font-size: 20px;
......
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