175 lines
6.2 KiB
TypeScript
175 lines
6.2 KiB
TypeScript
/**
|
|
* CommCoach Assistant View
|
|
*
|
|
* Wizard flow: Module type → Topic → Persona → KPIs → "Start first session"
|
|
*/
|
|
import React, { useState } from 'react';
|
|
import { useNavigate } from 'react-router-dom';
|
|
import { useCurrentInstance } from '../../../hooks/useCurrentInstance';
|
|
import * as commcoachApi from '../../../api/commcoachApi';
|
|
import { useLanguage } from '../../../providers/language/LanguageContext';
|
|
import styles from './Commcoach.module.css';
|
|
|
|
type WizardStep = 'type' | 'topic' | 'persona' | 'kpis' | 'confirm';
|
|
|
|
const STEPS: WizardStep[] = ['type', 'topic', 'persona', 'kpis', 'confirm'];
|
|
|
|
const MODULE_TYPES = [
|
|
{ value: 'coaching', label: 'Coaching', icon: '🎯' },
|
|
{ value: 'training', label: 'Training', icon: '📚' },
|
|
{ value: 'exam', label: 'Prüfung', icon: '✍️' },
|
|
{ value: 'elearning', label: 'E-Learning', icon: '💻' },
|
|
];
|
|
|
|
export const CommcoachAssistantView: React.FC = () => {
|
|
const { t } = useLanguage();
|
|
const { instance, mandateId } = useCurrentInstance();
|
|
const instanceId = instance?.id || '';
|
|
const navigate = useNavigate();
|
|
|
|
const [step, setStep] = useState<WizardStep>('type');
|
|
const [moduleType, setModuleType] = useState('coaching');
|
|
const [title, setTitle] = useState('');
|
|
const [goals, setGoals] = useState('');
|
|
const [personaId, setPersonaId] = useState<string | null>(null);
|
|
const [_personas, _setPersonas] = useState<any[]>([]);
|
|
const [loading, setLoading] = useState(false);
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
const stepIdx = STEPS.indexOf(step);
|
|
|
|
const _handleNext = () => {
|
|
const nextIdx = stepIdx + 1;
|
|
if (nextIdx < STEPS.length) setStep(STEPS[nextIdx]);
|
|
};
|
|
|
|
const _handleBack = () => {
|
|
const prevIdx = stepIdx - 1;
|
|
if (prevIdx >= 0) setStep(STEPS[prevIdx]);
|
|
};
|
|
|
|
const _handleCreate = async () => {
|
|
if (!title.trim()) {
|
|
setError(t('Bitte einen Titel eingeben'));
|
|
return;
|
|
}
|
|
setLoading(true);
|
|
setError(null);
|
|
try {
|
|
const apiRequest = commcoachApi.getApiRequest();
|
|
const module = await commcoachApi.createModuleApi(apiRequest, instanceId, {
|
|
title: title.trim(),
|
|
moduleType,
|
|
goals: goals.trim() || undefined,
|
|
personaId: personaId || undefined,
|
|
});
|
|
navigate(`/mandates/${mandateId}/commcoach/${instanceId}/session?moduleId=${module.id}`);
|
|
} catch (err: any) {
|
|
setError(err?.message || t('Fehler beim Erstellen'));
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className={styles.assistantContainer}>
|
|
<div className={styles.wizardHeader}>
|
|
<h2>{t('Neues Modul erstellen')}</h2>
|
|
<div className={styles.wizardHeaderRight}>
|
|
<div className={styles.stepIndicator}>
|
|
{STEPS.map((s, i) => (
|
|
<div key={s} className={`${styles.stepDot} ${i <= stepIdx ? styles.stepActive : ''}`} />
|
|
))}
|
|
</div>
|
|
<div className={styles.wizardActions}>
|
|
{stepIdx > 0 && (
|
|
<button className={styles.btnSecondary} onClick={_handleBack}>{t('Zurück')}</button>
|
|
)}
|
|
{step !== 'confirm' ? (
|
|
<button className={styles.btnPrimary} onClick={_handleNext}>{t('Weiter')}</button>
|
|
) : (
|
|
<button className={styles.btnPrimary} onClick={_handleCreate} disabled={loading}>
|
|
{loading ? t('Erstelle...') : t('Modul erstellen & erste Session starten')}
|
|
</button>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{error && <div className={styles.errorBanner}>{error}</div>}
|
|
|
|
<div className={styles.wizardContent}>
|
|
{step === 'type' && (
|
|
<div className={styles.wizardStep}>
|
|
<h3>{t('Modul-Typ wählen')}</h3>
|
|
<div className={styles.typeGrid}>
|
|
{MODULE_TYPES.map(mt => (
|
|
<button
|
|
key={mt.value}
|
|
className={`${styles.typeCard} ${moduleType === mt.value ? styles.typeCardActive : ''}`}
|
|
onClick={() => setModuleType(mt.value)}
|
|
>
|
|
<span className={styles.typeIcon}>{mt.icon}</span>
|
|
<span>{t(mt.label)}</span>
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{step === 'topic' && (
|
|
<div className={styles.wizardStep}>
|
|
<h3>{t('Thema & Titel')}</h3>
|
|
<input
|
|
type="text"
|
|
className={styles.wizardInput}
|
|
placeholder={t('z.B. Konfliktgespräche, Sales Training...')}
|
|
value={title}
|
|
onChange={e => setTitle(e.target.value)}
|
|
autoFocus
|
|
/>
|
|
<textarea
|
|
className={styles.wizardTextarea}
|
|
placeholder={t('Ziele beschreiben (optional)')}
|
|
value={goals}
|
|
onChange={e => setGoals(e.target.value)}
|
|
rows={4}
|
|
/>
|
|
</div>
|
|
)}
|
|
|
|
{step === 'persona' && (
|
|
<div className={styles.wizardStep}>
|
|
<h3>{t('Persona wählen (optional)')}</h3>
|
|
<p className={styles.wizardHint}>{t('Eine Persona bestimmt den Coaching-Stil. Du kannst dies später ändern.')}</p>
|
|
<button
|
|
className={`${styles.typeCard} ${!personaId ? styles.typeCardActive : ''}`}
|
|
onClick={() => setPersonaId(null)}
|
|
>
|
|
{t('Standard (kein Persona-Override)')}
|
|
</button>
|
|
</div>
|
|
)}
|
|
|
|
{step === 'kpis' && (
|
|
<div className={styles.wizardStep}>
|
|
<h3>{t('KPIs (optional)')}</h3>
|
|
<p className={styles.wizardHint}>{t('KPI-Ziele können später in den Modul-Einstellungen definiert werden.')}</p>
|
|
</div>
|
|
)}
|
|
|
|
{step === 'confirm' && (
|
|
<div className={styles.wizardStep}>
|
|
<h3>{t('Zusammenfassung')}</h3>
|
|
<div className={styles.confirmSummary}>
|
|
<div><strong>{t('Typ')}:</strong> {MODULE_TYPES.find(m => m.value === moduleType)?.label}</div>
|
|
<div><strong>{t('Titel')}:</strong> {title || t('(kein Titel)')}</div>
|
|
{goals && <div><strong>{t('Ziele')}:</strong> {goals}</div>}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
</div>
|
|
);
|
|
};
|