import { HeaderBar } from '@/components/ui/HeaderBar'; import { useAppDispatch, useAppSelector } from '@/hooks/redux'; import { fetchFamilyGroup, generateInviteCode, selectFamilyGroup, selectFamilyHealthLoading, selectInviteCode, selectInviteLoading, } from '@/store/familyHealthSlice'; import { Ionicons } from '@expo/vector-icons'; import { LinearGradient } from 'expo-linear-gradient'; import { Stack } from 'expo-router'; import React, { useEffect, useState } from 'react'; import { ActivityIndicator, Alert, Modal, ScrollView, Share, StyleSheet, Text, TouchableOpacity, View } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; export default function FamilyInviteScreen() { const insets = useSafeAreaInsets(); const dispatch = useAppDispatch(); const [agreed, setAgreed] = useState(true); const [showQRModal, setShowQRModal] = useState(false); // Redux state const familyGroup = useAppSelector(selectFamilyGroup); const inviteCode = useAppSelector(selectInviteCode); const isLoading = useAppSelector(selectFamilyHealthLoading); const isInviteLoading = useAppSelector(selectInviteLoading); // 初始化时获取家庭组信息 useEffect(() => { dispatch(fetchFamilyGroup()); }, [dispatch]); // 处理邀请按钮点击 const handleInvite = async () => { try { // 生成邀请码 await dispatch(generateInviteCode(24)).unwrap(); // 显示二维码弹窗 setShowQRModal(true); } catch (error: any) { Alert.alert('邀请失败', error?.message || '请稍后重试'); } }; // 分享邀请码 const handleShare = async () => { if (!inviteCode) return; try { await Share.share({ message: `邀请您加入我的家庭健康管理组!\n邀请码:${inviteCode.inviteCode}\n有效期至:${new Date(inviteCode.expiresAt).toLocaleString()}`, title: '家庭健康管理邀请', }); } catch (error) { console.error('分享失败:', error); } }; return ( {/* Header Title Area */} 家庭健康管理 保障全家健康 全家互相督促,让关爱不遗漏 {/* Hero Image / House Icon Area */} {/* Floating Labels */} 实时管理 守护家庭健康 {/* Main 3D House Icon Placeholder */} {/* Features Grid */} 数据共享 家人档案共同维护 异常提醒 数据异常实时提醒 用药监督 用药情况远程监督 {/* Steps Section */} 简单3步,帮家人管理档案 最多邀请6人,分享二维码有效期24小时 1 分享二维码邀请 2 家人下载登录App 3 扫二维码加入 {/* Bottom Spacing */} {/* Bottom Action Area */} setAgreed(!agreed)} activeOpacity={0.8} > 申请对方同意我查看并管理其健康档案,有数据异常预警我 {isLoading ? ( ) : ( 立即邀请 )} {/* QR Code Modal */} setShowQRModal(false)} > 邀请家人加入 setShowQRModal(false)}> {isInviteLoading ? ( ) : inviteCode ? ( <> {/* 邀请码大字展示(替代二维码,后续可安装 react-native-qrcode-svg 实现) */} {inviteCode.inviteCode} 请让家人在 App 中输入此邀请码 邀请码 {inviteCode.inviteCode} 有效期至:{new Date(inviteCode.expiresAt).toLocaleString()} 分享邀请 ) : null} ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#F9FAFB', }, background: { position: 'absolute', left: 0, right: 0, top: 0, bottom: 0, }, scrollContent: { paddingHorizontal: 20, }, headerSection: { alignItems: 'center', marginBottom: 30, }, mainTitle: { fontSize: 28, fontWeight: 'bold', color: '#1F2937', lineHeight: 36, textAlign: 'center', }, subtitleBadge: { flexDirection: 'row', alignItems: 'center', backgroundColor: 'rgba(255,255,255,0.6)', paddingHorizontal: 12, paddingVertical: 6, borderRadius: 16, marginTop: 16, borderWidth: 1, borderColor: '#FFFFFF', }, subtitleText: { fontSize: 12, color: '#5B4CFF', marginLeft: 6, fontWeight: '600', }, heroContainer: { alignItems: 'center', justifyContent: 'center', height: 180, marginBottom: 20, position: 'relative', }, houseIconPlaceholder: { width: 140, height: 140, alignItems: 'center', justifyContent: 'center', }, houseIconGradient: { width: 100, height: 100, borderRadius: 30, alignItems: 'center', justifyContent: 'center', transform: [{ rotate: '45deg' }], shadowColor: '#5B4CFF', shadowOffset: { width: 0, height: 10 }, shadowOpacity: 0.3, shadowRadius: 20, elevation: 10, }, floatingLabel: { position: 'absolute', flexDirection: 'row', alignItems: 'center', backgroundColor: 'rgba(255,255,255,0.8)', paddingHorizontal: 10, paddingVertical: 6, borderRadius: 12, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.05, shadowRadius: 4, elevation: 2, }, labelLeft: { left: 0, top: 40, }, labelRight: { right: 0, top: 20, }, floatingLabelText: { fontSize: 12, color: '#6B7280', fontWeight: '600', marginHorizontal: 4, }, dot: { width: 6, height: 6, borderRadius: 3, backgroundColor: '#5B4CFF', }, featuresCard: { flexDirection: 'row', backgroundColor: '#FFFFFF', borderRadius: 20, padding: 20, justifyContent: 'space-between', marginBottom: 24, shadowColor: '#000', shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.03, shadowRadius: 8, elevation: 2, }, featureItem: { flex: 1, alignItems: 'center', }, featureIcon: { width: 48, height: 48, borderRadius: 24, alignItems: 'center', justifyContent: 'center', marginBottom: 12, }, featureTitle: { fontSize: 14, fontWeight: 'bold', color: '#1F2937', marginBottom: 4, }, featureDesc: { fontSize: 10, color: '#9CA3AF', textAlign: 'center', }, stepsContainer: { backgroundColor: 'rgba(255,255,255,0.6)', borderRadius: 24, padding: 20, paddingBottom: 30, marginBottom: 20, }, stepsTitle: { fontSize: 18, fontWeight: 'bold', color: '#1F2937', textAlign: 'center', marginBottom: 8, }, stepsSubtitleContainer: { backgroundColor: '#F3F4F6', alignSelf: 'center', paddingHorizontal: 12, paddingVertical: 4, borderRadius: 10, marginBottom: 24, }, stepsSubtitle: { fontSize: 11, color: '#6B7280', }, stepsRow: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'flex-start', }, stepItem: { flex: 1, alignItems: 'center', }, stepNumber: { fontSize: 20, fontWeight: 'bold', color: '#5B4CFF', marginBottom: 8, fontStyle: 'italic', }, stepDesc: { fontSize: 12, color: '#4B5563', textAlign: 'center', marginBottom: 12, height: 32, }, stepPhoneMockup: { width: 60, height: 100, backgroundColor: '#FFFFFF', borderRadius: 10, borderWidth: 2, borderColor: '#E5E7EB', padding: 4, shadowColor: '#000', shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.05, shadowRadius: 4, elevation: 2, }, mockupScreen: { flex: 1, backgroundColor: '#F3F4F6', borderRadius: 6, }, bottomArea: { position: 'absolute', bottom: 0, left: 0, right: 0, backgroundColor: '#FFFFFF', paddingTop: 16, paddingHorizontal: 20, borderTopLeftRadius: 24, borderTopRightRadius: 24, shadowColor: '#000', shadowOffset: { width: 0, height: -4 }, shadowOpacity: 0.05, shadowRadius: 8, elevation: 10, }, checkboxRow: { flexDirection: 'row', alignItems: 'flex-start', marginBottom: 16, paddingHorizontal: 4, }, checkboxText: { flex: 1, marginLeft: 8, fontSize: 12, color: '#6B7280', lineHeight: 18, }, inviteButton: { backgroundColor: '#5B4CFF', borderRadius: 28, height: 56, alignItems: 'center', justifyContent: 'center', shadowColor: '#5B4CFF', shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.3, shadowRadius: 8, elevation: 4, }, inviteButtonDisabled: { backgroundColor: '#C4B5FD', shadowOpacity: 0, }, inviteButtonText: { color: '#FFFFFF', fontSize: 18, fontWeight: 'bold', }, // Modal styles modalOverlay: { flex: 1, backgroundColor: 'rgba(0, 0, 0, 0.5)', justifyContent: 'center', alignItems: 'center', padding: 20, }, modalContent: { width: '100%', backgroundColor: '#FFFFFF', borderRadius: 24, padding: 24, }, modalHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 24, }, modalTitle: { fontSize: 20, fontWeight: 'bold', color: '#1F2937', }, qrContainer: { alignItems: 'center', justifyContent: 'center', padding: 20, backgroundColor: '#F9FAFB', borderRadius: 16, marginBottom: 20, minHeight: 180, }, inviteCodeDisplay: { alignItems: 'center', justifyContent: 'center', }, inviteCodeBig: { fontSize: 36, fontWeight: 'bold', color: '#5B4CFF', letterSpacing: 4, marginTop: 16, marginBottom: 8, }, inviteCodeHint: { fontSize: 12, color: '#9CA3AF', }, inviteCodeContainer: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', backgroundColor: '#F3F4F6', borderRadius: 12, padding: 12, marginBottom: 12, }, inviteCodeLabel: { fontSize: 14, color: '#6B7280', marginRight: 8, }, inviteCodeText: { fontSize: 20, fontWeight: 'bold', color: '#5B4CFF', letterSpacing: 2, }, expireText: { fontSize: 12, color: '#9CA3AF', textAlign: 'center', marginBottom: 20, }, shareButton: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', backgroundColor: '#5B4CFF', borderRadius: 16, paddingVertical: 14, }, shareButtonText: { color: '#FFFFFF', fontSize: 16, fontWeight: '600', marginLeft: 8, }, });