fixes comcoach
This commit is contained in:
parent
7a0880e064
commit
a79da7c337
6 changed files with 285 additions and 3 deletions
|
|
@ -149,3 +149,90 @@
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ============================================================ */
|
||||||
|
/* MOBILE RESPONSIVE */
|
||||||
|
/* ============================================================ */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.dashboard {
|
||||||
|
padding: 0.75rem;
|
||||||
|
}
|
||||||
|
.kpiGrid {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
.kpiCard {
|
||||||
|
padding: 0.85rem;
|
||||||
|
}
|
||||||
|
.kpiValue {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
.contextGrid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
.badgeGrid {
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
.badgeCard {
|
||||||
|
padding: 0.4rem 0.7rem;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 400px) {
|
||||||
|
.kpiGrid {
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
.kpiCard {
|
||||||
|
padding: 0.65rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
.kpiValue {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
}
|
||||||
|
.kpiLabel {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.newTopicBtn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.4rem;
|
||||||
|
padding: 0.6rem 1.25rem;
|
||||||
|
background: var(--primary-color, #F25843);
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.newTopicBtn:hover { filter: brightness(1.08); }
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.dashboard { padding: 0.75rem; }
|
||||||
|
|
||||||
|
.kpiGrid {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 0.65rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kpiCard { padding: 0.9rem; }
|
||||||
|
.kpiValue { font-size: 1.5rem; }
|
||||||
|
.kpiLabel { font-size: 0.78rem; }
|
||||||
|
.kpiSub { font-size: 0.7rem; }
|
||||||
|
|
||||||
|
.contextGrid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: 0.65rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badgeGrid { gap: 0.5rem; }
|
||||||
|
.badgeCard { padding: 0.4rem 0.65rem; font-size: 0.8rem; }
|
||||||
|
|
||||||
|
.sectionTitle { font-size: 1rem; }
|
||||||
|
.tipCard { padding: 0.9rem; font-size: 0.85rem; }
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,12 @@ export const CommcoachDashboardView: React.FC = () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const _handleNewTopic = useCallback(() => {
|
||||||
|
if (mandateId && instanceId) {
|
||||||
|
navigate(`/mandates/${mandateId}/commcoach/${instanceId}/coaching?newContext=true`);
|
||||||
|
}
|
||||||
|
}, [mandateId, instanceId, navigate]);
|
||||||
|
|
||||||
const _categoryLabel = useCallback(
|
const _categoryLabel = useCallback(
|
||||||
(category: string) => {
|
(category: string) => {
|
||||||
const labels: Record<string, string> = {
|
const labels: Record<string, string> = {
|
||||||
|
|
@ -88,11 +94,16 @@ export const CommcoachDashboardView: React.FC = () => {
|
||||||
|
|
||||||
{/* Active Contexts */}
|
{/* Active Contexts */}
|
||||||
<div className={styles.section}>
|
<div className={styles.section}>
|
||||||
<h3 className={styles.sectionTitle}>{t('Aktive Coaching-Themen')}</h3>
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '1rem' }}>
|
||||||
|
<h3 className={styles.sectionTitle} style={{ margin: 0 }}>{t('Aktive Coaching-Themen')}</h3>
|
||||||
|
<button className={styles.newTopicBtn} onClick={_handleNewTopic}>
|
||||||
|
+ {t('Neues Thema')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
{dashboard.contexts.length === 0 ? (
|
{dashboard.contexts.length === 0 ? (
|
||||||
<div className={styles.emptyState}>
|
<div className={styles.emptyState}>
|
||||||
<p>{t('Noch keine Coaching-Themen angelegt.')}</p>
|
<p>{t('Noch keine Coaching-Themen angelegt.')}</p>
|
||||||
<p>{t('Wechseln Sie zum Tab Coaching, um ein Thema anzulegen.')}</p>
|
<p>{t('Klicken Sie auf "Neues Thema" um zu starten.')}</p>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className={styles.contextGrid}>
|
<div className={styles.contextGrid}>
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,21 @@
|
||||||
min-width: 36px;
|
min-width: 36px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.dossierLayout {
|
||||||
|
flex-direction: column;
|
||||||
|
height: calc(100vh - var(--mobile-topbar-height, 56px));
|
||||||
|
}
|
||||||
|
|
||||||
|
.udbSidebar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.udbSidebarCollapsed {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.udbToggle {
|
.udbToggle {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 8px;
|
top: 8px;
|
||||||
|
|
@ -51,9 +66,17 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
min-height: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.dossier {
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Context Selector */
|
/* Context Selector */
|
||||||
.contextSelector {
|
.contextSelector {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
@ -65,6 +88,29 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.contextSelector {
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
overflow-x: auto;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
scrollbar-width: none;
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
}
|
||||||
|
.contextSelector::-webkit-scrollbar { display: none; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.contextSelector {
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
overflow-x: auto;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
gap: 0.4rem;
|
||||||
|
scrollbar-width: none;
|
||||||
|
}
|
||||||
|
.contextSelector::-webkit-scrollbar { display: none; }
|
||||||
|
}
|
||||||
|
|
||||||
.contextChip {
|
.contextChip {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
@ -166,6 +212,31 @@
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.header {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
}
|
||||||
|
.headerActions {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.header {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
}
|
||||||
|
.headerActions {
|
||||||
|
width: 100%;
|
||||||
|
justify-content: flex-start;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
.title { font-size: 1.1rem; }
|
||||||
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font-size: 1.3rem;
|
font-size: 1.3rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
|
@ -273,6 +344,36 @@
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.tabs {
|
||||||
|
overflow-x: auto;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
scrollbar-width: none;
|
||||||
|
padding: 0 0.5rem;
|
||||||
|
}
|
||||||
|
.tabs::-webkit-scrollbar { display: none; }
|
||||||
|
.tab {
|
||||||
|
white-space: nowrap;
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.tabs {
|
||||||
|
overflow-x: auto;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
padding: 0 0.5rem;
|
||||||
|
scrollbar-width: none;
|
||||||
|
}
|
||||||
|
.tabs::-webkit-scrollbar { display: none; }
|
||||||
|
.tab {
|
||||||
|
white-space: nowrap;
|
||||||
|
padding: 0.5rem 0.9rem;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.tab {
|
.tab {
|
||||||
padding: 0.6rem 1.25rem;
|
padding: 0.6rem 1.25rem;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
|
|
@ -325,6 +426,12 @@
|
||||||
.personaSelector { margin-bottom: 1rem; }
|
.personaSelector { margin-bottom: 1rem; }
|
||||||
.personaLabel { font-size: 0.85rem; font-weight: 500; color: var(--text-primary, #333); display: block; margin-bottom: 0.5rem; }
|
.personaLabel { font-size: 0.85rem; font-weight: 500; color: var(--text-primary, #333); display: block; margin-bottom: 0.5rem; }
|
||||||
.personaGrid { display: flex; flex-wrap: wrap; gap: 0.5rem; justify-content: center; }
|
.personaGrid { display: flex; flex-wrap: wrap; gap: 0.5rem; justify-content: center; }
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.personaGrid { gap: 0.35rem; }
|
||||||
|
.personaChip { font-size: 0.75rem; padding: 0.3rem 0.6rem; }
|
||||||
|
.sessionStart { padding: 1rem; }
|
||||||
|
}
|
||||||
.personaChip {
|
.personaChip {
|
||||||
display: flex; align-items: center; gap: 0.3rem;
|
display: flex; align-items: center; gap: 0.3rem;
|
||||||
padding: 0.4rem 0.8rem;
|
padding: 0.4rem 0.8rem;
|
||||||
|
|
@ -350,6 +457,17 @@
|
||||||
.sessionLabel { font-size: 0.85rem; font-weight: 500; color: var(--text-primary, #333); }
|
.sessionLabel { font-size: 0.85rem; font-weight: 500; color: var(--text-primary, #333); }
|
||||||
.sessionActions { display: flex; gap: 0.5rem; }
|
.sessionActions { display: flex; gap: 0.5rem; }
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.sessionHeader {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
}
|
||||||
|
.sessionActions {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Messages */
|
/* Messages */
|
||||||
.messages {
|
.messages {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|
@ -361,9 +479,25 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.message { max-width: 80%; }
|
.message { max-width: 80%; }
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.message { max-width: 92%; }
|
||||||
|
.messages { padding: 0.75rem 0.5rem; gap: 0.5rem; }
|
||||||
|
}
|
||||||
.messageUser { align-self: flex-end; }
|
.messageUser { align-self: flex-end; }
|
||||||
.messageAssistant { align-self: flex-start; }
|
.messageAssistant { align-self: flex-start; }
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.message { max-width: 92%; }
|
||||||
|
.messages { padding: 0.75rem; gap: 0.5rem; }
|
||||||
|
.sessionHeader {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.4rem;
|
||||||
|
padding: 0.4rem 0.75rem;
|
||||||
|
}
|
||||||
|
.sessionActions { flex-wrap: wrap; gap: 0.3rem; }
|
||||||
|
}
|
||||||
|
|
||||||
.messageBubble {
|
.messageBubble {
|
||||||
padding: 0.75rem 1rem;
|
padding: 0.75rem 1rem;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
|
|
@ -528,6 +662,25 @@
|
||||||
|
|
||||||
.textInputRow { display: flex; gap: 0.5rem; align-items: flex-end; }
|
.textInputRow { display: flex; gap: 0.5rem; align-items: flex-end; }
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.inputArea {
|
||||||
|
padding: 0.5rem 0.5rem calc(env(safe-area-inset-bottom, 0px) + 0.5rem);
|
||||||
|
}
|
||||||
|
.textInputRow {
|
||||||
|
gap: 0.35rem;
|
||||||
|
}
|
||||||
|
.sendBtn {
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.inputArea { padding: 0.5rem 0.75rem; }
|
||||||
|
.textInputRow { gap: 0.35rem; }
|
||||||
|
.sendBtn { padding: 0.5rem 0.75rem; font-size: 0.8rem; }
|
||||||
|
}
|
||||||
|
|
||||||
.textInput {
|
.textInput {
|
||||||
flex: 1; min-width: 0;
|
flex: 1; min-width: 0;
|
||||||
padding: 0.6rem 0.75rem;
|
padding: 0.6rem 0.75rem;
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useState, useRef, useCallback, useEffect } from 'react';
|
import React, { useState, useRef, useCallback, useEffect } from 'react';
|
||||||
|
import { useSearchParams } from 'react-router-dom';
|
||||||
import { useCommcoach } from '../../../hooks/useCommcoach';
|
import { useCommcoach } from '../../../hooks/useCommcoach';
|
||||||
import { type TtsEvent } from '../../../hooks/useTtsPlayback';
|
import { type TtsEvent } from '../../../hooks/useTtsPlayback';
|
||||||
import { useApiRequest } from '../../../hooks/useApi';
|
import { useApiRequest } from '../../../hooks/useApi';
|
||||||
|
|
@ -73,6 +74,7 @@ export const CommcoachDossierView: React.FC<CommcoachDossierViewProps> = ({ pers
|
||||||
const mandateId = persistentMandateId || routeMandateId;
|
const mandateId = persistentMandateId || routeMandateId;
|
||||||
const coach = useCommcoach(instanceId);
|
const coach = useCommcoach(instanceId);
|
||||||
const { request } = useApiRequest();
|
const { request } = useApiRequest();
|
||||||
|
const [searchParams, setSearchParams] = useSearchParams();
|
||||||
|
|
||||||
const [activeTab, setActiveTab] = useState<TabKey>('coaching');
|
const [activeTab, setActiveTab] = useState<TabKey>('coaching');
|
||||||
const [showNewContext, setShowNewContext] = useState(false);
|
const [showNewContext, setShowNewContext] = useState(false);
|
||||||
|
|
@ -144,6 +146,14 @@ export const CommcoachDossierView: React.FC<CommcoachDossierViewProps> = ({ pers
|
||||||
}
|
}
|
||||||
}, [coach.contexts, coach.selectedContextId, coach.selectContext]);
|
}, [coach.contexts, coach.selectedContextId, coach.selectContext]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (searchParams.get('newContext') === 'true') {
|
||||||
|
setShowNewContext(true);
|
||||||
|
searchParams.delete('newContext');
|
||||||
|
setSearchParams(searchParams, { replace: true });
|
||||||
|
}
|
||||||
|
}, [searchParams, setSearchParams]);
|
||||||
|
|
||||||
// Load scores, personas when context changes
|
// Load scores, personas when context changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!instanceId || !coach.selectedContextId) return;
|
if (!instanceId || !coach.selectedContextId) return;
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,6 @@ export const CommcoachKeepAlive: React.FC<CommcoachKeepAliveProps> = ({ isVisibl
|
||||||
left: 0,
|
left: 0,
|
||||||
right: 0,
|
right: 0,
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
overflow: 'hidden',
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CommcoachDossierView
|
<CommcoachDossierView
|
||||||
|
|
|
||||||
|
|
@ -154,3 +154,25 @@
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.settings {
|
||||||
|
padding: 0.75rem;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
.statsGrid {
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
.voiceRow {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.settings { padding: 0.75rem; max-width: 100%; }
|
||||||
|
.statsGrid { grid-template-columns: 1fr 1fr; gap: 0.5rem; }
|
||||||
|
.statItem { padding: 0.5rem; }
|
||||||
|
.statValue { font-size: 1.2rem; }
|
||||||
|
.voiceRow { flex-direction: column; }
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue