KI-AGENT: Siri-Kurzbefehle für FEDEO-Todos ergänzen

This commit is contained in:
2026-08-08 22:59:15 +02:00
parent 5dae5b6aa5
commit ecbfdaa0cb
5 changed files with 530 additions and 1 deletions

View File

@@ -5,6 +5,7 @@ import { router } from 'expo-router';
import { DEFAULT_API_BASE_URL } from '@/src/config/env';
import { sendMobileTestPush } from '@/src/lib/api';
import { registerDeviceForPush } from '@/src/lib/push-registration';
import { getSiriPreferredTenantId, setSiriPreferredTenantId } from '@/src/lib/siri-settings';
import {
getApiBaseUrlSync,
hydrateApiBaseUrl,
@@ -21,13 +22,15 @@ function isValidServerUrl(value: string): boolean {
}
export default function SettingsScreen() {
const { logout, token } = useAuth();
const { activeTenantId, logout, tenants, token } = useAuth();
const [serverUrl, setServerUrlInput] = useState(getApiBaseUrlSync());
const [savedUrl, setSavedUrl] = useState(getApiBaseUrlSync());
const [submitting, setSubmitting] = useState(false);
const [pushSubmitting, setPushSubmitting] = useState(false);
const [error, setError] = useState<string | null>(null);
const [success, setSuccess] = useState<string | null>(null);
const [siriTenantId, setSiriTenantId] = useState<number | null>(null);
const [siriSubmitting, setSiriSubmitting] = useState(false);
const loadConfig = useCallback(async () => {
const current = await hydrateApiBaseUrl();
@@ -37,8 +40,26 @@ export default function SettingsScreen() {
useEffect(() => {
void loadConfig();
void getSiriPreferredTenantId().then(setSiriTenantId);
}, [loadConfig]);
async function onSelectSiriTenant(tenantId: number | null) {
setSiriSubmitting(true);
setError(null);
setSuccess(null);
try {
await setSiriPreferredTenantId(tenantId);
setSiriTenantId(tenantId);
setSuccess(tenantId === null
? 'Siri fragt beim nächsten Befehl wieder nach dem Tenant.'
: 'Siri-Standardtenant gespeichert.');
} catch (err) {
setError(err instanceof Error ? err.message : 'Siri-Standardtenant konnte nicht gespeichert werden.');
} finally {
setSiriSubmitting(false);
}
}
async function onSave() {
setError(null);
setSuccess(null);
@@ -175,6 +196,43 @@ export default function SettingsScreen() {
</View>
</View>
<View style={styles.card}>
<Text style={styles.title}>Siri & Kurzbefehle</Text>
<Text style={styles.hint}>
Der Siri-Standardtenant gilt nur für Sprachbefehle. Der aktuell in FEDEO geöffnete Tenant wird dadurch
nicht gewechselt. Ohne Auswahl fragt Siri beim nächsten Befehl nach.
</Text>
{tenants.map((tenant) => {
const tenantId = Number(tenant.id);
const selected = tenantId === siriTenantId;
return (
<Pressable
key={String(tenant.id)}
style={[styles.tenantButton, selected ? styles.tenantButtonSelected : null]}
onPress={() => onSelectSiriTenant(tenantId)}
disabled={siriSubmitting}>
<View style={styles.tenantTextWrap}>
<Text style={[styles.tenantName, selected ? styles.tenantNameSelected : null]}>{tenant.name}</Text>
{tenantId === activeTenantId ? <Text style={styles.meta}>Aktuell in FEDEO geöffnet</Text> : null}
</View>
<Text style={[styles.tenantAction, selected ? styles.tenantActionSelected : null]}>
{selected ? 'Siri-Standard' : 'Auswählen'}
</Text>
</Pressable>
);
})}
<Pressable
style={[styles.resetButton, siriSubmitting ? styles.buttonDisabled : null]}
onPress={() => onSelectSiriTenant(null)}
disabled={siriSubmitting || siriTenantId === null}>
<Text style={styles.resetButtonText}>Bei nächstem Befehl nachfragen</Text>
</Pressable>
<Text style={styles.meta}>Verfügbar: Todo erstellen · Offene Todos anzeigen · Todo erledigen</Text>
</View>
<View style={styles.card}>
<Text style={styles.title}>Mobile Push</Text>
<Text style={styles.hint}>
@@ -247,6 +305,25 @@ const styles = StyleSheet.create({
color: '#6b7280',
fontSize: 12,
},
tenantButton: {
minHeight: 52,
borderWidth: 1,
borderColor: '#d1d5db',
borderRadius: 10,
paddingHorizontal: 12,
paddingVertical: 9,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
gap: 10,
backgroundColor: '#ffffff',
},
tenantButtonSelected: { borderColor: PRIMARY, backgroundColor: '#eff9ea' },
tenantTextWrap: { flex: 1 },
tenantName: { color: '#111827', fontSize: 14, fontWeight: '600' },
tenantNameSelected: { color: '#2f5f24' },
tenantAction: { color: '#6b7280', fontSize: 12, fontWeight: '600' },
tenantActionSelected: { color: '#3d7a30' },
actions: {
gap: 8,
marginTop: 6,