feat(ai-act-kompass): printable training materials (paper test, answer key, handout)
- Paper version of the AI literacy test: name/date/department fields, 12 questions with tick boxes (A/B/C), marking line and signature block — for employees without computer access; contains no answers - Answer key for markers: correct letter plus explanation per question, pass threshold noted - Training handout: the 12 core rules (question + explanation) as Art. 4 training material to distribute before the test - All printable with company letterhead via the existing print/PDF pipeline and downloadable; buttons in the quiz view under 'Print training materials'; UI labels in all nine languages (document body DE/EN with EN fallback, full localization follows the content pack) - 3 new tests (72 total) Claude-Session: https://claude.ai/code/session_017YjohVNx1ZGNM4MX7tHpfv
This commit is contained in:
parent
efdc60fe84
commit
ca58f1738f
@ -1,6 +1,14 @@
|
|||||||
import { describe, expect, it } from 'vitest';
|
import { describe, expect, it } from 'vitest';
|
||||||
import { CONTENT_PACK } from '../content/pack';
|
import { CONTENT_PACK } from '../content/pack';
|
||||||
import { certificateDoc, getQuiz, scoreQuiz, trainingLogDoc } from './quiz';
|
import {
|
||||||
|
answerKeyDoc,
|
||||||
|
certificateDoc,
|
||||||
|
getQuiz,
|
||||||
|
handoutDoc,
|
||||||
|
printableTestDoc,
|
||||||
|
scoreQuiz,
|
||||||
|
trainingLogDoc,
|
||||||
|
} from './quiz';
|
||||||
import { QUIZ_PASS_PCT, QUIZ_QUESTIONS } from './quizContent';
|
import { QUIZ_PASS_PCT, QUIZ_QUESTIONS } from './quizContent';
|
||||||
import type { CompanyProfile } from './types';
|
import type { CompanyProfile } from './types';
|
||||||
|
|
||||||
@ -65,6 +73,30 @@ describe('KI-Kompetenztest', () => {
|
|||||||
expect(md).toContain('keine Rechtsberatung');
|
expect(md).toContain('keine Rechtsberatung');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Papierfassung enthält alle Fragen, Ankreuzfelder und Auswertungszeile', () => {
|
||||||
|
const md = printableTestDoc(CONTENT_PACK, '2026-07-04', profile);
|
||||||
|
expect(md).toContain('Papierfassung');
|
||||||
|
expect((md.match(/☐/g) ?? []).length).toBe(36); // 12 Fragen × 3 Optionen
|
||||||
|
expect(md).toContain('**Name:**');
|
||||||
|
expect(md).toContain('Ergebnis: ______ / 12');
|
||||||
|
expect(md).not.toContain('richtige Antwort'); // keine Lösungen im Testbogen
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Lösungsbogen nennt je Frage den richtigen Buchstaben', () => {
|
||||||
|
const md = answerKeyDoc(CONTENT_PACK, '2026-07-04', profile);
|
||||||
|
expect(md).toContain('Lösungsbogen');
|
||||||
|
expect((md.match(/\| \d+ \| \*\*[ABC]\*\* \|/g) ?? []).length).toBe(12);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Schulungshandout enthält die 12 Erklärungen und ist lokalisiert', () => {
|
||||||
|
const de = handoutDoc(CONTENT_PACK, '2026-07-04', profile, 'de');
|
||||||
|
expect(de).toContain('Schulungshandout');
|
||||||
|
expect((de.match(/^## \d+\./gm) ?? []).length).toBe(12);
|
||||||
|
const en = handoutDoc(CONTENT_PACK, '2026-07-04', profile, 'en');
|
||||||
|
expect(en).toContain('Training handout');
|
||||||
|
expect(en).not.toBe(de);
|
||||||
|
});
|
||||||
|
|
||||||
it('erzeugt das Schulungsregister mit allen Durchläufen', () => {
|
it('erzeugt das Schulungsregister mit allen Durchläufen', () => {
|
||||||
const md = trainingLogDoc(
|
const md = trainingLogDoc(
|
||||||
[
|
[
|
||||||
|
|||||||
@ -168,6 +168,156 @@ export function certificateDoc(
|
|||||||
].join('\n');
|
].join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface PrintStrings {
|
||||||
|
readonly testTitle: string;
|
||||||
|
readonly testIntro: string;
|
||||||
|
readonly nameDateLine: string;
|
||||||
|
readonly testFooter: string;
|
||||||
|
readonly keyTitle: string;
|
||||||
|
readonly keyIntro: string;
|
||||||
|
readonly keyCols: string;
|
||||||
|
readonly handoutTitle: string;
|
||||||
|
readonly handoutIntro: string;
|
||||||
|
readonly handoutFooter: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PRINT: Readonly<Record<'de' | 'en', PrintStrings>> = {
|
||||||
|
de: {
|
||||||
|
testTitle: 'KI-Kompetenztest (Art. 4 EU-KI-VO) — Papierfassung',
|
||||||
|
testIntro:
|
||||||
|
'Bitte kreuzen Sie je Frage genau eine Antwort an. Bestehensgrenze: {pct} % ({min} von {total} Fragen). Die Auswertung erfolgt mit dem Lösungsbogen; das Ergebnis wird im Schulungsregister dokumentiert.',
|
||||||
|
nameDateLine: '**Name:** ______________________________ **Datum:** ______________ **Abteilung:** ______________________________',
|
||||||
|
testFooter: 'Unterschrift Beschäftigte/r: _______________ Ausgewertet durch (Name, Unterschrift): _______________ Ergebnis: ______ / {total}',
|
||||||
|
keyTitle: 'KI-Kompetenztest — Lösungsbogen (nur für Auswertende)',
|
||||||
|
keyIntro: 'Richtige Antworten und Erklärungen. Bestehensgrenze: {pct} % ({min} von {total} Fragen).',
|
||||||
|
keyCols: '| Nr. | Richtig | Erklärung |',
|
||||||
|
handoutTitle: 'Schulungshandout: Die 12 wichtigsten Regeln im Umgang mit KI',
|
||||||
|
handoutIntro:
|
||||||
|
'Dieses Handout fasst die Kernregeln für den Arbeitsalltag zusammen und dient als Schulungsunterlage nach Art. 4 EU-KI-VO. Es kann vor dem Kompetenztest ausgeteilt werden.',
|
||||||
|
handoutFooter:
|
||||||
|
'Bei Fragen oder Vorfällen: an die/den KI-Beauftragte/n wenden (siehe interne Melde- und Eskalationsrichtlinie).',
|
||||||
|
},
|
||||||
|
en: {
|
||||||
|
testTitle: 'AI literacy test (Art. 4 EU AI Act) — paper version',
|
||||||
|
testIntro:
|
||||||
|
'Please tick exactly one answer per question. Pass threshold: {pct} % ({min} of {total} questions). Marking is done with the answer key; the result is documented in the training register.',
|
||||||
|
nameDateLine: '**Name:** ______________________________ **Date:** ______________ **Department:** ______________________________',
|
||||||
|
testFooter: 'Signature employee: _______________ Marked by (name, signature): _______________ Score: ______ / {total}',
|
||||||
|
keyTitle: 'AI literacy test — answer key (for markers only)',
|
||||||
|
keyIntro: 'Correct answers and explanations. Pass threshold: {pct} % ({min} of {total} questions).',
|
||||||
|
keyCols: '| No. | Correct | Explanation |',
|
||||||
|
handoutTitle: 'Training handout: the 12 most important rules for working with AI',
|
||||||
|
handoutIntro:
|
||||||
|
'This handout summarises the core rules for everyday work and serves as training material under Art. 4 EU AI Act. It can be handed out before the literacy test.',
|
||||||
|
handoutFooter:
|
||||||
|
'For questions or incidents: contact the AI officer (see the internal reporting and escalation policy).',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function printStrings(locale: Locale): PrintStrings {
|
||||||
|
return locale === 'de' ? PRINT.de : PRINT.en;
|
||||||
|
}
|
||||||
|
|
||||||
|
const OPTION_LETTERS = ['A', 'B', 'C'] as const;
|
||||||
|
|
||||||
|
function minCorrect(): number {
|
||||||
|
return Math.ceil((QUIZ_PASS_PCT / 100) * QUIZ_QUESTIONS.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
function fillIn(template: string): string {
|
||||||
|
return template
|
||||||
|
.replace('{pct}', String(QUIZ_PASS_PCT))
|
||||||
|
.replace('{min}', String(minCorrect()))
|
||||||
|
.replaceAll('{total}', String(QUIZ_QUESTIONS.length));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erzeugt die Papierfassung des Kompetenztests (zum Ausdrucken und
|
||||||
|
* handschriftlichen Ausfüllen) als Markdown.
|
||||||
|
*/
|
||||||
|
export function printableTestDoc(
|
||||||
|
pack: ContentPack,
|
||||||
|
today: string,
|
||||||
|
profile?: CompanyProfile,
|
||||||
|
locale: Locale = 'de',
|
||||||
|
): string {
|
||||||
|
const s = docStrings(locale);
|
||||||
|
const p = printStrings(locale);
|
||||||
|
const company = profile && profile.name.trim() !== '' ? profile.name : '_______________';
|
||||||
|
const lines = [
|
||||||
|
`# ${p.testTitle}`,
|
||||||
|
'',
|
||||||
|
`**${s.meta.company}:** ${company} · ${s.inventory.asOf}: ${formatDocDate(today, locale)} · Content-Pack v${pack.version}`,
|
||||||
|
'',
|
||||||
|
p.nameDateLine,
|
||||||
|
'',
|
||||||
|
fillIn(p.testIntro),
|
||||||
|
'',
|
||||||
|
];
|
||||||
|
getQuiz(locale).forEach((q, i) => {
|
||||||
|
lines.push(`## ${i + 1}. ${q.question}`, '');
|
||||||
|
q.options.forEach((option, oi) => {
|
||||||
|
lines.push(`- ☐ **${OPTION_LETTERS[oi]})** ${option}`);
|
||||||
|
});
|
||||||
|
lines.push('');
|
||||||
|
});
|
||||||
|
lines.push(fillIn(p.testFooter));
|
||||||
|
return lines.join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Erzeugt den Lösungsbogen (richtige Antworten + Erklärungen) als Markdown. */
|
||||||
|
export function answerKeyDoc(
|
||||||
|
pack: ContentPack,
|
||||||
|
today: string,
|
||||||
|
profile?: CompanyProfile,
|
||||||
|
locale: Locale = 'de',
|
||||||
|
): string {
|
||||||
|
const s = docStrings(locale);
|
||||||
|
const p = printStrings(locale);
|
||||||
|
const company = profile && profile.name.trim() !== '' ? profile.name : '_______________';
|
||||||
|
const lines = [
|
||||||
|
`# ${p.keyTitle}`,
|
||||||
|
'',
|
||||||
|
`**${s.meta.company}:** ${company} · ${s.inventory.asOf}: ${formatDocDate(today, locale)} · Content-Pack v${pack.version}`,
|
||||||
|
'',
|
||||||
|
fillIn(p.keyIntro),
|
||||||
|
'',
|
||||||
|
p.keyCols,
|
||||||
|
'|---|---|---|',
|
||||||
|
];
|
||||||
|
getQuiz(locale).forEach((q, i) => {
|
||||||
|
lines.push(`| ${i + 1} | **${OPTION_LETTERS[q.correctIndex]}** | ${q.explanation} |`);
|
||||||
|
});
|
||||||
|
return lines.join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Erzeugt das Schulungshandout (Kernregeln aus den Erklärungen) als Markdown. */
|
||||||
|
export function handoutDoc(
|
||||||
|
pack: ContentPack,
|
||||||
|
today: string,
|
||||||
|
profile?: CompanyProfile,
|
||||||
|
locale: Locale = 'de',
|
||||||
|
): string {
|
||||||
|
const s = docStrings(locale);
|
||||||
|
const p = printStrings(locale);
|
||||||
|
const company = profile && profile.name.trim() !== '' ? profile.name : '_______________';
|
||||||
|
const lines = [
|
||||||
|
`# ${p.handoutTitle}`,
|
||||||
|
'',
|
||||||
|
`**${s.meta.company}:** ${company} · ${s.inventory.asOf}: ${formatDocDate(today, locale)} · Content-Pack v${pack.version}`,
|
||||||
|
'',
|
||||||
|
s.disclaimer,
|
||||||
|
'',
|
||||||
|
p.handoutIntro,
|
||||||
|
'',
|
||||||
|
];
|
||||||
|
getQuiz(locale).forEach((q, i) => {
|
||||||
|
lines.push(`## ${i + 1}. ${q.question}`, '', q.explanation, '');
|
||||||
|
});
|
||||||
|
lines.push(p.handoutFooter);
|
||||||
|
return lines.join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Erzeugt das druckbare Schulungsregister (alle Testdurchläufe) als Markdown.
|
* Erzeugt das druckbare Schulungsregister (alle Testdurchläufe) als Markdown.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -62,6 +62,10 @@ export const CS: UIStrings = {
|
|||||||
quizLogPrint: 'Vytisknout registr / PDF',
|
quizLogPrint: 'Vytisknout registr / PDF',
|
||||||
quizColScore: 'Výsledek',
|
quizColScore: 'Výsledek',
|
||||||
quizColStatus: 'Stav',
|
quizColStatus: 'Stav',
|
||||||
|
quizDocsTitle: 'Tisk školicích materiálů',
|
||||||
|
quizPrintTest: 'Papírová verze testu',
|
||||||
|
quizPrintKey: 'List s řešením',
|
||||||
|
quizPrintHandout: 'Školicí materiál (12 pravidel)',
|
||||||
|
|
||||||
wizardTitleNew: 'Posoudit nový systém AI',
|
wizardTitleNew: 'Posoudit nový systém AI',
|
||||||
wizardTitleRe: 'Nové posouzení: {name}',
|
wizardTitleRe: 'Nové posouzení: {name}',
|
||||||
|
|||||||
@ -62,6 +62,10 @@ export const ES: UIStrings = {
|
|||||||
quizLogPrint: 'Imprimir registro / PDF',
|
quizLogPrint: 'Imprimir registro / PDF',
|
||||||
quizColScore: 'Resultado',
|
quizColScore: 'Resultado',
|
||||||
quizColStatus: 'Estado',
|
quizColStatus: 'Estado',
|
||||||
|
quizDocsTitle: 'Imprimir materiales de formación',
|
||||||
|
quizPrintTest: 'Versión en papel del test',
|
||||||
|
quizPrintKey: 'Hoja de soluciones',
|
||||||
|
quizPrintHandout: 'Material de formación (12 reglas)',
|
||||||
|
|
||||||
wizardTitleNew: 'Evaluar un nuevo sistema de IA',
|
wizardTitleNew: 'Evaluar un nuevo sistema de IA',
|
||||||
wizardTitleRe: 'Reevaluación: {name}',
|
wizardTitleRe: 'Reevaluación: {name}',
|
||||||
|
|||||||
@ -62,6 +62,10 @@ export const FR: UIStrings = {
|
|||||||
quizLogPrint: 'Imprimer le registre / PDF',
|
quizLogPrint: 'Imprimer le registre / PDF',
|
||||||
quizColScore: 'Résultat',
|
quizColScore: 'Résultat',
|
||||||
quizColStatus: 'Statut',
|
quizColStatus: 'Statut',
|
||||||
|
quizDocsTitle: 'Imprimer les supports de formation',
|
||||||
|
quizPrintTest: 'Version papier du test',
|
||||||
|
quizPrintKey: 'Corrigé',
|
||||||
|
quizPrintHandout: 'Support de formation (12 règles)',
|
||||||
|
|
||||||
wizardTitleNew: 'Évaluer un nouveau système d’IA',
|
wizardTitleNew: 'Évaluer un nouveau système d’IA',
|
||||||
wizardTitleRe: 'Réévaluation : {name}',
|
wizardTitleRe: 'Réévaluation : {name}',
|
||||||
|
|||||||
@ -62,6 +62,10 @@ export const IT: UIStrings = {
|
|||||||
quizLogPrint: 'Stampa registro / PDF',
|
quizLogPrint: 'Stampa registro / PDF',
|
||||||
quizColScore: 'Risultato',
|
quizColScore: 'Risultato',
|
||||||
quizColStatus: 'Stato',
|
quizColStatus: 'Stato',
|
||||||
|
quizDocsTitle: 'Stampa materiali formativi',
|
||||||
|
quizPrintTest: 'Versione cartacea del test',
|
||||||
|
quizPrintKey: 'Foglio delle soluzioni',
|
||||||
|
quizPrintHandout: 'Dispensa formativa (12 regole)',
|
||||||
|
|
||||||
wizardTitleNew: 'Valutare un nuovo sistema di IA',
|
wizardTitleNew: 'Valutare un nuovo sistema di IA',
|
||||||
wizardTitleRe: 'Rivalutazione: {name}',
|
wizardTitleRe: 'Rivalutazione: {name}',
|
||||||
|
|||||||
@ -62,6 +62,10 @@ export const PL: UIStrings = {
|
|||||||
quizLogPrint: 'Drukuj rejestr / PDF',
|
quizLogPrint: 'Drukuj rejestr / PDF',
|
||||||
quizColScore: 'Wynik',
|
quizColScore: 'Wynik',
|
||||||
quizColStatus: 'Status',
|
quizColStatus: 'Status',
|
||||||
|
quizDocsTitle: 'Drukuj materiały szkoleniowe',
|
||||||
|
quizPrintTest: 'Wersja papierowa testu',
|
||||||
|
quizPrintKey: 'Arkusz odpowiedzi',
|
||||||
|
quizPrintHandout: 'Materiał szkoleniowy (12 zasad)',
|
||||||
|
|
||||||
wizardTitleNew: 'Oceń nowy system AI',
|
wizardTitleNew: 'Oceń nowy system AI',
|
||||||
wizardTitleRe: 'Ponowna ocena: {name}',
|
wizardTitleRe: 'Ponowna ocena: {name}',
|
||||||
|
|||||||
@ -62,6 +62,10 @@ export const RO: UIStrings = {
|
|||||||
quizLogPrint: 'Tipărește registrul / PDF',
|
quizLogPrint: 'Tipărește registrul / PDF',
|
||||||
quizColScore: 'Rezultat',
|
quizColScore: 'Rezultat',
|
||||||
quizColStatus: 'Stare',
|
quizColStatus: 'Stare',
|
||||||
|
quizDocsTitle: 'Tipărește materialele de formare',
|
||||||
|
quizPrintTest: 'Versiunea pe hârtie a testului',
|
||||||
|
quizPrintKey: 'Foaia de răspunsuri',
|
||||||
|
quizPrintHandout: 'Material de formare (12 reguli)',
|
||||||
|
|
||||||
wizardTitleNew: 'Evaluează un sistem de IA nou',
|
wizardTitleNew: 'Evaluează un sistem de IA nou',
|
||||||
wizardTitleRe: 'Reevaluare: {name}',
|
wizardTitleRe: 'Reevaluare: {name}',
|
||||||
|
|||||||
@ -62,6 +62,10 @@ export const SK: UIStrings = {
|
|||||||
quizLogPrint: 'Vytlačiť register / PDF',
|
quizLogPrint: 'Vytlačiť register / PDF',
|
||||||
quizColScore: 'Výsledok',
|
quizColScore: 'Výsledok',
|
||||||
quizColStatus: 'Stav',
|
quizColStatus: 'Stav',
|
||||||
|
quizDocsTitle: 'Tlač školiacich materiálov',
|
||||||
|
quizPrintTest: 'Papierová verzia testu',
|
||||||
|
quizPrintKey: 'Hárok s riešeniami',
|
||||||
|
quizPrintHandout: 'Školiaci materiál (12 pravidiel)',
|
||||||
|
|
||||||
wizardTitleNew: 'Posúdiť nový systém AI',
|
wizardTitleNew: 'Posúdiť nový systém AI',
|
||||||
wizardTitleRe: 'Opätovné posúdenie: {name}',
|
wizardTitleRe: 'Opätovné posúdenie: {name}',
|
||||||
|
|||||||
@ -62,6 +62,10 @@ const DE = {
|
|||||||
quizLogPrint: 'Register drucken / PDF',
|
quizLogPrint: 'Register drucken / PDF',
|
||||||
quizColScore: 'Ergebnis',
|
quizColScore: 'Ergebnis',
|
||||||
quizColStatus: 'Status',
|
quizColStatus: 'Status',
|
||||||
|
quizDocsTitle: 'Schulungsunterlagen drucken',
|
||||||
|
quizPrintTest: 'Papierfassung des Tests',
|
||||||
|
quizPrintKey: 'Lösungsbogen',
|
||||||
|
quizPrintHandout: 'Schulungshandout (12 Regeln)',
|
||||||
|
|
||||||
wizardTitleNew: 'Neues KI-System bewerten',
|
wizardTitleNew: 'Neues KI-System bewerten',
|
||||||
wizardTitleRe: 'Neubewertung: {name}',
|
wizardTitleRe: 'Neubewertung: {name}',
|
||||||
@ -256,6 +260,10 @@ const EN: UIStrings = {
|
|||||||
quizLogPrint: 'Print register / PDF',
|
quizLogPrint: 'Print register / PDF',
|
||||||
quizColScore: 'Score',
|
quizColScore: 'Score',
|
||||||
quizColStatus: 'Status',
|
quizColStatus: 'Status',
|
||||||
|
quizDocsTitle: 'Print training materials',
|
||||||
|
quizPrintTest: 'Paper version of the test',
|
||||||
|
quizPrintKey: 'Answer key',
|
||||||
|
quizPrintHandout: 'Training handout (12 rules)',
|
||||||
|
|
||||||
wizardTitleNew: 'Assess a new AI system',
|
wizardTitleNew: 'Assess a new AI system',
|
||||||
wizardTitleRe: 'Reassessment: {name}',
|
wizardTitleRe: 'Reassessment: {name}',
|
||||||
|
|||||||
@ -1,5 +1,13 @@
|
|||||||
import { useMemo, useState } from 'react';
|
import { useMemo, useState } from 'react';
|
||||||
import { certificateDoc, getQuiz, scoreQuiz, trainingLogDoc } from '../engine/quiz';
|
import {
|
||||||
|
answerKeyDoc,
|
||||||
|
certificateDoc,
|
||||||
|
getQuiz,
|
||||||
|
handoutDoc,
|
||||||
|
printableTestDoc,
|
||||||
|
scoreQuiz,
|
||||||
|
trainingLogDoc,
|
||||||
|
} from '../engine/quiz';
|
||||||
import type { QuizScore, TrainingRecord } from '../engine/quiz';
|
import type { QuizScore, TrainingRecord } from '../engine/quiz';
|
||||||
import { QUIZ_PASS_PCT } from '../engine/quizContent';
|
import { QUIZ_PASS_PCT } from '../engine/quizContent';
|
||||||
import type { CompanyProfile } from '../engine/types';
|
import type { CompanyProfile } from '../engine/types';
|
||||||
@ -142,6 +150,36 @@ export function QuizView({ profile, records, onRecord }: QuizViewProps): JSX.Ele
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<div className="panel">
|
||||||
|
<h2 style={{ marginTop: 0 }}>{t.quizDocsTitle}</h2>
|
||||||
|
<div className="toolbar" style={{ marginBottom: 0 }}>
|
||||||
|
<button
|
||||||
|
className="ghost"
|
||||||
|
onClick={() =>
|
||||||
|
printDocument(`ki-test-papier-${today}`, printableTestDoc(pack, today, profile, locale), profile)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{t.quizPrintTest}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="ghost"
|
||||||
|
onClick={() =>
|
||||||
|
printDocument(`ki-test-loesungen-${today}`, answerKeyDoc(pack, today, profile, locale), profile)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{t.quizPrintKey}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="ghost"
|
||||||
|
onClick={() =>
|
||||||
|
printDocument(`ki-schulungshandout-${today}`, handoutDoc(pack, today, profile, locale), profile)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{t.quizPrintHandout}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="panel">
|
<div className="panel">
|
||||||
<div className="panel-head">
|
<div className="panel-head">
|
||||||
<h2 style={{ margin: 0 }}>{t.quizLogTitle}</h2>
|
<h2 style={{ margin: 0 }}>{t.quizLogTitle}</h2>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user