계획 입력 및 관리 화면 개발
기능 개요
PlanManagementScreen은 사용자가 운동 계획과 약물 복용 계획을 입력하고 관리할 수 있는 화면입니다. 다음 두 종류의 계획을 지원합니다:
- 운동 계획: 시작일과 종료일 + 일일 운동 시간(분 단위) + 세부 내용
- 약물 계획: 시작일과 종료일 + 복용 용량(문자열) + 세부 내용
사용자가 입력한 계획은 로컬 AsyncStorage에 저장되어 영구적으로 보존되며, 메인 화면(Dashboard)에서 당일에 실행해야 할 계획을 표시합니다. 또한 계획 삭제 기능을 제공하여 사용자가 일정을 쉽게 업데이트할 수 있습니다.
사용 기술 및 의존성
React Native프레임워크useState컴포넌트 상태 관리useEffect초기 데이터 로딩AsyncStorage로컬 데이터 저장- 서비스 모듈:
planDataService.ts
컴포넌트 상태 변수 구조
const [workoutStartDate, setWorkoutStartDate] = useState('');
const [workoutEndDate, setWorkoutEndDate] = useState('');
const [workoutTime, setWorkoutTime] = useState('');
const [workoutDetails, setWorkoutDetails] = useState('');
사용자가 입력한 운동 정보를 관리하는 상태 변수들입니다.
const [medicationStartDate, setMedicationStartDate] = useState('');
const [medicationEndDate, setMedicationEndDate] = useState('');
const [dosageInfo, setDosageInfo] = useState('');
const [medicationDetails, setMedicationDetails] = useState('');
위 변수들은 약물 계획 입력 필드를 관리합니다.
const [savedWorkouts, setSavedWorkouts] = useState<WorkoutPlan[]>([]);
const [savedMedications, setSavedMedications] = useState<MedicationPlan[]>([]);
이 두 상태 변수는 화면에 표시되고 삭제할 수 있는 모든 저장된 계획을 보관합니다.
⏳ 초기 데이터 로딩 로직
useEffect(() => {
const loadData = async () => {
const workoutData = await fetchWorkoutPlans();
const medicationData = await fetchMedicationPlans();
setSavedWorkouts(workoutData);
setSavedMedications(medicationData);
};
loadData();
}, []);
화면이 처음 로드될 때, planDataService.ts에 정의된 메서드를 통해 로컬 저장소에 보관된 운동 및 약물 계획을 JSON 배열 형태로 가져옵니다.
제출 및 로컬 저장 로직
const processFormSubmission = async () => {
const updatedWorkouts = workoutDetails && workoutTime
? [...savedWorkouts, {
startDate: workoutStartDate,
endDate: workoutEndDate,
duration: Number(workoutTime),
content: workoutDetails
}] : savedWorkouts;
const updatedMedications = medicationDetails && dosageInfo
? [...savedMedications, {
startDate: medicationStartDate,
endDate: medicationEndDate,
dosage: dosageInfo,
content: medicationDetails
}] : savedMedications;
await persistWorkoutPlans(updatedWorkouts);
await persistMedicationPlans(updatedMedications);
...
};
- 제출 로직은 필수 입력값이 채워져 있을 경우에만 새 계획을 추가하도록 유효성 검사를 수행합니다.
- 기존 배열에 새 계획을 추가하는 방식으로 저장됩니다.
- 모든 저장 작업은
planDataService.ts의persistWorkoutPlans와persistMedicationPlans메서드를 호출합니다.
계획 항목 삭제 기능
const removePlanItem = async (planType: 'workout' | 'medication', itemIndex: number) => {
const currentPlans = [...(planType === 'workout' ? savedWorkouts : savedMedications)];
currentPlans.splice(itemIndex, 1);
if (planType === 'workout') {
setSavedWorkouts(currentPlans);
await persistWorkoutPlans(currentPlans);
} else {
setSavedMedications(currentPlans);
await persistMedicationPlans(currentPlans);
}
};
"삭제" 버튼을 탭하면 해당 계획 항목이 즉시 삭제되고 로컬 저장소도 동기화됩니다.
입력 폼 표시 구조
화면 레이아웃은 ScrollView를 사용하며, 입력 필드는 TextInput 컴포넌트로 구현됩니다:
<TextInput placeholder="일일 운동 시간(분)" style={styles.input} keyboardType="numeric" value={workoutTime} onChangeText={setWorkoutTime} />
각 입력 필드는 해당 상태 변수와 연결되어 입력 시 상태가 업데이트됩니다. 하단에 제출 버튼이 배치됩니다.
저장된 계획 표시
{savedWorkouts.map((plan, index) => (
<View key={index} style={styles.planCard}>
<Text>{plan.startDate} ~ {plan.endDate} - 매일 {plan.duration}분 - {plan.content}</Text>
<TouchableOpacity onPress={() => removePlanItem('workout', index)}>
<Text style={styles.removeButton}>삭제</Text>
</TouchableOpacity>
</View>
))}
- 각 계획 항목은 기간, 운동 시간/약물 용량, 세부 내용을 표시합니다.
- 삭제 버튼은 빨간색 텍스트로 표시되며, 탭 시
removePlanItem함수를 호출합니다.
스타일링 개요
planCard: {
backgroundColor: '#f5f5f5',
borderRadius: 8,
padding: 12,
marginVertical: 8,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
리스트 항목은 연한 회색 배경과 둥근 모서리를 가진 카드 스타일로, 텍스트와 "삭제" 버튼이 좌우로 배치되어 깔끔하고 직관적인 디자인을 제공합니다.