Notice
Recent Posts
Recent Comments
Link
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

오늘도 코딩하나

[moneybook]_day3 본문

React/Daily

[moneybook]_day3

오늘도 코딩하나 2024. 8. 24. 23:52

1. 추가입력란 disabled

let [disabledItems, setDisabledItems] = useState([]);

// 입력란 추가 로직에 checkbox disabled 추가
  useEffect(() => {
    const empty = tempData.filter((item) => item.date !== undefined && item.date !== '');
    if(empty.length === tempData.length) {
      setTempData([...tempData, {id:tempData.length}]);
      setDisabledItems([...disabledItems, tempData.length]);
    }
  }, [tempData])

 

2. 엔터를 치면 초기값 세팅

어제 작성했던 소스 중 handleDate 부분에 price1, price2 초기값 세팅하는 것과

checkbox disabled 해제하는 소스코드를 작성했다.

const setInitial = (item) => {
    const today = new Date();
    const date = `${today.getFullYear()}-${String(today.getMonth()+1).padStart(2,'0')}-${today.getDate()}`;
    if(disabledItems.includes(item.id)) {
      const newDate = tempData.map((i) =>
        i.id === item.id ? {...i, ['date']:date, ['price1']:0, ['price2']:0} : i
      )
      setTempData(newDate);
      setDisabledItems(disabledItems.filter(itemId => itemId !== item.id));
    }
  }

 

 

3. 저장하기 버튼을 눌렀을 때만 내용 저장되게

기존에는 값을 수정하면 바로 반영이 되게 했었는데,

원본데이터에 대한 복제데이터를 만들고, 복제데이터에 CRUD에 대한 작업을 모두 하고

저장하기 버튼을 클릭했을때 복제데이터를 원본데이터에 덮어씌우는 방식으로 작업했다.

let payList = createSlice({
    name : 'payList',
    initialState,
    reducers : {
        updatePayList(state, action) {
            return action.payload;
        }
    }
})

export let { updatePayList } = payList.actions;
let payList = useSelector((state) => state.payList);
const [tempData, setTempData] = useState(payList);

// 입력란 추가
useEffect(() => {
    const empty = tempData.filter((item) => item.date !== undefined && item.date !== '');
    if(empty.length === tempData.length) {
      setTempData([...tempData, {id:tempData.length}]);
      setDisabledItems([...disabledItems, tempData.length]);
    }
}, [tempData])
  
// 데이터 수정
const handleUpdate = (id, key, event) => {
    let newItem = event.target.innerText;

    if(key === 'price1' || key === 'price2') {
      if(newItem.trim() === '') {
        newItem = 0;
        event.target.innerText = '0';
      }
	}

    const newData = tempData.map((item) =>
      item.id === id ? { ...item, [key]: newItem } : item
    )
    setTempData(newData);
}

// 삭제
const handleDelete = () => {
    const remains = tempData.filter(item => !checkedItems.includes(item.id));
    setTempData(remains);
}

return (
	<Button variant="primary" size="lg" onClick={()=>dispatch(updatePayList(tempData))} >저장하기</Button>
)

 

 

4. 엔터를 치면 수정 후 다음으로 이동

useRef()를 활용했다.

const inputRefs = useRef([]);

// Enter 입력
const handleKeyDown = (e, i) => {
    if(e.key === 'Enter') {
      // 엔터로 줄바꿈 방지
      e.preventDefault();
      if(inputRefs.current[i]) {
        inputRefs.current[i].focus();
      }
    }
}

