11import React , { useState } from "react" ;
22import "./style.css" ;
33
4- const CATEGORIES = [ "육류" , "채소류" , "가공류" , "유제품" , "기타" ] ;
4+ // 카테고리 상수는 제거하거나, 백엔드 전송용으로 내부에서만 기본값 처리하면 됩니다.
55
66export const AddIngredientPopup = ( { onClose, onAdd } ) => {
7- const [ name , setName ] = useState ( "" ) ;
8- const [ category , setCategory ] = useState ( "채소류" ) ;
9- const [ expiryDays , setExpiryDays ] = useState ( "" ) ;
10-
11- // 영수증 분석(1단계) 완료 여부를 체크하는 상태
127 const [ isReceiptProcessed , setIsReceiptProcessed ] = useState ( false ) ;
8+ const [ items , setItems ] = useState ( [ ] ) ;
139
14- const handleSubmit = ( e ) => {
10+ // 1단계: 영수증 분석 시뮬레이션
11+ const handleAnalyzeReceipt = ( e ) => {
1512 e . preventDefault ( ) ;
13+ console . log ( "영수증 분석 시작..." ) ;
1614
17- // 1단계: 영수증 등록 버튼을 눌렀을 때 (아직 분석 결과가 안 나왔을 때)
18- if ( ! isReceiptProcessed ) {
19- // TODO: 백엔드로 영수증 이미지를 보내고 분석 결과를 받아오는 로직이 들어갈 자리
20- console . log ( "영수증 분석 시작..." ) ;
21-
22- // [가상 시나리오] 백엔드에서 분석된 결과가 자동으로 채워진다고 가정
23- // setName("분석된 양파");
24- // setExpiryDays("7");
25-
26- setIsReceiptProcessed ( true ) ; // 입력 필드를 보여주도록 상태 변경
27- return ;
28- }
29-
30- // 2단계: 최종 등록 버튼을 눌렀을 때
31- if ( ! name || ! expiryDays ) {
32- alert ( "모든 필드를 입력해주세요." ) ;
33- return ;
34- }
15+ const mockAnalyzedData = [
16+ { id : 1 , name : "양파" , expiryDays : 7 } ,
17+ { id : 2 , name : "삼겹살" , expiryDays : 3 } ,
18+ { id : 3 , name : "우유" , expiryDays : 10 } ,
19+ { id : 4 , name : "종량제봉투" , expiryDays : 0 } ,
20+ ] ;
21+
22+ setItems ( mockAnalyzedData ) ;
23+ setIsReceiptProcessed ( true ) ;
24+ } ;
25+
26+ const handleItemChange = ( id , field , value ) => {
27+ setItems ( items . map ( item =>
28+ item . id === id ? { ...item , [ field ] : value } : item
29+ ) ) ;
30+ } ;
31+
32+ const handleDeleteItem = ( id ) => {
33+ setItems ( items . filter ( item => item . id !== id ) ) ;
34+ } ;
3535
36- const newIngredient = {
36+ const handleAddItem = ( ) => {
37+ const newItem = {
3738 id : Date . now ( ) ,
38- name,
39- category,
40- expiryDays : parseInt ( expiryDays ) ,
41- image : "https://c.animaapp.com/sjWITF5i/img/ingredientimage-7@2x.png"
39+ name : "" ,
40+ expiryDays : ""
4241 } ;
42+ setItems ( [ ...items , newItem ] ) ;
43+ } ;
44+
45+ const handleFinalSubmit = ( ) => {
46+ const isValid = items . every ( item => item . name && item . expiryDays !== "" ) ;
47+ if ( ! isValid ) {
48+ alert ( "모든 재료의 정보를 입력해주세요." ) ;
49+ return ;
50+ }
51+
52+ items . forEach ( item => {
53+ onAdd ( {
54+ ...item ,
55+ category : "기타" , // 백엔드에서 필요하다면 기본값으로 '기타'나 '미분류' 전송
56+ expiryDays : parseInt ( item . expiryDays ) ,
57+ image : "https://c.animaapp.com/sjWITF5i/img/ingredientimage-7@2x.png"
58+ } ) ;
59+ } ) ;
4360
44- // TODO: Send to backend
45- console . log ( "Adding ingredient via receipt:" , newIngredient ) ;
46- onAdd ( newIngredient ) ;
4761 onClose ( ) ;
4862 } ;
4963
@@ -53,68 +67,75 @@ export const AddIngredientPopup = ({ onClose, onAdd }) => {
5367 < button className = "add-ingredient-popup-close" onClick = { onClose } > ×</ button >
5468
5569 < div className = "add-ingredient-popup-header" >
56- < h2 className = "add-ingredient-popup-title" > 영수증 등록</ h2 >
70+ < h2 className = "add-ingredient-popup-title" >
71+ { isReceiptProcessed ? "분석 결과 확인" : "영수증 등록" }
72+ </ h2 >
5773 </ div >
5874
59- < form className = "add-ingredient-popup-form" onSubmit = { handleSubmit } >
60- < div className = "add-ingredient-popup-input-group" >
61- < label className = "add-ingredient-popup-label" > 영수증</ label >
62- < input
63- type = "file"
64- className = "add-ingredient-popup-input"
65- required = { ! isReceiptProcessed } // 분석 전에는 필수 입력
66- disabled = { isReceiptProcessed } // 분석 후에는 수정 불가 (선택 사항)
67- />
68- </ div >
69-
70- { /* isReceiptProcessed가 true일 때만 아래 내용 표시 백앤드에서 분석한 결과 표시해주는 곳 사용자 확인용 마음에 안들면 여기서 수정가능 */ }
71- { isReceiptProcessed && (
72- < >
73- < div className = "add-ingredient-popup-input-group" >
74- < label className = "add-ingredient-popup-label" > 재료명</ label >
75- < input
76- type = "text"
77- className = "add-ingredient-popup-input"
78- value = { name }
79- onChange = { ( e ) => setName ( e . target . value ) }
80- placeholder = "예: 양파"
81- required
82- />
83- </ div >
84-
85- < div className = "add-ingredient-popup-input-group" >
86- < label className = "add-ingredient-popup-label" > 카테고리</ label >
87- < select
88- className = "add-ingredient-popup-select"
89- value = { category }
90- onChange = { ( e ) => setCategory ( e . target . value ) }
91- required
92- >
93- { CATEGORIES . map ( ( cat ) => (
94- < option key = { cat } value = { cat } > { cat } </ option >
95- ) ) }
96- </ select >
97- </ div >
75+ { ! isReceiptProcessed ? (
76+ < form className = "add-ingredient-popup-form" onSubmit = { handleAnalyzeReceipt } >
77+ < div className = "add-ingredient-popup-input-group" >
78+ < label className = "add-ingredient-popup-label" > 영수증 업로드</ label >
79+ < input
80+ type = "file"
81+ className = "add-ingredient-popup-input file-input"
82+ accept = "image/*"
83+ required
84+ />
85+ < p className = "helper-text" > 선명한 영수증 사진을 올려주세요.</ p >
86+ </ div >
87+ < button type = "submit" className = "add-ingredient-popup-submit-btn" >
88+ 분석 시작
89+ </ button >
90+ </ form >
91+ ) : (
92+ < div className = "processed-list-container" >
93+ { /* 카테고리 헤더 삭제 */ }
94+ < div className = "processed-list-header" >
95+ < span style = { { flex : 3 } } > 재료명</ span >
96+ < span style = { { flex : 1 , textAlign : 'center' } } > 기한(일)</ span >
97+ < span style = { { width : '28px' } } > </ span > { /* 삭제버튼 자리 */ }
98+ </ div >
99+
100+ < div className = "processed-list-body" >
101+ { items . map ( ( item ) => (
102+ < div key = { item . id } className = "processed-item-row" >
103+ { /* 카테고리 Select 삭제, 이름 입력창 확장 */ }
104+ < input
105+ type = "text"
106+ className = "item-input name-input"
107+ value = { item . name }
108+ onChange = { ( e ) => handleItemChange ( item . id , "name" , e . target . value ) }
109+ placeholder = "재료명"
110+ />
111+
112+ < input
113+ type = "number"
114+ className = "item-input date-input"
115+ value = { item . expiryDays }
116+ onChange = { ( e ) => handleItemChange ( item . id , "expiryDays" , e . target . value ) }
117+ placeholder = "일"
118+ />
119+ < button
120+ className = "item-delete-btn"
121+ onClick = { ( ) => handleDeleteItem ( item . id ) }
122+ title = "삭제"
123+ >
124+ −
125+ </ button >
126+ </ div >
127+ ) ) }
128+
129+ < button className = "add-row-btn" onClick = { handleAddItem } >
130+ + 직접 추가하기
131+ </ button >
132+ </ div >
98133
99- < div className = "add-ingredient-popup-input-group" >
100- < label className = "add-ingredient-popup-label" > 유통기한 (일)</ label >
101- < input
102- type = "number"
103- className = "add-ingredient-popup-input"
104- value = { expiryDays }
105- onChange = { ( e ) => setExpiryDays ( e . target . value ) }
106- placeholder = "예: 7"
107- min = "1"
108- required
109- />
110- </ div >
111- </ >
112- ) }
113-
114- < button type = "submit" className = "add-ingredient-popup-submit-btn" >
115- { isReceiptProcessed ? "최종 등록" : "추가하기" }
116- </ button >
117- </ form >
134+ < button onClick = { handleFinalSubmit } className = "add-ingredient-popup-submit-btn" >
135+ { items . length } 개 재료 등록하기
136+ </ button >
137+ </ div >
138+ ) }
118139 </ div >
119140 </ div >
120141 ) ;
0 commit comments