\chapter{การพัฒนาระบบ}
หลังจากที่ได้มีการเตรียมความพร้อมสำหรับการพัฒนาในด้านต่างๆ ไม่ว่าจะเป็นที่มาและความสำคัญของปัญหา เทคโนโลยีที่มีความเหมาะสมกับระบบ และการออกแบบระบบการทำงานรวมไปถึงโครงสร้างของข้อมูล ในบทนี้จะเป็นการพูดถึงการสร้างระบบที่ได้มีการออกแบบไว้ในบทที่แล้ว โดยการพัฒนาระบบแบ่งได้เป็นส่วนต่าง ๆ ดังนี้


\section{การพัฒนาเว็บแอปพลิเคชัน}
	การพัฒนาระบบจองคิวร้านเสริมสวยสำหรับเว็บแอปพลิเคชันนั้นวัตถุประสงค์หลังเพื่อสร้างความสะดวกต่อการทำงานของผู้ใช้บริการ เจ้าของร้าน และช่าง โดยเว็บแอปพลิเคชันนี้ถูกพัฒนาขึ้นด้วย React.js มีรายละเอียดการทำงานดังนี้
	
	\subsection{การเชื่อมต่อ Cloud SQLstore}
	ในการเชื่อมต่อเว็บแอปพลิเคชันกับ mySQL เพื่อใช้บริการต่างๆ ของ mySQL ทำได้ดังนี้
	  4.1.1.1การเชื่อมต่อ Nodes กับ MySQl
		\begin{figure}[H]
		{\setstretch{1.0}\begin{lstlisting}
module.exports = {
  hostname: 'localhost',
  username: 'piyaphorn',
  password: 'zxcasdqwe',
  database_name: 'b_beauty_project',
  JWT_SECRET: 'benz'
} 
			\end{lstlisting}}
		\caption{ไฟล์ config.js}
		\label{Fig:sqlConfig}
	\end{figure}
	จากภาพที่ \ref{Fig:sqlConfig} โครงสร้างของไฟล์  config.js สามารถอธิบายการทำงานได้ดังนี้
	\begin{itemize}[label={--}]
		\item บรรทัดที่  1	    เป็นการส่งออกโมดูลเพื่อใช้งานในไฟล์อื่น
		\item บรรทัดที่  2 - 6 	เป็นการตั้งค่าระบุตัวตนเพื่อใช้งาน my SQL
	\end{itemize}
\newpage
4.1.1.2 การ connect database
	\begin{figure}[H]
		{\setstretch{1.0}\begin{lstlisting}
const Sequelize = require('sequelize');
const config = require('./config');
const db = {};

const connect = new Sequelize(config.database_name, config.username, config.password, {
	host: config.hostname,
	dialect: 'mysql',
	operatorsAliases: false,
		pool: {
			max: 5,
			min: 0,
			acquire: 30000,
			idle: 10000
		}
})
db.sequelize = connect
db.Sequelize = Sequelize

module.exports = db 
			\end{lstlisting}}
		\caption{ไฟล์ db.js}
		\label{Fig:dbConfig}
	\end{figure}
	จากภาพที่ \ref{Fig:dbConfig} โครงสร้างของไฟล์db.js สามารถอธิบายการทำงานได้ดังนี้
	\begin{itemize}[label={--}]
		\item บรรทัดที่  1	    เป็นการเรียกใช้งาน package
		\item บรรทัดที่  2	    เป็นการนำเข้าโมดูลเพื่อใช้งาน เป็นการนำเข้าโมดูลตั้งค่าที่ได้จากรูปภาพ \ref{Fig:sqlConfig}
		\item บรรทัดที่  5 - 17	เป็นการตั้งค่า host เพื่อนำไปใช้งาน
		\item บรรทัดที่  19     เป็นการส่งออกโมดูลเพื่อใช้งานในไฟล์อื่น
	\end{itemize}
\newpage
	4.1.1.3 การกำหนด api 
\begin{figure}[H]
	{\setstretch{1.0}\begin{lstlisting}
const express = require("express");
const cors = require("cors");
const bodyParser = require("body-parser");
const router = require("./routers");

const port = process.env.PORT || 9000;
const app = express();

app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use("/api/auth", router.auth);
app.use("/api/list", router.list);
app.use("/api/shop", router.shop);
app.use("/api/review", router.review);
app.use("/api/booking", router.booking);
app.use("/api/storage", router.storage);
app.use("/api/storageprofile", router.storageprofile);
app.use("/api/storageshop", router.storageshop);
app.use("/api/storagebeautician", router.storagebeautician)
app.listen(port, () => {
console.log("Express server listening on port " + port);
});

	\end{lstlisting}}
	\caption{ไฟล์ server.js}
	\label{Fig:apiConfig}
