Files
digital-pilates/components/ui/InfoCard.tsx
richarjiang 7ea558847d feat(medications): 增强药品详情页面的编辑功能
- 添加剂量、剂型和服药频率的交互式选择器
- 实现提醒时间的动态编辑和添加功能
- 引入玻璃效果优化删除按钮的视觉体验
- 重构常量配置,提取药物相关常量到独立文件
- 创建可复用的InfoCard组件支持玻璃效果
2025-11-11 11:31:06 +08:00

149 lines
4.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import type { Colors } from '@/constants/Colors';
import { Ionicons } from '@expo/vector-icons';
import { GlassView, isLiquidGlassAvailable } from 'expo-glass-effect';
import React from 'react';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
export interface InfoCardProps {
label: string;
value: string;
icon: keyof typeof Ionicons.glyphMap;
colors: (typeof Colors)[keyof typeof Colors];
onPress?: () => void;
clickable?: boolean;
glassEffectStyle?: 'clear' | 'regular';
tintColor?: string;
className?: string;
}
export const InfoCard: React.FC<InfoCardProps> = ({
label,
value,
icon,
colors,
onPress,
clickable = false,
glassEffectStyle = 'clear',
}) => {
const isGlassAvailable = isLiquidGlassAvailable();
// 如果可点击且有onPress回调使用TouchableOpacity包装
if (clickable && onPress) {
return (
<TouchableOpacity
style={styles.container}
onPress={onPress}
activeOpacity={0.7}
>
{isGlassAvailable ? (
<GlassView
style={[
styles.infoCard,
]}
glassEffectStyle={glassEffectStyle}
isInteractive={true}
>
<View style={styles.infoCardArrow}>
<Ionicons name="chevron-forward" size={16} color={colors.textMuted} />
</View>
<View style={styles.infoCardIcon}>
<Ionicons name={icon} size={16} color="#4C6EF5" />
</View>
<Text style={[styles.infoCardLabel, { color: colors.textSecondary }]}>{label}</Text>
<Text style={[styles.infoCardValue, { color: colors.text }]}>{value}</Text>
</GlassView>
) : (
<View style={[styles.infoCard]}>
<View style={styles.infoCardArrow}>
<Ionicons name="chevron-forward" size={16} color={colors.textMuted} />
</View>
<View style={styles.infoCardIcon}>
<Ionicons name={icon} size={16} color="#4C6EF5" />
</View>
<Text style={[styles.infoCardLabel, { color: colors.textSecondary }]}>{label}</Text>
<Text style={[styles.infoCardValue, { color: colors.text }]}>{value}</Text>
</View>
)}
</TouchableOpacity>
);
}
// 不可点击的版本
return (
<View style={styles.container}>
{isGlassAvailable ? (
<GlassView
style={[
styles.infoCard,
{
backgroundColor: 'transparent',
borderColor: `${colors.border}80`,
}
]}
glassEffectStyle={glassEffectStyle}
>
<View style={styles.infoCardIcon}>
<Ionicons name={icon} size={16} color="#4C6EF5" />
</View>
<Text style={[styles.infoCardLabel, { color: colors.textSecondary }]}>{label}</Text>
<Text style={[styles.infoCardValue, { color: colors.text }]}>{value}</Text>
</GlassView>
) : (
<View style={[styles.infoCard, { backgroundColor: colors.surface }]}>
<View style={styles.infoCardIcon}>
<Ionicons name={icon} size={16} color="#4C6EF5" />
</View>
<Text style={[styles.infoCardLabel, { color: colors.textSecondary }]}>{label}</Text>
<Text style={[styles.infoCardValue, { color: colors.text }]}>{value}</Text>
</View>
)}
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
infoCard: {
flex: 1,
borderRadius: 20,
padding: 16,
backgroundColor: '#fff',
gap: 6,
shadowColor: '#000',
shadowOpacity: 0.04,
shadowRadius: 8,
shadowOffset: { width: 0, height: 4 },
elevation: 2,
position: 'relative',
overflow: 'hidden', // 保证玻璃边界圆角效果
},
infoCardArrow: {
position: 'absolute',
top: 12,
right: 12,
zIndex: 1,
},
infoCardIcon: {
width: 28,
height: 28,
borderRadius: 14,
backgroundColor: '#EEF1FF',
alignItems: 'center',
justifyContent: 'center',
},
infoCardLabel: {
fontSize: 13,
color: '#6B7280',
marginTop: 8,
},
infoCardValue: {
fontSize: 16,
fontWeight: '600',
color: '#1F2933',
},
});
export default InfoCard;