-
[고객 관리 시스템] 2탄React 2020. 6. 13. 23:29
www.youtube.com/watch?v=zug4VBcZOrI&list=PLRx0vPvlEmdD1pSqKZiTihy5rplxecNpz&index=8
유튜브 나동빈님의 강의를 듣고 시작한 프로젝트입니다.
이번 시간에는 Database에 데이터를 전송하고, 삭제 하는 기능을 추가하는 시간입니다.
실제 Database를 생성 할 것입니다.
아래의 명령어로 customer라는 table을 생성합니다.
create table customer
이제 사용 될 테이블을 생성합니다.
CREATE TABLE CUSTOMER ( id INT(64), image VARCHAR(1024), name VARCHAR(64), birth VARCHAR(64), gender VARCHAR(64), job VARCHAR2(10), createdDate DATETIME, isDeleted INT, PRIMARY KEY id );
아래 INSERT를 이용하여 값을 넣어줍니다.
INSERT INTO CUSTOMER VALUES ()
select문을 이용하여 Table에 값이 정상적으로 들어갔는지 확인해봅니다.
select * from customer;
1. CustomerAdd
import React from 'react'; import { post } from 'axios'; import Dialog from '@material-ui/core/Dialog'; import DialogActions from '@material-ui/core/DialogActions'; import DialogTitle from '@material-ui/core/DialogTitle'; import DialogContent from '@material-ui/core/DialogContent'; import TextField from '@material-ui/core/TextField'; import Button from '@material-ui/core/Button'; import {withStyles} from '@material-ui/core/styles'; const styles = theme => ({ hidden : { display :'none' } }) class CustomerAdd extends React.Component{ constructor(props) { super(props); this.state = { file : null, userName : '', birth : '', gender : '', job : '', fileName : '', open : false //dialog open 상태 }; this.handleFormSubmit = this.handleFormSubmit.bind(this); this.addCustomer = this.addCustomer.bind(this); this.handleFileChange = this.handleFileChange.bind(this); this.handleValueChange = this.handleValueChange.bind(this); this.handleClickOpen = this.handleClickOpen.bind(this); this.handleClickClose = this.handleClickClose.bind(this); } handleClickOpen() { this.setState({ open : true }); } handleClickClose() { this.setState({ file : null, userName : '', birth : '', gender : '', job : '', fileName : '', open : false }); } //모든 값이 설정되고 OK버튼을 누를 시 발생하는 Submit이벤트 handleFormSubmit(e) { e.preventDefault(); this.addCustomer() .then(function(response) { console.log(response.data); //addCustomer가 성공적으로 발생 시 updateCustomer발생 this.props.updateCustomer(); }.bind(this)); this.setState({ file : null, userName : '', birth : '', gender : '', job : '', fileName : '', open : false }); //window.location.reload(); } addCustomer(e) { //form형태로 현재 설정된 state값들을 만들어 post로 전달한다. const url = '/api/customers'; const formData = new FormData(); formData.append('image', this.state.file); formData.append('fileName', this.state.fileName); formData.append('userName', this.state.userName); formData.append('birth', this.state.birth); formData.append('gender', this.state.gender); formData.append('job', this.state.job); //전송할 데이터에 파일이 있을경우 const config = { headers : { 'context-type' : 'multipart/form-data' } } return post(url, formData, config); } //file선택이 될 경우 file, fileName을 설정 handleFileChange(e) { e.preventDefault(); this.setState({ file : e.target.files[0], fileName : e.target.value }); } //직업, 생일, 성별, 직업의 onChange 발생 시 setState를 통하여 값을 넣어줌. handleValueChange(e){ let nextState = {}; nextState[e.target.name] = e.target.value; this.setState(nextState); } render() { const {classes} = this.props; return( <div> <Button variant="contained" color='primary' onClick={this.handleClickOpen.bind(this)}> 고객 추가하기 </Button> <Dialog open={this.state.open} onClose={this.handleClickClose}> <DialogTitle>고객 추가</DialogTitle> <DialogContent> <input className={classes.hidden} accept="image/*" id="raised-button-file" type='file' file={this.state.file} value={this.state.fileName} onChange={this.handleFileChange}></input> <label htmlFor="raised-button-file"> <Button variant="contained" color="primary" component="span" name="file"> {this.state.fileName === "" ? "프로필 이미지 선택" : this.state.fileName} </Button> </label> <br/> <TextField label="이름" type='text' name='userName' value={this.state.userName} onChange={this.handleValueChange}></TextField><br/> <TextField label="생년월일" type='text' name='birth' value={this.state.birth} onChange={this.handleValueChange}></TextField><br/> <TextField label="성별" type='text' name='gender' value={this.state.gender} onChange={this.handleValueChange}></TextField><br/> <TextField label="직업" type='text' name='job' value={this.state.job} onChange={this.handleValueChange}></TextField><br/> </DialogContent> <DialogActions> <Button variant="contained" color="primary" onClick={this.handleFormSubmit}> 추가 </Button> <Button variant="outlined" color="primary" onClick={this.handleClickClose}> 닫기 </Button> </DialogActions> </Dialog> </div> ) } } export default withStyles(styles)(CustomerAdd);
2. Server.js
const fs = require('fs'); const express = require("express"); const bodyParse = require("body-parser"); const app = express(); const port = process.env.PORT || 5000; app.use(bodyParse.json()); app.use(bodyParse.urlencoded({extended : true})); const data = fs.readFileSync('./database.json'); //npm install --save mysql //database 연동을 위한 라이브러리 const conf = JSON.parse(data); const mysql = require('mysql'); const connection = mysql.createConnection({ host : conf.host, user : conf.user, password : conf.password, port : conf.port, database : conf.database }); connection.connect(); //파일 처리를 위한 multer 라이브러리 //npm install --save multer const multer = require('multer'); const upload = multer({dest : './upload'}); //database에서 customers table을 가져온다. app.get('/api/customers', (req, res) => { connection.query( // isDeleted가 0인 것만 가져옴 "SELECT * FROM CUSTOMER WHERE isDeleted = 0", (err, rows, fields) => { res.send(rows); } ); }); app.use('/image', express.static('./upload')); //사용자는 image 폴더로 확인하고 실제 매핑은 ./upload //table에 새롭게 추가되는 사용자 정보를 추가한다. app.post('/api/customers', upload.single('image'), function(req, res) { let sql = "INSERT INTO CUSTOMER VALUES (null, ?, ?, ?, ?, ?, now(), 0)"; let image = '/image/' + req.file.filename; let name = req.body.userName; let birth = req.body.birth; let gender = req.body.gender; let job = req.body.job; let params = [image, name, birth, gender, job]; connection.query(sql, params, function(err, rows, fields) { res.send(rows); }); }); //table에서 사용자를 삭제한다. 실제 databases에서 삭제되지는 않지만, isDelete값으로 구분한다. app.delete('/api/customer/:id', function(req, res) { let sql = "UPDATE CUSTOMER SET isDeleted = 1 WHERE id = ?"; let params = [req.params.id]; connection.query(sql, params, function(err, rows, fields) { res.send(rows); }); }); app.listen(port, () => console.log(`Listening on port ${port}`));
3. CustomerDelete
import React from 'react'; import Button from '@material-ui/core/Button'; import Dialog from '@material-ui/core/Dialog'; import DialogActions from '@material-ui/core/DialogActions'; import DialogTitle from '@material-ui/core/DialogTitle'; import DialogContent from '@material-ui/core/DialogContent'; import TextField from '@material-ui/core/TextField'; import { Typography } from '@material-ui/core'; class CustomerDelete extends React.Component{ constructor(props) { super(props); this.state = { open : false }; } deleteCutomer(id) { const url = '/api/customer/' + id; fetch(url, { method : "DELETE" }); this.props.updateCustomer(); } handleDeleteClose() { this.setState({ open : false }); } handleDeleteOpen() { this.setState({ open : true }); } render() { return( <div> <Button variant="contained" color="secondary" onClick={this.handleDeleteOpen.bind(this)}>삭제</Button> <Dialog open={this.state.open} onClose={this.handleDeleteClose.bind(this)}> <DialogTitle>삭제</DialogTitle> <DialogContent> <Typography gutterBottom> 정말 삭제하시겠습니까? </Typography> </DialogContent> <DialogActions> <Button variant="contained" color="primary" onClick={this.deleteCutomer.bind(this, this.props.id)}> 네 </Button> <Button variant="outlined" color="primary" onClick={this.handleDeleteClose.bind(this)}> 아니오 </Button> </DialogActions> </Dialog> </div> ) } } export default CustomerDelete;
'React' 카테고리의 다른 글
[고객관리시스템] 1탄 (0) 2020.06.10 [React] 시작하기 (0) 2020.06.07