Initial Mobile

This commit is contained in:
2026-02-19 18:29:06 +01:00
parent 844af30b18
commit c782492ab5
49 changed files with 15375 additions and 33 deletions

View File

@@ -0,0 +1,187 @@
import { useState } from 'react';
import { Pressable, ScrollView, StyleSheet, Text, View } from 'react-native';
import { useAuth, useTokenStorageInfo } from '@/src/providers/auth-provider';
const PRIMARY = '#69c350';
export default function AccountScreen() {
const { token, user, tenants, activeTenantId, activeTenant, switchTenant, logout } = useAuth();
const storageInfo = useTokenStorageInfo();
const [switchingTenantId, setSwitchingTenantId] = useState<number | null>(null);
const [switchError, setSwitchError] = useState<string | null>(null);
const userId = String(user?.id || 'unbekannt');
async function onSwitchTenant(tenantId: number) {
setSwitchingTenantId(tenantId);
setSwitchError(null);
try {
await switchTenant(tenantId);
} catch (err) {
setSwitchError(err instanceof Error ? err.message : 'Tenant konnte nicht gewechselt werden.');
} finally {
setSwitchingTenantId(null);
}
}
return (
<ScrollView contentContainerStyle={styles.container}>
<Text style={styles.title}>Konto</Text>
<Text style={styles.subtitle}>Session-Infos und Tenant-Wechsel.</Text>
<View style={styles.card}>
<Text style={styles.label}>Token vorhanden</Text>
<Text style={styles.value}>{token ? 'ja' : 'nein'}</Text>
<Text style={styles.label}>User ID</Text>
<Text style={styles.value}>{userId}</Text>
<Text style={styles.label}>Aktiver Tenant</Text>
<Text style={styles.value}>{activeTenant ? `${activeTenant.name} (#${activeTenantId})` : 'nicht gesetzt'}</Text>
<Text style={styles.label}>Storage Modus</Text>
<Text style={styles.value}>{storageInfo.mode}</Text>
</View>
<View style={styles.card}>
<Text style={styles.sectionTitle}>Tenant wechseln</Text>
{switchError ? <Text style={styles.error}>{switchError}</Text> : null}
{tenants.map((tenant) => {
const tenantId = Number(tenant.id);
const isActive = tenantId === activeTenantId;
const isSwitching = switchingTenantId === tenantId;
return (
<Pressable
key={String(tenant.id)}
style={[
styles.tenantButton,
isActive ? styles.tenantButtonActive : null,
isSwitching ? styles.tenantButtonDisabled : null,
]}
onPress={() => onSwitchTenant(tenantId)}
disabled={isActive || switchingTenantId !== null}>
<View style={styles.tenantInfo}>
<Text style={styles.tenantName} numberOfLines={2} ellipsizeMode="tail">
{tenant.name}
</Text>
<Text style={styles.tenantMeta}>ID: {tenantId}</Text>
</View>
<View style={styles.tenantActionWrap}>
<Text style={styles.tenantAction}>{isActive ? 'Aktiv' : isSwitching ? 'Wechsel...' : 'Wechseln'}</Text>
</View>
</Pressable>
);
})}
</View>
<Pressable style={styles.logoutButton} onPress={logout}>
<Text style={styles.logoutText}>Logout</Text>
</Pressable>
</ScrollView>
);
}
const styles = StyleSheet.create({
container: {
flexGrow: 1,
backgroundColor: '#f9fafb',
padding: 16,
gap: 12,
},
title: {
fontSize: 24,
fontWeight: '700',
color: '#111827',
},
subtitle: {
color: '#6b7280',
},
card: {
backgroundColor: '#ffffff',
borderRadius: 12,
padding: 14,
borderWidth: 1,
borderColor: '#e5e7eb',
gap: 8,
},
sectionTitle: {
fontSize: 16,
fontWeight: '600',
color: '#111827',
marginBottom: 2,
},
label: {
fontSize: 12,
color: '#6b7280',
textTransform: 'uppercase',
},
value: {
fontSize: 16,
color: '#111827',
marginBottom: 2,
},
error: {
color: '#dc2626',
marginBottom: 4,
},
tenantButton: {
borderRadius: 10,
padding: 12,
borderWidth: 1,
borderColor: '#d1d5db',
backgroundColor: '#ffffff',
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
tenantButtonActive: {
borderColor: PRIMARY,
backgroundColor: '#eff9ea',
},
tenantButtonDisabled: {
opacity: 0.6,
},
tenantInfo: {
flex: 1,
minWidth: 0,
paddingRight: 10,
},
tenantName: {
fontSize: 15,
fontWeight: '600',
color: '#111827',
flexShrink: 1,
},
tenantMeta: {
color: '#6b7280',
marginTop: 3,
},
tenantActionWrap: {
minWidth: 84,
alignItems: 'flex-end',
},
tenantAction: {
color: PRIMARY,
fontWeight: '600',
textAlign: 'right',
},
logoutButton: {
marginTop: 4,
backgroundColor: '#dc2626',
minHeight: 44,
borderRadius: 10,
alignItems: 'center',
justifyContent: 'center',
},
logoutText: {
color: '#ffffff',
fontWeight: '600',
fontSize: 16,
},
});