노력이 좋아서

<step82>'redux(react)_고객관리 사이트_redux로 구현'

zoaseo 2022. 7. 18. 09:12

2022.07.08 - [공부가 좋아서] - 'react_고객관리 사이트 구현_step_final'

 

<step76>'react_고객관리 사이트 구현_step_final'

1) green_customer_client components/ CreateCustomer.js import React, { useState } from 'react'; import { Table, TableBody, TableRow, TableCell } from '@mui/material'; import PopupDom from './PopupD..

zoaseo.tistory.com

1)

components/

components/CreateCustomerContainer.js

import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { setInput, setSubmit, goToHome } from '../modules/customers';
import CreateCustomer2 from './CreateCustomer2';
import { useNavigate } from 'react-router-dom';

const CreateCustomerContainer = () => {
    const addCustomer = useSelector(state=>state.customers.addCustomer);
    const dispatch = useDispatch();
    const navigate = useNavigate();
    const onHome = () => {
        dispatch(goToHome(navigate));
    }
    const onChange = (e) => {
        dispatch(setInput(e));
    }
    const onSubmit = () => {
        dispatch(setSubmit());
    }
    return (
        <div>
            <CreateCustomer2 onHome={onHome} onChange={onChange} onSubmit={onSubmit} addCustomer={addCustomer}/>
        </div>
    );
};

export default CreateCustomerContainer;

components/CreateCustomer2.js

import React, { useState } from 'react';
import { Table, TableBody, TableRow, TableCell } from '@mui/material';
import PopupDom from './PopupDom';
import PopupPostCode from './PopupPostCode';

const CreateCustomer2 = ({ onChange, onSubmit, addCustomer, onHome }) => {
    // 우편번호 관리하기
    const onAddData = (data) => {
        console.log(data);
        const postAD = data.address;
        onChange({
            target: {
                name: 'c_add',
                value: postAD
            }
        })
    }
    // 팝업창 상태 관리
    const [ isPopupOpen, setIsPopupOpen] = useState(false);
    // 팝업창 상태 true로 변경
    const openPostCode = () => {
        setIsPopupOpen(true);
    }
    // 팝업창 상태 false로 변경
    const closePostCode = () => {
        setIsPopupOpen(false);
    }
    // 폼 submit 이벤트
    const onSubmitch = (e) => {
        // form에 원래 연결된 이벤트를 제거
        e.preventDefault();
 
        // 전화번호가 숫자인지 체크하기
        if(isNaN(addCustomer.c_phone)){
            alert("전화번호는 숫자만 입력해주세요");
        }
        // input에 값이 있는지 체크하고
        // 입력이 다되어있으면 post전송
        else if(addCustomer.c_name !== "" && addCustomer.c_phone !== "" &&
        addCustomer.c_birth !== "" && addCustomer.c_gender !== "" &&
        addCustomer.c_add !== "" && addCustomer.c_adddetail !== ""){
            onSubmit();
            onHome();
        }
    }

    return (
        <div>
            <h2>신규 고객 등록하기</h2>
            <form onSubmit={onSubmitch}>
                <Table>
                    <TableBody>
                        <TableRow>
                            <TableCell>이름</TableCell>
                            <TableCell>
                                <input name="c_name" type="text" 
                                value={addCustomer.c_name}
                                onChange={onChange}/>
                            </TableCell>
                        </TableRow>
                        <TableRow>
                            <TableCell>연락처</TableCell>
                            <TableCell>
                                <input name="c_phone" type="text" 
                                value={addCustomer.c_phone}
                                onChange={onChange}/>
                            </TableCell>
                        </TableRow>
                        <TableRow>
                            <TableCell>생년월일</TableCell>
                            <TableCell>
                                <input name="c_birth" type="date" 
                                value={addCustomer.c_birth}
                                onChange={onChange}/>
                            </TableCell>
                        </TableRow>
                        <TableRow>
                            <TableCell>성별</TableCell>
                            <TableCell>
                                여성<input name="c_gender" type="radio" 
                                value="여성"
                                onChange={onChange}/>
                                남성<input name="c_gender" type="radio" 
                                value="남성"
                                onChange={onChange}/>
                            </TableCell>
                        </TableRow>
                        <TableRow>
                            <TableCell>주소</TableCell>
                            <TableCell>
                                <input name="c_add" type="text" 
                                value={addCustomer.c_add}
                                onChange={onChange}/>
                                <input name="c_adddetail" type="text"
                                value={addCustomer.c_adddetail}
                                onChange={onChange}/>
                                <button type="button" onClick={openPostCode}>우편번호 검색</button>
                                <div id="popupDom">
                                    {isPopupOpen && (
                                        <PopupDom>
                                            <PopupPostCode onClose={closePostCode}
                                            onAddData={onAddData}/>
                                        </PopupDom>
                                    )}
                                </div>
                            </TableCell>
                        </TableRow>
                        <TableRow>
                            <TableCell colSpan={2}>
                                <button type="submit">등록</button>
                                <button type="reset">취소</button>
                            </TableCell>
                        </TableRow>
                    </TableBody>
                </Table>                
            </form>
        </div>
    );
};

