115 lines
2.6 KiB
TypeScript
115 lines
2.6 KiB
TypeScript
import {
|
|
SectionList,
|
|
StyleSheet,
|
|
Text,
|
|
View,
|
|
} from "react-native";
|
|
import { BirthdayEntry, useBirthdays } from "@/context/birthdays-context";
|
|
import { BirthdayItem } from "./birthdate-item";
|
|
|
|
interface SectionData {
|
|
title: string;
|
|
data: BirthdayEntry[];
|
|
}
|
|
|
|
export function BirthdayList() {
|
|
const { birthdays } = useBirthdays();
|
|
const groupedData = groupBirthdaysByDate(birthdays);
|
|
|
|
return (
|
|
<View style={styles.container}>
|
|
<SectionList
|
|
sections={groupedData}
|
|
keyExtractor={(item) => item.id}
|
|
renderItem={({ item }) => (
|
|
<BirthdayItem name={item.name} date={item.date} />
|
|
)}
|
|
style={styles.list}
|
|
contentContainerStyle={styles.listContent}
|
|
showsVerticalScrollIndicator={false}
|
|
ListEmptyComponent={
|
|
<View style={styles.emptyState}>
|
|
<Text style={styles.emptyTitle}>No birthdays yet</Text>
|
|
<Text style={styles.emptyText}>
|
|
Add one from the form and it will appear here.
|
|
</Text>
|
|
</View>
|
|
}
|
|
renderSectionHeader={({ section: { title } }) => (
|
|
<View style={styles.headerContainer}>
|
|
<Text style={styles.sectionHeader}>{formatDisplayDate(title)}</Text>
|
|
</View>
|
|
)}
|
|
/>
|
|
</View>
|
|
);
|
|
}
|
|
|
|
// Helper function to group and sort
|
|
function groupBirthdaysByDate(data: BirthdayEntry[]): SectionData[] {
|
|
// Sort by date
|
|
const sorted = [...data].sort((a, b) => {
|
|
return parseBirthdayDate(a.date).getTime() - parseBirthdayDate(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;
|
|
}
|
|
|
|
function parseBirthdayDate(date: string) {
|
|
return new Date(`${date}T00:00:00`);
|
|
}
|
|
|
|
function formatDisplayDate(date: string) {
|
|
return parseBirthdayDate(date).toLocaleDateString(undefined, {
|
|
month: "long",
|
|
day: "numeric",
|
|
year: "numeric",
|
|
});
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
flex: 1,
|
|
},
|
|
list: {
|
|
flex: 1,
|
|
},
|
|
listContent: {
|
|
paddingBottom: 20,
|
|
},
|
|
headerContainer: {
|
|
paddingVertical: 10,
|
|
paddingHorizontal: 5,
|
|
},
|
|
sectionHeader: {
|
|
fontSize: 18,
|
|
fontWeight: "bold",
|
|
},
|
|
emptyState: {
|
|
paddingHorizontal: 5,
|
|
paddingTop: 24,
|
|
gap: 6,
|
|
},
|
|
emptyTitle: {
|
|
fontSize: 18,
|
|
fontWeight: "bold",
|
|
},
|
|
emptyText: {
|
|
color: "#666",
|
|
fontSize: 15,
|
|
},
|
|
});
|