Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
309 changes: 9 additions & 300 deletions Frontend/src/Screens/HomeScreen.jsx
Original file line number Diff line number Diff line change
@@ -1,304 +1,13 @@
import React, {useState, useEffect, useRef} from 'react';
import {
SafeAreaView,
ScrollView,
StatusBar,
StyleSheet,
Text,
TouchableOpacity,
View,
Image,
RefreshControl,
} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
import {BASE_URL} from '@env';
import {useDrawer} from '../context/DrawerContext';
import {babySizes} from '../data/babySizes';

export default function HomeScreen({navigation}) {
const [dueDate, setDueDate] = useState('');
const [currentWeek, setCurrentWeek] = useState(1);
const [refreshing, setRefreshing] = useState(false);
const [allAppointments, setAllAppointments] = useState([]);
const [allTasks, setAllTasks] = useState([]);
const [currentBabySize, setCurrentBabySize] = useState('');
const weekScrollRef = useRef(null);
const {openDrawer} = useDrawer();

useEffect(() => {
fetchData();
}, []);

const fetchData = async () => {
try {
const profileRes = await fetch(`${BASE_URL}/get_profile`);
const profileData = await profileRes.json();
const fetchedDueDate = profileData?.due_date;

if (fetchedDueDate) {
setDueDate(fetchedDueDate);
console.log(' Due Date:', fetchedDueDate); // Debugging line

const calculatedWeek = calculateCurrentWeek(fetchedDueDate);
setCurrentWeek(calculatedWeek);
setCurrentBabySize(babySizes[calculatedWeek - 1]);
scrollToWeek(calculatedWeek);
}

const apptRes = await fetch(`${BASE_URL}/get_appointments`);
const apptData = await apptRes.json();
setAllAppointments(apptData || []);

const taskRes = await fetch(`${BASE_URL}/get_tasks`);
const taskData = await taskRes.json();
setAllTasks(taskData || []);
} catch (error) {
console.error('Error fetching data:', error);
}
};

const calculateCurrentWeek = dueDateString => {
const dueDateObj = new Date(dueDateString);
const conceptionDate = new Date(dueDateObj);
conceptionDate.setDate(conceptionDate.getDate() - 280);

const now = new Date();
const diffInMs = now - conceptionDate;
const week = Math.floor(diffInMs / (1000 * 60 * 60 * 24 * 7));
return Math.min(Math.max(week, 1), 40);
};

const scrollToWeek = week => {
setTimeout(() => {
const scrollX = (week - 1) * 50 - 160;
weekScrollRef.current?.scrollTo({x: scrollX, animated: true});
}, 300);
};

const handleRefresh = async () => {
setRefreshing(true);
await fetchData();
setRefreshing(false);
};

const handleWeekSelect = week => {
setCurrentWeek(week);
setCurrentBabySize(babySizes[week - 1]);
};

// ? Corrected Filtering Logic for Appointments (using date)
const filteredAppointments = allAppointments
.map(appt => {
const appointmentDate = new Date(appt.appointment_date);
const conceptionDate = new Date(dueDate);
conceptionDate.setDate(conceptionDate.getDate() - 280);
const diffInMs = appointmentDate - conceptionDate;
const weekNumber = Math.floor(diffInMs / (1000 * 60 * 60 * 24 * 7));
return {...appt, week_number: weekNumber};
})
.filter(appt => appt.week_number > currentWeek)
.sort((a, b) => a.week_number - b.week_number)
.slice(0, 2);

const filteredTasks = allTasks
.filter(task => parseInt(task.starting_week) >= currentWeek)
.sort((a, b) => parseInt(a.starting_week) - parseInt(b.starting_week))
.slice(0, 3);
import React from 'react';
import { View, Text } from 'react-native';
import { useHomeDashboard } from '../hooks/useHomeDashboard';

export default function HomeScreen() {
const { week, dueDate } = useHomeDashboard();
return (
<SafeAreaView style={styles.container}>
<StatusBar barStyle="dark-content" backgroundColor="#FFF5F8" />

<ScrollView
contentContainerStyle={styles.scrollContent}
refreshControl={
<RefreshControl refreshing={refreshing} onRefresh={handleRefresh} />
}>
{/* Header */}
<View style={styles.header}>
<TouchableOpacity onPress={openDrawer}>
<Icon name="menu" size={24} color="#000" />
</TouchableOpacity>
<Text style={styles.appName}>BabyNest</Text>
<TouchableOpacity onPress={() => navigation.navigate('Profile')}>
<Image
source={require('../assets/Avatar.jpeg')}
style={styles.profileImage}
/>
</TouchableOpacity>
</View>

{/* Baby Info */}
<View style={styles.babyInfoContainer}>
<Image
source={require('../assets/Baby.jpeg')}
style={styles.babyImage}
/>
<View style={styles.babyInfo}>
<Text style={styles.weekText}>Week {currentWeek}</Text>
<Text style={styles.babySize}>
{currentWeek >= 4 && 'Size of '}
{currentBabySize}
</Text>
<Text style={styles.dueDate}>
Due:{' '}
{dueDate
? new Date(dueDate).toLocaleDateString('en-GB', {
day: 'numeric',
month: 'long',
year: 'numeric',
})
: 'Not available'}
</Text>
</View>
</View>

{/* Timeline */}
<View style={styles.timelineContainer}>
<Text style={styles.sectionTitle}>Pregnancy Timeline</Text>
<ScrollView
horizontal
ref={weekScrollRef}
showsHorizontalScrollIndicator={false}
contentContainerStyle={styles.timelineScroll}>
{Array.from({length: 40}, (_, i) => i + 1).map(week => (
<TouchableOpacity
key={week}
style={[
styles.weekBubble,
currentWeek === week && styles.activeWeekBubble,
]}
onPress={() => handleWeekSelect(week)}>
<Text
style={[
styles.weekNumber,
currentWeek === week && styles.activeWeekNumber,
]}>
{week}
</Text>
</TouchableOpacity>
))}
</ScrollView>
</View>

{/* Appointments */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>Upcoming Appointments</Text>
{filteredAppointments.map((appt, idx) => (
<View key={idx} style={styles.card}>
<Icon name="calendar" size={20} color="rgb(218,79,122)" />
<View style={styles.cardContent}>
<Text style={styles.cardTitle}>{appt.title}</Text>
<Text>
{appt.appointment_date} at {appt.appointment_time}
</Text>
<Text>{appt.appointment_location}</Text>
</View>
</View>
))}
</View>

{/* Tasks */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>This Week's Tasks</Text>
{filteredTasks.map((task, idx) => (
<View key={idx} style={styles.card}>
<Icon
name="checkmark-circle-outline"
size={20}
color="rgb(218,79,122)"
/>
<View style={styles.cardContent}>
<Text style={styles.cardTitle}>{task.title}</Text>
<Text>
{task.starting_week === task.ending_week
? `Week ${task.starting_week}`
: `Weeks ${task.starting_week}-${task.ending_week}`}
</Text>
</View>
</View>
))}
</View>

{/* Floating Button */}
<TouchableOpacity style={styles.floatingButton}>
<MaterialIcons name="smart-toy" size={24} color="#fff" />
</TouchableOpacity>
</ScrollView>
</SafeAreaView>
<View>
<Text>Week {week}</Text>
<Text>Due: {dueDate}</Text>
</View>
Comment on lines +5 to +11
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Missing loading and error state handling.

The hook likely performs async data fetching, but the component doesn't handle loading or error states. Users will see empty/undefined values during fetch, which degrades UX.

Additionally, per the AI summary, useHomeDashboard returns { week, dueDate, appointments, tasks }, but only week and dueDate are destructured. If this is intentional (phased rollout), consider adding a comment; otherwise, the unused data suggests incomplete migration.

Suggested improvement
 export default function HomeScreen() {
-  const { week, dueDate } = useHomeDashboard();
+  const { week, dueDate, appointments, tasks, loading, error } = useHomeDashboard();
+
+  if (loading) {
+    return (
+      <View>
+        <Text>Loading...</Text>
+      </View>
+    );
+  }
+
+  if (error) {
+    return (
+      <View>
+        <Text>Error loading dashboard</Text>
+      </View>
+    );
+  }
+
   return (
     <View>
       <Text>Week {week}</Text>
       <Text>Due: {dueDate}</Text>
     </View>
   );
 }
πŸ€– Prompt for AI Agents
In @Frontend/src/Screens/HomeScreen.jsx around lines 5 - 11, HomeScreen
currently only destructures week and dueDate from useHomeDashboard and renders
them without handling loading or error states; update HomeScreen to destructure
loading and error flags (e.g., isLoading, error) from useHomeDashboard and
render a loading indicator (or placeholder) while isLoading is true and an error
message/UI when error is present, and either destructure and render appointments
and tasks or add a clear comment in HomeScreen explaining why appointments/tasks
are intentionally omitted; refer to the useHomeDashboard hook name and the
HomeScreen component to locate where to add these checks and the conditional
rendering.

);
}

const styles = StyleSheet.create({
container: {flex: 1, backgroundColor: '#FFF5F8'},
scrollContent: {paddingBottom: 100},
header: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
padding: 20,
},
appName: {
fontSize: 24,
fontWeight: 'bold',
color: 'rgb(218,79,122)',
},
profileImage: {width: 40, height: 40, borderRadius: 20},
babyInfoContainer: {
flexDirection: 'row',
backgroundColor: '#fff',
borderRadius: 20,
margin: 20,
padding: 20,
elevation: 3,
},
babyImage: {width: 100, height: 100, borderRadius: 50},
babyInfo: {marginLeft: 20, justifyContent: 'center', flex: 1},
weekText: {fontSize: 22, fontWeight: 'bold'},
babySize: {fontSize: 14, color: '#555', marginTop: 4},
dueDate: {fontSize: 14, color: 'rgb(218,79,122)', marginTop: 4},
timelineContainer: {paddingHorizontal: 20, marginTop: 10},
timelineScroll: {paddingVertical: 10},
weekBubble: {
width: 40,
height: 40,
borderRadius: 20,
backgroundColor: '#FFEEF2',
justifyContent: 'center',
alignItems: 'center',
marginRight: 10,
},
activeWeekBubble: {backgroundColor: 'rgb(218,79,122)'},
weekNumber: {fontWeight: '600', color: 'rgb(218,79,122)'},
activeWeekNumber: {color: '#fff'},
section: {paddingHorizontal: 20, marginTop: 30},
sectionTitle: {
fontSize: 18,
fontWeight: 'bold',
color: '#333',
marginBottom: 10,
},
card: {
flexDirection: 'row',
backgroundColor: '#fff',
borderRadius: 12,
padding: 15,
marginBottom: 10,
elevation: 2,
},
cardContent: {marginLeft: 12},
cardTitle: {fontWeight: 'bold', fontSize: 16},
floatingButton: {
position: 'absolute',
bottom: 30,
right: 30,
width: 60,
height: 60,
borderRadius: 30,
backgroundColor: 'rgb(218,79,122)',
justifyContent: 'center',
alignItems: 'center',
elevation: 8,
},
});
2 changes: 1 addition & 1 deletion Frontend/src/Screens/SOSAlertScreen.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export default SOSAlertScreen = ({ navigation }) => {
const handleTap = () => {
if (tapCount >= 3) {
navigation.navigate("EmergencyCalling");
} else {
} else {
setTapCount(tapCount + 1);
}
};
Expand Down
Loading