2022.07.21 - [Coding/React] - [React] 고객관리 사이트 (Client) redux로 구현하기
[React] 고객관리 사이트 (Client) redux로 구현하기
2022.07.07 - [Coding/React] - [React] 고객관리 사이트 구현 (Client) [React] 고객관리 사이트 구현 (Client) green_customer_client Header Footer CustomerList Customer DetailCustomer - 라이브러리 설치 a..
7ingout.tistory.com
2022.08.03 - [Coding/React] - [React] 회원가입 기능 구현 (MySQL / bcrypt / 쿠키)
[React] 회원가입 기능 구현 (MySQL / bcrypt / 쿠키)
2022.07.21 - [Coding/React] - [React] 고객관리 사이트 (Client) redux로 구현하기 [React] 고객관리 사이트 (Client) redux로 구현하기 2022.07.07 - [Coding/React] - [React] 고객관리 사이트 구현 (Client)..
7ingout.tistory.com
1.customer_gallery 테이블 추가하기
1) 테이블 생성
crate table customer_gallery(
no int primary key,
imgurl varchar(45),
title varchar(100),
desc text
usermail varchar(45)
)
2) 외래키 지정하기
ALTER TABLE customer_gallery
Add FOREIGN KEY (usermail)
REFERENCES customer_members (usermail)
ON UPDATE CASCADE ON DELETE RESTRICT;
2. 서버 파일 업로드 설정하기
MIDDLEWARE-GREEN-CUSTOMER-SERVER
npm install multer
https://www.npmjs.com/package/multer
multer
Middleware for handling `multipart/form-data`.. Latest version: 1.4.5-lts.1, last published: 2 months ago. Start using multer in your project by running `npm i multer`. There are 3368 other projects in the npm registry using multer.
www.npmjs.com
index.js
// 이미지 업로드 하는 부분
const multer = require("multer")
app.use("/upload", express.static("upload"));
// 파일 요청시 파일이 저장될 경로와 파일이름(요청된 원본파일이름) 지정
const storage = multer.diskStorage({
destination:"./upload",
filename: function(req, file, cb) {
cb(null, file.originalname); // 원본 파일 이름과 똑같이 저장하겠다
}
})
// 업로드 객체
const upload = multer({
storage: storage,
limits: { fieldSize: 1000000 }
})
// upload 경로로 post 요청이 왔을 경우 응답
app.post("/upload", upload.single("img"), function(req, res, next){
res.send({
imageUrl: req.file.filename
})
})