\end{figure}
	จากภาพที่ \ref{Fig:apiConfig} โครงสร้างของไฟล์ server.js สามารถอธิบายการทำงานได้ดังนี้
	\begin{itemize}[label={--}]
		\item บรรทัดที่  1 - 3	 เป็นการเรียกใช้งาน package 
		\item บรรทัดที่  4 	     เป็นการเรียกใช้งานไฟล์ routers 
		\item บรรทัดที่  6       เป็นการกำหนด port เพื่อใช้เชื่อ api ระหว่าง backend กับ fontend 
		\item บรรทัดที่  7 เป็นการประกาศตัวแปล เพื่อเรียกใช้งาน package ตามบรรทัดที่ 1
	\end{itemize}
	\newpage
	\subsection{โครงสร้างของการสร้างหน้าเข้าสู่ระบบ}
		4.1.2.1 การสร้าง form กรอกข้อมูล
	\begin{figure}[H]
	{\setstretch{1.0}\begin{lstlisting}

<div>
 <TextField  className={classes.margin}
  id="email"
  name="email"
  value={email}
  label="E_mail"
  variant="outlined"
  InputProps={{
  startAdornment: (
   <InputAdornment position="start">
    <MailOutlineIcon />
   </InputAdornment>
  )
 }}
   onChange={this.handleChange}/>
</div>
<div>
 <TextFieldclassName={classes.margin}
  id="password"
  name="password"
  value={password}
  label="Password"
  type="password"
  autoComplete="current-password"
  variant="outlined"
  InputProps={{
  startAdornment: (
  <InputAdornment position="start">
   <VpnKeyIcon />
  </InputAdornment>)
 }}
  onChange={this.handleChange}/>
</div>
<div><Button variant="contained" color="primary"
  disableElevation>
  เข้าสู่ระบบ</Button></div>

		\end{lstlisting}}
		\caption{การสร้างหน้าจอส่วนติดต่อผู้ใช้ของหน้าเข้าสู่ระบบ loginPage.js}
		\label{Fig:SignIn1}
	\end{figure}
	
	จากภาพที่ \ref{Fig:SignIn1} โครงสร้างของการสร้างหน้าจอส่วนติดต่อผู้ใช้ของหน้าเข้าสู่ระบบ สามารถอธิบายการทำงานได้ดังนี้
	\begin{itemize}[label={--}]
	
		\item บรรทัดที่ 2-17 เป็นสร้างช่องกรอกข้อมูลอีเมล (e-mail) จากผู้ใช้
		\item บรรทัดที่ 18-34 เป็นสร้างช่องกรอกข้อมูลรหัสผ่าน (password) จากผู้ใช้
		\item บรรทัดที่ 34-37 สร้างปุ่มเข้าสู่ระบบ
	\end{itemize}
4.1.2.2 การสร้าง axios เพื่อเพิ่มข้อมูลจากหน้าเว็บลงฐานข้อมูล
	\begin{figure}[H]
		{\setstretch{1.0}\begin{lstlisting}

axios
.post("http://localhost:9000/api/auth/login", {
email: email,
password: password
})
.then(async response => {
const token = response.data.token;
localStorage.setItem("token", token);
const user = await axios.get(
"http://localhost:9000/api/auth/currentUser",
{ headers: { token: token } }
);
if (user) {
this.props.setUser(user.data);
if (user.data.role === 0) {
this.props.history.push("/");
} else if (user.data.role === 1) {
this.props.history.push("/DataShopPage");
} else {
this.props.history.push("/BeauticianShopPage");
}
}
})
.catch(error => {
console.log(error);
alert("e-mail หรือรหัสผ่านไม่ถูกต้อง");
});
			\end{lstlisting}}
		\caption{การสร้างหน้าจอส่วนติดต่อผู้ใช้ของหน้าเข้าสู่ระบบ LoginPage.js}
		\label{Fig:SignIn2}
	\end{figure}
\newpage
	จากภาพที่ \ref{Fig:SignIn2} โครงสร้างของการสร้างหน้าจอส่วนติดต่อผู้ใช้ของหน้าเข้าสู่ระบบ สามารถอธิบายการทำงานได้ดังนี้
	\begin{itemize}[label={--}]
		\item บรรทัดที่ 2-6  เป็นการเรียกใช้ mysql พร้อมส่งค่า email และ password เพื่อทำการเข้าสู่ระบบ
		\item บรรทัดที่ 7-13 เป็นการกำหนดกที่ใช้ในการตรวจสอบความถูกต้องของอีเมลและรหัสผ่าน
		\item บรรทัดที่ 14-24 เป็นการเช็คบทบาทของ user
		\item บรรทัดที่ 25-28 เป็นการแจ้งเตือน error
	\end{itemize}
	4.1.2.3 การสร้างลอจิก(logic)การเข้าสู่ระบบ
	\begin{figure}[H]
		{\setstretch{1.0}\begin{lstlisting}
exports.login = async (req, res) => {
  const loginData = req.body;
  const user = await User.findOne({
    where: { email: loginData.email }
  });
  if (!user) {
    return res.status(400).json({ message: "email หรือ รหัสผ่านไม่ถูกต้อง" });
  } else {
  const chkPassword = await bcryptjs.compare(
    loginData.password,
    user.dataValues.password
  );
  if (chkPassword === false) {
    return res.status(400).json({ message: "รหัสผ่านไม่ถูกต้อง" });
  }
  const token = await createToken(user.dataValues.id);
    res.status(200).send({token});
  }
};

	\end{lstlisting}}
		\caption{การสร้างลอจิก (logic) ของหน้าเข้าสู่ระบบ authcontroller.js}
		\label{Fig:SignInJs}
	\end{figure}
