108 lines
2.3 KiB
TypeScript
108 lines
2.3 KiB
TypeScript
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
|
|
import {
|
|
Users, MapPin, Map, Calendar, BookOpen, Settings,
|
|
Inbox, FileText, Bell, Star, Heart, Search,
|
|
Package, Archive, List, Clipboard, Tag, Shield,
|
|
type LucideIcon,
|
|
} from 'lucide-react-native';
|
|
|
|
// Map of icon name strings to actual components
|
|
const ICON_MAP: Record<string, LucideIcon> = {
|
|
Users,
|
|
MapPin,
|
|
Map,
|
|
Calendar,
|
|
BookOpen,
|
|
Settings,
|
|
Inbox,
|
|
FileText,
|
|
Bell,
|
|
Star,
|
|
Heart,
|
|
Search,
|
|
Package,
|
|
Archive,
|
|
List,
|
|
Clipboard,
|
|
Tag,
|
|
Shield,
|
|
};
|
|
|
|
interface Props {
|
|
icon?: string;
|
|
title: string;
|
|
message?: string;
|
|
actionLabel?: string;
|
|
onAction?: () => void;
|
|
}
|
|
|
|
export function EmptyState({ icon, title, message, actionLabel, onAction }: Props) {
|
|
const IconComponent = icon ? ICON_MAP[icon] ?? Inbox : Inbox;
|
|
|
|
return (
|
|
<View style={styles.container} accessibilityRole="text" accessibilityLabel={title}>
|
|
<View style={styles.iconWrap}>
|
|
<IconComponent size={40} color="#9CA3AF" strokeWidth={1.5} />
|
|
</View>
|
|
<Text style={styles.title}>{title}</Text>
|
|
{message ? <Text style={styles.message}>{message}</Text> : null}
|
|
{actionLabel && onAction ? (
|
|
<TouchableOpacity
|
|
style={styles.button}
|
|
onPress={onAction}
|
|
accessibilityRole="button"
|
|
accessibilityLabel={actionLabel}
|
|
>
|
|
<Text style={styles.buttonText}>{actionLabel}</Text>
|
|
</TouchableOpacity>
|
|
) : null}
|
|
</View>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
paddingVertical: 60,
|
|
paddingHorizontal: 32,
|
|
},
|
|
iconWrap: {
|
|
width: 80,
|
|
height: 80,
|
|
borderRadius: 40,
|
|
backgroundColor: '#F3F4F6',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
marginBottom: 16,
|
|
},
|
|
title: {
|
|
fontSize: 17,
|
|
fontWeight: '600',
|
|
color: '#374151',
|
|
textAlign: 'center',
|
|
marginBottom: 6,
|
|
},
|
|
message: {
|
|
fontSize: 14,
|
|
color: '#9CA3AF',
|
|
textAlign: 'center',
|
|
lineHeight: 20,
|
|
marginBottom: 20,
|
|
},
|
|
button: {
|
|
backgroundColor: '#1A6B72',
|
|
paddingVertical: 12,
|
|
paddingHorizontal: 28,
|
|
borderRadius: 12,
|
|
minHeight: 44,
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
},
|
|
buttonText: {
|
|
color: 'white',
|
|
fontWeight: '600',
|
|
fontSize: 14,
|
|
},
|
|
});
|