diff --git a/src/app/api/admin/investasi/[id]/transaksi/route.ts b/src/app/api/admin/investasi/[id]/transaksi/route.ts index 518d59c3..8b84b856 100644 --- a/src/app/api/admin/investasi/[id]/transaksi/route.ts +++ b/src/app/api/admin/investasi/[id]/transaksi/route.ts @@ -12,8 +12,6 @@ export async function GET(request: Request, { params }: { params: { id: string } const takeData = 10; const skipData = Number(page) * takeData - takeData; - console.log("status >", status) - if (!page) { fixData = await prisma.investasi_Invoice.findMany({ diff --git a/src/app/api/job/[id]/route.ts b/src/app/api/job/[id]/route.ts new file mode 100644 index 00000000..9a4abc30 --- /dev/null +++ b/src/app/api/job/[id]/route.ts @@ -0,0 +1,9 @@ +import { NextResponse } from "next/server"; + +export { GET }; + +async function GET(request: Request) { + return NextResponse.json({ + success: true, + }); +} diff --git a/src/app/api/job/arsip/route.ts b/src/app/api/job/arsip/route.ts new file mode 100644 index 00000000..a274d525 --- /dev/null +++ b/src/app/api/job/arsip/route.ts @@ -0,0 +1,95 @@ +import backendLogger from "@/util/backendLogger"; +import { NextResponse } from "next/server"; +import { prisma } from "@/lib"; +import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; + +export { GET }; + +async function GET(request: Request) { + try { + let fixData; + const { searchParams } = new URL(request.url); + const page = searchParams.get("page"); + const dataTake = 10 + const dataSkip = Number(page) * dataTake - dataTake; + + const userLoginId = await funGetUserIdByToken(); + if (!userLoginId) { + return NextResponse.json( + { + success: false, + message: "Gagal mendapatkan data", + reason: "Unauthorized", + }, + { + status: 401, + } + ); + } + + if (!page) { + fixData = await prisma.job.findMany({ + orderBy: { + updatedAt: "desc", + }, + where: { + masterStatusId: "1", + isActive: true, + isArsip: true, + authorId: userLoginId, + }, + select: { + id: true, + title: true, + isArsip: true, + Author: { + select: { + id: true, + username: true, + Profile: true, + }, + }, + }, + }); + } else { + fixData = await prisma.job.findMany({ + take: dataTake, + skip: dataSkip, + orderBy: { + updatedAt: "desc", + }, + where: { + masterStatusId: "1", + isActive: true, + isArsip: true, + authorId: userLoginId, + }, + select: { + id: true, + title: true, + isArsip: true, + Author: { + select: { + id: true, + username: true, + Profile: true, + }, + }, + }, + }); + } + + return NextResponse.json({ + success: true, + message: "Berhasil mendapatkan data", + data: fixData, + }); + } catch (error) { + backendLogger.error("Error get data job"); + return NextResponse.json({ + success: false, + message: "Error get data job", + error: (error as Error).message, + }); + } +} diff --git a/src/app/api/job/gambar/[id]/route.ts b/src/app/api/job/gambar/[id]/route.ts deleted file mode 100644 index 98ab0697..00000000 --- a/src/app/api/job/gambar/[id]/route.ts +++ /dev/null @@ -1,36 +0,0 @@ -import prisma from "@/lib/prisma"; -import fs from "fs"; -import { NextRequest, NextResponse } from "next/server"; -import path from "path"; -const root = process.cwd(); - -export async function GET( - req: NextRequest, - { params }: { params: { id: string } } -) { - const get = await prisma.images.findUnique({ - where: { - id: params.id, - }, - select: { - url: true, - }, - }); - - if (!fs.existsSync(path.join(root, `public/job/${get?.url}`))) { - const notFile = fs.readFileSync( - path.join(root, "public/aset/global/no-file.png") - ); - return new NextResponse(notFile, { - headers: { - "Content-Type": "image/png", - }, - }); - } - const file = fs.readFileSync(path.join(root, `public/job/${get?.url}`)); - return new NextResponse(file, { - headers: { - "Content-Type": "image/png", - }, - }); -} diff --git a/src/app/api/job/get-all/route.ts b/src/app/api/job/route.ts similarity index 65% rename from src/app/api/job/get-all/route.ts rename to src/app/api/job/route.ts index 77a8f498..c7f15969 100644 --- a/src/app/api/job/get-all/route.ts +++ b/src/app/api/job/route.ts @@ -1,19 +1,20 @@ -import { prisma } from "@/lib"; +import backendLogger from "@/util/backendLogger"; import { NextResponse } from "next/server"; -export const dynamic = "force-dynamic"; +import { prisma } from "@/lib"; -export async function GET(request: Request) { +export { GET }; + +async function GET(request: Request) { try { + let fixData; const { searchParams } = new URL(request.url); const search = searchParams.get("search"); const page = searchParams.get("page"); - const dataTake = 10; + const dataTake = 5; const dataSkip = Number(page) * dataTake - dataTake; - if (search != "") { - const data = await prisma.job.findMany({ - take: dataTake, - skip: dataSkip, + if (!page) { + fixData = await prisma.job.findMany({ orderBy: { updatedAt: "desc", }, @@ -23,7 +24,7 @@ export async function GET(request: Request) { isArsip: false, title: { mode: "insensitive", - contains: search as string, + contains: search ? search : "", }, }, select: { @@ -38,17 +39,8 @@ export async function GET(request: Request) { }, }, }); - - return NextResponse.json( - { - success: true, - message: "Berhasil ambil data", - data: data, - }, - { status: 200 } - ); } else { - const data = await prisma.job.findMany({ + fixData = await prisma.job.findMany({ take: dataTake, skip: dataSkip, orderBy: { @@ -60,6 +52,7 @@ export async function GET(request: Request) { isArsip: false, title: { mode: "insensitive", + contains: search ? search : "", }, }, select: { @@ -74,21 +67,19 @@ export async function GET(request: Request) { }, }, }); - - return NextResponse.json( - { - success: true, - message: "Berhasil ambil data", - data: data, - }, - { status: 200 } - ); } + + return NextResponse.json({ + success: true, + message: "Berhasil mendapatkan data", + data: fixData, + }); } catch (error) { - console.error(error); + backendLogger.error("Error get data job"); return NextResponse.json({ success: false, - message: "Gagal ambil data", + message: "Error get data job", + error: (error as Error).message, }); } } diff --git a/src/app/dev/job/main/arsip/page.tsx b/src/app/dev/job/main/arsip/page.tsx index f46dce88..d4421358 100644 --- a/src/app/dev/job/main/arsip/page.tsx +++ b/src/app/dev/job/main/arsip/page.tsx @@ -2,11 +2,10 @@ import { Job_Arsip } from "@/app_modules/job"; import { job_getAllArsipById } from "@/app_modules/job/fun/get/get_all_arsip"; export default async function Page() { - const dataJob = await job_getAllArsipById({ page: 1 }); return ( <> - + ); } diff --git a/src/app/dev/job/main/status/[id]/page.tsx b/src/app/dev/job/main/status/[id]/page.tsx index dc2c7552..7e45000b 100644 --- a/src/app/dev/job/main/status/[id]/page.tsx +++ b/src/app/dev/job/main/status/[id]/page.tsx @@ -1,13 +1,9 @@ import { Job_Status } from "@/app_modules/job"; -import { job_funGetAllByStatusId } from "@/app_modules/job/fun"; -import { job_funGetMasterStatus } from "@/app_modules/job/fun/get/get_master_status"; export default async function Page() { - - return ( <> - + ); } diff --git a/src/app_modules/job/component/api_fetch_job.ts b/src/app_modules/job/component/api_fetch_job.ts index 5002fd5e..f12a79ce 100644 --- a/src/app_modules/job/component/api_fetch_job.ts +++ b/src/app_modules/job/component/api_fetch_job.ts @@ -1,4 +1,4 @@ -export { apiGetJobByStatus }; +export { apiGetJobByStatus, apiGetJob, apiGetJobArsip }; const apiGetJobByStatus = async ({ status, @@ -15,10 +15,8 @@ const apiGetJobByStatus = async ({ return null; } - console.log("status > ", status); - // Send PUT request to update portfolio logo - const isPage = `?page=${page}` + const isPage = `?page=${page}`; const response = await fetch(`/api/job/status/${status}${isPage}`, { method: "GET", headers: { @@ -45,3 +43,84 @@ const apiGetJobByStatus = async ({ throw error; // Re-throw the error to handle it in the calling function } }; + +const apiGetJob = async ({ page, search }: { page: string, search?: string }) => { + try { + // Fetch token from cookie + const { token } = await fetch("/api/get-cookie").then((res) => res.json()); + if (!token) { + console.error("No token found"); + return null; + } + + // Send PUT request to update portfolio logo + const isPage = `?page=${page}`; + const isSearch = search ? `&search=${search}` : ""; + const response = await fetch(`/api/job${isPage}${isSearch}`, { + method: "GET", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + Authorization: `Bearer ${token}`, + }, + }); + + // Check if the response is OK + if (!response.ok) { + const errorData = await response.json().catch(() => null); + console.error( + "Error updating portfolio logo:", + errorData?.message || "Unknown error" + ); + + return null; + } + + return await response.json(); + } catch (error) { + console.error("Error updating portfolio logo:", error); + throw error; // Re-throw the error to handle it in the calling function + } +}; + +const apiGetJobArsip = async ({ + page, +}: { + page: string; +}) => { + try { + // Fetch token from cookie + const { token } = await fetch("/api/get-cookie").then((res) => res.json()); + if (!token) { + console.error("No token found"); + return null; + } + + // Send PUT request to update portfolio logo + const isPage = `?page=${page}`; + const response = await fetch(`/api/job/arsip${isPage}`, { + method: "GET", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + Authorization: `Bearer ${token}`, + }, + }); + + // Check if the response is OK + if (!response.ok) { + const errorData = await response.json().catch(() => null); + console.error( + "Error updating portfolio logo:", + errorData?.message || "Unknown error" + ); + + return null; + } + + return await response.json(); + } catch (error) { + console.error("Error updating portfolio logo:", error); + throw error; // Re-throw the error to handle it in the calling function + } +}; diff --git a/src/app_modules/job/component/skeleton/comp_skeleton_beranda.tsx b/src/app_modules/job/component/skeleton/comp_skeleton_beranda.tsx index 7e773ed6..fb0561f2 100644 --- a/src/app_modules/job/component/skeleton/comp_skeleton_beranda.tsx +++ b/src/app_modules/job/component/skeleton/comp_skeleton_beranda.tsx @@ -1,20 +1,21 @@ import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component"; +import CustomSkeleton from "@/app_modules/components/CustomSkeleton"; import { Box, Center, Group, Skeleton, Stack } from "@mantine/core"; export default function Job_ComponentSkeletonBeranda() { return ( <> - {Array.from(new Array(10)).map((e, i) => ( + {Array.from(new Array(3)).map((e, i) => ( - - + +
- +
diff --git a/src/app_modules/job/main/arsip/view_arsip.tsx b/src/app_modules/job/main/arsip/view_arsip.tsx index e7a958f6..39c48bf9 100644 --- a/src/app_modules/job/main/arsip/view_arsip.tsx +++ b/src/app_modules/job/main/arsip/view_arsip.tsx @@ -1,11 +1,109 @@ -import { Box } from "@mantine/core"; +"use client"; + +import { Box, Center, Stack } from "@mantine/core"; import { MODEL_JOB } from "../../model/interface"; import { Job_UI_Arsip } from "./ui_arsip"; +import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data"; +import { RouterJob } from "@/lib/router_hipmi/router_job"; +import _ from "lodash"; +import { ScrollOnly } from "next-scroll-loader"; +import { useState } from "react"; +import ComponentJob_CardStatus from "../../component/card/card_view"; +import { job_getAllArsipById } from "../../fun/get/get_all_arsip"; +import ComponentGlobal_Loader from "@/app_modules/_global/component/loader"; +import { clientLogger } from "@/util/clientLogger"; +import { useShallowEffect } from "@mantine/hooks"; +import { apiGetJob, apiGetJobArsip } from "../../component/api_fetch_job"; +import { Job_ComponentSkeletonBeranda } from "../../component"; +import CustomSkeleton from "@/app_modules/components/CustomSkeleton"; + +export default function Job_ViewArsip() { + const [data, setData] = useState([]); + const [activePage, setActivePage] = useState(1); + const [hasMore, setHasMore] = useState(true); + const [isLoading, setIsLoading] = useState(false); + + useShallowEffect(() => { + onLoadNewData(); + }, []); + + async function onLoadNewData() { + try { + setIsLoading(true); + const response = await apiGetJobArsip({ + page: `${activePage}`, + }); + + if (response.success) { + setData(response.data); + setActivePage(1); + setHasMore(response.data.length > 0); + } else { + setData([]); + setHasMore(false); + } + } catch (error) { + clientLogger.error("Error get job", error); + setData([]); + setHasMore(false); + } finally { + setIsLoading(false); + } + } + + const handleMoreData = async () => { + if (!hasMore || isLoading) return null; + + try { + const nextPage = activePage + 1; + + const response = await apiGetJob({ + page: `${nextPage}`, + }); + + if (response?.data && response.data.length > 0) { + setActivePage(nextPage); + setHasMore(response.data.length > 0); + return response.data; + } else { + setHasMore(false); + return null; + } + } catch (error) { + clientLogger.error("Error get job", error); + setHasMore(false); + return null; + } + }; -export default function Job_ViewArsip({ dataJob }: { dataJob: MODEL_JOB[] }) { return ( <> - ; + {!data?.length && isLoading ? ( + + + + + ) : _.isEmpty(data) ? ( + + ) : ( + // --- Main component --- // + + } + data={data} + setData={setData} + moreData={handleMoreData} + > + {(item) => ( + + )} + + + )} ); } diff --git a/src/app_modules/job/main/beranda/view_beranda.tsx b/src/app_modules/job/main/beranda/view_beranda.tsx index b2f7bee3..915f0c21 100644 --- a/src/app_modules/job/main/beranda/view_beranda.tsx +++ b/src/app_modules/job/main/beranda/view_beranda.tsx @@ -1,6 +1,5 @@ "use client"; -import { API_RouteJob } from "@/lib/api_user_router/route_api_job"; import { gs_jobTiggerBeranda } from "@/lib/global_state"; import { RouterJob } from "@/lib/router_hipmi/router_job"; import ComponentGlobal_CreateButton from "@/app_modules/_global/component/button_create"; @@ -18,11 +17,15 @@ import { } from "../../component"; import ComponentJob_BerandaCardView from "../../component/beranda/card_view"; import { MODEL_JOB } from "../../model/interface"; +import { apiGetJob } from "../../component/api_fetch_job"; +import { clientLogger } from "@/util/clientLogger"; export default function Job_ViewBeranda() { - const [data, setData] = useState(null); + const [data, setData] = useState([]); const [activePage, setActivePage] = useState(1); const [isSearch, setIsSearch] = useState(""); + const [hasMore, setHasMore] = useState(true); + const [isLoading, setIsLoading] = useState(false); // Notifikasi const [isShowUpdate, setIsShowUpdate] = useState(false); @@ -38,26 +41,65 @@ export default function Job_ViewBeranda() { setIsTriggerJob(false); setIsShowUpdate(false); onLoadNewData(); - }, []); + }, [isSearch]); async function onSearch(text: string) { setIsSearch(text); - const loadData = await fetch( - API_RouteJob.get_all({ page: activePage, search: text }) - ); - const res = await loadData.json(); - - setData(res.data as any); setActivePage(1); + setHasMore(true); } async function onLoadNewData() { - const loadData = await fetch(API_RouteJob.get_all({ page: activePage })); - const res = await loadData.json(); - // console.log(res.data); - setData(res.data); + try { + setIsLoading(true); + const response = await apiGetJob({ + page: `${activePage}`, + search: isSearch, + }); + + if (response.success) { + setData(response.data); + setActivePage(1); + setHasMore(response.data.length > 0); + } else { + setData([]); + setHasMore(false); + } + } catch (error) { + clientLogger.error("Error get job", error); + setData([]); + setHasMore(false); + } finally { + setIsLoading(false); + } } + const handleMoreData = async () => { + if (!hasMore || isLoading) return null; + + try { + const nextPage = activePage + 1; + + const response = await apiGetJob({ + page: `${nextPage}`, + search: isSearch, + }); + + if (response?.data && response.data.length > 0) { + setActivePage(nextPage); + setHasMore(response.data.length > 0); + return response.data; + } else { + setHasMore(false); + return null; + } + } catch (error) { + clientLogger.error("Error get job", error); + setHasMore(false); + return null; + } + }; + return ( <> @@ -89,7 +131,7 @@ export default function Job_ViewBeranda() { }} /> - {_.isNull(data) ? ( + {!data?.length && isLoading ? ( ) : _.isEmpty(data) ? ( @@ -104,16 +146,7 @@ export default function Job_ViewBeranda() { )} data={data} setData={setData as any} - moreData={async () => { - const loadData = await fetch( - API_RouteJob.get_all({ page: activePage, search: isSearch }) - ); - - const res = await loadData.json(); - setActivePage((val) => val + 1); - - return res.data; - }} + moreData={handleMoreData} > {(item) => } diff --git a/src/app_modules/job/main/status/view_status.tsx b/src/app_modules/job/main/status/view_status.tsx index 1e5c7cd4..57133f60 100644 --- a/src/app_modules/job/main/status/view_status.tsx +++ b/src/app_modules/job/main/status/view_status.tsx @@ -31,7 +31,6 @@ export default function Job_NewViewStatus() { page: `${activePage}`, }); if (response.success) { - console.log(response.data); setData(response.data); } } catch (error) { diff --git a/src/lib/router_hipmi/router_job.ts b/src/lib/router_hipmi/router_job.ts index 29cd8585..5863448a 100644 --- a/src/lib/router_hipmi/router_job.ts +++ b/src/lib/router_hipmi/router_job.ts @@ -1,6 +1,4 @@ export const RouterJob = { - //api - api_gambar: "/api/job/gambar/", //spalsh spalsh: "/dev/job/splash", diff --git a/src/lib/routes.ts b/src/lib/routes.ts index c339a1f9..ed0e0fa4 100644 --- a/src/lib/routes.ts +++ b/src/lib/routes.ts @@ -414,7 +414,6 @@ export const apies = { `/api/portofolio/logo/${id}`, "/api/map/pin/[id]": ({ id }: { id: string }) => `/api/map/pin/${id}`, "/api/map/foto/[id]": ({ id }: { id: string }) => `/api/map/foto/${id}`, - "/api/job/gambar/[id]": ({ id }: { id: string }) => `/api/job/gambar/${id}`, "/api/investasi/prospektus/[id]": ({ id }: { id: string }) => `/api/investasi/prospektus/${id}`, "/api/investasi/midtrans/[id]": ({ id }: { id: string }) => diff --git a/src/middleware.ts b/src/middleware.ts index 3b172f51..a8abf4e0 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -27,7 +27,6 @@ const middlewareConfig: MiddlewareConfig = { "/api/collaboration/*", "/api/notifikasi/*", "/api/logs/*", - "/api/job/*", "/api/auth/*", "/api/origin-url", "/api/event/*",