diff --git a/bun.lockb b/bun.lockb index 03d96215..88eaa6ad 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 5440fb7a..63e0b3b0 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "@tiptap/pm": "^2.2.3", "@tiptap/react": "^2.2.3", "@tiptap/starter-kit": "^2.2.3", + "@types/bun": "^1.1.14", "@types/lodash": "^4.17.4", "@types/mapbox-gl": "^3.4.0", "@types/node": "20.4.5", @@ -48,6 +49,7 @@ "@types/uuid": "^9.0.4", "autoprefixer": "10.4.14", "bufferutil": "^4.0.8", + "bun": "^1.1.38", "dayjs": "^1.11.10", "dotenv": "^16.4.5", "echarts": "^5.4.3", diff --git a/src/app/api/auth/register/route.ts b/src/app/api/auth/register/route.ts index 45d3cd9e..c307d724 100644 --- a/src/app/api/auth/register/route.ts +++ b/src/app/api/auth/register/route.ts @@ -12,47 +12,34 @@ export async function POST(req: Request) { }, }); - if (cekUsername) + try { + if (cekUsername) + return NextResponse.json( + { success: false, message: "Username sudah digunakan" }, + { status: 400 } + ); + + const createUser = await prisma.user.create({ + data: { + username: data.username, + nomor: data.nomor, + active: true, + }, + }); + + const token = await sessionCreate({ + sessionKey: process.env.NEXT_PUBLIC_BASE_SESSION_KEY!, + encodedKey: process.env.NEXT_PUBLIC_BASE_TOKEN_KEY!, + user: createUser as any, + }); + return NextResponse.json( - { success: false, message: "Username sudah digunakan" }, - { status: 400 } + { success: true, message: "Berhasil Login", data: createUser }, + { status: 200 } ); - - const createUser = await prisma.user.create({ - data: { - username: data.username, - nomor: data.nomor, - active: true, - }, - }); - - const token = await sessionCreate({ - sessionKey: process.env.NEXT_PUBLIC_BASE_SESSION_KEY!, - encodedKey: process.env.NEXT_PUBLIC_BASE_TOKEN_KEY!, - user: createUser as any, - }); - - // try { - // const createUserSession = await prisma.userSession.create({ - // data: { - // token: token as string, - // userId: createUser.id, - // }, - // }); - - // if (!createUserSession) - // return NextResponse.json( - // { success: false, message: "Gagal Membuat Session" }, - // { status: 400 } - // ); - // } catch (error) { - // console.log(error); - // } - - return NextResponse.json( - { success: true, message: "Berhasil Login", data: createUser }, - { status: 200 } - ); + } catch (error) { + console.log(error); + } } return NextResponse.json( diff --git a/src/app/api/auth/validasi/route.ts b/src/app/api/auth/validasi/route.ts index 05ee6b26..69c64a8c 100644 --- a/src/app/api/auth/validasi/route.ts +++ b/src/app/api/auth/validasi/route.ts @@ -20,7 +20,7 @@ export async function POST(req: Request) { }, }); - if (dataUser === null) + if (dataUser == null) return NextResponse.json( { success: false, message: "Nomor Belum Terdaftar" }, { status: 404 } @@ -32,37 +32,6 @@ export async function POST(req: Request) { user: dataUser as any, }); - // const cekSessionUser = await prisma.userSession.findFirst({ - // where: { - // userId: dataUser.id, - // }, - // }); - - // if (cekSessionUser !== null) { - // await prisma.userSession.delete({ - // where: { - // userId: dataUser.id, - // }, - // }); - // } - - // try { - // const createUserSession = await prisma.userSession.create({ - // data: { - // token: token as string, - // userId: dataUser.id, - // }, - // }); - - // if (!createUserSession) - // return NextResponse.json( - // { success: false, message: "Gagal Membuat Session" }, - // { status: 400 } - // ); - // } catch (error) { - // console.log(error); - // } - return NextResponse.json( { success: true, diff --git a/src/app/api/upload/route.ts b/src/app/api/upload/route.ts new file mode 100644 index 00000000..00e2b69c --- /dev/null +++ b/src/app/api/upload/route.ts @@ -0,0 +1,51 @@ +import { NextResponse } from "next/server"; +export async function POST(request: Request) { + const WS_APIKEY = process.env.WS_APIKEY; + console.log(WS_APIKEY); + + try { + const formData = await request.formData(); + + const res = await fetch("https://wibu-storage.wibudev.com/api/upload", { + method: "POST", + body: formData, + headers: { + Authorization: `Bearer ${process.env.WS_APIKEY}`, + }, + }); + + // if (res.ok) { + // console.log("Berhasil"); + // const hasil = await res.json(); + // return { success: true, data: hasil.data }; + // } else { + // const errorText = await res.text(); + // return { success: false, data: {} }; + // } + } catch (error) { + console.log(error); + } + + // try { + // const res = await fetch("https://wibu-storage.wibudev.com/api/upload", { + // method: "POST", + // body: formData, + // headers: { + // Authorization: `Bearer ${process.env.WS_APIKEY}`, + // }, + // }); + + // if (res.ok) { + // const hasil = await res.json(); + // return { success: true, data: hasil.data }; + // } else { + // const errorText = await res.text(); + // return { success: false, data: {} }; + // } + // } catch (error) { + // console.error("Upload error:", error); + // return { success: false, data: {} }; + // } + + return NextResponse.json({ success: true }); +} diff --git a/src/app/zCoba/page.tsx b/src/app/zCoba/page.tsx index f07fb56c..8df38920 100644 --- a/src/app/zCoba/page.tsx +++ b/src/app/zCoba/page.tsx @@ -1,18 +1,111 @@ +"use client"; + +import { MainColor } from "@/app_modules/_global/color"; import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; import Coba_TestLoading from "@/app_modules/zCoba"; +import { + Avatar, + Button, + Center, + FileButton, + Paper, + Stack, +} from "@mantine/core"; +import { IconCamera } from "@tabler/icons-react"; +import { useState } from "react"; +import { DIRECTORY_ID } from "../lib"; +import { TokenStorage } from "../lib/token"; +import { envs } from "@/lib/envs"; -export default async function Page() { - await new Promise((a, b) => { - setTimeout(a, 3000); - }); +export default function Page() { + const [filePP, setFilePP] = useState(null); + const [imgPP, setImgPP] = useState(); - const userLoginId = await funGetUserIdByToken(); + async function onSave() { + const body = { + file: filePP, + dirId: DIRECTORY_ID.profile_foto, + }; + + const token = + "QWERTYUIOPLKJHGFDSAZXCVBNMQAZWSXEDCRFVTGBYHNUJMIKOLPPOIUYTREWQLKJHGFDSAMNBVCXZlghvftyguhijknhbgvcfytguu8okjnhbgvfty7u8oilkjnhgvtygu7u8ojilnkhbgvhujnkhghvjhukjnhb"; + + const formData = new FormData(); + formData.append("file", filePP as any); + + const res = await fetch("/api/upload", { + method: "POST", + body: formData, + }); + + console.log(await res.json()); + } return ( <> - {/* */} - - {/* */} + +
+ {imgPP ? ( + + + + ) : ( + + + + )} +
+ + { + try { + const buffer = URL.createObjectURL( + new Blob([new Uint8Array(await files.arrayBuffer())]) + ); + setImgPP(buffer); + setFilePP(files); + } catch (error) { + console.log(error); + } + }} + accept="image/png,image/jpeg" + > + {(props) => ( + + )} + + + +
); } diff --git a/src/app_modules/_global/fun/upload/fun_upload_to_storage.ts b/src/app_modules/_global/fun/upload/fun_upload_to_storage.ts index 30bc8a51..52155b9b 100644 --- a/src/app_modules/_global/fun/upload/fun_upload_to_storage.ts +++ b/src/app_modules/_global/fun/upload/fun_upload_to_storage.ts @@ -54,6 +54,4 @@ export async function funGlobal_UploadToStorage({ console.error("Error:", error); return { success: false, data: {} }; } - - return { success: false, data: { id: "" } }; } diff --git a/src/app_modules/auth/register/view.tsx b/src/app_modules/auth/register/view.tsx index f72d7e50..a8b6f985 100644 --- a/src/app_modules/auth/register/view.tsx +++ b/src/app_modules/auth/register/view.tsx @@ -64,6 +64,11 @@ export default function Register() { const result = await res.json(); + if (res.status === 400) { + setLoading(false); + ComponentGlobal_NotifikasiPeringatan(result.message); + } + if (res.status === 200) { localStorage.removeItem("hipmi_auth_code_id"); ComponentGlobal_NotifikasiBerhasil(result.message); @@ -73,11 +78,6 @@ export default function Register() { nomor: data.nomor, }); } - - if (res.status === 400) { - setLoading(false); - ComponentGlobal_NotifikasiPeringatan(result.message); - } } catch (error) { console.log(error); } diff --git a/src/app_modules/katalog/component/drawer_katalog_new.tsx b/src/app_modules/katalog/component/drawer_katalog_new.tsx index 9e154560..752a7643 100644 --- a/src/app_modules/katalog/component/drawer_katalog_new.tsx +++ b/src/app_modules/katalog/component/drawer_katalog_new.tsx @@ -1,110 +1,153 @@ import { RouterAdminDashboard } from "@/app/lib/router_hipmi/router_admin"; -import { RouterPortofolio, RouterProfile } from "@/app/lib/router_hipmi/router_katalog"; +import { + RouterPortofolio, + RouterProfile, +} from "@/app/lib/router_hipmi/router_katalog"; import { AccentColor } from "@/app_modules/_global/color"; +import { + gs_admin_navbar_menu, + gs_admin_navbar_subMenu, +} from "@/app_modules/admin/_admin_global/new_global_state"; import Component_ButtonLogout from "@/app_modules/auth/logout/view"; -import { ActionIcon, Drawer, Group, SimpleGrid, Stack, Text } from "@mantine/core"; +import { + ActionIcon, + Drawer, + Group, + SimpleGrid, + Stack, + Text, +} from "@mantine/core"; import { IconDashboard } from "@tabler/icons-react"; -import { IconEdit, IconPencilPlus, IconPhotoEdit, IconPolaroid, IconX } from "@tabler/icons-react"; +import { + IconEdit, + IconPencilPlus, + IconPhotoEdit, + IconPolaroid, + IconX, +} from "@tabler/icons-react"; +import { useAtom } from "jotai"; import { useParams, useRouter } from "next/navigation"; -export default function DrawerKatalogNew({ opened, close, userRoleId, userId }: { opened: boolean, close: () => void, userRoleId: string, userId: string }) { - const param = useParams<{ id: string }>() - const router = useRouter() +export default function DrawerKatalogNew({ + opened, + close, + userRoleId, + userId, +}: { + opened: boolean; + close: () => void; + userRoleId: string; + userId: string; +}) { + const param = useParams<{ id: string }>(); + const router = useRouter(); + const [activeId, setActiveId] = useAtom(gs_admin_navbar_menu); + const [activeChildId, setActiveChildId] = useAtom(gs_admin_navbar_subMenu); - const listPage = [ - { - id: "1", - name: "Edit profile", - icon: , - path: RouterProfile.edit + param.id, - }, - { - id: "2", - name: "Ubah foto profile", - icon: , - path: RouterProfile.update_foto_profile + param.id, - }, - { - id: "3", - name: "Ubah latar belakang", - icon: , - path: RouterProfile.update_foto_background + param.id, - }, - { - id: "4", - name: "Tambah portofolio", - icon: , - path: RouterPortofolio.create + param.id, - }, - ]; + const listPage = [ + { + id: "1", + name: "Edit profile", + icon: , + path: RouterProfile.edit + param.id, + }, + { + id: "2", + name: "Ubah foto profile", + icon: , + path: RouterProfile.update_foto_profile + param.id, + }, + { + id: "3", + name: "Ubah latar belakang", + icon: , + path: RouterProfile.update_foto_background + param.id, + }, + { + id: "4", + name: "Tambah portofolio", + icon: , + path: RouterPortofolio.create + param.id, + }, + ]; - return <> + return ( + <> close()} - position={"bottom"} - size={"auto"} - withCloseButton={false} - styles={{ - content: { - padding: 0, - position: "absolute", - margin: "auto", - backgroundColor: "transparent", - left: 0, - right: 0, - width: 500, - }, - body: { - backgroundColor: AccentColor.darkblue, - borderTop: `2px solid ${AccentColor.blue}`, - borderRight: `1px solid ${AccentColor.blue}`, - borderLeft: `1px solid ${AccentColor.blue}`, - borderRadius: "20px 20px 0px 0px", - color: "white", - paddingBottom: "5%", - }, - }} + opened={opened} + onClose={() => close()} + position={"bottom"} + size={"auto"} + withCloseButton={false} + styles={{ + content: { + padding: 0, + position: "absolute", + margin: "auto", + backgroundColor: "transparent", + left: 0, + right: 0, + width: 500, + }, + body: { + backgroundColor: AccentColor.darkblue, + borderTop: `2px solid ${AccentColor.blue}`, + borderRight: `1px solid ${AccentColor.blue}`, + borderLeft: `1px solid ${AccentColor.blue}`, + borderRadius: "20px 20px 0px 0px", + color: "white", + paddingBottom: "5%", + }, + }} > - - - - - - - - {listPage.map((e, i) => ( - - { router.push(e.path, { scroll: false }); }} - > - {e.icon} - - - {e.name} - - - ))} + + + + + + + + {listPage.map((e, i) => ( + + { + router.push(e.path, { scroll: false }); + }} + > + {e.icon} + + + {e.name} + + + ))} - - {userRoleId != "1" && userRoleId != "" && ( - - { router.push(RouterAdminDashboard.main_admin, { scroll: false }); }} - > - - - - Dashboard Admin - - - )} - - + + {userRoleId != "1" && userRoleId != "" && ( + + { + setActiveId("Main"); + setActiveChildId(""); + router.push(RouterAdminDashboard.main_admin, { + scroll: false, + }); + }} + > + + + + Dashboard Admin + + + )} + + - ; -} \ No newline at end of file + + ); +} diff --git a/src/app_modules/katalog/component/regular_expressions.ts b/src/app_modules/katalog/component/regular_expressions.ts index 526ff127..bb809be0 100644 --- a/src/app_modules/katalog/component/regular_expressions.ts +++ b/src/app_modules/katalog/component/regular_expressions.ts @@ -1,2 +1,3 @@ export var validRegex = /^([a-zA-Z0-9\.!#$%&'*+/=?^_`{|}~-]+)@([a-zA-Z0-9])+.([a-z]+)(.[a-z]+)?$/; +export const gmailRegex = /^[a-zA-Z0-9._%+-]+@gmail\.com$/; \ No newline at end of file diff --git a/src/app_modules/katalog/profile/_component/button/comp_create_new_profile.tsx b/src/app_modules/katalog/profile/_component/button/comp_create_new_profile.tsx index 2ac6621b..e523a2ba 100644 --- a/src/app_modules/katalog/profile/_component/button/comp_create_new_profile.tsx +++ b/src/app_modules/katalog/profile/_component/button/comp_create_new_profile.tsx @@ -16,6 +16,8 @@ import { useState } from "react"; import funCreateNewProfile from "../../fun/fun_create_profile"; import { MODEL_PROFILE } from "../../model/interface"; import { validRegex } from "@/app_modules/katalog/component"; +import { envs } from "@/lib/envs"; +import { TokenProvider, TokenStorage } from "@/app/lib/token"; export function Profile_ComponentCreateNewProfile({ value, @@ -54,7 +56,6 @@ export function Profile_ComponentCreateNewProfile({ file: filePP, dirId: DIRECTORY_ID.profile_foto, }); - // console.log("ini foto", uploadPhoto); if (!uploadPhoto.success) { setLoading(false); return ComponentGlobal_NotifikasiPeringatan( @@ -62,36 +63,28 @@ export function Profile_ComponentCreateNewProfile({ ); } - if (uploadPhoto.success) { - const uploadBackground = await funGlobal_UploadToStorage({ - file: fileBG, - dirId: DIRECTORY_ID.profile_background, - }); - // console.log("ini background", uploadBackground); - if (!uploadBackground.success) { - setLoading(false); - return ComponentGlobal_NotifikasiPeringatan( - "Gagal upload background profile" - ); - } + const uploadBackground = await funGlobal_UploadToStorage({ + file: fileBG, + dirId: DIRECTORY_ID.profile_background, + }); + if (!uploadBackground.success) { + setLoading(false); + return ComponentGlobal_NotifikasiPeringatan( + "Gagal upload background profile" + ); + } - if (uploadBackground.success) { - const create = await funCreateNewProfile({ - data: newData as any, - imageId: uploadPhoto.data.id, - imageBackgroundId: uploadBackground.data.id, - }); - if (create.status === 201) { - ComponentGlobal_NotifikasiBerhasil( - "Berhasil membuat profile", - 3000 - ); - router.push(RouterHome.main_home, { scroll: false }); - } else { - ComponentGlobal_NotifikasiGagal(create.message); - setLoading(false); - } - } + const create = await funCreateNewProfile({ + data: newData as any, + imageId: uploadPhoto.data.id, + imageBackgroundId: uploadBackground.data.id, + }); + if (create.status === 201) { + ComponentGlobal_NotifikasiBerhasil("Berhasil membuat profile", 3000); + router.push(RouterHome.main_home, { scroll: false }); + } else { + ComponentGlobal_NotifikasiGagal(create.message); + setLoading(false); } } catch (error) { console.log(error); diff --git a/src/app_modules/katalog/profile/create/view.tsx b/src/app_modules/katalog/profile/create/view.tsx index 0ae5e658..c97942ee 100644 --- a/src/app_modules/katalog/profile/create/view.tsx +++ b/src/app_modules/katalog/profile/create/view.tsx @@ -24,6 +24,8 @@ import { IconAt, IconCamera, IconUpload } from "@tabler/icons-react"; import { useState } from "react"; import { validRegex } from "../../component"; import { Profile_ComponentCreateNewProfile } from "../_component"; +import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global"; +import { gmailRegex } from "../../component/regular_expressions"; export default function CreateProfile() { const [filePP, setFilePP] = useState(null); @@ -38,6 +40,9 @@ export default function CreateProfile() { jenisKelamin: "", }); + // Maksimal ukuran file dalam byte (2 MB) + const MAX_SIZE = 2 * 1024 * 1024; // 2 MB + return ( <> @@ -83,8 +88,15 @@ export default function CreateProfile() { const buffer = URL.createObjectURL( new Blob([new Uint8Array(await files.arrayBuffer())]) ); - setImgPP(buffer); - setFilePP(files); + + if (files.size > MAX_SIZE) { + ComponentGlobal_NotifikasiPeringatan( + "Ukuran file terlalu besar. Maksimal 2 MB." + ); + } else { + setImgPP(buffer); + setFilePP(files); + } } catch (error) { console.log(error); } @@ -138,8 +150,15 @@ export default function CreateProfile() { const buffer = URL.createObjectURL( new Blob([new Uint8Array(await files.arrayBuffer())]) ); - setImgBG(buffer); - setFileBG(files); + + if (files.size > MAX_SIZE) { + ComponentGlobal_NotifikasiPeringatan( + "Ukuran file terlalu besar. Maksimal 2 MB." + ); + } else { + setImgBG(buffer); + setFileBG(files); + } } catch (error) { console.log(error); } @@ -189,7 +208,7 @@ export default function CreateProfile() { maxLength={100} placeholder="Contoh: User@gmail.com" error={ - value.email.length > 0 && !value.email.match(validRegex) ? ( + value.email.length > 0 && !value.email.match(gmailRegex) ? ( ) : ( "" diff --git a/src/middleware.ts b/src/middleware.ts index 621bde58..f4cd23ab 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -19,6 +19,7 @@ const middlewareConfig: MiddlewareConfig = { userPath: "/dev/home", publicRoutes: [ "/", + "/api/upload", "/api/validation", "/api/auth/*", "/api/origin-url",