Merge pull request #227 from bipproduction/fix/bug/middleware
fix ( middleware )
This commit is contained in:
15
src/app/api/get-cookie/route.ts
Normal file
15
src/app/api/get-cookie/route.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { cookies } from 'next/headers'
|
||||||
|
import { NextResponse } from 'next/server';
|
||||||
|
|
||||||
|
export const dynamic = "force-dynamic";
|
||||||
|
export async function GET(request: Request) {
|
||||||
|
try {
|
||||||
|
const cookiesKey = process.env.NEXT_PUBLIC_BASE_SESSION_KEY!
|
||||||
|
const cookieStore = cookies();
|
||||||
|
const hipmiKey = cookieStore.get(cookiesKey)?.value || '';
|
||||||
|
return NextResponse.json({ token: hipmiKey });
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return NextResponse.json({ error }, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,8 @@ import { NextResponse } from "next/server";
|
|||||||
|
|
||||||
export async function DELETE(req: Request) {
|
export async function DELETE(req: Request) {
|
||||||
const data = await req.json();
|
const data = await req.json();
|
||||||
|
|
||||||
|
console.log("data request =>", data);
|
||||||
const id = data.fileId;
|
const id = data.fileId;
|
||||||
const dirId = data.dirId;
|
const dirId = data.dirId;
|
||||||
|
|
||||||
@@ -25,9 +27,7 @@ export async function DELETE(req: Request) {
|
|||||||
backendLogger.info("Server status code: " + res.status);
|
backendLogger.info("Server status code: " + res.status);
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
backendLogger.info(
|
backendLogger.info(`Success delete ${keyOfDirectory}`);
|
||||||
`Success delete ${keyOfDirectory}`
|
|
||||||
);
|
|
||||||
return NextResponse.json({ success: true });
|
return NextResponse.json({ success: true });
|
||||||
} else {
|
} else {
|
||||||
const errorText = await res.json();
|
const errorText = await res.json();
|
||||||
|
|||||||
@@ -1,173 +1,234 @@
|
|||||||
import { prisma } from "@/app/lib";
|
import { DIRECTORY_ID, prisma } from "@/app/lib";
|
||||||
import { NextResponse } from "next/server";
|
import { NextResponse } from "next/server";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
|
import { funGlobal_DeleteFileById } from "@/app_modules/_global/fun";
|
||||||
|
import { apiDeleteImageById } from "@/app_modules/_global/lib/api_image";
|
||||||
|
import backendLogger from "@/util/backendLogger";
|
||||||
export const dynamic = "force-dynamic";
|
export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// GET ONE DATA PORTOFOLIO BY ID PORTOFOLIO
|
// GET ONE DATA PORTOFOLIO BY ID PORTOFOLIO
|
||||||
export async function GET(request: Request, context: { params: { id: string } }) {
|
export async function GET(
|
||||||
try {
|
request: Request,
|
||||||
let dataFix
|
context: { params: { id: string } }
|
||||||
const { id } = context.params;
|
) {
|
||||||
const { searchParams } = new URL(request.url);
|
try {
|
||||||
const kategori = searchParams.get('cat');
|
let dataFix;
|
||||||
|
const { id } = context.params;
|
||||||
|
const { searchParams } = new URL(request.url);
|
||||||
|
const kategori = searchParams.get("cat");
|
||||||
|
|
||||||
if (kategori == "bisnis") {
|
if (kategori == "bisnis") {
|
||||||
const data = await prisma.portofolio.findUnique({
|
const data = await prisma.portofolio.findUnique({
|
||||||
where: {
|
where: {
|
||||||
id: id,
|
id: id,
|
||||||
},
|
},
|
||||||
|
select: {
|
||||||
|
id_Portofolio: true,
|
||||||
|
namaBisnis: true,
|
||||||
|
alamatKantor: true,
|
||||||
|
tlpn: true,
|
||||||
|
deskripsi: true,
|
||||||
|
logoId: true,
|
||||||
|
MasterBidangBisnis: {
|
||||||
select: {
|
select: {
|
||||||
id_Portofolio: true,
|
name: true,
|
||||||
namaBisnis: true,
|
|
||||||
alamatKantor: true,
|
|
||||||
tlpn: true,
|
|
||||||
deskripsi: true,
|
|
||||||
logoId: true,
|
|
||||||
MasterBidangBisnis: {
|
|
||||||
select: {
|
|
||||||
name: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Profile: {
|
|
||||||
select: {
|
|
||||||
userId: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
dataFix = {
|
|
||||||
id_Portofolio: data?.id_Portofolio,
|
|
||||||
namaBisnis: data?.namaBisnis,
|
|
||||||
alamatKantor: data?.alamatKantor,
|
|
||||||
tlpn: data?.tlpn,
|
|
||||||
deskripsi: data?.deskripsi,
|
|
||||||
logoId: data?.logoId,
|
|
||||||
bidangBisnis: data?.MasterBidangBisnis?.name,
|
|
||||||
authorId: data?.Profile?.userId
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (kategori == "lokasi") {
|
|
||||||
const data = await prisma.portofolio.findUnique({
|
|
||||||
where: {
|
|
||||||
id: id,
|
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
Profile: {
|
||||||
select: {
|
select: {
|
||||||
logoId: true,
|
userId: true,
|
||||||
BusinessMaps: {
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
namePin: true,
|
|
||||||
latitude: true,
|
|
||||||
longitude: true,
|
|
||||||
imageId: true,
|
|
||||||
pinId: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
dataFix = {
|
|
||||||
mapId: data?.BusinessMaps?.id,
|
|
||||||
logoId: data?.logoId,
|
|
||||||
namePin: data?.BusinessMaps?.namePin,
|
|
||||||
latitude: data?.BusinessMaps?.latitude,
|
|
||||||
longitude: data?.BusinessMaps?.longitude,
|
|
||||||
imageId: data?.BusinessMaps?.imageId,
|
|
||||||
pinId: data?.BusinessMaps?.pinId
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (kategori == "sosmed") {
|
|
||||||
const data = await prisma.portofolio.findUnique({
|
|
||||||
where: {
|
|
||||||
id: id,
|
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
dataFix = {
|
||||||
|
id_Portofolio: data?.id_Portofolio,
|
||||||
|
namaBisnis: data?.namaBisnis,
|
||||||
|
alamatKantor: data?.alamatKantor,
|
||||||
|
tlpn: data?.tlpn,
|
||||||
|
deskripsi: data?.deskripsi,
|
||||||
|
logoId: data?.logoId,
|
||||||
|
bidangBisnis: data?.MasterBidangBisnis?.name,
|
||||||
|
authorId: data?.Profile?.userId,
|
||||||
|
};
|
||||||
|
} else if (kategori == "lokasi") {
|
||||||
|
const data = await prisma.portofolio.findUnique({
|
||||||
|
where: {
|
||||||
|
id: id,
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
logoId: true,
|
||||||
|
BusinessMaps: {
|
||||||
select: {
|
select: {
|
||||||
Portofolio_MediaSosial: {
|
id: true,
|
||||||
select: {
|
namePin: true,
|
||||||
facebook: true,
|
latitude: true,
|
||||||
twitter: true,
|
longitude: true,
|
||||||
instagram: true,
|
imageId: true,
|
||||||
tiktok: true,
|
pinId: true,
|
||||||
youtube: true
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
});
|
||||||
});
|
|
||||||
|
|
||||||
dataFix = {
|
dataFix = {
|
||||||
facebook: data?.Portofolio_MediaSosial?.facebook,
|
mapId: data?.BusinessMaps?.id,
|
||||||
twitter: data?.Portofolio_MediaSosial?.twitter,
|
logoId: data?.logoId,
|
||||||
instagram: data?.Portofolio_MediaSosial?.instagram,
|
namePin: data?.BusinessMaps?.namePin,
|
||||||
tiktok: data?.Portofolio_MediaSosial?.tiktok,
|
latitude: data?.BusinessMaps?.latitude,
|
||||||
youtube: data?.Portofolio_MediaSosial?.youtube
|
longitude: data?.BusinessMaps?.longitude,
|
||||||
}
|
imageId: data?.BusinessMaps?.imageId,
|
||||||
}
|
pinId: data?.BusinessMaps?.pinId,
|
||||||
|
};
|
||||||
|
} else if (kategori == "sosmed") {
|
||||||
|
const data = await prisma.portofolio.findUnique({
|
||||||
|
where: {
|
||||||
|
id: id,
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
Portofolio_MediaSosial: {
|
||||||
|
select: {
|
||||||
|
facebook: true,
|
||||||
|
twitter: true,
|
||||||
|
instagram: true,
|
||||||
|
tiktok: true,
|
||||||
|
youtube: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data: dataFix }, { status: 200 });
|
dataFix = {
|
||||||
|
facebook: data?.Portofolio_MediaSosial?.facebook,
|
||||||
|
twitter: data?.Portofolio_MediaSosial?.twitter,
|
||||||
|
instagram: data?.Portofolio_MediaSosial?.instagram,
|
||||||
|
tiktok: data?.Portofolio_MediaSosial?.tiktok,
|
||||||
|
youtube: data?.Portofolio_MediaSosial?.youtube,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
} catch (error) {
|
return NextResponse.json(
|
||||||
console.error(error);
|
{ success: true, message: "Berhasil mendapatkan data", data: dataFix },
|
||||||
return NextResponse.json({ success: false, message: "Gagal mendapatkan data, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
|
{ status: 200 }
|
||||||
}
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message: "Gagal mendapatkan data, coba lagi nanti (error: 500)",
|
||||||
|
reason: (error as Error).message,
|
||||||
|
},
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DELETE ONE DATA PORTOFOLIO
|
// DELETE ONE DATA PORTOFOLIO
|
||||||
export async function DELETE(request: Request, context: { params: { id: string } }) {
|
export async function DELETE(
|
||||||
try {
|
request: Request,
|
||||||
const { id } = context.params
|
context: { params: { id: string } }
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const { id } = context.params;
|
||||||
|
|
||||||
const data = await prisma.portofolio.findUnique({
|
const data = await prisma.portofolio.findUnique({
|
||||||
where: {
|
where: {
|
||||||
id: id
|
id: id,
|
||||||
}
|
},
|
||||||
})
|
include: {
|
||||||
|
BusinessMaps: {
|
||||||
|
select: {
|
||||||
|
pinId: true,
|
||||||
|
imageId: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const findLogo = await prisma.images.findFirst({
|
try {
|
||||||
where: {
|
const id = data?.logoId;
|
||||||
id: String(data?.logoId),
|
const deleteLogo = await fetch(
|
||||||
},
|
`https://wibu-storage.wibudev.com/api/files/${id}/delete`,
|
||||||
select: {
|
{
|
||||||
id: true,
|
method: "DELETE",
|
||||||
url: true,
|
headers: {
|
||||||
},
|
Authorization: `Bearer ${process.env.WS_APIKEY}`,
|
||||||
});
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
if (findLogo) {
|
if (deleteLogo.ok) {
|
||||||
fs.unlinkSync(`./public/portofolio/logo/${findLogo.url}`)
|
backendLogger.info(`Success delete logo`);
|
||||||
const deleteLogo = await prisma.images.delete({
|
|
||||||
where: {
|
|
||||||
id: String(findLogo?.id),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data?.BusinessMaps?.pinId != null) {
|
||||||
|
const pinId = data?.BusinessMaps?.pinId;
|
||||||
|
const deletePin = await fetch(
|
||||||
|
`https://wibu-storage.wibudev.com/api/files/${pinId}/delete`,
|
||||||
|
{
|
||||||
|
method: "DELETE",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${process.env.WS_APIKEY}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (deletePin.ok) {
|
||||||
|
backendLogger.info(`Success delete pin`);
|
||||||
|
}
|
||||||
|
|
||||||
const deletePortoMedsos = await prisma.portofolio_MediaSosial.delete({
|
const imageId = data?.BusinessMaps?.imageId;
|
||||||
where: {
|
const deleteImage = await fetch(
|
||||||
portofolioId: id,
|
`https://wibu-storage.wibudev.com/api/files/${imageId}/delete`,
|
||||||
},
|
{
|
||||||
});
|
method: "DELETE",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${process.env.WS_APIKEY}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const deleteMap = await prisma.businessMaps.delete({
|
if (deleteImage.ok) {
|
||||||
where: {
|
backendLogger.info(`Success delete image`);
|
||||||
portofolioId: id
|
}
|
||||||
}
|
}
|
||||||
})
|
} catch (error) {
|
||||||
|
backendLogger.error("Error delete logo", error);
|
||||||
|
}
|
||||||
|
|
||||||
const deletePortofolio = await prisma.portofolio.delete({
|
const deletePortoMedsos = await prisma.portofolio_MediaSosial.delete({
|
||||||
where: {
|
where: {
|
||||||
id: id,
|
portofolioId: id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return NextResponse.json({ success: true, message: "Berhasil menghapus data" }, { status: 200 });
|
const deleteMap = await prisma.businessMaps.delete({
|
||||||
|
where: {
|
||||||
|
portofolioId: id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
} catch (error) {
|
const deletePortofolio = await prisma.portofolio.delete({
|
||||||
console.error(error);
|
where: {
|
||||||
return NextResponse.json({ success: false, message: "Gagal menghapus data, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
|
id: id,
|
||||||
}
|
},
|
||||||
}
|
});
|
||||||
|
|
||||||
|
return NextResponse.json(
|
||||||
|
{ success: true, message: "Berhasil menghapus data" },
|
||||||
|
{ status: 200 }
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message: "Gagal menghapus data, coba lagi nanti (error: 500)",
|
||||||
|
reason: (error as Error).message,
|
||||||
|
},
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
33
src/app/api/user-validate/route.ts
Normal file
33
src/app/api/user-validate/route.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import { decrypt } from "@/app/auth/_lib/decrypt";
|
||||||
|
import { prisma } from "@/app/lib";
|
||||||
|
import { cookies } from 'next/headers'
|
||||||
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
|
|
||||||
|
export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
|
export async function GET(req: NextRequest) {
|
||||||
|
const token = req.headers.get('Authorization')?.split(' ')[1];
|
||||||
|
|
||||||
|
const decripted = await decrypt({
|
||||||
|
token: token!,
|
||||||
|
encodedKey: process.env.NEXT_PUBLIC_BASE_TOKEN_KEY!
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!decripted) {
|
||||||
|
return NextResponse.json({
|
||||||
|
success: false,
|
||||||
|
message: "Unauthorized"
|
||||||
|
}, { status: 401 })
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = await prisma.user.findUnique({
|
||||||
|
where: {
|
||||||
|
id: decripted.id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return NextResponse.json({
|
||||||
|
success: true,
|
||||||
|
message: "Berhasil mendapatkan data",
|
||||||
|
data: user
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -3,6 +3,8 @@ import _ from "lodash";
|
|||||||
import { cookies } from "next/headers";
|
import { cookies } from "next/headers";
|
||||||
import { NextResponse } from "next/server";
|
import { NextResponse } from "next/server";
|
||||||
|
|
||||||
|
export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
export async function GET() {
|
export async function GET() {
|
||||||
// const data = await req.text();
|
// const data = await req.text();
|
||||||
// console.log(data);
|
// console.log(data);
|
||||||
25
src/app/api/user/route.ts
Normal file
25
src/app/api/user/route.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
import { decrypt } from "@/app/auth/_lib/decrypt";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { cookies } from "next/headers";
|
||||||
|
import { NextResponse } from "next/server";
|
||||||
|
|
||||||
|
export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
|
export async function GET() {
|
||||||
|
const c = cookies().get(process.env.NEXT_PUBLIC_BASE_SESSION_KEY!);
|
||||||
|
|
||||||
|
if (!c || !c?.value || _.isEmpty(c?.value) || _.isUndefined(c?.value)) {
|
||||||
|
return NextResponse.json({ status: 401, message: "Unauthorized" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const token = c.value;
|
||||||
|
const dataUser = await decrypt({
|
||||||
|
token: token,
|
||||||
|
encodedKey: process.env.NEXT_PUBLIC_BASE_TOKEN_KEY!,
|
||||||
|
});
|
||||||
|
|
||||||
|
const id = dataUser?.id
|
||||||
|
|
||||||
|
return NextResponse.json({ status: 200, message: "OK", data: id });
|
||||||
|
}
|
||||||
@@ -5,12 +5,7 @@ import { NextResponse } from "next/server";
|
|||||||
export async function GET(req: Request) {
|
export async function GET(req: Request) {
|
||||||
const auth = req.headers.get("Authorization");
|
const auth = req.headers.get("Authorization");
|
||||||
const token = auth?.split(" ")[1];
|
const token = auth?.split(" ")[1];
|
||||||
|
|
||||||
console.log("validasi atas", token);
|
|
||||||
|
|
||||||
if (!token) return NextResponse.json({ success: false }, { status: 401 });
|
if (!token) return NextResponse.json({ success: false }, { status: 401 });
|
||||||
|
|
||||||
console.log("validasi bawah", token);
|
|
||||||
|
|
||||||
return NextResponse.json({ success: true });
|
return NextResponse.json({ success: true });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,8 @@
|
|||||||
import { ViewKatalogNew } from "@/app_modules/katalog";
|
import { ViewKatalogNew } from "@/app_modules/katalog";
|
||||||
|
|
||||||
export default async function Page({ params }: { params: { id: string } }) {
|
export default async function Page() {
|
||||||
// let profileId = params.id;
|
|
||||||
// const userLoginId = await funGetUserIdByToken();
|
|
||||||
|
|
||||||
// const listPorto = await funGetListPortofolio(profileId);
|
|
||||||
// const dataProfile = await Profile_getOneProfileAndUserById(profileId);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* <Katalog_MainView
|
|
||||||
profile={dataProfile as any}
|
|
||||||
listPorto={listPorto as any}
|
|
||||||
userLoginId={userLoginId as any}
|
|
||||||
/> */}
|
|
||||||
|
|
||||||
<ViewKatalogNew />
|
<ViewKatalogNew />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,16 +1,8 @@
|
|||||||
import { ListDetailPortofolioNew } from "@/app_modules/katalog/portofolio";
|
import { ListDetailPortofolioNew } from "@/app_modules/katalog/portofolio";
|
||||||
|
|
||||||
export default async function Page({ params }: { params: { id: string } }) {
|
export default async function Page() {
|
||||||
// const profileId = params.id;
|
|
||||||
// const dataPortofolio = await portofolio_funGetAllDaftarByid({
|
|
||||||
// profileId,
|
|
||||||
// page: 1,
|
|
||||||
// });
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* <Portofolio_ViewListDetail dataPortofolio={dataPortofolio as any} profileId={profileId} /> */}
|
|
||||||
<ListDetailPortofolioNew />
|
<ListDetailPortofolioNew />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,19 +1,16 @@
|
|||||||
|
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
|
||||||
import { Portofolio_UiDetailNew } from "@/app_modules/katalog/portofolio";
|
import { Portofolio_UiDetailNew } from "@/app_modules/katalog/portofolio";
|
||||||
|
|
||||||
const mapboxToken = process.env.MAPBOX_TOKEN!;
|
const mapboxToken = process.env.MAPBOX_TOKEN!;
|
||||||
export default async function Page({ params }: { params: { id: string } }) {
|
export default async function Page() {
|
||||||
// const portofolioId = params.id;
|
const userLoginId = await funGetUserIdByToken()
|
||||||
// const dataPortofolio = await portofolio_getOneById(portofolioId);
|
|
||||||
// const userLoginId = await funGetUserIdByToken();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* <ViewPortofolio
|
<Portofolio_UiDetailNew
|
||||||
dataPorto={dataPortofolio as any}
|
|
||||||
userLoginId={userLoginId as any}
|
|
||||||
mapboxToken={mapboxToken}
|
mapboxToken={mapboxToken}
|
||||||
/> */}
|
userLoginId={userLoginId}
|
||||||
<Portofolio_UiDetailNew mapboxToken={mapboxToken} />
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
"use server";
|
"use server";
|
||||||
|
|
||||||
import { jwtVerify } from "jose";
|
|
||||||
import { cookies } from "next/headers";
|
import { cookies } from "next/headers";
|
||||||
import { decrypt } from "../../../../app/auth/_lib/decrypt";
|
import { decrypt } from "../../../../app/auth/_lib/decrypt";
|
||||||
|
|
||||||
@@ -16,21 +15,3 @@ export async function funGetUserIdByToken() {
|
|||||||
return cekUser?.id;
|
return cekUser?.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
// async function decrypt({
|
|
||||||
// token,
|
|
||||||
// encodedKey,
|
|
||||||
// }: {
|
|
||||||
// token: string;
|
|
||||||
// encodedKey: string;
|
|
||||||
// }): Promise<Record<string, any> | null> {
|
|
||||||
// try {
|
|
||||||
// const enc = new TextEncoder().encode(encodedKey);
|
|
||||||
// const { payload } = await jwtVerify(token, enc, {
|
|
||||||
// algorithms: ["HS256"],
|
|
||||||
// });
|
|
||||||
// return (payload.user as Record<string, any>) || null;
|
|
||||||
// } catch (error) {
|
|
||||||
// console.error("Gagal verifikasi session", error);
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|||||||
16
src/app_modules/_global/lib/api_image.ts
Normal file
16
src/app_modules/_global/lib/api_image.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
export const apiDeleteImageById = async ({
|
||||||
|
fileId,
|
||||||
|
dirId,
|
||||||
|
}: {
|
||||||
|
fileId: string;
|
||||||
|
dirId?: string;
|
||||||
|
}) => {
|
||||||
|
const response = await fetch(`/api/image/delete`, {
|
||||||
|
method: "DELETE",
|
||||||
|
body: JSON.stringify({ fileId, dirId }),
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("delete api =>", await response.json());
|
||||||
|
|
||||||
|
return await response.json().catch(() => null);
|
||||||
|
};
|
||||||
@@ -1,9 +1,39 @@
|
|||||||
|
export const apiGetUserId = async () => {
|
||||||
|
const { token } = await fetch("/api/get-cookie").then((res) => res.json());
|
||||||
|
if (!token) return await token.json().catch(() => null);
|
||||||
|
|
||||||
|
const response = await fetch(`/api/user`, {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "application/json",
|
||||||
|
"Access-Control-Allow-Origin": "*",
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("Ini di pemanggilan API",await response.json());
|
||||||
|
|
||||||
|
if (!response.ok) return null;
|
||||||
|
const data: Record<string, any> = await response.json();
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
export const apiGetCookiesUser = async () => {
|
export const apiGetCookiesUser = async () => {
|
||||||
const response = await fetch(`/api/user/get`);
|
const response = await fetch(`/api/user/get`);
|
||||||
return await response.json().catch(() => null);
|
return await response.json().catch(() => null);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const apiGetACtivationUser = async () => {
|
export const apiGetACtivationUser = async () => {
|
||||||
const response = await fetch(`/api/user/activation`);
|
const { token } = await fetch("/api/get-cookie").then((res) => res.json());
|
||||||
|
if (!token) return await token.json().catch(() => null);
|
||||||
|
|
||||||
|
const response = await fetch(`/api/user/activation`, {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "application/json",
|
||||||
|
"Access-Control-Allow-Origin": "*",
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
return await response.json().catch(() => null);
|
return await response.json().catch(() => null);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import {
|
|||||||
Paper,
|
Paper,
|
||||||
SimpleGrid,
|
SimpleGrid,
|
||||||
Stack,
|
Stack,
|
||||||
Text
|
Text,
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import { useShallowEffect } from "@mantine/hooks";
|
import { useShallowEffect } from "@mantine/hooks";
|
||||||
import { IconUserSearch } from "@tabler/icons-react";
|
import { IconUserSearch } from "@tabler/icons-react";
|
||||||
@@ -22,6 +22,7 @@ import { useRouter } from "next/navigation";
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { apiGetDataHome } from "../fun/get/api_home";
|
import { apiGetDataHome } from "../fun/get/api_home";
|
||||||
import { listMenuHomeBody, menuHomeJob } from "./list_menu_home";
|
import { listMenuHomeBody, menuHomeJob } from "./list_menu_home";
|
||||||
|
import { clientLogger } from "@/util/clientLogger";
|
||||||
|
|
||||||
export default function BodyHome() {
|
export default function BodyHome() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -37,24 +38,31 @@ export default function BodyHome() {
|
|||||||
|
|
||||||
async function cekUserLogin() {
|
async function cekUserLogin() {
|
||||||
try {
|
try {
|
||||||
const response = await apiGetDataHome("?cat=cek_profile");
|
const response = await apiGetDataHome({
|
||||||
if (response.success) {
|
path: "?cat=cek_profile",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response) {
|
||||||
setDataUser(response.data);
|
setDataUser(response.data);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
clientLogger.error("Error get data user", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getHomeJob() {
|
async function getHomeJob() {
|
||||||
try {
|
try {
|
||||||
setLoadingJob(true);
|
setLoadingJob(true);
|
||||||
const response = await apiGetDataHome("?cat=job");
|
|
||||||
if (response.success) {
|
const response = await apiGetDataHome({
|
||||||
|
path: "?cat=job",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response) {
|
||||||
setDataJob(response.data);
|
setDataJob(response.data);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
clientLogger.error("Error get data job", error);
|
||||||
} finally {
|
} finally {
|
||||||
setLoadingJob(false);
|
setLoadingJob(false);
|
||||||
}
|
}
|
||||||
@@ -197,12 +205,22 @@ export default function BodyHome() {
|
|||||||
<Box key={i} mb={"md"}>
|
<Box key={i} mb={"md"}>
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.Col span={6}>
|
<Grid.Col span={6}>
|
||||||
<CustomSkeleton height={10} mt={0} radius="xl" width={"75%"} />
|
<CustomSkeleton
|
||||||
<CustomSkeleton height={10} mt={10} radius="xl" />
|
height={10}
|
||||||
</Grid.Col >
|
mt={0}
|
||||||
|
radius="xl"
|
||||||
|
width={"75%"}
|
||||||
|
/>
|
||||||
|
<CustomSkeleton height={10} mt={10} radius="xl" />
|
||||||
|
</Grid.Col>
|
||||||
<Grid.Col span={6}>
|
<Grid.Col span={6}>
|
||||||
<CustomSkeleton height={10} mt={0} radius="xl" width={"75%"} />
|
<CustomSkeleton
|
||||||
<CustomSkeleton height={10} mt={10} radius="xl" />
|
height={10}
|
||||||
|
mt={0}
|
||||||
|
radius="xl"
|
||||||
|
width={"75%"}
|
||||||
|
/>
|
||||||
|
<CustomSkeleton height={10} mt={10} radius="xl" />
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import { apiGetDataHome } from "../fun/get/api_home";
|
|||||||
import { Home_ComponentAvatarProfile } from "./comp_avatar_profile";
|
import { Home_ComponentAvatarProfile } from "./comp_avatar_profile";
|
||||||
import { listMenuHomeFooter } from "./list_menu_home";
|
import { listMenuHomeFooter } from "./list_menu_home";
|
||||||
import { MainColor } from "@/app_modules/_global/color";
|
import { MainColor } from "@/app_modules/_global/color";
|
||||||
|
import { clientLogger } from "@/util/clientLogger";
|
||||||
|
|
||||||
export default function FooterHome() {
|
export default function FooterHome() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -28,12 +29,14 @@ export default function FooterHome() {
|
|||||||
|
|
||||||
async function cekUserLogin() {
|
async function cekUserLogin() {
|
||||||
try {
|
try {
|
||||||
const response = await apiGetDataHome("?cat=cek_profile");
|
const response = await apiGetDataHome({
|
||||||
if (response.success) {
|
path: "?cat=cek_profile",
|
||||||
|
});
|
||||||
|
if (response) {
|
||||||
setDataUser(response.data);
|
setDataUser(response.data);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
clientLogger.error("Error get data profile",error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,7 +107,10 @@ export default function FooterHome() {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ActionIcon variant={"transparent"}>
|
<ActionIcon
|
||||||
|
|
||||||
|
|
||||||
|
variant={"transparent"}>
|
||||||
{dataUser.profile === undefined || dataUser?.profile === null ? (
|
{dataUser.profile === undefined || dataUser?.profile === null ? (
|
||||||
<IconUserCircle color={MainColor.white} />
|
<IconUserCircle color={MainColor.white} />
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -1,4 +1,17 @@
|
|||||||
export const apiGetDataHome = async (path?: string) => {
|
export const apiGetDataHome = async ({ path }: { path?: string }) => {
|
||||||
const response = await fetch(`/api/new/home${(path) ? path : ''}`)
|
const { token } = await fetch("/api/get-cookie").then((res) => res.json());
|
||||||
return await response.json().catch(() => null)
|
if (!token) return await token.json().catch(() => null);
|
||||||
}
|
|
||||||
|
const response = await fetch(`/api/new/home${path ? path : ""}`, {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "application/json",
|
||||||
|
"Access-Control-Allow-Origin": "*",
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) return null;
|
||||||
|
const data: Record<string, any> = await response.json();
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import { gs_notifikasi_kategori_app } from "../notifikasi/lib";
|
|||||||
import BodyHome from "./component/body_home";
|
import BodyHome from "./component/body_home";
|
||||||
import FooterHome from "./component/footer_home";
|
import FooterHome from "./component/footer_home";
|
||||||
import { apiGetDataHome } from "./fun/get/api_home";
|
import { apiGetDataHome } from "./fun/get/api_home";
|
||||||
|
import { clientLogger } from "@/util/clientLogger";
|
||||||
|
|
||||||
export default function HomeViewNew() {
|
export default function HomeViewNew() {
|
||||||
const [countNtf, setCountNtf] = useAtom(gs_count_ntf);
|
const [countNtf, setCountNtf] = useAtom(gs_count_ntf);
|
||||||
@@ -48,12 +49,14 @@ export default function HomeViewNew() {
|
|||||||
|
|
||||||
async function cekUserLogin() {
|
async function cekUserLogin() {
|
||||||
try {
|
try {
|
||||||
const response = await apiGetDataHome("?cat=cek_profile");
|
const response = await apiGetDataHome({
|
||||||
if (response.success) {
|
path: "?cat=cek_profile",
|
||||||
|
});
|
||||||
|
if (response) {
|
||||||
setDataUser(response.data);
|
setDataUser(response.data);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
clientLogger.error("Error get data home", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export default function LayoutKatalogNew({ children }: { children: any }) {
|
|||||||
setLoading(true)
|
setLoading(true)
|
||||||
const response = await apiGetUserProfile(`?profile=${param.id}`)
|
const response = await apiGetUserProfile(`?profile=${param.id}`)
|
||||||
const response2 = await funGetUserIdByToken()
|
const response2 = await funGetUserIdByToken()
|
||||||
if (response.success) {
|
if (response) {
|
||||||
setAuthorId(response.data.id)
|
setAuthorId(response.data.id)
|
||||||
setUserRoleId(response.data.masterUserRoleId)
|
setUserRoleId(response.data.masterUserRoleId)
|
||||||
setUserLoginId(response2)
|
setUserLoginId(response2)
|
||||||
|
|||||||
@@ -1,98 +1,103 @@
|
|||||||
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
|
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
|
||||||
import { ComponentGlobal_NotifikasiBerhasil, ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global";
|
import {
|
||||||
|
ComponentGlobal_NotifikasiBerhasil,
|
||||||
|
ComponentGlobal_NotifikasiGagal,
|
||||||
|
} from "@/app_modules/_global/notif_global";
|
||||||
import { UIGlobal_Modal } from "@/app_modules/_global/ui";
|
import { UIGlobal_Modal } from "@/app_modules/_global/ui";
|
||||||
import { Button } from "@mantine/core";
|
import { Button } from "@mantine/core";
|
||||||
import { useShallowEffect } from "@mantine/hooks";
|
import { useShallowEffect } from "@mantine/hooks";
|
||||||
import { IconTrash } from "@tabler/icons-react";
|
import { IconTrash } from "@tabler/icons-react";
|
||||||
import { useParams, useRouter } from "next/navigation";
|
import { useParams, useRouter } from "next/navigation";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { apiDeletePortofolio, apiGetOnePortofolioById } from "../lib/api_portofolio";
|
import {
|
||||||
|
apiDeletePortofolio,
|
||||||
|
apiGetOnePortofolioById,
|
||||||
|
} from "../lib/api_portofolio";
|
||||||
import { IDetailPortofolioBisnis } from "../lib/type_portofolio";
|
import { IDetailPortofolioBisnis } from "../lib/type_portofolio";
|
||||||
import { MainColor } from "@/app_modules/_global/color";
|
import { MainColor } from "@/app_modules/_global/color";
|
||||||
|
import { apiGetUserId } from "@/app_modules/_global/lib/api_user";
|
||||||
|
import { clientLogger } from "@/util/clientLogger";
|
||||||
|
|
||||||
export default function ComponentPortofolio_ButtonDeleteNew() {
|
export default function ComponentPortofolio_ButtonDeleteNew({
|
||||||
const param = useParams<{ id: string }>()
|
userLoginId,
|
||||||
const [openModal, setModal] = useState(false)
|
}: {
|
||||||
const [loadingDel, setLoadingDel] = useState(false)
|
userLoginId: string;
|
||||||
const [userLoginId, setUserLoginId] = useState("")
|
}) {
|
||||||
const [dataPorto, setDataPorto] = useState<IDetailPortofolioBisnis>()
|
const param = useParams<{ id: string }>();
|
||||||
const router = useRouter()
|
const [openModal, setModal] = useState(false);
|
||||||
|
const [loadingDel, setLoadingDel] = useState(false);
|
||||||
|
const [dataPorto, setDataPorto] = useState<IDetailPortofolioBisnis>();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
async function onDelete() {
|
||||||
async function onDelete() {
|
try {
|
||||||
try {
|
setLoadingDel(true);
|
||||||
setLoadingDel(true)
|
const response = await apiDeletePortofolio(param.id);
|
||||||
const response = await apiDeletePortofolio(param.id)
|
if (response) {
|
||||||
if (response.success) {
|
ComponentGlobal_NotifikasiBerhasil(response.message);
|
||||||
ComponentGlobal_NotifikasiBerhasil(response.message)
|
router.back();
|
||||||
router.back()
|
} else {
|
||||||
} else {
|
ComponentGlobal_NotifikasiGagal(response?.message);
|
||||||
ComponentGlobal_NotifikasiGagal(response.message);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error)
|
|
||||||
ComponentGlobal_NotifikasiGagal("Gagal menghapus portofolio");
|
|
||||||
} finally {
|
|
||||||
setLoadingDel(false)
|
|
||||||
}
|
}
|
||||||
}
|
} catch (error) {
|
||||||
|
clientLogger.error("Error delete portofolio", error);
|
||||||
|
ComponentGlobal_NotifikasiGagal("Gagal menghapus portofolio");
|
||||||
|
} finally {
|
||||||
|
setLoadingDel(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function funGetPortofolio() {
|
async function funGetPortofolio() {
|
||||||
try {
|
try {
|
||||||
const response = await apiGetOnePortofolioById(param.id, "bisnis")
|
const response = await apiGetOnePortofolioById(param.id, "bisnis");
|
||||||
const response2 = await funGetUserIdByToken()
|
if (response) {
|
||||||
if (response.success) {
|
setDataPorto(response.data);
|
||||||
setDataPorto(response.data)
|
|
||||||
setUserLoginId(response2)
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
}
|
}
|
||||||
}
|
} catch (error) {
|
||||||
|
console.error("Error get data button delete:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
funGetPortofolio()
|
funGetPortofolio();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{userLoginId === dataPorto?.authorId && (
|
||||||
|
<Button
|
||||||
|
radius={"xl"}
|
||||||
|
bg={MainColor.red}
|
||||||
|
color="red"
|
||||||
|
onClick={() => {
|
||||||
|
setModal(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconTrash />
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
|
||||||
return (
|
<UIGlobal_Modal
|
||||||
<>
|
title={"Anda yakin menghapus portofolio ini ?"}
|
||||||
{userLoginId === dataPorto?.authorId ? (
|
opened={openModal}
|
||||||
<Button
|
close={() => setModal(false)}
|
||||||
radius={"xl"}
|
buttonKiri={
|
||||||
bg={MainColor.red}
|
<Button radius={"xl"} onClick={() => setModal(false)}>
|
||||||
color="red"
|
Batal
|
||||||
onClick={() => {
|
</Button>
|
||||||
setModal(true)
|
}
|
||||||
}}
|
buttonKanan={
|
||||||
>
|
<Button
|
||||||
<IconTrash />
|
radius={"xl"}
|
||||||
</Button>
|
color="red"
|
||||||
) : (
|
loaderPosition="center"
|
||||||
""
|
loading={loadingDel}
|
||||||
)}
|
onClick={() => onDelete()}
|
||||||
|
>
|
||||||
<UIGlobal_Modal
|
Hapus
|
||||||
title={"Anda yakin menghapus portofolio ini ?"}
|
</Button>
|
||||||
opened={openModal}
|
}
|
||||||
close={() => setModal(false)}
|
/>
|
||||||
buttonKiri={
|
</>
|
||||||
<Button radius={"xl"} onClick={() => setModal(false)}>
|
);
|
||||||
Batal
|
}
|
||||||
</Button>
|
|
||||||
}
|
|
||||||
buttonKanan={
|
|
||||||
<Button
|
|
||||||
radius={"xl"}
|
|
||||||
color="red"
|
|
||||||
loaderPosition="center"
|
|
||||||
loading={loadingDel}
|
|
||||||
onClick={() => onDelete()}
|
|
||||||
>
|
|
||||||
Hapus
|
|
||||||
</Button>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -89,9 +89,9 @@ export default function ComponentPortofolio_ButtonMoreNew() {
|
|||||||
const response = await apiGetOnePortofolioById(param.id, "bisnis")
|
const response = await apiGetOnePortofolioById(param.id, "bisnis")
|
||||||
const response3 = await apiGetOnePortofolioById(param.id, "lokasi")
|
const response3 = await apiGetOnePortofolioById(param.id, "lokasi")
|
||||||
const response2 = await funGetUserIdByToken()
|
const response2 = await funGetUserIdByToken()
|
||||||
if (response.success) {
|
if (response) {
|
||||||
setAuthorId(response.data.authorId)
|
setAuthorId(response.data.authorId)
|
||||||
setMapId((response3.data?.mapId !== null && response3.data?.mapId !== undefined) ? true : false)
|
setMapId((response3 !== null && response3.data?.mapId !== undefined) ? true : false)
|
||||||
setUserLoginId(response2)
|
setUserLoginId(response2)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function Portofolio_SkeletonListPorto() {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -170,30 +170,6 @@ export default function CreatePortofolio({
|
|||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
{/* <TextInput
|
|
||||||
styles={{
|
|
||||||
label: {
|
|
||||||
color: MainColor.white,
|
|
||||||
},
|
|
||||||
// input: {
|
|
||||||
// backgroundColor: MainColor.white,
|
|
||||||
// },
|
|
||||||
// required: {
|
|
||||||
// color: MainColor.red,
|
|
||||||
// },
|
|
||||||
}}
|
|
||||||
withAsterisk
|
|
||||||
label="Nomor Telepon "
|
|
||||||
placeholder="Nomor telepon "
|
|
||||||
type="number"
|
|
||||||
onChange={(val) => {
|
|
||||||
setDataPortofolio({
|
|
||||||
...dataPortofolio,
|
|
||||||
tlpn: val.target.value,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/> */}
|
|
||||||
|
|
||||||
<Stack spacing={5}>
|
<Stack spacing={5}>
|
||||||
<Textarea
|
<Textarea
|
||||||
styles={{
|
styles={{
|
||||||
|
|||||||
@@ -1,19 +1,51 @@
|
|||||||
export const apiGetPortofolioByProfile = async (path?: string) => {
|
export const apiGetPortofolioByProfile = async (path?: string) => {
|
||||||
const response = await fetch(`/api/new/portofolio${(path) ? path : ''}`)
|
const { token } = await fetch("/api/get-cookie").then((res) => res.json());
|
||||||
return await response.json().catch(() => null)
|
if (!token) return null;
|
||||||
}
|
|
||||||
|
|
||||||
export const apiGetOnePortofolioById = async (path: string, cat:string) => {
|
const response = await fetch(`/api/new/portofolio${path ? path : ""}`, {
|
||||||
const response = await fetch(`/api/new/portofolio/${path}?cat=${cat}`);
|
headers: {
|
||||||
return await response.json().catch(() => null);
|
"Content-Type": "application/json",
|
||||||
}
|
Accept: "application/json",
|
||||||
|
"Access-Control-Allow-Origin": "*",
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) return null;
|
||||||
|
const data: Record<string, any> = await response.json();
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const apiGetOnePortofolioById = async (path: string, cat: string) => {
|
||||||
|
const { token } = await fetch("/api/get-cookie").then((res) => res.json());
|
||||||
|
if (!token) return null;
|
||||||
|
|
||||||
|
const response = await fetch(`/api/new/portofolio/${path}?cat=${cat}`, {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "application/json",
|
||||||
|
"Access-Control-Allow-Origin": "*",
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) return null;
|
||||||
|
const data: Record<string, any> = await response.json();
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
export const apiDeletePortofolio = async (path: string) => {
|
export const apiDeletePortofolio = async (path: string) => {
|
||||||
const response = await fetch(`/api/new/portofolio/${path}`, {
|
const { token } = await fetch("/api/get-cookie").then((res) => res.json());
|
||||||
method: "DELETE",
|
if (!token) return null;
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
const response = await fetch(`/api/new/portofolio/${path}`, {
|
||||||
},
|
method: "DELETE",
|
||||||
});
|
headers: {
|
||||||
return await response.json().catch(() => null);
|
"Content-Type": "application/json",
|
||||||
}
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
return await response.json().catch(() => null);
|
||||||
|
};
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export default function Portofolio_UiDetailDataNew() {
|
|||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const response = await apiGetOnePortofolioById(param.id, "bisnis");
|
const response = await apiGetOnePortofolioById(param.id, "bisnis");
|
||||||
if (response.success) {
|
if (response) {
|
||||||
setDataPorto(response.data);
|
setDataPorto(response.data);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export default function Portofolio_UiMapNew({ mapboxToken }: { mapboxToken: stri
|
|||||||
try {
|
try {
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
const response = await apiGetOnePortofolioById(param.id, "lokasi");
|
const response = await apiGetOnePortofolioById(param.id, "lokasi");
|
||||||
if (response.success) {
|
if (response) {
|
||||||
setDataPorto(response.data);
|
setDataPorto(response.data);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export default function Portofolio_UiSosialMediaNew() {
|
|||||||
try {
|
try {
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
const response = await apiGetOnePortofolioById(param.id, "sosmed");
|
const response = await apiGetOnePortofolioById(param.id, "sosmed");
|
||||||
if (response.success) {
|
if (response) {
|
||||||
setDataPorto(response.data);
|
setDataPorto(response.data);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -5,15 +5,21 @@ import Portofolio_UiMapNew from "./ui_detail_map_new";
|
|||||||
import Portofolio_UiSosialMediaNew from "./ui_detail_media_new";
|
import Portofolio_UiSosialMediaNew from "./ui_detail_media_new";
|
||||||
import ComponentPortofolio_ButtonDeleteNew from "../component/button_delete_new";
|
import ComponentPortofolio_ButtonDeleteNew from "../component/button_delete_new";
|
||||||
|
|
||||||
export default function Portofolio_UiDetailNew({ mapboxToken }: { mapboxToken: string }) {
|
export default function Portofolio_UiDetailNew({
|
||||||
return (
|
mapboxToken,
|
||||||
<>
|
userLoginId,
|
||||||
<Stack mb={"lg"}>
|
}: {
|
||||||
<Portofolio_UiDetailDataNew />
|
mapboxToken: string;
|
||||||
<Portofolio_UiMapNew mapboxToken={mapboxToken} />
|
userLoginId: string
|
||||||
<Portofolio_UiSosialMediaNew />
|
}) {
|
||||||
<ComponentPortofolio_ButtonDeleteNew/>
|
return (
|
||||||
</Stack>
|
<>
|
||||||
</>
|
<Stack mb={"lg"}>
|
||||||
)
|
<Portofolio_UiDetailDataNew />
|
||||||
|
<Portofolio_UiMapNew mapboxToken={mapboxToken} />
|
||||||
|
<Portofolio_UiSosialMediaNew />
|
||||||
|
<ComponentPortofolio_ButtonDeleteNew userLoginId={userLoginId} />
|
||||||
|
</Stack>
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
@@ -1,59 +1,84 @@
|
|||||||
import ComponentGlobal_Loader from "@/app_modules/_global/component/loader";
|
import ComponentGlobal_Loader from "@/app_modules/_global/component/loader";
|
||||||
import { Box, Center } from "@mantine/core";
|
import { Box, Center, Group, Skeleton, Stack } from "@mantine/core";
|
||||||
|
import { useShallowEffect } from "@mantine/hooks";
|
||||||
import { ScrollOnly } from "next-scroll-loader";
|
import { ScrollOnly } from "next-scroll-loader";
|
||||||
|
import { useParams } from "next/navigation";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { ComponentPortofolio_DaftarBoxView } from "../component/card_view_daftar";
|
import { ComponentPortofolio_DaftarBoxView } from "../component/card_view_daftar";
|
||||||
import { portofolio_funGetAllDaftarByid } from "../fun/get/get_all_portofolio";
|
|
||||||
import { MODEL_PORTOFOLIO } from "../model/interface";
|
|
||||||
import { useParams } from "next/navigation";
|
|
||||||
import { useShallowEffect } from "@mantine/hooks";
|
|
||||||
import { apiGetPortofolioByProfile } from "../lib/api_portofolio";
|
import { apiGetPortofolioByProfile } from "../lib/api_portofolio";
|
||||||
|
import { MODEL_PORTOFOLIO } from "../model/interface";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component";
|
||||||
|
import CustomSkeleton from "@/app_modules/components/CustomSkeleton";
|
||||||
|
|
||||||
export default function Portofolio_UiListDetailNew() {
|
export default function Portofolio_UiListDetailNew() {
|
||||||
const param = useParams<{ id: string }>()
|
const param = useParams<{ id: string }>();
|
||||||
const profileId = param.id
|
const profileId = param.id;
|
||||||
const [data, setData] = useState<MODEL_PORTOFOLIO[]>([])
|
const [data, setData] = useState<MODEL_PORTOFOLIO[] | null>(null);
|
||||||
const [activePage, setActivePage] = useState(1)
|
const [activePage, setActivePage] = useState(1);
|
||||||
|
|
||||||
async function getPortofolio() {
|
async function getPortofolio() {
|
||||||
try {
|
try {
|
||||||
const response = await apiGetPortofolioByProfile(`?profile=${param.id}&cat=portofolio&page=1`)
|
const response = await apiGetPortofolioByProfile(
|
||||||
if (response.success) {
|
`?profile=${param.id}&cat=portofolio&page=1`
|
||||||
setData(response.data);
|
);
|
||||||
}
|
if (response) {
|
||||||
} catch (error) {
|
setData(response.data);
|
||||||
console.error(error);
|
|
||||||
}
|
}
|
||||||
}
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
getPortofolio();
|
||||||
|
}, []);
|
||||||
|
|
||||||
useShallowEffect(() => {
|
if (_.isNull(data))
|
||||||
getPortofolio()
|
return (
|
||||||
}, []);
|
<>
|
||||||
|
<Stack>
|
||||||
|
<CustomSkeleton height={80} radius={"md"} width={"100%"} />
|
||||||
|
<CustomSkeleton height={80} radius={"md"} width={"100%"} />
|
||||||
|
</Stack>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
return <>
|
return (
|
||||||
|
<>
|
||||||
<Box py={5}>
|
<Box py={5}>
|
||||||
<ScrollOnly
|
<ScrollOnly
|
||||||
height="90vh"
|
height="90vh"
|
||||||
renderLoading={() => (
|
renderLoading={() => (
|
||||||
<Center mt={"lg"}>
|
<Center mt={"lg"}>
|
||||||
<ComponentGlobal_Loader />
|
<ComponentGlobal_Loader />
|
||||||
</Center>
|
</Center>
|
||||||
)}
|
)}
|
||||||
data={data}
|
data={data}
|
||||||
setData={setData}
|
setData={setData as any}
|
||||||
moreData={async () => {
|
moreData={async () => {
|
||||||
const loadData = await portofolio_funGetAllDaftarByid({
|
// const loadData = await portofolio_funGetAllDaftarByid({
|
||||||
profileId,
|
// profileId,
|
||||||
page: activePage + 1,
|
// page: activePage + 1,
|
||||||
});
|
// });
|
||||||
setActivePage((val) => val + 1);
|
|
||||||
|
|
||||||
return loadData;
|
try {
|
||||||
}}
|
const response = await apiGetPortofolioByProfile(
|
||||||
>
|
`?profile=${param.id}&cat=portofolio&page=${activePage + 1}`
|
||||||
{(item) => <ComponentPortofolio_DaftarBoxView data={item} />}
|
);
|
||||||
</ScrollOnly>
|
if (response) {
|
||||||
|
setActivePage((val) => val + 1);
|
||||||
|
|
||||||
|
return response.data;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{(item) => <ComponentPortofolio_DaftarBoxView data={item} />}
|
||||||
|
</ScrollOnly>
|
||||||
</Box>
|
</Box>
|
||||||
</>;
|
</>
|
||||||
}
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export default function ListPortofolioProfileNew() {
|
|||||||
try {
|
try {
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
const response = await apiGetPortofolioByProfile(`?profile=${param.id}&cat=profile`)
|
const response = await apiGetPortofolioByProfile(`?profile=${param.id}&cat=profile`)
|
||||||
if (response.success) {
|
if (response) {
|
||||||
setDataPortofolio(response.data);
|
setDataPortofolio(response.data);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ export default function ProfileDetail() {
|
|||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const response = await apiGetUserProfile(`?profile=${param.id}`);
|
const response = await apiGetUserProfile(`?profile=${param.id}`);
|
||||||
if (response.success) {
|
if (response) {
|
||||||
setDataProfile(response.data);
|
setDataProfile(response.data);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -1,9 +1,20 @@
|
|||||||
export const apiGetAllMap = async (path?: string) => {
|
export const apiGetAllMap = async (path?: string) => {
|
||||||
const response = await fetch(`/api/new/map${(path) ? path : ''}`)
|
const { token } = await fetch("/api/get-cookie").then((res) => res.json());
|
||||||
return await response.json().catch(() => null)
|
if (!token) return await token.json().catch(() => null);
|
||||||
}
|
|
||||||
|
const response = await fetch(`/api/new/map${path ? path : ""}`, {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "application/json",
|
||||||
|
"Access-Control-Allow-Origin": "*",
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return await response.json().catch(() => null);
|
||||||
|
};
|
||||||
|
|
||||||
export const apiGetOneMapById = async (path: string) => {
|
export const apiGetOneMapById = async (path: string) => {
|
||||||
const response = await fetch(`/api/new/map/${path}`);
|
|
||||||
return await response.json().catch(() => null);
|
const response = await fetch(`/api/new/map/${path}`);
|
||||||
}
|
return await response.json().catch(() => null);
|
||||||
|
};
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export function UiMap_MapBoxViewNew({ mapboxToken, }: { mapboxToken: string }) {
|
|||||||
try {
|
try {
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
const response = await apiGetAllMap()
|
const response = await apiGetAllMap()
|
||||||
if (response.success) {
|
if (response) {
|
||||||
setData(response.data)
|
setData(response.data)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -1,4 +1,19 @@
|
|||||||
export const apiGetUserProfile = async (path?: string) => {
|
export const apiGetUserProfile = async (path?: string) => {
|
||||||
const response = await fetch(`/api/new/user${(path) ? path : ''}`)
|
const { token } = await fetch("/api/get-cookie").then((res) => res.json());
|
||||||
return await response.json().catch(() => null)
|
if(!token) return null
|
||||||
|
|
||||||
|
const response = await fetch(`/api/new/user${(path) ? path : ''}`, {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'Access-Control-Allow-Origin': '*',
|
||||||
|
'Authorization': `Bearer ${token}`,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// console.log(await response.json())
|
||||||
|
|
||||||
|
if (!response.ok) return null
|
||||||
|
const data: Record<string, any> = await response.json()
|
||||||
|
return data
|
||||||
}
|
}
|
||||||
@@ -2,22 +2,14 @@
|
|||||||
|
|
||||||
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global";
|
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global";
|
||||||
import { UIGlobal_LayoutDefault } from "@/app_modules/_global/ui";
|
import { UIGlobal_LayoutDefault } from "@/app_modules/_global/ui";
|
||||||
import {
|
import { clientLogger } from "@/util/clientLogger";
|
||||||
Button,
|
import { Skeleton, Stack, Text } from "@mantine/core";
|
||||||
Center,
|
|
||||||
Group,
|
|
||||||
Skeleton,
|
|
||||||
Stack,
|
|
||||||
Text,
|
|
||||||
Title,
|
|
||||||
} from "@mantine/core";
|
|
||||||
import { useShallowEffect } from "@mantine/hooks";
|
import { useShallowEffect } from "@mantine/hooks";
|
||||||
import { redirect, useRouter } from "next/navigation";
|
import _ from "lodash";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { ComponentGlobal_CardStyles } from "../_global/component";
|
import { ComponentGlobal_CardStyles } from "../_global/component";
|
||||||
import { apiGetACtivationUser } from "../_global/lib/api_user";
|
import { apiGetACtivationUser } from "../_global/lib/api_user";
|
||||||
import { clientLogger } from "@/util/clientLogger";
|
|
||||||
import _ from "lodash";
|
|
||||||
|
|
||||||
export default function WaitingRoom_View({
|
export default function WaitingRoom_View({
|
||||||
userLoginId,
|
userLoginId,
|
||||||
@@ -49,7 +41,6 @@ export default function WaitingRoom_View({
|
|||||||
try {
|
try {
|
||||||
const respone = await apiGetACtivationUser();
|
const respone = await apiGetACtivationUser();
|
||||||
if (respone) {
|
if (respone) {
|
||||||
console.log(respone.data);
|
|
||||||
setData(respone.data);
|
setData(respone.data);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ const middlewareConfig: MiddlewareConfig = {
|
|||||||
loginPath: "/login",
|
loginPath: "/login",
|
||||||
userPath: "/dev/home",
|
userPath: "/dev/home",
|
||||||
publicRoutes: [
|
publicRoutes: [
|
||||||
|
// API
|
||||||
"/",
|
"/",
|
||||||
"/api/voting/*",
|
"/api/voting/*",
|
||||||
"/api/collaboration/*",
|
"/api/collaboration/*",
|
||||||
@@ -25,26 +26,36 @@ const middlewareConfig: MiddlewareConfig = {
|
|||||||
"/api/logs/*",
|
"/api/logs/*",
|
||||||
"/api/image/*",
|
"/api/image/*",
|
||||||
"/api/job/*",
|
"/api/job/*",
|
||||||
"/api/validation",
|
|
||||||
"/api/auth/*",
|
"/api/auth/*",
|
||||||
"/api/origin-url",
|
"/api/origin-url",
|
||||||
"/api/user",
|
// "/api/user",
|
||||||
"/api/event/*",
|
"/api/event/*",
|
||||||
|
// Akses awal
|
||||||
|
"/api/get-cookie",
|
||||||
|
"/api/user/activation",
|
||||||
|
"/api/user-validate",
|
||||||
|
|
||||||
|
// PAGE
|
||||||
"/login",
|
"/login",
|
||||||
"/register",
|
"/register",
|
||||||
"/validasi",
|
"/validasi",
|
||||||
"/splash",
|
"/splash",
|
||||||
|
"/job-vacancy",
|
||||||
|
"/preview-image",
|
||||||
"/auth/login",
|
"/auth/login",
|
||||||
"/auth/api/login",
|
"/auth/api/login",
|
||||||
|
"/waiting-room",
|
||||||
|
|
||||||
|
// ASSETS
|
||||||
"/aset/global/main_background.png",
|
"/aset/global/main_background.png",
|
||||||
"/aset/logo/logo-hipmi.png",
|
"/aset/logo/logo-hipmi.png",
|
||||||
"/api/new/*",
|
|
||||||
],
|
],
|
||||||
encodedKey: process.env.NEXT_PUBLIC_BASE_TOKEN_KEY!,
|
encodedKey: process.env.NEXT_PUBLIC_BASE_TOKEN_KEY!,
|
||||||
sessionKey: process.env.NEXT_PUBLIC_BASE_SESSION_KEY!,
|
sessionKey: process.env.NEXT_PUBLIC_BASE_SESSION_KEY!,
|
||||||
validationApiRoute: "/api/validation",
|
validationApiRoute: "/api/validation",
|
||||||
log: false,
|
log: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const middleware = async (req: NextRequest) => {
|
export const middleware = async (req: NextRequest) => {
|
||||||
const {
|
const {
|
||||||
apiPath,
|
apiPath,
|
||||||
@@ -64,14 +75,20 @@ export const middleware = async (req: NextRequest) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Skip authentication for public routes
|
// Skip authentication for public routes
|
||||||
const isPublicRoute = [...publicRoutes, loginPath, validationApiRoute].some(
|
const isPublicRoute = [...publicRoutes, loginPath].some((route) => {
|
||||||
(route) => {
|
const pattern = route.replace(/\*/g, ".*");
|
||||||
const pattern = route.replace(/\*/g, ".*");
|
return new RegExp(`^${pattern}$`).test(pathname);
|
||||||
return new RegExp(`^${pattern}$`).test(pathname);
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (isPublicRoute) {
|
// Always protect validation endpoint
|
||||||
|
if (pathname === validationApiRoute) {
|
||||||
|
const reqToken = req.headers.get("Authorization")?.split(" ")[1];
|
||||||
|
if (!reqToken) {
|
||||||
|
return setCorsHeaders(unauthorizedResponse());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPublicRoute && pathname !== loginPath) {
|
||||||
return setCorsHeaders(NextResponse.next());
|
return setCorsHeaders(NextResponse.next());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,21 +99,43 @@ export const middleware = async (req: NextRequest) => {
|
|||||||
// Token verification
|
// Token verification
|
||||||
const user = await verifyToken({ token, encodedKey });
|
const user = await verifyToken({ token, encodedKey });
|
||||||
|
|
||||||
if (!user) {
|
// Handle login page access
|
||||||
if (pathname.startsWith(apiPath)) {
|
if (pathname === loginPath) {
|
||||||
return setCorsHeaders(unauthorizedResponse());
|
if (user) {
|
||||||
|
return setCorsHeaders(NextResponse.redirect(new URL(userPath, req.url)));
|
||||||
}
|
}
|
||||||
|
return setCorsHeaders(NextResponse.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle protected routes
|
||||||
|
if (!user) {
|
||||||
return setCorsHeaders(NextResponse.redirect(new URL(loginPath, req.url)));
|
return setCorsHeaders(NextResponse.redirect(new URL(loginPath, req.url)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Redirect authenticated user away from login page
|
if (pathname.startsWith("/dev")) {
|
||||||
if (user && pathname === loginPath) {
|
const userValidate = await fetch(new URL("/api/user-validate", req.url), {
|
||||||
return setCorsHeaders(NextResponse.redirect(new URL(userPath, req.url)));
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const userValidateJson = await userValidate.json();
|
||||||
|
|
||||||
|
if (!userValidateJson.data.active) {
|
||||||
|
return setCorsHeaders(
|
||||||
|
NextResponse.redirect(new URL("/waiting-room", req.url))
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req.nextUrl.pathname.startsWith(apiPath)) {
|
// Handle authenticated API requests
|
||||||
|
if (pathname.startsWith(apiPath)) {
|
||||||
const reqToken = req.headers.get("Authorization")?.split(" ")[1];
|
const reqToken = req.headers.get("Authorization")?.split(" ")[1];
|
||||||
|
if (!reqToken) {
|
||||||
|
return setCorsHeaders(unauthorizedResponse());
|
||||||
|
}
|
||||||
|
|
||||||
// Validate user access with external API
|
// Validate user access with external API
|
||||||
const validationResponse = await fetch(
|
const validationResponse = await fetch(
|
||||||
new URL(validationApiRoute, req.url),
|
new URL(validationApiRoute, req.url),
|
||||||
@@ -111,6 +150,8 @@ export const middleware = async (req: NextRequest) => {
|
|||||||
if (!validationResponse.ok) {
|
if (!validationResponse.ok) {
|
||||||
return setCorsHeaders(unauthorizedResponse());
|
return setCorsHeaders(unauthorizedResponse());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const dataJson = await validationResponse.json();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Proceed with the request
|
// Proceed with the request
|
||||||
|
|||||||
471
xserver/index.html
Normal file
471
xserver/index.html
Normal file
@@ -0,0 +1,471 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="id">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>HIPMI Feature Checklist</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f4f4f4;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
color: #333;
|
||||||
|
text-align: center;
|
||||||
|
border-bottom: 2px solid #333;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
h3 {
|
||||||
|
color: #444;
|
||||||
|
margin-top: 20px;
|
||||||
|
background-color: #e0e0e0;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
ul {
|
||||||
|
list-style-type: none;
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
background-color: #fff;
|
||||||
|
margin: 5px 0;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
||||||
|
transition: background-color 0.3s ease;
|
||||||
|
}
|
||||||
|
input[type="checkbox"] {
|
||||||
|
margin-right: 10px;
|
||||||
|
transform: scale(1.2);
|
||||||
|
}
|
||||||
|
li:hover {
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
}
|
||||||
|
li.checked {
|
||||||
|
text-decoration: line-through;
|
||||||
|
color: #888;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
}
|
||||||
|
#progress-bar {
|
||||||
|
width: 100%;
|
||||||
|
background-color: #e0e0e0;
|
||||||
|
padding: 10px;
|
||||||
|
margin-top: 20px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
#progress {
|
||||||
|
width: 0%;
|
||||||
|
height: 20px;
|
||||||
|
background-color: #4caf50;
|
||||||
|
border-radius: 5px;
|
||||||
|
transition: width 0.5s ease;
|
||||||
|
}
|
||||||
|
#reset-btn {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
background-color: #f44336;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin-top: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
#reset-btn:hover {
|
||||||
|
background-color: #d32f2f;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>HIPMI Feature Checklist</h1>
|
||||||
|
|
||||||
|
<div id="progress-bar">
|
||||||
|
<div id="progress"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="checklist">
|
||||||
|
<h3>Authentication</h3>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="login" /> <label for="login">Login</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="validasi" />
|
||||||
|
<label for="validasi">Validasi</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="register" />
|
||||||
|
<label for="register">Register</label>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Profile</h3>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="buat-profile" />
|
||||||
|
<label for="buat-profile">Buat profile baru</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="edit-data" />
|
||||||
|
<label for="edit-data">Edit Data</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="update-foto-profile" />
|
||||||
|
<label for="update-foto-profile">Update foto profile</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="update-foto-background" />
|
||||||
|
<label for="update-foto-background">Update foto background</label>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Portofolio</h3>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="buat-portofolio" />
|
||||||
|
<label for="buat-portofolio">Buat portofolio baru</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="edit-detail-portofolio" />
|
||||||
|
<label for="edit-detail-portofolio">Edit detail portofolio</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="edit-logo-map" />
|
||||||
|
<label for="edit-logo-map">Edit logo map</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="edit-sosial-media" />
|
||||||
|
<label for="edit-sosial-media">Edit data sosial media</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="edit-data-map" />
|
||||||
|
<label for="edit-data-map">Edit data map</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="custom-pin-map" />
|
||||||
|
<label for="custom-pin-map">Custom pin map</label>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>User Search</h3>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="cari-pengguna" />
|
||||||
|
<label for="cari-pengguna"
|
||||||
|
>Cari pengguna lain & masuk ke katalog nya</label
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Business Map</h3>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="buka-pin-map" />
|
||||||
|
<label for="buka-pin-map">Buka pin map user lain</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="lihat-detail-map" />
|
||||||
|
<label for="lihat-detail-map">Lihat detailnya</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="buka-google-maps" />
|
||||||
|
<label for="buka-google-maps">Buka map (Google Maps)</label>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Event</h3>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="buat-event-bebas" />
|
||||||
|
<label for="buat-event-bebas">Buat event baru (tanggal bebas)</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="batalkan-review" />
|
||||||
|
<label for="batalkan-review">Batalkan review</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="edit-event" />
|
||||||
|
<label for="edit-event">Edit event</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="ajukan-event" />
|
||||||
|
<label for="ajukan-event">Ajukan event</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="tunggu-acc-admin-event" />
|
||||||
|
<label for="tunggu-acc-admin-event">Tunggu acc admin</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="reload-beranda" />
|
||||||
|
<label for="reload-beranda"
|
||||||
|
>Reload data beranda (dengan button reload)</label
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="join-detail-event" />
|
||||||
|
<label for="join-detail-event">Join melalui detail event</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="scan-qr-join" />
|
||||||
|
<label for="scan-qr-join"
|
||||||
|
>Scan QrCode dan join melalui halaman konfirmasi</label
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="buat-event-hari-ini" />
|
||||||
|
<label for="buat-event-hari-ini"
|
||||||
|
>Buat event baru (tanggal dan jam hari ini)</label
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="tunggu-acc-admin-event-2" />
|
||||||
|
<label for="tunggu-acc-admin-event-2">Tunggu acc admin</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="scan-qr-konfirmasi" />
|
||||||
|
<label for="scan-qr-konfirmasi"
|
||||||
|
>Scan QrCode dan join melalui halaman konfirmasi</label
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="cek-kontribusi-user" />
|
||||||
|
<label for="cek-kontribusi-user">Cek kontribusi user</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="cek-riwayat-semua" />
|
||||||
|
<label for="cek-riwayat-semua">Cek Riwayat Semua</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="cek-riwayat-saya" />
|
||||||
|
<label for="cek-riwayat-saya">Cek Riwayat Saya</label>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Collaboration</h3>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="buat-kolaborasi" />
|
||||||
|
<label for="buat-kolaborasi">Buat kolaborasi baru</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="user-join-kolaborasi" />
|
||||||
|
<label for="user-join-kolaborasi">User lain join</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="pilih-user-kolaborasi" />
|
||||||
|
<label for="pilih-user-kolaborasi"
|
||||||
|
>User pemilik proyek kolaborasi memilih user yang ada di list</label
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="grup-proyek-kolaborasi" />
|
||||||
|
<label for="grup-proyek-kolaborasi"
|
||||||
|
>Grup proyek kolabari terbentuk dan memulai chat</label
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Voting</h3>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="buat-voting" />
|
||||||
|
<label for="buat-voting">Buat voting baru</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="tunggu-acc-voting" />
|
||||||
|
<label for="tunggu-acc-voting">Tunggu acc admin</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="user-voting" />
|
||||||
|
<label for="user-voting">User lain melakukan voting</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="cek-kontribusi-voting" />
|
||||||
|
<label for="cek-kontribusi-voting"
|
||||||
|
>Setelah melakukan voting cek kontribusi nya di halaman
|
||||||
|
kontribusi</label
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Investasi</h3>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="buat-investasi" />
|
||||||
|
<label for="buat-investasi">Buat invetasi baru</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="tunggu-acc-investasi" />
|
||||||
|
<label for="tunggu-acc-investasi">Tunggu acc admin</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="user-investasi-baru" />
|
||||||
|
<label for="user-investasi-baru"
|
||||||
|
>User lain melakukan investasi baru</label
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="lampirkan-bukti-transfer" />
|
||||||
|
<label for="lampirkan-bukti-transfer"
|
||||||
|
>User lain melampirkan bukti transfer</label
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="validasi-admin-investasi" />
|
||||||
|
<label for="validasi-admin-investasi">Admin melakukan validasi</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="investor-lihat-transaksi" />
|
||||||
|
<label for="investor-lihat-transaksi"
|
||||||
|
>User investor melihat hasilnya pada halaman transaksi</label
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Donasi</h3>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="buat-donasi" />
|
||||||
|
<label for="buat-donasi">Buat donasi baru</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="tunggu-acc-donasi" />
|
||||||
|
<label for="tunggu-acc-donasi">Tunggu acc admin</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="user-donasi-baru" />
|
||||||
|
<label for="user-donasi-baru">User lain melakukan donasi baru</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="lampirkan-bukti-donasi" />
|
||||||
|
<label for="lampirkan-bukti-donasi"
|
||||||
|
>User lain melampirkan bukti transfer</label
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="validasi-admin-donasi" />
|
||||||
|
<label for="validasi-admin-donasi">Admin melakukan validasi</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="donatur-lihat-donasi" />
|
||||||
|
<label for="donatur-lihat-donasi"
|
||||||
|
>User donatur melihat hasilnya pada halaman donasi saya</label
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Job</h3>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="buat-job-baru" />
|
||||||
|
<label for="buat-job-baru">Buat job baru</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="tunggu-acc-job" />
|
||||||
|
<label for="tunggu-acc-job">Tunggu acc admin</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="update-beranda-job" />
|
||||||
|
<label for="update-beranda-job"
|
||||||
|
>User lain melihat update diberanda</label
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="share-whatsapp" />
|
||||||
|
<label for="share-whatsapp">Share melalui whatsapp</label>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Forum</h3>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="buat-forum-baru" />
|
||||||
|
<label for="buat-forum-baru">Buat forum baru</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="user-komentar" />
|
||||||
|
<label for="user-komentar">User lain berkomentar</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="kontrol-komentar" />
|
||||||
|
<label for="kontrol-komentar"
|
||||||
|
>User pemilik forum menutup atau membuka kolom komentar</label
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="user-report" />
|
||||||
|
<label for="user-report">User lain melakukan report</label>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button id="reset-btn">Reset Semua Checklist</button>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
const checkboxes = document.querySelectorAll('input[type="checkbox"]');
|
||||||
|
const progressBar = document.getElementById("progress");
|
||||||
|
const resetBtn = document.getElementById("reset-btn");
|
||||||
|
|
||||||
|
// Load saved state from localStorage
|
||||||
|
checkboxes.forEach((checkbox) => {
|
||||||
|
const savedState = localStorage.getItem(checkbox.id);
|
||||||
|
if (savedState === "checked") {
|
||||||
|
checkbox.checked = true;
|
||||||
|
checkbox.parentElement.classList.add("checked");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update progress
|
||||||
|
function updateProgress() {
|
||||||
|
const totalCheckboxes = checkboxes.length;
|
||||||
|
const checkedCheckboxes = document.querySelectorAll(
|
||||||
|
'input[type="checkbox"]:checked'
|
||||||
|
).length;
|
||||||
|
const progressPercentage =
|
||||||
|
(checkedCheckboxes / totalCheckboxes) * 100;
|
||||||
|
progressBar.style.width = `${progressPercentage}%`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initial progress update
|
||||||
|
updateProgress();
|
||||||
|
|
||||||
|
// Add event listeners to checkboxes
|
||||||
|
checkboxes.forEach((checkbox) => {
|
||||||
|
checkbox.addEventListener("change", () => {
|
||||||
|
// Toggle 'checked' class on parent li
|
||||||
|
checkbox.parentElement.classList.toggle(
|
||||||
|
"checked",
|
||||||
|
checkbox.checked
|
||||||
|
);
|
||||||
|
|
||||||
|
// Save state to localStorage
|
||||||
|
localStorage.setItem(
|
||||||
|
checkbox.id,
|
||||||
|
checkbox.checked ? "checked" : "unchecked"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Update progress bar
|
||||||
|
updateProgress();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Reset button functionality
|
||||||
|
resetBtn.addEventListener("click", () => {
|
||||||
|
checkboxes.forEach((checkbox) => {
|
||||||
|
checkbox.checked = false;
|
||||||
|
checkbox.parentElement.classList.remove("checked");
|
||||||
|
localStorage.removeItem(checkbox.id);
|
||||||
|
});
|
||||||
|
updateProgress();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user