diff --git a/src/app/navigation/RootNavigator.tsx b/src/app/navigation/RootNavigator.tsx
index d80e042..5038f5d 100644
--- a/src/app/navigation/RootNavigator.tsx
+++ b/src/app/navigation/RootNavigator.tsx
@@ -3,6 +3,7 @@ import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { useSessionStore } from '@shared/store/useSessionStore';
import LoginScreen from '@screens/auth/Login/LoginScreen';
import SignupScreen from '@screens/auth/Signup/SignupScreen';
+import TermsAgreementScreen from '@screens/auth/terms/TermsAgreementScreen';
import { LinkAccountScreen } from '@screens/auth/LinkAccount/LinkAccountScreen';
import { GuardianStackNavigator } from './GuardianStackNavigator';
import { SeniorHomeScreen } from '@screens/senior/Home/SeniorHomeScreen';
@@ -31,7 +32,8 @@ export function RootNavigator() {
+
);
-}
+}
\ No newline at end of file
diff --git a/src/screens/auth/terms/CaringLogo.tsx b/src/screens/auth/terms/CaringLogo.tsx
new file mode 100644
index 0000000..4f3f8a4
--- /dev/null
+++ b/src/screens/auth/terms/CaringLogo.tsx
@@ -0,0 +1,86 @@
+import React from 'react';
+import { View, StyleSheet } from 'react-native';
+import Svg, { Circle, Path, Rect, G, Defs, Pattern, Use, Filter, FeFlood, FeColorMatrix, FeOffset, FeGaussianBlur, FeComposite, FeBlend, LinearGradient, Stop, Image as SvgImage } from 'react-native-svg';
+
+export function CaringLogo() {
+ return (
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ alignItems: 'center',
+ justifyContent: 'center',
+ marginBottom: 8,
+ },
+});
\ No newline at end of file
diff --git a/src/screens/auth/terms/TermsAgreement.styles.ts b/src/screens/auth/terms/TermsAgreement.styles.ts
new file mode 100644
index 0000000..7d9dba6
--- /dev/null
+++ b/src/screens/auth/terms/TermsAgreement.styles.ts
@@ -0,0 +1,112 @@
+import { StyleSheet } from 'react-native';
+
+export const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: '#FFFFFF',
+ paddingHorizontal: 24,
+ paddingTop: 60,
+ },
+ headerContainer: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ width: '100%',
+ marginBottom: 24,
+ position: 'relative',
+ },
+ titleContainer: {
+ position: 'absolute',
+ left: 0,
+ right: 0,
+ alignItems: 'center',
+ zIndex: 1,
+ },
+ /* π λ‘κ³ λ₯Ό κ°μΈκΈ° μν΄ μΆκ°λ μ€νμΌ */
+ logoContainer: {
+ alignItems: 'center',
+ marginBottom: 24,
+ },
+ title: {
+ fontSize: 20,
+ fontWeight: 'bold',
+ color: '#000000',
+ },
+ subtitle: {
+ fontSize: 14,
+ color: '#666666',
+ marginBottom: 24,
+ },
+ allAgreeBox: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ backgroundColor: '#F5F6F8',
+ padding: 16,
+ borderRadius: 12,
+ marginBottom: 24,
+ // μ 체 λ°μ€ ν
λ리 μ κ±°λ¨
+ },
+ allAgreeText: {
+ fontSize: 16,
+ fontWeight: 'bold',
+ color: '#000000',
+ marginLeft: 12,
+ },
+ sectionTitle: {
+ fontSize: 14,
+ fontWeight: '600',
+ color: '#888888',
+ marginBottom: 12,
+ marginTop: 12,
+ },
+ termItem: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ paddingVertical: 12,
+ // κ°λ³ λ°μ€ ν
λ리 μ κ±°λ¨
+ },
+ termText: {
+ fontSize: 15,
+ color: '#333333',
+ marginLeft: 12,
+ },
+ required: {
+ color: '#FF7E00',
+ },
+ /* νΌκ·Έλ§μ λμΌν λΉμ¨/ν¬κΈ°μ 체ν¬λ°μ€ μ€νμΌ */
+ checkbox: {
+ width: 22,
+ height: 22,
+ borderRadius: 4,
+ borderWidth: 1,
+ borderColor: '#DDDDDD',
+ backgroundColor: '#FFFFFF',
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ checkboxChecked: {
+ borderColor: '#FF7E00', // 체ν¬λμμ λλ§ ν
λλ¦¬κ° μ£Όν©μ
+ backgroundColor: '#FFF9F5',
+ },
+ checkmark: {
+ color: '#FF7E00',
+ fontSize: 12,
+ fontWeight: 'bold',
+ },
+ nextButton: {
+ backgroundColor: '#FF7E00',
+ height: 56,
+ borderRadius: 12,
+ justifyContent: 'center',
+ alignItems: 'center',
+ marginTop: 20,
+ marginBottom: 30,
+ },
+ nextButtonDisabled: {
+ backgroundColor: '#DDDDDD',
+ },
+ nextButtonText: {
+ fontSize: 16,
+ fontWeight: 'bold',
+ color: '#FFFFFF',
+ },
+});
\ No newline at end of file
diff --git a/src/screens/auth/terms/TermsAgreementScreen.tsx b/src/screens/auth/terms/TermsAgreementScreen.tsx
new file mode 100644
index 0000000..ea13240
--- /dev/null
+++ b/src/screens/auth/terms/TermsAgreementScreen.tsx
@@ -0,0 +1,48 @@
+import React from 'react';
+import { View, Text, TouchableOpacity, ScrollView } from 'react-native';
+import { useTermsAgreement, TERM_LIST } from './useTermsAgreement';
+import { styles } from './TermsAgreement.styles';
+import { CaringLogo } from './CaringLogo';
+
+export default function TermsAgreementScreen({ navigation }: any) {
+ const { checkedItems, isAllChecked, isRequiredChecked, handleCheckItem, handleCheckAll } = useTermsAgreement();
+
+ return (
+
+
+
+
+
+ μλΉμ€ μ΄μ©μ μν΄{'\n'}μ½κ΄μ λμν΄ μ£ΌμΈμ.
+
+ {/* μ 체 λμ λ²νΌ (μ€νμΌ μ΄λ¦μ allAgreeBoxλ‘ μμ ) */}
+
+ λͺ¨λ μ½κ΄μ λμν©λλ€.
+
+
+ {/* κ°λ³ μ½κ΄ λͺ©λ‘ */}
+ {TERM_LIST.map(term => (
+ handleCheckItem(term.id)}
+ >
+
+ {term.required ? '[νμ]' : '[μ ν]'} {term.title} {checkedItems[term.id] ? 'β' : ''}
+
+
+ ))}
+
+ {/* λ€μ λ²νΌ */}
+ {
+ navigation.navigate('Signup');
+ }}
+ >
+ λ€μ
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/screens/auth/terms/types.ts b/src/screens/auth/terms/types.ts
new file mode 100644
index 0000000..092f793
--- /dev/null
+++ b/src/screens/auth/terms/types.ts
@@ -0,0 +1,5 @@
+export interface TermItem {
+ id: string;
+ title: string;
+ required: boolean;
+}
\ No newline at end of file
diff --git a/src/screens/auth/terms/useTermsAgreement.ts b/src/screens/auth/terms/useTermsAgreement.ts
new file mode 100644
index 0000000..59ecc77
--- /dev/null
+++ b/src/screens/auth/terms/useTermsAgreement.ts
@@ -0,0 +1,45 @@
+import { useState } from 'react';
+import { TermItem } from './types';
+
+export const TERM_LIST: TermItem[] = [
+ { id: 'service', title: 'μλΉμ€ μ΄μ©μ½κ΄ λμ', required: true },
+ { id: 'privacy', title: 'κ°μΈμ 보 μμ§ λ° μ΄μ© λμ', required: true },
+ { id: 'location', title: 'μμΉκΈ°λ° μλΉμ€ μ΄μ©μ½κ΄ λμ', required: true },
+ { id: 'thirdParty', title: 'κ°μΈμ 보 μ 3μ μ 곡 λμ', required: true },
+ { id: 'marketing', title: 'λ§μΌν
μ 보 μμ λμ', required: false },
+ { id: 'optionalPrivacy', title: 'κ°μΈμ 보 μ ν μμ§ λμ', required: false },
+ { id: 'voice', title: 'μμ± λ°μ΄ν° μμ§ λ° μ΄μ© λμ', required: false },
+];
+
+export const useTermsAgreement = () => {
+ const [checkedItems, setCheckedItems] = useState<{ [key: string]: boolean }>({});
+
+ const isAllChecked = TERM_LIST.every((item) => checkedItems[item.id]);
+ const isRequiredChecked = TERM_LIST
+ .filter((item) => item.required)
+ .every((item) => checkedItems[item.id]);
+
+ const handleCheckItem = (id: string) => {
+ setCheckedItems((prev) => ({
+ ...prev,
+ [id]: !prev[id],
+ }));
+ };
+
+ const handleCheckAll = () => {
+ const nextValue = !isAllChecked;
+ const newCheckedItems: { [key: string]: boolean } = {};
+ TERM_LIST.forEach((item) => {
+ newCheckedItems[item.id] = nextValue;
+ });
+ setCheckedItems(newCheckedItems);
+ };
+
+ return {
+ checkedItems,
+ isAllChecked,
+ isRequiredChecked,
+ handleCheckItem,
+ handleCheckAll,
+ };
+};
\ No newline at end of file