summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRafi Zadanly <zadanlyr@gmail.com>2023-02-20 14:20:44 +0700
committerRafi Zadanly <zadanlyr@gmail.com>2023-02-20 14:20:44 +0700
commite33a330786ffbfcd774de00dc697c6dff47faf27 (patch)
treecd35ce2a36c37cd8c6e991862f929d83dcd45464 /src
parentfdefe7cfe899125a9bd553b542976eed0de919c1 (diff)
fix
Diffstat (limited to 'src')
-rw-r--r--src/core/components/elements/Alert/Alert.jsx21
-rw-r--r--src/core/components/elements/Link/Link.jsx2
-rw-r--r--src/core/components/elements/Sidebar/Sidebar.jsx26
-rw-r--r--src/core/components/elements/Spinner/Spinner.jsx13
-rw-r--r--src/core/utils/greeting.js9
-rw-r--r--src/lib/auth/api/loginApi.js12
-rw-r--r--src/lib/auth/components/Login.jsx99
-rw-r--r--src/lib/cart/components/Cart.jsx6
-rw-r--r--src/pages/login.jsx7
9 files changed, 194 insertions, 1 deletions
diff --git a/src/core/components/elements/Alert/Alert.jsx b/src/core/components/elements/Alert/Alert.jsx
new file mode 100644
index 00000000..3f5584b9
--- /dev/null
+++ b/src/core/components/elements/Alert/Alert.jsx
@@ -0,0 +1,21 @@
+const Alert = ({ children, className, type }) => {
+ let typeClass = ''
+ switch (type) {
+ case 'info':
+ typeClass = 'bg-blue-100 text-blue-900 border-blue-400'
+ break
+ case 'success':
+ typeClass = 'bg-green-100 text-green-900 border-green-400'
+ break
+ case 'warning':
+ typeClass = 'bg-yellow-100 text-yellow-900 border-yellow-400'
+ break
+ }
+ return (
+ <div className={`rounded-md w-full text-medium p-3 border ${typeClass} ${className}`}>
+ {children}
+ </div>
+ )
+}
+
+export default Alert \ No newline at end of file
diff --git a/src/core/components/elements/Link/Link.jsx b/src/core/components/elements/Link/Link.jsx
index a619164d..897cf6d7 100644
--- a/src/core/components/elements/Link/Link.jsx
+++ b/src/core/components/elements/Link/Link.jsx
@@ -5,7 +5,7 @@ const Link = ({ children, ...props }) => {
<NextLink
{...props}
scroll={false}
- className={`block font-medium text-red_r-11 ${props?.className}`}
+ className={`block font-medium text-red_r-11 ${props?.className || ''}`}
>
{children}
</NextLink>
diff --git a/src/core/components/elements/Sidebar/Sidebar.jsx b/src/core/components/elements/Sidebar/Sidebar.jsx
index 249ccbce..74984393 100644
--- a/src/core/components/elements/Sidebar/Sidebar.jsx
+++ b/src/core/components/elements/Sidebar/Sidebar.jsx
@@ -1,14 +1,40 @@
+import { getAuth } from "@/core/utils/auth"
import Link from "../Link/Link"
+import greeting from "@/core/utils/greeting"
+import { Cog6ToothIcon } from "@heroicons/react/24/solid"
const Sidebar = ({
active,
close
}) => {
+ const auth = getAuth()
+
return (
<>
{ active && <div className="overlay z-50" onClick={close}></div> }
<div className={`fixed z-[55] top-0 h-full w-[80%] transition-all ease-linear duration-50 bg-white ${active ? 'left-0' : '-left-[80%]'}`}>
<div className="divide-y divide-gray_r-6">
+ <div className="p-4 flex gap-x-3">
+ { !auth && (
+ <>
+ <Link href="/register" className="btn-yellow !text-gray_r-12 py-2 flex-1">Daftar</Link>
+ <Link href="/login" className="btn-solid-red !text-gray_r-1 py-2 flex-1">Masuk</Link>
+ </>
+ ) }
+ { auth && (
+ <>
+ <div className="text-caption-2 text-gray_r-11">
+ {/* { greeting() }, */}
+ <span className="text-body-2 text-gray_r-12 block mt-1 font-medium">
+ { auth?.name }
+ </span>
+ </div>
+ <Link href="/my/menu" className="!text-gray_r-11 ml-auto my-auto">
+ <Cog6ToothIcon className="w-6" />
+ </Link>
+ </>
+ ) }
+ </div>
<Link href="/" className="px-4 py-3 block !text-gray_r-12 font-normal">
Semua Brand
</Link>
diff --git a/src/core/components/elements/Spinner/Spinner.jsx b/src/core/components/elements/Spinner/Spinner.jsx
new file mode 100644
index 00000000..60f88279
--- /dev/null
+++ b/src/core/components/elements/Spinner/Spinner.jsx
@@ -0,0 +1,13 @@
+const Spinner = ({ className }) => {
+ return (
+ <div role="status">
+ <svg aria-hidden="true" className={"animate-spin " + className} viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg">
+ <path d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" fill="currentColor"/>
+ <path d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" fill="currentFill"/>
+ </svg>
+ <span className="sr-only">Loading...</span>
+ </div>
+ )
+}
+
+export default Spinner \ No newline at end of file
diff --git a/src/core/utils/greeting.js b/src/core/utils/greeting.js
new file mode 100644
index 00000000..014c0e3c
--- /dev/null
+++ b/src/core/utils/greeting.js
@@ -0,0 +1,9 @@
+const greeting = () => {
+ let hours = new Date().getHours()
+ if (hours < 11) return 'Selamat Pagi'
+ if (hours < 15) return 'Selamat Siang'
+ if (hours < 18) return 'Selamat Sore'
+ return 'Selamat Malam'
+}
+
+export default greeting \ No newline at end of file
diff --git a/src/lib/auth/api/loginApi.js b/src/lib/auth/api/loginApi.js
new file mode 100644
index 00000000..4782680c
--- /dev/null
+++ b/src/lib/auth/api/loginApi.js
@@ -0,0 +1,12 @@
+import odooApi from "@/core/api/odooApi"
+
+const loginApi = async ({email, password}) => {
+ let result = await odooApi(
+ 'POST',
+ '/api/v1/user/login',
+ {email, password}
+ )
+ return result
+}
+
+export default loginApi \ No newline at end of file
diff --git a/src/lib/auth/components/Login.jsx b/src/lib/auth/components/Login.jsx
new file mode 100644
index 00000000..e598fe48
--- /dev/null
+++ b/src/lib/auth/components/Login.jsx
@@ -0,0 +1,99 @@
+import Image from "next/image"
+import IndoteknikLogo from "@/images/logo.png"
+import Link from "@/core/components/elements/Link/Link"
+import { useState } from "react"
+import loginApi from "../api/loginApi"
+import { useRouter } from "next/router"
+import Alert from "@/core/components/elements/Alert/Alert"
+import { setAuth } from "@/core/utils/auth"
+
+const Login = () => {
+ const router = useRouter()
+ const [ email, setEmail ] = useState('')
+ const [ password, setPassword ] = useState('')
+ const [ isLoading, setIsLoading ] = useState(false)
+ const [ alert, setAlert ] = useState(null)
+
+ const handleSubmit = async (e) => {
+ e.preventDefault()
+ setIsLoading(true)
+ const login = await loginApi({ email, password })
+ setIsLoading(false)
+
+ if (login.isAuth) {
+ setAuth(login.user)
+ router.push('/')
+ return
+ }
+ switch (login.reason) {
+ case 'NOT_FOUND':
+ setAlert({
+ children: 'Email atau password tidak cocok',
+ type: 'info'
+ })
+ break
+ case 'NOT_ACTIVE':
+ setAlert({
+ children: (
+ <>
+ Email belum diaktivasi,
+ <Link className="text-gray-900" href={`/activate?email=${email}`}>aktivasi sekarang</Link>
+ </>
+ ),
+ type: 'info'
+ })
+ break
+ }
+ }
+
+ return (
+ <div className="p-6 pt-10 flex flex-col items-center">
+ <Link href="/">
+ <Image src={IndoteknikLogo} alt="Logo Indoteknik" width={150} height={50} />
+ </Link>
+ <h1 className="text-2xl mt-4 font-semibold">Mulai Belanja Sekarang</h1>
+ <h2 className="text-gray_r-11 font-normal mt-1 mb-4">Masuk ke akun kamu untuk belanja</h2>
+
+ { alert && (
+ <Alert className="text-center" type={alert.type}>
+ { alert.children }
+ </Alert>
+ ) }
+
+ <form className="w-full mt-6 flex flex-col gap-y-4" onSubmit={handleSubmit}>
+ <div>
+ <label htmlFor="email">Alamat Email</label>
+ <input
+ type="text"
+ id="email"
+ className="form-input w-full mt-3"
+ value={email}
+ onChange={(e) => setEmail(e.target.value)}
+ placeholder="contoh@email.com"
+ />
+ </div>
+ <div>
+ <label htmlFor="password">Kata Sandi</label>
+ <input
+ type="password"
+ id="password"
+ className="form-input w-full mt-3"
+ value={password}
+ onChange={(e) => setPassword(e.target.value)}
+ placeholder="••••••••••••"
+ />
+ </div>
+ <button
+ type="submit"
+ className="btn-solid-red w-full mt-2"
+ disabled={!email || !password || isLoading}
+ >
+ { !isLoading ? 'Masuk' : 'Loading...'}
+ </button>
+ </form>
+ <p className="text-gray_r-11 mt-4">Belum punya akun Indoteknik? <Link href="/register" className="inline">Daftar</Link></p>
+ </div>
+ )
+}
+
+export default Login \ No newline at end of file
diff --git a/src/lib/cart/components/Cart.jsx b/src/lib/cart/components/Cart.jsx
index 4b9dd41f..bb1f21f6 100644
--- a/src/lib/cart/components/Cart.jsx
+++ b/src/lib/cart/components/Cart.jsx
@@ -9,6 +9,7 @@ import { createSlug } from "@/core/utils/slug"
import { useRouter } from "next/router"
import BottomPopup from "@/core/components/elements/Popup/BottomPopup"
import { toast } from "react-hot-toast"
+import Spinner from "@/core/components/elements/Spinner/Spinner"
const Cart = () => {
const router = useRouter()
@@ -119,6 +120,11 @@ const Cart = () => {
</div>
<div className="flex flex-col gap-y-4 px-4">
+ { cart.isLoading && (
+ <div className="flex justify-center my-4">
+ <Spinner className="w-6 text-gray_r-12/50 fill-gray_r-12" />
+ </div>
+ ) }
{ products?.map((product) => (
<div key={product?.id} className="flex">
<button
diff --git a/src/pages/login.jsx b/src/pages/login.jsx
new file mode 100644
index 00000000..b9009b8e
--- /dev/null
+++ b/src/pages/login.jsx
@@ -0,0 +1,7 @@
+import LoginComponent from "@/lib/auth/components/Login"
+
+export default function Login() {
+ return (
+ <LoginComponent />
+ )
+} \ No newline at end of file