From 370e3ec4e4c6e1f342c966feb7a65b62a09d2945 Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Fri, 13 Sep 2024 16:12:42 +0800 Subject: [PATCH] fix: Upload image Deskripsi: - Upload image job di arahkan ke storage server ## No Issue --- prisma/schema.prisma | 10 +- .../37a3ffae-a422-4f4b-b63e-4e174a66d7ba.jpeg | Bin 0 -> 11231 bytes .../91150f04-cff1-4c1a-9c4a-b1e8eed2e4ae.jpeg | Bin 0 -> 11791 bytes src/app/contoh/page.tsx | 19 +- src/app/dev/admin/job/child/review/page.tsx | 1 - src/app/dev/auth/login/page.tsx | 2 +- src/app/dev/auth/splash/page.tsx | 12 +- src/app/dev/event/create/page.tsx | 6 +- src/app/layout.tsx | 8 +- src/app/lib/APIs.ts | 7 + src/app/lib/api.ts | 20 - src/app/lib/id-derectory.ts | 14 + src/app/lib/index.ts | 7 + src/app/lib/token.ts | 18 + .../_global/component/box_information.tsx | 15 +- .../comp_card_box_and_background.tsx | 43 ++ src/app_modules/_global/component/index.ts | 6 + src/app_modules/_global/component/loader.tsx | 14 +- src/app_modules/_global/fun/index.ts | 3 + .../fun/upload/fun_upload_to_storage.ts | 55 +++ src/app_modules/_global/notif_global/index.ts | 7 + .../admin/_admin_global/logout.tsx | 18 +- .../admin/job/child/arsip/index.tsx | 27 +- .../admin/job/child/publish/index.tsx | 55 +-- .../admin/job/child/reject/index.tsx | 4 +- .../admin/job/child/review/index.tsx | 6 +- .../admin/job/detail/detail_poster.tsx | 19 +- .../admin/job/fun/get/get_list_publish.ts | 13 +- .../admin/job/fun/get/get_list_reject.ts | 12 +- .../admin/job/fun/get/get_list_review.ts | 12 +- .../fun/get/get_list_table_by_status_id.ts | 49 +- src/app_modules/auth/splash/view.tsx | 13 +- src/app_modules/fun_global/get_user_token.ts | 9 +- .../comp_card_border_and_background.tsx | 4 +- .../button/comp_button_save_create.tsx | 164 +++++++ .../component/button/comp_button_update.tsx | 128 +++++ .../detail/comp_box_upload_image.tsx | 24 + .../job/component/detail/detail_data.tsx | 53 +- src/app_modules/job/component/index.ts | 7 + src/app_modules/job/create/TextEdit.tsx | 61 --- src/app_modules/job/create/view.tsx | 456 +++++++----------- src/app_modules/job/edit/view.tsx | 188 ++------ src/app_modules/job/fun/create/fun_create.ts | 95 ---- .../job/fun/create/fun_create_no_file.ts | 37 ++ .../job/fun/create/fun_create_with_file.ts | 131 +++++ .../job/fun/edit/fun_edit_by_id.ts | 67 +-- .../job/fun/get/get_two_for_home_view.ts | 1 + src/app_modules/job/fun/index.ts | 5 + src/app_modules/job/model/interface.ts | 15 +- src/app_modules/job/non_user_view/view.tsx | 27 +- ..._to_admin.tsx => create_notif_to_admin.ts} | 0 ...if_to_user.tsx => create_notif_to_user.ts} | 0 src/app_modules/notifikasi/fun/index.ts | 9 + .../notifikasi/ui/ui_notifiaksi.tsx | 8 +- src/app_modules/zCoba/ui_coba_upload_file.tsx | 219 +++++++++ 55 files changed, 1326 insertions(+), 877 deletions(-) create mode 100644 public/donasi/image/37a3ffae-a422-4f4b-b63e-4e174a66d7ba.jpeg create mode 100644 public/donasi/image_cerita/91150f04-cff1-4c1a-9c4a-b1e8eed2e4ae.jpeg create mode 100644 src/app/lib/APIs.ts delete mode 100644 src/app/lib/api.ts create mode 100644 src/app/lib/id-derectory.ts create mode 100644 src/app/lib/index.ts create mode 100644 src/app/lib/token.ts create mode 100644 src/app_modules/_global/component/comp_card_box_and_background.tsx create mode 100644 src/app_modules/_global/fun/index.ts create mode 100644 src/app_modules/_global/fun/upload/fun_upload_to_storage.ts create mode 100644 src/app_modules/_global/notif_global/index.ts create mode 100644 src/app_modules/job/component/button/comp_button_save_create.tsx create mode 100644 src/app_modules/job/component/button/comp_button_update.tsx create mode 100644 src/app_modules/job/component/detail/comp_box_upload_image.tsx create mode 100644 src/app_modules/job/component/index.ts delete mode 100644 src/app_modules/job/create/TextEdit.tsx delete mode 100644 src/app_modules/job/fun/create/fun_create.ts create mode 100644 src/app_modules/job/fun/create/fun_create_no_file.ts create mode 100644 src/app_modules/job/fun/create/fun_create_with_file.ts create mode 100644 src/app_modules/job/fun/index.ts rename src/app_modules/notifikasi/fun/create/{create_notif_to_admin.tsx => create_notif_to_admin.ts} (100%) rename src/app_modules/notifikasi/fun/create/{create_notif_to_user.tsx => create_notif_to_user.ts} (100%) create mode 100644 src/app_modules/notifikasi/fun/index.ts create mode 100644 src/app_modules/zCoba/ui_coba_upload_file.tsx diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 5aa6018e..c391b394 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -114,7 +114,6 @@ model Images { Donasi_PencairanDana Donasi_PencairanDana[] Donasi_Invoice Donasi_Invoice[] Portofolio Portofolio[] - Job Job[] Image_Map BusinessMaps[] @relation("ImageMap") Image_Pin BusinessMaps[] @relation("ImagePin") Investasi_Invoice Investasi_Invoice[] @@ -684,16 +683,15 @@ model Job { updatedAt DateTime @updatedAt isArsip Boolean @default(false) catatan String? + title String + content String @db.Text + deskripsi String @db.Text - title String - content String @db.Text - deskripsi String @db.Text - Images Images? @relation(fields: [imagesId], references: [id]) - imagesId String? Author User? @relation(fields: [authorId], references: [id]) authorId String? MasterStatus MasterStatus? @relation(fields: [masterStatusId], references: [id]) masterStatusId String? @default("2") + imageId String? } // ========================================= FORUM ========================================= // diff --git a/public/donasi/image/37a3ffae-a422-4f4b-b63e-4e174a66d7ba.jpeg b/public/donasi/image/37a3ffae-a422-4f4b-b63e-4e174a66d7ba.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..d3ea1214f5274a66ecf9271986db568fe70c7b89 GIT binary patch literal 11231 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 literal 0 HcmV?d00001 diff --git a/public/donasi/image_cerita/91150f04-cff1-4c1a-9c4a-b1e8eed2e4ae.jpeg b/public/donasi/image_cerita/91150f04-cff1-4c1a-9c4a-b1e8eed2e4ae.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..e25549da371bf341e52ea1e331cd8e5d934382f1 GIT binary patch literal 11791 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 a&t=?Rqdp*S(6aYTbHik|Oo8il<-Y)Be;Ypl literal 0 HcmV?d00001 diff --git a/src/app/contoh/page.tsx b/src/app/contoh/page.tsx index 211c2c35..8196cbb4 100644 --- a/src/app/contoh/page.tsx +++ b/src/app/contoh/page.tsx @@ -1,13 +1,14 @@ "use client"; import { ComponentNotifikasi_CardSkeleton } from "@/app_modules/notifikasi/component"; +import Coba_UploadFile from "@/app_modules/zCoba/ui_coba_upload_file"; import { Box, Button, Flex, Paper, Stack, Title } from "@mantine/core"; export default function Page() { - - return<> - - - + return ( + <> + + + ); return ( {Array.from(new Array(10), (_, i) => ( - + Contoh ))} diff --git a/src/app/dev/admin/job/child/review/page.tsx b/src/app/dev/admin/job/child/review/page.tsx index 55838522..84fd487f 100644 --- a/src/app/dev/admin/job/child/review/page.tsx +++ b/src/app/dev/admin/job/child/review/page.tsx @@ -1,6 +1,5 @@ import { AdminJob_TableReview } from "@/app_modules/admin/job"; import adminJob_getListReview from "@/app_modules/admin/job/fun/get/get_list_review"; -import { AdminJob_getListTableByStatusId } from "@/app_modules/admin/job/fun/get/get_list_table_by_status_id"; export default async function Page() { const dataReview = await adminJob_getListReview({ page: 1 }); diff --git a/src/app/dev/auth/login/page.tsx b/src/app/dev/auth/login/page.tsx index 9ef15c54..3cefa21a 100644 --- a/src/app/dev/auth/login/page.tsx +++ b/src/app/dev/auth/login/page.tsx @@ -2,7 +2,7 @@ import { Login } from "@/app_modules/auth"; import { cookies } from "next/headers"; export default function Page() { - const c = cookies().getAll(); + const c: any = cookies().getAll(); return ( <> diff --git a/src/app/dev/auth/splash/page.tsx b/src/app/dev/auth/splash/page.tsx index 183d35c3..f542411c 100644 --- a/src/app/dev/auth/splash/page.tsx +++ b/src/app/dev/auth/splash/page.tsx @@ -7,22 +7,16 @@ import { unsealData } from "iron-session"; import { getConfig } from "@/bin/config"; import yaml from "yaml"; import fs from "fs"; +import { user_funGetOneUserId } from "@/app_modules/fun_global"; const config = yaml.parse(fs.readFileSync("config.yaml").toString()); export default async function PageSplash() { - const c = cookies().get("ssn"); - const tkn = !c - ? null - : JSON.parse( - await unsealData(c.value as string, { - password: (await getConfig()).server.password, - }) - ); + const userLoginId = await user_funGetOneUserId(); return ( <> - + ); } diff --git a/src/app/dev/event/create/page.tsx b/src/app/dev/event/create/page.tsx index a1eb4bc1..96e80d5f 100644 --- a/src/app/dev/event/create/page.tsx +++ b/src/app/dev/event/create/page.tsx @@ -4,8 +4,10 @@ import { user_funGetOneUserId } from "@/app_modules/fun_global/get_user_token"; import _ from "lodash"; export default async function Page() { - const userId = await user_funGetOneUserId() + const userId = await user_funGetOneUserId(); const listTipeAcara = await Event_getMasterTipeAcara(); - return ; + return ( + + ); } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 18f8eb90..c2c6abc7 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,16 +1,20 @@ import MqttLoader from "@/util/mqtt_loader"; import RootStyleRegistry from "./emotion"; -import { Container } from "@mantine/core"; -import './globals.css' +import "./globals.css"; +import { TokenProvider } from "./lib/token"; + +const token = process.env.WS_APIKEY; export default function RootLayout({ children, }: { children: React.ReactNode; }) { + if (!token) return <>require token; return ( + {children} ); diff --git a/src/app/lib/APIs.ts b/src/app/lib/APIs.ts new file mode 100644 index 00000000..b2443d43 --- /dev/null +++ b/src/app/lib/APIs.ts @@ -0,0 +1,7 @@ +const APIs = { + GET: "https://wibu-storage.wibudev.com/api/files/", +}; + +export default APIs + + diff --git a/src/app/lib/api.ts b/src/app/lib/api.ts deleted file mode 100644 index 48812758..00000000 --- a/src/app/lib/api.ts +++ /dev/null @@ -1,20 +0,0 @@ -export const ApiHipmi = { - // Get one token - get_token: "/api/user/get-token", - // Auth - login: "/api/auth/login", - validasi: "/api/auth/validasi", - register: "/api/auth/register", - logout: "/api/auth/logout", - - //Profile - create_profile: "/api/profile/create", - edit_profile: "/api/profile/edit", - get_foto: "/api/profile/foto/", - - //Portofolio - create_portofolio: "/api/portofolio/create", - - //Investasi - get_gambar_investasi: "/api/investasi/gambar" -}; diff --git a/src/app/lib/id-derectory.ts b/src/app/lib/id-derectory.ts new file mode 100644 index 00000000..3ee92dce --- /dev/null +++ b/src/app/lib/id-derectory.ts @@ -0,0 +1,14 @@ +const DIRECTORY_ID = { + profile_foto: "cm0x93rgo000jbp5tj8baoaus", + profile_background: "cm0x93ze8000lbp5t1a8uc9wl", + portofolio_logo: "cm0yjl6ug000310njwmk6j0tx", + map_pin: "cm0yjq8up000710njv5klra32", + map_image: "cm0yjqnxl000910njplqho07w", + investasi_image: "cm0yjs35h000b10njb35o12h1", + investasi_bukti_transfer: "cm0yjsflu000d10njrc3lnqho", + donasi_image: "cm0yk1coh000f10nj597a99kv", + donasi_bukti_transfer: "cm0yk1pmh000h10njhi6m8b8t", + job_image: "cm0ypp6zl0003kp7jf59zuvjy", +}; + +export default DIRECTORY_ID; diff --git a/src/app/lib/index.ts b/src/app/lib/index.ts new file mode 100644 index 00000000..e9c5bc8c --- /dev/null +++ b/src/app/lib/index.ts @@ -0,0 +1,7 @@ +import APIs from "./APIs"; +import DIRECTORY_ID from "./id-derectory"; +import prisma from "./prisma"; + +export { DIRECTORY_ID }; +export { prisma }; +export { APIs }; diff --git a/src/app/lib/token.ts b/src/app/lib/token.ts new file mode 100644 index 00000000..7ce27bae --- /dev/null +++ b/src/app/lib/token.ts @@ -0,0 +1,18 @@ +"use client"; + +class TokenStorage { + static value = ""; + static get() { + return TokenStorage.value; + } + static set(value: string) { + TokenStorage.value = value; + } +} + +function TokenProvider({ token }: { token: string }) { + TokenStorage.set(token); + return null; +} + +export { TokenStorage, TokenProvider }; diff --git a/src/app_modules/_global/component/box_information.tsx b/src/app_modules/_global/component/box_information.tsx index ce66af3f..71a91909 100644 --- a/src/app_modules/_global/component/box_information.tsx +++ b/src/app_modules/_global/component/box_information.tsx @@ -3,10 +3,12 @@ import { AccentColor, MainColor } from "../color/color_pallet"; export default function ComponentGlobal_BoxInformation({ informasi, - isReport, + isReport, + fonsize, }: { informasi: string; isReport?: boolean; + fonsize?: number | string; }) { return ( <> @@ -20,10 +22,15 @@ export default function ComponentGlobal_BoxInformation({ }} > - + * Report - + {informasi} @@ -38,7 +45,7 @@ export default function ComponentGlobal_BoxInformation({ }} > - + *{" "} {informasi} diff --git a/src/app_modules/_global/component/comp_card_box_and_background.tsx b/src/app_modules/_global/component/comp_card_box_and_background.tsx new file mode 100644 index 00000000..aad520e2 --- /dev/null +++ b/src/app_modules/_global/component/comp_card_box_and_background.tsx @@ -0,0 +1,43 @@ +import { AccentColor } from "@/app_modules/_global/color"; +import { Card } from "@mantine/core"; +import React from "react"; + +export function ComponentGlobal_CardStyles({ + children, + backgroundColor, + border, + marginBottom, + height, + color, + onClickHandler, +}: { + children: React.ReactNode; + backgroundColor?: string; + border?: string; + marginBottom?: string | number; + height?: string | number; + color?: string; + onClickHandler?: React.MouseEventHandler; +}) { + return ( + <> + + {children} + + + ); +} diff --git a/src/app_modules/_global/component/index.ts b/src/app_modules/_global/component/index.ts index e5e7bad5..dcd7dc74 100644 --- a/src/app_modules/_global/component/index.ts +++ b/src/app_modules/_global/component/index.ts @@ -1,9 +1,15 @@ +import ComponentGlobal_BoxInformation from "./box_information"; import ComponentGlobal_AvatarAndAuthorName from "./comp_author_name_and_avatar"; +import { ComponentGlobal_CardStyles } from "./comp_card_box_and_background"; import ComponentGlobal_CardLoadingOverlay from "./comp_loading_card"; import ComponentGlobal_TampilanAngkaRatusan from "./comp_tampilan_angka_ratusan"; import ComponentGlobal_TampilanRupiah from "./comp_tampilan_rupiah"; +import ComponentGlobal_InputCountDown from "./input_countdown"; export { ComponentGlobal_TampilanRupiah }; export { ComponentGlobal_TampilanAngkaRatusan }; export { ComponentGlobal_AvatarAndAuthorName }; export { ComponentGlobal_CardLoadingOverlay }; +export { ComponentGlobal_BoxInformation }; +export { ComponentGlobal_InputCountDown }; +export { ComponentGlobal_CardStyles }; diff --git a/src/app_modules/_global/component/loader.tsx b/src/app_modules/_global/component/loader.tsx index 8df65a5d..e3c03c23 100644 --- a/src/app_modules/_global/component/loader.tsx +++ b/src/app_modules/_global/component/loader.tsx @@ -1,10 +1,20 @@ import { Loader } from "@mantine/core"; import { MainColor } from "../color/color_pallet"; -export default function ComponentGlobal_Loader({ size }: { size?: number }) { +export default function ComponentGlobal_Loader({ + size, + variant, +}: { + size?: number; + variant?: "dots" | "bars" | "oval"; +}) { return ( <> - + ); } diff --git a/src/app_modules/_global/fun/index.ts b/src/app_modules/_global/fun/index.ts new file mode 100644 index 00000000..e85ec448 --- /dev/null +++ b/src/app_modules/_global/fun/index.ts @@ -0,0 +1,3 @@ +import { funGlobal_UploadToStorage } from "./upload/fun_upload_to_storage"; + +export { funGlobal_UploadToStorage }; 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 new file mode 100644 index 00000000..9ef9155c --- /dev/null +++ b/src/app_modules/_global/fun/upload/fun_upload_to_storage.ts @@ -0,0 +1,55 @@ +import { TokenStorage } from "@/app/lib/token"; + +export async function funGlobal_UploadToStorage({ + file, + dirId, +}: { + file: File; + dirId: string; +}) { + if (!file) console.log("Tidak ada file"); + + const allowedMimeTypes = [ + "image/png", + "image/jpeg", + "image/gif", + "text/csv", + "application/pdf", + "application/msword", + "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + "application/vnd.ms-excel", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + "text/plain", + ]; + + if (!allowedMimeTypes.includes(file.type)) console.log("File tidak sesuai"); + + if (file.size > 100 * 1024 * 1024) console.log("File terlalu besar"); + + const formData = new FormData(); + formData.append("file", file); + formData.append("dirId", dirId); + + try { + const res = await fetch("https://wibu-storage.wibudev.com/api/upload", { + method: "POST", + body: formData, + headers: { + Authorization: `Bearer ${TokenStorage.value}`, + }, + }); + + const dataRes = await res.json(); + + if (res.ok) { + return { success: true, data: dataRes.data }; + } else { + const errorText = await res.text(); + console.error("Error:", errorText); + return { success: false, data: {} }; + } + } catch (error) { + console.error("Error:", error); + return { success: false, data: {} }; + } +} diff --git a/src/app_modules/_global/notif_global/index.ts b/src/app_modules/_global/notif_global/index.ts new file mode 100644 index 00000000..355d8145 --- /dev/null +++ b/src/app_modules/_global/notif_global/index.ts @@ -0,0 +1,7 @@ +import { ComponentGlobal_NotifikasiBerhasil } from "./notifikasi_berhasil"; +import { ComponentGlobal_NotifikasiGagal } from "./notifikasi_gagal"; +import { ComponentGlobal_NotifikasiPeringatan } from "./notifikasi_peringatan"; + +export { ComponentGlobal_NotifikasiBerhasil }; +export { ComponentGlobal_NotifikasiGagal }; +export { ComponentGlobal_NotifikasiPeringatan }; diff --git a/src/app_modules/admin/_admin_global/logout.tsx b/src/app_modules/admin/_admin_global/logout.tsx index 0b2508fc..837d3423 100644 --- a/src/app_modules/admin/_admin_global/logout.tsx +++ b/src/app_modules/admin/_admin_global/logout.tsx @@ -1,6 +1,9 @@ "use client"; -import { myConsole } from "@/app/fun/my_console"; -import { ApiHipmi } from "@/app/lib/api"; +import { Warna } from "@/app/lib/warna"; +import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil"; +import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global/notifikasi_peringatan"; +import { auth_Logout } from "@/app_modules/auth/fun/fun_logout"; +import { gs_kodeId } from "@/app_modules/auth/state/state"; import { ActionIcon, Button, @@ -10,15 +13,10 @@ import { Stack, Title, } from "@mantine/core"; -import { useRouter } from "next/navigation"; -import { useAtom } from "jotai"; -import { IconLogout } from "@tabler/icons-react"; -import { Warna } from "@/app/lib/warna"; import { useDisclosure } from "@mantine/hooks"; -import { gs_kodeId, gs_nomor, gs_otp } from "@/app_modules/auth/state/state"; -import { auth_Logout } from "@/app_modules/auth/fun/fun_logout"; -import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil"; -import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global/notifikasi_peringatan"; +import { IconLogout } from "@tabler/icons-react"; +import { useAtom } from "jotai"; +import { useRouter } from "next/navigation"; import { useState } from "react"; export default function Admin_Logout() { diff --git a/src/app_modules/admin/job/child/arsip/index.tsx b/src/app_modules/admin/job/child/arsip/index.tsx index 37819715..bb39e9c9 100644 --- a/src/app_modules/admin/job/child/arsip/index.tsx +++ b/src/app_modules/admin/job/child/arsip/index.tsx @@ -1,40 +1,21 @@ "use client"; -import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog"; import ComponentAdminGlobal_HeaderTamplate from "@/app_modules/admin/_admin_global/header_tamplate"; -import { adminEvent_getListPesertaById } from "@/app_modules/admin/event/fun/get/get_list_peserta_by_id"; -import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global/notifikasi_peringatan"; -import { - MODEL_EVENT, - MODEL_EVENT_PESERTA, -} from "@/app_modules/event/model/interface"; import { MODEL_JOB } from "@/app_modules/job/model/interface"; import { - MODEL_VOTE_KONTRIBUTOR, - MODEL_VOTING, - MODEL_VOTING_DAFTAR_NAMA_VOTE, -} from "@/app_modules/vote/model/interface"; -import { - Avatar, - Badge, Box, Button, - Card, Center, - Divider, - Grid, - Group, Modal, - Paper, ScrollArea, Spoiler, Stack, Table, Text, - Title, + Title } from "@mantine/core"; import { useDisclosure } from "@mantine/hooks"; -import { IconEyeCheck, IconEyeShare } from "@tabler/icons-react"; +import { IconEyeCheck } from "@tabler/icons-react"; import _ from "lodash"; import { useRouter } from "next/navigation"; import { useState } from "react"; @@ -74,13 +55,13 @@ function TableStatus({ listArsip }: { listArsip: MODEL_JOB[] }) {
- {e.imagesId ? ( + {e.imageId ? ( ) : ( -
+
Tidak ada poster @@ -147,28 +148,22 @@ function TableStatus({ dataPublish }: { dataPublish: any }) { return ( <> - - {/*
{JSON.stringify(listUser, null, 2)}
*/} - - - Publish - - } - radius={"xl"} - placeholder="Masukan judul" - onChange={(val) => { - onSearch(val.currentTarget.value); - }} - /> - + } + radius={"xl"} + placeholder="Masukan judul" + onChange={(val) => { + onSearch(val.currentTarget.value); + }} + /> + } + /> @@ -217,8 +212,6 @@ function TableStatus({ dataPublish }: { dataPublish: any }) {
- - ); } diff --git a/src/app_modules/admin/job/child/reject/index.tsx b/src/app_modules/admin/job/child/reject/index.tsx index 8299b4e1..476da95a 100644 --- a/src/app_modules/admin/job/child/reject/index.tsx +++ b/src/app_modules/admin/job/child/reject/index.tsx @@ -97,13 +97,13 @@ function TableStatus({ listReject }: { listReject: any }) {
- {e.imagesId ? ( + {e.imageId ? ( + + ); +} + +export default Job_ComponentButtonSaveCreate; diff --git a/src/app_modules/job/component/button/comp_button_update.tsx b/src/app_modules/job/component/button/comp_button_update.tsx new file mode 100644 index 00000000..225cb84d --- /dev/null +++ b/src/app_modules/job/component/button/comp_button_update.tsx @@ -0,0 +1,128 @@ +import { MainColor, AccentColor } from "@/app_modules/_global/color"; +import { + ComponentGlobal_NotifikasiBerhasil, + ComponentGlobal_NotifikasiGagal, + ComponentGlobal_NotifikasiPeringatan, +} from "@/app_modules/_global/notif_global"; +import { Modal, Stack, Title, Group, Button } from "@mantine/core"; +import { useDisclosure, useWindowScroll } from "@mantine/hooks"; +import { useAtom } from "jotai"; +import { useRouter } from "next/navigation"; +import { useState } from "react"; +import { job_EditById } from "../../fun/edit/fun_edit_by_id"; +import { gs_job_hot_menu, gs_job_status } from "../../global_state"; +import { MODEL_JOB } from "../../model/interface"; +import { funGlobal_UploadToStorage } from "@/app_modules/_global/fun"; +import { DIRECTORY_ID } from "@/app/lib"; + +export function Job_ComponentButtonUpdate({ + value, + file, +}: { + value: MODEL_JOB; + file: File; +}) { + const router = useRouter(); + const [isLoading, setIsLoading] = useState(false); + + const [hotMenu, setHotMenu] = useAtom(gs_job_hot_menu); + const [status, setStatus] = useAtom(gs_job_status); + const [opened, { open, close }] = useDisclosure(false); + const [scroll, scrollTo] = useWindowScroll(); + + async function onUpdate() { + if (file === null) { + const update = await job_EditById({ + data: value, + }); + if (update.status !== 200) + return ComponentGlobal_NotifikasiGagal(update.message); + } else { + const uploadFile = await funGlobal_UploadToStorage({ + file: file, + dirId: DIRECTORY_ID.job_image, + }); + + if (!uploadFile.success) + return ComponentGlobal_NotifikasiPeringatan("Gagal upload gambar"); + + const updateWithFile = await job_EditById({ + data: value, + }); + if (updateWithFile.status !== 200) + return ComponentGlobal_NotifikasiGagal(updateWithFile.message); + } + + setHotMenu(2); + setStatus("Draft"); + setIsLoading(true); + router.back(); + return ComponentGlobal_NotifikasiBerhasil("Berhasil Update"); + } + + return ( + <> + + + + Anda yakin menyimpan data ini ? + + + + + + + + + + + ); +} diff --git a/src/app_modules/job/component/detail/comp_box_upload_image.tsx b/src/app_modules/job/component/detail/comp_box_upload_image.tsx new file mode 100644 index 00000000..f9de93fb --- /dev/null +++ b/src/app_modules/job/component/detail/comp_box_upload_image.tsx @@ -0,0 +1,24 @@ +import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component"; +import { Box } from "@mantine/core"; + +export function Job_ComponentBoxUploadImage({ + children, +}: { + children: React.ReactNode; +}) { + return ( + <> + + + {children} + + + + ); +} diff --git a/src/app_modules/job/component/detail/detail_data.tsx b/src/app_modules/job/component/detail/detail_data.tsx index d5216eb2..9727bcd8 100644 --- a/src/app_modules/job/component/detail/detail_data.tsx +++ b/src/app_modules/job/component/detail/detail_data.tsx @@ -1,21 +1,35 @@ "use client"; -import { Card, Stack, Skeleton, Image, Text, Center } from "@mantine/core"; -import { MODEL_JOB } from "../../model/interface"; -import { RouterJob } from "@/app/lib/router_hipmi/router_job"; +import { APIs } from "@/app/lib"; import { AccentColor, MainColor, } from "@/app_modules/_global/color/color_pallet"; +import { + Card, + Center, + Image, + Loader, + Paper, + Skeleton, + Stack, + Text, +} from "@mantine/core"; +import { MODEL_JOB } from "../../model/interface"; +import { useState } from "react"; +import ComponentGlobal_Loader from "@/app_modules/_global/component/loader"; export default function ComponentJob_DetailData({ data, }: { data?: MODEL_JOB; }) { + const [isLoading, setIsLoading] = useState(true); + return ( <> {/*
{JSON.stringify(data, null, 2)}
*/} + {data ? ( - {data.imagesId ? ( + {data.imageId ? ( + {isLoading ? ( + +
+ +
+
+ ) : ( + "" + )} + { + setIsLoading(false); + }} + onError={() => { + setIsLoading(false); + }} + alt="Image" + src={APIs.GET + data?.imageId} + maw={200} />
) : ( diff --git a/src/app_modules/job/component/index.ts b/src/app_modules/job/component/index.ts new file mode 100644 index 00000000..616e108c --- /dev/null +++ b/src/app_modules/job/component/index.ts @@ -0,0 +1,7 @@ +import Job_ComponentButtonSaveCreate from "./button/comp_button_save_create"; +import { Job_ComponentButtonUpdate } from "./button/comp_button_update"; +import { Job_ComponentBoxUploadImage } from "./detail/comp_box_upload_image"; + +export { Job_ComponentButtonSaveCreate }; +export { Job_ComponentBoxUploadImage }; +export { Job_ComponentButtonUpdate }; diff --git a/src/app_modules/job/create/TextEdit.tsx b/src/app_modules/job/create/TextEdit.tsx deleted file mode 100644 index c75551cd..00000000 --- a/src/app_modules/job/create/TextEdit.tsx +++ /dev/null @@ -1,61 +0,0 @@ -"use client"; - -import { Center, Stack } from "@mantine/core"; -import { useShallowEffect } from "@mantine/hooks"; -import dynamic from "next/dynamic"; -import React, { useState } from "react"; -const ReactQuill = dynamic( - () => { - return import("react-quill"); - }, - { ssr: false } -); -import "react-quill/dist/quill.snow.css"; - -export default function Demo() { - const [value, setValue] = useState(""); - const [udah, setUdah] = useState(false); - - // useShallowEffect(() => { - // if (window && window.document) setUdah(true); - // }, []); - - // if (!udah) return <>
; - return ( - - Judul Lowongan Kerja -


-

Syarat & Ketentuan :

-
    -
  1. Minimal pendidika SMA / Sederajat
  2. -
  3. Pasif berbahasa inggris
  4. -
  5. Dll,.
  6. -
-


-

Deskripsi :

-

Jika berminat dapat menghubungi WA berikut

-

+6281 xxx xxx xx

-

Kirim CV anda melalui email berikut

-

@test-hipmi.com

-

Atau kunjungi website kami:

-

https://test-hipmi.wibudev.com/

- `} - modules={{ - toolbar: [ - [{ header: [1, 2, 3, 4, 5, 6, false] }], - ["bold", "italic", "underline", "link"], - // [{ align: [] }], - [{ list: "ordered" }, { list: "bullet" }], - - ["clean"], - ], - }} - theme="snow" - onChange={setValue} - /> - {/* {value} -
*/} - - ); -} diff --git a/src/app_modules/job/create/view.tsx b/src/app_modules/job/create/view.tsx index 57a33249..23c6bcce 100644 --- a/src/app_modules/job/create/view.tsx +++ b/src/app_modules/job/create/view.tsx @@ -1,24 +1,19 @@ "use client"; import { + AspectRatio, + Box, Button, Center, FileButton, - Group, Image, - Loader, - Paper, Stack, Text, TextInput, } from "@mantine/core"; import { IconCamera, IconUpload } from "@tabler/icons-react"; -import { useAtom } from "jotai"; -import { useRouter } from "next/navigation"; -import { useState } from "react"; -import { gs_job_hot_menu, gs_job_status } from "../global_state"; - import dynamic from "next/dynamic"; +import { useState } from "react"; import "react-quill/dist/quill.snow.css"; const ReactQuill = dynamic( () => { @@ -27,22 +22,21 @@ const ReactQuill = dynamic( { ssr: false } ); -import { RouterJob } from "@/app/lib/router_hipmi/router_job"; import { AccentColor, MainColor, } from "@/app_modules/_global/color/color_pallet"; -import ComponentGlobal_BoxInformation from "@/app_modules/_global/component/box_information"; -import ComponentGlobal_InputCountDown from "@/app_modules/_global/component/input_countdown"; -import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil"; -import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global/notifikasi_gagal"; -import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global/notifikasi_peringatan"; -import notifikasiToAdmin_funCreate from "@/app_modules/notifikasi/fun/create/create_notif_to_admin"; -import mqtt_client from "@/util/mqtt_client"; -import { useShallowEffect } from "@mantine/hooks"; + +import { + ComponentGlobal_BoxInformation, + ComponentGlobal_CardStyles, + ComponentGlobal_InputCountDown, +} from "@/app_modules/_global/component"; +import { + Job_ComponentBoxUploadImage, + Job_ComponentButtonSaveCreate, +} from "../component"; import { defaultDeskripsi, defaultSyarat } from "../component/default_value"; -import { Job_funCreate } from "../fun/create/fun_create"; -import { MODEL_JOB } from "../model/interface"; export default function Job_Create() { const [value, setValue] = useState({ @@ -52,272 +46,172 @@ export default function Job_Create() { }); const [reload, setReload] = useState(false); const [file, setFile] = useState(null); - const [images, setImages] = useState(); + const [img, setImg] = useState(); - useShallowEffect(() => { - if (window && window.document) setReload(true); - }, []); + // useShallowEffect(() => { + // if (window && window.document) setReload(true); + // }, []); return ( - <> - {!reload ? ( -
- -
- ) : ( - - - {images ? ( - - ) : ( - - - - - Upload Gambar - - - + + + + + + {img ? ( + + Foto + + ) : ( + + + + Upload Gambar + + + )} + + +
+ { + try { + const buffer = URL.createObjectURL( + new Blob([new Uint8Array(await files.arrayBuffer())]) + ); + setImg(buffer); + setFile(files); + } catch (error) { + console.log(error); + } + }} + accept="image/png,image/jpeg" + > + {(props) => ( + )} - - { - try { - const buffer = URL.createObjectURL( - new Blob([new Uint8Array(await files.arrayBuffer())]) - ); - if (files.size > 200000) { - ComponentGlobal_NotifikasiPeringatan( - "Maaf, Ukuran file terlalu besar, maksimal 2mb", - 3000 - ); - } else { - setImages(buffer); - setFile(files); - } - } catch (error) { - console.log(error); - } - }} - accept="image/png,image/jpeg" - > - {(props) => ( - - )} - - - - - - - { - setValue({ - ...value, - title: val.currentTarget.value, - }); - }} - /> - - - - Syarat & Ketentuan - - {" "} - * - - - - - { - setValue({ - ...value, - content: val, - }); - }} - /> - - - - - - Deskripsi - - {" "} - * - - - - { - setValue({ - ...value, - deskripsi: val, - }); - }} - /> - - - - - - - - )} - - ); -} - -function ButtonAction({ value, file }: { value: MODEL_JOB; file: FormData }) { - const router = useRouter(); - const [isLoading, setIsLoading] = useState(false); - - const [hotMenu, setHotMenu] = useAtom(gs_job_hot_menu); - const [status, setStatus] = useAtom(gs_job_status); - - async function onCreate() { - const gambar = new FormData(); - gambar.append("file", file as any); - - const create = await Job_funCreate(value as any, gambar); - if (create.status === 201) { - const dataNotif: any = { - appId: create.data?.id as any, - kategoriApp: "JOB", - status: create.data?.MasterStatus?.name as any, - userId: create.data?.authorId as any, - pesan: create.data?.title as any, - title: "Job baru", - }; - - const notif = await notifikasiToAdmin_funCreate({ - data: dataNotif as any, - }); - // console.log(notif); . - - if (notif.status === 201) { - mqtt_client.publish( - "ADMIN", - JSON.stringify({ - count: 1, - }) - ); - setHotMenu(2); - setStatus("Review"); - router.replace(RouterJob.status); - setIsLoading(true); - ComponentGlobal_NotifikasiBerhasil(create.message); - } - } else { - ComponentGlobal_NotifikasiGagal(create.message); - } - } - - return ( - <> - - - - + +
- + + + + { + setValue({ + ...value, + title: val.currentTarget.value, + }); + }} + /> + + + + Syarat & Ketentuan + + {" "} + * + + + + + { + setValue({ + ...value, + content: val, + }); + }} + /> + + + + + + + Deskripsi + + {" "} + * + + + + + { + setValue({ + ...value, + deskripsi: val, + }); + }} + /> + + + + + + + +
); } diff --git a/src/app_modules/job/edit/view.tsx b/src/app_modules/job/edit/view.tsx index 180d70db..4810d7fa 100644 --- a/src/app_modules/job/edit/view.tsx +++ b/src/app_modules/job/edit/view.tsx @@ -3,6 +3,7 @@ import { RouterJob } from "@/app/lib/router_hipmi/router_job"; import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil"; import { + AspectRatio, Button, Center, FileButton, @@ -14,7 +15,7 @@ import { Stack, Text, TextInput, - Title + Title, } from "@mantine/core"; import { useDisclosure, @@ -36,55 +37,53 @@ import ComponentGlobal_InputCountDown from "@/app_modules/_global/component/inpu import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global/notifikasi_gagal"; import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global/notifikasi_peringatan"; import dynamic from "next/dynamic"; -import { Job_EditById } from "../fun/edit/fun_edit_by_id"; +import { job_EditById } from "../fun/edit/fun_edit_by_id"; const ReactQuill = dynamic( () => { return import("react-quill"); }, { ssr: false } ); +import "react-quill/dist/quill.snow.css"; +import { Job_ComponentBoxUploadImage, Job_ComponentButtonUpdate } from "../component"; +import { APIs } from "@/app/lib"; +import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component"; export default function Job_Edit({ dataJob }: { dataJob: MODEL_JOB }) { const [value, setValue] = useState(dataJob); - const [reload, setReload] = useState(false); const [file, setFile] = useState(null); - const [images, setImages] = useState(); - const [maxFile, setMaxFile] = useState(false); + const [img, setImg] = useState(); - useShallowEffect(() => { - if (window && window.document) setReload(true); - }, []); + // useShallowEffect(() => { + // if (window && window.document) setReload(true); + // }, []); return ( <> - {!reload ? ( -
- -
- ) : ( - - - {images ? ( - - ) : value.imagesId ? ( - Foto + + + + {value.imageId ? ( + + Foto + ) : ( - - - - - Upload Gambar - - - + + + + Upload Gambar + + )} + +
{ try { @@ -92,19 +91,8 @@ export default function Job_Edit({ dataJob }: { dataJob: MODEL_JOB }) { new Blob([new Uint8Array(await files.arrayBuffer())]) ); - if (files.size > 200000) { - // setMaxFile(true); - ComponentGlobal_NotifikasiPeringatan( - "Maaf, Ukuran file terlalu besar, maksimal 2mb", - 3000 - ); - } else { - // console.log(buffer, "ini buffer"); - // console.log(files, " ini file"); - - setImages(buffer); - setFile(files); - } + setImg(buffer); + setFile(files); } catch (error) { console.log(error); } @@ -121,21 +109,15 @@ export default function Job_Edit({ dataJob }: { dataJob: MODEL_JOB }) { border: `1px solid ${AccentColor.yellow}`, }} > - + )} - +
+
- + + + - -
- )} + +
); } -function ButtonAction({ value, file }: { value: MODEL_JOB; file: FormData }) { - const router = useRouter(); - const [isLoading, setIsLoading] = useState(false); - const [hotMenu, setHotMenu] = useAtom(gs_job_hot_menu); - const [status, setStatus] = useAtom(gs_job_status); - const [opened, { open, close }] = useDisclosure(false); - const [scroll, scrollTo] = useWindowScroll(); - - async function onUpdate() { - const gambar = new FormData(); - gambar.append("file", file as any); - - await Job_EditById(value, gambar).then((res) => { - if (res.status === 200) { - setHotMenu(2); - setStatus("Draft"); - ComponentGlobal_NotifikasiBerhasil(res.message); - setIsLoading(true); - router.back(); - } else { - ComponentGlobal_NotifikasiGagal(res.message); - } - }); - } - - return ( - <> - - - - Anda yakin menyimpan data ini ? - - - - - - - - - - ); -} diff --git a/src/app_modules/job/fun/create/fun_create.ts b/src/app_modules/job/fun/create/fun_create.ts deleted file mode 100644 index 7f0a8fd2..00000000 --- a/src/app_modules/job/fun/create/fun_create.ts +++ /dev/null @@ -1,95 +0,0 @@ -"use server"; - -import prisma from "@/app/lib/prisma"; -import { user_funGetOneUserId } from "@/app_modules/fun_global/get_user_token"; -import _ from "lodash"; -import { v4 } from "uuid"; -import fs from "fs"; -import { revalidatePath } from "next/cache"; -import { MODEL_JOB } from "../../model/interface"; -import path from "path"; -const root = process.cwd(); - -export async function Job_funCreate(req: MODEL_JOB, file: FormData) { - const authorId = await user_funGetOneUserId(); - - const dataImage: any = file.get("file"); - if (dataImage !== "null") { - const fileName = dataImage.name; - const fileExtension = _.lowerCase(dataImage.name.split(".").pop()); - const fRandomName = v4(fileName) + "." + fileExtension; - - const upload = await prisma.images.create({ - data: { - url: fRandomName, - label: "JOB", - }, - select: { - id: true, - url: true, - }, - }); - - if (!upload) return { status: 400, message: "Gagal upload gambar" }; - const uploadFolder = Buffer.from(await dataImage.arrayBuffer()); - fs.writeFileSync( - path.join(root, `public/job/${upload.url}`), - uploadFolder - ); - const createDataWithImg = await prisma.job.create({ - data: { - title: req.title, - content: req.content, - deskripsi: req.deskripsi, - authorId: authorId, - imagesId: upload.id, - }, - select: { - id: true, - authorId: true, - MasterStatus: { - select: { - name: true, - }, - }, - title: true, - }, - }); - - if (!createDataWithImg) return { status: 400, message: "Gagal Disimpan" }; - revalidatePath("/dev/job/main/status"); - return { - data: createDataWithImg, - status: 201, - message: "Berhasil Disimpan", - }; - } else { - const createDataWithoutImg = await prisma.job.create({ - data: { - title: req.title, - content: req.content, - deskripsi: req.deskripsi, - authorId: authorId, - }, - select: { - id: true, - authorId: true, - MasterStatus: { - select: { - name: true, - }, - }, - title: true, - }, - }); - - if (!createDataWithoutImg) - return { status: 400, message: "Gagal Disimpan" }; - revalidatePath("/dev/job/main/status"); - return { - data: createDataWithoutImg, - status: 201, - message: "Berhasil Disimpan", - }; - } -} diff --git a/src/app_modules/job/fun/create/fun_create_no_file.ts b/src/app_modules/job/fun/create/fun_create_no_file.ts new file mode 100644 index 00000000..0d8e5137 --- /dev/null +++ b/src/app_modules/job/fun/create/fun_create_no_file.ts @@ -0,0 +1,37 @@ +"use server"; + +import { prisma } from "@/app/lib"; +import { user_funGetOneUserId } from "@/app_modules/fun_global"; +import { revalidatePath } from "next/cache"; +import { MODEL_JOB } from "../../model/interface"; + +export async function job_funCreateNoFile({ data }: { data: MODEL_JOB }) { + const authorId = await user_funGetOneUserId(); + + const createNoImage = await prisma.job.create({ + data: { + title: data.title, + content: data.content, + deskripsi: data.deskripsi, + authorId: authorId, + }, + select: { + id: true, + authorId: true, + MasterStatus: { + select: { + name: true, + }, + }, + title: true, + }, + }); + + if (!createNoImage) return { status: 400, message: "Gagal Disimpan" }; + revalidatePath("/dev/job/main/status"); + return { + status: 201, + message: "Berhasil Disimpan", + data: createNoImage, + }; +} diff --git a/src/app_modules/job/fun/create/fun_create_with_file.ts b/src/app_modules/job/fun/create/fun_create_with_file.ts new file mode 100644 index 00000000..2007946f --- /dev/null +++ b/src/app_modules/job/fun/create/fun_create_with_file.ts @@ -0,0 +1,131 @@ +"use server"; + +import prisma from "@/app/lib/prisma"; +import { user_funGetOneUserId } from "@/app_modules/fun_global/get_user_token"; +import _ from "lodash"; +import { v4 } from "uuid"; +import fs from "fs"; +import { revalidatePath } from "next/cache"; +import { MODEL_JOB } from "../../model/interface"; +import path from "path"; +import { funGlobal_UploadToStorage } from "@/app_modules/_global/fun"; +import { DIRECTORY_ID } from "@/app/lib"; + +export async function job_funCreateWithFile({ + data, + fileId, +}: { + data: MODEL_JOB; + fileId: string; +}) { + const authorId = await user_funGetOneUserId(); + console.log(authorId); + + const createDataWithoutImg = await prisma.job.create({ + data: { + title: data.title, + content: data.content, + deskripsi: data.deskripsi, + authorId: authorId, + imageId: fileId, + }, + select: { + id: true, + authorId: true, + MasterStatus: { + select: { + name: true, + }, + }, + title: true, + }, + }); + + if (!createDataWithoutImg) return { status: 400, message: "Gagal Disimpan" }; + revalidatePath("/dev/job/main/status"); + return { + data: createDataWithoutImg, + status: 201, + message: "Berhasil Disimpan", + }; + + // const dataImage: any = file.get("file"); + // if (dataImage !== "null") { + // const fileName = dataImage.name; + // const fileExtension = _.lowerCase(dataImage.name.split(".").pop()); + // const fRandomName = v4(fileName) + "." + fileExtension; + + // const upload = await prisma.images.create({ + // data: { + // url: fRandomName, + // label: "JOB", + // }, + // select: { + // id: true, + // url: true, + // }, + // }); + + // if (!upload) return { status: 400, message: "Gagal upload gambar" }; + // const uploadFolder = Buffer.from(await dataImage.arrayBuffer()); + // fs.writeFileSync( + // path.join(root, `public/job/${upload.url}`), + // uploadFolder + // ); + // const createDataWithImg = await prisma.job.create({ + // data: { + // title: req.title, + // content: req.content, + // deskripsi: req.deskripsi, + // authorId: authorId, + // imagesId: upload.id, + // }, + // select: { + // id: true, + // authorId: true, + // MasterStatus: { + // select: { + // name: true, + // }, + // }, + // title: true, + // }, + // }); + + // if (!createDataWithImg) return { status: 400, message: "Gagal Disimpan" }; + // revalidatePath("/dev/job/main/status"); + // return { + // data: createDataWithImg, + // status: 201, + // message: "Berhasil Disimpan", + // }; + // } else { + // const createDataWithoutImg = await prisma.job.create({ + // data: { + // title: req.title, + // content: req.content, + // deskripsi: req.deskripsi, + // authorId: authorId, + // }, + // select: { + // id: true, + // authorId: true, + // MasterStatus: { + // select: { + // name: true, + // }, + // }, + // title: true, + // }, + // }); + + // if (!createDataWithoutImg) + // return { status: 400, message: "Gagal Disimpan" }; + // revalidatePath("/dev/job/main/status"); + // return { + // data: createDataWithoutImg, + // status: 201, + // message: "Berhasil Disimpan", + // }; + // } +} diff --git a/src/app_modules/job/fun/edit/fun_edit_by_id.ts b/src/app_modules/job/fun/edit/fun_edit_by_id.ts index 9d341fd5..ec59bcdb 100644 --- a/src/app_modules/job/fun/edit/fun_edit_by_id.ts +++ b/src/app_modules/job/fun/edit/fun_edit_by_id.ts @@ -6,68 +6,51 @@ import { v4 } from "uuid"; import fs from "fs"; import { MODEL_JOB } from "../../model/interface"; import { revalidatePath } from "next/cache"; +import { RouterJob } from "@/app/lib/router_hipmi/router_job"; -export async function Job_EditById(req: MODEL_JOB, file: FormData) { - // console.log(file); - // console.log(req); - // return { status: 200 }; - - const dataImage: any = file.get("file"); - if (dataImage !== "null") { - const fileName = dataImage.name; - const fileExtension = _.lowerCase(dataImage.name.split(".").pop()); - const fRandomName = v4(fileName) + "." + fileExtension; - - const upload = await prisma.images.create({ - data: { - url: fRandomName, - label: "JOB", - }, - select: { - id: true, - url: true, - }, - }); - - if (!upload) return { status: 400, message: "Gagal upload gambar" }; - const uploadFolder = Buffer.from(await dataImage.arrayBuffer()); - fs.writeFileSync(`./public/job/${upload.url}`, uploadFolder); - +export async function job_EditById({ + data, + imageId, +}: { + data: MODEL_JOB; + imageId?: string; +}) { + if (imageId == undefined) { const updt = await prisma.job.update({ where: { - id: req.id, + id: data.id, }, data: { - title: req.title, - content: req.content, - deskripsi: req.deskripsi, - imagesId: upload.id, + title: data.title, + content: data.content, + deskripsi: data.deskripsi, }, }); - if (!updt) return { status: 400, message: "Gagal Update" }; - revalidatePath("/dev/job/detail/draft"); + revalidatePath(RouterJob.status); + return { status: 200, - message: "Berhasil Disimpan", + message: "Berhasil Update", }; } else { - const updt = await prisma.job.update({ + const updtWithFile = await prisma.job.update({ where: { - id: req.id, + id: data.id, }, data: { - title: req.title, - content: req.content, - deskripsi: req.deskripsi, + title: data.title, + content: data.content, + deskripsi: data.deskripsi, + imageId: imageId, }, }); + if (!updtWithFile) return { status: 400, message: "Gagal Update" }; + revalidatePath(RouterJob.status); - if (!updt) return { status: 400, message: "Gagal Update" }; - revalidatePath("/dev/job/detail/draft"); return { status: 200, - message: "Berhasil Disimpan", + message: "Berhasil Update", }; } } diff --git a/src/app_modules/job/fun/get/get_two_for_home_view.ts b/src/app_modules/job/fun/get/get_two_for_home_view.ts index e1a0fd6a..fe9db5d6 100644 --- a/src/app_modules/job/fun/get/get_two_for_home_view.ts +++ b/src/app_modules/job/fun/get/get_two_for_home_view.ts @@ -10,6 +10,7 @@ export async function job_getTwoForHomeView() { }, where: { isActive: true, + masterStatusId: "1" }, select: { id: true, diff --git a/src/app_modules/job/fun/index.ts b/src/app_modules/job/fun/index.ts new file mode 100644 index 00000000..3e4cf25f --- /dev/null +++ b/src/app_modules/job/fun/index.ts @@ -0,0 +1,5 @@ +import { job_funCreateNoFile } from "./create/fun_create_no_file"; +import { job_funCreateWithFile } from "./create/fun_create_with_file"; + +export { job_funCreateWithFile }; +export { job_funCreateNoFile }; diff --git a/src/app_modules/job/model/interface.ts b/src/app_modules/job/model/interface.ts index 46548408..9ded22d2 100644 --- a/src/app_modules/job/model/interface.ts +++ b/src/app_modules/job/model/interface.ts @@ -1,11 +1,13 @@ import { MODEL_USER } from "@/app_modules/home/model/interface"; -import { MODEL_IMAGES, MODEL_NEW_DEFAULT_MASTER } from "@/app_modules/model_global/interface"; +import { + MODEL_NEW_DEFAULT_MASTER +} from "@/app_modules/model_global/interface"; export interface MODEL_JOB { id: string; - title: string + title: string; content: string; - deskripsi: string + deskripsi: string; isActive: boolean; isArsip: boolean; createdAt: Date; @@ -13,8 +15,7 @@ export interface MODEL_JOB { catatan: string; authorId: string; Author: MODEL_USER; - Images: MODEL_IMAGES - imagesId: string - MasterStatus: MODEL_NEW_DEFAULT_MASTER - masterStatusId: string + MasterStatus: MODEL_NEW_DEFAULT_MASTER; + masterStatusId: string; + imageId: string; } diff --git a/src/app_modules/job/non_user_view/view.tsx b/src/app_modules/job/non_user_view/view.tsx index e98a6a23..82d59658 100644 --- a/src/app_modules/job/non_user_view/view.tsx +++ b/src/app_modules/job/non_user_view/view.tsx @@ -1,16 +1,28 @@ "use client"; -import { Card, Center, Image, Overlay, Stack, Text, Title } from "@mantine/core"; +import { + Card, + Center, + Image, + Overlay, + Stack, + Text, + Title, +} from "@mantine/core"; import ComponentJob_DetailData from "../component/detail/detail_data"; import { RouterJob } from "@/app/lib/router_hipmi/router_job"; import { data } from "autoprefixer"; import { MODEL_JOB } from "../model/interface"; -import { AccentColor, MainColor } from "@/app_modules/_global/color/color_pallet"; +import { + AccentColor, + MainColor, +} from "@/app_modules/_global/color/color_pallet"; +import { APIs } from "@/app/lib"; export default function Job_NonUserView({ data }: { data: MODEL_JOB }) { return ( <> -
+
- {data.imagesId ? ( + {data.imageId ? ( ) : ( diff --git a/src/app_modules/notifikasi/fun/create/create_notif_to_admin.tsx b/src/app_modules/notifikasi/fun/create/create_notif_to_admin.ts similarity index 100% rename from src/app_modules/notifikasi/fun/create/create_notif_to_admin.tsx rename to src/app_modules/notifikasi/fun/create/create_notif_to_admin.ts diff --git a/src/app_modules/notifikasi/fun/create/create_notif_to_user.tsx b/src/app_modules/notifikasi/fun/create/create_notif_to_user.ts similarity index 100% rename from src/app_modules/notifikasi/fun/create/create_notif_to_user.tsx rename to src/app_modules/notifikasi/fun/create/create_notif_to_user.ts diff --git a/src/app_modules/notifikasi/fun/index.ts b/src/app_modules/notifikasi/fun/index.ts new file mode 100644 index 00000000..a8995e3c --- /dev/null +++ b/src/app_modules/notifikasi/fun/index.ts @@ -0,0 +1,9 @@ +import notifikasiToAdmin_funCreate from "./create/create_notif_to_admin"; +import notifikasiToUser_funCreate from "./create/create_notif_to_user"; +import { notifikasiToUser_CreateGroupCollaboration } from "./create/create_notif_to_user_collaboration"; +import { notifikasiToUser_CreateKabarDonasi } from "./create/create_notif_to_user_kabar_donasi"; + +export { notifikasiToAdmin_funCreate }; +export { notifikasiToUser_CreateGroupCollaboration }; +export { notifikasiToUser_CreateKabarDonasi }; +export { notifikasiToUser_funCreate }; diff --git a/src/app_modules/notifikasi/ui/ui_notifiaksi.tsx b/src/app_modules/notifikasi/ui/ui_notifiaksi.tsx index 1083ecb7..8a6c84ba 100644 --- a/src/app_modules/notifikasi/ui/ui_notifiaksi.tsx +++ b/src/app_modules/notifikasi/ui/ui_notifiaksi.tsx @@ -21,17 +21,15 @@ import { gs_vote_status, } from "@/app_modules/vote/global_state"; import { Box, Button, Center, Flex, Stack } from "@mantine/core"; +import { useShallowEffect } from "@mantine/hooks"; import { useAtom } from "jotai"; -import _, { find } from "lodash"; +import _ from "lodash"; import { ScrollOnly } from "next-scroll-loader"; import { useState } from "react"; -import { ComponentNotifikasi_CardSkeleton } from "../component"; import { ComponentNotifiaksi_CardView } from "../component/card_view"; import notifikasi_getByUserId from "../fun/get/get_notifiaksi_by_id"; -import { MODEL_NOTIFIKASI } from "../model/interface"; -import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global/notifikasi_gagal"; import { gs_notifikasi_kategori_app } from "../lib"; -import { useShallowEffect } from "@mantine/hooks"; +import { MODEL_NOTIFIKASI } from "../model/interface"; export function Notifikasi_UiView({ listNotifikasi, diff --git a/src/app_modules/zCoba/ui_coba_upload_file.tsx b/src/app_modules/zCoba/ui_coba_upload_file.tsx new file mode 100644 index 00000000..7877bef7 --- /dev/null +++ b/src/app_modules/zCoba/ui_coba_upload_file.tsx @@ -0,0 +1,219 @@ +import { TokenStorage } from "@/app/lib/token"; +import { + Box, + Button, + Card, + Center, + FileButton, + Image, + Paper, + Stack, + Text, +} from "@mantine/core"; +import { useShallowEffect } from "@mantine/hooks"; +import { IconCamera, IconUpload } from "@tabler/icons-react"; +import { useState } from "react"; +import { AccentColor, MainColor } from "../_global/color"; +import { + ComponentGlobal_NotifikasiBerhasil, + ComponentGlobal_NotifikasiPeringatan, +} from "../_global/notif_global"; +import { DIRECTORY_ID } from "@/app/lib"; +import { funGlobal_UploadToStorage } from "../_global/fun"; + +export default function Coba_UploadFile() { + const [data, setData] = useState(); + const [file, setFile] = useState(null); + const [images, setImages] = useState(); + + async function loadListDir(setData: any) { + const rootDirEndPoint = await fetch( + "https://wibu-storage.wibudev.com/api/dir/root/list", + { + method: "GET", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${TokenStorage.value}`, + }, + } + ); + const dataDir = await rootDirEndPoint.json(); + // console.log(dataDir); + + const dirHipmiEndPoint = await fetch( + `https://wibu-storage.wibudev.com/api/dir/${dataDir.dirs[0].id}/list`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${TokenStorage.value}`, + }, + } + ); + + const hipmiDir = await dirHipmiEndPoint.json(); + // console.log(hipmiDir.dirs[0]); + setData(hipmiDir.dirs[0]); + } + + // async function CcekToken() { + // const rootDirEndPoint = await fetch( + // "https://wibu-storage.wibudev.com/api/dir/root/list", + // { + // method: "GET", + // headers: { + // "Content-Type": "application/json", + // Authorization: `Bearer ${process.env.WS_APIKEY}`, + // }, + // } + // ); + // const dataDir = await rootDirEndPoint.json(); + // console.log(dataDir); + // } + + useShallowEffect(() => { + loadListDir(setData); + // CekToken() + }, [setData]); + + const [imagesId, setImagesId] = useState(""); + return ( + + + + {images ? ( + + ) : ( + + + + + Upload Gambar + + + + )} + + { + try { + const buffer = URL.createObjectURL( + new Blob([new Uint8Array(await files.arrayBuffer())]) + ); + setImages(buffer); + setFile(files); + } catch (error) { + console.log(error); + } + }} + accept="image/png,image/jpeg" + > + {(props) => ( + + )} + + + +
+ +
+
+ {/* +
{JSON.stringify(data, null, 2)}
+
*/} + + {/* + Foto + */} +
+ ); +} + +async function coba_ButtonFileUpload({ + file, + dirId, + onDone, +}: { + file: File; + dirId: string; + onDone: () => void; +}) { + if (!file) return ComponentGlobal_NotifikasiPeringatan("Tidak ada file"); + + const allowedMimeTypes = [ + "image/png", + "image/jpeg", + "image/gif", + "text/csv", + "application/pdf", + "application/msword", + "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + "application/vnd.ms-excel", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + "text/plain", + ]; + + if (!allowedMimeTypes.includes(file.type)) + return ComponentGlobal_NotifikasiPeringatan("File tidak sesuai"); + + if (file.size > 100 * 1024 * 1024) + return ComponentGlobal_NotifikasiPeringatan("File terlalu besar"); + + const formData = new FormData(); + formData.append("file", file); + formData.append("dirId", dirId); + + try { + const res = await fetch("https://wibu-storage.wibudev.com/api/upload", { + method: "POST", + body: formData, + headers: { + Authorization: `Bearer ${TokenStorage.value}`, + }, + }); + + const dataRes = await res.json(); + + if (res.ok) { + console.log("File Sukses Di Upload"); + console.log(dataRes); + } else { + const errorText = await res.text(); + console.log("jika error", errorText); + } + } catch (error) { + console.error("Upload error:", error); + } finally { + onDone(); + } +}