|
1 | | -import React from 'react'; |
2 | | -import { View, Text, StyleSheet, TouchableOpacity, FlatList, Image } from 'react-native'; |
3 | | -/* |
4 | | -import Icon from 'react-native-vector-icons/MaterialCommunityIcons'; |
5 | | -
|
6 | | -const notifications = [ |
7 | | - { id: '1', title: "Hey, it's time for lunch", time: 'About 1 minute ago', icon: require('./assets/lunch.png') }, |
8 | | - { id: '2', title: "Don't miss your lowerbody workout", time: 'About 3 hours ago', icon: require('./assets/workout.png') }, |
9 | | - { id: '3', title: "Hey, let's add some meals for your b..", time: 'About 3 hours ago', icon: require('./assets/meals.png') }, |
10 | | - { id: '4', title: 'Congratulations, You have finished A..', time: '29 May', icon: require('./assets/congrats.png') }, |
11 | | - { id: '5', title: "Hey, it's time for lunch", time: '8 April', icon: require('./assets/lunch.png') }, |
12 | | - { id: '6', title: 'Ups, You have missed your Lowerbo..', time: '3 April', icon: require('./assets/workout.png') }, |
13 | | -]; |
14 | | -*/ |
15 | | - |
16 | | -export default function NotificationScreen({ navigation }) { |
17 | | - const renderItem = ({ item }) => ( |
| 1 | +// app/screens/NotificationScreen.tsx |
| 2 | + |
| 3 | +import React, { useState, useEffect } from "react"; |
| 4 | +import { |
| 5 | + SafeAreaView, |
| 6 | + View, |
| 7 | + Text, |
| 8 | + StyleSheet, |
| 9 | + FlatList, |
| 10 | + Dimensions, |
| 11 | + ActivityIndicator, |
| 12 | +} from "react-native"; |
| 13 | + |
| 14 | +// Define the shape of each quote, matching QuoteOut from the backend |
| 15 | +type QuoteItem = { |
| 16 | + date: string; // "YYYY-MM-DD" |
| 17 | + text: string; |
| 18 | +}; |
| 19 | + |
| 20 | +export default function NotificationScreen() { |
| 21 | + const [notifications, setNotifications] = useState<QuoteItem[]>([]); |
| 22 | + const [loading, setLoading] = useState(true); |
| 23 | + |
| 24 | + useEffect(() => { |
| 25 | + // Fetch the last 7 days of quotes from the backend |
| 26 | + // Replace localhost with your actual host or LAN IP if testing on device |
| 27 | + fetch("http://localhost:8000/api/v1/notifications/quotes") |
| 28 | + .then((res) => res.json()) |
| 29 | + .then((data: QuoteItem[]) => { |
| 30 | + // data is an array like [{ date: "2025-06-05", text: "..." }, …] |
| 31 | + setNotifications(data); |
| 32 | + }) |
| 33 | + .catch((err) => { |
| 34 | + console.error("Error fetching quotes:", err); |
| 35 | + }) |
| 36 | + .finally(() => { |
| 37 | + setLoading(false); |
| 38 | + }); |
| 39 | + }, []); |
| 40 | + |
| 41 | + const renderItem = ({ item }: { item: QuoteItem }) => ( |
18 | 42 | <View style={styles.item}> |
19 | | - <Image source={item.icon} style={styles.itemIcon} /> |
20 | 43 | <View style={styles.itemText}> |
21 | | - <Text style={styles.title} numberOfLines={1}>{item.title}</Text> |
22 | | - <Text style={styles.time}>{item.time}</Text> |
| 44 | + <Text style={styles.title} numberOfLines={2}> |
| 45 | + {item.text} |
| 46 | + </Text> |
| 47 | + <Text style={styles.time}>{item.date}</Text> |
23 | 48 | </View> |
24 | | - <TouchableOpacity style={styles.itemMenu}> |
25 | | - <Icon name="dots-vertical" size={20} /> |
26 | | - </TouchableOpacity> |
27 | 49 | </View> |
28 | 50 | ); |
| 51 | + |
| 52 | + if (loading) { |
| 53 | + return ( |
| 54 | + <SafeAreaView style={styles.container}> |
| 55 | + <ActivityIndicator size="large" color="#333" /> |
| 56 | + </SafeAreaView> |
| 57 | + ); |
| 58 | + } |
| 59 | + |
29 | 60 | return ( |
30 | | - <View style={styles.container}> |
| 61 | + <SafeAreaView style={styles.container}> |
31 | 62 | <View style={styles.header}> |
32 | | - <TouchableOpacity onPress={() => navigation.goBack()}> |
33 | | - <Icon name="arrow-left" size={24} /> |
34 | | - </TouchableOpacity> |
35 | | - <Text style={styles.headerTitle}>Notification</Text> |
36 | | - <TouchableOpacity> |
37 | | - <Icon name="dots-horizontal" size={24} /> |
38 | | - </TouchableOpacity> |
| 63 | + <Text style={styles.headerTitle}>Daily Quotes</Text> |
39 | 64 | </View> |
40 | 65 | <FlatList |
41 | 66 | data={notifications} |
42 | | - keyExtractor={item => item.id} |
| 67 | + keyExtractor={(item) => item.date} |
43 | 68 | renderItem={renderItem} |
44 | 69 | ItemSeparatorComponent={() => <View style={styles.separator} />} |
| 70 | + contentContainerStyle={styles.listContent} |
45 | 71 | /> |
46 | | - </View> |
| 72 | + </SafeAreaView> |
47 | 73 | ); |
48 | 74 | } |
49 | 75 |
|
| 76 | +const { width, height } = Dimensions.get("window"); |
| 77 | + |
50 | 78 | const styles = StyleSheet.create({ |
51 | | - container: { flex: 1, backgroundColor: '#fff' }, |
52 | | - header: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', padding: 16 }, |
53 | | - headerTitle: { fontSize: 18, fontWeight: 'bold' }, |
54 | | - item: { flexDirection: 'row', alignItems: 'center', padding: 16 }, |
55 | | - itemIcon: { width: 40, height: 40, borderRadius: 20 }, |
56 | | - itemText: { flex: 1, marginLeft: 12 }, |
57 | | - title: { fontSize: 16 }, |
58 | | - time: { fontSize: 12, color: '#888' }, |
59 | | - itemMenu: { padding: 8 }, |
60 | | - separator: { height: 1, backgroundColor: '#eee', marginLeft: 68 }, |
| 79 | + container: { |
| 80 | + flex: 1, |
| 81 | + width, |
| 82 | + height, |
| 83 | + backgroundColor: "#ffffff", |
| 84 | + alignItems: "center", |
| 85 | + justifyContent: "center", |
| 86 | + }, |
| 87 | + header: { |
| 88 | + padding: 16, |
| 89 | + borderBottomWidth: 1, |
| 90 | + borderBottomColor: "#ddd", |
| 91 | + backgroundColor: "#fafafa", |
| 92 | + alignItems: "center", |
| 93 | + width: "100%", |
| 94 | + }, |
| 95 | + headerTitle: { |
| 96 | + fontSize: 20, |
| 97 | + fontWeight: "bold", |
| 98 | + }, |
| 99 | + listContent: { |
| 100 | + paddingVertical: 8, |
| 101 | + width: "100%", |
| 102 | + }, |
| 103 | + item: { |
| 104 | + flexDirection: "row", |
| 105 | + alignItems: "center", |
| 106 | + paddingHorizontal: 16, |
| 107 | + paddingVertical: 12, |
| 108 | + backgroundColor: "#fff", |
| 109 | + }, |
| 110 | + itemText: { |
| 111 | + flex: 1, |
| 112 | + }, |
| 113 | + title: { |
| 114 | + fontSize: 16, |
| 115 | + color: "#333", |
| 116 | + }, |
| 117 | + time: { |
| 118 | + fontSize: 12, |
| 119 | + color: "#888", |
| 120 | + marginTop: 4, |
| 121 | + }, |
| 122 | + separator: { |
| 123 | + height: 1, |
| 124 | + backgroundColor: "#eee", |
| 125 | + marginLeft: 16, |
| 126 | + width: "100%", |
| 127 | + }, |
61 | 128 | }); |
0 commit comments