140 lines
3.5 KiB
TypeScript
140 lines
3.5 KiB
TypeScript
// birthdate-list.tsx
|
|
import { useRouter } from "expo-router";
|
|
import {
|
|
SectionList,
|
|
StyleSheet,
|
|
Text,
|
|
TouchableOpacity,
|
|
View,
|
|
} from "react-native";
|
|
import { BirthdayItem } from "./birthdate-item";
|
|
|
|
const DATA = [
|
|
{ id: "1", name: "John Doe", date: "2024-01-15" },
|
|
{ id: "2", name: "Jane Smith", date: "2024-01-15" },
|
|
{ id: "3", name: "Bob Johnson", date: "2024-02-10" },
|
|
{ id: "4", name: "Alice Brown", date: "2024-02-10" },
|
|
{ id: "5", name: "Charlie Wilson", date: "2024-01-20" },
|
|
{ id: "6", name: "Bob Johnson", date: "2024-02-10" },
|
|
{ id: "7", name: "Alice Brown", date: "2024-02-10" },
|
|
{ id: "8", name: "Charlie Wilson", date: "2024-01-20" },
|
|
{ id: "9", name: "Bob Johnson", date: "2024-02-10" },
|
|
{ id: "10", name: "Alice Brown", date: "2024-02-10" },
|
|
{ id: "11", name: "Charlie Wilson", date: "2024-01-20" },
|
|
{ id: "12", name: "Charlie Wilson", date: "2024-01-20" },
|
|
{ id: "13", name: "Charlie Wilson", date: "2024-01-20" },
|
|
{ id: "14", name: "Charlie Wilson", date: "2024-01-20" },
|
|
];
|
|
|
|
interface BirthdayItemData {
|
|
id: string;
|
|
name: string;
|
|
date: string;
|
|
}
|
|
|
|
interface SectionData {
|
|
title: string;
|
|
data: BirthdayItemData[];
|
|
}
|
|
|
|
export function BirthdayList() {
|
|
const router = useRouter();
|
|
const groupedData = groupBirthdaysByDate(DATA);
|
|
|
|
return (
|
|
<View style={styles.container}>
|
|
<View style={styles.titleContainer}>
|
|
<Text style={{ fontSize: 24, fontWeight: "bold" }}>
|
|
Upcoming Birthdays
|
|
</Text>
|
|
<TouchableOpacity
|
|
onPress={() => router.push("/add")}
|
|
style={styles.addButton}
|
|
>
|
|
<Text style={styles.addButtonText}>+</Text>
|
|
</TouchableOpacity>
|
|
</View>
|
|
|
|
<SectionList
|
|
sections={groupedData}
|
|
keyExtractor={(item) => item.id}
|
|
renderItem={({ item }) => (
|
|
<BirthdayItem name={item.name} date={item.date} />
|
|
)}
|
|
style={styles.list}
|
|
contentContainerStyle={styles.listContent}
|
|
showsVerticalScrollIndicator={false}
|
|
renderSectionHeader={({ section: { title } }) => (
|
|
<View style={styles.headerContainer}>
|
|
<Text style={styles.sectionHeader}>{title}</Text>
|
|
</View>
|
|
)}
|
|
/>
|
|
</View>
|
|
);
|
|
}
|
|
|
|
// Helper function to group and sort
|
|
function groupBirthdaysByDate(data: BirthdayItemData[]): SectionData[] {
|
|
// Sort by date
|
|
const sorted = [...data].sort((a, b) => {
|
|
return new Date(a.date).getTime() - new Date(b.date).getTime();
|
|
});
|
|
|
|
// Group by date
|
|
const grouped = sorted.reduce((acc, item) => {
|
|
const existing = acc.find((section) => section.title === item.date);
|
|
|
|
if (existing) {
|
|
existing.data.push(item);
|
|
} else {
|
|
acc.push({ title: item.date, data: [item] });
|
|
}
|
|
|
|
return acc;
|
|
}, [] as SectionData[]);
|
|
|
|
return grouped;
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
flex: 1,
|
|
},
|
|
titleContainer: {
|
|
flexDirection: "row",
|
|
justifyContent: "space-between",
|
|
alignItems: "center",
|
|
gap: 12,
|
|
paddingHorizontal: 5,
|
|
paddingVertical: 10,
|
|
},
|
|
list: {
|
|
flex: 1,
|
|
},
|
|
listContent: {
|
|
paddingBottom: 20,
|
|
},
|
|
addButton: {
|
|
width: 40,
|
|
height: 40,
|
|
borderRadius: 20,
|
|
backgroundColor: "#007AFF",
|
|
justifyContent: "center",
|
|
alignItems: "center",
|
|
},
|
|
addButtonText: {
|
|
fontSize: 24,
|
|
color: "white",
|
|
fontWeight: "bold",
|
|
},
|
|
headerContainer: {
|
|
paddingVertical: 10,
|
|
paddingHorizontal: 5,
|
|
},
|
|
sectionHeader: {
|
|
fontSize: 18,
|
|
fontWeight: "bold",
|
|
},
|
|
});
|