// gallery post, get
// gallery post 요청
app.post('/gallery', async(req,res) => {
const { usermail, title, imgurl, desc} = req.body;
connection.query("insert into customer_gallery(`title`, `imgurl`, `desc`, `usermail`) values(?,?,?,?)",
[title, imgurl, desc, usermail],
(err, result, fields) => {
res.send("등록되었습니다.");
console.log(err);
})
})
// gallery get 요청
app.get("/gallery", async (req, res)=> {
connection.query("select * from customer_gallery",
(err, result, fields)=> {
res.send(result)
})
})
MIDDLEWARE-GREEN-CUSTOMER-CLIENT
components/CreateGallery.js
import React, { useState } from 'react';
import { Table, TableBody, TableRow, TableCell } from '@mui/material';
import axios from "axios";
import { API_URL } from '../config/contansts';
import './GalleryStyle.css'
import { getCookie } from '../util/cookie'
import { useNavigate } from 'react-router-dom';
const CreateGallery = () => {
const navigate = useNavigate()
const umail = getCookie("usermail")
const [ formData, setformData ] = useState({
imgurl:"",
title:"",
desc:"",
usermail:umail
});
const onChange = (e) => {
const { name, value } = e.target;
setformData({
...formData,
[name]: value
})
}
const onChangeImg = (e) => {
const { name } = e.target;
const imgFormData = new FormData();
imgFormData.append(name, e.target.files[0]);
axios.post(`${API_URL}/upload`, imgFormData, {
Headers: {'content-type':'multipart/form-data'},
}).then (response=>{
// setUploadImg(response.data.imageUrl);
setformData({
...formData,
imgurl: response.data.imageUrl
})
}).catch(e=>{
console.log(e)
})
}
const onSubmit = (e) => {
e.preventDefault();
axios.post(`${API_URL}/gallery`, formData)
.then(res=> {
alert('등록되었습니다.');
navigate('/');
}).catch(e=> {
console.log(e);
})
}
return (
<div>
<h2>이미지 게시글 등록하기</h2>
<form onSubmit={onSubmit}>
<Table>
<TableBody>
<TableRow>
<TableCell>이메일</TableCell>
<TableCell>
<input name="username" type="text"
value={formData.usermail}
onChange={onChange} readOnly />
</TableCell>
</TableRow>
<TableRow>
<TableCell>이미지보기</TableCell>
<TableCell>
<div className='imgDiv'>
<div className='imgBox'></div>
<input type="file" className='imgInput' name="img" onChange={onChangeImg}/>
{
formData.imgurl && <img src={`${API_URL}/upload/${formData.imgurl}`} alt="" className='imgview'/>
}
</div>
</TableCell>
</TableRow>
<TableRow>
<TableCell>제목</TableCell>
<TableCell>
<input name="title" type="text"
value={formData.title}
onChange={onChange}/>
</TableCell>
</TableRow>
<TableRow>
<TableCell>내용</TableCell>
<TableCell>
<input name="desc" type="text"
value={formData.desc}
onChange={onChange}/>
</TableCell>
</TableRow>
<TableRow>
<TableCell colSpan={2}>
<button type="submit">등록</button>
<button type="reset">취소</button>
</TableCell>
</TableRow>
</TableBody>
</Table>
</form>
</div>
);
};
export default CreateGallery;
components/GalleryStyle.css
.imgDiv {
position: relative;
}
.imgBox {
width: 150px;
height: 150px;
background-color: darkseagreen;
}
.imgInput {
position: absolute;
width: 150px;
height: 150px;
left: 0;
top: 0;
opacity: 0;
}
.imgview {
width: 150px;
height: 150px;
position: absolute;
left: 0;
top: 0;
}
components/Header.js // 이미지 등록 li 추가
{ isLogin &&
<>
<li>{uname}님 환영합니다!</li>
<li onClick={logoutClick}>로그아웃</li>
<li><Link to="/">회원정보수정</Link></li>
<li><Link to="/gallery">이미지등록</Link></li>
</>
}
App.js // link 추가, 새로고침하면 풀리는 것두 수정
import './App.css';
// import CustomerList from './components/CustomerList';
import DetailCustomer from './components/DetailCustomer';
import Footer from './components/Footer';
import Header from './components/Header';
import { Route, Routes } from "react-router-dom";
// import CreateCustomer from './components/CreateCustomer';
import EditCustomer from './components/EditCustomer';
import CustomerContainer from './components/CustomerContainer';
import CreateCustomerContainer from './components/CreateCustomerContainer';
import JoinForm from './components/JoinForm';
import Login from './components/Login';
import CreateGallery from './components/CreateGallery';
import { useEffect } from 'react';
import { getCookie } from './util/cookie';
import { setLogin } from './modules/logincheck';
import { useDispatch } from 'react-redux';
// const customers = [
// {
// no: 1,
// name: "고객",
// phone: "01012345678",
// birth: "19920206",
// gender: "여성",
// add: "울산시 남구"
// },
// {
// no: 2,
// name: "그린",
// phone: "01012345678",
// birth: "19920206",
// gender: "남성",
// add: "울산시 동구"
// },
// {
// no: 3,
// name: "kh",
// phone: "01012345678",
// birth: "19920206",
// gender: "여성",
// add: "울산시 남구"
// }
// ]
function App() {
const dispatch = useDispatch();
const uname= getCookie('username');
useEffect(()=>{
if(uname){
dispatch(setLogin())
}
},[])
return (
<div className="App">
<Header />
<Routes>
{/* props로 위에 {customers}를 CustomerList로 전달 */}
{/* <Route path="/" element={<CustomerList customers={customers}/>} /> */}
<Route path="/" element={<CustomerContainer/>} />
<Route path="/detailview/:no" element={<DetailCustomer/>} />
<Route path="/edit/:no" element={<EditCustomer/>} />
{/* <Route path="/write" element={<CreateCustomer/>} /> */}
<Route path="/write" element={<CreateCustomerContainer/>} />
<Route path="/join" element={<JoinForm />} />
<Route path="/login" element={<Login />} />
<Route path="/gallery" element={<CreateGallery/>}/>
</Routes>
<Footer/>
</div>
);
}
export default App;
modules/gallery.js
import { API_URL } from "../config/contansts";
import axios from "axios";
// 액션타입, 액션 생성함수, 초기값, 리듀서
const GET_GALLERY = "GET_GALLERY";
const GET_GALLERY_SUCCESS = "GET_GALLERY_SUCCESS";
const GET_GALLERY_ERROR = "GET_GALLERY_ERROR";
const initialState = {
data: null,
loading: false,
error: null
}
// 액션 생성함수
// thunk 함수 사용
export const getGallery = () => async dispatch => {
dispatch({ type: GET_GALLERY }) // 요청시작
try {
const response = await axios.get(`${API_URL}/gallery`)
const gallerydata = response.data;
dispatch({ type: GET_GALLERY_SUCCESS, payload: gallerydata })
}
catch(e) {
dispatch({ type: GET_GALLERY_ERROR, payload: e})
}
}
export default function gallery(state=initialState, action) {
switch(action.type) {
case GET_GALLERY:
return {
loading: true,
data: null,
error: null
}
case GET_GALLERY_SUCCESS:
return {
loading: false,
data: action.payload,
error: null
}
case GET_GALLERY_ERROR:
return {
loading: false,
data: null,
error: action.payload
}
default:
return state
}
}
modules/index.js
import { combineReducers } from "redux";
import customers from './customers';
import logincheck from "./logincheck";
import gallery from "./gallery";
const rootReducer = combineReducers({ customers, logincheck, gallery });
export default rootReducer;
components/GalleryListContainer.js
import React, { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { getGallery } from '../modules/gallery'
import { API_URL } from '../config/contansts.js';
const GalleryListContainer = () => {
const { data, error, loading } = useSelector(state=>state.gallery);
const dispatch = useDispatch();
//컴포넌트 마운트 후 게시글 요청하기
useEffect(()=>{
dispatch(getGallery(dispatch))
},[dispatch])
if(loading) return <div>로딩중입니다.</div>
if(error) return <div>에러가 발생했습니다.</div>
if(!data) return null
return (
<div>
<ul>
{data.map(da=><li>
<img src = {`${API_URL}/upload/${da.imgurl}`} width="300" alt="" />
<br/><span>{da.title}</span>
</li>)}
</ul>
</div>
);
};
export default GalleryListContainer;
'Stack > React' 카테고리의 다른 글
[React / 스터디] 영화 평점 사이트 구현하기 (2) | 2022.11.21 |
---|---|
[React / 스터디] 모두의 일기장 클론 코딩 (2) | 2022.09.30 |
[React] 회원가입 기능 구현 (MySQL / bcrypt / 쿠키) (0) | 2022.08.03 |
[React] 고객관리 사이트 (Client) redux로 구현하기 (0) | 2022.07.21 |
[React] json-server을 이용하여 데이터 받아오기 (0) | 2022.07.15 |