diff --git a/messages/de/field.json b/messages/de/field.json
index c1b3f21..f4cff5d 100644
--- a/messages/de/field.json
+++ b/messages/de/field.json
@@ -6,7 +6,8 @@
"emergency": "Notdienst",
"sync": "Sync",
"profile": "Profil",
- "approvalsBadge": "{count} Zeiten zur Freigabe"
+ "approvalsBadge": "{count} Zeiten zur Freigabe",
+ "lotse": "Lotse"
},
"connection": {
"online": "Online",
diff --git a/messages/de/lotse.json b/messages/de/lotse.json
index 313ff19..be3cd64 100644
--- a/messages/de/lotse.json
+++ b/messages/de/lotse.json
@@ -89,6 +89,8 @@
"use": "Verwendung",
"enabled": "Lotse für diesen Betrieb verwenden",
"enabledHint": "Ausgeschaltet: keine Berichtsentwürfe, keine Zusammenfassungen, Sprachnotizen ohne Transkription.",
+ "chatEnabled": "Lotse-Chat für Monteure",
+ "chatEnabledHint": "Monteure schreiben oder sprechen mit dem Lotsen. Aktionen (Status, Zeiten, Material, Notizen) werden nur nach Bestätigung durch den Monteur ausgeführt.",
"addressForm": "Anrede des Lotsen",
"addressFormHint": "Gilt einheitlich für alle Texte des Lotsen in diesem Betrieb.",
"address": {
@@ -114,7 +116,9 @@
"order": "Auftragstitel, Beschreibung und Leistungsumfang",
"notes": "Tätigkeitsnotizen und Texte aus Sprachnotizen",
"work": "Checkliste, Material mit Abweichungsgründen, Fotokommentare, Arbeitszeiten",
- "audio": "Für die Transkription: die Audiodatei der Sprachnotiz"
+ "audio": "Für die Transkription: die Audiodatei der Sprachnotiz",
+ "chat": "Lotse-Chat: Nachrichten des Monteurs (Telefonnummern, E-Mail-Adressen und Anschriften ersetzt) und die Auftragsdaten oben. Kundennamen und Kontaktdaten nur als Platzhalter – eingesetzt wird erst in der Antwort auf dem Gerät des Monteurs.",
+ "chatAudio": "Spracheingabe im Chat: die Aufnahme zur Transkription (wird nicht gespeichert)"
},
"notSentTitle": "Nicht gesendet wird",
"notSent": {
@@ -152,7 +156,172 @@
"voice_summary": "Zusammenfassung Sprachnotiz",
"transcription": "Transkription",
"import_extraction": "Auftragsimport",
- "completeness_check": "Vollständigkeitsprüfung"
+ "completeness_check": "Vollständigkeitsprüfung",
+ "lotse_chat": "Lotse-Chat"
+ }
+ },
+ "chat": {
+ "title": "Lotse-Chat",
+ "intro": "Kurz schreiben oder sprechen, was erledigt ist – z. B. „Auftrag fertig, Speicher installiert, 2 Std., 1 Filter verbaut“. Der Lotse schlägt Aktionen vor. Gespeichert wird erst nach Bestätigung.",
+ "context": "Auftrag {number} · {title}",
+ "noContext": "Ohne Auftragsbezug",
+ "ask": "Lotse fragen",
+ "input": "Nachricht an den Lotsen",
+ "send": "Senden",
+ "sending": "Lotse denkt nach …",
+ "newChat": "Neuer Chat",
+ "userLabel": "Eigene Nachricht",
+ "lotseLabel": "Lotse",
+ "empty": "Noch keine Nachrichten.",
+ "notConfigured": "Lotse ist nicht eingerichtet. Das Büro kann den KI-Anbieter hinterlegen.",
+ "offline": "Keine Verbindung. Der Lotse braucht Internet – die Eingabe bleibt erhalten.",
+ "chipsLabel": "Antwortvorschläge",
+ "linksLabel": "Direkt ergänzen",
+ "confirmAll": "Alle bestätigen ({count})",
+ "mic": {
+ "record": "Sprechen",
+ "stop": "Aufnahme beenden",
+ "recording": "Aufnahme läuft · {time}",
+ "transcribing": "Wird in Text umgewandelt …",
+ "unavailable": "Spracheingabe ist nicht eingerichtet.",
+ "denied": "Kein Zugriff auf das Mikrofon.",
+ "unsupported": "Spracheingabe wird auf diesem Gerät nicht unterstützt.",
+ "failed": "Umwandlung in Text fehlgeschlagen. Bitte tippen.",
+ "hint": "Text vor dem Senden prüfen."
+ },
+ "card": {
+ "confirm": "Bestätigen",
+ "edit": "Bearbeiten",
+ "discard": "Verwerfen",
+ "saveConfirm": "Übernehmen und bestätigen",
+ "cancel": "Abbrechen",
+ "busy": "Wird ausgeführt …",
+ "validUntil": "Gültig bis {time} Uhr",
+ "status": {
+ "proposed": "Offen – bitte bestätigen",
+ "confirmed": "Ausgeführt",
+ "discarded": "Verworfen",
+ "expired": "Abgelaufen",
+ "failed": "Nicht ausgeführt"
+ },
+ "kind": {
+ "transition_work_order": "Status ändern",
+ "book_time": "Zeit buchen",
+ "record_material": "Material erfassen",
+ "add_note": "Notiz speichern",
+ "suggest_report_fields": "Berichtsvorschlag"
+ },
+ "action": {
+ "accept": "Auftrag {number} annehmen",
+ "start_travel": "Anfahrt zu {number} starten",
+ "start_work": "Arbeit an {number} starten",
+ "pause": "Pause bei {number}",
+ "resume": "Arbeit an {number} fortsetzen",
+ "complete": "Auftrag {number} technisch abschließen"
+ },
+ "switchFrom": "Die laufende Uhr von {number} wird pausiert.",
+ "completeHint": "Die eigene Uhr wird beendet. Fehlende Pflichtangaben verhindern den Abschluss.",
+ "order": "Auftrag {number}",
+ "timeLine": "{date} · {from}–{to} Uhr · {duration} Std.",
+ "timeType": {
+ "work": "Arbeitszeit",
+ "travel": "Anfahrt",
+ "return_travel": "Rückfahrt",
+ "material_procurement": "Material holen"
+ },
+ "type": "Art",
+ "date": "Datum",
+ "from": "Von",
+ "to": "Bis",
+ "reason": "Grund",
+ "note": "Notiz",
+ "approvalHint": "Zählt nach Freigabe durch Teamleiter oder Büro.",
+ "pendingApproval": "Zur Freigabe eingereicht",
+ "planned": "Geplante Position",
+ "additional": "Zusatzmaterial",
+ "name": "Bezeichnung",
+ "quantity": "Menge",
+ "unit": "Einheit",
+ "deviationReason": "Grund der Abweichung",
+ "noteKind": "Art der Notiz",
+ "text": "Text",
+ "reportFields": "Vorschläge für den {type}",
+ "reportType": {
+ "daily": "Tagesbericht",
+ "completion": "Abschlussbericht"
+ },
+ "reportHint": "Erscheint im Bericht als „Vorschlag vom Lotsen“ und wird dort übernommen oder verworfen.",
+ "openReport": "Bericht öffnen",
+ "field": {
+ "workPerformed": "Ausgeführte Leistungen",
+ "deviations": "Abweichungen",
+ "additionalWork": "Zusatzarbeiten",
+ "openItems": "Offene Punkte",
+ "nextSteps": "Nächste Schritte",
+ "hints": "Hinweise"
+ }
+ },
+ "noteKind": {
+ "work_done": "Erledigte Arbeit",
+ "deviation": "Abweichung",
+ "problem": "Problem",
+ "additional_work": "Zusatzarbeit",
+ "not_executable": "Nicht ausführbar",
+ "follow_up": "Nacharbeit",
+ "recommendation": "Empfehlung",
+ "customer_note": "Hinweis vom Kunden",
+ "general": "Allgemein"
+ },
+ "system": {
+ "failed": "Nicht ausgeführt ({number}): {reason}",
+ "stopped": "„Alle bestätigen“ gestoppt – {remaining, plural, one {# Karte ist} other {# Karten sind}} noch offen.",
+ "rounds_exceeded": "Das war zu umfangreich. Bitte kürzer oder in Schritten schreiben.",
+ "turn_budget": "Das war zu umfangreich. Bitte kürzer oder in Schritten schreiben.",
+ "refusal": "Dazu kann der Lotse nichts vorschlagen.",
+ "provider_failed": "Lotse ist gerade nicht erreichbar. Bitte später erneut versuchen.",
+ "proposals_ready": "Vorschläge liegen bereit. Bitte prüfen und bestätigen.",
+ "empty": "Keine Antwort erhalten. Bitte anders formulieren."
+ },
+ "links": {
+ "order": "Auftrag öffnen",
+ "report": "Bericht öffnen",
+ "myTime": "Meine Zeiten öffnen",
+ "materials": "Material öffnen",
+ "otherOrder": "Laufenden Auftrag öffnen",
+ "runningSession": "Uhr eines Kollegen läuft noch"
+ },
+ "errors": {
+ "generic": "Das hat nicht geklappt. Bitte erneut versuchen.",
+ "not_found": "Nicht gefunden.",
+ "forbidden": "Dafür fehlt die Berechtigung.",
+ "disabled": "Lotse ist für diesen Betrieb ausgeschaltet.",
+ "chat_disabled": "Der Lotse-Chat ist für diesen Betrieb ausgeschaltet.",
+ "not_configured": "Lotse ist nicht eingerichtet.",
+ "provider_failed": "Lotse ist gerade nicht erreichbar. Bitte später erneut versuchen.",
+ "budget_exceeded": "Das monatliche KI-Kontingent des Betriebs ist aufgebraucht.",
+ "invalid": "Bitte Eingaben prüfen.",
+ "conflict": "Inzwischen geändert. Bitte neu laden.",
+ "expired": "Vorschlag abgelaufen (nach 30 Minuten). Bitte neu anfragen.",
+ "already_decided": "Dieser Vorschlag ist schon erledigt.",
+ "tampered": "Der Vorschlag wurde verändert und nicht ausgeführt.",
+ "blocked": "Pflichtangaben fehlen.",
+ "offline": "Keine Verbindung – nichts gesendet.",
+ "overlap": "Der Zeitraum überschneidet sich mit einer erfassten Zeit.",
+ "too_old": "Nachträge sind nur 7 Tage rückwirkend möglich.",
+ "in_future": "Zeiten in der Zukunft können nicht gebucht werden.",
+ "too_long": "Ein Eintrag darf höchstens 16 Stunden lang sein.",
+ "end_before_start": "Das Ende liegt vor dem Beginn.",
+ "work_order_status": "Im aktuellen Auftragsstatus nicht möglich.",
+ "other_session_running": "Auf einem anderen Auftrag läuft noch die Uhr.",
+ "transition_not_allowed": "Dieser Statuswechsel ist gerade nicht möglich.",
+ "transition_forbidden": "Dafür fehlt die Berechtigung.",
+ "not_editable": "Der Bericht ist eingereicht und kann nicht mehr geändert werden.",
+ "reason_required": "Der Grund fehlt.",
+ "use_billing_overview": "Nur über die Abrechnungsübersicht möglich."
+ },
+ "unavailable": {
+ "title": "Lotse-Chat nicht verfügbar",
+ "back": "Zur Übersicht"
}
}
}
diff --git a/messages/en/field.json b/messages/en/field.json
index 57a6825..9863338 100644
--- a/messages/en/field.json
+++ b/messages/en/field.json
@@ -6,7 +6,8 @@
"emergency": "Emergency",
"sync": "Sync",
"profile": "Profile",
- "approvalsBadge": "{count} time entries to approve"
+ "approvalsBadge": "{count} time entries to approve",
+ "lotse": "Lotse"
},
"connection": {
"online": "Online",
diff --git a/messages/en/lotse.json b/messages/en/lotse.json
index 00b78a4..aa89269 100644
--- a/messages/en/lotse.json
+++ b/messages/en/lotse.json
@@ -89,6 +89,8 @@
"use": "Usage",
"enabled": "Use Lotse in this business",
"enabledHint": "Switched off: no report drafts, no summaries, voice notes without transcription.",
+ "chatEnabled": "Lotse chat for technicians",
+ "chatEnabledHint": "Technicians write or talk to the Lotse. Actions (status, times, material, notes) are only executed after the technician confirms them.",
"addressForm": "Lotse form of address",
"addressFormHint": "Applies consistently to all Lotse texts in this business.",
"address": {
@@ -114,7 +116,9 @@
"order": "Work order title, description and scope",
"notes": "Activity notes and voice note texts",
"work": "Checklist, material with deviation reasons, photo comments, working times",
- "audio": "For transcription: the audio file of the voice note"
+ "audio": "For transcription: the audio file of the voice note",
+ "chat": "Lotse chat: the technician's messages (phone numbers, e-mail and postal addresses replaced) and the order data above. Customer names and contact data only as placeholders – values are inserted only in the answer on the technician's device.",
+ "chatAudio": "Voice input in the chat: the recording for transcription (not stored)"
},
"notSentTitle": "Not sent",
"notSent": {
@@ -152,7 +156,172 @@
"voice_summary": "Voice note summary",
"transcription": "Transcription",
"import_extraction": "Order import",
- "completeness_check": "Completeness check"
+ "completeness_check": "Completeness check",
+ "lotse_chat": "Lotse chat"
+ }
+ },
+ "chat": {
+ "title": "Lotse chat",
+ "intro": "Briefly write or say what is done – e.g. “Order finished, storage tank installed, 2 hrs, 1 filter fitted”. The Lotse proposes actions. Nothing is saved before confirmation.",
+ "context": "Order {number} · {title}",
+ "noContext": "No order context",
+ "ask": "Ask the Lotse",
+ "input": "Message to the Lotse",
+ "send": "Send",
+ "sending": "Lotse is thinking …",
+ "newChat": "New chat",
+ "userLabel": "Own message",
+ "lotseLabel": "Lotse",
+ "empty": "No messages yet.",
+ "notConfigured": "The Lotse is not set up. The office can configure the AI provider.",
+ "offline": "No connection. The Lotse needs internet – your input is kept.",
+ "chipsLabel": "Suggested answers",
+ "linksLabel": "Complete directly",
+ "confirmAll": "Confirm all ({count})",
+ "mic": {
+ "record": "Speak",
+ "stop": "Stop recording",
+ "recording": "Recording · {time}",
+ "transcribing": "Converting to text …",
+ "unavailable": "Voice input is not set up.",
+ "denied": "No access to the microphone.",
+ "unsupported": "Voice input is not supported on this device.",
+ "failed": "Conversion to text failed. Please type.",
+ "hint": "Check the text before sending."
+ },
+ "card": {
+ "confirm": "Confirm",
+ "edit": "Edit",
+ "discard": "Discard",
+ "saveConfirm": "Apply and confirm",
+ "cancel": "Cancel",
+ "busy": "Running …",
+ "validUntil": "Valid until {time}",
+ "status": {
+ "proposed": "Open – please confirm",
+ "confirmed": "Done",
+ "discarded": "Discarded",
+ "expired": "Expired",
+ "failed": "Not executed"
+ },
+ "kind": {
+ "transition_work_order": "Change status",
+ "book_time": "Book time",
+ "record_material": "Record material",
+ "add_note": "Save note",
+ "suggest_report_fields": "Report suggestion"
+ },
+ "action": {
+ "accept": "Accept order {number}",
+ "start_travel": "Start travel to {number}",
+ "start_work": "Start work on {number}",
+ "pause": "Pause {number}",
+ "resume": "Resume work on {number}",
+ "complete": "Technically complete order {number}"
+ },
+ "switchFrom": "The running clock of {number} will be paused.",
+ "completeHint": "Your own clock is stopped. Missing mandatory items prevent completion.",
+ "order": "Order {number}",
+ "timeLine": "{date} · {from}–{to} · {duration} hrs",
+ "timeType": {
+ "work": "Working time",
+ "travel": "Travel",
+ "return_travel": "Return travel",
+ "material_procurement": "Fetching material"
+ },
+ "type": "Type",
+ "date": "Date",
+ "from": "From",
+ "to": "To",
+ "reason": "Reason",
+ "note": "Note",
+ "approvalHint": "Counts after approval by the team lead or office.",
+ "pendingApproval": "Submitted for approval",
+ "planned": "Planned item",
+ "additional": "Additional material",
+ "name": "Name",
+ "quantity": "Quantity",
+ "unit": "Unit",
+ "deviationReason": "Reason for deviation",
+ "noteKind": "Note type",
+ "text": "Text",
+ "reportFields": "Suggestions for the {type}",
+ "reportType": {
+ "daily": "daily report",
+ "completion": "completion report"
+ },
+ "reportHint": "Appears in the report as “Suggestion from the Lotse” and is accepted or discarded there.",
+ "openReport": "Open report",
+ "field": {
+ "workPerformed": "Work performed",
+ "deviations": "Deviations",
+ "additionalWork": "Additional work",
+ "openItems": "Open items",
+ "nextSteps": "Next steps",
+ "hints": "Notes"
+ }
+ },
+ "noteKind": {
+ "work_done": "Work done",
+ "deviation": "Deviation",
+ "problem": "Problem",
+ "additional_work": "Additional work",
+ "not_executable": "Not executable",
+ "follow_up": "Follow-up",
+ "recommendation": "Recommendation",
+ "customer_note": "Customer note",
+ "general": "General"
+ },
+ "system": {
+ "failed": "Not executed ({number}): {reason}",
+ "stopped": "“Confirm all” stopped – {remaining, plural, one {# card is} other {# cards are}} still open.",
+ "rounds_exceeded": "That was too much at once. Please write shorter or in steps.",
+ "turn_budget": "That was too much at once. Please write shorter or in steps.",
+ "refusal": "The Lotse cannot propose anything for this.",
+ "provider_failed": "The Lotse is not reachable right now. Please try again later.",
+ "proposals_ready": "Proposals are ready. Please check and confirm.",
+ "empty": "No answer received. Please rephrase."
+ },
+ "links": {
+ "order": "Open order",
+ "report": "Open report",
+ "myTime": "Open my times",
+ "materials": "Open material",
+ "otherOrder": "Open running order",
+ "runningSession": "A colleague's clock is still running"
+ },
+ "errors": {
+ "generic": "That did not work. Please try again.",
+ "not_found": "Not found.",
+ "forbidden": "You lack the permission.",
+ "disabled": "The Lotse is switched off for this company.",
+ "chat_disabled": "The Lotse chat is switched off for this company.",
+ "not_configured": "The Lotse is not set up.",
+ "provider_failed": "The Lotse is not reachable right now. Please try again later.",
+ "budget_exceeded": "The company's monthly AI quota is used up.",
+ "invalid": "Please check your input.",
+ "conflict": "Changed in the meantime. Please reload.",
+ "expired": "Proposal expired (after 30 minutes). Please ask again.",
+ "already_decided": "This proposal has already been handled.",
+ "tampered": "The proposal was changed and not executed.",
+ "blocked": "Mandatory items are missing.",
+ "offline": "No connection – nothing sent.",
+ "overlap": "The period overlaps with recorded time.",
+ "too_old": "Entries can only be added up to 7 days back.",
+ "in_future": "Times in the future cannot be booked.",
+ "too_long": "An entry may be at most 16 hours long.",
+ "end_before_start": "The end is before the start.",
+ "work_order_status": "Not possible in the current order status.",
+ "other_session_running": "A clock is still running on another order.",
+ "transition_not_allowed": "This status change is not possible right now.",
+ "transition_forbidden": "You lack the permission.",
+ "not_editable": "The report has been submitted and can no longer be changed.",
+ "reason_required": "The reason is missing.",
+ "use_billing_overview": "Only possible via the billing overview."
+ },
+ "unavailable": {
+ "title": "Lotse chat not available",
+ "back": "Back to overview"
}
}
}
diff --git a/src/app/(app)/settings/lotse/page.tsx b/src/app/(app)/settings/lotse/page.tsx
index 449a264..a74f5e9 100644
--- a/src/app/(app)/settings/lotse/page.tsx
+++ b/src/app/(app)/settings/lotse/page.tsx
@@ -61,6 +61,15 @@ export default async function LotseSettingsPage({ searchParams }: { searchParams
{t("settings.enabledHint")}
+ {/* L16 Lotse-Chat für Monteure */}
+
+