\newpage
	จากภาพที่ \ref{Fig:SignInJs} โครงสร้างลอจิกของหน้าเข้าสู่ระบบ สามารถอธิบายการทำงานได้ดังนี้
	\begin{itemize}[label={--}]
		\item บรรทัดที่ 1 เรียกใช้ฟังก์ชันอื่นเพื่อทำการอัพเดทสถานะการเข้าสู่ระบบ
		\item บรรทัดที่ 2 สร้างตัวแปลเพื่อใช้เก็บข้อมูลเข้าสู่ระบบ
		\item บรรทัดที่ 3-5 เป็นการเช็คข้อมูลการเข้าสู่ระบบ	
		\item บรรทัดที่ 7-15 เป็นการอัพเดทสถานะเมื่อเข้าสู่ระบบไม่สำเร็จ 
		\item บรรทัดที่ 16-19 เป็นการอัพเดทสถานะเมื่อเข้าสู่ระบบสำเร็จ
	\end{itemize}
	
	\subsection{โครงสร้างของการสร้างหน้าหลัก}
	4.1.3.1 การสร้างหน้าจอส่วนติดต่อผู้ใช้ของหน้าหลัก
	\begin{figure}[H]
		{\setstretch{1.0}\begin{lstlisting}
componentDidMount = async () => {
 let { pathname } = this.props.location;
 const response = await axios.get("http://localhost:9000/api/shop/all");
  for (let i = 0; i < response.data.length; i++) {
    const resposeimgshop = await axios.get(`http://localhost:9000/api/storage/file/shop/${response.data[i].id}`)
    response.data[i].image = ('data:' + resposeimgshop.data.type+';base64,'+resposeimgshop.data.url)}
   console.log("response", response.data);
   this.setState({shops: response.data,});

};

			\end{lstlisting}}
		\caption{การสร้างหน้าจอส่วนติดต่อผู้ใช้ของหน้าหลัก HomePage.JS}
		\label{Fig:Home1}
	\end{figure}
	จากภาพที่ \ref{Fig:Home1} โครงสร้างของการสร้างหน้าจอข้อมูลร้าน  สามารถอธิบายการทำงานได้ดังนี้
	\begin{itemize}[label={--}]
		\item บรรทัดที่ 1 และ 10 เป็นการกำหนดฟังก์ชันให้ข้อมูลแสดงเวลาเปิดระบบ
	    \item บรรทัดที่ 2   เป็นการเก็บตัวใน props
		\item บรรทัดที่ 3 เป็นการเรียกใช้ mysql พร้อมดึงข้อมูลร้าน
		\item บรรทัดที่ 4-7 เป็นการเรียกใช้ mysql พร้อมดึงข้อมูลรูปภาพร้าน
		\item บรรทัดที่ 8 เป็นการ set ค่าใน State
	\end{itemize}
	\newpage
	4.1.3.2 การสร้างลอจิก(logic)ของหน้าหลัก 
		\begin{figure}[H]
			{\setstretch{1.0}\begin{lstlisting}
exports.getShop = async (req, res) => {
	try {
		let shop = await Shop.findAll();
		res.status(200).send(shop);
	} catch (err) {
		console.log(err);
		res.sendStatus(401);
	}
};




				\end{lstlisting}}
			\caption{การสร้างลอจิก(logic)ของหน้าหลัก Shopcontroller.js}
			\label{Fig:HomeshopJs}
		\end{figure}
		จากภาพที่ \ref{Fig:HomeshopJs} โครงสร้างลอจิกของหน้าข่าวสาร สามารถอธิบายการทำงานได้ดังนี้
		\begin{itemize}[label={--}]
			\item บรรทัดที่ 1-9  เป็นการสร้างฟังก์ชันเพื่อดึงข้อมูลร้านทั้งหมดในฐานข้อมูลมาแสดง
		
		\end{itemize}
		\newpage
	\subsection{โครงสร้างของการสร้างหน้าดูรายละเอียดร้าน}
	4.1.4.1 การสร้างหน้าจอส่วนติดต่อผู้ใช้ของหน้ารายละเอียดร้าน
	\begin{figure}[H]
		{\setstretch{1.0}\begin{lstlisting}
componentDidMount = async () => {
	const { location, userInfo } = this.props;
	const id = location.state.id;
	const response1 = await axios.get(
	`http://localhost:9000/api/shop/getShopId/${id}`
	);
	const response2 = await axios.get(
	`http://localhost:9000/api/list/getListshop/${id}`
	);
	console.log("response", response1.data);
	console.log("response", response2.data);
	let { timeopen, timeclose } = response1.data;
	timeopen = timeopen.split(":");
	timeclose = timeclose.split(":");
	let dateClose = new Date();
	dateClose.setHours(parseInt(timeclose[0]));
	dateClose.setMinutes(parseInt(timeclose[1]));
	const result = this.calculate(moment(dateClose), timeopen);

	this.setState({
		shop: response1.data,
		data: result, 
		datalist: response2.data
	});

};
				\end{lstlisting}}
			\caption{การสร้างหน้าจอส่วนติดต่อผู้ใช้ของหน้ารายละเอียดร้าน ShopPage.js}
			\label{Fig:shop1}
		\end{figure}
	\newpage
			จากภาพที่ \ref{Fig:shop1} โครงสร้างของการสร้างหน้าจอส่วนติดต่อผู้ใช้ของหน้าดูรายละเอียดข่าวสาร  สามารถอธิบายการทำงานได้ดังนี้
			\begin{itemize}[label={--}]
				\item บรรทัดที่ 1 และ 26 เป็นการสร้างฟังก์ชันเพื่อให้ข้อมูลแสดงเวลาเปิดหน้า ShopPage
				\item บรรทัดที่ 2	เป็นการประกาศตัวแปลใน props
				\item บรรทัดที่ 3 สร้างตัวแปล id เพื่อมาเก็บข้อมูล id จาก location.props 
				\item บรรทัดที่ 5-6 เป็นการดึงข้อมูลร้านจากฐานข้อมูลโดยดึงตาม id ร้าน
				\item บรรทัดที่ 7-9 เป็นการดึงข้อมูลรายการจากฐานข้อมูลโดยดึงตาม id ร้าน
				\item บรรทัดที่ 10-11 เป็นการ log ข้อมูลมาดูว่าแสดงตามที่ต้องการหรือไม่
				\item บรรทัดที่ 12-19 เป็นการกำหนดช่วงเวลาที่จะให้แสดง
				\item บรรทัดที่ 20-24 เป็นการ set ค่าใน state
			\end{itemize}
			4.1.4.2 การสร้างลอจิกของหน้าดูรายละเอียดของร้าน
			\begin{figure}[H]
				{\setstretch{1.0}\begin{lstlisting}
exports.getShopId = async (req, res) => {
	try {
		const shopId = req.params.id;
		let shop = await Shop.findOne({
			where: {
			id: shopId,
			},
		});
	res.status(200).send(shop);
	} catch (err) {
	 	console.log(err);
		res.sendStatus(401);
	}
};				\end{lstlisting}}
				\caption{การสร้างลอจิกของหน้าดูรายละเอียดของร้าน shopcontroller.js}
				\label{Fig:shopJS2}
			\end{figure}
			จากภาพที่ \ref{Fig:shopJS2} โครงสร้างลอจิกของหน้าดูรายละเอียดของร้าน สามารถอธิบายการทำงานได้ดังนี้
			\begin{itemize}[label={--}]
				\item บรรทัดที่ 1   เป็นการส่งออกเพื่อใช้งานในไฟล์อื่น
				\item บรรทัดที่ 2-9 เป็นการกำหนดค่าข้อมูลเพื่อให้ข้อมูลแสดงตาม id ร้าน
				\item บรรทัดที่ 10-13 เป็นการกำหนด error
			\end{itemize}
			
	\subsection{โครงสร้างของการสร้างหน้าโปรไฟล์}
	4.1.5.1 การสร้างหน้าจอส่วนติดต่อผู้ใช้ของหน้าโปรไฟล์
	\begin{figure}[H]
		{\setstretch{1.0}\begin{lstlisting}
componentDidMount = async () => {
	const { location, userInfo } = this.props;
	const response = await axios.get(
	`http://localhost:9000/api/auth/getUserById/${userInfo.id}` );
	const resposeimguser = await axios.get(`http://localhost:9000/api/storageprofile/file/user/${userInfo.id}`)
	response.data.image = ('data:' + resposeimguser.data.type+';base64,'+resposeimguser.data.url)
	this.setState({
	user: response.data,
	});
};
			\end{lstlisting}}
		\caption{การสร้างหน้าจอส่วนติดต่อผู้ใช้ของหน้าโปรไฟล์ Profile.js}
		\label{Fig:Profile1}
	\end{figure}
	จากภาพที่ \ref{Fig:Profile1} โครงสร้างของการสร้างหน้าจอส่วนติดต่อผู้ใช้ของหน้าโปรไฟล์ สามารถอธิบายการทำงานได้ดังนี้
	\begin{itemize}[label={--}]
		\item บรรทัดที่ 1  เป็นการสร้างฟังก์ชันเพื่อให้แสดงข้อมูลเวลาเปิดหน้าโปรไฟล์
		\item บรรทัดที่ 2 เป็นการประกาศตัวแปลใน props
		\item บรรทัดที่ 3-4  เป็นการดึงข้อมูล user จากฐานข้อมูลโดยดึงตาม id user
		\item บรรทัดที่ 5-6 เป็นการดึงข้อมูล imageuser จากฐานข้อมูลโดยดึงตาม id user
		\item บรรทัดที่ 7-9  เป็นการ set ค่า ใน state
	
	\end{itemize}
