Commit 9c4b08df authored by Nawasan Wisitsingkhon's avatar Nawasan Wisitsingkhon

finish state: login front and back;

parent 69925dae
......@@ -3,5 +3,5 @@
# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings
JWT_TOKEN=
DATABASE_URL="mysql://<username>:<password>@localhost:3306/<db_name>?schema=public"
\ No newline at end of file
import { Request, Response } from "express";
import { SHA1 } from "crypto-js";
import db from "../models/prismaClient";
import { JwtGenerate } from "@/components/lib/jwttoken";
const UserController = {
/**
......@@ -62,6 +63,44 @@ const UserController = {
});
}
},
/**
*
* @param {Request} req
* @param {Response} res
*/
async login(req, res) {
try {
let { username, password } = req.body;
if (!(username && password)) throw 202;
password = SHA1(password).toString();
let user = await db.user.findFirst({
where: { AND: { username } },
});
if (!user) throw 203;
if (user.password !== password) throw 203;
let token = JwtGenerate({
id: user.id,
name: user.name,
email: user.email,
phone: user.phone,
photo: user.photo,
username: user.username,
rank: user.rank,
});
return res.json({ status: 201, token, message: "login success" });
} catch (err) {
if (err === 203)
return res.json({
status: 203,
message: "usrname or password is wrong",
});
else if (err === 202)
res.json({ status: 202, message: "error data emty", req: req.body });
else {
res.json({ status: 200, err, message: "error something" });
}
}
},
};
export default UserController;
......@@ -5,6 +5,7 @@ const route = express.Router();
route.get("/", WelcomeController.index);
route.post("/user/auth", UserController.login);
route.post("/user", UserController.create);
route.get("/user", (req, res) => {
res.json({
......
......@@ -13,17 +13,11 @@ import Menu from "@mui/material/Menu";
import MenuIcon from "@mui/icons-material/Menu";
import SearchIcon from "@mui/icons-material/Search";
import AccountCircle from "@mui/icons-material/AccountCircle";
import MailIcon from "@mui/icons-material/Mail";
import { Divider } from "@mui/material";
import List from "@mui/material/List";
import { ListItem } from "@mui/material";
import { ListItemButton } from "@mui/material";
import { ListItemIcon } from "@mui/material";
import InboxIcon from "@mui/icons-material/MoveToInbox";
import ListItemText from "@mui/material/ListItemText";
import ShoppingCart from "@mui/icons-material/ShoppingCart";
import { UserContext } from "@/pages/_app";
import Link from "next/link";
import { Favorite } from "@mui/icons-material";
import { Logout } from "@mui/icons-material";
const Search = styled("div")(({ theme }) => ({
position: "relative",
......@@ -65,26 +59,6 @@ const StyledInputBase = styled(InputBase)(({ theme }) => ({
},
}));
const drawer = (
<div>
<Toolbar />
<Divider />
<List>
{["Inbox", "Starred", "Send email", "Drafts"].map((text, index) => (
<ListItem key={index} disablePadding>
<ListItemButton>
<ListItemIcon>
{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}
</ListItemIcon>
<ListItemText primary={text} />
</ListItemButton>
</ListItem>
))}
</List>
{/* <Divider /> */}
</div>
);
function Navbar(props) {
const user = useContext(UserContext);
const { window } = props;
......@@ -143,7 +117,21 @@ function Navbar(props) {
const MenuList = user?.value?.name
? [
{
id: 0,
label: "สินค้าที่ชอบ",
link: "/wishlist",
element: (
<IconButton
size="large"
aria-label="show 4 new mails"
color="inherit"
>
<Badge badgeContent={4} color="error">
<Favorite />
</Badge>
</IconButton>
),
},
{
label: "ตระกร้า",
link: "/cart",
element: (
......@@ -159,8 +147,7 @@ function Navbar(props) {
),
},
{
id: 1,
label: "โปรไฟล์",
label: user.value.name,
link: "/profile",
element: (
<IconButton
......@@ -175,15 +162,39 @@ function Navbar(props) {
</IconButton>
),
},
{
label: "ออกจากระบบ",
link: "/logout",
element: (
<IconButton
size="large"
aria-label="show 4 new mails"
color="inherit"
>
<Badge color="error">
<Logout />
</Badge>
</IconButton>
),
},
]
: [
{
id: 0,
label: "Register",
element: <span className="inline-block mx-3 hover:underline">Register</span>,
element: (
<span className="inline-block mx-3 hover:underline">Register</span>
),
link: "/register",
},
{ id: 1, lable: "Login", element: <span className="inline-block mx-3 hover:underline">Login</span>, link: "/login" },
{
id: 1,
lable: "Login",
element: (
<span className="inline-block mx-3 hover:underline">Login</span>
),
link: "/login",
},
];
const mobileMenuId = "primary-search-account-menu-mobile";
......
import jwt from "jsonwebtoken";
/**
*
* @param {{id: number, name: string, email: string, phone: string, photo: string, username: string }} data
*/
export const JwtGenerate = (data) => {
let token = jwt.sign(data, process.env.JWT_TOKEN, { algorithm: "HS256" });
return token;
};
......@@ -7,6 +7,12 @@ class userCookie {
isLogin() {
return !!this.token;
}
store(token) {
Cookies.set("token", token);
}
delete() {
Cookies.remove("token");
}
}
export default userCookie;
......@@ -5,12 +5,25 @@ import "@fontsource/roboto/500.css";
import "@fontsource/roboto/700.css";
import { createContext, useState, useEffect } from "react";
import UserLayout from "@/components/layout/UserLayout";
import userCookie from "@/components/lib/userCookie";
// axios.defaults.baseURL = ""
export const UserContext = createContext(null);
export default function App({ Component, pageProps }) {
const [user, setUser] = useState({});
useEffect(() => {
const usrcookie = new userCookie();
let token = usrcookie.token.split(".")[1];
if (token) {
let user_info = JSON.parse(atob(token));
user_info.token = usrcookie.token;
setUser(user_info);
console.log(user_info);
}
}, []);
return (
<UserContext.Provider value={{ value: user, set: setUser }}>
<UserLayout>
......
import { Box, Button, Divider, Grid, TextField } from "@mui/material";
import { Snackbar } from "@mui/material";
import React from "react";
import { useContext } from "react";
import { UserContext } from "./_app";
import { Container } from "@mui/material";
import { Google } from "@mui/icons-material";
import { useState } from "react";
import axios from "axios";
import userCookie from "@/components/lib/userCookie";
export default function Login() {
const user = useContext(UserContext);
const [errorMessage, setErrorMessage] = useState("");
const [successMessage, setSuccessMessage] = useState("");
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
if (user.value?.name)
return (
<div>
<h3>{user.value.name}</h3>
</div>
);
/**
*
* @param {FormDataEvent} e
*/
async function onSubmitForm(e) {
e.preventDefault();
let response = await axios.post("/api/user/auth", { username, password });
console.log(response.data);
if (response.data.status === 201) {
const usrsto = new userCookie();
usrsto.store(response.data.token);
window.location.href = '/'
} else if (response.data.status === 203) {
setErrorMessage("ชื่อผู้ใช้หรือระหัสผ่านไม่ถูกต้อง");
setTimeout(() => {
setErrorMessage("");
}, 3000);
}
}
return (
<div>
<Container>
<Snackbar
ContentProps={{ className: "bg-red-500" }}
anchorOrigin={{ horizontal: "center", vertical: "top" }}
open={!!errorMessage.length}
message={errorMessage}
/>
<Snackbar
ContentProps={{ className: "bg-green-500" }}
anchorOrigin={{ horizontal: "center", vertical: "top" }}
open={!!successMessage.length}
message={successMessage}
/>
<Grid container>
<Grid item lg={3} md={0}></Grid>
<Grid item lg={6} md={12}>
<div className="border border-red-500 bg-white py-3 text-center rounded-lg">
<form onSubmit={onSubmitForm} className="">
<Box component={"h2"} className="text-gray-700">
เข้าสู่ระบบ
</Box>
<TextField
label="username"
variant="standard"
className="mx-3 my-1"
value={username}
onChange={(e) => setUsername(e.target.value)}
required
/>
<TextField
label="password"
type="password"
variant="standard"
className="mx-3 my-1"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
/>
<div className="text-right px-10 sm:px-16">
<Button
className="my-5 text-lg"
variant="contained"
type="submit"
>
เข้าสู่ระบบ
</Button>
</div>
</form>
<Divider />
<Box component={"h4"}>หรือเข้าสู่ระบบด้วยบัญชี google</Box>
<button className="bg-white rounded-full border-none hover:shadow-md shadow-gray-400 duration-300 hover:-translate-y-1 cursor-pointer hover:scale-105">
<Google color="primary" fontSize="large" />
</button>
</div>
</Grid>
<Grid item lg={3} md={0}></Grid>
</Grid>
</Container>
</div>
);
}
import userCookie from "@/components/lib/userCookie";
import { useRouter } from "next/router";
import React from "react";
export default function Logout() {
React.useEffect(() => {
const usr = new userCookie();
usr.delete();
window.location.href = '/'
}, []);
return <div>Logout</div>;
}
......@@ -70,13 +70,13 @@ export default function Login() {
<Snackbar
ContentProps={{ className: "bg-red-500" }}
anchorOrigin={{ horizontal: "center", vertical: "top" }}
open={errorMessage.length}
open={!!errorMessage.length}
message={errorMessage}
/>
<Snackbar
ContentProps={{ className: "bg-green-500" }}
anchorOrigin={{ horizontal: "center", vertical: "top" }}
open={successMessage.length}
open={!!successMessage.length}
message={successMessage}
/>
<Grid container>
......@@ -136,6 +136,7 @@ export default function Login() {
className="mx-3 my-1"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
/>
<div className="text-right px-10 sm:px-16">
<Button
......@@ -149,7 +150,7 @@ export default function Login() {
</form>
<Divider />
<Box component={"h4"}>หรือสมัครด้วยบัญชี google</Box>
<button className="bg-white rounded-full border-none hover:shadow-md shadow-gray-400 duration-300 hover:-translate-y-1">
<button className="bg-white rounded-full border-none hover:shadow-md shadow-gray-400 duration-300 hover:-translate-y-1 cursor-pointer hover:scale-105">
<Google color="primary" fontSize="large" />
</button>
</div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment