112 lines
3.1 KiB
TypeScript
112 lines
3.1 KiB
TypeScript
import { useState } from 'react';
|
|
import { View, Text, Switch, ActivityIndicator } from 'react-native';
|
|
import { Ionicons } from '@expo/vector-icons';
|
|
|
|
type Props = {
|
|
icon: React.ComponentProps<typeof Ionicons>['name'];
|
|
title: string;
|
|
subtitle: string;
|
|
/** Wenn true: zeigt grünen Check statt Switch (Layer ist an). */
|
|
active: boolean;
|
|
/** Aktivierung (zeigt System-Dialog). UI hat nur read-on-flow,
|
|
* Toggle-off ist nicht hier — passiert nur über Cooldown. */
|
|
onActivate: () => Promise<{ enabled: boolean; error?: string }>;
|
|
/** Optional: Hinweistext unter Subtitle für commit-heavy Layer. */
|
|
warning?: string;
|
|
};
|
|
|
|
export function LayerSwitchCard({ icon, title, subtitle, active, onActivate, warning }: Props) {
|
|
const [busy, setBusy] = useState(false);
|
|
|
|
async function handleSwitch(v: boolean) {
|
|
if (!v || active || busy) return;
|
|
setBusy(true);
|
|
try {
|
|
await onActivate();
|
|
} finally {
|
|
setBusy(false);
|
|
}
|
|
}
|
|
|
|
const iconBg = active ? '#dcfce7' : '#f5f5f5';
|
|
const iconColor = active ? '#16a34a' : '#737373';
|
|
const borderColor = active ? '#86efac' : '#e5e5e5';
|
|
const cardBg = active ? '#f0fdf4' : '#ffffff';
|
|
|
|
return (
|
|
<View
|
|
style={{
|
|
backgroundColor: cardBg,
|
|
borderWidth: 1,
|
|
borderColor,
|
|
borderRadius: 16,
|
|
padding: 14,
|
|
}}
|
|
>
|
|
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 12 }}>
|
|
<View
|
|
style={{
|
|
width: 40,
|
|
height: 40,
|
|
borderRadius: 12,
|
|
backgroundColor: iconBg,
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
}}
|
|
>
|
|
<Ionicons name={icon} size={20} color={iconColor} />
|
|
</View>
|
|
<View style={{ flex: 1 }}>
|
|
<Text style={{ fontSize: 14, fontFamily: 'Nunito_700Bold', color: '#0a0a0a' }}>
|
|
{title}
|
|
</Text>
|
|
<Text
|
|
style={{
|
|
fontSize: 12,
|
|
fontFamily: 'Nunito_400Regular',
|
|
color: '#525252',
|
|
marginTop: 2,
|
|
}}
|
|
>
|
|
{subtitle}
|
|
</Text>
|
|
</View>
|
|
|
|
{busy ? (
|
|
<ActivityIndicator color={iconColor} />
|
|
) : active ? (
|
|
<Ionicons name="checkmark-circle" size={28} color="#16a34a" />
|
|
) : (
|
|
<Switch value={false} onValueChange={handleSwitch} trackColor={{ true: '#16a34a' }} />
|
|
)}
|
|
</View>
|
|
|
|
{warning && !active && (
|
|
<View
|
|
style={{
|
|
marginTop: 10,
|
|
paddingTop: 10,
|
|
borderTopWidth: 1,
|
|
borderTopColor: 'rgba(0,0,0,0.06)',
|
|
flexDirection: 'row',
|
|
gap: 8,
|
|
}}
|
|
>
|
|
<Ionicons name="information-circle" size={16} color="#525252" />
|
|
<Text
|
|
style={{
|
|
flex: 1,
|
|
fontSize: 11,
|
|
fontFamily: 'Nunito_400Regular',
|
|
color: '#525252',
|
|
lineHeight: 16,
|
|
}}
|
|
>
|
|
{warning}
|
|
</Text>
|
|
</View>
|
|
)}
|
|
</View>
|
|
);
|
|
}
|