\newpage
4.1.5.2 การสร้างลอจิกของหน้าโปรไฟล์
	\begin{figure}[H]
		{\setstretch{1.0}\begin{lstlisting}
exports.getUserById = async (req, res) => {
	try {
		console.log("req.param", req.param);
		const userId = req.params.id;
		const user = await User.findOne({
			where: { id: userId }
		});
		res.status(200).send(user);
	} catch (err) {
		console.log(err);
		res.sendStatus(401);
	}
};
			\end{lstlisting}}
		\caption{การสร้างลอจิกของหน้าโปรไฟล์ authcontroller.js}
		\label{Fig:MessageJs}
	\end{figure}
	
	จากภาพที่ \ref{Fig:MessageJs} โครงสร้างลอจิกของหน้าโปรไฟล์ สามารถอธิบายการทำงานได้ดังนี้
	\begin{itemize}[label={--}]
		\item บรรทัดที่ 1  การส่งออกข้อมูลเพื่อไปใช้ในไฟล์อื่น
		\item บรรทัดที่ 2-8 คำสั่งที่ใช้ดึงข้อมูล user จากฐานข้อมูลตาก id user
		\item บรรทัดที่ 9-12 คำสั่งแสดง error เมื่อไม่พบข้อมูล

	\end{itemize}
