diff --git a/CHANGELOG.md b/CHANGELOG.md index a3791091..2883a20b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines. +## [1.2.65](https://github.com/bipproduction/hipmi/compare/v1.2.64...v1.2.65) (2025-02-27) + +## [1.2.64](https://github.com/bipproduction/hipmi/compare/v1.2.63...v1.2.64) (2025-02-26) + ## [1.2.63](https://github.com/bipproduction/hipmi/compare/v1.2.62...v1.2.63) (2025-02-26) ## [1.2.62](https://github.com/bipproduction/hipmi/compare/v1.2.61...v1.2.62) (2025-02-25) diff --git a/bun.lock b/bun.lock old mode 100755 new mode 100644 index fc8ef387..348ae19e --- a/bun.lock +++ b/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "dependencies": { @@ -58,6 +58,8 @@ "next-dev": "^1.1.9", "next-scroll-loader": "^1.0.9", "p-limit": "^6.2.0", + "pdf-lib": "^1.17.1", + "pdf2pic": "^3.1.3", "pdfjs-dist": "^4.6.82", "postcss": "8.4.27", "prisma": "^6.3.0", @@ -717,6 +719,10 @@ "@oven/bun-windows-x64-baseline": ["@oven/bun-windows-x64-baseline@1.2.2", "", { "os": "win32", "cpu": "x64" }, "sha512-bYopMWSCjjjCKjANv7xxAXQoabVUxLZxTw0iC1bGYD9VZGo48nGaJXPn7DsPfeCXGyl+CY3Cy4QIEn+3gNRS2A=="], + "@pdf-lib/standard-fonts": ["@pdf-lib/standard-fonts@1.0.0", "", { "dependencies": { "pako": "^1.0.6" } }, "sha512-hU30BK9IUN/su0Mn9VdlVKsWBS6GyhVfqjwl1FjZN4TxP6cCw0jP2w7V3Hf5uX7M0AZJ16vey9yE0ny7Sa59ZA=="], + + "@pdf-lib/upng": ["@pdf-lib/upng@1.0.1", "", { "dependencies": { "pako": "^1.0.10" } }, "sha512-dQK2FUMQtowVP00mtIksrlZhdFXQZPC+taih1q4CvPZ5vqdxR/LKBaFg0oAfzd1GlHZXXSPdQfzQnt+ViGvEIQ=="], + "@peculiar/asn1-schema": ["@peculiar/asn1-schema@2.3.15", "", { "dependencies": { "asn1js": "^3.0.5", "pvtsutils": "^1.3.6", "tslib": "^2.8.1" } }, "sha512-QPeD8UA8axQREpgR5UTAfu2mqQmm97oUqahDtNdBcfj3qAnoXzFdQW+aNf/tD2WVXF8Fhmftxoj0eMIT++gX2w=="], "@peculiar/json-schema": ["@peculiar/json-schema@1.1.12", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w=="], @@ -1151,6 +1157,10 @@ "array-includes": ["array-includes@3.1.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.4", "is-string": "^1.0.7" } }, "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ=="], + "array-parallel": ["array-parallel@0.1.3", "", {}, "sha512-TDPTwSWW5E4oiFiKmz6RGJ/a80Y91GuLgUYuLd49+XBS75tYo8PNgaT2K/OxuQYqkoI852MDGBorg9OcUSTQ8w=="], + + "array-series": ["array-series@0.1.5", "", {}, "sha512-L0XlBwfx9QetHOsbLDrE/vh2t018w9462HM3iaFfxRiK83aJjAt/Ja3NMkOW7FICwWTlQBa3ZbL5FKhuQWkDrg=="], + "array-union": ["array-union@2.1.0", "", {}, "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw=="], "array.prototype.findlast": ["array.prototype.findlast@1.2.5", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ=="], @@ -1815,6 +1825,8 @@ "globby": ["globby@11.1.0", "", { "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", "fast-glob": "^3.2.9", "ignore": "^5.2.0", "merge2": "^1.4.1", "slash": "^3.0.0" } }, "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g=="], + "gm": ["gm@1.25.1", "", { "dependencies": { "array-parallel": "~0.1.3", "array-series": "~0.1.5", "cross-spawn": "^7.0.5", "debug": "^3.1.0" } }, "sha512-jgcs2vKir9hFogGhXIfs0ODhJTfIrbECCehg38tqFgHm8zqXx7kAJyCYAFK4jTjx71AxrkFtkJBawbAxYUPX9A=="], + "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], "gpt-3-encoder": ["gpt-3-encoder@1.1.4", "", {}, "sha512-fSQRePV+HUAhCn7+7HL7lNIXNm6eaFWFbNLOOGtmSJ0qJycyQvj60OvRlH7mee8xAMjBDNRdMXlMwjAbMTDjkg=="], @@ -2457,6 +2469,10 @@ "pbf": ["pbf@3.3.0", "", { "dependencies": { "ieee754": "^1.1.12", "resolve-protobuf-schema": "^2.1.0" }, "bin": { "pbf": "bin/pbf" } }, "sha512-XDF38WCH3z5OV/OVa8GKUNtLAyneuzbCisx7QUCF8Q6Nutx0WnJrQe5O+kOtBlLfRNUws98Y58Lblp+NJG5T4Q=="], + "pdf-lib": ["pdf-lib@1.17.1", "", { "dependencies": { "@pdf-lib/standard-fonts": "^1.0.0", "@pdf-lib/upng": "^1.0.1", "pako": "^1.0.11", "tslib": "^1.11.1" } }, "sha512-V/mpyJAoTsN4cnP31vc0wfNA1+p20evqqnap0KLoRUN0Yk/p3wN52DOEsL4oBFcLdb76hlpKPtzJIgo67j/XLw=="], + + "pdf2pic": ["pdf2pic@3.1.3", "", { "dependencies": { "gm": "^1.25.0" } }, "sha512-KbW4Qb7iHw2fBRWtA9FTc4pZg9cokiFIzc6cE7dzelTrhXWolfQuG1fYVC0E2BRmK/w7xfBjQ+OEsPZPO3QEew=="], + "pdfjs-dist": ["pdfjs-dist@4.10.38", "", { "optionalDependencies": { "@napi-rs/canvas": "^0.1.65" } }, "sha512-/Y3fcFrXEAsMjJXeL9J8+ZG9U01LbuWaYypvDW2ycW1jL269L3js3DVBjDJ0Up9Np1uqDXsDrRihHANhZOlwdQ=="], "peerjs": ["peerjs@1.5.4", "", { "dependencies": { "@msgpack/msgpack": "^2.8.0", "eventemitter3": "^4.0.7", "peerjs-js-binarypack": "^2.1.0", "webrtc-adapter": "^9.0.0" } }, "sha512-yFsoLMnurJKlQbx6kVSBpOp+AlNldY1JQS2BrSsHLKCZnq6t7saHleuHM5svuLNbQkUJXHLF3sKOJB1K0xulOw=="], @@ -3467,6 +3483,8 @@ "formdata-node/web-streams-polyfill": ["web-streams-polyfill@4.0.0-beta.3", "", {}, "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug=="], + "gm/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], + "has-ansi/ansi-regex": ["ansi-regex@2.1.1", "", {}, "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA=="], "html-tokenize/readable-stream": ["readable-stream@1.0.34", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", "isarray": "0.0.1", "string_decoder": "~0.10.x" } }, "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg=="], @@ -3555,6 +3573,8 @@ "password-prompt/ansi-escapes": ["ansi-escapes@4.3.2", "", { "dependencies": { "type-fest": "^0.21.3" } }, "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ=="], + "pdf-lib/tslib": ["tslib@1.14.1", "", {}, "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="], + "peerjs/eventemitter3": ["eventemitter3@4.0.7", "", {}, "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="], "pkg-dir/find-up": ["find-up@3.0.0", "", { "dependencies": { "locate-path": "^3.0.0" } }, "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg=="], diff --git a/logs/backend/.31d2357fa2026a78b8cb786880c7c733460d7dbe-audit.json b/logs/backend/.31d2357fa2026a78b8cb786880c7c733460d7dbe-audit.json index 877fc566..b3f493a3 100644 --- a/logs/backend/.31d2357fa2026a78b8cb786880c7c733460d7dbe-audit.json +++ b/logs/backend/.31d2357fa2026a78b8cb786880c7c733460d7dbe-audit.json @@ -5,16 +5,6 @@ }, "auditLog": "logs/backend/.31d2357fa2026a78b8cb786880c7c733460d7dbe-audit.json", "files": [ - { - "date": 1739242050497, - "name": "logs/backend/combined-2025-02-11.log", - "hash": "13ef770bd22a1c0c4412156ffbf32e0a38fa2d61caa14054dc71d579374e8f56" - }, - { - "date": 1739327386336, - "name": "logs/backend/combined-2025-02-12.log", - "hash": "e37b3d0427223c278c22797248e12d501c266188b48b4edee0591037415ce990" - }, { "date": 1739413125862, "name": "logs/backend/combined-2025-02-13.log", @@ -64,6 +54,16 @@ "date": 1740450562875, "name": "logs/backend/combined-2025-02-25.log", "hash": "1ab2165b4d456ebed03006c88d9ce4b4f7be61bd38246e306fecbc73f72f8fdd" + }, + { + "date": 1740536165848, + "name": "logs/backend/combined-2025-02-26.log", + "hash": "428aedb3a3a248ad2c7069fcb8c6e0d669c23eae0dc3db08914886cce8d2cad9" + }, + { + "date": 1740595120097, + "name": "logs/backend/combined-2025-02-27.log", + "hash": "f6884fe9b12faf0557662daa93ae1d32d64bb6b12714c8be494ce9396a55ae18" } ], "hashType": "sha256" diff --git a/logs/backend/.5d9a990e0c6075347623def466341a14f8ba4a12-audit.json b/logs/backend/.5d9a990e0c6075347623def466341a14f8ba4a12-audit.json index b805d8d1..98e1702e 100644 --- a/logs/backend/.5d9a990e0c6075347623def466341a14f8ba4a12-audit.json +++ b/logs/backend/.5d9a990e0c6075347623def466341a14f8ba4a12-audit.json @@ -5,16 +5,6 @@ }, "auditLog": "logs/backend/.5d9a990e0c6075347623def466341a14f8ba4a12-audit.json", "files": [ - { - "date": 1739242050493, - "name": "logs/backend/error-2025-02-11.log", - "hash": "a346dd5f2327d9f40439c851473199450ec0918d7f0bd4b280343540a0b5ccb0" - }, - { - "date": 1739327386330, - "name": "logs/backend/error-2025-02-12.log", - "hash": "0d834a4ac0d78d547969ae0e55bc53a760b5a11942ed2efb7a08b50b2a16e7ee" - }, { "date": 1739413125859, "name": "logs/backend/error-2025-02-13.log", @@ -64,6 +54,16 @@ "date": 1740450562872, "name": "logs/backend/error-2025-02-25.log", "hash": "189996570b83d8dbc20aac1eaf0583edf1472e1d1ac0dc83be0fb9b20a20ee07" + }, + { + "date": 1740536165843, + "name": "logs/backend/error-2025-02-26.log", + "hash": "fc1b904017c0517b4aa4138d2edb5dd58474ef723a17cab177d0605026a23c11" + }, + { + "date": 1740595120075, + "name": "logs/backend/error-2025-02-27.log", + "hash": "50f75c53936bf2ca5beb3f48fb5de09dde49fea0792fc3532055fab75aae408f" } ], "hashType": "sha256" diff --git a/package.json b/package.json index 5d92a2a6..e8a7da47 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hipmi", - "version": "1.2.63", + "version": "1.2.65", "private": true, "type": "module", "prisma": { @@ -70,6 +70,8 @@ "next-dev": "^1.1.9", "next-scroll-loader": "^1.0.9", "p-limit": "^6.2.0", + "pdf-lib": "^1.17.1", + "pdf2pic": "^3.1.3", "pdfjs-dist": "^4.6.82", "postcss": "8.4.27", "prisma": "^6.3.0", diff --git a/src/app/api/pdf-to-image/route.ts b/src/app/api/pdf-to-image/route.ts new file mode 100644 index 00000000..26274157 --- /dev/null +++ b/src/app/api/pdf-to-image/route.ts @@ -0,0 +1,283 @@ +// // app/api/pdf-to-image/route.ts +import { execSync } from 'child_process'; +import { NextResponse } from 'next/server'; +import { PDFDocument } from 'pdf-lib'; +import { fromBuffer } from 'pdf2pic'; + +// // Tambahkan custom error +// class PDFConversionError extends Error { +// constructor(message: string, public statusCode: number = 500) { +// super(message); +// this.name = 'PDFConversionError'; +// } +// } + +// // Improve fungsi check dependencies +// async function checkDependencies() { +// const dependencies = [ +// { cmd: 'gm version', name: 'GraphicsMagick' }, +// { cmd: 'gs --version', name: 'Ghostscript' } +// ]; + +// for (const dep of dependencies) { +// try { +// execSync(dep.cmd); +// } catch (error) { +// throw new PDFConversionError(`${dep.name} tidak terinstall`, 500); +// } +// } +// } + +// // Tambah konstanta +// const MAX_PDF_SIZE_MB = 50; +// const MAX_IMAGE_DIMENSION = 2000; +// const CONVERSION_TIMEOUT_MS = 30000; +// const MAX_PAGES = 10; // Batasan jumlah halaman +// const DEFAULT_PAGE = 1; + +// // Modifikasi validateParams +// function validateParams(pdfUrl: string | null, pages: number[]) { +// if (!pdfUrl) { +// throw new PDFConversionError('URL parameter wajib diisi', 400); +// } +// if (pages.some(p => p < 1)) { +// throw new PDFConversionError('Nomor halaman tidak valid', 400); +// } +// if (pages.length > MAX_PAGES) { +// throw new PDFConversionError(`Maksimal ${MAX_PAGES} halaman per request`, 400); +// } +// } + +// interface ConversionResult { +// buffer: Buffer; +// text: string; +// density: number; +// width: number; +// height: number; +// } + +// // Fungsi untuk validasi dan fetch PDF +// async function fetchPDF(url: string) { +// const controller = new AbortController(); +// const timeout = setTimeout(() => controller.abort(), 10000); + +// try { +// // Validasi URL +// const validUrl = new URL(url); +// if (!validUrl.protocol.startsWith('http')) { +// throw new PDFConversionError('URL tidak valid', 400); +// } + +// const response = await fetch(url, { +// signal: controller.signal, +// headers: { +// 'Accept': 'application/pdf', +// 'User-Agent': 'Mozilla/5.0 (compatible; PDFConverter/1.0)' +// } +// }); + +// if (!response.ok) { +// throw new PDFConversionError( +// `Gagal mengakses PDF: ${response.status} ${response.statusText}`, +// response.status +// ); +// } + +// const contentType = response.headers.get('content-type'); +// if (!contentType?.includes('pdf')) { +// throw new PDFConversionError('URL bukan file PDF', 400); +// } + +// return response; + +// } catch (error: unknown) { +// if (error instanceof PDFConversionError) throw error; +// if (error instanceof Error && error.name === 'AbortError') { +// throw new PDFConversionError('Timeout saat mengunduh PDF', 504); +// } +// const message = error instanceof Error ? error.message : 'Unknown error'; +// throw new PDFConversionError('Gagal mengunduh PDF: ' + message, 500); +// } finally { +// clearTimeout(timeout); +// } +// } + +// // Tambahkan error SVG template +// const errorImageSvg = ` +// +// +// +// +// +// PDF Conversion Failed +// +// `; + +// // Tambahkan SVG untuk end of page +// const endOfPageSvg = ` +// +// +// +// End of PDF +// +// +// No more pages available +// +// +// `; + +// // Fungsi helper untuk set common headers +// function setCommonHeaders(headers: Headers) { +// headers.set('Access-Control-Allow-Origin', '*'); +// headers.set('Access-Control-Allow-Methods', 'GET, OPTIONS'); +// headers.set('Content-Security-Policy', "default-src 'self'; img-src 'self' data: blob:;"); +// headers.set('X-Content-Type-Options', 'nosniff'); +// } + +// // Fungsi helper untuk return error image +// function returnErrorImage(message: string = 'Conversion failed') { +// const response = new NextResponse(errorImageSvg, { +// headers: { +// 'Content-Type': 'image/svg+xml', +// 'Cache-Control': 'no-store', +// 'X-Error-Message': message +// } +// }); +// setCommonHeaders(response.headers); +// return response; +// } + +// // Fungsi helper untuk return end of page image +// function returnEndOfPageImage() { +// const response = new NextResponse(endOfPageSvg, { +// headers: { +// 'Content-Type': 'image/svg+xml', +// 'Cache-Control': 'public, max-age=31536000', +// 'X-Error-Message': 'End of PDF pages' +// } +// }); +// setCommonHeaders(response.headers); +// return response; +// } + +// // Fungsi untuk get total pages menggunakan pdf-lib +// async function getPDFPageCount(buffer: Buffer): Promise { +// try { +// const pdfDoc = await PDFDocument.load(buffer); +// return pdfDoc.getPageCount(); +// } catch (error) { +// console.error('Error getting PDF page count:', error); +// throw new Error('Failed to get PDF page count'); +// } +// } + +// export async function GET(request: Request) { +// let pdfBuffer: Buffer | null = null; +// const { searchParams } = new URL(request.url); + +// try { +// // Validasi parameter wajib +// const pdfUrl = searchParams.get('url'); +// if (!pdfUrl) { +// return NextResponse.json({ +// error: 'URL parameter wajib diisi' +// }, { status: 400 }); +// } + +// // Decode URL jika perlu +// const decodedUrl = decodeURIComponent(pdfUrl); + +// await checkDependencies(); + +// const getTotalPages = searchParams.get('total') === 'true'; + +// // Single fetch PDF dengan URL yang sudah di-decode +// const pdfResponse = await fetchPDF(decodedUrl); + +// const arrayBuffer = await pdfResponse.arrayBuffer(); +// pdfBuffer = Buffer.from(arrayBuffer); + +// // Get total pages +// if (getTotalPages) { +// try { +// const pageCount = await getPDFPageCount(pdfBuffer); +// return Response.json({ +// totalPages: pageCount, +// message: 'Success get total pages' +// }); +// } catch (error) { +// console.error('PDF parse error:', error); +// return Response.json({ +// error: 'Gagal membaca total halaman PDF', +// totalPages: 0 +// }, { status: 500 }); +// } +// } + +// // Parse page parameter dengan lebih baik +// const pageStr = searchParams.get('page'); +// let pageNum = 1; // Default ke halaman 1 + +// if (pageStr) { +// pageNum = parseInt(pageStr); +// if (isNaN(pageNum) || pageNum < 1) { +// return returnErrorImage('Invalid page number'); +// } + +// // Validasi halaman tidak melebihi total +// const totalPages = await getPDFPageCount(pdfBuffer); +// if (pageNum > totalPages) { +// return returnEndOfPageImage(); +// } +// } + +// const options = { +// density: 300, +// format: "png", +// width: Math.min(1200, MAX_IMAGE_DIMENSION), +// height: Math.min(1700, MAX_IMAGE_DIMENSION), +// preserveAspectRatio: true, +// saveFilename: "", +// savePath: "", +// returnBuffer: true +// }; + +// // Konversi single page +// const convert = fromBuffer(pdfBuffer, options); +// const result = await Promise.race([ +// convert(pageNum, { responseType: "buffer" }), +// new Promise((_, reject) => +// setTimeout(() => reject(new PDFConversionError('Konversi timeout', 504)), +// CONVERSION_TIMEOUT_MS) +// ) +// ]) as ConversionResult; + +// if (!result?.buffer) { +// return returnErrorImage('Konversi gagal: tidak ada output'); +// } + +// // Return image buffer +// const response = new NextResponse(result.buffer, { +// headers: { +// 'Content-Type': 'image/png', +// 'Content-Length': result.buffer.length.toString(), +// 'Cache-Control': 'public, max-age=31536000' +// } +// }); +// setCommonHeaders(response.headers); +// return response; + +// } catch (error) { +// console.error('PDF conversion error:', error); + +// // Return appropriate error response +// const errorMessage = error instanceof Error ? error.message : 'Unknown error'; +// const statusCode = error instanceof PDFConversionError ? error.statusCode : 500; + +// return !searchParams.get('pages') ? +// returnErrorImage(errorMessage) : +// NextResponse.json({ error: errorMessage }, { status: statusCode }); +// } finally { +// pdfBuffer = null; +// } +// } \ No newline at end of file diff --git a/src/app/dev/admin/investasi/konfirmasi/[id]/page.tsx b/src/app/dev/admin/investasi/konfirmasi/[id]/page.tsx index 533187e5..b31fb4a0 100644 --- a/src/app/dev/admin/investasi/konfirmasi/[id]/page.tsx +++ b/src/app/dev/admin/investasi/konfirmasi/[id]/page.tsx @@ -1,14 +1,9 @@ import { Admin_KonfirmasiInvestasi } from "@/app_modules/admin/investasi"; -import { adminInvestasi_getOneById } from "@/app_modules/admin/investasi/fun"; export default async function Page() { - // const investasiId = params.id; - // const dataInvestasi = await adminInvestasi_getOneById({investasiId}); - // console.log(dataUser) - return ( <> - + > ); } diff --git a/src/app/dev/investasi/file-view/dokumen/[id]/page.tsx b/src/app/dev/investasi/file-view/dokumen/[id]/page.tsx index 446fef71..22aa6e7c 100644 --- a/src/app/dev/investasi/file-view/dokumen/[id]/page.tsx +++ b/src/app/dev/investasi/file-view/dokumen/[id]/page.tsx @@ -1,11 +1,9 @@ import { Investasi_UiFileViewDokumen } from "@/app_modules/investasi/_ui"; -export default async function Page({ params }: { params: { id: string } }) { - const dokumenId = params.id; - +export default async function Page() { return ( <> - + > ); } diff --git a/src/app/dev/investasi/file-view/prospektus/[id]/page.tsx b/src/app/dev/investasi/file-view/prospektus/[id]/page.tsx index 25de80fd..dd56c9a0 100644 --- a/src/app/dev/investasi/file-view/prospektus/[id]/page.tsx +++ b/src/app/dev/investasi/file-view/prospektus/[id]/page.tsx @@ -1,12 +1,9 @@ -import { investasi_funGetProspekById } from "@/app_modules/investasi/_fun"; import { Investasi_UiFileView } from "@/app_modules/investasi/_ui"; -export default async function Page({ params }: { params: { id: string } }) { - const pospektusId = params.id; - +export default async function Page() { return ( <> - + > ); } diff --git a/src/app/dev/investasi/main/page.tsx b/src/app/dev/investasi/main/page.tsx index 7951c323..e168b7bb 100644 --- a/src/app/dev/investasi/main/page.tsx +++ b/src/app/dev/investasi/main/page.tsx @@ -1,11 +1,8 @@ import { Investasi_ViewBerandaNew } from "@/app_modules/investasi/_ui"; export default async function Page() { - // const allData = await investasi_funGetAllPublish({ page: 1 }); - return ( <> - {/* */} > ); diff --git a/src/app/dev/profile/upload/background/[id]/page.tsx b/src/app/dev/profile/upload/background/[id]/page.tsx index ef64703e..35367183 100644 --- a/src/app/dev/profile/upload/background/[id]/page.tsx +++ b/src/app/dev/profile/upload/background/[id]/page.tsx @@ -1,12 +1,9 @@ -import { Profile_getOneById } from "@/app_modules/katalog/profile/fun/get/get_one_profile" import Profile_UpdateFotoBackground from "@/app_modules/katalog/profile/upload/foto_background" -export default async function Page({params}:{params: {id: string}}) { - let profileId = params.id - const dataProfile = await Profile_getOneById(profileId) - - return <> - +export default async function Page() { + return ( + <> + > - -} \ No newline at end of file + ); +} diff --git a/src/app/dev/profile/upload/foto/[id]/page.tsx b/src/app/dev/profile/upload/foto/[id]/page.tsx index b36862ab..66ced2af 100644 --- a/src/app/dev/profile/upload/foto/[id]/page.tsx +++ b/src/app/dev/profile/upload/foto/[id]/page.tsx @@ -1,13 +1,9 @@ import { UploadFotoProfile } from "@/app_modules/katalog/profile"; -import { Profile_getOneById } from "@/app_modules/katalog/profile/fun/get/get_one_profile"; - -export default async function Page({ params }: { params: { id: string } }) { - let profileId = params.id; - const dataProfile = await Profile_getOneById(profileId); +export default async function Page() { return ( <> - + > ); } diff --git a/src/app/zCoba/pdf/_view.tsx b/src/app/zCoba/pdf/_view.tsx new file mode 100644 index 00000000..fc7378ef --- /dev/null +++ b/src/app/zCoba/pdf/_view.tsx @@ -0,0 +1,46 @@ +"use client"; + +import { Button } from "@mantine/core"; + +interface DownloadButtonProps { + fileUrl: string; + fileName: string; +} + +export default function Coba() { + const fileUrl = + "https://wibu-storage.wibudev.com/api/pdf-to-image?url=https://wibu-storage.wibudev.com/api/files/cm7liew81000t3y8ax1v6yo02"; + const fileName = "example.pdf"; // Nama file yang akan diunduh + + return ( + + Download File Example + + + ); +} + +export function DownloadButton({ fileUrl, fileName }: DownloadButtonProps) { + const handleDownloadFromAPI = async () => { + try { + const response = await fetch("https://wibu-storage.wibudev.com/api/files/cm7liew81000t3y8ax1v6yo02") + const blob = await response.blob(); // Konversi respons ke Blob + const url = window.URL.createObjectURL(blob); // Buat URL untuk Blob + const link = document.createElement("a"); + link.href = url; + link.download = "generated-file.pdf"; // Nama file yang akan diunduh + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + window.URL.revokeObjectURL(url); // Bersihkan URL + } catch (error) { + console.error("Error downloading file:", error); + } + }; + + return ( + + Download File + + ); +} diff --git a/src/app/zCoba/pdf/page.tsx b/src/app/zCoba/pdf/page.tsx new file mode 100644 index 00000000..a645fa5d --- /dev/null +++ b/src/app/zCoba/pdf/page.tsx @@ -0,0 +1,13 @@ +import Coba from "./_view"; + + + +async function Page() { + return ( + <> + + > + ); +} + +export default Page; diff --git a/src/app_modules/_global/lib/api_fetch_global.ts b/src/app_modules/_global/lib/api_fetch_global.ts new file mode 100644 index 00000000..c07ee4a6 --- /dev/null +++ b/src/app_modules/_global/lib/api_fetch_global.ts @@ -0,0 +1,52 @@ +export { apiGetPdfToImage }; + +export interface PageData { + imageUrl: string; + pageNumber: number; +} + +interface PdfResponse { + pages: PageData[]; + totalPages: number; +} +const apiGetPdfToImage = async ({ id }: { id: 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; + // } + + const token = + "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjp7ImlkIjoiY20wdXIxeXh3MDAwMDU2bnNqbHI2MTg3cCIsIm5hbWUiOiJiYWdhcyIsImVtYWlsIjoiYmFnYXNAZ21haWwuY29tIn0sImlhdCI6MTcyNTg3MTAzNiwiZXhwIjo0ODgxNjMxMDM2fQ.wFQLcrJj66wFeqIMYk2esMx3ULaHK6RFxkiToaLCuko"; + + // Anda bisa menggunakan prospektusId di URL jika diperlukan + const pdfUrl = `https://wibu-storage.wibudev.com/api/pdf-to-image?url=https://wibu-storage.wibudev.com/api/files/${id}`; + + const response = await fetch(pdfUrl, { + method: "GET", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${token}`, + }, + }); + + // Check if the response is OK + if (!response.ok) { + const errorData = await response.json().catch(() => null); + console.error( + "Error get admin contact:", + errorData?.message || "Unknown error" + ); + + return null; + } + + const jsonData: PdfResponse = await response.json(); + return jsonData; + } catch (error) { + console.error("Error get admin contact:", error); + throw error; // Re-throw the error to handle it in the calling function + } +}; diff --git a/src/app_modules/admin/investasi/_component/ui_detail_file.tsx b/src/app_modules/admin/investasi/_component/ui_detail_file.tsx index f0780e28..b9727556 100644 --- a/src/app_modules/admin/investasi/_component/ui_detail_file.tsx +++ b/src/app_modules/admin/investasi/_component/ui_detail_file.tsx @@ -11,6 +11,7 @@ import { Group, Button, Text, + Box, } from "@mantine/core"; import { IconFileTypePdf } from "@tabler/icons-react"; import _ from "lodash"; @@ -73,7 +74,7 @@ export function ComponentAdminInvestasi_UIDetailFile({ - ) : ( listDokumen.map((e: MODEL_INVESTASI_DOKUMEN) => ( - + {e.title} @@ -84,7 +85,7 @@ export function ComponentAdminInvestasi_UIDetailFile({ Lihat - + )) )} diff --git a/src/app_modules/admin/investasi/detail/detail_review.tsx b/src/app_modules/admin/investasi/detail/detail_review.tsx index df0992c3..e73ac196 100644 --- a/src/app_modules/admin/investasi/detail/detail_review.tsx +++ b/src/app_modules/admin/investasi/detail/detail_review.tsx @@ -1,10 +1,10 @@ "use client"; -import { IRealtimeData } from "@/lib/global_state"; import { MainColor } from "@/app_modules/_global/color"; import { MODEL_INVESTASI } from "@/app_modules/investasi/_lib/interface"; -import getOneInvestasiById from "@/app_modules/investasi/fun/get_one_investasi_by_id"; -import { Button, Group, SimpleGrid, Stack, Loader } from "@mantine/core"; +import { IRealtimeData } from "@/lib/global_state"; +import { clientLogger } from "@/util/clientLogger"; +import { Button, Group, SimpleGrid, Stack } from "@mantine/core"; import { useShallowEffect } from "@mantine/hooks"; import _ from "lodash"; import { useParams, useRouter } from "next/navigation"; @@ -20,12 +20,11 @@ import adminNotifikasi_funCreateToUser from "../../notifikasi/fun/create/fun_cre import { ComponentAdminInvestasi_DetailDataAuthor } from "../_component/detail_data_author"; import { ComponentAdminInvestasi_DetailData } from "../_component/detail_data_investasi"; import { ComponentAdminInvestasi_DetailGambar } from "../_component/detail_gambar_investasi"; +import SkeletonAdminInvestasi from "../_component/skeleton_admin_investasi"; import { ComponentAdminInvestasi_UIDetailFile } from "../_component/ui_detail_file"; +import { apiGetAdminInvestasiById } from "../_lib/api_fetch_admin_investasi"; import { adminInvestasi_funEditStatusPublishById } from "../fun/edit/fun_status_publish_by_id"; import Admin_funRejectInvestasi from "../fun/fun_reject_investasi"; -import { clientLogger } from "@/util/clientLogger"; -import { apiGetAdminInvestasiById } from "../_lib/api_fetch_admin_investasi"; -import SkeletonAdminInvestasi from "../_component/skeleton_admin_investasi"; export default function AdminInvestasi_DetailReview() { const params = useParams<{ id: string }>(); @@ -45,19 +44,19 @@ export default function AdminInvestasi_DetailReview() { }, []); const loadInitialData = async () => { - try { - const response = await apiGetAdminInvestasiById({ - id: params.id, - }) + try { + const response = await apiGetAdminInvestasiById({ + id: params.id, + }); - if (response?.success && response?.data) { - setData(response.data); + if (response?.success && response?.data) { + setData(response.data); + } + } catch (error) { + clientLogger.error("Invalid data format recieved:", error); + setData(null); } - } catch (error) { - clientLogger.error("Invalid data format recieved:", error); - setData(null); - } -} + }; async function cekStatusPublish() { if (data?.MasterStatusInvestasi.id === "3") setPublish(false); @@ -72,98 +71,106 @@ export default function AdminInvestasi_DetailReview() { if (_.isEmpty(body.catatan)) return ComponentAdminGlobal_NotifikasiPeringatan("Lengkapi alasan"); - const res = await Admin_funRejectInvestasi(body); - if (res.status === 200) { + try { setIsLoadingReject(true); + const res = await Admin_funRejectInvestasi(body); + if (res.status === 200) { + const dataNotifikasi: IRealtimeData = { + appId: res.data?.id as string, + userId: res.data?.authorId as string, + pesan: res.data?.title as string, + status: res.data?.MasterStatusInvestasi?.name as any, + kategoriApp: "INVESTASI", + title: "Investasi anda di tolak !", + }; - const dataNotifikasi: IRealtimeData = { - appId: res.data?.id as string, - userId: res.data?.authorId as string, - pesan: res.data?.title as string, - status: res.data?.MasterStatusInvestasi?.name as any, - kategoriApp: "INVESTASI", - title: "Investasi anda di tolak !", - }; - - const notif = await adminNotifikasi_funCreateToUser({ - data: dataNotifikasi as any, - }); - - if (notif.status === 201) { - WibuRealtime.setData({ - type: "notification", - pushNotificationTo: "USER", - dataMessage: dataNotifikasi, + const notif = await adminNotifikasi_funCreateToUser({ + data: dataNotifikasi as any, }); + + if (notif.status === 201) { + WibuRealtime.setData({ + type: "notification", + pushNotificationTo: "USER", + dataMessage: dataNotifikasi, + }); + } + + ComponentAdminGlobal_NotifikasiBerhasil(res.message); + router.back(); + setOpenModalReject(false); + setIsLoadingReject(false); + } else { + ComponentAdminGlobal_NotifikasiGagal(res.message); + setOpenModalReject(false); + setIsLoadingReject(false); } - - // const loadData = await getOneInvestasiById(data?.id); - // setData(loadData as any); - - ComponentAdminGlobal_NotifikasiBerhasil(res.message); - router.back(); + } catch (error) { + console.log(error); setOpenModalReject(false); setIsLoadingReject(false); - } else { - ComponentAdminGlobal_NotifikasiGagal(res.message); - setOpenModalReject(false); } } async function onPublish() { - const res = await adminInvestasi_funEditStatusPublishById({ - investasiId: data?.id as any, - statusId: "1", - progesInvestasiId: "1", - }); - if (res.status === 200) { + try { setIsLoadingPublish(true); - const dataNotifikasi: IRealtimeData = { - appId: res.data?.id as string, - userId: res.data?.authorId as any, - pesan: res.data?.title as any, - status: res.data?.MasterStatusInvestasi?.name as any, - kategoriApp: "INVESTASI", - title: "Investasi publish", - }; - - const notif = await adminNotifikasi_funCreateToUser({ - data: dataNotifikasi as any, + const res = await adminInvestasi_funEditStatusPublishById({ + investasiId: data?.id as any, + statusId: "1", + progesInvestasiId: "1", }); + if (res.status === 200) { + const dataNotifikasi: IRealtimeData = { + appId: res.data?.id as string, + userId: res.data?.authorId as any, + pesan: res.data?.title as any, + status: res.data?.MasterStatusInvestasi?.name as any, + kategoriApp: "INVESTASI", + title: "Investasi publish", + }; - if (notif.status === 201) { - WibuRealtime.setData({ - type: "notification", - pushNotificationTo: "USER", - dataMessage: dataNotifikasi, + const notif = await adminNotifikasi_funCreateToUser({ + data: dataNotifikasi as any, }); - WibuRealtime.setData({ - type: "trigger", - pushNotificationTo: "USER", - dataMessage: dataNotifikasi, - }); + if (notif.status === 201) { + WibuRealtime.setData({ + type: "notification", + pushNotificationTo: "USER", + dataMessage: dataNotifikasi, + }); - const loadData = await getOneInvestasiById(data?.id as any); - setData(loadData as any); + WibuRealtime.setData({ + type: "trigger", + pushNotificationTo: "USER", + dataMessage: dataNotifikasi, + }); - ComponentAdminGlobal_NotifikasiBerhasil("Proyek Investasi Di Publish"); + ComponentAdminGlobal_NotifikasiBerhasil( + "Proyek Investasi Di Publish" + ); + setOpenModalPublish(false); + setIsLoadingPublish(false); + router.back(); + // router.push(RouterAdminInvestasi_OLD.table_status_review); + } + } else { + ComponentAdminGlobal_NotifikasiGagal(res.message); setOpenModalPublish(false); setIsLoadingPublish(false); - router.back(); - // router.push(RouterAdminInvestasi_OLD.table_status_review); } - } else { - ComponentAdminGlobal_NotifikasiGagal(res.message); + } catch (error) { + console.log(error); setOpenModalPublish(false); + setIsLoadingPublish(false); } } if (!data) { - return + return ; } - return ( <> @@ -173,8 +180,6 @@ export default function AdminInvestasi_DetailReview() { {data?.masterStatusInvestasiId === "2" ? ( setOpenModalPublish(true)} @@ -204,7 +209,9 @@ export default function AdminInvestasi_DetailReview() { ]} > {/* Data Author */} - + {/* Data Foto */} @@ -257,8 +264,8 @@ export default function AdminInvestasi_DetailReview() { buttonKanan={ { onPublish(); diff --git a/src/app_modules/crowd/main/view.tsx b/src/app_modules/crowd/main/view.tsx index 4284d299..8886cdcc 100644 --- a/src/app_modules/crowd/main/view.tsx +++ b/src/app_modules/crowd/main/view.tsx @@ -55,12 +55,8 @@ export default function MainCrowd() { }} onClick={() => { setLoadingInv(true); - router.push(RouterCrowd.investasi); + router.push(RouterCrowd.investasi, { scroll: false }); setChangeColor(0); - // ComponentGlobal_NotifikasiPeringatan( - // "Sedang Perbaikan", - // 3000 - // ); }} > @@ -99,7 +95,7 @@ export default function MainCrowd() { }} onClick={() => { setLoadingDon(true); - router.push(RouterCrowd.donasi); + router.push(RouterCrowd.donasi, { scroll: false }); setDonasiHotMenu(0); // ComponentGlobal_NotifikasiPeringatan( // "Sementara ini sedang maintenance", diff --git a/src/app_modules/home/fun/get/api_home.ts b/src/app_modules/home/fun/get/api_home.ts index 8600b3aa..c9c58610 100644 --- a/src/app_modules/home/fun/get/api_home.ts +++ b/src/app_modules/home/fun/get/api_home.ts @@ -1,17 +1,73 @@ export const apiGetDataHome = async ({ path }: { path?: string }) => { - const { token } = await fetch("/api/get-cookie").then((res) => res.json()); - if (!token) return await token.json().catch(() => null); + // Fetch token from cookie + try { + const { token } = await fetch("/api/get-cookie").then((res) => res.json()); + if (!token) { + console.error("No token found"); + return 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}`, - }, - }); + const response = await fetch(`/api/new/home${path ? path : ""}`, { + headers: { + "Content-Type": "application/json", + Accept: "application/json", + Authorization: `Bearer ${token}`, + }, + }); - if (!response.ok) return null; - const data: Record = await response.json(); - return data; + // if (!response.ok) return null; + // const data: Record = await response.json(); + // return data; + + if (!response.ok) { + const errorData = await response.json().catch(() => null); + console.error( + "Error get admin contact:", + errorData?.message || "Unknown error" + ); + + return null; + } + + const result = await response.json(); + return result; + } catch (error) { + console.error("Error get admin contact:", error); + throw error; // Re-throw the error to handle it in the calling function + } +}; + +export const apiGetNotifikasiHome = async () => { + // Fetch token from cookie + try { + const { token } = await fetch("/api/get-cookie").then((res) => res.json()); + if (!token) { + console.error("No token found"); + return null; + } + + const response = await fetch(`/api/notifikasi/count`, { + headers: { + "Content-Type": "application/json", + Accept: "application/json", + Authorization: `Bearer ${token}`, + }, + }); + + if (!response.ok) { + const errorData = await response.json().catch(() => null); + console.error( + "Error get admin contact:", + errorData?.message || "Unknown error" + ); + + return null; + } + + const result = await response.json(); + return result; + } catch (error) { + console.error("Error get admin contact:", error); + throw error; // Re-throw the error to handle it in the calling function + } }; diff --git a/src/app_modules/home/view_home_new.tsx b/src/app_modules/home/view_home_new.tsx index 71ece24a..fad2762c 100644 --- a/src/app_modules/home/view_home_new.tsx +++ b/src/app_modules/home/view_home_new.tsx @@ -1,5 +1,4 @@ "use client"; -import { API_RouteNotifikasi } from "@/lib/api_user_router/route_api_notifikasi"; import { gs_count_ntf, gs_user_ntf } from "@/lib/global_state"; import global_limit from "@/lib/limit"; import { RouterProfile } from "@/lib/router_hipmi/router_katalog"; @@ -18,7 +17,7 @@ import UIGlobal_LayoutTamplate from "../_global/ui/ui_layout_tamplate"; import { gs_notifikasi_kategori_app } from "../notifikasi/lib"; import BodyHome from "./component/body_home"; import FooterHome from "./component/footer_home"; -import { apiGetDataHome } from "./fun/get/api_home"; +import { apiGetDataHome, apiGetNotifikasiHome } from "./fun/get/api_home"; export default function HomeViewNew() { const [countNtf, setCountNtf] = useAtom(gs_count_ntf); @@ -53,9 +52,10 @@ export default function HomeViewNew() { async function onLoadNotifikasi() { try { - const loadNotif = await fetch(API_RouteNotifikasi.get_count_by_id()); - const data = await loadNotif.json().then((res) => res.data); - setCountNtf(data); + const response = await apiGetNotifikasiHome(); + if (response && response.success) { + setCountNtf(response.data); + } } catch (error) { clientLogger.error("Error load notifikasi", error); } @@ -66,11 +66,14 @@ export default function HomeViewNew() { const response = await apiGetDataHome({ path: "?cat=cek_profile", }); - if (response) { + if (response && response.success) { setDataUser(response.data); + } else { + setDataUser(null); } } catch (error) { clientLogger.error("Error get data home", error); + setDataUser(null); } } @@ -83,7 +86,7 @@ export default function HomeViewNew() { customButtonLeft={ !dataUser || !countNtf ? ( - + ) : dataUser?.profile === undefined ? ( - + ) : dataUser?.profile === undefined ? ( { - router.push( - NEW_RouterInvestasi.file_prospektus({ id: data.fileId }), - { scroll: false } - ); + router.push(NEW_RouterInvestasi.file_dokumen({ id: data.fileId }), { + scroll: false, + }); setVisible(true); }} > diff --git a/src/app_modules/investasi/_component/detail/comp_card_rekap_document.tsx b/src/app_modules/investasi/_component/detail/comp_card_rekap_document.tsx index b2727e20..9bfa2458 100644 --- a/src/app_modules/investasi/_component/detail/comp_card_rekap_document.tsx +++ b/src/app_modules/investasi/_component/detail/comp_card_rekap_document.tsx @@ -97,7 +97,7 @@ export function Investasi_ComponentCardRekapDocument({ span={"auto"} onClick={() => { router.push( - NEW_RouterInvestasi.file_prospektus({ id: data.fileId }), + NEW_RouterInvestasi.file_dokumen({ id: data.fileId }), { scroll: false } ); setVisible(true); diff --git a/src/app_modules/investasi/_component/main/com_card_beranda_new.tsx b/src/app_modules/investasi/_component/main/com_card_beranda_new.tsx index a564c40b..dc5f2a3b 100644 --- a/src/app_modules/investasi/_component/main/com_card_beranda_new.tsx +++ b/src/app_modules/investasi/_component/main/com_card_beranda_new.tsx @@ -1,109 +1,141 @@ import { NEW_RouterInvestasi } from "@/lib/router_hipmi/router_investasi"; import { Warna } from "@/lib/warna"; import { MainColor } from "@/app_modules/_global/color/color_pallet"; -import { ComponentGlobal_CardStyles, ComponentGlobal_LoadImageCustom } from "@/app_modules/_global/component"; +import { + ComponentGlobal_CardStyles, + ComponentGlobal_LoadImageCustom, +} from "@/app_modules/_global/component"; import { Box, Grid, Group, Progress, Stack, Text } from "@mantine/core"; import { IconCircleCheck, IconXboxX } from "@tabler/icons-react"; import moment from "moment"; import { useRouter } from "next/navigation"; import { IDataInvestasiBursa } from "../../_lib/type_investasi"; -export function Investasi_ComponentCardBerandaNew({ data }: { data: IDataInvestasiBursa; }) { - const router = useRouter() +export function Investasi_ComponentCardBerandaNew({ + data, +}: { + data: IDataInvestasiBursa; +}) { + const router = useRouter(); - return ( - <> - { - router.push(NEW_RouterInvestasi.detail_main({ id: data.id }), { - scroll: false, - }); - }} - > - - - - - - - - - {data?.title} - + return ( + <> + { + router.push(NEW_RouterInvestasi.detail_main({ id: data.id }), { + scroll: false, + }); + }} + > + + + + + + + + + {data?.title} + - - - {data?.progress === "100" ? ( - - - - Selesai - - - ) : ( - - {+data?.pencarianInvestor - - moment(new Date()).diff( - new Date(data?.countDown), - "days" - ) <= - 0 ? ( - - - - Waktu Habis - - - ) : ( - - Sisa waktu: - - {Number(data?.pencarianInvestor) - - moment(new Date()).diff( - new Date(data?.countDown), - "days" - )} - - Hari - - )} - - )} + + + + {data?.progress === "100" ? ( + + + + Selesai + + + ) : ( + + {+data?.pencarianInvestor - + moment(new Date()).diff( + new Date(data?.countDown), + "days" + ) <= + 0 ? ( + + + + Waktu Habis + - - - - - - > - ); + ) : ( + + + Sisa waktu: + + + {Number(data?.pencarianInvestor) - + moment(new Date()).diff( + new Date(data?.countDown), + "days" + )} + + + Hari + + + )} + + )} + + + + + + + > + ); } diff --git a/src/app_modules/investasi/_ui/file_view/ui_file_view_dokumen.tsx b/src/app_modules/investasi/_ui/file_view/ui_file_view_dokumen.tsx index c29c745b..a145b8c8 100644 --- a/src/app_modules/investasi/_ui/file_view/ui_file_view_dokumen.tsx +++ b/src/app_modules/investasi/_ui/file_view/ui_file_view_dokumen.tsx @@ -1,31 +1,141 @@ "use client"; -import { APIs } from "@/lib"; +import { MainColor } from "@/app_modules/_global/color"; +import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data"; +import { + apiGetPdfToImage, + PageData, +} from "@/app_modules/_global/lib/api_fetch_global"; +import { UIGlobal_DrawerCustom } from "@/app_modules/_global/ui"; import UIGlobal_LayoutHeaderTamplate from "@/app_modules/_global/ui/ui_header_tamplate"; import UIGlobal_LayoutTamplate from "@/app_modules/_global/ui/ui_layout_tamplate"; -import { Box } from "@mantine/core"; -import { IconX } from "@tabler/icons-react"; -import dynamic from "next/dynamic"; -const PdfToImage = dynamic( - () => - import("../../_view/file_view/view_file_viewer").then((mod) => mod.default), - { ssr: false } -); +import CustomSkeleton from "@/app_modules/components/CustomSkeleton"; +import { ActionIcon, Box, Stack, Text } from "@mantine/core"; +import { IconDotsVertical, IconDownload, IconX } from "@tabler/icons-react"; +import Image from "next/image"; +import { useParams } from "next/navigation"; +import { useEffect, useRef, useState } from "react"; + +export function Investasi_UiFileViewDokumen() { + const param = useParams<{ id: string }>(); + const dokumenId = param.id; + + const [pdfPages, setPdfPages] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + const pdfsRef = useRef(null); + const [isOpen, setOpen] = useState(false); + + useEffect(() => { + const fetchPdfData = async () => { + try { + setLoading(true); + const response = await apiGetPdfToImage({ id: dokumenId }); + + if (response) { + setPdfPages(response.pages as any); + setLoading(false); + } + } catch (err) { + console.error("Error fetching PDF:", err); + setError(err instanceof Error ? err.message : "Unknown error occurred"); + setLoading(false); + } + }; + + fetchPdfData(); + }, [dokumenId]); + + const handleDownloadFromAPI = async () => { + try { + const response = await fetch( + `https://wibu-storage.wibudev.com/api/files/${dokumenId}` + ); + const blob = await response.blob(); // Konversi respons ke Blob + const url = window.URL.createObjectURL(blob); // Buat URL untuk Blob + const link = document.createElement("a"); + link.href = url; + link.download = `file-dokumen-${new Date()}.pdf`; // Nama file yang akan diunduh + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + window.URL.revokeObjectURL(url); // Bersihkan URL + } catch (error) { + console.error("Error downloading file:", error); + } + }; -export function Investasi_UiFileViewDokumen({ - dokumenId, -}: { - dokumenId: string; -}) { return ( <> } />} + header={ + } + customButtonRight={ + { + setOpen(true); + }} + > + + + } + /> + } > - - + + {loading ? ( + + ) : error ? ( + + + + + ) : ( + + {pdfPages?.map((page, index) => ( + + ))} + + )} + + setOpen(false)} + opened={isOpen} + component={ + + + + + + Download + + + } + /> > ); } diff --git a/src/app_modules/investasi/_ui/file_view/ui_file_view_prospektus.tsx b/src/app_modules/investasi/_ui/file_view/ui_file_view_prospektus.tsx index adb3cae5..84ffa0c2 100644 --- a/src/app_modules/investasi/_ui/file_view/ui_file_view_prospektus.tsx +++ b/src/app_modules/investasi/_ui/file_view/ui_file_view_prospektus.tsx @@ -1,35 +1,141 @@ "use client"; -import { APIs } from "@/lib"; -import { RouterInvestasi_OLD } from "@/lib/router_hipmi/router_investasi"; +import { MainColor } from "@/app_modules/_global/color"; +import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data"; +import { + apiGetPdfToImage, + PageData, +} from "@/app_modules/_global/lib/api_fetch_global"; +import { UIGlobal_DrawerCustom } from "@/app_modules/_global/ui"; import UIGlobal_LayoutHeaderTamplate from "@/app_modules/_global/ui/ui_header_tamplate"; import UIGlobal_LayoutTamplate from "@/app_modules/_global/ui/ui_layout_tamplate"; -import { Box } from "@mantine/core"; -import { IconX } from "@tabler/icons-react"; -import dynamic from "next/dynamic"; -const PdfToImage = dynamic( - () => - import("../../_view/file_view/view_file_viewer").then((mod) => mod.default), - { ssr: false } -); +import CustomSkeleton from "@/app_modules/components/CustomSkeleton"; +import { ActionIcon, Box, Stack, Text } from "@mantine/core"; +import { IconDotsVertical, IconDownload, IconX } from "@tabler/icons-react"; +import Image from "next/image"; +import { useParams } from "next/navigation"; +import { useEffect, useRef, useState } from "react"; + +export function Investasi_UiFileViewProspektus() { + const param = useParams<{ id: string }>(); + const prospektusId = param.id; + + const [pdfPages, setPdfPages] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + const pdfsRef = useRef(null); + const [isOpen, setOpen] = useState(false); + + useEffect(() => { + const fetchPdfData = async () => { + try { + setLoading(true); + const response = await apiGetPdfToImage({ id: prospektusId }); + + if (response) { + setPdfPages(response.pages as any); + setLoading(false); + } + } catch (err) { + console.error("Error fetching PDF:", err); + setError(err instanceof Error ? err.message : "Unknown error occurred"); + setLoading(false); + } + }; + + fetchPdfData(); + }, [prospektusId]); + + const handleDownloadFromAPI = async () => { + try { + const response = await fetch( + `https://wibu-storage.wibudev.com/api/files/${prospektusId}` + ); + const blob = await response.blob(); // Konversi respons ke Blob + const url = window.URL.createObjectURL(blob); // Buat URL untuk Blob + const link = document.createElement("a"); + link.href = url; + link.download = `file-portofolio-${new Date()}.pdf`; // Nama file yang akan diunduh + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + window.URL.revokeObjectURL(url); // Bersihkan URL + } catch (error) { + console.error("Error downloading file:", error); + } + }; -export function Investasi_UiFileViewProspektus({ - pospektusId, -}: { - pospektusId: string; -}) { return ( <> } />} - > - - } + customButtonRight={ + { + setOpen(true); + }} + > + + + } /> + } + > + + {loading ? ( + + ) : error ? ( + + + + + ) : ( + + {pdfPages?.map((page, index) => ( + + ))} + + )} + + setOpen(false)} + opened={isOpen} + component={ + + + + + + Download + + + } + /> > ); } diff --git a/src/app_modules/investasi/_view/main/view_beranda_new.tsx b/src/app_modules/investasi/_view/main/view_beranda_new.tsx index 187188ed..b2698f14 100644 --- a/src/app_modules/investasi/_view/main/view_beranda_new.tsx +++ b/src/app_modules/investasi/_view/main/view_beranda_new.tsx @@ -1,11 +1,12 @@ "use client"; -import { RouterInvestasi_OLD } from "@/lib/router_hipmi/router_investasi"; import ComponentGlobal_CreateButton from "@/app_modules/_global/component/button_create"; import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data"; import ComponentGlobal_Loader from "@/app_modules/_global/component/loader"; -import mqtt_client from "@/util/mqtt_client"; +import { gs_investasiTriggerBeranda } from "@/lib/global_state"; +import { RouterInvestasi_OLD } from "@/lib/router_hipmi/router_investasi"; import { Box, Center } from "@mantine/core"; import { useShallowEffect } from "@mantine/hooks"; +import { useAtom } from "jotai"; import _ from "lodash"; import { ScrollOnly } from "next-scroll-loader"; import { useState } from "react"; @@ -14,8 +15,6 @@ import { Investasi_ComponentCardBerandaNew } from "../../_component/main/com_car import { apiGetAllInvestasi } from "../../_lib/api_interface"; import { IDataInvestasiBursa } from "../../_lib/type_investasi"; import SkeletonInvestasiBursa from "./skeleton_beranda"; -import { useAtom } from "jotai"; -import { gs_investasiTriggerBeranda } from "@/lib/global_state"; export function Investasi_ViewBerandaNew() { const [data, setData] = useState([]); @@ -86,7 +85,7 @@ export function Investasi_ViewBerandaNew() { const loadData = await apiGetAllInvestasi( `?cat=bursa&page=${pageNew}` ); - setActivePage((val) => val + 1); + setActivePage(pageNew); return loadData.data as any; }} diff --git a/src/app_modules/investasi/create/view.tsx b/src/app_modules/investasi/create/view.tsx deleted file mode 100644 index 057162b4..00000000 --- a/src/app_modules/investasi/create/view.tsx +++ /dev/null @@ -1,396 +0,0 @@ -"use client"; - -import { MainColor } from "@/app_modules/_global/color/color_pallet"; -import { - ComponentGlobal_BoxInformation, - ComponentGlobal_BoxUploadImage, - ComponentGlobal_CardStyles, -} from "@/app_modules/_global/component"; -import { MODEL_DEFAULT_MASTER_OLD } from "@/app_modules/model_global/model_default_master"; -import { - AspectRatio, - Box, - Button, - Center, - FileButton, - Grid, - Group, - Image, - Select, - Stack, - Text, - TextInput, -} from "@mantine/core"; -import { - IconCamera, - IconCircleCheck, - IconFileTypePdf, - IconPdf, - IconUpload, -} from "@tabler/icons-react"; -import _ from "lodash"; -import { useState } from "react"; -import { Investasi_ComponentButtonCreateNewInvestasi } from "../_component"; - -export default function InvestasiCreate({ - pencarianInvestor, - periodeDeviden, - pembagianDeviden, -}: { - pencarianInvestor: MODEL_DEFAULT_MASTER_OLD[]; - periodeDeviden: MODEL_DEFAULT_MASTER_OLD[]; - pembagianDeviden: MODEL_DEFAULT_MASTER_OLD[]; -}) { - const [fileImage, setFileImage] = useState(null); - const [img, setImg] = useState(); - const [filePdf, setFilePdf] = useState(null); - const [fPdf, setFPdf] = useState(null); - const [totalLembar, setTotalLembar] = useState(0); - - const [value, setValue] = useState({ - title: "", - targetDana: 0, - hargaLembar: 0, - roi: 0, - pencarianInvestorId: "", - periodeDevidenId: "", - pembagianDevidenId: "", - }); - const [target, setTarget] = useState(""); - const [harga, setHarga] = useState(""); - - async function onTotalLembar({ - target, - harga, - }: { - target?: number | any; - harga?: number | any; - }) { - if (target !== 0 && harga !== 0) { - const hasil: any = target / harga; - setTotalLembar(_.floor(hasil === Infinity ? 0 : hasil)); - } - } - - return ( - <> - - {/* Upload Image */} - - - - - - {img ? ( - - - - ) : ( - - - - Upload Gambar - - - )} - - - {/* Upload Foto */} - - { - try { - const buffer = URL.createObjectURL( - new Blob([new Uint8Array(await files.arrayBuffer())]) - ); - - setImg(buffer); - setFileImage(files); - } catch (error) { - console.log(error); - } - }} - accept="image/png,image/jpeg" - > - {(props) => ( - } - radius={50} - bg={MainColor.yellow} - color="yellow" - c={"black"} - > - Upload Gambar - - )} - - - - - {/* Upload File */} - - - - {!filePdf ? ( - - Upload File Prospektus - - ) : ( - - - - - {filePdf.name} - - - - - - - - - )} - - - - { - try { - const buffer = URL.createObjectURL( - new Blob([new Uint8Array(await files.arrayBuffer())]) - ); - setFPdf(buffer); - setFilePdf(files); - } catch (error) { - console.log(error); - } - }} - > - {(props) => ( - } - {...props} - radius={"xl"} - bg={MainColor.yellow} - color="yellow" - c={"black"} - > - Upload File - - )} - - - - - - { - setValue({ - ...value, - title: val.target.value, - }); - }} - /> - - Rp.} - min={0} - withAsterisk - label="Dana Dibutuhkan" - placeholder="0" - value={target} - onChange={(val) => { - // console.log(typeof val) - const match = val.currentTarget.value - .replace(/\./g, "") - .match(/^[0-9]+$/); - - if (val.currentTarget.value === "") return setTarget(0 + ""); - if (!match?.[0]) return null; - - const nilai = val.currentTarget.value.replace(/\./g, ""); - const targetNilai = Intl.NumberFormat("id-ID").format(+nilai); - - onTotalLembar({ - target: +nilai, - harga: +value.hargaLembar, - }); - - setTarget(targetNilai); - setValue({ - ...value, - targetDana: +nilai, - }); - }} - /> - - Rp.} - min={0} - withAsterisk - label="Harga Per Lembar" - placeholder="0" - value={harga} - onChange={(val) => { - try { - // console.log(typeof +val.currentTarget.value); - - const match = val.currentTarget.value - .replace(/\./g, "") - .match(/^[0-9]+$/); - - if (val.currentTarget.value === "") return setHarga(0 + ""); - - if (!match?.[0]) return null; - - const nilai = val.currentTarget.value.replace(/\./g, ""); - const targetNilai = Intl.NumberFormat("id-ID").format(+nilai); - - onTotalLembar({ - harga: +nilai, - target: +value.targetDana, - }); - - setHarga(targetNilai); - setValue({ - ...value, - hargaLembar: +nilai, - }); - } catch (error) { - console.log(error); - } - }} - /> - - - - - % - - } - withAsterisk - type="number" - label={"Rasio Keuntungan / ROI %"} - placeholder="Masukan rasio keuntungan" - onChange={(val) => { - setValue({ - ...value, - roi: _.toNumber(val.target.value), - }); - }} - /> - - ({ - value: e.id, - label: e.name + " " + "hari", - }))} - onChange={(val) => { - setValue({ - ...(value as any), - pencarianInvestorId: val, - }); - }} - /> - - ({ value: e.id, label: e.name }))} - onChange={(val) => { - setValue({ - ...(value as any), - periodeDevidenId: val, - }); - }} - /> - - ({ - value: e.id, - label: e.name + " " + "bulan", - }))} - onChange={(val) => { - setValue({ - ...(value as any), - pembagianDevidenId: val, - }); - }} - /> - - - - - > - ); -} diff --git a/src/app_modules/investasi/create/view_new.tsx b/src/app_modules/investasi/create/view_new.tsx index b0f1c46e..67f5f722 100644 --- a/src/app_modules/investasi/create/view_new.tsx +++ b/src/app_modules/investasi/create/view_new.tsx @@ -6,17 +6,11 @@ import { ComponentGlobal_ButtonUploadFileImage, ComponentGlobal_CardStyles, } from "@/app_modules/_global/component"; -import { MAX_SIZE } from "@/app_modules/_global/lib"; -import { PemberitahuanMaksimalFile } from "@/app_modules/_global/lib/max_size"; -import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global"; import { AspectRatio, Box, - Button, Center, - FileButton, Grid, - Group, Image, Loader, Select, @@ -26,7 +20,6 @@ import { } from "@mantine/core"; import { useShallowEffect } from "@mantine/hooks"; import { - IconCamera, IconCircleCheck, IconFileTypePdf, IconPhoto, @@ -64,6 +57,7 @@ export default function InvestasiCreateNew() { const [isLoadingImg, setIsLoadingImg] = useState(false); const [isLoadingPdf, setIsLoadingPdf] = useState(false); + const [isMinimalTarget, setMinimalTarget] = useState(false); async function onTotalLembar({ target, @@ -162,48 +156,6 @@ export default function InvestasiCreateNew() { onSetImage={setImg} /> - {/* - { - try { - setIsLoadingImg(true); - const buffer = URL.createObjectURL( - new Blob([new Uint8Array(await files.arrayBuffer())]) - ); - - if (files.size > MAX_SIZE) { - ComponentGlobal_NotifikasiPeringatan( - PemberitahuanMaksimalFile - ); - setImg(null); - - return; - } - - setImg(buffer); - setFileImage(files); - } catch (error) { - console.log(error); - } finally { - setIsLoadingImg(false); - } - }} - accept="image/png,image/jpeg" - > - {(props) => ( - } - radius={50} - bg={MainColor.yellow} - color="yellow" - c={"black"} - > - Upload Gambar - - )} - - */} {/* Upload File */} @@ -244,48 +196,6 @@ export default function InvestasiCreateNew() { icon={} /> - {/* - { - try { - setIsLoadingPdf(true); - const buffer = URL.createObjectURL( - new Blob([new Uint8Array(await files.arrayBuffer())]) - ); - - if (files.size > MAX_SIZE) { - ComponentGlobal_NotifikasiPeringatan( - PemberitahuanMaksimalFile - ); - setFilePdf(null); - - return; - } - - setFPdf(buffer); - setFilePdf(files); - } catch (error) { - console.log(error); - } finally { - setIsLoadingPdf(false); - } - }} - > - {(props) => ( - } - {...props} - radius={"xl"} - bg={MainColor.yellow} - color="yellow" - c={"black"} - > - Upload File - - )} - - */} @@ -313,48 +223,62 @@ export default function InvestasiCreateNew() { }} /> - Rp.} - min={0} - withAsterisk - label="Dana Dibutuhkan" - placeholder="0" - value={target} - onChange={(val) => { - // console.log(typeof val) - const match = val.currentTarget.value - .replace(/\./g, "") - .match(/^[0-9]+$/); + + Rp.} + min={0} + withAsterisk + label="Dana Dibutuhkan" + placeholder="0" + value={target} + error={isMinimalTarget ? "Minimal target 10.000.000" : ""} + onChange={(val) => { + // console.log(typeof val) + const match = val.currentTarget.value + .replace(/\./g, "") + .match(/^[0-9]+$/); - if (val.currentTarget.value === "") return setTarget(0 + ""); - if (!match?.[0]) return null; + if (val.currentTarget.value === "") return setTarget(0 + ""); + if (!match?.[0]) return null; - const nilai = val.currentTarget.value.replace(/\./g, ""); - const targetNilai = Intl.NumberFormat("id-ID").format(+nilai); + const nilai = val.currentTarget.value.replace(/\./g, ""); + const targetNilai = Intl.NumberFormat("id-ID").format(+nilai); - onTotalLembar({ - target: +nilai, - harga: +value.hargaLembar, - }); + // console.log("type nilai", typeof nilai); + // console.log("nilai", nilai); + // console.log("targetNilai", targetNilai); + // console.log("type targetNilai", typeof targetNilai); - setTarget(targetNilai); - setValue({ - ...value, - targetDana: +nilai, - }); - }} - /> + if (+nilai < 10000000) { + setMinimalTarget(true); + } else { + setMinimalTarget(false); + } + + onTotalLembar({ + target: +nilai, + harga: +value.hargaLembar, + }); + + setTarget(targetNilai); + setValue({ + ...value, + targetDana: +nilai, + }); + }} + /> + > diff --git a/src/app_modules/investasi/index.ts b/src/app_modules/investasi/index.ts index e5102391..d7849c4f 100644 --- a/src/app_modules/investasi/index.ts +++ b/src/app_modules/investasi/index.ts @@ -1,4 +1,3 @@ -import InvestasiCreate from "./create/view"; import InvestasiCreateNew from "./create/view_new"; import InvestasiCreateLayout from "./create/layout"; import DetailInvestasi from "./detail/view"; @@ -46,7 +45,6 @@ import StatusPesananInvetsatsi from "./status_pesanan/view"; import LayoutStatusPesananInvestasi from "./status_pesanan/layout"; export { - InvestasiCreate, InvestasiCreateLayout, DetailInvestasi, LayoutDetailInvestasi, diff --git a/src/app_modules/katalog/portofolio/component/button_more_new.tsx b/src/app_modules/katalog/portofolio/component/button_more_new.tsx index 33b325bc..dd641880 100644 --- a/src/app_modules/katalog/portofolio/component/button_more_new.tsx +++ b/src/app_modules/katalog/portofolio/component/button_more_new.tsx @@ -118,18 +118,13 @@ export default function ComponentPortofolio_ButtonMoreNew({ return ( <> - { - userLoginId === authorId && ( - setOpenDrawer(true)}> - - - ) - // : ( - // - // - // - // ) - } + {userLoginId === authorId ? ( + setOpenDrawer(true)}> + + + ) : ( + + )} (); + const profileId = param.id; + const [profile, setProfile] = useState(null); const [file, setFile] = useState(null); const [image, setImage] = useState(null); + useShallowEffect(() => { + handleLoadData(); + }, []); + + const handleLoadData = async () => { + try { + const response = await apiGetOneProfileById({ id: profileId }); + if (response && response.success) { + setProfile(response.data); + } else { + setProfile(null); + } + } catch (error) { + console.log("Error get profile", error); + setProfile(null); + } + }; + + if (!profile) + return ; + return ( <> diff --git a/src/app_modules/katalog/profile/upload/foto_profile/index.tsx b/src/app_modules/katalog/profile/upload/foto_profile/index.tsx index eaeace7d..85c5bff9 100644 --- a/src/app_modules/katalog/profile/upload/foto_profile/index.tsx +++ b/src/app_modules/katalog/profile/upload/foto_profile/index.tsx @@ -9,16 +9,39 @@ import { AspectRatio, Center, Image, Stack } from "@mantine/core"; import { useState } from "react"; import { Profile_ComponentButtonUpdatePhotoProfile } from "../../_component"; import { MODEL_PROFILE } from "../../model/interface"; +import CustomSkeleton from "@/app_modules/components/CustomSkeleton"; +import { useShallowEffect } from "@mantine/hooks"; +import { useParams } from "next/navigation"; +import { apiGetOneProfileById } from "../../lib/api_fetch_profile"; -export default function UploadFotoProfile({ - dataProfile, -}: { - dataProfile: MODEL_PROFILE; -}) { - const [profile, setProfile] = useState(dataProfile); +export default function UploadFotoProfile() { + const param = useParams<{ id: string }>(); + const profileId = param.id; + const [profile, setProfile] = useState(null); const [file, setFile] = useState(null); const [image, setImage] = useState(null); + useShallowEffect(() => { + handleLoadData(); + }, []); + + const handleLoadData = async () => { + try { + const response = await apiGetOneProfileById({ id: profileId }); + if (response && response.success) { + setProfile(response.data); + } else { + setProfile(null); + } + } catch (error) { + console.log("Error get profile", error); + setProfile(null); + } + }; + + if (!profile) + return ; + return ( <> diff --git a/src/lib/router_hipmi/router_investasi.ts b/src/lib/router_hipmi/router_investasi.ts index 6eec841f..fabf1208 100644 --- a/src/lib/router_hipmi/router_investasi.ts +++ b/src/lib/router_hipmi/router_investasi.ts @@ -8,7 +8,8 @@ export const NEW_RouterInvestasi = { * @param param status id | 1: Publish, 2: Review, 3: Draft, 4: Reject * @type string */ - portofolio: ({ id }: { id: "1" | "2" | "3" | "4" }) => `/dev/investasi/main/portofolio/${id}`, + portofolio: ({ id }: { id: "1" | "2" | "3" | "4" }) => + `/dev/investasi/main/portofolio/${id}`, // portofolio: ({ id }: { id?: string }) => `/dev/investasi/main/portofolio/${id}`, // TRANSAKSI @@ -24,6 +25,8 @@ export const NEW_RouterInvestasi = { // FILE VIEW file_prospektus: ({ id }: { id: string }) => `/dev/investasi/file-view/prospektus/${id}`, + file_dokumen: ({ id }: { id: string }) => + `/dev/investasi/file-view/dokumen/${id}`, OLD_file_view_prospektus: "/dev/investasi/file-view/prospektus/", OLD_file_view_dokumen: "/dev/investasi/file-view/dokumen/", diff --git a/x-example-show-pdf/index.html b/x-example-show-pdf/index.html index 23e750a9..3aeee7f1 100644 --- a/x-example-show-pdf/index.html +++ b/x-example-show-pdf/index.html @@ -20,7 +20,7 @@ const token = "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjp7ImlkIjoiY20wdXIxeXh3MDAwMDU2bnNqbHI2MTg3cCIsIm5hbWUiOiJiYWdhcyIsImVtYWlsIjoiYmFnYXNAZ21haWwuY29tIn0sImlhdCI6MTcyNTg3MTAzNiwiZXhwIjo0ODgxNjMxMDM2fQ.wFQLcrJj66wFeqIMYk2esMx3ULaHK6RFxkiToaLCuko"; const res = await fetch( - "https://wibu-storage.wibudev.com/api/pdf-to-image?url=https://wibu-storage.wibudev.com/api/files/cm5jgzg7d001dxpugxseb2ua0", + "https://wibu-storage.wibudev.com/api/pdf-to-image?url=https://wibu-storage.wibudev.com/api/files/cm7liew81000t3y8ax1v6yo02", { method: "GET", headers: {