diff --git a/app/sleep-detail.tsx b/app/sleep-detail.tsx index a66696d..29f49ae 100644 --- a/app/sleep-detail.tsx +++ b/app/sleep-detail.tsx @@ -11,9 +11,6 @@ import { router } from 'expo-router'; import React, { useCallback, useEffect, useState } from 'react'; import { ActivityIndicator, - Animated, - Modal, - Pressable, ScrollView, StyleSheet, Text, @@ -22,6 +19,8 @@ import { } from 'react-native'; import { HeaderBar } from '@/components/ui/HeaderBar'; +import { InfoModal, type SleepDetailData } from '@/components/sleep/InfoModal'; +import { SleepStagesInfoModal } from '@/components/sleep/SleepStagesInfoModal'; import { Colors } from '@/constants/Colors'; import { useColorScheme } from '@/hooks/useColorScheme'; @@ -67,21 +66,11 @@ type HeartRateData = { value: number; }; -// 睡眠详情数据类型 -type SleepDetailData = { - sleepScore: number; - totalSleepTime: number; - sleepQualityPercentage: number; - bedtime: string; - wakeupTime: string; - timeInBed: number; +// 睡眠详情数据类型从 InfoModal 组件导入,但需要扩展以包含其他字段 +type ExtendedSleepDetailData = SleepDetailData & { sleepStages: SleepStageStats[]; rawSleepSamples: SleepSample[]; - averageHeartRate: number | null; sleepHeartRateData: HeartRateData[]; - sleepEfficiency: number; - qualityDescription: string; - recommendation: string; }; // 工具函数 @@ -349,7 +338,7 @@ const getSleepQualityInfo = (sleepScore: number): { description: string; recomme }; // 主函数:获取完整的睡眠详情数据 -const fetchSleepDetailData = async (date: Date): Promise => { +const fetchSleepDetailData = async (date: Date): Promise => { try { console.log('开始获取睡眠详情数据...', date); @@ -424,7 +413,7 @@ const fetchSleepDetailData = async (date: Date): Promise console.log('睡眠得分:', sleepScore); console.log('========================'); - const sleepDetailData: SleepDetailData = { + const sleepDetailData: ExtendedSleepDetailData = { sleepScore, totalSleepTime, sleepQualityPercentage: sleepScore, @@ -554,354 +543,16 @@ const SleepStageChart = ({ ); }; -// Sleep Grade Component 睡眠等级组件 -const SleepGradeCard = ({ - icon, - grade, - range, - isActive = false -}: { - icon: string; - grade: string; - range: string; - isActive?: boolean; -}) => { - const theme = (useColorScheme() ?? 'light') as 'light' | 'dark'; - const colorTokens = Colors[theme]; +// SleepGradeCard 组件现在在 InfoModal 组件内部 - const getGradeColor = (grade: string) => { - switch (grade) { - case '低': case '较差': return { bg: '#FECACA', text: '#DC2626' }; - case '正常': case '一般': return { bg: '#D1FAE5', text: '#065F46' }; - case '良好': return { bg: '#D1FAE5', text: '#065F46' }; - case '优秀': return { bg: '#FEF3C7', text: '#92400E' }; - default: return { bg: colorTokens.pageBackgroundEmphasis, text: colorTokens.textSecondary }; - } - }; +// SleepStagesInfoModal 组件现在从独立文件导入 - const colors = getGradeColor(grade); - - return ( - - - - - {grade} - - - - {range} - - - ); -}; - -// Sleep Stages Info Modal 组件 -const SleepStagesInfoModal = ({ - visible, - onClose -}: { - visible: boolean; - onClose: () => void; -}) => { - const theme = (useColorScheme() ?? 'light') as 'light' | 'dark'; - const colorTokens = Colors[theme]; - const slideAnim = useState(new Animated.Value(0))[0]; - - React.useEffect(() => { - if (visible) { - slideAnim.setValue(0); - Animated.spring(slideAnim, { - toValue: 1, - useNativeDriver: true, - tension: 100, - friction: 8, - }).start(); - } else { - Animated.spring(slideAnim, { - toValue: 0, - useNativeDriver: true, - tension: 100, - friction: 8, - }).start(); - } - }, [visible]); - - const translateY = slideAnim.interpolate({ - inputRange: [0, 1], - outputRange: [300, 0], - }); - - const opacity = slideAnim.interpolate({ - inputRange: [0, 1], - outputRange: [0, 1], - }); - - return ( - - - - - - - - - - 了解你的睡眠阶段 - - - - - - - - - 人们对睡眠阶段和睡眠质量有许多误解。有些人可能需要更多深度睡眠,其他人则不然。科学家和医生仍在探索不同睡眠阶段的作用及其对身体的影响。通过跟踪睡眠阶段并留意每天清晨的感受,你或许能深入了解自己的睡眠。 - - - {/* 清醒时间 */} - - - - - 清醒时间 - - - - 一次睡眠期间,你可能会醒来几次。偶尔醒来很正常。可能你会立刻再次入睡,并不记得曾在夜间醒来。 - - - - {/* 快速动眼睡眠 */} - - - - - 快速动眼睡眠 - - - - 这一睡眠阶段可能对学习和记忆产生一定影响。在此阶段,你的肌肉最为放松,眼球也会快速左右移动。这也是你大多数梦境出现的阶段。 - - - - {/* 核心睡眠 */} - - - - - 核心睡眠 - - - - 这一阶段有时也称为浅睡期,与其他阶段一样重要。此阶段通常占据你每晚大部分的睡眠时间。对于认知至关重要的脑电波会在这一阶段产生。 - - - - {/* 深度睡眠 */} - - - - - 深度睡眠 - - - - 因为脑电波的特征,这一阶段也称为慢波睡眠。在此阶段,身体组织得到修复,并释放重要荷尔蒙。它通常出现在睡眠的前半段,且持续时间较长。深度睡眠期间,身体非常放松,因此相较于其他阶段,你可能更难在此阶段醒来。 - - - - - - - - ); -}; - -// Info Modal 组件 -const InfoModal = ({ - visible, - onClose, - title, - type, - sleepData -}: { - visible: boolean; - onClose: () => void; - title: string; - type: 'sleep-time' | 'sleep-quality'; - sleepData: SleepDetailData; -}) => { - const theme = (useColorScheme() ?? 'light') as 'light' | 'dark'; - const colorTokens = Colors[theme]; - const slideAnim = useState(new Animated.Value(0))[0]; - - React.useEffect(() => { - if (visible) { - // 重置动画值确保每次打开都有动画 - slideAnim.setValue(0); - Animated.spring(slideAnim, { - toValue: 1, - useNativeDriver: true, - tension: 100, - friction: 8, - }).start(); - } else { - Animated.spring(slideAnim, { - toValue: 0, - useNativeDriver: true, - tension: 100, - friction: 8, - }).start(); - } - }, [visible]); - - const translateY = slideAnim.interpolate({ - inputRange: [0, 1], - outputRange: [300, 0], - }); - - const opacity = slideAnim.interpolate({ - inputRange: [0, 1], - outputRange: [0, 1], - }); - - // 根据实际睡眠时间计算等级 - const getSleepTimeGrade = (totalSleepMinutes: number) => { - const hours = totalSleepMinutes / 60; - if (hours < 6) return 0; // 低 - if ((hours >= 6 && hours < 7) || hours > 9) return 1; // 正常 - if (hours >= 7 && hours < 8) return 2; // 良好 - if (hours >= 8 && hours <= 9) return 3; // 优秀 - return 1; // 默认正常 - }; - - // 根据实际睡眠质量百分比计算等级 - const getSleepQualityGrade = (qualityPercentage: number) => { - if (qualityPercentage < 55) return 0; // 较差 - if (qualityPercentage < 70) return 1; // 一般 - if (qualityPercentage < 85) return 2; // 良好 - return 3; // 优秀 - }; - - const currentSleepTimeGrade = getSleepTimeGrade(sleepData.totalSleepTime || 443); // 默认7h23m - const currentSleepQualityGrade = getSleepQualityGrade(sleepData.sleepQualityPercentage || 94); // 默认94% - - const sleepTimeGrades = [ - { icon: 'alert-circle-outline', grade: '低', range: '< 6h', isActive: currentSleepTimeGrade === 0 }, - { icon: 'checkmark-circle-outline', grade: '正常', range: '6h - 7h or > 9h', isActive: currentSleepTimeGrade === 1 }, - { icon: 'checkmark-circle', grade: '良好', range: '7h - 8h', isActive: currentSleepTimeGrade === 2 }, - { icon: 'star', grade: '优秀', range: '8h - 9h', isActive: currentSleepTimeGrade === 3 }, - ]; - - const sleepQualityGrades = [ - { icon: 'alert-circle-outline', grade: '较差', range: '< 55%', isActive: currentSleepQualityGrade === 0 }, - { icon: 'checkmark-circle-outline', grade: '一般', range: '55% - 69%', isActive: currentSleepQualityGrade === 1 }, - { icon: 'checkmark-circle', grade: '良好', range: '70% - 84%', isActive: currentSleepQualityGrade === 2 }, - { icon: 'star', grade: '优秀', range: '85% - 100%', isActive: currentSleepQualityGrade === 3 }, - ]; - - const currentGrades = type === 'sleep-time' ? sleepTimeGrades : sleepQualityGrades; - - const getDescription = () => { - if (type === 'sleep-time') { - return '睡眠最重要 - 它占据了你睡眠得分的一半以上。长时间的睡眠可以减少睡眠债务,但是规律的睡眠时间对于高质量的休息至关重要。'; - } else { - return '睡眠质量综合评估您的睡眠效率、深度睡眠时长、REM睡眠比例等多个指标。高质量的睡眠不仅仅取决于时长,还包括睡眠的连续性和各睡眠阶段的平衡。'; - } - }; - - return ( - - - - - - - {title} - - - - - - - {/* 等级卡片区域 */} - - {currentGrades.map((grade, index) => ( - - ))} - - - - {getDescription()} - - - - - ); -}; +// InfoModal 组件现在从独立文件导入 export default function SleepDetailScreen() { const theme = (useColorScheme() ?? 'light') as 'light' | 'dark'; const colorTokens = Colors[theme]; - const [sleepData, setSleepData] = useState(null); + const [sleepData, setSleepData] = useState(null); const [loading, setLoading] = useState(true); const [selectedDate] = useState(dayjs().toDate()); @@ -963,7 +614,7 @@ export default function SleepDetailScreen() { } // 如果没有数据,使用默认数据结构 - const displayData: SleepDetailData = sleepData || { + const displayData: ExtendedSleepDetailData = sleepData || { sleepScore: 0, totalSleepTime: 0, sleepQualityPercentage: 0, @@ -1586,81 +1237,7 @@ const styles = StyleSheet.create({ color: '#9CA3AF', fontStyle: 'italic', }, - // Info Modal 样式 - modalOverlay: { - flex: 1, - backgroundColor: 'rgba(0, 0, 0, 0.5)', - justifyContent: 'flex-end', - }, - infoModalContent: { - borderTopLeftRadius: 24, - borderTopRightRadius: 24, - paddingTop: 12, - paddingHorizontal: 20, - paddingBottom: 34, - minHeight: 200, - shadowColor: '#000', - shadowOffset: { width: 0, height: -4 }, - shadowOpacity: 0.1, - shadowRadius: 16, - elevation: 8, - }, - modalHandle: { - width: 36, - height: 4, - backgroundColor: '#D1D5DB', - borderRadius: 2, - alignSelf: 'center', - marginBottom: 20, - }, - infoModalHeader: { - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - marginBottom: 16, - }, - infoModalTitle: { - fontSize: 18, - fontWeight: '700', - letterSpacing: -0.3, - }, - infoModalCloseButton: { - padding: 4, - }, - infoModalText: { - fontSize: 15, - lineHeight: 22, - letterSpacing: -0.1, - }, - // Grade Cards 样式 - gradesContainer: { - marginBottom: 20, - gap: 8, - }, - gradeCard: { - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - paddingHorizontal: 16, - paddingVertical: 12, - borderRadius: 12, - borderWidth: 1, - }, - gradeCardLeft: { - flexDirection: 'row', - alignItems: 'center', - gap: 8, - }, - gradeText: { - fontSize: 16, - fontWeight: '600', - letterSpacing: -0.2, - }, - gradeRange: { - fontSize: 16, - fontWeight: '700', - letterSpacing: -0.3, - }, + // Info Modal 和 Grade Cards 样式已移动到独立组件中 mockDataToggle: { paddingHorizontal: 12, paddingVertical: 6, @@ -1798,73 +1375,7 @@ const styles = StyleSheet.create({ height: '100%', borderRadius: 3, }, - // Sleep Stages Modal 样式 - sleepStagesModalContent: { - borderTopLeftRadius: 24, - borderTopRightRadius: 24, - height: '80%', - shadowColor: '#000', - shadowOffset: { width: 0, height: -4 }, - shadowOpacity: 0.1, - shadowRadius: 16, - elevation: 8, - }, - sleepStagesModalInner: { - flex: 1, - paddingTop: 12, - paddingHorizontal: 20, - paddingBottom: 34, - }, - sleepStagesModalHeader: { - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - marginBottom: 20, - }, - sleepStagesModalTitle: { - fontSize: 20, - fontWeight: '700', - letterSpacing: -0.4, - }, - sleepStagesScrollView: { - flex: 1, - }, - sleepStagesScrollContent: { - paddingBottom: 40, - }, - sleepStagesDescription: { - fontSize: 15, - lineHeight: 22, - letterSpacing: -0.1, - marginBottom: 24, - }, - sleepStageInfoCard: { - marginBottom: 20, - }, - sleepStageInfoHeader: { - paddingBottom: 12, - marginBottom: 12, - }, - sleepStageInfoTitleContainer: { - flexDirection: 'row', - alignItems: 'center', - gap: 12, - }, - sleepStageDot: { - width: 12, - height: 12, - borderRadius: 6, - }, - sleepStageInfoTitle: { - fontSize: 18, - fontWeight: '600', - letterSpacing: -0.2, - }, - sleepStageInfoContent: { - fontSize: 15, - lineHeight: 22, - letterSpacing: -0.1, - }, + // Sleep Stages Modal 样式已移动到独立组件中 // 睡眠时间标签样式 sleepTimeLabels: { flexDirection: 'row', diff --git a/components/sleep/InfoModal.tsx b/components/sleep/InfoModal.tsx new file mode 100644 index 0000000..5005e3f --- /dev/null +++ b/components/sleep/InfoModal.tsx @@ -0,0 +1,307 @@ +import { Ionicons } from '@expo/vector-icons'; +import React, { useState } from 'react'; +import { + Animated, + Modal, + StyleSheet, + Text, + TouchableOpacity, + View +} from 'react-native'; + +import { Colors } from '@/constants/Colors'; +import { useColorScheme } from '@/hooks/useColorScheme'; + +// 睡眠详情数据类型 +export type SleepDetailData = { + sleepScore: number; + totalSleepTime: number; + sleepQualityPercentage: number; + bedtime: string; + wakeupTime: string; + timeInBed: number; + sleepStages: any[]; + rawSleepSamples: any[]; + averageHeartRate: number | null; + sleepHeartRateData: any[]; + sleepEfficiency: number; + qualityDescription: string; + recommendation: string; +}; + +// Sleep Grade Component 睡眠等级组件 +const SleepGradeCard = ({ + icon, + grade, + range, + isActive = false +}: { + icon: string; + grade: string; + range: string; + isActive?: boolean; +}) => { + const theme = (useColorScheme() ?? 'light') as 'light' | 'dark'; + const colorTokens = Colors[theme]; + + const getGradeColor = (grade: string) => { + switch (grade) { + case '低': case '较差': return { bg: '#FECACA', text: '#DC2626' }; + case '正常': case '一般': return { bg: '#D1FAE5', text: '#065F46' }; + case '良好': return { bg: '#D1FAE5', text: '#065F46' }; + case '优秀': return { bg: '#FEF3C7', text: '#92400E' }; + default: return { bg: colorTokens.pageBackgroundEmphasis, text: colorTokens.textSecondary }; + } + }; + + const colors = getGradeColor(grade); + + return ( + + + + + {grade} + + + + {range} + + + ); +}; + +// Info Modal 组件 +export const InfoModal = ({ + visible, + onClose, + title, + type, + sleepData +}: { + visible: boolean; + onClose: () => void; + title: string; + type: 'sleep-time' | 'sleep-quality'; + sleepData: SleepDetailData; +}) => { + const theme = (useColorScheme() ?? 'light') as 'light' | 'dark'; + const colorTokens = Colors[theme]; + const slideAnim = useState(new Animated.Value(0))[0]; + + React.useEffect(() => { + if (visible) { + // 重置动画值确保每次打开都有动画 + slideAnim.setValue(0); + Animated.spring(slideAnim, { + toValue: 1, + useNativeDriver: true, + tension: 100, + friction: 8, + }).start(); + } else { + Animated.spring(slideAnim, { + toValue: 0, + useNativeDriver: true, + tension: 100, + friction: 8, + }).start(); + } + }, [visible]); + + const translateY = slideAnim.interpolate({ + inputRange: [0, 1], + outputRange: [300, 0], + }); + + const opacity = slideAnim.interpolate({ + inputRange: [0, 1], + outputRange: [0, 1], + }); + + // 根据实际睡眠时间计算等级 + const getSleepTimeGrade = (totalSleepMinutes: number) => { + const hours = totalSleepMinutes / 60; + if (hours < 6) return 0; // 低 + if ((hours >= 6 && hours < 7) || hours > 9) return 1; // 正常 + if (hours >= 7 && hours < 8) return 2; // 良好 + if (hours >= 8 && hours <= 9) return 3; // 优秀 + return 1; // 默认正常 + }; + + // 根据实际睡眠质量百分比计算等级 + const getSleepQualityGrade = (qualityPercentage: number) => { + if (qualityPercentage < 55) return 0; // 较差 + if (qualityPercentage < 70) return 1; // 一般 + if (qualityPercentage < 85) return 2; // 良好 + return 3; // 优秀 + }; + + const currentSleepTimeGrade = getSleepTimeGrade(sleepData.totalSleepTime || 443); // 默认7h23m + const currentSleepQualityGrade = getSleepQualityGrade(sleepData.sleepQualityPercentage || 94); // 默认94% + + const sleepTimeGrades = [ + { icon: 'alert-circle-outline', grade: '低', range: '< 6h', isActive: currentSleepTimeGrade === 0 }, + { icon: 'checkmark-circle-outline', grade: '正常', range: '6h - 7h or > 9h', isActive: currentSleepTimeGrade === 1 }, + { icon: 'checkmark-circle', grade: '良好', range: '7h - 8h', isActive: currentSleepTimeGrade === 2 }, + { icon: 'star', grade: '优秀', range: '8h - 9h', isActive: currentSleepTimeGrade === 3 }, + ]; + + const sleepQualityGrades = [ + { icon: 'alert-circle-outline', grade: '较差', range: '< 55%', isActive: currentSleepQualityGrade === 0 }, + { icon: 'checkmark-circle-outline', grade: '一般', range: '55% - 69%', isActive: currentSleepQualityGrade === 1 }, + { icon: 'checkmark-circle', grade: '良好', range: '70% - 84%', isActive: currentSleepQualityGrade === 2 }, + { icon: 'star', grade: '优秀', range: '85% - 100%', isActive: currentSleepQualityGrade === 3 }, + ]; + + const currentGrades = type === 'sleep-time' ? sleepTimeGrades : sleepQualityGrades; + + const getDescription = () => { + if (type === 'sleep-time') { + return '睡眠最重要 - 它占据了你睡眠得分的一半以上。长时间的睡眠可以减少睡眠债务,但是规律的睡眠时间对于高质量的休息至关重要。'; + } else { + return '睡眠质量综合评估您的睡眠效率、深度睡眠时长、REM睡眠比例等多个指标。高质量的睡眠不仅仅取决于时长,还包括睡眠的连续性和各睡眠阶段的平衡。'; + } + }; + + return ( + + + + + + + {title} + + + + + + + {/* 等级卡片区域 */} + + {currentGrades.map((grade, index) => ( + + ))} + + + + {getDescription()} + + + + + ); +}; + +const styles = StyleSheet.create({ + // Info Modal 样式 + modalOverlay: { + flex: 1, + backgroundColor: 'rgba(0, 0, 0, 0.5)', + justifyContent: 'flex-end', + }, + infoModalContent: { + borderTopLeftRadius: 24, + borderTopRightRadius: 24, + paddingTop: 12, + paddingHorizontal: 20, + paddingBottom: 34, + minHeight: 200, + shadowColor: '#000', + shadowOffset: { width: 0, height: -4 }, + shadowOpacity: 0.1, + shadowRadius: 16, + elevation: 8, + }, + modalHandle: { + width: 36, + height: 4, + backgroundColor: '#D1D5DB', + borderRadius: 2, + alignSelf: 'center', + marginBottom: 20, + }, + infoModalHeader: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + marginBottom: 16, + }, + infoModalTitle: { + fontSize: 18, + fontWeight: '700', + letterSpacing: -0.3, + }, + infoModalCloseButton: { + padding: 4, + }, + infoModalText: { + fontSize: 15, + lineHeight: 22, + letterSpacing: -0.1, + }, + // Grade Cards 样式 + gradesContainer: { + marginBottom: 20, + gap: 8, + }, + gradeCard: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + paddingHorizontal: 16, + paddingVertical: 12, + borderRadius: 12, + borderWidth: 1, + }, + gradeCardLeft: { + flexDirection: 'row', + alignItems: 'center', + gap: 8, + }, + gradeText: { + fontSize: 16, + fontWeight: '600', + letterSpacing: -0.2, + }, + gradeRange: { + fontSize: 16, + fontWeight: '700', + letterSpacing: -0.3, + }, +}); \ No newline at end of file diff --git a/components/sleep/SleepStagesInfoModal.tsx b/components/sleep/SleepStagesInfoModal.tsx new file mode 100644 index 0000000..4e028c0 --- /dev/null +++ b/components/sleep/SleepStagesInfoModal.tsx @@ -0,0 +1,246 @@ +import { Ionicons } from '@expo/vector-icons'; +import React, { useState } from 'react'; +import { + Animated, + Modal, + Pressable, + ScrollView, + StyleSheet, + Text, + TouchableOpacity, + View +} from 'react-native'; + +import { Colors } from '@/constants/Colors'; +import { useColorScheme } from '@/hooks/useColorScheme'; + +// Sleep Stages Info Modal 组件 +export const SleepStagesInfoModal = ({ + visible, + onClose +}: { + visible: boolean; + onClose: () => void; +}) => { + const theme = (useColorScheme() ?? 'light') as 'light' | 'dark'; + const colorTokens = Colors[theme]; + const slideAnim = useState(new Animated.Value(0))[0]; + + React.useEffect(() => { + if (visible) { + slideAnim.setValue(0); + Animated.spring(slideAnim, { + toValue: 1, + useNativeDriver: true, + tension: 100, + friction: 8, + }).start(); + } else { + Animated.spring(slideAnim, { + toValue: 0, + useNativeDriver: true, + tension: 100, + friction: 8, + }).start(); + } + }, [visible]); + + const translateY = slideAnim.interpolate({ + inputRange: [0, 1], + outputRange: [300, 0], + }); + + const opacity = slideAnim.interpolate({ + inputRange: [0, 1], + outputRange: [0, 1], + }); + + return ( + + + + + + + + + + 了解你的睡眠阶段 + + + + + + + + + 人们对睡眠阶段和睡眠质量有许多误解。有些人可能需要更多深度睡眠,其他人则不然。科学家和医生仍在探索不同睡眠阶段的作用及其对身体的影响。通过跟踪睡眠阶段并留意每天清晨的感受,你或许能深入了解自己的睡眠。 + + + {/* 清醒时间 */} + + + + + 清醒时间 + + + + 一次睡眠期间,你可能会醒来几次。偶尔醒来很正常。可能你会立刻再次入睡,并不记得曾在夜间醒来。 + + + + {/* 快速动眼睡眠 */} + + + + + 快速动眼睡眠 + + + + 这一睡眠阶段可能对学习和记忆产生一定影响。在此阶段,你的肌肉最为放松,眼球也会快速左右移动。这也是你大多数梦境出现的阶段。 + + + + {/* 核心睡眠 */} + + + + + 核心睡眠 + + + + 这一阶段有时也称为浅睡期,与其他阶段一样重要。此阶段通常占据你每晚大部分的睡眠时间。对于认知至关重要的脑电波会在这一阶段产生。 + + + + {/* 深度睡眠 */} + + + + + 深度睡眠 + + + + 因为脑电波的特征,这一阶段也称为慢波睡眠。在此阶段,身体组织得到修复,并释放重要荷尔蒙。它通常出现在睡眠的前半段,且持续时间较长。深度睡眠期间,身体非常放松,因此相较于其他阶段,你可能更难在此阶段醒来。 + + + + + + + + ); +}; + +const styles = StyleSheet.create({ + modalOverlay: { + flex: 1, + backgroundColor: 'rgba(0, 0, 0, 0.5)', + justifyContent: 'flex-end', + }, + modalHandle: { + width: 36, + height: 4, + backgroundColor: '#D1D5DB', + borderRadius: 2, + alignSelf: 'center', + marginBottom: 20, + }, + infoModalCloseButton: { + padding: 4, + }, + // Sleep Stages Modal 样式 + sleepStagesModalContent: { + borderTopLeftRadius: 24, + borderTopRightRadius: 24, + height: '80%', + shadowColor: '#000', + shadowOffset: { width: 0, height: -4 }, + shadowOpacity: 0.1, + shadowRadius: 16, + elevation: 8, + }, + sleepStagesModalInner: { + flex: 1, + paddingTop: 12, + paddingHorizontal: 20, + paddingBottom: 34, + }, + sleepStagesModalHeader: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + marginBottom: 20, + }, + sleepStagesModalTitle: { + fontSize: 20, + fontWeight: '700', + letterSpacing: -0.4, + }, + sleepStagesScrollView: { + flex: 1, + }, + sleepStagesScrollContent: { + paddingBottom: 40, + }, + sleepStagesDescription: { + fontSize: 15, + lineHeight: 22, + letterSpacing: -0.1, + marginBottom: 24, + }, + sleepStageInfoCard: { + marginBottom: 20, + }, + sleepStageInfoHeader: { + paddingBottom: 12, + marginBottom: 12, + }, + sleepStageInfoTitleContainer: { + flexDirection: 'row', + alignItems: 'center', + gap: 12, + }, + sleepStageDot: { + width: 12, + height: 12, + borderRadius: 6, + }, + sleepStageInfoTitle: { + fontSize: 18, + fontWeight: '600', + letterSpacing: -0.2, + }, + sleepStageInfoContent: { + fontSize: 15, + lineHeight: 22, + letterSpacing: -0.1, + }, +}); \ No newline at end of file