Works
This commit is contained in:
@@ -7,6 +7,7 @@ import { Stack } from "expo-router";
|
|||||||
import { StatusBar } from "expo-status-bar";
|
import { StatusBar } from "expo-status-bar";
|
||||||
import "react-native-reanimated";
|
import "react-native-reanimated";
|
||||||
|
|
||||||
|
import { BirthdaysProvider } from "@/context/birthdays-context";
|
||||||
import { useColorScheme } from "@/hooks/use-color-scheme";
|
import { useColorScheme } from "@/hooks/use-color-scheme";
|
||||||
|
|
||||||
export const unstable_settings = {
|
export const unstable_settings = {
|
||||||
@@ -17,6 +18,7 @@ export default function RootLayout() {
|
|||||||
const colorScheme = useColorScheme();
|
const colorScheme = useColorScheme();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<BirthdaysProvider>
|
||||||
<ThemeProvider value={colorScheme === "dark" ? DarkTheme : DefaultTheme}>
|
<ThemeProvider value={colorScheme === "dark" ? DarkTheme : DefaultTheme}>
|
||||||
<Stack>
|
<Stack>
|
||||||
<Stack.Screen name="index" options={{ headerShown: false }} />
|
<Stack.Screen name="index" options={{ headerShown: false }} />
|
||||||
@@ -24,5 +26,6 @@ export default function RootLayout() {
|
|||||||
</Stack>
|
</Stack>
|
||||||
<StatusBar style="auto" />
|
<StatusBar style="auto" />
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
|
</BirthdaysProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,33 @@
|
|||||||
import DateTimePicker from "@react-native-community/datetimepicker";
|
import DateTimePicker, {
|
||||||
|
DateTimePickerEvent,
|
||||||
|
} from "@react-native-community/datetimepicker";
|
||||||
|
import { useBirthdays } from "@/context/birthdays-context";
|
||||||
import { useRouter } from "expo-router";
|
import { useRouter } from "expo-router";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import {
|
import {
|
||||||
Button,
|
Alert,
|
||||||
KeyboardAvoidingView,
|
KeyboardAvoidingView,
|
||||||
Platform,
|
Platform,
|
||||||
ScrollView,
|
ScrollView,
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput,
|
||||||
|
TouchableOpacity,
|
||||||
View,
|
View,
|
||||||
} from "react-native";
|
} from "react-native";
|
||||||
import { SafeAreaView } from "react-native-safe-area-context";
|
import { SafeAreaView } from "react-native-safe-area-context";
|
||||||
|
|
||||||
export default function SimpleForm() {
|
export default function SimpleForm() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const { addBirthday } = useBirthdays();
|
||||||
const [name, setName] = useState("");
|
const [name, setName] = useState("");
|
||||||
const [date, setDate] = useState(new Date());
|
const [date, setDate] = useState(new Date());
|
||||||
const [showPicker, setShowPicker] = useState(false);
|
const [showPicker, setShowPicker] = useState(false);
|
||||||
|
|
||||||
const onChangeDate = (event, selectedDate) => {
|
const onChangeDate = (
|
||||||
|
event: DateTimePickerEvent,
|
||||||
|
selectedDate?: Date
|
||||||
|
) => {
|
||||||
setShowPicker(Platform.OS === "ios");
|
setShowPicker(Platform.OS === "ios");
|
||||||
if (selectedDate) {
|
if (selectedDate) {
|
||||||
setDate(selectedDate);
|
setDate(selectedDate);
|
||||||
@@ -27,8 +35,18 @@ export default function SimpleForm() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmit = () => {
|
const handleSubmit = () => {
|
||||||
alert(`Name: ${name}\nDate: ${date.toDateString()}`);
|
if (!name.trim()) {
|
||||||
router.push("/");
|
Alert.alert("Missing name", "Enter a name before saving.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
addBirthday({
|
||||||
|
name,
|
||||||
|
date: formatBirthdayDate(date),
|
||||||
|
});
|
||||||
|
setName("");
|
||||||
|
setDate(new Date());
|
||||||
|
router.back();
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -37,6 +55,8 @@ export default function SimpleForm() {
|
|||||||
style={styles.keyboardContainer}
|
style={styles.keyboardContainer}
|
||||||
behavior={Platform.OS === "ios" ? "padding" : undefined}
|
behavior={Platform.OS === "ios" ? "padding" : undefined}
|
||||||
>
|
>
|
||||||
|
<View style={styles.content}>
|
||||||
|
<Text style={styles.title}>Add Birthday</Text>
|
||||||
<ScrollView
|
<ScrollView
|
||||||
contentContainerStyle={styles.scrollContent}
|
contentContainerStyle={styles.scrollContent}
|
||||||
keyboardShouldPersistTaps="handled"
|
keyboardShouldPersistTaps="handled"
|
||||||
@@ -45,15 +65,24 @@ export default function SimpleForm() {
|
|||||||
<Text style={styles.label}>Name:</Text>
|
<Text style={styles.label}>Name:</Text>
|
||||||
<TextInput
|
<TextInput
|
||||||
style={styles.input}
|
style={styles.input}
|
||||||
placeholder="Enter your name"
|
placeholder="Enter name of the person"
|
||||||
value={name}
|
value={name}
|
||||||
onChangeText={setName}
|
onChangeText={setName}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Text style={styles.label}>Date:</Text>
|
<Text style={styles.label}>Date:</Text>
|
||||||
<Button title="Select Date" onPress={() => setShowPicker(true)} />
|
<TouchableOpacity
|
||||||
|
onPress={() => {
|
||||||
|
setShowPicker(true);
|
||||||
|
}}
|
||||||
|
style={[{ backgroundColor: "#00adaa" }, styles.button]}
|
||||||
|
>
|
||||||
|
<Text style={styles.buttonText}>Select Date</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
<Text style={styles.dateText}>{date.toDateString()}</Text>
|
<Text style={styles.dateText}>
|
||||||
|
{"Selected date: " + date.toDateString()}
|
||||||
|
</Text>
|
||||||
|
|
||||||
{showPicker && (
|
{showPicker && (
|
||||||
<DateTimePicker
|
<DateTimePicker
|
||||||
@@ -64,9 +93,15 @@ export default function SimpleForm() {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Button title="Submit" onPress={handleSubmit} />
|
<TouchableOpacity
|
||||||
|
onPress={handleSubmit}
|
||||||
|
style={[{ backgroundColor: "#00984c" }, styles.button]}
|
||||||
|
>
|
||||||
|
<Text style={styles.buttonText}>Save</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
</View>
|
||||||
</KeyboardAvoidingView>
|
</KeyboardAvoidingView>
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
);
|
);
|
||||||
@@ -76,30 +111,63 @@ const styles = StyleSheet.create({
|
|||||||
safeArea: {
|
safeArea: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
backgroundColor: "#fff",
|
backgroundColor: "#fff",
|
||||||
|
justifyContent: "center",
|
||||||
|
marginBottom: 0,
|
||||||
},
|
},
|
||||||
keyboardContainer: {
|
keyboardContainer: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
},
|
},
|
||||||
|
content: {
|
||||||
|
flex: 1,
|
||||||
|
paddingHorizontal: 16,
|
||||||
|
paddingTop: 12,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: "bold",
|
||||||
|
paddingHorizontal: 5,
|
||||||
|
paddingBottom: 10,
|
||||||
|
},
|
||||||
scrollContent: {
|
scrollContent: {
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
justifyContent: "center",
|
paddingHorizontal: 20,
|
||||||
padding: 20,
|
paddingBottom: 20,
|
||||||
},
|
},
|
||||||
formCard: {
|
formCard: {
|
||||||
gap: 12,
|
gap: 12,
|
||||||
},
|
},
|
||||||
label: {
|
label: {
|
||||||
|
paddingTop: 20,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
},
|
},
|
||||||
input: {
|
input: {
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
borderColor: "#ccc",
|
borderColor: "#ccc",
|
||||||
padding: 10,
|
padding: 10,
|
||||||
marginBottom: 15,
|
|
||||||
borderRadius: 5,
|
borderRadius: 5,
|
||||||
},
|
},
|
||||||
dateText: {
|
dateText: {
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
marginBottom: 8,
|
marginBottom: 8,
|
||||||
},
|
},
|
||||||
|
button: {
|
||||||
|
borderRadius: 10,
|
||||||
|
paddingVertical: 10,
|
||||||
|
paddingHorizontal: 12,
|
||||||
|
elevation: 8
|
||||||
|
},
|
||||||
|
buttonText: {
|
||||||
|
fontSize: 18,
|
||||||
|
color: "#fff",
|
||||||
|
fontWeight: "bold",
|
||||||
|
alignSelf: "center"
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function formatBirthdayDate(date: Date) {
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = `${date.getMonth() + 1}`.padStart(2, "0");
|
||||||
|
const day = `${date.getDate()}`.padStart(2, "0");
|
||||||
|
|
||||||
|
return `${year}-${month}-${day}`;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,12 +1,25 @@
|
|||||||
import { StyleSheet, View } from "react-native";
|
import { StyleSheet, Text, View, TouchableOpacity } from "react-native";
|
||||||
import { SafeAreaView } from "react-native-safe-area-context";
|
import { SafeAreaView } from "react-native-safe-area-context";
|
||||||
|
|
||||||
import { BirthdayList } from "@/components/birthdate-list";
|
import { BirthdayList } from "@/components/birthdate-list";
|
||||||
|
import { useRouter } from "expo-router";
|
||||||
|
|
||||||
export default function HomeScreen() {
|
export default function HomeScreen() {
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SafeAreaView style={styles.screen} edges={["top", "bottom"]}>
|
<SafeAreaView style={styles.screen} edges={["top", "bottom"]}>
|
||||||
<View style={styles.content}>
|
<View style={styles.content}>
|
||||||
|
<View style={styles.actionsContainer}>
|
||||||
|
<Text style={styles.title}>Upcoming Birthdays</Text>
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={() => router.push("/add")}
|
||||||
|
style={styles.addButton}
|
||||||
|
>
|
||||||
|
<Text style={styles.addButtonText}>+</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
<BirthdayList />
|
<BirthdayList />
|
||||||
</View>
|
</View>
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
@@ -23,4 +36,30 @@ const styles = StyleSheet.create({
|
|||||||
paddingHorizontal: 16,
|
paddingHorizontal: 16,
|
||||||
paddingTop: 12,
|
paddingTop: 12,
|
||||||
},
|
},
|
||||||
|
title: {
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: "bold",
|
||||||
|
paddingHorizontal: 5,
|
||||||
|
paddingBottom: 10,
|
||||||
|
},
|
||||||
|
addButton: {
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
borderRadius: 20,
|
||||||
|
backgroundColor: "#007AFF",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
addButtonText: {
|
||||||
|
fontSize: 24,
|
||||||
|
color: "white",
|
||||||
|
fontWeight: "bold",
|
||||||
|
},
|
||||||
|
actionsContainer: {
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
gap: 12,
|
||||||
|
paddingHorizontal: 5,
|
||||||
|
paddingBottom: 10,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ const styles = StyleSheet.create({
|
|||||||
padding: 15,
|
padding: 15,
|
||||||
borderRadius: 8,
|
borderRadius: 8,
|
||||||
backgroundColor: "#f0f0f0",
|
backgroundColor: "#f0f0f0",
|
||||||
boxShadow: "0 1px 4px rgba(0,0,0,0.3)",
|
elevation: 2,
|
||||||
marginBottom: 10,
|
marginBottom: 10,
|
||||||
},
|
},
|
||||||
name: {
|
name: {
|
||||||
|
|||||||
@@ -1,60 +1,23 @@
|
|||||||
// birthdate-list.tsx
|
|
||||||
import { useRouter } from "expo-router";
|
|
||||||
import {
|
import {
|
||||||
SectionList,
|
SectionList,
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
Text,
|
Text,
|
||||||
TouchableOpacity,
|
|
||||||
View,
|
View,
|
||||||
} from "react-native";
|
} from "react-native";
|
||||||
|
import { BirthdayEntry, useBirthdays } from "@/context/birthdays-context";
|
||||||
import { BirthdayItem } from "./birthdate-item";
|
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 {
|
interface SectionData {
|
||||||
title: string;
|
title: string;
|
||||||
data: BirthdayItemData[];
|
data: BirthdayEntry[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function BirthdayList() {
|
export function BirthdayList() {
|
||||||
const router = useRouter();
|
const { birthdays } = useBirthdays();
|
||||||
const groupedData = groupBirthdaysByDate(DATA);
|
const groupedData = groupBirthdaysByDate(birthdays);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<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
|
<SectionList
|
||||||
sections={groupedData}
|
sections={groupedData}
|
||||||
keyExtractor={(item) => item.id}
|
keyExtractor={(item) => item.id}
|
||||||
@@ -64,9 +27,17 @@ export function BirthdayList() {
|
|||||||
style={styles.list}
|
style={styles.list}
|
||||||
contentContainerStyle={styles.listContent}
|
contentContainerStyle={styles.listContent}
|
||||||
showsVerticalScrollIndicator={false}
|
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 } }) => (
|
renderSectionHeader={({ section: { title } }) => (
|
||||||
<View style={styles.headerContainer}>
|
<View style={styles.headerContainer}>
|
||||||
<Text style={styles.sectionHeader}>{title}</Text>
|
<Text style={styles.sectionHeader}>{formatDisplayDate(title)}</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
@@ -75,10 +46,10 @@ export function BirthdayList() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to group and sort
|
// Helper function to group and sort
|
||||||
function groupBirthdaysByDate(data: BirthdayItemData[]): SectionData[] {
|
function groupBirthdaysByDate(data: BirthdayEntry[]): SectionData[] {
|
||||||
// Sort by date
|
// Sort by date
|
||||||
const sorted = [...data].sort((a, b) => {
|
const sorted = [...data].sort((a, b) => {
|
||||||
return new Date(a.date).getTime() - new Date(b.date).getTime();
|
return parseBirthdayDate(a.date).getTime() - parseBirthdayDate(b.date).getTime();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Group by date
|
// Group by date
|
||||||
@@ -97,37 +68,28 @@ function groupBirthdaysByDate(data: BirthdayItemData[]): SectionData[] {
|
|||||||
return grouped;
|
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({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
},
|
},
|
||||||
titleContainer: {
|
|
||||||
flexDirection: "row",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
alignItems: "center",
|
|
||||||
gap: 12,
|
|
||||||
paddingHorizontal: 5,
|
|
||||||
paddingVertical: 10,
|
|
||||||
},
|
|
||||||
list: {
|
list: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
},
|
},
|
||||||
listContent: {
|
listContent: {
|
||||||
paddingBottom: 20,
|
paddingBottom: 20,
|
||||||
},
|
},
|
||||||
addButton: {
|
|
||||||
width: 40,
|
|
||||||
height: 40,
|
|
||||||
borderRadius: 20,
|
|
||||||
backgroundColor: "#007AFF",
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
},
|
|
||||||
addButtonText: {
|
|
||||||
fontSize: 24,
|
|
||||||
color: "white",
|
|
||||||
fontWeight: "bold",
|
|
||||||
},
|
|
||||||
headerContainer: {
|
headerContainer: {
|
||||||
paddingVertical: 10,
|
paddingVertical: 10,
|
||||||
paddingHorizontal: 5,
|
paddingHorizontal: 5,
|
||||||
@@ -136,4 +98,17 @@ const styles = StyleSheet.create({
|
|||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
fontWeight: "bold",
|
fontWeight: "bold",
|
||||||
},
|
},
|
||||||
|
emptyState: {
|
||||||
|
paddingHorizontal: 5,
|
||||||
|
paddingTop: 24,
|
||||||
|
gap: 6,
|
||||||
|
},
|
||||||
|
emptyTitle: {
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: "bold",
|
||||||
|
},
|
||||||
|
emptyText: {
|
||||||
|
color: "#666",
|
||||||
|
fontSize: 15,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
70
apk/context/birthdays-context.tsx
Normal file
70
apk/context/birthdays-context.tsx
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
import {
|
||||||
|
createContext,
|
||||||
|
ReactNode,
|
||||||
|
useContext,
|
||||||
|
useMemo,
|
||||||
|
useState,
|
||||||
|
} from "react";
|
||||||
|
|
||||||
|
export interface BirthdayEntry {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
date: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AddBirthdayInput {
|
||||||
|
name: string;
|
||||||
|
date: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BirthdaysContextValue {
|
||||||
|
birthdays: BirthdayEntry[];
|
||||||
|
addBirthday: (input: AddBirthdayInput) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BirthdaysContext = createContext<BirthdaysContextValue | undefined>(
|
||||||
|
undefined
|
||||||
|
);
|
||||||
|
|
||||||
|
export function BirthdaysProvider({ children }: { children: ReactNode }) {
|
||||||
|
const [birthdays, setBirthdays] = useState<BirthdayEntry[]>([]);
|
||||||
|
|
||||||
|
const value = useMemo(
|
||||||
|
() => ({
|
||||||
|
birthdays,
|
||||||
|
addBirthday: ({ name, date }: AddBirthdayInput) => {
|
||||||
|
const trimmedName = name.trim();
|
||||||
|
|
||||||
|
if (!trimmedName) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setBirthdays((currentBirthdays) => [
|
||||||
|
...currentBirthdays,
|
||||||
|
{
|
||||||
|
id: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
||||||
|
name: trimmedName,
|
||||||
|
date,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
[birthdays]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BirthdaysContext.Provider value={value}>
|
||||||
|
{children}
|
||||||
|
</BirthdaysContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useBirthdays() {
|
||||||
|
const context = useContext(BirthdaysContext);
|
||||||
|
|
||||||
|
if (!context) {
|
||||||
|
throw new Error("useBirthdays must be used within a BirthdaysProvider");
|
||||||
|
}
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user