export default CreateCustomer2;

components/CustomerContainer.js

import React, { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { getCustomers } from '../modules/customers';
import CustomerUi from './CustomerUi';

const CustomerContainer = () => {
    const { data, loading, error } = useSelector(state => state.customers.customers);
    const dispatch = useDispatch();
    // 컴포넌트 마운트 후 고객 목록 요청
    useEffect(()=>{
        dispatch(getCustomers());
    },[dispatch]);
    if(loading) return <div>로딩중입니다.</div>
    if(error) return <div>에러가 발생했습니다.</div>
    if(!data) return null;
    return (
        <div>
            <CustomerUi customers={data}/>
        </div>
    );
};

export default CustomerContainer;

components/CustomerUi.js

import React from 'react';
import { Table, TableBody, TableHead, TableCell, TableRow} from '@mui/material';
import Customer from './Customer';

const CustomerUi = ({customers}) => {
    return (
    <div>
        <h2>고객리스트</h2>
        <Table>
            <TableHead>
                <TableRow>
                    <TableCell>번호</TableCell>
                    <TableCell>이름</TableCell>
                    <TableCell>연락처</TableCell>
                    <TableCell>생년월일</TableCell>
                    <TableCell>성별</TableCell>
                    <TableCell>주소</TableCell>
                </TableRow>
            </TableHead>
            <TableBody>
                {customers.map(customer=>(
                    <Customer key={customer.no} customer={customer}/>
                ))}
            </TableBody>
        </Table>
    </div>
    );
};

export default CustomerUi;

modules/

modules/customers.js

import axios from 'axios';
import { API_URL } from '../config/conf';

// 리덕스 액션타입, 초깃값, 액션생성함수, 리듀서
const GET_CUSTOMERS = "GET_CUSTOMERS";
const GET_CUSTOMERS_ERROR = "GET_CUSTOMERS_ERROR";
const GET_CUSTOMERS_SUCCESS = "GET_CUSTOMERS_SUCCESS";
const SET_INPUT = "SET_INPUT";
const SET_RESET = "SET_RESET";

// 초깃값 설정
const initialState = {
    customers: {
        loading: false,
        data: null,
        error: null
    },
    addCustomer: {
        c_name: "",
        c_phone: "",
        c_birth: "",
        c_gender: "",
        c_add: "",
        c_adddetail: ""
    }
}

// 액션생성함수
export const setInput = (e) => {
    const { name, value } = e.target;
    return {
        type: SET_INPUT,
        name,
        value
    }
}

// 홈으로 이동 함수
export const goToHome = (navigate) => {
    navigate('/');
}

// thunk 함수를 사용해서 액션객체 디스패치하기
export const getCustomers = () => async dispatch => {
    dispatch({type:GET_CUSTOMERS}) // 요청시작
    try {
        const response = await axios.get(`${API_URL}/customers`);
        const customers = response.data;
        dispatch({type: GET_CUSTOMERS_SUCCESS, customers});
    }
    catch(e) {
        dispatch({type: GET_CUSTOMERS_ERROR, error:e});
    }
}

export const setSubmit = () => async (dispatch, getState) => {
    const formdata = getState().customers.addCustomer;
    try {
        const response = await axios.post(`${API_URL}/addCustomer`, formdata);
        
        dispatch({type: SET_RESET})
    }
    catch(e) {
        dispatch({type: SET_RESET})
    }
}

// 리듀서 만들기
export default function customers(state = initialState, action){
    switch(action.type){
        case GET_CUSTOMERS:
            return {
                ...state,
                customers: {
                    loading: false,
                    data: null,
                    error: null
                }
            }
        case GET_CUSTOMERS_SUCCESS:
            return {
                ...state,
                customers: {
                    loading: false,
                    data: action.customers,
                    error: null
                }
            }
        case GET_CUSTOMERS_ERROR:
            return {
                ...state,
                customers: {
                    loading: false,
                    data: null,
                    error: action.error
                }
            }
        case SET_INPUT:
            return {
                ...state,
                addCustomer: {
                    ...state.addCustomer,
                    [action.name]: action.value
                }
            }
        case SET_RESET:
            return {
                ...state,
                addCustomer: {
                    ...state.addCustomer,
                    c_name: "",
                    c_phone: "",
                    c_birth: "",
                    c_gender: "",
                    c_add: "",
                    c_adddetail: ""
                }
            }
        default:
            return state;
    }
}

modules/index.js

import { combineReducers } from "redux";
import customers from "./customers";

const rootReducer = combineReducers({ customers });

export default rootReducer;

index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from 'react-router-dom';
import { applyMiddleware, legacy_createStore as createStore } from 'redux';
import rootReducer from './modules';
import { composeWithDevTools } from 'redux-devtools-extension';
import thunk from 'redux-thunk';
import { Provider } from 'react-redux';

const store = createStore(rootReducer, composeWithDevTools(applyMiddleware(thunk)));
console.log(store.getState());
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <BrowserRouter>
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>
  </BrowserRouter>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();