Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
F
final-exam
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Nawasan Wisitsingkhon
final-exam
Commits
568e03d1
Commit
568e03d1
authored
Oct 01, 2023
by
Nawasan Wisitsingkhon
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
delete product
parent
bbf90a9e
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
385 additions
and
75 deletions
+385
-75
AdminProductController.js
app/controllers/AdminProductController.js
+51
-6
admin.js
app/routes/admin.js
+4
-1
DeleteCategory.js
src/components/category/DeleteCategory.js
+1
-2
AddProduct.js
src/components/product/AddProduct.js
+3
-6
DeleteProduct.js
src/components/product/DeleteProduct.js
+63
-0
UpdateProduct.js
src/components/product/UpdateProduct.js
+175
-0
stock.js
src/pages/admin/stock.js
+88
-60
No files found.
app/controllers/AdminProductController.js
View file @
568e03d1
...
...
@@ -25,15 +25,61 @@ const AdminProductController = {
await
db
.
$disconnect
();
res
.
json
({
status
:
201
,
message
:
"add product success"
});
}
catch
(
err
)
{
console
.
log
(
err
);
console
.
log
(
err
);
res
.
json
({
status
:
200
,
message
:
"error in server"
,
err
err
,
});
}
},
/**
*
* @param {Request} req
* @param {Response} res
*/
async
update
(
req
,
res
)
{
try
{
const
{
id
,
name
,
price
,
detail
,
discount
,
stock
,
image
,
category
}
=
req
.
body
;
await
db
.
product
.
update
({
where
:
{
id
:
Number
(
id
)
},
data
:
{
name
,
price
,
detail
,
discount
:
Number
(
discount
),
stock
,
image
,
cateId
:
Number
(
category
),
},
});
await
db
.
$disconnect
();
return
res
.
json
({
status
:
301
,
message
:
"update success"
});
}
catch
(
err
)
{
console
.
log
(
err
);
res
.
json
({
status
:
300
,
message
:
"update failed with some error on server"
,
});
}
},
/**
*
* @param {Request} req
* @param {Response} res
*/
async
delete
(
req
,
res
)
{
try
{
const
{
id
}
=
req
.
query
;
if
(
!
id
)
throw
400
;
await
db
.
product
.
delete
({
where
:
{
id
:
Number
(
id
)
}
});
res
.
json
({
status
:
401
,
message
:
"delete success"
});
}
catch
(
err
)
{
console
.
log
(
err
);
res
.
json
({
status
:
400
,
message
:
"delete failed with some error"
});
}
},
};
}
export
default
AdminProductController
;
\ No newline at end of file
export
default
AdminProductController
;
app/routes/admin.js
View file @
568e03d1
...
...
@@ -6,8 +6,11 @@ const adminRouter = express.Router();
adminRouter
.
get
(
"/user"
,
AdminUserController
.
index
);
adminRouter
.
post
(
"/product"
,
AdminProductController
.
create
);
adminRouter
.
put
(
"/product"
,
AdminProductController
.
update
);
adminRouter
.
delete
(
"/product"
,
AdminProductController
.
delete
);
adminRouter
.
post
(
"/category"
,
CategoryController
.
create
);
adminRouter
.
put
(
"/category"
,
CategoryController
.
update
);
adminRouter
.
delete
(
'/category'
,
CategoryController
.
delete
)
adminRouter
.
delete
(
"/category"
,
CategoryController
.
delete
);
export
default
adminRouter
;
src/components/category/DeleteCategory.js
View file @
568e03d1
import
{
useState
,
use
Effect
,
use
Context
}
from
"react"
;
import
{
useState
,
useContext
}
from
"react"
;
import
Button
from
"@mui/material/Button"
;
import
TextField
from
"@mui/material/TextField"
;
import
Dialog
from
"@mui/material/Dialog"
;
import
DialogActions
from
"@mui/material/DialogActions"
;
import
DialogContent
from
"@mui/material/DialogContent"
;
...
...
src/components/AddProduct.js
→
src/components/
product/
AddProduct.js
View file @
568e03d1
...
...
@@ -6,6 +6,7 @@ import DialogActions from "@mui/material/DialogActions";
import
DialogContent
from
"@mui/material/DialogContent"
;
import
DialogTitle
from
"@mui/material/DialogTitle"
;
import
{
Alert
,
FormControl
,
InputLabel
,
MenuItem
,
...
...
@@ -78,12 +79,8 @@ export default function AddProduct({ open, handleClose }) {
<>
<
Snackbar
anchorOrigin
=
{{
horizontal
:
"center"
,
vertical
:
"top"
}}
ContentProps
=
{{
className
:
message
.
error
?
"bg-red-500"
:
"bg-green-500"
,
}}
open
=
{
!!
message
.
message
.
length
}
message
=
{
message
.
message
}
/
>
open
=
{
!!
message
.
message
.
length
}
><
Alert
severity
=
{
message
.
error
?
"error"
:
"success"
}
>
{
message
.
message
}
<
/Alert></
Snackbar
>
<
Dialog
open
=
{
open
}
onClose
=
{
handleClose
}
>
<
form
onSubmit
=
{
fetchAddProduct
}
>
<
DialogTitle
>
เพิ่มสินค้า
<
/DialogTitle
>
...
...
src/components/product/DeleteProduct.js
0 → 100644
View file @
568e03d1
import
{
useState
,
useContext
}
from
"react"
;
import
Button
from
"@mui/material/Button"
;
import
Dialog
from
"@mui/material/Dialog"
;
import
DialogActions
from
"@mui/material/DialogActions"
;
import
DialogContent
from
"@mui/material/DialogContent"
;
import
DialogTitle
from
"@mui/material/DialogTitle"
;
import
{
Alert
,
Snackbar
}
from
"@mui/material"
;
import
axios
from
"axios"
;
import
{
UserContext
}
from
"@/pages/_app"
;
export
default
function
DeleteProduct
({
open
,
handleClose
,
id
})
{
const
user
=
useContext
(
UserContext
);
const
[
message
,
setMessage
]
=
useState
({
message
:
""
,
error
:
false
});
async
function
onDeleteProduct
()
{
try
{
let
response
=
await
axios
.
delete
(
`/api/admin/product?id=
${
id
}
`
,
{
headers
:
{
token
:
user
.
value
.
token
},
});
if
(
response
.
data
.
status
===
401
)
{
setMessage
({
error
:
false
,
message
:
"สบสำเร็จ!"
});
setTimeout
(()
=>
{
handleClose
();
setMessage
({
error
:
false
,
message
:
""
});
},
1000
);
}
}
catch
(
err
)
{
setMessage
({
error
:
true
,
message
:
"พบข้อผิดพลาด ไม่สามารถลบได้"
});
setTimeout
(()
=>
{
setMessage
({
error
:
false
,
message
:
""
});
},
3000
);
}
}
return
(
<>
<
Snackbar
anchorOrigin
=
{{
horizontal
:
"center"
,
vertical
:
"top"
}}
ContentProps
=
{{
className
:
message
.
error
?
"bg-red-500"
:
"bg-green-500"
,
}}
open
=
{
!!
message
.
message
.
length
}
message
=
{
message
.
message
}
>
<
Alert
severity
=
{
message
.
error
?
"error"
:
"success"
}
>
{
message
.
message
}
<
/Alert
>
<
/Snackbar
>
<
Dialog
open
=
{
open
}
onClose
=
{
handleClose
}
>
<
DialogTitle
>
ยืนยันการลบ
<
/DialogTitle
>
<
DialogContent
className
=
"text-center"
>
เมื่อกดลบแล้วจะไม่สามารถกู้คืนได้
<
/DialogContent
>
<
DialogActions
>
<
Button
color
=
"error"
onClick
=
{
handleClose
}
>
ยกเลิก
<
/Button
>
<
Button
onClick
=
{
onDeleteProduct
}
>
ยืนยัน
<
/Button
>
<
/DialogActions
>
<
/Dialog
>
<
/
>
);
}
src/components/product/UpdateProduct.js
0 → 100644
View file @
568e03d1
import
{
useState
,
useEffect
,
useContext
}
from
"react"
;
import
Button
from
"@mui/material/Button"
;
import
TextField
from
"@mui/material/TextField"
;
import
Dialog
from
"@mui/material/Dialog"
;
import
DialogActions
from
"@mui/material/DialogActions"
;
import
DialogContent
from
"@mui/material/DialogContent"
;
import
DialogTitle
from
"@mui/material/DialogTitle"
;
import
{
Alert
,
FormControl
,
InputLabel
,
MenuItem
,
Select
,
Snackbar
,
}
from
"@mui/material"
;
import
axios
from
"axios"
;
import
{
UserContext
}
from
"@/pages/_app"
;
export
default
function
UpdateProduct
({
open
,
handleClose
,
data
})
{
const
user
=
useContext
(
UserContext
);
const
[
categoryList
,
setCategoryList
]
=
useState
([]);
const
[
message
,
setMessage
]
=
useState
({
message
:
""
,
error
:
false
});
const
[
name
,
setName
]
=
useState
(
data
.
name
);
const
[
price
,
setPrice
]
=
useState
(
data
.
price
);
const
[
detail
,
setDetail
]
=
useState
(
data
.
detail
);
const
[
discount
,
setDiscount
]
=
useState
(
data
.
discount
);
const
[
stock
,
setStock
]
=
useState
(
data
.
stock
);
const
[
image
,
setImage
]
=
useState
(
data
.
image
);
const
[
category
,
setCategory
]
=
useState
(
Number
(
data
.
cateId
));
useEffect
(()
=>
{
axios
.
get
(
"/api/category"
).
then
((
res
)
=>
{
setCategoryList
(
res
.
data
);
});
},
[]);
/**
*
* @param {FormDataEvent} e
*/
async
function
fetchUpdateProduct
(
e
)
{
e
.
preventDefault
();
let
response
=
await
axios
.
put
(
"/api/admin/product"
,
{
id
:
data
.
id
,
name
,
price
,
detail
,
discount
,
stock
,
image
,
category
,
},
{
headers
:
{
token
:
user
.
value
.
token
}
}
);
console
.
log
(
response
.
data
);
if
(
response
.
data
.
status
===
301
)
{
setMessage
({
message
:
"แก้ไขสินค้าสำเร็จ"
,
error
:
false
});
setTimeout
(()
=>
{
handleClose
();
setMessage
({
message
:
""
,
error
:
false
});
},
2000
);
}
else
{
setMessage
({
message
:
"เกิดข้อผิดพลาด กรุณาลองอีกคร้ัง"
,
error
:
true
});
setTimeout
(()
=>
{
setMessage
({
message
:
""
,
error
:
false
});
},
3000
);
}
}
return
(
<>
<
Snackbar
anchorOrigin
=
{{
horizontal
:
"center"
,
vertical
:
"top"
}}
open
=
{
!!
message
.
message
.
length
}
message
=
{
message
.
message
}
>
<
Alert
severity
=
{
message
.
error
?
"error"
:
"success"
}
>
{
message
.
message
}
<
/Alert
>
<
/Snackbar
>
<
Dialog
open
=
{
open
}
onClose
=
{
handleClose
}
>
<
form
onSubmit
=
{
fetchUpdateProduct
}
>
<
DialogTitle
>
แก้ไขสินค้า
<
/DialogTitle
>
<
DialogContent
className
=
"text-center"
>
<
TextField
className
=
"m-1"
label
=
"ชื่อสินค้า"
variant
=
"standard"
value
=
{
name
}
onChange
=
{(
e
)
=>
setName
(
e
.
target
.
value
)}
required
/>
<
TextField
className
=
"m-1"
label
=
"ราคา"
variant
=
"standard"
type
=
"number"
value
=
{
price
}
onChange
=
{(
e
)
=>
setPrice
(
Number
(
e
.
target
.
value
))}
required
/>
<
div
className
=
"text-left"
>
<
TextField
fullWidth
className
=
"m-1"
label
=
"รายละเอียด"
variant
=
"standard"
multiline
rows
=
{
3
}
value
=
{
detail
}
onChange
=
{(
e
)
=>
setDetail
(
e
.
target
.
value
)}
required
/>
<
/div
>
<
div
className
=
"text-left"
>
<
TextField
className
=
"m-1"
label
=
"ส่วนลด (%)"
variant
=
"standard"
type
=
"number"
value
=
{
discount
}
onChange
=
{(
e
)
=>
setDiscount
(
e
.
target
.
value
)}
required
/>
<
TextField
className
=
"m-1"
label
=
"จำนวนสินค้า"
variant
=
"standard"
type
=
"number"
value
=
{
stock
}
onChange
=
{(
e
)
=>
setStock
(
e
.
target
.
value
)}
required
/>
<
/div
>
<
TextField
label
=
"รูปภาพ"
variant
=
"standard"
fullWidth
helperText
=
"https://www.domain.com/image.png"
value
=
{
image
}
onChange
=
{(
e
)
=>
setImage
(
e
.
target
.
value
)}
/
>
<
FormControl
className
=
"m-1"
variant
=
"standard"
sx
=
{{
minWidth
:
100
}}
>
<
InputLabel
>
หมวดหมู่
<
/InputLabel
>
<
Select
value
=
{
category
}
onChange
=
{(
e
)
=>
setCategory
(
Number
(
e
.
target
.
value
))}
required
>
{
categoryList
.
map
((
cat
,
idx
)
=>
(
<
MenuItem
key
=
{
idx
}
value
=
{
cat
.
id
}
>
{
cat
.
name
}
<
/MenuItem
>
))}
<
/Select
>
<
/FormControl
>
<
/DialogContent
>
<
DialogActions
>
<
Button
color
=
"error"
onClick
=
{
handleClose
}
>
ยกเลิก
<
/Button
>
<
Button
type
=
"submit"
>
เพิ่ม
<
/Button
>
<
/DialogActions
>
<
/form
>
<
/Dialog
>
<
/
>
);
}
src/pages/admin/stock.js
View file @
568e03d1
import
{
AddShoppingCart
}
from
"@mui/icons-material"
;
import
AddProduct
from
"@/components/AddProduct"
;
import
AddProduct
from
"@/components/
product/
AddProduct"
;
import
{
Box
,
Button
,
...
...
@@ -18,17 +18,21 @@ import axios from "axios";
import
Head
from
"next/head"
;
import
{
Delete
}
from
"@mui/icons-material"
;
import
{
Edit
}
from
"@mui/icons-material"
;
import
UpdateProduct
from
"@/components/product/UpdateProduct"
;
import
DeleteProduct
from
"@/components/product/DeleteProduct"
;
export
default
function
Stock
()
{
const
[
modal
,
setModal
]
=
useState
(
false
);
const
[
products
,
setProducts
]
=
useState
([]);
const
[
updateState
,
setUpdateState
]
=
useState
({
open
:
false
,
data
:
{}
});
const
[
deleteState
,
setDeleteState
]
=
useState
({
open
:
false
,
id
:
-
1
});
const
[
category
,
setCategory
]
=
useState
([]);
useEffect
(()
=>
{
axios
.
get
(
"/api/product"
).
then
((
res
)
=>
{
console
.
log
(
res
.
data
);
setProducts
(
res
.
data
);
});
},
[
modal
]);
},
[
modal
,
updateState
,
deleteState
]);
useEffect
(()
=>
{
axios
.
get
(
"/api/category"
).
then
((
res
)
=>
{
setCategory
(
res
.
data
);
...
...
@@ -37,64 +41,88 @@ export default function Stock() {
return
(
<>
<
Head
>
<
title
>
รายการสินค้า
|
admin
<
/title
>
<
/Head
>
<
Box
>
<
Box
sx
=
{{
mb
:
2
,
textAlign
:
"right"
}}
>
<
Button
onClick
=
{()
=>
setModal
(
!
modal
)}
>
<
AddShoppingCart
/>
เพิ่มสินค้า
<
/Button
>
<
Head
>
<
title
>
รายการสินค้า
|
admin
<
/title
>
<
/Head
>
<
Box
>
<
Box
sx
=
{{
mb
:
2
,
textAlign
:
"right"
}}
>
<
Button
onClick
=
{()
=>
setModal
(
!
modal
)}
>
<
AddShoppingCart
/>
เพิ่มสินค้า
<
/Button
>
<
/Box
>
{
products
.
map
((
product
,
idx
)
=>
(
<
Card
key
=
{
idx
}
sx
=
{{
m
:
1
,
px
:
1
,
width
:
300
,
height
:
500
,
display
:
"inline-block"
,
}}
>
<
Box
sx
=
{{
px
:
1
}}
>
<
h5
className
=
"h-[40px] overflow-y-hidden"
>
{
product
.
name
}
<
/h5
>
<
/Box
>
<
CardMedia
className
=
"rounded"
component
=
{
"img"
}
height
=
{
150
}
image
=
{
product
.
image
.
length
?
product
.
image
:
"/empty.jpg"
}
/
>
<
CardContent
sx
=
{{
px
:
1
}}
>
<
Typography
sx
=
{{
height
:
70
,
overflowY
:
"scroll"
}}
variant
=
"body2"
color
=
{
"text.secondary"
}
>
{
product
.
detail
}
<
/Typography
>
<
Table
sx
=
{{
m
:
0
,
p
:
0
}}
>
<
TableBody
>
<
TableRow
sx
=
{{
m
:
0
,
p
:
0
}}
>
<
TableCell
sx
=
{{
m
:
0
,
p
:
0
,
textAlign
:
"center "
}}
>
{
Number
(
product
.
price
).
toLocaleString
()
+
" บาท"
}
<
/TableCell
>
<
TableCell
>
{
`ส่วนลด
${
product
.
discount
}
%`
}
<
/TableCell
>
<
/TableRow
>
<
TableRow
>
<
TableCell
>
เข้าชม
{
product
.
watch_count
}
ครั้ง
<
/TableCell
>
<
TableCell
>
คงเหลือ
{
product
.
stock
}
ชิ้น
<
/TableCell
>
<
/TableRow
>
<
/TableBody
>
<
/Table
>
<
/CardContent
>
<
CardActions
disableSpacing
sx
=
{{
justifyContent
:
"end"
}}
>
<
Button
color
=
"warning"
onClick
=
{()
=>
setUpdateState
({
open
:
true
,
data
:
product
})}
>
<
Edit
/>
แก้ไข
<
/Button
>
<
Button
color
=
"error"
onClick
=
{()
=>
setDeleteState
({
open
:
true
,
id
:
product
.
id
})}
>
<
Delete
/>
ลบ
<
/Button
>
<
/CardActions
>
<
/Card
>
))}
<
AddProduct
open
=
{
modal
}
handleClose
=
{()
=>
setModal
(
false
)}
/
>
<
/Box
>
{
products
.
map
((
product
,
idx
)
=>
(
<
Card
sx
=
{{
m
:
1
,
px
:
1
,
width
:
300
,
height
:
500
,
display
:
"inline-block"
}}
>
<
Box
sx
=
{{
px
:
1
}}
>
<
h5
className
=
"h-[40px] overflow-y-hidden"
>
{
product
.
name
}
<
/h5
>
<
/Box
>
<
CardMedia
className
=
"rounded"
component
=
{
"img"
}
height
=
{
150
}
image
=
{
product
.
image
.
length
?
product
.
image
:
"/empty.jpg"
}
/
>
<
CardContent
sx
=
{{
px
:
1
}}
>
<
Typography
sx
=
{{
height
:
70
,
overflowY
:
"scroll"
}}
variant
=
"body2"
color
=
{
"text.secondary"
}
>
{
product
.
detail
}
<
/Typography
>
<
Table
sx
=
{{
m
:
0
,
p
:
0
}}
>
<
TableBody
>
<
TableRow
sx
=
{{
m
:
0
,
p
:
0
}}
>
<
TableCell
sx
=
{{
m
:
0
,
p
:
0
,
textAlign
:
"center "
}}
>
{
Number
(
product
.
price
).
toLocaleString
()
+
" บาท"
}
<
/TableCell
>
<
TableCell
>
{
`ส่วนลด
${
product
.
discount
}
%`
}
<
/TableCell
>
<
/TableRow
>
<
TableRow
>
<
TableCell
>
เข้าชม
{
product
.
watch_count
}
ครั้ง
<
/TableCell
>
<
TableCell
>
คงเหลือ
{
product
.
stock
}
ชิ้น
<
/TableCell
>
<
/TableRow
>
<
/TableBody
>
<
/Table
>
<
/CardContent
>
<
CardActions
disableSpacing
sx
=
{{
justifyContent
:
"end"
}}
>
<
Button
color
=
"warning"
>
<
Edit
/>
แก้ไข
<
/Button
>
<
Button
color
=
"error"
>
<
Delete
/>
ลบ
<
/Button
>
<
/CardActions
>
<
/Card
>
))}
<
AddProduct
open
=
{
modal
}
handleClose
=
{()
=>
setModal
(
false
)}
/
>
<
/Box
>
{
updateState
.
open
&&
(
<
UpdateProduct
open
=
{
updateState
.
open
}
handleClose
=
{()
=>
setUpdateState
({
open
:
false
,
data
:
{}
})}
data
=
{
updateState
.
data
}
/
>
)}
{
deleteState
.
open
&&
(
<
DeleteProduct
open
=
{
deleteState
.
open
}
handleClose
=
{()
=>
setDeleteState
({
open
:
false
,
id
:
-
1
})}
id
=
{
deleteState
.
id
}
/
>
)}
<
/
>
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment