import React, { ReactNode, useState } from 'react';
import { View, ScrollView, ActivityIndicator, TouchableOpacity } from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import { Text } from './Text';
import { Button } from './Button';
import { useTheme } from '~/contexts/ThemeContext';
export type OptionItem = {
id: string;
label: string;
subtitle?: string;
icon?: string;
description?: string;
};
type OptionSelectorProps = {
options: OptionItem[];
selectedId: string | null;
onSelect: (option: OptionItem) => void;
loading?: boolean;
error?: string | null;
onRetry?: () => void;
disabled?: boolean;
minWidth?: number;
title?: string;
};
export function OptionSelector({
options,
selectedId,
onSelect,
loading = false,
error = null,
onRetry,
disabled = false,
minWidth = 160,
title,
}: OptionSelectorProps) {
const { theme } = useTheme();
const [showInfo, setShowInfo] = useState(false);
// Loading state
if (loading) {
return (
Lade...
);
}
// Error state
if (error || options.length === 0) {
return (
{error || 'Keine Optionen verfügbar'}
{onRetry && (
)}
);
}
// Find selected option for description
const selectedOption = options.find(opt => opt.id === selectedId);
// Check if any option has subtitle or description
const hasDetails = options.some(opt => opt.subtitle || opt.description);
// Success state - show options
return (
{/* Header with Title and Info Icon */}
{(title || hasDetails) && (
{title && (
{title}
)}
{hasDetails && (
setShowInfo(!showInfo)}
style={{
flexDirection: 'row',
alignItems: 'center',
padding: 4,
}}
>
{showInfo ? 'Info ausblenden' : 'Info'}
)}
)}
{options.map((option) => {
const isSelected = selectedId === option.id;
return (
!disabled && onSelect(option)}
disabled={disabled}
activeOpacity={0.7}
style={{
backgroundColor: isSelected
? theme.colors.primary.default
: theme.colors.surface,
borderWidth: 2,
borderColor: isSelected
? theme.colors.primary.default
: theme.colors.border,
borderRadius: 12,
padding: 16,
marginHorizontal: 4,
minWidth: minWidth,
opacity: disabled ? 0.5 : 1,
alignItems: 'center',
}}
>
{option.icon && (
{option.icon}
)}
{option.label}
{showInfo && option.subtitle && (
{option.subtitle}
)}
);
})}
{showInfo && selectedOption?.description && (
{selectedOption.description}
)}
);
}