feat: 初始提交(仅核心代码,已排除大文件)
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
import React from 'react';
|
||||
import { View, Text, StyleSheet, TouchableOpacity } from 'react-native';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import { theme } from '../theme';
|
||||
import { Event } from '../types';
|
||||
import { safeParseDate } from '../utils/recurrence';
|
||||
|
||||
interface EventCardProps {
|
||||
event: Event;
|
||||
onEdit: (event: Event) => void;
|
||||
onToggleComplete: (event: Event) => void;
|
||||
onDelete: (event: Event) => void;
|
||||
}
|
||||
|
||||
export default function EventCard({
|
||||
event,
|
||||
onEdit,
|
||||
onToggleComplete,
|
||||
onDelete,
|
||||
}: EventCardProps) {
|
||||
const formatTime = (dateString: string) => {
|
||||
const date = safeParseDate(dateString);
|
||||
return date.toLocaleTimeString('zh-CN', {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<TouchableOpacity
|
||||
style={[styles.container, event.completed && styles.completedContainer]}
|
||||
onPress={() => onEdit(event)}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
<TouchableOpacity
|
||||
style={styles.checkbox}
|
||||
onPress={() => onToggleComplete(event)}
|
||||
>
|
||||
{event.completed ? (
|
||||
<Ionicons name="checkmark-circle" size={28} color={theme.colors.primary} />
|
||||
) : (
|
||||
<View style={styles.checkboxEmpty} />
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
|
||||
<View style={styles.content}>
|
||||
<Text
|
||||
style={[
|
||||
styles.title,
|
||||
event.completed && styles.completedText,
|
||||
]}
|
||||
numberOfLines={2}
|
||||
>
|
||||
{event.title}
|
||||
</Text>
|
||||
{event.content ? (
|
||||
<Text
|
||||
style={[
|
||||
styles.contentText,
|
||||
event.completed && styles.completedText,
|
||||
]}
|
||||
numberOfLines={2}
|
||||
>
|
||||
{event.content}
|
||||
</Text>
|
||||
) : null}
|
||||
<View style={styles.timeContainer}>
|
||||
<Ionicons
|
||||
name="time-outline"
|
||||
size={16}
|
||||
color={theme.colors.textSecondary}
|
||||
/>
|
||||
<Text style={styles.timeText}>{formatTime(event.start)}</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<TouchableOpacity
|
||||
style={styles.deleteButton}
|
||||
onPress={() => onDelete(event)}
|
||||
>
|
||||
<Ionicons name="trash-outline" size={20} color={theme.colors.error} />
|
||||
</TouchableOpacity>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flexDirection: 'row',
|
||||
backgroundColor: theme.colors.surface,
|
||||
borderRadius: theme.borderRadius.lg,
|
||||
padding: theme.spacing.md,
|
||||
marginBottom: theme.spacing.sm,
|
||||
alignItems: 'center',
|
||||
borderWidth: 1,
|
||||
borderColor: theme.colors.surfaceVariant,
|
||||
},
|
||||
completedContainer: {
|
||||
opacity: 0.6,
|
||||
},
|
||||
checkbox: {
|
||||
marginRight: theme.spacing.sm,
|
||||
},
|
||||
checkboxEmpty: {
|
||||
width: 28,
|
||||
height: 28,
|
||||
borderRadius: 14,
|
||||
borderWidth: 2,
|
||||
borderColor: theme.colors.textSecondary,
|
||||
},
|
||||
content: {
|
||||
flex: 1,
|
||||
},
|
||||
title: {
|
||||
...theme.typography.h3,
|
||||
color: theme.colors.text,
|
||||
marginBottom: theme.spacing.xs,
|
||||
},
|
||||
contentText: {
|
||||
...theme.typography.bodySmall,
|
||||
color: theme.colors.textSecondary,
|
||||
marginBottom: theme.spacing.xs,
|
||||
},
|
||||
completedText: {
|
||||
textDecorationLine: 'line-through',
|
||||
},
|
||||
timeContainer: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: theme.spacing.xs,
|
||||
},
|
||||
timeText: {
|
||||
...theme.typography.caption,
|
||||
color: theme.colors.textSecondary,
|
||||
},
|
||||
deleteButton: {
|
||||
padding: theme.spacing.sm,
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user