diff --git a/components/template.jsx b/components/template.jsx
index b2180297dec59663d0254cb74b9264ebd0ccfe28..d1c5d5e5f8bcbfcd3b7fecfa7b2bc9f878095125 100644
--- a/components/template.jsx
+++ b/components/template.jsx
@@ -22,6 +22,9 @@ const Template = ({ children }) => {
if (response.status !== 200) return null;
const responsejson = await response.json();
setUser(responsejson.data)
+ }).catch(error => {
+ console.error(error)
+ return
})
}, [])
return <>
diff --git a/pages/dashboard/owner.jsx b/pages/dashboard/owner.jsx
index f98bf6c90d1b109d3d7f70d4183bab3db376b7ad..bd5cdf978d12488d2f1e84ab38e548e090851b67 100644
--- a/pages/dashboard/owner.jsx
+++ b/pages/dashboard/owner.jsx
@@ -39,19 +39,19 @@ const DashboardOwner = () => {
<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>
+ () => 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 shadow-[#FFDFE0] 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>
+ () => 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 shadow-[#FFDFE0] 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>
+ <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>
@@ -60,13 +60,13 @@ const DashboardOwner = () => {
<span className="text-center font-extrabold text-xl text-[#F875AA]">Data Kendaraan</span>
<Image className="mx-auto" src="/sedan.png" width={117} height={117} 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>
+ () => 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 shadow-[#FFDFE0] 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>
+ <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>
@@ -75,4 +75,4 @@ const DashboardOwner = () => {
)
}
-export default DashboardOwner
\ No newline at end of file
+export default DashboardOwner
diff --git a/pages/index.jsx b/pages/index.jsx
index 09fe3ba02464a61d64648f928d96928c1f3c24e6..a6e164f7a300600a939b13e7395e86ab15f92d8e 100644
--- a/pages/index.jsx
+++ b/pages/index.jsx
@@ -1,70 +1,64 @@
import Template from "@/components/template"
-import { useEffect, useState } from "react"
-import { toast } from "react-toastify"
import { useRouter } from "next/router"
export default function Home({ kelasMengemudi, propertyWebsite }) {
const router = useRouter();
-
return <>
<Template>
<main className="min-h-screen px-14 py-5 bg-[#FFF6F6]">
- <h1 className="text-[#F875AA] font-extrabold text-4xl mt-5 mb-10 text-center">Sistem Manajemen Kursus Mengemudi RPL</h1>
-
- <p className="mx-auto w-11/12 justify-center text-center">{propertyWebsite.description}</p>
+ <h1 className="text-[#F875AA] font-extrabold text-4xl mt-5 mb-4 text-center leading-[1.5]">Sistem Manajemen Kursus Mengemudi RPL</h1>
+ <div className="flex justify-center items-center">
+ <span className="text-[#000000] mb-10 max-w-[950px] text-1xl text-center">{propertyWebsite.description}</span>
+ </div>
<div className="flex flex-col justify-center items-center space-y-5">
- <span className="text-[#F875AA] font-extrabold text-3xl text-center mt-20">Paket Kelas</span>
+ <span className="text-[#F875AA] font-extrabold text-3xl text-center mt-10">Paket Kelas</span>
<span className="text-[#16A4FF]">*) Setiap 1 sesi kelas berlangsung selama 2 jam</span>
</div>
<div className={`max-h-fit px-28 mt-10 mx-auto max-w-[1270px] relative grid grid-cols-3 gap-x-8 gap-y-8`}>
{kelasMengemudi.map((row, index) => {
return (
- <div key={row.kelasMengemudiID}
- className={`relative col-span-1 row-span-1 col-start-${(index % 3) + 1} row-start-${Math.floor(index / 3) + 1}`}>
- <div className="w-[320px] h-[360px] bg-white rounded-[15px] shadow-xl shadow-[#FFDFE0] relative flex flex-col justify-center items-center">
- <span className="text-[#F875AA] text-xl font-extrabold">{row.namaKelas}</span>
- <span className="text-center text-black text-base mt-8">Harga: Rp{row.hargaKelas}</span>
- <span className="text-center text-black text-base mt-3">Total Jam Kursus: {2*row.jumlahSesi}</span>
- <span className="text-center text-black text-base mt-3">Jumlah Sesi: {row.jumlahSesi}</span>
- <span className="text-center text-black text-base mt-3">Nama Kendaraan: {row.namaKendaraan}</span>
- <span className="text-center text-black text-base mt-3">Jenis Kendaraan: {row.jenisKendaraan}</span>
-
- <button onClick={(e) => {
- e.preventDefault();
- router.push({
- pathname: "/calonpelanggan/create",
- query: {kelasID: row.kelasMengemudiID, namaKelas: row.namaKelas},
- })
- }} className="bg-[#AFDEFC] w-[126px] h-[53px] p-3 text-lg font-bold text-black rounded-2xl mt-8">Daftar</button>
- </div>
- </div>);
+ <div key={row.kelasMengemudiID}
+ className={`relative col-span-1 row-span-1 col-start-${(index % 3) + 1} row-start-${Math.floor(index / 3) + 1}`}>
+ <div className="w-[320px] h-[360px] bg-white rounded-[15px] shadow-xl shadow-[#FFDFE0] relative flex flex-col justify-center items-center">
+ <span className="text-[#F875AA] text-xl font-extrabold">{row.namaKelas}</span>
+ <span className="text-center text-black text-base mt-8">Harga: Rp{row.hargaKelas}</span>
+ <span className="text-center text-black text-base mt-3">Total Jam Kursus: {2 * row.jumlahSesi}</span>
+ <span className="text-center text-black text-base mt-3">Jumlah Sesi: {row.jumlahSesi}</span>
+ <span className="text-center text-black text-base mt-3">Nama Kendaraan: {row.namaKendaraan}</span>
+ <span className="text-center text-black text-base mt-3">Jenis Kendaraan: {row.jenisKendaraan}</span>
+
+ <button onClick={(e) => {
+ e.preventDefault();
+ router.push({
+ pathname: "/calonpelanggan/create",
+ query: { kelasID: row.kelasMengemudiID, namaKelas: row.namaKelas },
+ })
+ }} className="bg-[#AFDEFC] w-[126px] h-[53px] p-3 text-lg font-bold text-black rounded-2xl mt-8">Daftar</button>
+ </div>
+ </div>);
})}
</div>
<div className="flex justify-center items-center">
- <span className="text-[#F875AA] font-extrabold text-3xl text-center mt-20">Frequently Asked Questions</span>
+ <span className="text-[#F875AA] font-extrabold mt-10 mb-10 text-3xl text-center">Frequently Asked Questions</span>
</div>
- <div className="mt-10 mb-20 mx-auto relative space-y-10">
+ <div>
<div>
{propertyWebsite.faq.map((item, index) => (
- <div key={index} className="faq-item">
- <div className="mx-auto w-11/12 h-auto bg-white rounded-[15px] shadow-xl shadow-[#FFDFE0] relative flex flex-col justify-center mb-5">
- <span className="question text-[#F875AA] text-xl font-bold text-left m-5">{item.question}</span>
- <span className="answer ml-5 mb-5 mr-5">{item.answer}</span>
- </div>
+ <div key={index} className="faq-item" style={{ backgroundColor: 'white', padding: '20px', borderRadius: '10px', boxShadow: '0 4px 8px rgba(0, 0, 0, 0.1)', marginBottom: '15px' }}>
+ <div className="question" style={{ color: '#F875AA', fontSize: '1rem', fontWeight: 'bold', textAlign: 'left', marginTop: '0', marginBottom: '10px' }}>{item.question}</div>
+ <div className="answer" style={{ color: 'black', fontSize: '1rem', textAlign: 'left', marginTop: '0', marginBottom: '0' }}>{item.answer}</div>
</div>
))}
</div>
</div>
-
</main>
</Template>
</>
}
-
export const getServerSideProps = async () => {
const kelasMengemudiQuery = await fetch("https://rpl-backend-production.up.railway.app/v1/kelasmengemudi/list", {
method: "GET",
@@ -97,4 +91,5 @@ export const getServerSideProps = async () => {
propertyWebsite
}
}
-}
+
+}
\ No newline at end of file
diff --git a/pages/infoperusahaan/create.jsx b/pages/infoperusahaan/create.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..1f1e839d431ce527cb9d37d788680620ad846ff6
--- /dev/null
+++ b/pages/infoperusahaan/create.jsx
@@ -0,0 +1,106 @@
+import Template from "@/components/template"
+import { useState } from "react"
+import { toast } from "react-toastify"
+import { useRouter } from "next/router"
+const Create = ({ propertyWebsite }) => {
+ const router = useRouter()
+ const [faq, setFaq] = useState({
+ question: "",
+ answer: ""
+ })
+
+
+ const handleUpdate = async () => {
+ const token = window.localStorage.getItem("token")
+ if (token === undefined || token === null) {
+ window.location.replace("/auth/login")
+ return
+ }
+ const body = JSON.stringify({
+ question: faq.question,
+ answer: faq.answer
+ })
+ const updateQuery = await fetch("https://rpl-backend-production.up.railway.app/v1/property/faq", {
+ method: "PUT",
+ headers: {
+ Authorization: token,
+ "Content-Type": "application/json"
+ },
+ body
+ }).then(response => response).catch(() => null)
+ if (updateQuery === null) {
+ toast.error("Someting went wrong..")
+ return
+ }
+ if (updateQuery.status !== 200) {
+ toast.error("Failed to create...")
+ return
+ }
+ toast.success("Successfully created!")
+ router.push("/infoperusahaan")
+ 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.push("/infoperusahaan")
+ }}>Back</span>
+ </div>
+ <h1 className="text-[#F875AA] font-extrabold text-5xl mb-20 text-center">Tambah Data FAQ</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">Question</span>
+ <input value={faq.question} onChange={(e) => {
+ setFaq({
+ question: e.target.value,
+ answer: faq.answer
+ })
+ }} 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">Answer</span>
+ <input value={faq.answer} onChange={(e) => {
+ setFaq({
+ question: faq.question,
+ answer: e.target.value
+ })
+ }} type="text" 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 const getServerSideProps = async () => {
+ const propertyQuery = await fetch("https://rpl-backend-production.up.railway.app/v1/property", {
+ method: "GET",
+ }).catch(error => {
+ return null
+ })
+ let propertyWebsite;
+ if (propertyQuery === null) propertyWebsite = {
+ description: "",
+ faq: []
+ }
+ else {
+ const propertyJson = await propertyQuery.json();
+ propertyWebsite = propertyJson.data
+ }
+ return {
+ props: {
+ propertyWebsite
+ }
+ }
+
+}
+export default Create
\ No newline at end of file
diff --git a/pages/infoperusahaan/edit/[id].jsx b/pages/infoperusahaan/edit/[id].jsx
new file mode 100644
index 0000000000000000000000000000000000000000..d084c978ac632da470ba60cdca4d5d9e2ebdab97
--- /dev/null
+++ b/pages/infoperusahaan/edit/[id].jsx
@@ -0,0 +1,110 @@
+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 [faq, setFaq] = useState({
+ question: "",
+ answer: ""
+ })
+
+ const handleUpdate = async () => {
+ const token = window.localStorage.getItem("token")
+ if (token === undefined || token === null) {
+ window.location.replace("/auth/login")
+ return
+ }
+ const body = JSON.stringify({
+ question: faq.question,
+ answer: faq.answer
+ })
+ const updateQuery = await fetch("https://rpl-backend-production.up.railway.app/v1/property/faq/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 when trying to save...")
+ return
+ }
+ if (updateQuery.status !== 200) {
+ toast.error("Failed to update...")
+ return
+ }
+ toast.success("Successfully updated!")
+ router.push("/infoperusahaan")
+ return;
+ }
+
+ useEffect(() => {
+ if (!router.isReady) return;
+ const index = router.query.id;
+ 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/property/", {
+ method: "GET",
+ headers: {
+ "Authorization": token
+ }
+ }).then(async response => {
+ if (response.status !== 200) {
+ toast.error("Failed to retrieve items")
+ return
+ }
+ const responsejson = await response.json()
+ setFaq(responsejson.data.faq[index])
+ }).catch((err) => {
+ toast.error("Something went wrong when trying to retrieve the items..")
+ return;
+ })
+ //eslint-disable-next-line
+ }, [router.isReady])
+ 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.push("/infoperusahaan")
+ }}>Back</span>
+ </div>
+ <h1 className="text-[#F875AA] font-extrabold text-5xl mb-20 text-center">Update Data FAQ</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">Question</span>
+ <input value={faq.question} onChange={(e) => {
+ setFaq({
+ question: e.target.value,
+ answer: faq.answer
+ })
+ }} 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">Answer</span>
+ <input value={faq.answer} onChange={(e) => {
+ setFaq({
+ question: faq.question,
+ answer: e.target.value
+ })
+ }} type="text" 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/infoperusahaan/index.jsx b/pages/infoperusahaan/index.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..2c53b67e4801535f1d95c88930deada220261feb
--- /dev/null
+++ b/pages/infoperusahaan/index.jsx
@@ -0,0 +1,155 @@
+import Template from "@/components/template";
+import { useRouter } from "next/router"
+import { toast } from "react-toastify"
+import { useEffect, useState } from "react"
+
+export default function InformasiPerusahaan({ propertyWebsite }) {
+ const [deskripsi, setDeskripsi] = useState("")
+ const [faq, setFaq] = useState([])
+ const [deleteToggle, setDeleteToggle] = useState(null)
+
+ const router = useRouter();
+ const saveDeskripsi = () => {
+ const token = window.localStorage.getItem("token")
+ if (token === undefined || token === null) {
+ window.location.replace("/")
+ return;
+ }
+ fetch("https://rpl-backend-production.up.railway.app/v1/property/description", {
+ method: "PATCH",
+ body: JSON.stringify({
+ description: deskripsi
+ }),
+ headers: {
+ Authorization: token,
+ "Content-Type": "application/json"
+ }
+ }).then((response) => {
+ if (response.status !== 200) {
+ toast.error("Failed to update description")
+ return
+ }
+ toast.success("Successfully saved description")
+ return
+ }).catch((err) => {
+ toast.error("Something went wrong when trying to save the description")
+ 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/property/faq/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(() => {
+ fetch("https://rpl-backend-production.up.railway.app/v1/property").then(async (response) => {
+ const responsejson = await response.json()
+ setDeskripsi(responsejson.data.description)
+ setFaq(responsejson.data.faq)
+ })
+ }, [])
+
+ 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.push("/dashboard/owner")
+ }}>Back</span>
+ </div>
+ <div>
+ <h1 className="text-[#F875AA] font-extrabold text-5xl mt-10 mb-10 text-center">Informasi Perusahaan</h1>
+ </div>
+ <div>
+ <h1 className="text-[#F875AA] font-extrabold text-3xl mt-10 mb-10 text-lef ml-3">Deskripsi Perusahaan</h1>
+ </div>
+ <div className="flex flex-row align-middle justify-between">
+ <textarea rows="4" style={{resize: "vertical"}} value={deskripsi} onChange={(e) => {
+ setDeskripsi(e.target.value)
+ }} type="text" required className="drop-shadow-xl w-5/6 p-2 rounded-xl"/>
+ <button className="px-9 h-12 rounded bg-[#FFDFDF] border-2 border-[#F875AA]" onClick={() => {
+ saveDeskripsi()
+ }}>Simpan</button>
+ </div>
+ <div>
+ <span className="text-[#16A4FF]">*) Minimum 10 karakter, maksimal 500 karakter</span>
+ </div>
+ <div className="flex flex-row items-center align-middle justify-between">
+ <h1 className="text-[#F875AA] font-extrabold text-3xl mt-10 mb-10 ml-3">Frequently Asked Questions</h1>
+ <div>
+ <button onClick={(e) => {
+ e.preventDefault();
+ router.push("/infoperusahaan/create")
+ }} className="bg-[#F875AA] p-3 text-lg font-bold text-white rounded-2xl">Tambah FAQ</button>
+ </div>
+ </div>
+ <table className="w-full text-center items-center border-spacing-3 border-separate">
+ <thead>
+ <tr>
+ <th className="bg-[#F875AA] p-2 border border-[#F875AA]">Question</th>
+ <th className="bg-[#F875AA] p-2 border border-[#F875AA]">Answer</th>
+ <th className=""></th>
+ </tr>
+ </thead>
+ <tbody>
+ {faq.map((item, index) => {
+ return <tr key={index}>
+ <td className="p-2 border border-[#F875AA] bg-white">{item.question}</td>
+ <td className="p-2 border border-[#F875AA] bg-white">{item.answer}</td>
+ <td className="px-2 mx-auto flex flex-col align-middle justify-evenly space-y-2">
+ <button className="bg-[#AEDEFC] p-3 rounded-lg" onClick={(e) => {
+ e.preventDefault();
+ router.push("/infoperusahaan/edit/" + index)
+ return;
+ }}>Update</button>
+ <button data-modal-target="popup-modal" data-modal-toggle="popup-modal" className="bg-[#FFDFDF] p-3 rounded-lg" onClick={(e) => {
+ e.preventDefault()
+ setDeleteToggle(index)
+ }}>Delete</button>
+ </td>
+ </tr>
+ })}
+ </tbody>
+ </table>
+ </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 Frequently Asked Questions?</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>
+ </>
+}
diff --git a/pages/kelasmengemudi/create.jsx b/pages/kelasmengemudi/create.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..ddfff81a4a233d2ff9fb3b12f60249e6fc5ea754
--- /dev/null
+++ b/pages/kelasmengemudi/create.jsx
@@ -0,0 +1,125 @@
+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 [namaKelas, setNamaKelas] = useState("")
+ const [hargaKelas, setHargaKelas] = useState("")
+ const [jenisKendaraan, setJenisKendaraan] = useState("")
+ const [totalJamKursus, setTotalJamKursus] = useState("")
+ const [jumlahSesi, setJumlahSesi] = useState("")
+ const [instruktur, setInstruktur] = useState("")
+ const [nomorKendaraan, setNomorKendaraan] = useState("")
+ const [namaKendaraan, setNamaKendaraan] = 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({
+ namaKelas,
+ hargaKelas,
+ jenisKendaraan,
+ totalJamKursus,
+ jumlahSesi,
+ instruktur,
+ nomorKendaraan,
+ namaKendaraan
+ })
+ const updateQuery = await fetch("https://rpl-backend-production.up.railway.app/v1/kelasmengemudi/create", {
+ method: "POST",
+ headers: {
+ Authorization: token,
+ "Content-Type": "application/json"
+ },
+ body
+ }).then(response => response).catch(() => null)
+ if (updateQuery === null) {
+ toast.error("Someting went wrong..")
+ return
+ }
+ if (updateQuery.status !== 200) {
+ toast.error("Failed to create...")
+ return
+ }
+ toast.success("Successfully created!")
+ router.push("/kelasmengemudi")
+ 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.push("/")
+ }}>Back</span>
+ </div>
+ <h1 className="text-[#F875AA] font-extrabold text-5xl mb-20 text-center">Add Data Kelas</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">Nama Kelas</span>
+ <input value={namaKelas} onChange={(e) => {
+ setNamaKelas(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">Harga Kelas</span>
+ <input value={hargaKelas} onChange={(e) => {
+ setHargaKelas(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">Jenis Kendaraan</span>
+ <input value={jenisKendaraan} onChange={(e) => {
+ setJenisKendaraan(e.target.value)
+ }} 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">Total Jam Kursus</span>
+ <input value={totalJamKursus} onChange={(e) => {
+ setTotalJamKursus(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">Jumlah Sesi</span>
+ <input value={jumlahSesi} onChange={(e) => {
+ setJumlahSesi(e.target.value)
+ }} 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">NIK Instruktur</span>
+ <input value={instruktur} onChange={(e) => {
+ setInstruktur(e.target.value)
+ }} 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">Nomor Kendaraan</span>
+ <input value={nomorKendaraan} onChange={(e) => {
+ setNomorKendaraan(e.target.value)
+ }} 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">Nama Kendaraan</span>
+ <input value={namaKendaraan} onChange={(e) => {
+ setNamaKendaraan(e.target.value)
+ }} type="tel" 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
diff --git a/pages/kelasmengemudi/edit/[id].jsx b/pages/kelasmengemudi/edit/[id].jsx
new file mode 100644
index 0000000000000000000000000000000000000000..a0a35d6d320c72cf40467c10e18ee3b0f88a9284
--- /dev/null
+++ b/pages/kelasmengemudi/edit/[id].jsx
@@ -0,0 +1,158 @@
+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 [ID, setID] = useState()
+ const [namaKelas, setNamaKelas] = useState("")
+ const [hargaKelas, setHargaKelas] = useState("")
+ const [jenisKendaraan, setJenisKendaraan] = useState("")
+ const [totalJamKursus, setTotalJamKursus] = useState("")
+ const [jumlahSesi, setJumlahSesi] = useState("")
+ const [instruktur, setInstruktur] = useState("")
+ const [nomorKendaraan, setNomorKendaraan] = useState("")
+ const [namaKendaraan, setNamaKendaraan] = 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({
+ namaKelas,
+ hargaKelas,
+ jenisKendaraan,
+ totalJamKursus,
+ jumlahSesi,
+ instruktur,
+ nomorKendaraan,
+ namaKendaraan
+ })
+ const updateQuery = await fetch("https://rpl-backend-production.up.railway.app/v1/kelasmengemudi/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("/kelasmengemudi")
+ 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/kelasmengemudi/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()
+ setID(responsejson.data.kelasMengemudiID)
+ setNamaKelas(responsejson.data.namaKelas)
+ setHargaKelas(responsejson.data.hargaKelas)
+ setJenisKendaraan(responsejson.data.jenisKendaraan)
+ setTotalJamKursus(responsejson.data.totalJamKursus)
+ setJumlahSesi(responsejson.data.jumlahSesi)
+ setInstruktur(responsejson.data.instruktur)
+ setNomorKendaraan(responsejson.data.kendaraan)
+ setNamaKendaraan(responsejson.data.calonPelanggan)
+ })
+ }, [])
+ 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 Data Kelas</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">ID Kelas</span>
+ <input disabled value={ID} type="number" 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">Nama Kelas</span>
+ <input value={namaKelas} onChange={(e) => {
+ setNamaKelas(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">Harga Kelas</span>
+ <input value={hargaKelas} onChange={(e) => {
+ setHargaKelas(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">Total Jam Kursus</span>
+ <input value={totalJamKursus} onChange={(e) => {
+ setTotalJamKursus(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">Jumlah Sesi</span>
+ <input value={jumlahSesi} onChange={(e) => {
+ setJumlahSesi(e.target.value)
+ }} 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">NIK Instruktur</span>
+ <input value={instruktur} onChange={(e) => {
+ setInstruktur(e.target.value)
+ }} 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">Jenis Kendaraan</span>
+ <input value={jenisKendaraan} onChange={(e) => {
+ setJenisKendaraan(e.target.value)
+ }} 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">Nomor Kendaraan</span>
+ <input value={nomorKendaraan} onChange={(e) => {
+ setNomorKendaraan(e.target.value)
+ }} 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">Nama Kendaraan</span>
+ <input value={namaKendaraan} onChange={(e) => {
+ setNamaKendaraan(e.target.value)
+ }} type="tel" 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
diff --git a/pages/kelasmengemudi/index.jsx b/pages/kelasmengemudi/index.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..855dabe9e4e6ff88435b809eabf3dace009869c9
--- /dev/null
+++ b/pages/kelasmengemudi/index.jsx
@@ -0,0 +1,166 @@
+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/kelasmengemudi/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/kelasmengemudi/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/kelasmengemudi/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.push("/dashboard/owner")
+ }}>Back</span>
+ </div>
+ <div className="flex flex-row align-middle justify-between">
+ <h1 className="text-[#F875AA] font-extrabold text-5xl mb-8">Data Kelas yang Tersedia</h1>
+ <button onClick={(e) => {
+ e.preventDefault();
+ router.push("/kelasmengemudi/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]">ID</th>
+ <th className="bg-[#F875AA] p-2 border border-[#F875AA]">Nama Kelas</th>
+ <th className="bg-[#F875AA] p-2 border border-[#F875AA]">Harga</th>
+ <th className="bg-[#F875AA] p-2 border border-[#F875AA]">Total Jam Kursus</th>
+ <th className="bg-[#F875AA] p-2 border border-[#F875AA]">Jumlah Sesi</th>
+ <th className="bg-[#F875AA] p-2 border border-[#F875AA]">Jenis Kendaraan</th>
+ <th className=""></th>
+ </tr>
+ </thead>
+ <tbody>
+ {rows.map((row, index) => {
+ return <tr key={row.kelasMengemudiID}>
+ <td className="p-6 border border-[#F875AA] bg-white">{row.kelasMengemudiID}</td>
+ <td className="p-6 border border-[#F875AA] bg-white">{row.namaKelas}</td>
+ <td className="p-6 border border-[#F875AA] bg-white">{row.hargaKelas}</td>
+ <td className="p-6 border border-[#F875AA] bg-white">{row.totalJamKursus}</td>
+ <td className="p-6 border border-[#F875AA] bg-white">{row.jumlahSesi}</td>
+ <td className="p-6 border border-[#F875AA] bg-white">{row.jenisKendaraan}</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("/kelasmengemudi/edit/" + row.kelasMengemudiID)
+ 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.kelasMengemudiID)
+ }}>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 kelas mengemudi?</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