\newpage
	\subsection{โครงสร้างของการสร้างหน้าเพิ่มข้อมูลร้าน}
	4.1.6.1 การสร้างหน้าจอส่วนติดต่อผู้ใช้ของหน้าเพิ่มข้อมูลร้าน
	\begin{figure}[H]
		{\setstretch{1.0}\begin{lstlisting}
<div className="row center">>
 <img src={shop.image}  width="60%"/>
 <div className="row center">
  <Button variant="outlined" color="primary">
   เพิ่มรูปภาพร้าน</Button>
</div>
<div className="col s12 m12 l12">
 <div ClassName="row">
  <TextField
   className={classes.margin} id="name" name="name" value={shop.name} label="ชื่อร้าน*" variant="outlined" />
  <TextField
   className={classes.margin} id="nameeng" name="nameeng"
   value={shop.nameeng}label="Name*" variant="outlined" />
<div className="row">
  <Button variant="contained" color="secondary">
   ยกเลิก
  </Button>{" "}
  <Button variant="contained" color="primary"
   onClick={() => {
    axios
    .post("http://localhost:9000/api/shop/add", {
      ...shop,
    userId: userInfo.id
  })
  .then(response => {
    console.log("เพิ่มข้อมูลร้านสำเร็จ", response);
    alert("กรอกข้อมูลไม่ครบ");
   })
  .catch(error => {
    console.log(error);
  });
  }}
  > ตกลง</Button>
</div>


			\end{lstlisting}}
		\caption{การสร้างหน้าจอส่วนติดต่อผู้ใช้ของหน้าเพิ่มข้อมูลร้าน DataShop.js}
		\label{Fig:Datashopjs}
	\end{figure}
	จากภาพที่ \ref{Fig:Datashopjs} โครงสร้างของการสร้างหน้าจอส่วนติดต่อผู้ใช้ของหน้าเพิ่มข้อมูลร้าน สามารถอธิบายการทำงานได้ดังนี้
	\begin{itemize}[label={--}]
		\item บรรทัดที่ 1-2 แสดงรูปภาพ
		\item บรรทัดที่ 3-7 ปุ่มเพิ่มรูปภาพ
		\item บรรทัดที่ 8-15 ฟอร์มเพื่อกรอกข้อมูลร้าน
		\item บรรทัดที่ 16-18 ปุ่มยกเลิก
		\item บรรทัดที่ 19-35 ปุ่มตกลง เมื่อกดปุ่มระบบจะบันทึกข้อมูลลงฐานข้อมูล
	\end{itemize}
