diff --git a/UserHomeScreen.tsx b/UserHomeScreen.tsx new file mode 100644 index 0000000..a00d263 --- /dev/null +++ b/UserHomeScreen.tsx @@ -0,0 +1,413 @@ +// ParentHomeScreen.tsx +import React from 'react'; +import { + StyleSheet, + Text, + View, + ScrollView, + SafeAreaView +} from 'react-native'; +import MedicationPill from './MedicationPill'; // tsx 컴포넌트 불러오기 + +export default function ParentHomeScreen() { + // 4월 날짜 배열 생성 (TypeScript에서 number 타입 배열로 명시) + const days: number[] = Array.from({ length: 30 }, (_, i) => i + 1); + + return ( + + {/* --- GNB 헤더 영역 --- */} + + + + Caring + + + + 🔔 + + + + + {/* --- 메인 스크롤 콘텐츠 (조회 전용) --- */} + + + {/* 1. 하루 요약 레포트 카드 */} + + + 🐱 하루 요약 레포트 + + 하루 요약 레포트를 매일 21 : 00 시에 받아요 + + 오늘의 건강 상태 + + + 😀 + + + 😐 + + + 😥 + + + + + 오늘 하루 요약 + 어머니의 오늘 건강 상태는 '좋음' 이예요! + 어머니는 오늘 자녀에게 전화를 거셨어요 + + + + {/* 2. 일정 관리 카드 */} + + + 📅 일정 관리 + 일정 등록 + + + + 2026년 4월 < > + + {['일', '월', '화', '수', '목', '금', '토'].map((w, i) => ( + {w} + ))} + + + {/* 디자인 레이아웃 정렬을 위한 공백 칸 */} + + + + {days.map((day) => ( + + {day} + + ))} + + + + + {/* 3. 복약 관리 카드 */} + + + 💊 복약 관리 + 복약 추가 + + + + {/* 데이터 타입을 맞춰 true/false 바인딩 */} + + + + + + + {/* 4. 위치 GPS 카드 */} + + + 📍 위치 GPS + + + + 🔵 + + 지도 실시간 위치 표시 영역 + + + + {/* 5. 주변 공공 복지 시설 카드 */} + + + 🔖 주변 공공 복지 시설 + 더보기 > + + + + 🏢 + + 국가지원금 확인하기 + 돌봄대상자를 위한 지원금 체크 + + + + 🏛️ + + 보건복지부 지원 서비스 확인 + 보건복지부에서 지원하는 돌봄 서비스 + + + + + + + {/* --- 하단 탭 바 --- */} + + + 🏠 + + + + 👥 + 돌봄대상자 관리 + + + 👤 + 마이페이지 + + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: '#FFFFFF', + }, + header: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + paddingHorizontal: 16, + paddingVertical: 12, + borderBottomWidth: 1, + borderBottomColor: '#F2F2F7', + }, + logoContainer: { + flexDirection: 'row', + alignItems: 'center', + }, + logoCircle: { + width: 50, + height: 50, + borderRadius: 25, + borderWidth: 1, + borderColor: '#E5E5EA', + justifyContent: 'center', + alignItems: 'center', + backgroundColor: '#FFF8F2', + }, + logoText: { + fontSize: 12, + fontWeight: 'bold', + color: '#FF7A00', + }, + headerIcons: { + flexDirection: 'row', + gap: 16, + }, + iconPlaceholder: { + fontSize: 22, + color: '#333', + }, + scrollContent: { + paddingVertical: 16, + }, + card: { + backgroundColor: '#FFFFFF', + borderRadius: 16, + padding: 16, + marginHorizontal: 16, + marginBottom: 20, + shadowColor: '#000', + shadowOffset: { width: 0, height: 2 }, + shadowOpacity: 0.05, + shadowRadius: 8, + elevation: 3, + borderWidth: 1, + borderColor: '#E5E5EA', + }, + cardHeader: { + marginBottom: 8, + }, + cardHeaderSpace: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + marginBottom: 12, + }, + cardTitle: { + fontSize: 16, + fontWeight: 'bold', + color: '#1C1C1E', + }, + miniTag: { + backgroundColor: '#F2F2F7', + paddingHorizontal: 8, + paddingVertical: 4, + borderRadius: 6, + }, + miniTagText: { + fontSize: 11, + color: '#636366', + }, + reportSubText: { + fontSize: 12, + color: '#333', + marginBottom: 2, + }, + reportNotice: { + fontSize: 9, + color: '#8E8E93', + marginBottom: 16, + }, + sectionSubTitle: { + fontSize: 13, + fontWeight: '600', + color: '#1C1C1E', + marginBottom: 10, + }, + emojiContainer: { + flexDirection: 'row', + justifyContent: 'space-around', + marginBottom: 16, + }, + emojiCircle: { + width: 60, + height: 60, + borderRadius: 30, + backgroundColor: '#F2F2F7', + justifyContent: 'center', + alignItems: 'center', + }, + emojiSelected: { + borderWidth: 2, + borderColor: '#FF7A00', + backgroundColor: '#FFF8F2', + }, + emojiText: { + fontSize: 30, + }, + summaryBox: { + backgroundColor: '#F8F9FA', + borderRadius: 12, + padding: 12, + borderWidth: 1, + borderColor: '#E5E5EA', + }, + summaryTitle: { + fontSize: 13, + fontWeight: 'bold', + marginBottom: 6, + }, + summaryContent: { + fontSize: 12, + color: '#48484A', + marginBottom: 2, + }, + calendarContainer: { + borderWidth: 1, + borderColor: '#E5E5EA', + borderRadius: 12, + padding: 12, + }, + calendarMonth: { + fontSize: 14, + fontWeight: '600', + textAlign: 'center', + marginBottom: 12, + }, + weekLabels: { + flexDirection: 'row', + justifyContent: 'space-around', + marginBottom: 8, + }, + weekText: { + fontSize: 11, + color: '#8E8E93', + width: '14.28%', + textAlign: 'center', + }, + daysGrid: { + flexDirection: 'row', + flexWrap: 'wrap', + }, + dayCell: { + width: '14.28%', + height: 32, + justifyContent: 'center', + alignItems: 'center', + }, + dayText: { + fontSize: 13, + color: '#1C1C1E', + }, + pillsRow: { + flexDirection: 'row', + justifyContent: 'space-around', + paddingVertical: 8, + }, + mapMock: { + height: 180, + backgroundColor: '#E5E5EA', + borderRadius: 12, + justifyContent: 'center', + alignItems: 'center', + position: 'relative', + overflow: 'hidden', + }, + mapOverlay: { + position: 'absolute', + top: '50%', + left: '50%', + marginLeft: -10, + marginTop: -10, + }, + mapMarker: { + fontSize: 20, + }, + mapText: { + fontSize: 12, + color: '#8E8E93', + marginTop: 40, + }, + moreText: { + fontSize: 12, + color: '#8E8E93', + }, + facilityItem: { + flexDirection: 'row', + alignItems: 'center', + padding: 12, + borderWidth: 1, + borderColor: '#F2F2F7', + borderRadius: 12, + marginBottom: 8, + gap: 12, + }, + facilityIcon: { + fontSize: 24, + }, + facilityName: { + fontSize: 13, + fontWeight: '600', + color: '#1C1C1E', + }, + facilityDesc: { + fontSize: 11, + color: '#8E8E93', + }, + bottomTabBar: { + flexDirection: 'row', + justifyContent: 'space-around', + alignItems: 'center', + height: 64, + borderTopWidth: 1, + borderTopColor: '#F2F2F7', + backgroundColor: '#FFFFFF', + }, + tabItem: { + alignItems: 'center', + }, + tabIcon: { + fontSize: 20, + }, + tabLabel: { + fontSize: 10, + color: '#8E8E93', + marginTop: 2, + }, + activeTab: { + color: '#1C1C1E', + fontWeight: 'bold', + }, +}); \ No newline at end of file diff --git a/src/features/health/hooks/useHealthRecord.ts b/src/features/health/hooks/useHealthRecord.ts new file mode 100644 index 0000000..6b748ac --- /dev/null +++ b/src/features/health/hooks/useHealthRecord.ts @@ -0,0 +1,14 @@ +import { useState } from 'react'; +import { HealthData } from '../types/health'; + +export const useHealthRecord = () => { + const [data, setData] = useState({ bloodSugar: '', bloodPressure: '', weight: '' }); + + const updateField = (key: keyof HealthData, value: string) => { + setData((prev) => ({ ...prev, [key]: value })); + }; + + const reset = () => setData({ bloodSugar: '', bloodPressure: '', weight: '' }); + + return { data, updateField, reset }; +}; \ No newline at end of file diff --git a/src/features/health/styles/HealthStyles.ts b/src/features/health/styles/HealthStyles.ts new file mode 100644 index 0000000..1c7ac3f --- /dev/null +++ b/src/features/health/styles/HealthStyles.ts @@ -0,0 +1,11 @@ +import { StyleSheet } from 'react-native'; + +export const HealthStyles = StyleSheet.create({ + overlay: { flex: 1, backgroundColor: 'rgba(0,0,0,0.5)', justifyContent: 'center', alignItems: 'center' }, + modalContent: { width: '85%', padding: 20, backgroundColor: 'white', borderRadius: 15 }, + title: { fontSize: 20, fontWeight: 'bold', marginBottom: 5 }, + subtitle: { fontSize: 12, color: '#666', marginBottom: 15 }, + input: { borderWidth: 1, borderColor: '#ddd', borderRadius: 8, padding: 12, marginBottom: 15 }, + saveButton: { backgroundColor: '#FF8C00', padding: 15, borderRadius: 8, alignItems: 'center' }, + saveButtonText: { color: 'white', fontWeight: 'bold', fontSize: 16 } +}); \ No newline at end of file diff --git a/src/features/health/styles/ScheduleStyles.ts b/src/features/health/styles/ScheduleStyles.ts new file mode 100644 index 0000000..f9140e4 --- /dev/null +++ b/src/features/health/styles/ScheduleStyles.ts @@ -0,0 +1,24 @@ +import { StyleSheet } from 'react-native'; + +export const styles = StyleSheet.create({ + container: { flex: 1, backgroundColor: '#FFFFFF', padding: 20 }, + headerRow: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginTop: 10, marginBottom: 25 }, + titleGroup: { flexDirection: 'row', alignItems: 'center' }, + iconCalendar: { width: 16, height: 16, backgroundColor: '#FF7A00', borderRadius: 3, marginRight: 8 }, + textTitle: { color: '#333333', fontSize: 19, fontWeight: 'bold' }, + label: { color: '#333333', fontSize: 15, fontWeight: 'bold', marginBottom: 8, marginTop: 12 }, + input: { height: 48, borderWidth: 1, borderColor: '#EAEAEA', borderRadius: 6, paddingHorizontal: 12, fontSize: 14, color: '#333', marginBottom: 20 }, + pickerCard: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', backgroundColor: '#FFFFFF', borderWidth: 1, borderColor: '#F0F0F0', borderRadius: 16, paddingHorizontal: 15, height: 150, marginBottom: 25, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.04, shadowRadius: 5, elevation: 2 }, + wheel: { flex: 1, height: 130, backgroundColor: 'transparent' }, + colon: { fontSize: 18, fontWeight: 'bold', color: '#333', textAlign: 'center', width: 10 }, + voiceSettingContainer: { borderWidth: 1, borderColor: '#F0F0F0', borderRadius: 16, padding: 16, marginBottom: 25 }, + radioOption: { flexDirection: 'row', alignItems: 'center', marginTop: 12 }, + radioCircle: { width: 18, height: 18, borderRadius: 9, borderWidth: 2, borderColor: '#EAEAEA', marginRight: 10 }, + radioChecked: { borderColor: '#FF7A00', backgroundColor: '#FF7A00' }, + radioText: { fontSize: 14, color: '#333', fontWeight: '500' }, + voiceButtonContainer: { flexDirection: 'row', justifyContent: 'space-between', marginTop: 15 }, + voiceBtn: { flex: 1, height: 40, borderWidth: 1, borderColor: '#FF7A00', borderRadius: 8, backgroundColor: '#FFFFFF', alignItems: 'center', justifyContent: 'center', marginHorizontal: 4 }, + voiceBtnText: { color: '#FF7A00', fontSize: 13, fontWeight: 'bold' }, + btnSave: { height: 54, backgroundColor: '#FF7A00', borderRadius: 10, alignItems: 'center', justifyContent: 'center', marginTop: 5 }, + btnSaveText: { color: '#FFFFFF', fontSize: 16, fontWeight: 'bold' }, +}); \ No newline at end of file diff --git a/src/features/health/types/health.ts b/src/features/health/types/health.ts new file mode 100644 index 0000000..182e978 --- /dev/null +++ b/src/features/health/types/health.ts @@ -0,0 +1,5 @@ +export interface HealthData { + bloodSugar: string; + bloodPressure: string; + weight: string; +} \ No newline at end of file diff --git a/src/features/health/ui/HealthRecordModal.tsx b/src/features/health/ui/HealthRecordModal.tsx new file mode 100644 index 0000000..1d10240 --- /dev/null +++ b/src/features/health/ui/HealthRecordModal.tsx @@ -0,0 +1,39 @@ +import React from 'react'; +import { Modal, View, Text, TextInput, TouchableOpacity } from 'react-native'; +import { HealthStyles as styles } from '../styles/HealthStyles'; +import { useHealthRecord } from '../hooks/useHealthRecord'; + +interface Props { + visible: boolean; + onClose: () => void; + onSave: (data: any) => void; +} + +export const HealthRecordModal = ({ visible, onClose, onSave }: Props) => { + const { data, updateField, reset } = useHealthRecord(); + + const handleSave = () => { + onSave(data); + reset(); + onClose(); + }; + + return ( + + + + 오늘의 건강 기록하기 + 입력하신 수치는 보호자님 리포트에 반영됩니다. + + updateField('bloodSugar', v)} /> + updateField('bloodPressure', v)} /> + updateField('weight', v)} /> + + + 저장하기 + + + + + ); +}; \ No newline at end of file