이어서 InputMenuPage입니다.
식단 입력 페이지인데 이 부분은 어느정도 chatGPT의 도움을 받았기 때문에
리뷰를 해보려고 합니다.
U.I는 antd라는 프레임워크를 사용했습니다.
import React, { useState } from 'react';
import { Typography, Input, Form, Button, Select, message, Modal } from 'antd';
import styles from '../css/Button.css';
import '../css/InputPage.css';
function InputMenuPage({ }) {
const { Option } = Select;
// 각 요일에 해당하는 식단과 선택된 요일을 관리하는 state
const [weeklyMenu, setWeeklyMenu] = useState({
monday: [],
tuesday: [],
wednesday: [],
thursday: [],
friday: [],
saturday: [],
sunday: []
});
const [selectedDay, setSelectedDay] = useState('monday'); // 기본값은 월요일
const [inputValue, setInputValue] = useState('');
const [modalVisible, setModalVisible] = useState(false);
const onDescriptionChange = (event) => {
const { value } = event.target;
setInputValue(value);
};
const onDayChange = (value) => {
setSelectedDay(value);
};
const onSubmit = event => {
event.preventDefault();
const newMenu = inputValue.split(/[, ]+/).filter(item => item.trim() !== ''); // 쉼표 또는 공백으로 구분하여 입력값 처리
setWeeklyMenu(prevMenu => ({
...prevMenu,
[selectedDay]: [...prevMenu[selectedDay], ...newMenu]
}));
setInputValue('');
const formattedMenu = newMenu.join(', '); // 등록된 식단을 쉼표로 구분하여 표시
message.success(`${selectedDay.charAt(0).toUpperCase() + selectedDay.slice(1)}에 다음 식단이 추가되었습니다: ${formattedMenu}`);
};
const deleteMenu = (day) => {
setWeeklyMenu(prevMenu => ({
...prevMenu,
[day]: []
}));
message.success(`${day.charAt(0).toUpperCase() + day.slice(1)}의 식단이 삭제되었습니다.`);
};
const showModal = () => {
setModalVisible(true);
};
const handleCancel = () => {
setModalVisible(false);
};
return (
<div className='inputPage' style={{ backgroundColor: 'beige', display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100vh' }}>
<div style={{ maxWidth: '700px', background: 'white', padding: '40px', borderRadius: '20px' }}>
<div className='input-logo2'>식단 정보</div>
<Form onSubmit={onSubmit}>
{/* 요일 선택 */}
<Form.Item label="요일">
<Select defaultValue="monday" onChange={onDayChange}>
<Option value="monday">월요일</Option>
<Option value="tuesday">화요일</Option>
<Option value="wednesday">수요일</Option>
<Option value="thursday">목요일</Option>
<Option value="friday">금요일</Option>
<Option value="saturday">토요일</Option>
<Option value="sunday">일요일</Option>
</Select>
</Form.Item>
{/* 선택된 요일에 대한 식단 입력 폼 */}
<Form.Item label="식단">
<Input
onChange={onDescriptionChange}
value={inputValue}
/>
</Form.Item>
<div style={{ textAlign: 'center' }}>
<Button className={`${styles.btn} }`} onClick={onSubmit}>
등록하기
</Button>
<Button onClick={showModal} style={{ marginLeft: '10px' }}>등록된 식단 </Button>
</div>
</Form>
</div>
<Modal
title="등록된 식단"
visible={modalVisible}
onCancel={handleCancel}
footer={[
<Button key="back" onClick={handleCancel}>닫기</Button>
]}
>
{Object.keys(weeklyMenu).map(day => (
<div key={day}>
<p>{day.charAt(0).toUpperCase() + day.slice(1)}: {weeklyMenu[day].join(', ')}</p>
<Button onClick={() => deleteMenu(day)} type="default">식단 삭제</Button>
</div>
))}
</Modal>
</div>
);
}
export default InputMenuPage;
코드입니다.
각 요일별로 복수의 식단을 입력 받아야하는데 입력 받을 때 쉼표와 공백을 기준으로 입력받아야 합니다.
먼저 각 요일별로 state를 만들어 줍니다.
const [weeklyMenu, setWeeklyMenu] = useState({
monday: [],
tuesday: [],
wednesday: [],
thursday: [],
friday: [],
saturday: [],
sunday: []
});
state는 식단을 여러 개 입력 받아야 하므로 배열로 만들어 줍니다.
const onDescriptionChange = (event) => {
const { value } = event.target;
setInputValue(value);
};
const onDayChange = (value) => {
setSelectedDay(value);
};
그리고 식단과 요일의 상태변경 함수를 만들어 줍니다.
const onSubmit = event => {
event.preventDefault();
const newMenu = inputValue.split(/[, ]+/).filter(item => item.trim() !== ''); // 쉼표 또는 공백으로 구분하여 입력값 처리
setWeeklyMenu(prevMenu => ({
...prevMenu,
[selectedDay]: [...prevMenu[selectedDay], ...newMenu]
}));
setInputValue('');
const formattedMenu = newMenu.join(', '); // 등록된 식단을 쉼표로 구분하여 표시
message.success(`${selectedDay.charAt(0).toUpperCase() + selectedDay.slice(1)}에 다음 식단이 추가되었습니다: ${formattedMenu}`);
};
쉼표와 공백으로 단어를 구분하는 작업은 onSubmit에서 이뤄집니다.
파이썬에서만 보던 split함수를 Javascript에서도 쓰더군요.
공백을 기준으로 문자열을 나눠주는 함수입니다.
newMenu에서는
- split(/[, ]+/): inputValue 문자열을 정규 표현식 /[, ]+/에 따라 분할합니다. 이 정규 표현식은 쉼표 또는 공백을 기준으로 분할합니다.
- filter(item => item.trim() !== ''): 앞서 분할된 배열에서 각 요소에 대해 trim() 메서드를 사용하여 양쪽의 공백을 제거한 후, 그 결과가 빈 문자열이 아닌 요소들로 이루어진 새로운 배열을 생성합니다.
그리고 이것을 setWeeklyMenu를 통해서 이전에 있던 메뉴에 더해서 삽입해줍니다.
const formattedMenu = newMenu.join(', ');
여기서는 모달에 쉼표로 메뉴들이 보이게끔 새로운 변수에 메뉴룰 저장합니다.
const deleteMenu = (day) => {
setWeeklyMenu(prevMenu => ({
...prevMenu,
[day]: []
}));
message.success(`${day.charAt(0).toUpperCase() + day.slice(1)}의 식단이 삭제되었습니다.`);
};
여기서는 메뉴를 삭제하는 작업을 합니다.
배열의 내용을 삭제하고 삭제 메세지를 출력합니다.
const showModal = () => {
setModalVisible(true);
};
const handleCancel = () => {
setModalVisible(false);
};
ModalVisible이라는 함수를 통해서 Modal의 스위치 역할을 합니다.
return (
<div className='inputPage' style={{ backgroundColor: 'beige', display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100vh' }}>
<div style={{ maxWidth: '700px', background: 'white', padding: '40px', borderRadius: '20px' }}>
<div className='input-logo2'>식단 정보</div>
<Form onSubmit={onSubmit}>
{/* 요일 선택 */}
<Form.Item label="요일">
<Select defaultValue="monday" onChange={onDayChange}>
<Option value="monday">월요일</Option>
<Option value="tuesday">화요일</Option>
<Option value="wednesday">수요일</Option>
<Option value="thursday">목요일</Option>
<Option value="friday">금요일</Option>
<Option value="saturday">토요일</Option>
<Option value="sunday">일요일</Option>
</Select>
</Form.Item>
{/* 선택된 요일에 대한 식단 입력 폼 */}
<Form.Item label="식단">
여기서는 요일별로 선택할 수 있는 Select BOX를 생성합니다.
<Form.Item label="식단">
<Input
onChange={onDescriptionChange}
value={inputValue}
/>
</Form.Item>
<div style={{ textAlign: 'center' }}>
<Button className={`${styles.btn} }`} onClick={onSubmit}>
등록하기
</Button>
<Button onClick={showModal} style={{ marginLeft: '10px' }}>등록된 식단 </Button>
</div>
</Form>
식단을 입력하는 Input 상자와
등록하기, 등록된 식단 버튼을 생성합니다.
<Modal
title="등록된 식단"
visible={modalVisible}
onCancel={handleCancel}
footer={[
<Button key="back" onClick={handleCancel}>닫기</Button>
]}
>
{Object.keys(weeklyMenu).map(day => (
<div key={day}>
<p>{day.charAt(0).toUpperCase() + day.slice(1)}: {weeklyMenu[day].join(', ')}</p>
<Button onClick={() => deleteMenu(day)} type="default">식단 삭제</Button>
</div>
))}
</Modal>
antd의 Modal 컴포넌트를 사용해서 상태창을 띄웁니다.
여기서는 요일별로 메뉴를 보여주고 식단 삭제 버튼을 통해서 삭제할 수 있습니다.
식단 정보 입력 폼
뭔가 입력창만 있는 것이 휑해서 디자인을 다시 고려해 봐야할 것 같습니다.
식단 Modal
이 부분도 버튼의 위치를 조정할 필요가 있을 것 같습니다.
다음 시간에는 U.I를 개선하고 새로운 페이지를 만들어보겠습니다.
읽어주셔서 감사합니다!