return (
	{tempData.map((item,i) => (
        <tr key={i}>
          <td><input type="checkbox" checked={checkedItems.includes(item.id)} onChange={() => handleCheck(item.id)} disabled={disabledItems.includes(item.id)} /></td>
          <Input ref={el => inputRefs.current[i * 7 + 0] = el} onBlur={(e) => handleUpdate(item.id, 'date', e)} onKeyDown={(e) => handleKeyDown(e, (i+1)*7+0)} onClick={()=>setInitial(item)} onKeyUp={()=>setInitial(item)}>{item.date}</Input>
          <Input ref={el => inputRefs.current[i * 7 + 1] = el} onBlur={(e) => handleUpdate(item.id, 'group1', e)} onKeyDown={(e) => handleKeyDown(e, (i+1)*7+1)} onClick={()=>setInitial(item)} onKeyUp={()=>setInitial(item)}>{item.group1}</Input>
          <Input ref={el => inputRefs.current[i * 7 + 2] = el} onBlur={(e) => handleUpdate(item.id, 'group2', e)} onKeyDown={(e) => handleKeyDown(e, (i+1)*7+2)} onClick={()=>setInitial(item)} onKeyUp={()=>setInitial(item)}>{item.group2}</Input>
          <Input ref={el => inputRefs.current[i * 7 + 3] = el} onBlur={(e) => handleUpdate(item.id, 'price1', e)} onKeyDown={(e) => handleKeyDown(e, (i+1)*7+3)} onClick={()=>setInitial(item)} onKeyUp={()=>setInitial(item)}>{!isNaN(item.price1) ? Number(item.price1).toLocaleString('ko-KR') : item.price1}</Input>
          <Input ref={el => inputRefs.current[i * 7 + 4] = el} onBlur={(e) => handleUpdate(item.id, 'price2', e)} onKeyDown={(e) => handleKeyDown(e, (i+1)*7+4)} onClick={()=>setInitial(item)} onKeyUp={()=>setInitial(item)}>{!isNaN(item.price2) ? Number(item.price2).toLocaleString('ko-KR') : item.price2}</Input>
          <Input ref={el => inputRefs.current[i * 7 + 5] = el} onBlur={(e) => handleUpdate(item.id, 'payment', e)} onKeyDown={(e) => handleKeyDown(e, (i+1)*7+5)} onClick={()=>setInitial(item)} onKeyUp={()=>setInitial(item)}>{item.payment}</Input>
          <Input ref={el => inputRefs.current[i * 7 + 6] = el} onBlur={(e) => handleUpdate(item.id, 'remark', e)} onKeyDown={(e) => handleKeyDown(e, (i+1)*7+6)} onClick={()=>setInitial(item)} onKeyUp={()=>setInitial(item)}>{item.remark}</Input>
        </tr>
    ))}
)

뭔가 굉장히 복잡복잡하게 짠거같은데... 추후 리팩토링하는 걸로... 콜록

일단 연습이라 생각해보기로...ㅎ

 

5. 금액을 입력하면 합계 세팅

useEffect(() => {
    let sumPrice1 = 0;
    tempData.filter(item => item.price1 > 0).map(item => sumPrice1 += parseInt(item.price1));
    setExpense(sumPrice1.toLocaleString('ko-KR'));

    let sumPrice2 = 0;
    tempData.filter(item => item.price2 > 0).map(item => sumPrice2 += parseInt(item.price2));
    setRealExpense(sumPrice2.toLocaleString('ko-KR'));
}, [handleUpdate]);
  
return (
	<div className="summary-group">
        <div className="button-group">
            <Button variant="outline-dark" size="sm" disabled={checkedItems.length === 0} onClick={handleDelete}>선택삭제</Button>
            <Button variant="outline-dark" size="sm" disabled={checkedItems.length === 0}>선택복사</Button>
            <Button variant="outline-dark" size="sm" disabled={checkedItems.length === 0}>카드선택</Button>
            <Button variant="outline-dark" size="sm">고정금액</Button>
        </div>
        <div className="summary-item item1">
            <div>지출합계</div>
            <div className="font-bold">{expense}</div>
        </div>
        <div className="summary-item item2">
            <div>실지출합계</div>
            <div className="font-bold">{realExpense}</div>
        </div>
        <div className="summary-item item3">
        	<Button variant="primary" size="lg" onClick={()=>dispatch(updatePayList(tempData))} >저장하기</Button>
        </div>
	</div>
)

 

꽤 그럴듯해졌다..ㅎ

 

### 오늘 꽤 많은 기능을 완성시켰는데,

작업량 대비 시간이 꽤 걸린 것 같다.

그래도 hook 사용에 대해 점차 익숙해지고 있는 것 같다.

내일은 추가 기능을 구현하기 전에 챗GPT를 활용해서 리팩토링하는 시간을 가져보면 좋을 것 같다.

 

'React > Daily' 카테고리의 다른 글

[moneybook]_day6  (0) 2024.09.02
[moneybook]_day5  (0) 2024.08.30
[moneybook]_day4  (0) 2024.08.29
[moneybook]_day2  (0) 2024.08.24
[moneybook]_day1  (0) 2024.08.22