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
eb6f7e3a
Commit
eb6f7e3a
authored
Oct 03, 2023
by
Nawasan Wisitsingkhon
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
create and show cart in controller;
create: cart list ui;
parent
a2278911
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
252 additions
and
27 deletions
+252
-27
CartController.js
app/controllers/CartController.js
+54
-0
user.js
app/routes/user.js
+4
-0
Navbar.js
src/components/Navbar.js
+3
-2
ProductCard.js
src/components/ProductCard.js
+10
-6
_app.js
src/pages/_app.js
+35
-19
cart.js
src/pages/cart.js
+126
-0
index.js
src/pages/index.js
+20
-0
No files found.
app/controllers/CartController.js
0 → 100644
View file @
eb6f7e3a
import
{
Request
,
Response
}
from
"express"
;
import
db
from
"../models/prismaClient"
;
const
CartController
=
{
/**
*
* @param {Request} req
* @param {Response} res
*/
async
index
(
req
,
res
)
{
try
{
let
cart
=
await
db
.
cart
.
findMany
({
where
:
{
user_id
:
Number
(
req
.
user
.
id
)
},
});
res
.
json
({
status
:
101
,
message
:
"fetch success"
,
cart
});
}
catch
(
err
)
{
res
.
json
({
status
:
100
,
message
:
"error on server"
});
}
},
/**
*
* @param {Request} req
* @param {Response} res
*/
async
create
(
req
,
res
)
{
try
{
const
{
id
}
=
req
.
body
;
if
(
!
id
)
throw
200
;
let
check_cart
=
await
db
.
cart
.
findFirst
({
where
:
{
AND
:
{
product_id
:
Number
(
id
),
user_id
:
Number
(
req
.
user
.
id
)
},
},
});
if
(
check_cart
)
throw
202
;
await
db
.
cart
.
create
({
data
:
{
user_id
:
Number
(
req
.
user
.
id
),
product_id
:
Number
(
id
),
},
});
await
db
.
$disconnect
();
res
.
json
({
status
:
201
,
message
:
"add to cart success"
});
}
catch
(
err
)
{
if
(
err
===
202
)
return
res
.
json
({
status
:
202
,
message
:
"this product was added"
,
});
res
.
json
({
status
:
200
,
message
:
"found some error on server"
});
}
},
};
export
default
CartController
;
app/routes/user.js
View file @
eb6f7e3a
import
express
from
"express"
;
import
express
from
"express"
;
import
WishlistController
from
"../controllers/WishlistController"
;
import
WishlistController
from
"../controllers/WishlistController"
;
import
CartController
from
"../controllers/CartController"
;
const
UserRouter
=
express
.
Router
();
const
UserRouter
=
express
.
Router
();
UserRouter
.
get
(
"/wishlist"
,
WishlistController
.
index
);
UserRouter
.
get
(
"/wishlist"
,
WishlistController
.
index
);
UserRouter
.
post
(
"/wishlist"
,
WishlistController
.
create
);
UserRouter
.
post
(
"/wishlist"
,
WishlistController
.
create
);
UserRouter
.
delete
(
"/wishlist"
,
WishlistController
.
delete
);
UserRouter
.
delete
(
"/wishlist"
,
WishlistController
.
delete
);
UserRouter
.
get
(
"/cart"
,
CartController
.
index
);
UserRouter
.
post
(
"/cart"
,
CartController
.
create
);
export
default
UserRouter
;
export
default
UserRouter
;
src/components/Navbar.js
View file @
eb6f7e3a
...
@@ -14,7 +14,7 @@ import MenuIcon from "@mui/icons-material/Menu";
...
@@ -14,7 +14,7 @@ import MenuIcon from "@mui/icons-material/Menu";
import
SearchIcon
from
"@mui/icons-material/Search"
;
import
SearchIcon
from
"@mui/icons-material/Search"
;
import
AccountCircle
from
"@mui/icons-material/AccountCircle"
;
import
AccountCircle
from
"@mui/icons-material/AccountCircle"
;
import
ShoppingCart
from
"@mui/icons-material/ShoppingCart"
;
import
ShoppingCart
from
"@mui/icons-material/ShoppingCart"
;
import
{
UserContext
,
WishlistContext
}
from
"@/pages/_app"
;
import
{
CartContext
,
UserContext
,
WishlistContext
}
from
"@/pages/_app"
;
import
Link
from
"next/link"
;
import
Link
from
"next/link"
;
import
{
Favorite
}
from
"@mui/icons-material"
;
import
{
Favorite
}
from
"@mui/icons-material"
;
import
{
Logout
,
SupervisedUserCircle
}
from
"@mui/icons-material"
;
import
{
Logout
,
SupervisedUserCircle
}
from
"@mui/icons-material"
;
...
@@ -64,6 +64,7 @@ function Navbar(props) {
...
@@ -64,6 +64,7 @@ function Navbar(props) {
const
router
=
useRouter
();
const
router
=
useRouter
();
const
[
search
,
setSearch
]
=
React
.
useState
(
router
.
query
?.
q
??
""
);
const
[
search
,
setSearch
]
=
React
.
useState
(
router
.
query
?.
q
??
""
);
const
wishlist
=
useContext
(
WishlistContext
);
const
wishlist
=
useContext
(
WishlistContext
);
const
cart
=
useContext
(
CartContext
)
const
user
=
useContext
(
UserContext
);
const
user
=
useContext
(
UserContext
);
const
{
window
}
=
props
;
const
{
window
}
=
props
;
...
@@ -139,7 +140,7 @@ function Navbar(props) {
...
@@ -139,7 +140,7 @@ function Navbar(props) {
aria
-
label
=
"show 4 new mails"
aria
-
label
=
"show 4 new mails"
color
=
"inherit"
color
=
"inherit"
>
>
<
Badge
badgeContent
=
{
4
}
color
=
"error"
>
<
Badge
badgeContent
=
{
cart
.
value
.
length
}
color
=
"error"
>
<
ShoppingCart
/>
<
ShoppingCart
/>
<
/Badge
>
<
/Badge
>
<
/IconButton
>
<
/IconButton
>
...
...
src/components/ProductCard.js
View file @
eb6f7e3a
...
@@ -18,18 +18,22 @@ import { UserContext } from "@/pages/_app";
...
@@ -18,18 +18,22 @@ import { UserContext } from "@/pages/_app";
import
axios
from
"axios"
;
import
axios
from
"axios"
;
import
{
headers
}
from
"../../next.config"
;
import
{
headers
}
from
"../../next.config"
;
export
default
function
ProductCard
({
product
,
isFav
,
favHandler
})
{
export
default
function
ProductCard
({
const
user
=
useContext
(
UserContext
);
product
,
const
fav
=
isFav
isFav
,
favHandler
,
cartHandler
,
})
{
const
fav
=
isFav
;
/**
/**
*
*
* @param {number} id
* @param {number} id
* @param {boolean} isRemove
* @param {boolean} isRemove
*/
*/
return
(
return
(
<
div
<
div
className
=
"p-1 m-1 w-[300px] inline-block bg-white rounded hover:shadow duration-300"
className
=
"p-1 m-1 w-[300px] inline-block bg-white rounded hover:shadow duration-300"
sx
=
{{
sx
=
{{
m
:
1
,
m
:
1
,
px
:
1
,
px
:
1
,
...
@@ -69,7 +73,7 @@ export default function ProductCard({ product, isFav, favHandler }) {
...
@@ -69,7 +73,7 @@ export default function ProductCard({ product, isFav, favHandler }) {
>
>
{
fav
?
<
Favorite
/>
:
<
FavoriteBorder
/>
}
{
fav
?
<
Favorite
/>
:
<
FavoriteBorder
/>
}
<
/Button
>
<
/Button
>
<
Button
title
=
"เพิ่มลงตระกร้า"
color
=
"warning"
>
<
Button
title
=
"เพิ่มลงตระกร้า"
color
=
"warning"
onClick
=
{
cartHandler
}
>
<
ShoppingCart
/>
<
ShoppingCart
/>
<
/Button
>
<
/Button
>
<
/span
>
<
/span
>
...
...
src/pages/_app.js
View file @
eb6f7e3a
...
@@ -14,12 +14,23 @@ import axios from "axios";
...
@@ -14,12 +14,23 @@ import axios from "axios";
export
const
UserContext
=
createContext
(
null
);
export
const
UserContext
=
createContext
(
null
);
export
const
WishlistContext
=
createContext
(
null
);
export
const
WishlistContext
=
createContext
(
null
);
export
const
CartContext
=
createContext
(
null
);
export
default
function
App
({
Component
,
pageProps
})
{
export
default
function
App
({
Component
,
pageProps
})
{
const
[
user
,
setUser
]
=
useState
({});
const
[
user
,
setUser
]
=
useState
({});
const
[
wishlist
,
setWishlist
]
=
useState
([]);
const
[
wishlist
,
setWishlist
]
=
useState
([]);
const
[
cart
,
setCart
]
=
useState
([]);
const
pathname
=
usePathname
();
const
pathname
=
usePathname
();
const
fetchCart
=
async
()
=>
{
if
(
!
user
.
token
)
return
;
let
response
=
await
axios
.
get
(
"/api/u/cart"
,
{
headers
:
{
token
:
user
.
token
},
});
if
(
response
.
data
.
status
===
101
)
{
setCart
(
response
.
data
.
cart
);
}
};
const
fetchWishlist
=
async
()
=>
{
const
fetchWishlist
=
async
()
=>
{
if
(
!
user
?.
token
)
return
;
if
(
!
user
?.
token
)
return
;
let
response
=
await
axios
.
get
(
"/api/u/wishlist"
,
{
let
response
=
await
axios
.
get
(
"/api/u/wishlist"
,
{
...
@@ -40,30 +51,35 @@ export default function App({ Component, pageProps }) {
...
@@ -40,30 +51,35 @@ export default function App({ Component, pageProps }) {
},
[]);
},
[]);
useEffect
(()
=>
{
useEffect
(()
=>
{
fetchCart
();
fetchWishlist
();
fetchWishlist
();
},
[
user
]);
},
[
user
]);
return
(
return
(
<
UserContext
.
Provider
value
=
{{
value
:
user
,
set
:
setUser
}}
>
<
UserContext
.
Provider
value
=
{{
value
:
user
,
set
:
setUser
}}
>
<
WishlistContext
.
Provider
value
=
{{
value
:
wishlist
,
set
:
setWishlist
}}
>
<
CartContext
.
Provider
{
pathname
.
split
(
"/"
)[
1
]
===
"admin"
?
(
value
=
{{
value
:
cart
,
set
:
setCart
,
fetch
:
fetchCart
}}
<>
>
{
user
.
rank
?
(
<
WishlistContext
.
Provider
value
=
{{
value
:
wishlist
,
set
:
setWishlist
}}
>
<
AdminLayout
>
{
pathname
.
split
(
"/"
)[
1
]
===
"admin"
?
(
<
Component
{...
pageProps
}
/
>
<>
<
/AdminLayout
>
{
user
.
rank
?
(
)
:
(
<
AdminLayout
>
<
UserLayout
>
<
Component
{...
pageProps
}
/
>
<
Error
/>
<
/AdminLayout
>
<
/UserLayout
>
)
:
(
)}
<
UserLayout
>
<
/
>
<
Error
/>
)
:
(
<
/UserLayout
>
<
UserLayout
>
)}
<
Component
{...
pageProps
}
/
>
<
/
>
<
/UserLayout
>
)
:
(
)}
<
UserLayout
>
<
/WishlistContext.Provider
>
<
Component
{...
pageProps
}
/
>
<
/UserLayout
>
)}
<
/WishlistContext.Provider
>
<
/CartContext.Provider
>
<
/UserContext.Provider
>
<
/UserContext.Provider
>
);
);
}
}
src/pages/cart.js
0 → 100644
View file @
eb6f7e3a
import
{
Box
,
Button
,
Paper
,
Table
,
TableBody
,
TableCell
,
TableHead
,
TableRow
,
}
from
"@mui/material"
;
import
React
,
{
useContext
,
useEffect
,
useState
}
from
"react"
;
import
{
CartContext
,
UserContext
,
WishlistContext
}
from
"./_app"
;
import
{
useRouter
}
from
"next/router"
;
import
axios
from
"axios"
;
import
{
Delete
}
from
"@mui/icons-material"
;
import
{
ShoppingCart
}
from
"@mui/icons-material"
;
import
PopupAlert
from
"@/components/PopupAlert"
;
import
Head
from
"next/head"
;
export
default
function
Cart
()
{
const
user
=
useContext
(
UserContext
);
const
wishlist
=
useContext
(
WishlistContext
);
const
cart
=
useContext
(
CartContext
);
const
[
products
,
setProducts
]
=
useState
([]);
const
[
message
,
setMessage
]
=
useState
({
error
:
false
,
message
:
""
});
const
router
=
useRouter
();
const
[
CartProduct
,
setCartProduct
]
=
useState
([]);
const
removeFromCart
=
async
(
id
)
=>
{};
const
fetchProduct
=
async
()
=>
{
try
{
let
product
=
await
axios
.
get
(
"/api/product"
);
setProducts
(
product
.
data
);
}
catch
(
err
)
{}
};
useEffect
(()
=>
{
fetchProduct
();
},
[]);
useEffect
(()
=>
{
setCartProduct
(
cart
.
value
.
map
(
(
ct
)
=>
products
.
filter
((
pd
)
=>
pd
.
id
===
ct
.
product_id
)[
0
]
)
);
},
[
cart
,
products
]);
return
(
<>
<
Head
>
<
title
>
ตระกร้าสินค้า
|
OpenShop
<
/title
>
<
/Head
>
<
Box
>
<
PopupAlert
open
=
{
!!
message
.
message
.
length
}
isError
=
{
message
.
error
}
message
=
{
message
.
message
}
/
>
<
Paper
sx
=
{{
p
:
1
,
overflowX
:
"scroll"
}}
>
{
wishlist
.
value
.
length
>
0
?
(
<
Table
>
<
TableHead
>
<
TableRow
>
{[
"ลำดับ"
,
"รูปภาพ"
,
"ชื่อสินค้า"
,
"รายละเอียด"
,
"ราคา"
,
"นำออกจากรายการ"
,
].
map
((
label
,
idx
)
=>
(
<
TableCell
key
=
{
idx
}
>
{
label
}
<
/TableCell
>
))}
<
/TableRow
>
<
/TableHead
>
<
TableBody
>
{
CartProduct
.
map
(
(
pdt
,
idx
)
=>
pdt
&&
(
<
TableRow
key
=
{
idx
}
>
<
TableCell
>
{
idx
+
1
}
<
/TableCell
>
<
TableCell
>
<
img
width
=
{
100
}
src
=
{
pdt
.
image
?.
length
?
pdt
.
image
:
"/empty.jpg"
}
alt
=
"รูปสินค้า"
/>
<
/TableCell
>
<
TableCell
>
{
pdt
.
name
}
<
/TableCell
>
<
TableCell
>
<
div
className
=
"max-h-10 overflow-scroll"
>
{
pdt
.
detail
}
<
/div
>
<
/TableCell
>
<
TableCell
>
{
pdt
.
discount
>
0
?
(
<
Box
color
=
{
"orangered"
}
>
<
del
>
$
{
pdt
.
price
}
<
/del>
$
{
pdt
.
price
-
pdt
.
price
*
(
pdt
.
discount
/
100
)}
<
/Box
>
)
:
(
<
Box
color
=
"orangered"
>
$
{
pdt
.
price
}
<
/Box
>
)}
<
/TableCell
>
<
TableCell
>
<
Button
color
=
"error"
onClick
=
{()
=>
removeFromCart
(
pdt
.
id
)}
>
<
Delete
/>
<
/Button
>
<
/TableCell
>
<
/TableRow
>
)
)}
<
/TableBody
>
<
/Table
>
)
:
(
<
div
className
=
"text-center"
>
รายการว่างเปล่า
<
/div
>
)}
<
/Paper
>
<
/Box
>
<
/
>
);
}
src/pages/index.js
View file @
eb6f7e3a
...
@@ -20,6 +20,25 @@ export default function Home() {
...
@@ -20,6 +20,25 @@ export default function Home() {
?
products
.
filter
((
prod
)
=>
String
(
prod
.
name
).
includes
(
router
.
query
.
q
))
?
products
.
filter
((
prod
)
=>
String
(
prod
.
name
).
includes
(
router
.
query
.
q
))
:
products
.
filter
((
prod
)
=>
Number
(
prod
.
stock
)
>
0
);
:
products
.
filter
((
prod
)
=>
Number
(
prod
.
stock
)
>
0
);
async
function
onCart
(
id
,
isRemove
=
false
)
{
if
(
!
user
.
value
?.
token
)
{
setMessage
({
message
:
"คุณยังไม่ได้เข้าสู่ระบบ"
,
error
:
true
});
setTimeout
(()
=>
{
setMessage
({
message
:
""
,
error
:
true
});
},
2000
);
return
;
}
if
(
isRemove
)
{
}
else
{
let
response
=
await
axios
.
post
(
"/api/u/cart"
,
{
id
},
{
headers
:
{
token
:
user
.
value
.
token
}
}
);
console
.
log
(
response
.
data
);
}
}
async
function
onWishlist
(
id
,
isRemove
=
false
)
{
async
function
onWishlist
(
id
,
isRemove
=
false
)
{
if
(
!
user
.
value
?.
token
)
{
if
(
!
user
.
value
?.
token
)
{
setMessage
({
message
:
"คุณยังไม่ได้เข้าสู่ระบบ"
,
error
:
true
});
setMessage
({
message
:
"คุณยังไม่ได้เข้าสู่ระบบ"
,
error
:
true
});
...
@@ -80,6 +99,7 @@ export default function Home() {
...
@@ -80,6 +99,7 @@ export default function Home() {
).
length
).
length
}
}
product
=
{
prod
}
product
=
{
prod
}
cartHandler
=
{()
=>
onCart
(
prod
.
id
)}
favHandler
=
{()
=>
favHandler
=
{()
=>
onWishlist
(
onWishlist
(
prod
.
id
,
prod
.
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