import React, { useState, useEffect } from 'react';
import {
View,
Text,
StyleSheet,
ScrollView,
Switch,
TouchableOpacity,
Alert,
ActivityIndicator,
} from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import { SafeAreaView } from 'react-native-safe-area-context';
import { router } from 'expo-router';
import { AppColors, BorderRadius, FontSizes, Spacing } from '@/constants/theme';
import { PageHeader } from '@/components/PageHeader';
import { api } from '@/services/api';
import type { NotificationSettings } from '@/types';
interface NotificationSettingProps {
icon: keyof typeof Ionicons.glyphMap;
iconColor: string;
iconBgColor: string;
title: string;
description: string;
value: boolean;
onValueChange: (value: boolean) => void;
}
function NotificationSetting({
icon,
iconColor,
iconBgColor,
title,
description,
value,
onValueChange,
}: NotificationSettingProps) {
return (
{title}
{description}
);
}
// Default settings
const DEFAULT_SETTINGS: NotificationSettings = {
emergencyAlerts: true,
activityAlerts: true,
lowBattery: true,
dailySummary: false,
weeklySummary: true,
pushEnabled: true,
emailEnabled: false,
smsEnabled: false,
quietHours: false,
quietStart: '22:00',
quietEnd: '07:00',
};
export default function NotificationsScreen() {
const [isLoading, setIsLoading] = useState(true);
const [isSaving, setIsSaving] = useState(false);
// Alert types
const [emergencyAlerts, setEmergencyAlerts] = useState(DEFAULT_SETTINGS.emergencyAlerts);
const [activityAlerts, setActivityAlerts] = useState(DEFAULT_SETTINGS.activityAlerts);
const [lowBattery, setLowBattery] = useState(DEFAULT_SETTINGS.lowBattery);
const [dailySummary, setDailySummary] = useState(DEFAULT_SETTINGS.dailySummary);
const [weeklySummary, setWeeklySummary] = useState(DEFAULT_SETTINGS.weeklySummary);
// Delivery methods
const [pushEnabled, setPushEnabled] = useState(DEFAULT_SETTINGS.pushEnabled);
const [emailEnabled, setEmailEnabled] = useState(DEFAULT_SETTINGS.emailEnabled);
const [smsEnabled, setSmsEnabled] = useState(DEFAULT_SETTINGS.smsEnabled);
// Quiet hours
const [quietHours, setQuietHours] = useState(DEFAULT_SETTINGS.quietHours);
const [quietStart, setQuietStart] = useState(DEFAULT_SETTINGS.quietStart);
const [quietEnd, setQuietEnd] = useState(DEFAULT_SETTINGS.quietEnd);
// Load settings on mount
useEffect(() => {
loadSettings();
}, []);
const loadSettings = async () => {
try {
const response = await api.getNotificationSettings();
if (response.ok && response.data) {
const s = response.data;
setEmergencyAlerts(s.emergencyAlerts ?? DEFAULT_SETTINGS.emergencyAlerts);
setActivityAlerts(s.activityAlerts ?? DEFAULT_SETTINGS.activityAlerts);
setLowBattery(s.lowBattery ?? DEFAULT_SETTINGS.lowBattery);
setDailySummary(s.dailySummary ?? DEFAULT_SETTINGS.dailySummary);
setWeeklySummary(s.weeklySummary ?? DEFAULT_SETTINGS.weeklySummary);
setPushEnabled(s.pushEnabled ?? DEFAULT_SETTINGS.pushEnabled);
setEmailEnabled(s.emailEnabled ?? DEFAULT_SETTINGS.emailEnabled);
setSmsEnabled(s.smsEnabled ?? DEFAULT_SETTINGS.smsEnabled);
setQuietHours(s.quietHours ?? DEFAULT_SETTINGS.quietHours);
setQuietStart(s.quietStart ?? DEFAULT_SETTINGS.quietStart);
setQuietEnd(s.quietEnd ?? DEFAULT_SETTINGS.quietEnd);
}
} catch (error) {
// Failed to load notification settings
} finally {
setIsLoading(false);
}
};
const handleSave = async () => {
setIsSaving(true);
try {
const settings: NotificationSettings = {
emergencyAlerts,
activityAlerts,
lowBattery,
dailySummary,
weeklySummary,
pushEnabled,
emailEnabled,
smsEnabled,
quietHours,
quietStart,
quietEnd,
};
const response = await api.updateNotificationSettings(settings);
if (response.ok) {
Alert.alert(
'Settings Saved',
'Your notification preferences have been updated.',
[{ text: 'OK', onPress: () => router.back() }]
);
} else {
Alert.alert('Error', response.error?.message || 'Failed to save settings');
}
} catch (error) {
Alert.alert('Error', 'Failed to save settings. Please try again.');
} finally {
setIsSaving(false);
}
};
const handleQuietHoursConfig = () => {
Alert.alert(
'Quiet Hours',
`Current: ${quietStart} - ${quietEnd}\n\nDuring quiet hours, only emergency alerts will be delivered.`,
[
{ text: 'Cancel', style: 'cancel' },
{ text: 'Set Start Time', onPress: () => Alert.alert('Coming Soon', 'Time picker coming soon!') },
]
);
};
if (isLoading) {
return (
);
}
return (
{/* Alert Types */}
Alert Types
{/* Delivery Methods */}
Delivery Methods
{
if (value) {
Alert.alert(
'SMS Notifications',
'SMS notifications require a verified phone number. Would you like to add one?',
[
{ text: 'Cancel', style: 'cancel' },
{
text: 'Add Phone',
onPress: () => router.push('/profile/edit')
},
]
);
} else {
setSmsEnabled(false);
}
}}
/>
{/* Quiet Hours */}
Quiet Hours
{quietHours && (
<>
Quiet Period
{quietStart} - {quietEnd}
>
)}
Emergency alerts will always be delivered, even during quiet hours.
{/* Test Notification */}
{
Alert.alert(
'Test Notification Sent',
'A test push notification has been sent to your device.',
[{ text: 'OK' }]
);
}}
>
Send Test Notification
{/* Save Button */}
{isSaving ? (
) : (
Save Preferences
)}
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: AppColors.surface,
},
loadingContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
section: {
marginTop: Spacing.md,
},
sectionTitle: {
fontSize: FontSizes.sm,
fontWeight: '600',
color: AppColors.textSecondary,
paddingHorizontal: Spacing.lg,
paddingVertical: Spacing.sm,
textTransform: 'uppercase',
},
card: {
backgroundColor: AppColors.background,
},
settingRow: {
flexDirection: 'row',
alignItems: 'center',
paddingVertical: Spacing.md,
paddingHorizontal: Spacing.lg,
},
iconContainer: {
width: 40,
height: 40,
borderRadius: BorderRadius.md,
justifyContent: 'center',
alignItems: 'center',
},
settingContent: {
flex: 1,
marginLeft: Spacing.md,
},
settingTitle: {
fontSize: FontSizes.base,
fontWeight: '500',
color: AppColors.textPrimary,
},
settingDescription: {
fontSize: FontSizes.xs,
color: AppColors.textMuted,
marginTop: 2,
},
divider: {
height: 1,
backgroundColor: AppColors.border,
marginLeft: Spacing.lg + 40 + Spacing.md,
},
timeRow: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingVertical: Spacing.md,
paddingHorizontal: Spacing.lg,
},
timeInfo: {
flexDirection: 'row',
alignItems: 'center',
},
timeLabel: {
fontSize: FontSizes.base,
color: AppColors.textPrimary,
marginLeft: Spacing.sm,
},
timeValue: {
flexDirection: 'row',
alignItems: 'center',
},
timeText: {
fontSize: FontSizes.sm,
color: AppColors.textSecondary,
marginRight: Spacing.xs,
},
quietNote: {
fontSize: FontSizes.xs,
color: AppColors.textMuted,
paddingHorizontal: Spacing.lg,
paddingTop: Spacing.sm,
},
testButton: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: AppColors.background,
paddingVertical: Spacing.md,
marginHorizontal: Spacing.lg,
borderRadius: BorderRadius.lg,
borderWidth: 1,
borderColor: AppColors.primary,
},
testButtonText: {
fontSize: FontSizes.base,
fontWeight: '500',
color: AppColors.primary,
marginLeft: Spacing.sm,
},
footer: {
padding: Spacing.lg,
backgroundColor: AppColors.background,
borderTopWidth: 1,
borderTopColor: AppColors.border,
},
saveButton: {
backgroundColor: AppColors.primary,
borderRadius: BorderRadius.lg,
paddingVertical: Spacing.md,
alignItems: 'center',
minHeight: 48,
justifyContent: 'center',
},
saveButtonDisabled: {
opacity: 0.7,
},
saveButtonText: {
fontSize: FontSizes.base,
fontWeight: '600',
color: AppColors.white,
},
});