mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-04 18:52:56 +00:00
hot fix #1
This commit is contained in:
@@ -0,0 +1,308 @@
|
||||
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,
|
||||
};
|
||||
Reference in New Issue
Block a user