mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-03 18:22:57 +00:00
309 lines
7.8 KiB
TypeScript
309 lines
7.8 KiB
TypeScript
import React from 'react';
|
|
import { View, Text, StyleSheet, TextInput, TouchableOpacity } from 'react-native';
|
|
import { useClubTheme } from '../../theme';
|
|
|
|
interface ModernCardProps {
|
|
children: React.ReactNode;
|
|
style?: any;
|
|
shadow?: boolean;
|
|
padding?: number;
|
|
margin?: number;
|
|
borderRadius?: number;
|
|
}
|
|
|
|
export const ModernCard: React.FC<ModernCardProps> = ({
|
|
children,
|
|
style,
|
|
shadow = true,
|
|
padding = 16,
|
|
margin = 0,
|
|
borderRadius = 16,
|
|
}) => {
|
|
const { theme } = useClubTheme();
|
|
|
|
const cardStyle = {
|
|
padding,
|
|
margin,
|
|
borderRadius,
|
|
backgroundColor: '#FFFFFF',
|
|
borderLeftWidth: 4,
|
|
borderLeftColor: theme.primary,
|
|
...(shadow && {
|
|
shadowColor: '#000',
|
|
shadowOffset: { width: 0, height: 2 },
|
|
shadowOpacity: 0.1,
|
|
shadowRadius: 8,
|
|
elevation: 4,
|
|
}),
|
|
...style,
|
|
};
|
|
|
|
return <View style={cardStyle}>{children}</View>;
|
|
};
|
|
|
|
interface ModernButtonProps {
|
|
title: string;
|
|
onPress: () => void;
|
|
variant?: 'primary' | 'secondary' | 'outline' | 'ghost';
|
|
size?: 'small' | 'medium' | 'large';
|
|
disabled?: boolean;
|
|
loading?: boolean;
|
|
style?: any;
|
|
textStyle?: any;
|
|
icon?: string;
|
|
}
|
|
|
|
export const ModernButton: React.FC<ModernButtonProps> = ({
|
|
title,
|
|
onPress,
|
|
variant = 'primary',
|
|
size = 'medium',
|
|
disabled = false,
|
|
loading = false,
|
|
style,
|
|
textStyle,
|
|
icon,
|
|
}) => {
|
|
const { theme } = useClubTheme();
|
|
|
|
const getButtonStyle = () => {
|
|
let baseStyle: any = {
|
|
alignItems: 'center' as const,
|
|
justifyContent: 'center' as const,
|
|
borderRadius: 12,
|
|
};
|
|
|
|
// Size variants
|
|
if (size === 'small') {
|
|
baseStyle = { ...baseStyle, paddingHorizontal: 12, paddingVertical: 8 };
|
|
} else if (size === 'large') {
|
|
baseStyle = { ...baseStyle, paddingHorizontal: 24, paddingVertical: 16 };
|
|
} else {
|
|
baseStyle = { ...baseStyle, paddingHorizontal: 20, paddingVertical: 12 };
|
|
}
|
|
|
|
// Variant styles
|
|
if (variant === 'primary') {
|
|
baseStyle = { ...baseStyle, backgroundColor: theme.primary };
|
|
} else if (variant === 'secondary') {
|
|
baseStyle = { ...baseStyle, backgroundColor: theme.secondary };
|
|
} else if (variant === 'outline') {
|
|
baseStyle = { ...baseStyle, backgroundColor: 'transparent', borderWidth: 2, borderColor: theme.primary };
|
|
} else {
|
|
baseStyle = { ...baseStyle, backgroundColor: 'transparent' };
|
|
}
|
|
|
|
if (disabled) {
|
|
baseStyle = { ...baseStyle, opacity: 0.5 };
|
|
}
|
|
|
|
return { ...baseStyle, ...style };
|
|
};
|
|
|
|
const getTextStyle = () => {
|
|
let baseStyle: any = {
|
|
fontWeight: '600' as const,
|
|
textAlign: 'center' as const,
|
|
};
|
|
|
|
if (size === 'small') {
|
|
baseStyle = { ...baseStyle, fontSize: 14 };
|
|
} else if (size === 'large') {
|
|
baseStyle = { ...baseStyle, fontSize: 18 };
|
|
} else {
|
|
baseStyle = { ...baseStyle, fontSize: 16 };
|
|
}
|
|
|
|
if (variant === 'outline' || variant === 'ghost') {
|
|
baseStyle = { ...baseStyle, color: theme.primary };
|
|
} else {
|
|
baseStyle = { ...baseStyle, color: '#FFFFFF' };
|
|
}
|
|
|
|
if (disabled) {
|
|
baseStyle = { ...baseStyle, opacity: 0.7 };
|
|
}
|
|
|
|
return { ...baseStyle, ...textStyle };
|
|
};
|
|
|
|
return (
|
|
<TouchableOpacity
|
|
style={getButtonStyle()}
|
|
onPress={onPress}
|
|
disabled={disabled || loading}
|
|
>
|
|
<View style={{ flexDirection: 'row', alignItems: 'center', gap: icon ? 8 : 0 }}>
|
|
{icon && <Text style={getTextStyle()}>{icon}</Text>}
|
|
<Text style={getTextStyle()}>
|
|
{loading ? 'Načítám...' : title}
|
|
</Text>
|
|
</View>
|
|
</TouchableOpacity>
|
|
);
|
|
};
|
|
|
|
interface ModernInputProps {
|
|
value: string;
|
|
onChangeText: (text: string) => void;
|
|
placeholder?: string;
|
|
label?: string;
|
|
error?: string;
|
|
icon?: string;
|
|
secureTextEntry?: boolean;
|
|
keyboardType?: 'default' | 'email-address' | 'numeric' | 'phone-pad';
|
|
autoCapitalize?: 'none' | 'sentences' | 'words' | 'characters';
|
|
style?: any;
|
|
}
|
|
|
|
export const ModernInput: React.FC<ModernInputProps> = ({
|
|
value,
|
|
onChangeText,
|
|
placeholder,
|
|
label,
|
|
error,
|
|
icon,
|
|
secureTextEntry = false,
|
|
keyboardType = 'default',
|
|
autoCapitalize = 'sentences',
|
|
style,
|
|
}) => {
|
|
const { theme } = useClubTheme();
|
|
|
|
return (
|
|
<View style={[{ marginBottom: 16 }, style]}>
|
|
{label && <Text style={{ fontSize: 14, fontWeight: '600', marginBottom: 8, color: '#374151' }}>{label}</Text>}
|
|
<View style={[
|
|
{ flexDirection: 'row', alignItems: 'center', borderWidth: 1, borderRadius: 12, paddingHorizontal: 16, paddingVertical: 12, backgroundColor: '#FFFFFF' },
|
|
error && { borderWidth: 2, borderColor: '#EF4444' },
|
|
!error && { borderColor: theme.primary + '30' }
|
|
]}>
|
|
{icon && <Text style={{ marginRight: 12, fontSize: 16 }}>{icon}</Text>}
|
|
<TextInput
|
|
style={[
|
|
{ flex: 1, fontSize: 16 },
|
|
{ color: theme.text }
|
|
]}
|
|
value={value}
|
|
onChangeText={onChangeText}
|
|
placeholder={placeholder}
|
|
placeholderTextColor="#9CA3AF"
|
|
secureTextEntry={secureTextEntry}
|
|
keyboardType={keyboardType}
|
|
autoCapitalize={autoCapitalize}
|
|
/>
|
|
</View>
|
|
{error && <Text style={{ fontSize: 12, color: '#EF4444', marginTop: 4 }}>{error}</Text>}
|
|
</View>
|
|
);
|
|
};
|
|
|
|
interface ModernBadgeProps {
|
|
text: string;
|
|
variant?: 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'outline';
|
|
size?: 'small' | 'medium' | 'large';
|
|
style?: any;
|
|
}
|
|
|
|
export const ModernBadge: React.FC<ModernBadgeProps> = ({
|
|
text,
|
|
variant = 'primary',
|
|
size = 'medium',
|
|
style,
|
|
}) => {
|
|
const { theme } = useClubTheme();
|
|
|
|
const getBadgeStyle = () => {
|
|
let baseStyle: any = {
|
|
paddingHorizontal: 8,
|
|
paddingVertical: 4,
|
|
borderRadius: 999,
|
|
alignSelf: 'flex-start' as const,
|
|
};
|
|
|
|
// Size variants
|
|
if (size === 'small') {
|
|
baseStyle = { ...baseStyle, paddingHorizontal: 6, paddingVertical: 2 };
|
|
} else if (size === 'large') {
|
|
baseStyle = { ...baseStyle, paddingHorizontal: 12, paddingVertical: 6 };
|
|
}
|
|
|
|
// Variant colors
|
|
if (variant === 'primary') {
|
|
baseStyle = { ...baseStyle, backgroundColor: theme.primary };
|
|
} else if (variant === 'secondary') {
|
|
baseStyle = { ...baseStyle, backgroundColor: theme.secondary };
|
|
} else if (variant === 'success') {
|
|
baseStyle = { ...baseStyle, backgroundColor: '#10B981' };
|
|
} else if (variant === 'warning') {
|
|
baseStyle = { ...baseStyle, backgroundColor: '#F59E0B' };
|
|
} else if (variant === 'error') {
|
|
baseStyle = { ...baseStyle, backgroundColor: '#EF4444' };
|
|
} else if (variant === 'outline') {
|
|
baseStyle = { ...baseStyle, backgroundColor: 'transparent', borderWidth: 1, borderColor: theme.primary };
|
|
}
|
|
|
|
return { ...baseStyle, ...style };
|
|
};
|
|
|
|
return (
|
|
<View style={getBadgeStyle()}>
|
|
<Text style={{ fontSize: 12, fontWeight: '600', color: variant === 'outline' ? theme.primary : '#FFFFFF' }}>{text}</Text>
|
|
</View>
|
|
);
|
|
};
|
|
|
|
const styles = StyleSheet.create({
|
|
inputContainer: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
borderWidth: 1,
|
|
borderRadius: 12,
|
|
paddingHorizontal: 16,
|
|
paddingVertical: 12,
|
|
backgroundColor: '#FFFFFF',
|
|
},
|
|
inputError: {
|
|
borderWidth: 2,
|
|
},
|
|
inputIcon: {
|
|
marginRight: 12,
|
|
fontSize: 16,
|
|
},
|
|
input: {
|
|
flex: 1,
|
|
fontSize: 16,
|
|
},
|
|
errorText: {
|
|
fontSize: 12,
|
|
color: '#EF4444',
|
|
marginTop: 4,
|
|
},
|
|
badge: {
|
|
paddingHorizontal: 8,
|
|
paddingVertical: 4,
|
|
borderRadius: 999,
|
|
alignSelf: 'flex-start',
|
|
},
|
|
badgeSmall: {
|
|
paddingHorizontal: 6,
|
|
paddingVertical: 2,
|
|
},
|
|
badgeLarge: {
|
|
paddingHorizontal: 12,
|
|
paddingVertical: 6,
|
|
},
|
|
badgeText: {
|
|
fontSize: 12,
|
|
fontWeight: '600',
|
|
color: '#FFFFFF',
|
|
},
|
|
});
|
|
|
|
export default {
|
|
ModernCard,
|
|
ModernButton,
|
|
ModernInput,
|
|
ModernBadge,
|
|
};
|