2026-07-07 11:14:00 +02:00
import type { FeedbackRating } from '../db/types'
2026-07-02 10:18:51 +02:00
export const BRAND_COLOR = '#0070AD'
/ * *
* Kanonische Reihenfolge der Rating - Skala ( nicht ä ndern — DB - Werte sind stabil ) .
* ` color ` = Badge / Display - State ( inaktiv )
* ` active ` = ausgewählter Button - State
* /
export const RATING_OPTIONS : ReadonlyArray < {
value : FeedbackRating
short : string
label : string
color : string
active : string
} > = [
{ value : 'na' , short : 'N/A' , label : 'N/A (0)' , color : 'bg-gray-100 text-gray-500 border-gray-300' , active : 'bg-gray-400 text-white border-gray-400' } ,
{ value : 'not_client_ready' , short : 'Not' , label : 'Not (1)' , color : 'bg-red-100 text-red-700 border-red-300' , active : 'bg-red-500 text-white border-red-500' } ,
{ value : 'partially_client_ready' , short : 'Partially' , label : 'Partially (2)' , color : 'bg-orange-100 text-orange-700 border-orange-300' , active : 'bg-orange-500 text-white border-orange-500' } ,
{ value : 'nearly_client_ready' , short : 'Nearly' , label : 'Nearly (3)' , color : 'bg-green-100 text-green-600 border-green-300' , active : 'bg-green-400 text-white border-green-400' } ,
{ value : 'client_ready' , short : 'Fully' , label : 'Fully (4)' , color : 'bg-green-100 text-green-800 border-green-400' , active : 'bg-green-700 text-white border-green-700' } ,
]
/** Farb-Schemata für Teilnehmer-Badges (Index = Reihenfolge im Assignment). */
export const INST_COLORS = [
{ bg : 'bg-blue-50' , border : 'border-blue-300' , tag : 'bg-blue-500' , text : 'text-blue-700' } ,
{ bg : 'bg-purple-50' , border : 'border-purple-300' , tag : 'bg-purple-500' , text : 'text-purple-700' } ,
{ bg : 'bg-emerald-50' , border : 'border-emerald-300' , tag : 'bg-emerald-500' , text : 'text-emerald-700' } ,
{ bg : 'bg-orange-50' , border : 'border-orange-300' , tag : 'bg-orange-500' , text : 'text-orange-700' } ,
] as const
export const AI_CONFIG = {
localStorageKeyApiKey : 'ai_api_key' ,
localStorageKeyModel : 'ai_model' ,
defaultModel : 'openai/gpt-4o-mini' ,
openRouterBaseUrl : 'https://openrouter.ai/api/v1' ,
2026-07-07 11:14:00 +02:00
defaultDimensionPromptTemplate : ` Du bist Führungskraft und Mentor bei Capgemini. Erstelle einen professionellen, konstruktiven Beitrag zum Performance-Feedback für einen Berater/Trainee, beschränkt auf die Dimension "{{DIMENSION_NAME}}", auf Basis der folgenden Beobachtungsdaten aus echten Kundenterminen.
BERATER : { { BERATER_NAME } }
ASSIGNMENT : { { ASSIGNMENT_TITEL } } | Kunde : { { ASSIGNMENT_KUNDE } }
FÜLLWÖRTER GESAMT : { { FUELLWOERTER_GESAMT } }
KATEGORIEN DIESER DIMENSION :
{ { KATEGORIEN_STRUKTUR } }
BEOBACHTETE KRITERIEN UND SCORES ( 0 - 4 ) :
{ { KRITERIEN_SCORES } }
MANUELLE KATEGORIE - BEWERTUNGEN :
{ { KATEGORIE_BEWERTUNGEN } }
ENTWICKLUNG Ü BER DIE LAUFZEIT ( chronologisch je Kategorie ) :
{ { ENTWICKLUNG_VERLAUF } }
ALLGEMEINE MEETING - NOTIZEN ( Berater - unabhängig , chronologisch ) :
{ { NOTIZEN_ALLGEMEIN_MEETING } }
NICHT EINEM KRITERIUM ZUGEORDNETE PROTOKOLL - NOTIZEN DIESES BERATERS ( chronologisch , Notation : + gut , ! negativ , > Kundeninput ) :
{ { PROTOKOLL_UNZUGEORDNET } }
Schreibe für JEDE der oben gelisteten Kategorien einen kurzen Bewertungstext ( 2 - 3 Sätze , konkret , auf Beobachtungen gestützt ) sowie abschließend einen Achievements - Absatz ( 2 - 4 Sätze , anerkennend ) und einen Development - Needs - Absatz ( 2 - 4 Sätze , konstruktiv , handlungsorientiert ) für die gesamte Dimension . Falls eine Kategorie aus den Daten nicht beurteilbar ist , schreibe "n/a" . Beziehe erkennbare Verbesserungen / Verschlechterungen aus der Entwicklung ü ber die Laufzeit ein . Schreibe direkt und persönlich ( du - Form ) , vermeide generische Phrasen .
Antworte AUSSCHLIESSLICH in exakt diesem Format , ohne zusätzliche Erklärungen , ohne Markdown - Formatierung :
KATEGORIE : < Name der ersten Kategorie >
< Bewertungstext >
KATEGORIE : < Name der zweiten Kategorie >
< Bewertungstext >
ACHIEVEMENTS :
< Text >
DEVELOPMENT_NEEDS :
< Text > ` ,
dimensionPromptPlaceholders : [
{ token : '{{BERATER_NAME}}' , description : 'Vor- und Nachname des Institutee' } ,
{ token : '{{ASSIGNMENT_TITEL}}' , description : 'Titel des Assignments' } ,
{ token : '{{ASSIGNMENT_KUNDE}}' , description : 'Kundenname des Assignments' } ,
{ token : '{{DIMENSION_NAME}}' , description : 'Name der aktuellen Dimension' } ,
{ token : '{{KATEGORIEN_STRUKTUR}}' , description : 'Liste der Kategorienamen dieser Dimension' } ,
{ token : '{{KRITERIEN_SCORES}}' , description : 'Kriterien mit Ø-Score und zusammengeführten Notizen, gruppiert nach Kategorie' } ,
{ token : '{{KATEGORIE_BEWERTUNGEN}}' , description : 'Manuell gesetzte Kategorie-Bewertungen (Not/Partially/Nearly/Fully)' } ,
{ token : '{{ENTWICKLUNG_VERLAUF}}' , description : 'Chronologischer Bewertungs-Trend je Kategorie über die Meetings' } ,
{ token : '{{NOTIZEN_ALLGEMEIN_MEETING}}' , description : 'Allgemeine, Berater-unabhängige Notizen je Meeting, chronologisch' } ,
{ token : '{{PROTOKOLL_UNZUGEORDNET}}' , description : 'Nicht getaggte Protokollzeilen dieses Beraters, chronologisch je Meeting' } ,
{ token : '{{FUELLWOERTER_GESAMT}}' , description : 'Füllwörter-Summe dieses Beraters über alle Meetings' } ,
] ,
2026-07-02 10:18:51 +02:00
} as const
/** Numerische Gewichte für Rating-Aggregation. N/A wird aus Berechnungen ausgeschlossen. */
export const RATING_NUM_MAP : Record < FeedbackRating , number > = {
na : 0 ,
not_client_ready : 1 ,
partially_client_ready : 2 ,
nearly_client_ready : 3 ,
client_ready : 4 ,
}
2026-07-03 11:56:22 +02:00
/** Default-Zeitgewichtung für den Bewertungs-Vorschlag, überschreibbar über Config > Gewichtung. */
export const DEFAULT_RATING_TREND_WEIGHT_STEP = 0.5
/** Mindest-Punktedelta zwischen erstem und letztem bewerteten Meeting einer Kategorie, ab dem ein Trend gilt. */
export const RATING_TREND_DELTA_THRESHOLD = 0.5