4.1.6.2 การสร้างลอจิกของหน้าเพิ่มข้อมูลร้าน
	\begin{figure}[H]
		{\setstretch{1.0}\begin{lstlisting}
exports.addShop = async (req, res) => {
	try {
		const addshopData = req.body;
		console.log(addshopData);
		await Shop.create(addshopData);
		res.send("create");
	} catch (err) {
		console.log(err);
		res.sendStatus(401);
	}
};
			\end{lstlisting}}ุ
		\caption{การสร้างลอจิกของหน้าเพิ่มข้อมูลร้าน shopcontroller.js}
		\label{Fig:AddShop}
	\end{figure}
	จากภาพที่ \ref{Fig:AddShop} โครงสร้างลอจิกของหน้าเพิ่มข้อมูลร้าน สามารถอธิบายการทำงานได้ดังนี้
	\begin{itemize}[label={--}]
		\item บรรทัดที่ 1 เป็นการส่งออกข้อมูลเพื่อใช้ในไฟล์อื่น
		\item บรรทัดที่ 2-6 เป็นคำสั่งที่ใช้เพิ่มข้อมูลลงฐานข้อมูล
		\item บรรทัดที่ 7-10 เป็นการแสดง error เมื่อเพิ่มข้อมูลไม่ได้
	\end{itemize}
