diff --git a/components/template.jsx b/components/template.jsx index b318f84b66350a373d0a424934334b57565ddb1e..b2180297dec59663d0254cb74b9264ebd0ccfe28 100644 --- a/components/template.jsx +++ b/components/template.jsx @@ -12,7 +12,7 @@ const Template = ({ children }) => { const handleLogout = (e) => { e.preventDefault(); window.localStorage.removeItem("token"); - window.location.reload(); + window.location.replace("/"); } useEffect(() => { const token = window.localStorage.getItem("token") diff --git a/components/templatenofooter.jsx b/components/templatenofooter.jsx new file mode 100644 index 0000000000000000000000000000000000000000..7682e9376d7a36fe50d81138698b3ecdc67affb6 --- /dev/null +++ b/components/templatenofooter.jsx @@ -0,0 +1,46 @@ +import Image from "next/image" +import { useRouter } from "next/router" +import { useEffect, useState } from "react" +const Template = ({ children }) => { + const router = useRouter() + const [userObject, setUser] = useState(null) + const handleLogin = (e) => { + e.preventDefault(); + router.push("/auth/login") + return; + } + const handleLogout = (e) => { + e.preventDefault(); + window.localStorage.removeItem("token"); + window.location.replace("/"); + } + useEffect(() => { + const token = window.localStorage.getItem("token") + if (!token) return; + const tokenParsed = token.split(" ")[1] + fetch(`https://rpl-backend-production.up.railway.app/v1/auth/verify/${tokenParsed}`).then(async (response) => { + if (response.status !== 200) return null; + const responsejson = await response.json(); + setUser(responsejson.data) + }).catch(error=>{ + console.error(error) + return + }) + }, []) + return <> + <header className="flex flex-row align-middle justify-between bg-[#AEDEFC] px-10"> + <div className="flex flex-row align-middle justify-center space-x-3"> + <Image src="/logo.png" alt="Main Logo" width={100} height={100} /> + <span className="h-min my-auto font-bold text-xl">SISTEM MANAJEMEN KURSUS MENGEMUDI RPL</span> + </div> + <div className="flex flex-row align-middle justify-center space-x-6"> + {userObject === null && <span className="h-min my-auto font-semibold">Login as Admin Kursus/Owner?</span>} + {userObject !== null && <span className="h-min my-auto font-semibold">Logged in as {userObject.tipe_user}</span>} + {userObject === null && <button className="bg-[#F875AA] h-1/2 w-28 rounded-2xl font-bold text-white text-xl my-auto p-2 " onClick={handleLogin}>Log In</button>} + {userObject !== null && <button className="bg-[#F875AA] h-1/2 w-28 rounded-2xl font-bold text-white text-xl my-auto p-2 " onClick={handleLogout}>Log Out</button>} + </div> + </header > + {children} + </> +} +export default Template \ No newline at end of file diff --git a/pages/adminkursus/create.jsx b/pages/adminkursus/create.jsx new file mode 100644 index 0000000000000000000000000000000000000000..29bfa4e5d89dd2ffef6bd10a5bd366dd16dea573 --- /dev/null +++ b/pages/adminkursus/create.jsx @@ -0,0 +1,78 @@ +import Template from "@/components/template" +import { useState } from "react" +import { toast } from "react-toastify" +import { useRouter } from "next/router" +const Create = () => { + const router = useRouter() + const [username, setusername] = useState("") + const [password, setpassword] = useState("") + + + const handleUpdate = async () => { + const token = window.localStorage.getItem("token") + if (token === undefined || token === null) { + window.location.replace("/auth/login") + return + } + const body = JSON.stringify({ + username, + password + }) + const updateQuery = await fetch("https://rpl-backend-production.up.railway.app/v1/adminkursus/create", { + method: "POST", + headers: { + Authorization: token, + "Content-Type": "application/json" + }, + body + }).then(response => response).catch(() => null) + if (updateQuery === null) { + toast.error("Something went wrong..") + return + } + if (updateQuery.status !== 200) { + toast.error("Failed to create...") + return + } + toast.success("Successfully created!") + router.push("/adminkursus") + return; + } + return <> + <Template> + <main className="min-h-screen px-14 py-5 bg-[#FFF6F6]"> + <div className="w-full mb-2"> + <span className="text-[#F875AA] font-bold text-2xl hover:cursor-pointer" onClick={(e) => { + e.preventDefault() + router.back() + }}>Back</span> + </div> + <h1 className="text-[#F875AA] font-extrabold text-5xl mb-20 text-center">Create Admin Kursus</h1> + <form className="w-2/3 mx-auto space-y-10 flex flex-col align-middle justify-evenly" onSubmit={(e) => { + e.preventDefault() + handleUpdate() + return; + }}> + + <div className="flex flex-row align-middle justify-between"> + <span className="h-min my-auto font-bold text-lg">Username</span> + <input value={username} onChange={(e) => { + setusername(e.target.value) + }} type="text" required className="drop-shadow-xl w-2/3 p-2 rounded-xl" /> + </div> + <div className="flex flex-row align-middle justify-between"> + <span className="h-min my-auto font-bold text-lg">Password</span> + <input value={password} onChange={(e) => { + setpassword(e.target.value) + }} type="password" required className="drop-shadow-xl w-2/3 p-2 rounded-xl" /> + </div> + + <input type="submit" className="bg-[#F875AA] px-8 py-3 text-xl font-bold text-white rounded-xl mx-auto" value={"Simpan"} /> + </form> + + </main> + </Template > + </> +} + +export default Create \ No newline at end of file diff --git a/pages/adminkursus/edit/[id].jsx b/pages/adminkursus/edit/[id].jsx new file mode 100644 index 0000000000000000000000000000000000000000..14d452ded085a9b17427f5b2f6ddf9067969e633 --- /dev/null +++ b/pages/adminkursus/edit/[id].jsx @@ -0,0 +1,108 @@ +import Template from "@/components/template" +import { useEffect, useState } from "react" +import { toast } from "react-toastify" +import { useRouter } from "next/router" +const Edit = () => { + const router = useRouter() + const [user_id, setuserid] = useState("") + const [username, setusername] = useState("") + const [password_hash, setpassword_hash] = useState("") + const [password, setpassword] = useState("") + + + const handleUpdate = async () => { + const token = window.localStorage.getItem("token") + if (token === undefined || token === null) { + window.location.replace("/auth/login") + return + } + const body = JSON.stringify({ + username, + password + }) + const updateQuery = await fetch("https://rpl-backend-production.up.railway.app/v1/adminkursus/update/" + router.query.id, { + method: "PATCH", + headers: { + Authorization: token, + "Content-Type": "application/json" + }, + body + }).then(response => response).catch(() => null) + if (updateQuery === null) { + toast.error("Something went wrong..") + return + } + if (updateQuery.status !== 200) { + toast.error("Failed to update...") + return + } + toast.success("Successfully updated!") + router.push("/adminkursus") + return; + } + + useEffect(() => { + const token = window.localStorage.getItem("token") + if (token === undefined || token === null) { + window.location.replace("/auth/login") + return + } + fetch("https://rpl-backend-production.up.railway.app/v1/adminkursus/list/" + router.query.id, { + method: "GET", + headers: { + "Authorization": token + } + }).then(async response => { + if (response.status !== 200) { + toast.error("Failed to retrieve items") + return + } + const responsejson = await response.json() + setuserid(responsejson.data.user_id) + setusername(responsejson.data.username) + setpassword_hash(responsejson.data.password_hash) + }) + //eslint-disable-next-line + }, []) + return <> + <Template> + <main className="min-h-screen px-14 py-5 bg-[#FFF6F6]"> + <div className="w-full mb-2"> + <span className="text-[#F875AA] font-bold text-2xl hover:cursor-pointer" onClick={(e) => { + e.preventDefault() + router.back() + }}>Back</span> + </div> + <h1 className="text-[#F875AA] font-extrabold text-5xl mb-20 text-center">Update Admin Kursus</h1> + <form className="w-2/3 mx-auto space-y-10 flex flex-col align-middle justify-evenly" onSubmit={(e) => { + e.preventDefault() + handleUpdate() + return; + }}> + <div className="flex flex-row align-middle justify-between"> + <span className="h-min my-auto font-bold text-lg">user_id</span> + <input disabled value={user_id} type="tel" required className="drop-shadow-xl w-2/3 p-2 rounded-xl" /> + </div> + <div className="flex flex-row align-middle justify-between"> + <span className="h-min my-auto font-bold text-lg">Username</span> + <input value={username} onChange={(e) => { + setusername(e.target.value) + }} type="text" required className="drop-shadow-xl w-2/3 p-2 rounded-xl" /> + </div> + <div className="flex flex-row align-middle justify-between"> + <span className="h-min my-auto font-bold text-lg">Password</span> + <input value={password} onChange={(e) => { + setpassword(e.target.value) + }} type="password" required className="drop-shadow-xl w-2/3 p-2 rounded-xl" /> + </div> + + <input type="submit" className="bg-[#F875AA] px-8 py-3 text-xl font-bold text-white rounded-xl mx-auto" value={"Simpan"} /> + </form> + + </main> + </Template > + </> + +} + +export default Edit \ No newline at end of file diff --git a/pages/adminkursus/index.jsx b/pages/adminkursus/index.jsx new file mode 100644 index 0000000000000000000000000000000000000000..39d20990fce5e44a59686886d62cb9e5fbd93e94 --- /dev/null +++ b/pages/adminkursus/index.jsx @@ -0,0 +1,160 @@ +import Template from "@/components/template" +import { useEffect, useState } from "react" +import { toast } from "react-toastify" +import { useRouter } from "next/router" +const Index = () => { + const [rows, setRows] = useState([]) + const router = useRouter() + const [deleteToggle, setDeleteToggle] = useState(null) + const [currentPage, setCurrentPage] = useState(1); + const [isLastPage, setLastPage] = useState(false) + + const getNextPage = async (page) => { + const token = window.localStorage.getItem("token") + if (token === undefined || token === null) { + window.location.replace("/auth/login") + return; + } + const getItems = await fetch("https://rpl-backend-production.up.railway.app/v1/adminkursus/list?page=" + (page), { + method: "GET", + headers: { + Authorization: token + } + }).then(response => response).catch(() => null) + if (getItems === null) { + toast.error("Something went wrong..") + return; + } + if (getItems.status !== 200) { + toast.error("Unable to get more items!") + return + } + const responsejson = await getItems.json(); + setLastPage(responsejson.data.length < 10) + setRows(responsejson.data); + return + } + const handleDelete = async () => { + const token = window.localStorage.getItem("token") + if (token === undefined || token === null) { + window.location.replace("/auth/login") + return + } + const deleteRequest = await fetch("https://rpl-backend-production.up.railway.app/v1/adminkursus/delete/" + deleteToggle, { + method: "DELETE", + headers: { + Authorization: token + } + }).then(response => response).catch(() => null) + setDeleteToggle(null) + if (deleteRequest === null) { + toast.error("Something went wrong..."); + return; + } + if (deleteRequest.status !== 200) { + toast.error("Failed to delete.."); + return; + } + toast.success("Successfully deleted!"); + router.reload(); + return; + } + useEffect(() => { + const token = window.localStorage.getItem("token") + if (token === undefined || token === null) { + window.location.replace("/auth/login") + return + } + fetch("https://rpl-backend-production.up.railway.app/v1/adminkursus/list", { + method: "GET", + headers: { + "Authorization": token + } + }).then(async response => { + if (response.status !== 200) { + toast.error("Failed to retrieve items") + return + } + const responsejson = await response.json() + setRows(responsejson.data) + }) + }, []) + return <> + <Template> + <main className="min-h-screen px-14 py-5 bg-[#FFF6F6]"> + <div className="w-full mb-2"> + <span className="text-[#F875AA] font-bold text-2xl hover:cursor-pointer" onClick={(e) => { + e.preventDefault() + router.back() + }}>Back</span> + </div> + <div className="flex flex-row align-middle justify-between"> + <h1 className="text-[#F875AA] font-extrabold text-5xl mb-8">Data Akun Admin</h1> + <button onClick={(e) => { + e.preventDefault(); + router.push("/adminkursus/create") + }} className="bg-[#F875AA] p-4 text-lg font-bold text-white rounded-3xl">Create</button> + </div> + <table className="w-full text-center border-spacing-3 border-separate"> + <thead> + <tr> + <th className="bg-[#F875AA] p-2 border border-[#F875AA]">User ID</th> + <th className="bg-[#F875AA] p-2 border border-[#F875AA]">Username</th> + <th className="bg-[#F875AA] p-2 border border-[#F875AA]">Password</th> + <th className=""></th> + </tr> + </thead> + <tbody> + {rows.filter(row => row.user_id !== 10000).map((row, index) => { + return <tr key={row.user_id}> + <td className="p-6 border border-[#F875AA] bg-white">{row.user_id}</td> + <td className="p-6 border border-[#F875AA] bg-white">{row.username}</td> + <td className="p-6 border border-[#F875AA] bg-white">{row.password_hash}</td> + <td className="px-2 flex flex-col align-middle justify-evenly space-y-2 "> + <button className="bg-[#AEDEFC] p-1 rounded-lg" onClick={(e) => { + e.preventDefault(); + router.push("/adminkursus/edit/" + row.user_id) + return; + }}>Update</button> + <button data-modal-target="popup-modal" data-modal-toggle="popup-modal" className="bg-[#FFDFDF] p-1 rounded-lg" onClick={(e) => { + e.preventDefault() + setDeleteToggle(row.user_id) + }}>Delete</button> + </td> + </tr> + })} + </tbody> + </table> + <div className="flex flex-row align-middle justify-around"> + <button className="bg-red-400 p-5 rounded-2xl text-white font-bold" disabled={currentPage === 1} onClick={() => { + getNextPage(currentPage - 1) + setCurrentPage(page => page - 1) + }}>Prev</button> + <span className="h-min my-auto font-bold">Page {currentPage}</span> + <button className="bg-blue-400 p-5 rounded-2xl text-white font-bold" disabled={isLastPage} onClick={() => { + getNextPage(currentPage + 1) + setCurrentPage(page => page + 1) + }}>Next</button> + </div> + </main> + {deleteToggle !== null && <div className="left-0 top-0 fixed w-screen h-screen bg-white bg-opacity-80 p-20 flex flex-col align-middle justify-center"> + <div className="w-1/2 mx-auto space-y-5"> + <h1 className="text-center p-10 bg-[#FFDFDF] border-2 border-[#F875AA] rounded-xl font-bold text-xl">Apakah anda yakin akan menghapus data admin kursus?</h1> + <div className="space-x-5 flex flex-row align-middle justify"> + <button className="p-3 rounded-xl w-full bg-[#FFDFDF] border-2 border-[#F875AA]" onClick={(e) => { + e.preventDefault(); + handleDelete() + }}>Delete</button> + <button className="p-3 rounded-xl w-full bg-[#FFDFDF] border-2 border-[#F875AA]" onClick={(e) => { + e.preventDefault() + setDeleteToggle(null) + }}>Cancel</button> + </div> + </div> + </div>} + </Template > + </> + +} + +export default Index \ No newline at end of file diff --git a/pages/auth/login.jsx b/pages/auth/login.jsx index e744536725f66798e28a5735959ae8021357ba97..810f4820bc0f1f7c0559467672c4c758385a8bd2 100644 --- a/pages/auth/login.jsx +++ b/pages/auth/login.jsx @@ -1,51 +1,80 @@ -import Template from "@/components/template" import { useState } from "react" import { toast } from "react-toastify" +import { useRouter } from "next/router" +import Image from "next/image" + const Login = () => { const [username, setUsername] = useState("") const [password, setPassword] = useState("") - return <Template> - <main className="min-h-screen flex flex-col align-middle justify-center"> - <h1 className="font-bold text-center text-3xl mb-5">Temporary login screen...</h1> - <h3 className="font-semibold text-center text-xl mb-5">geblek hirup daek jadi runtahhh</h3> - <form onSubmit={(e) => { + const router = useRouter() + const handleGoBack = () => { + router.back() + } + + return ( + <main className="min-h-screen px-14 py-7 bg-[#FFF6F6] flex flex-col"> + <div className="fex flex-row w-full"> + <button className="text-xl text-[#F875AA] font-extrabold" onClick={handleGoBack}>Back</button> + </div> + <div className="flex flex-col w-1/2 align-middle justify-around mx-auto my-auto"> + <h1 className="text-center font-extrabold text-5xl text-[#F875AA]">Log In</h1> + <div className="w-full"><Image src={"/logo.png"} width={400} height={400} alt="Main Logo" className="mx-auto"/></div> + <form className="flex flex-col align-middle justify-evenly space-y-8" onSubmit={(e) => { e.preventDefault() const requestBody = JSON.stringify({ - username, password + username,password }) fetch("https://rpl-backend-production.up.railway.app/v1/auth/login", { - method: "POST", - body: requestBody, - headers: { - "Content-Type": "application/json" - } - }).then(async (response) => { - if (response.status !== 200) { - toast.error("Failed to login..") - return - } - const responsejson = await response.json(); - const type = responsejson.data.type - const token = responsejson.data.token - localStorage.setItem("token", `${type} ${token}`) - window.location.replace("/") - return - }).catch(() => { - toast.error("Something went wrong..") - }) + method: "POST", + body: requestBody, + headers: { + "Content-Type": "application/json" + } + }).then(async (response) => { + if (response.status !== 200){ + toast.error("Failed to login..") + return + } + const responsejson = await response.json(); + const type = responsejson.data.type + const token = responsejson.data.token + window.localStorage.setItem("token", `${type} ${token}`) - }} className="flex flex-col align-middle justify-center w-1/2 bg-slate-300 p-28 mx-auto space-y-2"> - <input type="text" placeholder="Username" required className="p-2 rounded-xl" value={username} onChange={(e) => { - setUsername(e.target.value) - }} /> - <input type="password" placeholder="Password" required className="p-2 rounded-xl" value={password} onChange={(e) => { - setPassword(e.target.value) - }} /> - <input type="submit" className="bg-blue-500 w-1/3 p-3 mx-auto rounded-xl font-bold text-white" value={"Login"} /> + fetch("https://rpl-backend-production.up.railway.app/v1/auth/verify/" + token,) + .then(async(response) =>{ + const responsejson = await response.json(); + if (responsejson.data.tipe_user === "OWNER"){ + router.push("/dashboard/owner") + return + } + if (responsejson.data.tipe_user === "ADMIN"){ + router.push("/dashboard/admin") + return + } + }) + }).catch(() => { + toast.error("Something went wrong..") + }) + + }}> + <div className="flex flex-row align-middle justify-between "> + <span className="h-min my-auto font-extrabold text-[#F875AA] text-xl">Username</span> + <input className="w-2/3 drop-shadow-lg p-3 rounded-xl shadow shadow-red-100" type="text" placeholder="Username" required value={username} onChange={(e) => { + setUsername(e.target.value) + }}/> + </div> + <div className="flex flex-row align-middle justify-between "> + <span className="h-min my-auto font-extrabold text-[#F875AA] text-xl">Password</span> + <input className="w-2/3 drop-shadow-lg p-3 rounded-xl shadow shadow-red-100" type="password" placeholder="Password" required value={password} onChange={(e) => { + setPassword(e.target.value) + }}/> + </div> + <input type="submit" value={"Log In"} className="w-min px-20 py-3 mx-auto bg-pink-400 rounded-xl text-white font-bold text-2xl hover:cursor-pointer"/> </form> + + </div> </main> - </Template> - + ) } export default Login \ No newline at end of file diff --git a/pages/dashboard/admin.jsx b/pages/dashboard/admin.jsx new file mode 100644 index 0000000000000000000000000000000000000000..9382f880a9bd4a924085cb9992463e3509730fe4 --- /dev/null +++ b/pages/dashboard/admin.jsx @@ -0,0 +1,58 @@ +import Template from "@/components/templatenofooter" +import { toast } from "react-toastify" +import { useEffect, useState} from "react" +import { useRouter } from "next/router" + +const DashboardOwner = () => { + const router = useRouter(); + const [username, setUsername] = useState(null) + + useEffect(() => { + const token = window.localStorage.getItem("token") + if (!token){ + window.location.replace("/auth/login") + } + const tokenParsed = token.split(" ")[1] + fetch(`https://rpl-backend-production.up.railway.app/v1/auth/verify/${tokenParsed}`).then(async (response) => { + if (response.status !== 200){ + toast.error("Failed to retrieve items") + return; + } + const responsejson = await response.json(); + if (responsejson.data.tipe_user !== "ADMIN"){ + window.location.replace("/auth/login") + return + } + setUsername(responsejson.data.username) + + }) + }, []) + + return ( + <Template> + + <main className="min-h-screen px-14 py-10 bg-[#FFF6F6]"> + + <div className="text-[#F875AA] font-extrabold text-5xl mb-20 text-center">Selamat datang kembali, {username}!</div> + <div className = "flex flex-row align-middle justify-between"> + {/* <div className="bg-white p-6 rounded-lg shadow-md" /> */} + + </div> + <div className="w-[226px] h-[95px] left-[638px] top-[381px] absolute text-center text-pink-400 text-[32px] font-extrabold font-'Poppins'">Data<br/>Pelanggan</div> + <div className="w-[126px] h-[53px] left-[694px] top-[715px] absolute"> + <div className="w-[126px] h-[53px] left-0 top-0 absolute bg-sky-200 rounded-[15px]" /> + <span className="w-[84.28px] h-[28.33px] left-[21px] top-[15px] absolute text-center text-black text-base font-bold font-'Poppins'" onClick={(e) => { + e.preventDefault() + router.push("/") + }}>Ubah</span> + </div> + <img className="w-[171px] h-[171px] left-[670px] top-[497px] absolute" src="/client.png" /> + </main> + </Template> + + + ) + +} + +export default DashboardOwner \ No newline at end of file diff --git a/pages/dashboard/owner.jsx b/pages/dashboard/owner.jsx new file mode 100644 index 0000000000000000000000000000000000000000..6f39c24e2661ae9a56f3c3951159a0f873c33737 --- /dev/null +++ b/pages/dashboard/owner.jsx @@ -0,0 +1,78 @@ +import Template from "@/components/templatenofooter" +import { toast } from "react-toastify" +import { useEffect } from "react" +import { useRouter } from "next/router" +import Image from "next/image" + +const DashboardOwner = () => { + const router = useRouter(); + + useEffect(() => { + const token = window.localStorage.getItem("token") + if (!token) { + window.location.replace("/auth/login") + } + const tokenParsed = token.split(" ")[1] + fetch(`https://rpl-backend-production.up.railway.app/v1/auth/verify/${tokenParsed}`).then(async (response) => { + if (response.status !== 200) { + console.log(response) + toast.error("Failed to retrieve items") + return; + } + const responsejson = await response.json(); + if (responsejson.data.tipe_user !== "OWNER") { + window.location.replace("/auth/login") + return + } + }).catch(error => { + console.error(error) + return + }) + }, []) + + return ( + <Template> + <main className="min-h-screen px-28 py-28 bg-[#FFF6F6] flex flex-col align-middle space-y-20"> + <h2 className="text-center text-5xl font-extrabold text-[#F875AA] ">Selamat datang kembali, Helmi!</h2> + <div className="flex flex-row align-middle justify-evenly"> + <div className="bg-white rounded-xl px-5 py-10 space-y-5 flex flex-col align-middle justify-evenly shadow-xl w-1/4"> + <span className="text-center font-extrabold text-xl text-[#F875AA]">Data Kelas Yang Tersedia</span> + <Image className="mx-auto" src="/todolist.png" width={99} height={100} alt="Data Kelas" /> + <button className="bg-sky-200 rounded-xl font-bold text-center w-min mx-auto px-10 py-3" onClick={ + ()=>router.push("/kelasmengemudi")}>Ubah</button> + </div> + <div className="bg-white rounded-xl px-5 py-10 space-y-5 flex flex-col align-middle justify-evenly shadow-xl w-1/4"> + <span className="text-center font-extrabold text-xl text-[#F875AA]">Akun Pengguna Admin</span> + <Image className="mx-auto" src="/setting.png" width={117} height={117} alt="Akun Pengguna Admin" /> + <button className="bg-sky-200 rounded-xl font-bold text-center w-min mx-auto px-10 py-3" onClick={ + ()=>router.push("/adminkursus")}>Ubah</button> + </div> + <div className="bg-white rounded-xl px-5 py-10 space-y-5 flex flex-col align-middle justify-evenly shadow-xl w-1/4"> + <span className="text-center font-extrabold text-xl text-[#F875AA]">Info Perusahaan dan FAQ</span> + <Image className="mx-auto" src="/briefcase.png" width={108} height={108} alt="Data Kelas" /> + <button className="bg-sky-200 rounded-xl font-bold text-center w-min mx-auto px-10 py-3"onClick={ + ()=>router.push("/infoperusahaan")}>Ubah</button> + </div> + + </div> + <div className="flex flex-row align-middle justify-center space-x-32"> + <div className="bg-white rounded-xl px-5 py-10 space-y-5 flex flex-col align-middle justify-evenly shadow-xl w-1/4"> + <span className="text-center font-extrabold text-xl text-[#F875AA]">Data Kendaraan</span> + <Image className="mx-auto" src="/sedan.png" width={138} height={138} alt="Data Kendaraan" /> + <button className="bg-sky-200 rounded-xl font-bold text-center w-min mx-auto px-10 py-3" onClick={ + ()=>router.push("/kendaraan")}>Ubah</button> + </div> + <div className="bg-white rounded-xl px-5 py-10 space-y-5 flex flex-col align-middle justify-evenly shadow-xl w-1/4"> + <span className="text-center font-extrabold text-xl text-[#F875AA]">Data Instruktur</span> + <Image className="mx-auto" src="/instructor.png" width={112} height={112} alt="Data Instruktur" /> + <button className="bg-sky-200 rounded-xl font-bold text-center w-min mx-auto px-10 py-3"onClick={ + ()=>router.push("/instruktur")}>Ubah</button> + </div> + + </div> + </main> + </Template> + + ) +} +export default DashboardOwner \ No newline at end of file diff --git a/public/back.png b/public/back.png new file mode 100644 index 0000000000000000000000000000000000000000..1f79dd63a0d3cc085cd0f9797f4e6a15b94819e6 Binary files /dev/null and b/public/back.png differ diff --git a/public/briefcase.png b/public/briefcase.png new file mode 100644 index 0000000000000000000000000000000000000000..ba932f4c7df7fb3bc96ed7ac93dd6cfe629f6c81 Binary files /dev/null and b/public/briefcase.png differ diff --git a/public/client.png b/public/client.png new file mode 100644 index 0000000000000000000000000000000000000000..c4eaab8a628e93a82a3034d58e9bd30c20504d87 Binary files /dev/null and b/public/client.png differ diff --git a/public/instructor.png b/public/instructor.png new file mode 100644 index 0000000000000000000000000000000000000000..94d48560b05cc1b93f6faf424a3db3b8a9a9d6cc Binary files /dev/null and b/public/instructor.png differ diff --git a/public/sedan.png b/public/sedan.png new file mode 100644 index 0000000000000000000000000000000000000000..adf06f46f90fe0f413c173ce711d19f527a31f67 Binary files /dev/null and b/public/sedan.png differ diff --git a/public/setting.png b/public/setting.png new file mode 100644 index 0000000000000000000000000000000000000000..82e0fa8db737f69bd412ada043808c449994df56 Binary files /dev/null and b/public/setting.png differ diff --git a/public/todolist.png b/public/todolist.png new file mode 100644 index 0000000000000000000000000000000000000000..082497f16ebed9868abc2b1c1ca9e73dd79cee9b Binary files /dev/null and b/public/todolist.png differ