https://blog.soshace.com/create-simple-pos-with-react-js-node-js-and-mongodb-10-crud-supplier/
방어 : POS –“판매 시점”. 판매 시점에서 판매자는 고객이 지불해야 할 금액을 계산하고 그 금액을 나타내며 고객에 대한 송장을 작성할 수 있습니다 (현금 등록기 출력물 일 수 있음). 고객이 지불 할 수 있는 옵션을 나타냅니다.
이전 장에서는 식료품 점의 일반 정보에 대한 CRUD 작업을 성공적으로 구현했습니다. 이 장에서는 식료품 점의 공급 업체 정보에 대한 CRUD 작업을 계속 구현할 것입니다.
이 과정은 이전 장과 비슷합니다. 각 반복 단계에서 개선 된 기능을 통해 CRUD 작업을 보다 자세하게 이해하는 데 도움이 됩니다. Redux 작업을 반복하면 유창하고 자연스럽게 Redux 메커니즘 사용 사례가 됩니다.
1. 상수 추가
Redux 구현에 대한 이전 자습서와 마찬가지로 상수 정의부터 시작합니다. 이를 위해 ./constants 폴더를 열고 아래 코드 스니펫에 표시된 대로 상태 이름을 지정하는 데 사용되는 상수를 추가해야 합니다.
1 2 3 4 5 | // SUPPLIER export const SUPPLIER_FETCHING = "SUPPLIER_FETCHING"; export const SUPPLIER_SUCCESS = "SUPPLIER_SUCCESS"; export const SUPPLIER_FAILED = "SUPPLIER_FAILED"; export const SUPPLIER_CLEAR = "SUPPLIER_CLEAR"; |
2. Reducer 추가
Reducer를 구현하려면 ./reducer 폴더로 이동해야 합니다. 그런 다음 supplier.reducer.js라는 리듀서를 만들어야 합니다. 이 과정은 이전에 만든 감속기와 유사합니다. 감속기 파일에서 상수를 가져온 다음 아래 코드 스니펫에 표시된 것처럼 초기 상태 및 감속기 함수를 정의해야 합니다.
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 | import { SUPPLIER_FETCHING, SUPPLIER_SUCCESS, SUPPLIER_FAILED, SUPPLIER_CLEAR, } from "../constants"; const initialState = { isFetching: false, isError: false, result: null, }; export default (state = initialState, { type, payload }) => { switch (type) { case SUPPLIER_FETCHING: return { ...state, isFetching: true, isError: false, result: null }; case SUPPLIER_FAILED: return { ...state, isFetching: false, isError: true, result: null }; case SUPPLIER_SUCCESS: return { ...state, isFetching: false, isError: false, result: payload }; case SUPPLIER_CLEAR: return { ...state, result: null, isFetching: false, isError: false }; default: return state; } }; |
3. Register Reducer
이제 index.reducer.js 파일에서 감속기를 루트 감속기에 등록해야 합니다. 이를 위해 index.reducer.js 파일을 열고 supplierReducer를 포함 시켜 아래 코드 스니펫에 표시된 대로 Reducers 함수를 결합해야 합니다.
2 3 4 5 6 7 8 9 10 | import supplierReducer from './supplier.reducer' export default combineReducers({ loginReducer, registerReducer, forgotpasswordReducer, resetpasswordReducer, posmachineReducer, branchReducer, supplierReducer }); |
4. Creating Action
다음으로 ./actions 폴더에 supplier.action.js 파일이라는 새 작업 파일을 만들어야 합니다. 먼저 아래 코드 스니펫에 표시된 대로 필요한 상수, 구성 요소 및 모듈을 가져와야 합니다.
1 2 3 4 5 6 7 8 | import { SUPPLIER_FETCHING, SUPPLIER_SUCCESS, SUPPLIER_FAILED, SUPPLIER_CLEAR, } from "../constants"; import swal from "sweetalert"; import { httpClient } from "./../utils/HttpClient"; |
1 2 3 4 5 6 7 8 | import { SUPPLIER_FETCHING, SUPPLIER_SUCCESS, SUPPLIER_FAILED, SUPPLIER_CLEAR, } from "../constants"; import swal from "sweetalert"; import { httpClient } from "./../utils/HttpClient"; |
이제 CRUD 작업을 구현할 수 있습니다.
4. Create Operation
먼저 create 작업을 구현합니다. 이를 위해 ./supplier라는 새 구성 요소 폴더를 작성하고 그 안에 action이라는 파일을 작성해야 합니다.
이 동작에 대한 흥미로운 점은 디스패치를 사용하여 감속기가 아닌 다른 기능을 트리거 하는 방법을 배우는 것입니다. 인덱스 페이지로 다시 리디렉션하면서 디스패치를 사용하여 새 데이터를 다시 로드하려고 합니다. 코딩 구현은 아래 코드 스니펫에 제공됩니다.
export const Create = (values, history) => {
return async (dispatch) => {
dispatch(setSupplierStateToFetching());
const response = await httpClient.post(
process.env.REACT_APP_API_URL + "supplier",
values
);
if (response.data.result == "success") {
dispatch(setSupplierStateToSuccess(response.data));
swal("Success!", response.data.message, "success").then((value) => {
dispatch(setSupplierStateToClear());
history.goBack();
dispatch(Index());
});
} else if (response.data.result === "error") {
dispatch(setSupplierStateToFailed());
swal("Error!", response.data.message, "error");
}
};
};
다음으로 create.js라는 새 파일을 만들고 아래 코드 스니펫에 표시된 대로 필요한 구성 요소를 가져와야 합니다.
import React, { useState, useEffect } from "react";
import { Formik } from "formik";
import { useDispatch } from "react-redux";
import * as supplierActions from "../../actions/supplier.action";
import * as Yup from "yup";
import { server } from "../../constants";
그런 다음 아래 코드 스니펫에 표시된 대로 Yup 모듈을 사용하여 유효성 검증 스키마를 정의해야 합니다.
const Create_Schema = Yup.object().shape({
name: Yup.string()
.min(2, "name is Too Short!")
.max(50, "name is Too Long!")
.required("name is Required"),
address: Yup.string().required(),
email: Yup.string()
.email("Invalid email")
.required("Email is Required"),
tel: Yup.string().required("Telephone number is required"),
vat: Yup.string().required("VAT number is required"),
});
이제 이 컴포넌트를 처음 탐색하기 위해 아래 코드 스니펫에 표시된 대로 사용자 세션을 확인하려고 합니다.
export default (props) => {
const dispatch = useDispatch();
useEffect(() => {
if (localStorage.getItem(server.TOKEN_KEY) === null) {
return props.history.push("/login");
}
}, []);
다음으로 아래 코드 스니펫에 표시된 것처럼 Formik 구성 요소를 사용하여 양식을 작성해야 합니다.
const showForm = ({
values,
errors,
touched,
handleChange,
handleSubmit,
isSubmitting,
}) => {
return (
<form role="form" onSubmit={handleSubmit}>
<div class="card-body">
<div class="row">
<div className="form-group col-md-6 input-group has-feedback">
<input
type="text"
name="name"
onChange={handleChange}
value={values.name}
className="form-control"
placeholder="Supplier Name"
className={
errors.name && touched.name
? "form-control is-invalid"
: "form-control"
}
/>
<div class="input-group-append">
<div class="input-group-text">
<span class="fas fa-user"></span>
</div>
</div>
{errors.name && touched.name ? (
<small id="passwordHelp" class="text-danger">
{errors.name}
</small>
) : null}
</div>
</div>
<div class="row">
<div className="form-group col-md-8 input-group has-feedback">
<textarea
name="address"
onChange={handleChange}
value={values.address}
className="form-control"
placeholder="Supplier Address"
className={
errors.address && touched.address
? "form-control is-invalid"
: "form-control"
}
></textarea>
<div class="input-group-append">
<div class="input-group-text">
<span class="fas fa-building"></span>
</div>
</div>
{errors.address && touched.address ? (
<small id="passwordHelp" class="text-danger">
{errors.address}
</small>
) : null}
</div>
</div>
<div className="form-group input-group has-feedback">
<input
type="text"
name="tel"
onChange={handleChange}
value={values.tel}
className="form-control"
placeholder="Supplier Telephone"
className={
errors.tel && touched.tel
? "form-control is-invalid"
: "form-control"
}
/>
{errors.tel && touched.tel ? (
<small id="passwordHelp" class="text-danger">
{errors.tel}
</small>
) : null}
</div>
<div class="row">
<div className="form-group col-md-6 input-group has-feedback">
<input
type="email"
name="email"
onChange={handleChange}
value={values.email}
className="form-control "
placeholder="Supplier E-mail"
className={
errors.email && touched.email
? "form-control is-invalid"
: "form-control"
}
/>
<div class="input-group-append">
<div class="input-group-text">
<span class="fas fa-envelope"></span>
</div>
</div>
{errors.email && touched.email ? (
<small id="passwordHelp" class="text-danger">
{errors.email}
</small>
) : null}
</div>
</div>
<div class="row">
<div className="form-group col-md-6 input-group has-feedback">
<input
type="text"
name="vat"
onChange={handleChange}
value={values.vat}
className="form-control"
placeholder="Supplier Vat Number"
className={
errors.vat && touched.vat
? "form-control is-invalid"
: "form-control"
}
/>
<div class="input-group-append">
<div class="input-group-text">
<span class="fas fa-user"></span>
</div>
</div>
{errors.vat && touched.vat ? (
<small id="passwordHelp" class="text-danger">
{errors.vat}
</small>
) : null}
</div>
</div>
<div class="row">
<div class="offset-md-1 col-4">
<button
type="submit"
disabled={isSubmitting}
class="btn btn-primary btn-block"
>
Add
</button>
</div>
</div>
</div>
</form>
);
};
마지막으로 객체의 모든 구성을 래핑하고 supplierActions.action.js에 데이터를 보내는 기본 render() 함수를 추가해야 합니다. 여기에는 유효성 검사도 포함됩니다. render() 함수 내부의 코딩 구현은 아래 코드 스니펫에 제공됩니다.
return (
<div className="content-wrapper">
<div className="content-header">
<div className="container-fluid">
<div className="row mb-2">
<div className="col-sm-6">
<h1 className="m-0 text-dark">Create Supplier</h1>
</div>
</div>
{/* /.row */}
</div>
{/* /.container-fluid */}
</div>
<div className="content">
<div class="card card-success">
<div class="card-header">
</div>
<Formik
initialValues={{
name: "",
address: "",
tel: '',
}}
onSubmit={(values, { setSubmitting }) => {
console.log(values)
dispatch(supplierActions.Create(values, props.history));
setSubmitting(false);
}}
validationSchema={Create_Schema}
>
{/* {this.showForm()} */}
{(props) => showForm(props)}
</Formik>
</div>
{/* /.card */}
</div>
</div>
);
따라서 결과 양식은 아래 스크린 샷과 같이 나타납니다.
5. 데이터베이스 스키마
여기서 백엔드 프로젝트를 열어야 합니다. 백엔드 파트의 경우 아래 코드 스니펫에 표시된대로 mongoose 패키지를 사용하여 새 데이터베이스 스키마를 작성하는 것으로 시작하십시오.
const mongoose = require("mongoose");
const schema = mongoose.Schema({
name: String,
address: String,
tel: String,
email: String,
vat: Number,
created: { type: Date, default: Date.now },
});
module.exports = mongoose.model("supplier", schema);
이제 공급 업체 데이터를 저장하는 새로운 스키마가 생겼습니다.
6. 백엔드 API 구현
다음으로 supplier_schema.js라는 새 파일을 만들고 아래 코드 스니펫에 표시된대로 API 엔드 포인트를 빌드 하는 데 필요한 컴포넌트를 가져와야 합니다.
const express = require("express");
const router = express.Router();
const supplier = require("./models/supplier_schema");
const jwt = require("./jwt");
그런 다음 클라이언트에서 데이터를 수신하고 새 행을 작성하려면 post post 메소드를 추가해야 합니다. post 함수의 구현은 아래 코드 스니펫에 나와 있습니다.
router.post("/supplier", async (req, res) => {
try {
let doc = await supplier.create(req.body);
res.json({
result: "success",
message: "Create new Supplier data Successfully",
});
} catch (err) {
console.log(err)
res.json({ result: "error", message: err.msg });
}
});
따라서 아래의 시뮬레이션 스크린 샷에 표시된 대로 양식에서 새 항목을 추가 할 수 있습니다.
따라서 Create 작업을 성공적으로 구현했습니다. 이제 인덱스 작업을 시작해야 합니다.
.....
등록된 댓글이 없습니다.