\newpage
		\subsection{โครงสร้างของการสร้างหน้าเพิ่มรายการ}
		4.1.7.1 การสร้างหน้าจอส่วนติดต่อผู้ใช้ของหน้าเพิ่มรายการ
		\begin{figure}[H]
			{\setstretch{1.0}\begin{lstlisting}
<div className="row">
 <MaterialTable title="รายการ" columns={columns} data={data}
   options={{ selection: false,}} 
   editable={{
     onRowAdd: (newData) =>
      new Promise((resolve) => {
          resolve();
          this.setState((prevState) => {
        let data = [...prevState.data];
          data = [newData, ...data];
          return { ...prevState, data };
        }) }),
      onRowUpdate: (newData, oldData) =>
        new Promise((resolve) => {
          setTimeout(() => {
           resolve();
            if (oldData) {
            this.setState((prevState) => {
            const data = [...prevState.data];
            data[data.indexOf(oldData)] = newData;
             return { ...prevState, data };
        });
       } }, 600);}),
    onRowDelete: (oldData) =>
      new Promise((resolve) => {
       setTimeout(() => {
       resolve();
       this.setState((prevState) => {
       const data = [...prevState.data];
       data.splice(data.indexOf(oldData), 1);
          return { ...prevState, data };
       }); }, 600); }),}} />
</div>
				\end{lstlisting}}
			\caption{การสร้างหน้าจอส่วนติดต่อผู้ใช้ของหน้าเพิ่มรายการ List.js}
			\label{Fig:ListJS}
		\end{figure}
		จากภาพที่ \ref{Fig:ListJS} โครงสร้างของการสร้างหน้าจอส่วนติดต่อผู้ใช้ของหน้ารายการ สามารถอธิบายการทำงานได้ดังนี้
		\begin{itemize}[label={--}]
			\item บรรทัดที่ 1-3  เป็นการแสดงตาราง
			\item บรรทัดที่ 4-12 เป็นการเพิ่มข้อมูลในตาราง
			\item บรรทัดที่ 13-23 เป็นการแก้ไขในตาราง
			\item บรรทัดที่ 23-33 เป็นการลบข้อมูลในตาราง
		
		\end{itemize}
	4.1.7.2 การสร้างลอจิกของหน้าเพิ่มรายการ
		\begin{figure}[H]
			{\setstretch{1.0}\begin{lstlisting}
exports.addlist = async (req, res) => {
	try {
		const addlistData = req.body;
		await List.create({
			name: addlistData.name,
			price: addlistData.price,
			time: addlistData.time,
			shop: addlistData.shop,
			userId: addlistData.userId
		});
		res.send("create");
	} catch (err) {
		console.log(err);
		res.sendStatus(401);
	}
};
				\end{lstlisting}}
			\caption{การสร้างลอจิกของหน้าเพิ่มรายการ listcontroller.js}
			\label{Fig:ListShop}
		\end{figure}
		จากภาพที่ \ref{Fig:ListShop} โครงสร้างลอจิกของหน้ารายการ สามารถอธิบายการทำงานได้ดังนี้
		\begin{itemize}[label={--}]
			\item บรรทัดที่ 1 การส่งออกข้อมูลเพื่อใช้ในไฟล์อื่น
			\item บรรทัดที่ 2-11 เป็นการเพิ่มข้อมูลลงในฐานข้อมูล
			\item บรรทัดที่ 12-15 เป็นคำสั่งแสดง error เมื่อไม่สามารถเพิ่มข้อมูลได้
		\end{itemize}
		\newpage
		\subsection{โครงสร้างของการสร้างหน้าการจองคิว}
		4.1.8.1 การสร้างหน้าจอส่วนติดต่อผู้ใช้ของหน้าดูคิวจอง
		\begin{figure}[H]
			{\setstretch{1.0}\begin{lstlisting}
<div className="row center">
	<KeyboardDatePicker
		disableToolbar
		variant="inline"
		format="dd/MM/yyyy"
		margin="normal"
		id="date-picker-inline"
		label="เลือกวันที่"
		value={selectedDate}
		onChange={this.handleDateChange}
		KeyboardButtonProps={{
		"aria-label": "change date"
		}}
	/>
</div>
<div className="row">
	<MaterialTable
		title="คิวจอง"
		columns={columns}
		data={data}
		options={{
		selection: false
		}}
	/>
</div>

				\end{lstlisting}}
			\caption{การสร้างหน้าจอส่วนติดต่อผู้ใช้ของหน้าดูคิวจอง Managequeue.js} %TODO ตัวหนังสือแปลกๆ
			\label{Fig:Managequeue}
		\end{figure}
		จากภาพที่ \ref{Fig:Managequeue} โครงสร้างของการสร้างหน้าจอส่วนติดต่อผู้ใช้ของหน้าดูคิวจอง สามารถอธิบายการทำงานได้ดังนี้
		\begin{itemize}[label={--}]
			\item บรรทัดที่ 1-15 เป็นการสร่้างวันที่แบบคีบอร์ดเพื่อเลือกวันที่ในการแสดงข้อมูล
			\item บรรทัดที่ 16-25 ตารางแสดงข้อมูลจองคิว  
		\end{itemize}
	\newpage
	4.1.8.2 การสร้างลอจิกของหน้าดูการจองคิว
		\begin{figure}[H]
			{\setstretch{1.0}\begin{lstlisting}
exports.getBooking = async (req, res) => {
	try {
		let booking = await Booking.findAll();
		res.status(200).send("success");
	} catch (err) {
		console.log(err);
		res.sendStatus(401);
	}
};

				\end{lstlisting}}
			\caption{การสร้างลอจิกของหน้าดูการจองคิว booking.js}
			\label{Fig:BookingJs}
		\end{figure}
		จากภาพที่ \ref{Fig:BookingJs} โครงสร้างลอจิกของหน้าดูการจองคิว สามารถอธิบายการทำงานได้ดังนี้
		\begin{itemize}[label={--}]
			\item บรรทัดที่ 1 เป็นการส่งออกข้อมูลเพื่อใช้ในไฟล์อื่น
			\item บรรทัดที่ 2-9 เป็นการดึงข้อมูลจากฐานข้มูล
			
		\end{itemize}
		\newpage
		\subsection{โครงสร้างของการสร้างหน้าเพิ่มข้อมูลช่าง}
		4.1.9.1 การสร้างหน้าจอส่วนติดต่อผู้ใช้ของหน้าเพิ่มข้อมูลช่าง
		\begin{figure}[H]
			{\setstretch{1.0}\begin{lstlisting}
<TextField
	className={classes.margin}
	id="tel"
	name="tel"
	value={tel}
	label="เบอร์โทร"
	autoComplete="Phone number"
	variant="outlined"
	onChange={this.handleChange}/>
<Button
	color="primary"
	autoFocus
	onClick={() => {
	if (password === password2) {
	const register = axios
	.post("http://localhost:9000/api/auth/register", {
		email: email,
		password: password,
		name: name,
		address: address,
		tel: tel,
		role: "2",	})
	const Beautician = axios
	.post("http://localhost:9000/api/beautician/add", {
		email: email,
		name: name,
		address: address,
		tel: tel,
		shopID: shops.id
	}).then(response => {
	console.log("สร้างผู้ใช้สำเร็จ", response);
	this.handleClose();
	}).catch(error => {
	console.log(error);
	});
	} else {alert("password ไม่ถูกต้อง");} }} > ยืนยัน </Button>
				\end{lstlisting}}
			\caption{การสร้างหน้าจอส่วนติดต่อผู้ใช้ของหน้าเพิ่มข้อมูลช่าง beautician.js}
			\label{Fig:Beautician}
		\end{figure}
		จากภาพที่ \ref{Fig:Beautician} โครงสร้างของการสร้างหน้าจอส่วนติดต่อผู้ใช้ของหน้าเพิ่มข้อมูลช่าง สามารถอธิบายการทำงานได้ดังนี้
		\begin{itemize}[label={--}]
			\item บรรทัดที่ 1-9 เป็นตัวอย่างการสร้าง form เพื่อกรอกข้อมูล
			\item บรรทัดที่ 10-36 เป็นปุ่มยืนยัน และเพิ่มข้อมูลลงฐานข้อมูล
		
		\end{itemize}
	4.1.9.2 การสร้างลอจิกของหน้าสร้างกำหนดการเพิ่มข้อมูลช่าง
		\begin{figure}[H]
			{\setstretch{1.0}\begin{lstlisting}
exports.add = async (req, res) => {
	try {
		const addbeauticianData = req.body;
		console.log(addbeauticianData);
			await Beautician.create({
			name: addbeauticianData.name,
			email: addbeauticianData.email,
			address: addbeauticianData.address,
			tel: addbeauticianData.tel,
			shopID: addbeauticianData.shopID
	});
		res.send("create");
	} catch (err) {
		console.log(err);
		res.sendStatus(401);
	}
};

				\end{lstlisting}}
			\caption{การสร้างลอจิกของหน้าสร้างกำหนดการเพิ่มข้อมูลช่าง beauticianconrolletr.js}
			\label{Fig:BeauticianJS}
		\end{figure}
		จากภาพที่ \ref{Fig:BeauticianJS} โครงสร้างลอจิกของหน้าสร้างกำหนดการเพิ่มข้อมูลช่าง สามารถอธิบายการทำงานได้ดังนี้
		\begin{itemize}[label={--}]
			\item บรรทัดที่ 1 เป็นการส่งออกไฟล์เพื่อใช้ในไฟล์อื่น
			\item บรรทัดที่ 2-17 เป็นคำสั่งที่ใช้ในการเพิ่มข้อมูลช่างลงฐานข้อมูล
		\end{itemize}

	\subsection{โครงสร้างของการสร้างหน้าอัพโหลดรูปภาพ}
	4.1.10.1 การสร้างหน้าจอส่วนติดต่อผู้ใช้ของหน้าอัพโหลดรูปภาพ
\begin{figure}[H]
	{\setstretch{1.0}\begin{lstlisting}	
<Dialog open={open} onClose={this.handleClose}
	aria-labelledby="alert-dialog-title"
	aria-describedby="alert-dialog-description"	>
	<DialogTitle id="alert-dialog-title">{"เพิ่มรูปภาพ"}</DialogTitle>
	<DialogContent>
	<TextField className={classes.margin}
	id="outlined-file-input" label="เพิ่มรูปภาพ"
	type="file" autoComplete="current-password"
	variant="outlined"
	onChange={(e) => {
	this.setState({
	file: e.target.files[0],
	});	}}	/>
	</DialogContent>
	<DialogActions>
	<Button color="primary" autoFocus
	onClick={() => {
	const { location, userInfo } = this.props;
	const formData = new FormData();
	console.log(file);
	formData.append("images", file);
	formData.append("shop_id", shop.id);
	axios
	.post(
	`http://localhost:9000/api/storageshop/upload/work/${shop.id}`,formData)
	.then((response) => {
	console.log("เพิ่มรูปภาพสำเร็จ", response);
	alert("เพิ่มรูปภาพสำเร็จ");
	this.handleClose();
	})
	.catch((error) => {
	console.log(error);
	}); }} >	ยืนยัน </Button>
</DialogActions>	</Dialog>
		\end{lstlisting}}
	\caption{การสร้างหน้าจอส่วนติดต่อผู้ใช้ของหน้าอัพโหลดรูปภาพ Addimage.js}
	\label{Fig:AddimageJS}
\end{figure}
จากภาพที่ \ref{Fig:AddimageJS} โครงสร้างของการสร้างหน้าจอส่วนติดต่อผู้ใช้ของหน้าอัพโหลดรูปภาพ สามารถอธิบายการทำงานได้ดังนี้
\begin{itemize}[label={--}]
	\item บรรทัดที่ 1-4 สร้าง Dialog เพื่อเพิ่มอัพโหลดรูปภาพ
	\item บรรทัดที่ 5-15 สร้าง form สำหรับอัพโหลดรูปภาพ
	\item บรรทัดที่ 16-34 เป็นปุ่มเพื่อเพิ่มข้อมูลลงฐานข้อมูล
	
\end{itemize}
4.10.2 การสร้างลอจิกของหน้าสร้างกำหนดการอัพโหลดรูปภาพ 
\begin{figure}[H]
	{\setstretch{1.0}\begin{lstlisting}
const router = require('express-promise-router')();
const storageshop = require('../../multer');	
const WorkImage = require('../../models/workimage');
const Shop = require('../../models/shop')
router.post('/upload/work/:shopId',storageshop.single('images'), async (req, res) => {
	const images = req.file;
	const shop_id = req.body.shopId
		await WorkImage.create({
			shop_id: req.params.shopId,
			image: images.buffer,
			type: images.mimetype
		});
		res.send('success')
})	
module.exports = router;
		\end{lstlisting}}
	\caption{การสร้างลอจิกของหน้าสร้างกำหนดการอัพโหลดรูปภาพ storageshop.js}
	\label{Fig:Upimage}
\end{figure}
จากภาพที่ \ref{Fig:Upimage} โครงสร้างลอจิกของหน้าสร้างกำหนดการอัพโหลดรูปภาพ สามารถอธิบายการทำงานได้ดังนี้
\begin{itemize}[label={--}]
	\item บรรทัดที่ 1 เป็นการเรียกใช้ package express-promise-router
	\item บรรทัดที่ 2-4 เป็นการเรียกใช้ข้อมูลจากไฟล์อื่น
	\item บรรทัดที่ 5-14  เป็นคำสั่งอัพโหลดรูปภาพ
	\item บรรทัดที่ 15 เป็นการส่งออก module เพื่อใช้ในไฟล์อิ่น
\end{itemize}
