3
.gitignore
vendored
3
.gitignore
vendored
@@ -34,6 +34,9 @@ yarn-error.log*
|
|||||||
# vercel
|
# vercel
|
||||||
.vercel
|
.vercel
|
||||||
|
|
||||||
|
# logs
|
||||||
|
/logs
|
||||||
|
|
||||||
# typescript
|
# typescript
|
||||||
*.tsbuildinfo
|
*.tsbuildinfo
|
||||||
next-env.d.ts
|
next-env.d.ts
|
||||||
|
|||||||
15
CHANGELOG.md
15
CHANGELOG.md
@@ -2,6 +2,21 @@
|
|||||||
|
|
||||||
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.
|
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.32](https://github.com/bipproduction/hipmi/compare/v1.2.31...v1.2.32) (2024-12-19)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* donasi ([72b6d23](https://github.com/bipproduction/hipmi/commit/72b6d239fee3e90e812ab24192154e5e8910fccb))
|
||||||
|
|
||||||
|
## [1.2.31](https://github.com/bipproduction/hipmi/compare/v1.2.30...v1.2.31) (2024-12-17)
|
||||||
|
|
||||||
|
## [1.2.30](https://github.com/bipproduction/hipmi/compare/v1.2.29...v1.2.30) (2024-12-16)
|
||||||
|
|
||||||
|
## [1.2.29](https://github.com/bipproduction/hipmi/compare/v1.2.28...v1.2.29) (2024-12-13)
|
||||||
|
|
||||||
|
## [1.2.28](https://github.com/bipproduction/hipmi/compare/v1.2.27...v1.2.28) (2024-12-12)
|
||||||
|
|
||||||
## [1.2.27](https://github.com/bipproduction/hipmi/compare/v1.2.26...v1.2.27) (2024-12-12)
|
## [1.2.27](https://github.com/bipproduction/hipmi/compare/v1.2.26...v1.2.27) (2024-12-12)
|
||||||
|
|
||||||
## [1.2.26](https://github.com/bipproduction/hipmi/compare/v1.2.25...v1.2.26) (2024-12-12)
|
## [1.2.26](https://github.com/bipproduction/hipmi/compare/v1.2.25...v1.2.26) (2024-12-12)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hipmi",
|
"name": "hipmi",
|
||||||
"version": "1.2.27",
|
"version": "1.2.32",
|
||||||
"private": true,
|
"private": true,
|
||||||
"prisma": {
|
"prisma": {
|
||||||
"seed": "npx tsx prisma/seed.ts --yes"
|
"seed": "npx tsx prisma/seed.ts --yes"
|
||||||
@@ -50,6 +50,7 @@
|
|||||||
"autoprefixer": "10.4.14",
|
"autoprefixer": "10.4.14",
|
||||||
"bufferutil": "^4.0.8",
|
"bufferutil": "^4.0.8",
|
||||||
"bun": "^1.1.38",
|
"bun": "^1.1.38",
|
||||||
|
"date-fns": "^4.1.0",
|
||||||
"dayjs": "^1.11.10",
|
"dayjs": "^1.11.10",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"echarts": "^5.4.3",
|
"echarts": "^5.4.3",
|
||||||
@@ -95,6 +96,8 @@
|
|||||||
"wibu": "bipproduction/wibu",
|
"wibu": "bipproduction/wibu",
|
||||||
"wibu-cli": "^1.0.91",
|
"wibu-cli": "^1.0.91",
|
||||||
"wibu-pkg": "^1.0.3",
|
"wibu-pkg": "^1.0.3",
|
||||||
|
"winston": "^3.17.0",
|
||||||
|
"winston-daily-rotate-file": "^5.0.0",
|
||||||
"yaml": "^2.3.2"
|
"yaml": "^2.3.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
138
src/app/(admin)/logs/logs.module.css
Normal file
138
src/app/(admin)/logs/logs.module.css
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
/* app/admin/logs/logs.module.css */
|
||||||
|
.container {
|
||||||
|
padding: 24px;
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filterContainer {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select {
|
||||||
|
padding: 8px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 4px;
|
||||||
|
min-width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logsContainer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logItem {
|
||||||
|
padding: 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.errorLog {
|
||||||
|
background-color: #fef2f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warnLog {
|
||||||
|
background-color: #fefce8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infoLog {
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logHeader {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timestamp {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level {
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.errorLevel {
|
||||||
|
background-color: #fee2e2;
|
||||||
|
color: #991b1b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warnLevel {
|
||||||
|
background-color: #fef3c7;
|
||||||
|
color: #92400e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infoLevel {
|
||||||
|
background-color: #dbeafe;
|
||||||
|
color: #1e40af;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metadata {
|
||||||
|
margin-top: 8px;
|
||||||
|
padding: 8px;
|
||||||
|
background-color: #f9fafb;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
overflow-x: auto;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading {
|
||||||
|
text-align: center;
|
||||||
|
padding: 24px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
color: #dc2626;
|
||||||
|
text-align: center;
|
||||||
|
padding: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hover effects */
|
||||||
|
.logItem:hover {
|
||||||
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.select:hover {
|
||||||
|
border-color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Focus states */
|
||||||
|
.select:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: #2563eb;
|
||||||
|
box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive adjustments */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.container {
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logHeader {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metadata {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
106
src/app/(admin)/logs/page.tsx
Normal file
106
src/app/(admin)/logs/page.tsx
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
// app/admin/logs/page.tsx
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { format } from "date-fns";
|
||||||
|
import styles from "./logs.module.css";
|
||||||
|
|
||||||
|
interface LogEntry {
|
||||||
|
timestamp: string;
|
||||||
|
level: string;
|
||||||
|
message: string;
|
||||||
|
metadata?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function LogsPage() {
|
||||||
|
const [logs, setLogs] = useState<LogEntry[]>([]);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
const [filter, setFilter] = useState<"all" | "error" | "info" | "warn">(
|
||||||
|
"all"
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchLogs();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
async function fetchLogs() {
|
||||||
|
try {
|
||||||
|
const response = await fetch("/api/logs/view");
|
||||||
|
if (!response.ok) throw new Error("Failed to fetch logs");
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
setLogs(data.logs);
|
||||||
|
} catch (err) {
|
||||||
|
setError(err instanceof Error ? err.message : "Error fetching logs");
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const filteredLogs = logs.filter((log) =>
|
||||||
|
filter === "all" ? true : log.level === filter
|
||||||
|
);
|
||||||
|
|
||||||
|
if (loading) return <div className={styles.loading}>Loading logs...</div>;
|
||||||
|
if (error) return <div className={styles.error}>Error: {error}</div>;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.container}>
|
||||||
|
<h1 className={styles.title}>System Logs</h1>
|
||||||
|
|
||||||
|
<div className={styles.filterContainer}>
|
||||||
|
<select
|
||||||
|
value={filter}
|
||||||
|
onChange={(e) => setFilter(e.target.value as any)}
|
||||||
|
className={styles.select}
|
||||||
|
>
|
||||||
|
<option value="all">All Logs</option>
|
||||||
|
<option value="error">Errors</option>
|
||||||
|
<option value="warn">Warnings</option>
|
||||||
|
<option value="info">Info</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.logsContainer}>
|
||||||
|
{filteredLogs.map((log, index) => (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
className={`${styles.logItem} ${
|
||||||
|
log.level === "error"
|
||||||
|
? styles.errorLog
|
||||||
|
: log.level === "warn"
|
||||||
|
? styles.warnLog
|
||||||
|
: styles.infoLog
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<div className={styles.logHeader}>
|
||||||
|
<span className={styles.timestamp}>
|
||||||
|
{format(new Date(log.timestamp), "yyyy-MM-dd HH:mm:ss")}
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
className={`${styles.level} ${
|
||||||
|
log.level === "error"
|
||||||
|
? styles.errorLevel
|
||||||
|
: log.level === "warn"
|
||||||
|
? styles.warnLevel
|
||||||
|
: styles.infoLevel
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{log.level.toUpperCase()}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.message}>{log.message}</div>
|
||||||
|
|
||||||
|
{log.metadata && (
|
||||||
|
<pre className={styles.metadata}>
|
||||||
|
{JSON.stringify(log.metadata, null, 2)}
|
||||||
|
</pre>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
20
src/app/api/collaboration/master/route.ts
Normal file
20
src/app/api/collaboration/master/route.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { prisma } from "@/app/lib";
|
||||||
|
import backendLogger from "@/util/backendLogger";
|
||||||
|
import { NextResponse } from "next/server";
|
||||||
|
|
||||||
|
export const dynamic = "force-dynamic";
|
||||||
|
export async function GET(request: Request) {
|
||||||
|
try {
|
||||||
|
const data = await prisma.projectCollaborationMaster_Industri.findMany({});
|
||||||
|
return NextResponse.json(
|
||||||
|
{ success: true, message: "Berhasil mendapatkan data", data: data },
|
||||||
|
{ status: 200 }
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
backendLogger.error("Master Collaboration:=========>", error);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ success: false, message: "Gagal mendapatkan data" },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
53
src/app/api/image/delete/route.ts
Normal file
53
src/app/api/image/delete/route.ts
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import { funGetDirectoryNameByValue } from "@/app_modules/_global/fun/get";
|
||||||
|
import backendLogger from "@/util/backendLogger";
|
||||||
|
import { NextResponse } from "next/server";
|
||||||
|
|
||||||
|
export async function DELETE(req: Request) {
|
||||||
|
const data = await req.json();
|
||||||
|
const id = data.fileId;
|
||||||
|
const dirId = data.dirId;
|
||||||
|
|
||||||
|
const keyOfDirectory = await funGetDirectoryNameByValue({
|
||||||
|
value: dirId,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (req.method === "DELETE") {
|
||||||
|
try {
|
||||||
|
const res = await fetch(
|
||||||
|
`https://wibu-storage.wibudev.com/api/files/${id}/delete`,
|
||||||
|
{
|
||||||
|
method: "DELETE",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${process.env.WS_APIKEY}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
backendLogger.info("Server status code: " + res.status);
|
||||||
|
const data = await res.json();
|
||||||
|
if (res.ok) {
|
||||||
|
backendLogger.info(
|
||||||
|
`Success delete ${keyOfDirectory}`
|
||||||
|
);
|
||||||
|
return NextResponse.json({ success: true });
|
||||||
|
} else {
|
||||||
|
const errorText = await res.json();
|
||||||
|
backendLogger.error(
|
||||||
|
`Failed delete ${keyOfDirectory}: ` + errorText.message
|
||||||
|
);
|
||||||
|
return NextResponse.json({
|
||||||
|
success: false,
|
||||||
|
message: errorText.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
backendLogger.error(`Delete error ${keyOfDirectory}:`, error);
|
||||||
|
return NextResponse.json({
|
||||||
|
success: false,
|
||||||
|
message: "An unexpected error occurred",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
backendLogger.error(`Error upload ${keyOfDirectory}: Method not allowed`);
|
||||||
|
return NextResponse.json({ success: false, message: "Method not allowed" });
|
||||||
|
}
|
||||||
|
}
|
||||||
58
src/app/api/image/upload/route.ts
Normal file
58
src/app/api/image/upload/route.ts
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import { funGetDirectoryNameByValue } from "@/app_modules/_global/fun/get";
|
||||||
|
import backendLogger from "@/util/backendLogger";
|
||||||
|
import { NextResponse } from "next/server";
|
||||||
|
export async function POST(request: Request) {
|
||||||
|
const formData = await request.formData();
|
||||||
|
|
||||||
|
const valueOfDir = formData.get("dirId");
|
||||||
|
const keyOfDirectory = await funGetDirectoryNameByValue({
|
||||||
|
value: valueOfDir as string,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (request.method === "POST") {
|
||||||
|
try {
|
||||||
|
const res = await fetch("https://wibu-storage.wibudev.com/api/upload", {
|
||||||
|
method: "POST",
|
||||||
|
body: formData,
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${process.env.WS_APIKEY}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
backendLogger.info("Server status code: " + res.status);
|
||||||
|
const dataRes = await res.json();
|
||||||
|
|
||||||
|
if (res.ok) {
|
||||||
|
backendLogger.info(
|
||||||
|
`Success upload ${keyOfDirectory}: ${JSON.stringify(dataRes.data)}`
|
||||||
|
);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ success: true, data: dataRes.data },
|
||||||
|
{ status: 200 }
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
const errorText = await res.text();
|
||||||
|
backendLogger.error(`Failed upload ${keyOfDirectory}: ${errorText}`);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ success: false, message: errorText },
|
||||||
|
{ status: 400 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
backendLogger.error(`Error upload ${keyOfDirectory}: ${error}`);
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message: "An unexpected error occurred",
|
||||||
|
},
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
backendLogger.error(`Error upload ${keyOfDirectory}: Method not allowed`);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ success: false, message: "Method not allowed" },
|
||||||
|
{ status: 405 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +1,94 @@
|
|||||||
import { job_getAllListPublish } from "@/app_modules/job/fun/get/get_all_publish";
|
import { prisma } from "@/app/lib";
|
||||||
import _ from "lodash";
|
|
||||||
import { NextResponse } from "next/server";
|
import { NextResponse } from "next/server";
|
||||||
|
export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
export async function GET(params: Request) {
|
export async function GET(request: Request) {
|
||||||
const { searchParams } = new URL(params.url);
|
try {
|
||||||
const page = searchParams.get("page");
|
const { searchParams } = new URL(request.url);
|
||||||
const search = searchParams.get("search");
|
const search = searchParams.get("search");
|
||||||
|
const page = searchParams.get("page");
|
||||||
|
const dataTake = 10;
|
||||||
|
const dataSkip = Number(page) * dataTake - dataTake;
|
||||||
|
|
||||||
const data = await job_getAllListPublish({
|
if (search != "") {
|
||||||
page: _.toNumber(page),
|
const data = await prisma.job.findMany({
|
||||||
search: search as string,
|
take: dataTake,
|
||||||
});
|
skip: dataSkip,
|
||||||
|
orderBy: {
|
||||||
|
updatedAt: "desc",
|
||||||
|
},
|
||||||
|
where: {
|
||||||
|
masterStatusId: "1",
|
||||||
|
isActive: true,
|
||||||
|
isArsip: false,
|
||||||
|
title: {
|
||||||
|
mode: "insensitive",
|
||||||
|
contains: search as string,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
title: true,
|
||||||
|
Author: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
username: true,
|
||||||
|
Profile: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
return NextResponse.json({ data });
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
success: true,
|
||||||
|
message: "Berhasil ambil data",
|
||||||
|
data: data,
|
||||||
|
},
|
||||||
|
{ status: 200 }
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
const data = await prisma.job.findMany({
|
||||||
|
take: dataTake,
|
||||||
|
skip: dataSkip,
|
||||||
|
orderBy: {
|
||||||
|
updatedAt: "desc",
|
||||||
|
},
|
||||||
|
where: {
|
||||||
|
masterStatusId: "1",
|
||||||
|
isActive: true,
|
||||||
|
isArsip: false,
|
||||||
|
title: {
|
||||||
|
mode: "insensitive",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
title: true,
|
||||||
|
Author: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
username: true,
|
||||||
|
Profile: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
success: true,
|
||||||
|
message: "Berhasil ambil data",
|
||||||
|
data: data,
|
||||||
|
},
|
||||||
|
{ status: 200 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return NextResponse.json({
|
||||||
|
success: false,
|
||||||
|
message: "Gagal ambil data",
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
71
src/app/api/logs/view/route.ts
Normal file
71
src/app/api/logs/view/route.ts
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
// app/api/logs/view/route.ts
|
||||||
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
|
import fs from "fs/promises";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
|
interface LogEntry {
|
||||||
|
timestamp: string;
|
||||||
|
level: string;
|
||||||
|
message: string;
|
||||||
|
metadata?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function readLogFiles(directory: string): Promise<LogEntry[]> {
|
||||||
|
try {
|
||||||
|
const logPath = path.join(process.cwd(), directory);
|
||||||
|
const files = await fs.readdir(logPath);
|
||||||
|
const logFiles = files.filter((file) => file.endsWith(".log"));
|
||||||
|
|
||||||
|
const allLogs: LogEntry[] = [];
|
||||||
|
|
||||||
|
for (const file of logFiles) {
|
||||||
|
const filePath = path.join(logPath, file);
|
||||||
|
const content = await fs.readFile(filePath, "utf-8");
|
||||||
|
|
||||||
|
// Parse setiap baris log
|
||||||
|
const logs = content
|
||||||
|
.split("\n")
|
||||||
|
.filter(Boolean)
|
||||||
|
.map((line) => {
|
||||||
|
try {
|
||||||
|
return JSON.parse(line);
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter(Boolean);
|
||||||
|
|
||||||
|
allLogs.push(...logs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort berdasarkan timestamp, terbaru di atas
|
||||||
|
return allLogs.sort(
|
||||||
|
(a, b) =>
|
||||||
|
new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error reading log files:", error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GET(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
// Baca logs dari frontend dan backend
|
||||||
|
const frontendLogs = await readLogFiles("logs/frontend");
|
||||||
|
const backendLogs = await readLogFiles("logs/backend");
|
||||||
|
|
||||||
|
// Gabungkan dan sort semua logs
|
||||||
|
const allLogs = [...frontendLogs, ...backendLogs].sort(
|
||||||
|
(a, b) =>
|
||||||
|
new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
|
||||||
|
);
|
||||||
|
|
||||||
|
return NextResponse.json({ logs: allLogs });
|
||||||
|
} catch (error) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Failed to fetch logs" },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
77
src/app/api/new/donasi/invoice/route.ts
Normal file
77
src/app/api/new/donasi/invoice/route.ts
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
import { prisma } from "@/app/lib";
|
||||||
|
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { NextResponse } from "next/server";
|
||||||
|
export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// GET ALL DATA DONASI SAYA (INVOICE)
|
||||||
|
export async function GET(request: Request) {
|
||||||
|
try {
|
||||||
|
const { searchParams } = new URL(request.url)
|
||||||
|
const page = searchParams.get("page")
|
||||||
|
const dataSkip = Number(page) * 5 - 5;
|
||||||
|
|
||||||
|
|
||||||
|
const userLoginId = await funGetUserIdByToken()
|
||||||
|
if (userLoginId == null) {
|
||||||
|
return NextResponse.json({ success: false, message: "Gagal mendapatkan data, user id tidak ada" }, { status: 500 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await prisma.donasi_Invoice.findMany({
|
||||||
|
take: 5,
|
||||||
|
skip: dataSkip,
|
||||||
|
orderBy: {
|
||||||
|
createdAt: "desc",
|
||||||
|
},
|
||||||
|
where: {
|
||||||
|
authorId: userLoginId,
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
nominal: true,
|
||||||
|
donasiMaster_StatusInvoiceId: true,
|
||||||
|
DonasiMaster_StatusInvoice: {
|
||||||
|
select: {
|
||||||
|
name: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Donasi: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
title: true,
|
||||||
|
publishTime: true,
|
||||||
|
progres: true,
|
||||||
|
imageId: true,
|
||||||
|
DonasiMaster_Durasi: {
|
||||||
|
select: {
|
||||||
|
name: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const dataFix = data.map((v: any) => ({
|
||||||
|
..._.omit(v, ["DonasiMaster_StatusInvoice", "Donasi"]),
|
||||||
|
nameStatusInvoice: v.DonasiMaster_StatusInvoice.name,
|
||||||
|
donasiId: v.Donasi.id,
|
||||||
|
title: v.Donasi.title,
|
||||||
|
publishTime: v.Donasi.publishTime,
|
||||||
|
progres: v.Donasi.progres,
|
||||||
|
imageId: v.Donasi.imageId,
|
||||||
|
durasiDonasi: v.Donasi.DonasiMaster_Durasi.name
|
||||||
|
}))
|
||||||
|
|
||||||
|
|
||||||
|
return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data: dataFix }, { status: 200 });
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return NextResponse.json({ success: false, message: "Gagal mendapatkan data, coba lagi nanti ", reason: (error as Error).message, }, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
33
src/app/api/new/donasi/master/route.ts
Normal file
33
src/app/api/new/donasi/master/route.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import { prisma } from "@/app/lib";
|
||||||
|
import { NextResponse } from "next/server";
|
||||||
|
export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
|
|
||||||
|
// GET ALL DATA MASTER UNTUK DONASI
|
||||||
|
export async function GET(request: Request) {
|
||||||
|
try {
|
||||||
|
let dataFix
|
||||||
|
const { searchParams } = new URL(request.url)
|
||||||
|
const kategori = searchParams.get("cat")
|
||||||
|
|
||||||
|
if (kategori == "kategori") {
|
||||||
|
dataFix = await prisma.donasiMaster_Kategori.findMany({
|
||||||
|
orderBy: {
|
||||||
|
createdAt: "asc",
|
||||||
|
},
|
||||||
|
where: {
|
||||||
|
active: true,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else if (kategori == "durasi") {
|
||||||
|
dataFix = await prisma.donasiMaster_Durasi.findMany()
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data: dataFix }, { status: 200 });
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return NextResponse.json({ success: false, message: "Gagal mendapatkan data, coba lagi nanti ", reason: (error as Error).message, }, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -46,23 +46,44 @@ export async function GET(request: Request) {
|
|||||||
..._.omit(v, ["DonasiMaster_Durasi"]),
|
..._.omit(v, ["DonasiMaster_Durasi"]),
|
||||||
nameDonasiDurasi: v.DonasiMaster_Durasi.name
|
nameDonasiDurasi: v.DonasiMaster_Durasi.name
|
||||||
}))
|
}))
|
||||||
} else {
|
} else if (kategori == "galang-dana") {
|
||||||
const userLoginId = await funGetUserIdByToken()
|
const userLoginId = await funGetUserIdByToken()
|
||||||
if (userLoginId == null) {
|
if (userLoginId == null) {
|
||||||
return NextResponse.json({ success: false, message: "Gagal mendapatkan data, user id tidak ada" }, { status: 500 });
|
return NextResponse.json({ success: false, message: "Gagal mendapatkan data, user id tidak ada" }, { status: 500 });
|
||||||
}
|
}
|
||||||
|
|
||||||
dataFix = await prisma.donasi.findMany({
|
const data = await prisma.donasi.findMany({
|
||||||
take: 5,
|
take: 5,
|
||||||
skip: dataSkip,
|
skip: dataSkip,
|
||||||
where: {
|
where: {
|
||||||
authorId: userLoginId,
|
authorId: userLoginId,
|
||||||
donasiMaster_StatusDonasiId: status,
|
donasiMaster_StatusDonasiId: status,
|
||||||
|
active: true,
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
title: true,
|
||||||
|
imagesId: true,
|
||||||
|
target: true,
|
||||||
|
progres: true,
|
||||||
|
publishTime: true,
|
||||||
|
DonasiMaster_Durasi: {
|
||||||
|
select: {
|
||||||
|
name: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
terkumpul: true,
|
||||||
|
imageId: true,
|
||||||
},
|
},
|
||||||
orderBy: {
|
orderBy: {
|
||||||
updatedAt: "desc",
|
updatedAt: "desc",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
dataFix = data.map((v: any) => ({
|
||||||
|
..._.omit(v, ["DonasiMaster_Durasi"]),
|
||||||
|
nameDonasiDurasi: v.DonasiMaster_Durasi.name
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data: dataFix }, { status: 200 });
|
return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data: dataFix }, { status: 200 });
|
||||||
|
|||||||
39
src/app/api/new/investasi/[id]/route.ts
Normal file
39
src/app/api/new/investasi/[id]/route.ts
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import { prisma } from "@/app/lib";
|
||||||
|
import { NextResponse } from "next/server";
|
||||||
|
export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// GET ONE DATA INVESTASI BY ID
|
||||||
|
export async function GET(request: Request, context: { params: { id: string } }) {
|
||||||
|
try {
|
||||||
|
const { id } = context.params
|
||||||
|
const data = await prisma.investasi.findUnique({
|
||||||
|
where: {
|
||||||
|
id: id,
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
title: true,
|
||||||
|
targetDana: true,
|
||||||
|
hargaLembar: true,
|
||||||
|
totalLembar: true,
|
||||||
|
roi: true,
|
||||||
|
countDown: true,
|
||||||
|
catatan: true,
|
||||||
|
sisaLembar: true,
|
||||||
|
imageId: true,
|
||||||
|
masterPencarianInvestorId: true,
|
||||||
|
masterPeriodeDevidenId: true,
|
||||||
|
masterPembagianDevidenId: true,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data }, { status: 200 });
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return NextResponse.json({ success: false, message: "Gagal mendapatkan data, coba lagi nanti ", reason: (error as Error).message, }, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
99
src/app/api/new/investasi/invoice/route.ts
Normal file
99
src/app/api/new/investasi/invoice/route.ts
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
import { prisma } from "@/app/lib";
|
||||||
|
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { NextResponse } from "next/server";
|
||||||
|
export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// GET ALL DATA INVESTASI SAYA (INVOICE)
|
||||||
|
export async function GET(request: Request) {
|
||||||
|
try {
|
||||||
|
let dataFix
|
||||||
|
const { searchParams } = new URL(request.url)
|
||||||
|
const page = searchParams.get("page")
|
||||||
|
const dataSkip = Number(page) * 10 - 10;
|
||||||
|
const kategori = searchParams.get("cat")
|
||||||
|
|
||||||
|
|
||||||
|
const userLoginId = await funGetUserIdByToken()
|
||||||
|
if (userLoginId == null) {
|
||||||
|
return NextResponse.json({ success: false, message: "Gagal mendapatkan data, user id tidak ada" }, { status: 500 });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kategori == "saham-saya") {
|
||||||
|
const data = await prisma.investasi_Invoice.findMany({
|
||||||
|
take: 10,
|
||||||
|
skip: dataSkip,
|
||||||
|
orderBy: {
|
||||||
|
updatedAt: "desc",
|
||||||
|
},
|
||||||
|
where: {
|
||||||
|
authorId: userLoginId,
|
||||||
|
statusInvoiceId: "1",
|
||||||
|
isActive: true,
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
nominal: true,
|
||||||
|
lembarTerbeli: true,
|
||||||
|
Investasi: {
|
||||||
|
select: {
|
||||||
|
title: true,
|
||||||
|
progress: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
dataFix = data.map((v: any) => ({
|
||||||
|
..._.omit(v, ["Investasi"]),
|
||||||
|
title: v.Investasi.title,
|
||||||
|
progress: v.Investasi.progress
|
||||||
|
}))
|
||||||
|
|
||||||
|
} else if (kategori == "transaksi") {
|
||||||
|
const data = await prisma.investasi_Invoice.findMany({
|
||||||
|
take: 10,
|
||||||
|
skip: dataSkip,
|
||||||
|
orderBy: {
|
||||||
|
updatedAt: "desc",
|
||||||
|
},
|
||||||
|
where: {
|
||||||
|
authorId: userLoginId,
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
statusInvoiceId: true,
|
||||||
|
nominal: true,
|
||||||
|
createdAt: true,
|
||||||
|
StatusInvoice: {
|
||||||
|
select: {
|
||||||
|
name: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Investasi: {
|
||||||
|
select: {
|
||||||
|
title: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
dataFix = data.map((v: any) => ({
|
||||||
|
..._.omit(v, ["Investasi", "StatusInvoice"]),
|
||||||
|
title: v.Investasi.title,
|
||||||
|
statusInvoice: v.StatusInvoice.name
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data: dataFix }, { status: 200 });
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return NextResponse.json({ success: false, message: "Gagal mendapatkan data, coba lagi nanti ", reason: (error as Error).message, }, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
46
src/app/api/new/investasi/master/route.ts
Normal file
46
src/app/api/new/investasi/master/route.ts
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import { prisma } from "@/app/lib";
|
||||||
|
import { NextResponse } from "next/server";
|
||||||
|
export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
|
|
||||||
|
// GET ALL DATA MASTER UNTUK INVESTASI
|
||||||
|
export async function GET(request: Request) {
|
||||||
|
try {
|
||||||
|
let dataFix
|
||||||
|
const { searchParams } = new URL(request.url)
|
||||||
|
const kategori = searchParams.get("cat")
|
||||||
|
|
||||||
|
if (kategori == "pencarian-investor") {
|
||||||
|
dataFix = await await prisma.masterPencarianInvestor.findMany({
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
name: true,
|
||||||
|
active: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else if (kategori == "periode-deviden") {
|
||||||
|
dataFix = await prisma.masterPeriodeDeviden.findMany({
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
name: true,
|
||||||
|
active: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else if (kategori == "pembagian-deviden") {
|
||||||
|
dataFix = await prisma.masterPembagianDeviden.findMany({
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
name: true,
|
||||||
|
active: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data: dataFix }, { status: 200 });
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return NextResponse.json({ success: false, message: "Gagal mendapatkan data, coba lagi nanti ", reason: (error as Error).message, }, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
144
src/app/api/new/investasi/route.ts
Normal file
144
src/app/api/new/investasi/route.ts
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
import { prisma } from "@/app/lib";
|
||||||
|
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
|
||||||
|
import _ from "lodash";
|
||||||
|
import moment from "moment";
|
||||||
|
import { NextResponse } from "next/server";
|
||||||
|
export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
|
|
||||||
|
// GET ALL DATA INVESTASI
|
||||||
|
export async function GET(request: Request) {
|
||||||
|
try {
|
||||||
|
let dataFix
|
||||||
|
const { searchParams } = new URL(request.url)
|
||||||
|
const kategori = searchParams.get("cat")
|
||||||
|
const status = searchParams.get("status")
|
||||||
|
const page = searchParams.get("page")
|
||||||
|
const dataSkip = Number(page) * 5 - 5;
|
||||||
|
|
||||||
|
if (kategori == "bursa") {
|
||||||
|
const data = await prisma.investasi.findMany({
|
||||||
|
where: {
|
||||||
|
masterStatusInvestasiId: "1",
|
||||||
|
masterProgresInvestasiId: "1",
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
MasterPencarianInvestor: true,
|
||||||
|
countDown: true,
|
||||||
|
progress: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
for (let a of data) {
|
||||||
|
if (
|
||||||
|
(a.MasterPencarianInvestor?.name as any) -
|
||||||
|
moment(new Date()).diff(new Date(a.countDown as any), "days") <=
|
||||||
|
0
|
||||||
|
) {
|
||||||
|
await prisma.investasi.update({
|
||||||
|
where: {
|
||||||
|
id: a.id,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
masterProgresInvestasiId: "3",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a.progress === "100") {
|
||||||
|
await prisma.investasi.update({
|
||||||
|
where: {
|
||||||
|
id: a.id,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
masterProgresInvestasiId: "2",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// cek data yang lewat
|
||||||
|
// klo ada, update status
|
||||||
|
const dataAwal = await prisma.investasi.findMany({
|
||||||
|
take: 5,
|
||||||
|
skip: dataSkip,
|
||||||
|
orderBy: [
|
||||||
|
{
|
||||||
|
masterProgresInvestasiId: "asc",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
countDown: "desc",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
where: {
|
||||||
|
masterStatusInvestasiId: "1",
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
imageId: true,
|
||||||
|
title: true,
|
||||||
|
progress: true,
|
||||||
|
countDown: true,
|
||||||
|
MasterPencarianInvestor: {
|
||||||
|
select: {
|
||||||
|
name: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
dataFix = dataAwal.map((v: any) => ({
|
||||||
|
..._.omit(v, ["MasterPencarianInvestor"]),
|
||||||
|
pencarianInvestor: v.MasterPencarianInvestor.name
|
||||||
|
}))
|
||||||
|
|
||||||
|
} else if (kategori == "portofolio") {
|
||||||
|
const userLoginId = await funGetUserIdByToken()
|
||||||
|
if (userLoginId == null) {
|
||||||
|
return NextResponse.json({ success: false, message: "Gagal mendapatkan data, user id tidak ada" }, { status: 500 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await prisma.investasi.findMany({
|
||||||
|
take: 5,
|
||||||
|
skip: dataSkip,
|
||||||
|
orderBy: {
|
||||||
|
updatedAt: "desc",
|
||||||
|
},
|
||||||
|
where: {
|
||||||
|
authorId: userLoginId,
|
||||||
|
masterStatusInvestasiId: status,
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
title: true,
|
||||||
|
targetDana: true,
|
||||||
|
imageId: true,
|
||||||
|
countDown: true,
|
||||||
|
updatedAt: true,
|
||||||
|
MasterPencarianInvestor: {
|
||||||
|
select: {
|
||||||
|
name: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
dataFix = data.map((v: any) => ({
|
||||||
|
..._.omit(v, ["MasterPencarianInvestor"]),
|
||||||
|
pencarianInvestor: v.MasterPencarianInvestor.name
|
||||||
|
}))
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data: dataFix }, { status: 200 });
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return NextResponse.json({ success: false, message: "Gagal mendapatkan data, coba lagi nanti ", reason: (error as Error).message, }, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
28
src/app/api/notifikasi/count/route.ts
Normal file
28
src/app/api/notifikasi/count/route.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { prisma } from "@/app/lib";
|
||||||
|
import { newFunGetUserId } from "@/app/lib/new_fun_user_id";
|
||||||
|
import backendLogger from "@/util/backendLogger";
|
||||||
|
import { NextResponse } from "next/server";
|
||||||
|
|
||||||
|
export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
|
export async function GET(request: Request) {
|
||||||
|
try {
|
||||||
|
const userLoginId = await newFunGetUserId();
|
||||||
|
|
||||||
|
const count = await prisma.notifikasi.findMany({
|
||||||
|
where: {
|
||||||
|
userId: userLoginId,
|
||||||
|
isRead: false,
|
||||||
|
userRoleId: "1",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return NextResponse.json({ success: true, data: count.length });
|
||||||
|
} catch (error) {
|
||||||
|
backendLogger.error("Gagal mendapatkan data count notifikasi", error);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ success: false, message: "Gagal mendapatkan data" },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
65
src/app/api/notifikasi/get-all-by-category/route.ts
Normal file
65
src/app/api/notifikasi/get-all-by-category/route.ts
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
import { prisma } from "@/app/lib";
|
||||||
|
import { newFunGetUserId } from "@/app/lib/new_fun_user_id";
|
||||||
|
import { ICategoryapp } from "@/app_modules/notifikasi/model/interface";
|
||||||
|
import backendLogger from "@/util/backendLogger";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { NextResponse } from "next/server";
|
||||||
|
export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
|
export async function GET(request: Request) {
|
||||||
|
try {
|
||||||
|
let fixData;
|
||||||
|
const { searchParams } = new URL(request.url);
|
||||||
|
const category = searchParams.get("category") as ICategoryapp;
|
||||||
|
const page = searchParams.get("page");
|
||||||
|
|
||||||
|
const userLoginId = await newFunGetUserId();
|
||||||
|
const fixPage = _.toNumber(page);
|
||||||
|
const takeData = 10;
|
||||||
|
const skipData = fixPage * takeData - takeData;
|
||||||
|
|
||||||
|
if (category === "Semua") {
|
||||||
|
fixData = await prisma.notifikasi.findMany({
|
||||||
|
take: takeData,
|
||||||
|
skip: skipData,
|
||||||
|
orderBy: [
|
||||||
|
{
|
||||||
|
isRead: "asc",
|
||||||
|
},
|
||||||
|
{ createdAt: "desc" },
|
||||||
|
],
|
||||||
|
where: {
|
||||||
|
userId: userLoginId,
|
||||||
|
userRoleId: "1",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
fixData = await prisma.notifikasi.findMany({
|
||||||
|
take: takeData,
|
||||||
|
skip: skipData,
|
||||||
|
orderBy: [
|
||||||
|
{
|
||||||
|
isRead: "asc",
|
||||||
|
},
|
||||||
|
{ createdAt: "desc" },
|
||||||
|
],
|
||||||
|
where: {
|
||||||
|
userId: userLoginId,
|
||||||
|
userRoleId: "1",
|
||||||
|
kategoriApp: _.upperCase(category),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(
|
||||||
|
{ success: true, data: fixData, message: "Berhasil mendapatkan data" },
|
||||||
|
{ status: 200 }
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
backendLogger.error("Error get data notifikasi: " + error);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ success: false, message: "Gagal mendapatkan data" },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
35
src/app/api/notifikasi/master/route.ts
Normal file
35
src/app/api/notifikasi/master/route.ts
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import { prisma } from "@/app/lib";
|
||||||
|
import backendLogger from "@/util/backendLogger";
|
||||||
|
import { NextResponse } from "next/server";
|
||||||
|
|
||||||
|
export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
|
export async function GET(request: Request) {
|
||||||
|
try {
|
||||||
|
const data = await prisma.masterKategoriApp.findMany({
|
||||||
|
where: {
|
||||||
|
isActive: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
data.unshift({
|
||||||
|
id: "0",
|
||||||
|
isActive: true,
|
||||||
|
createdAt: new Date(),
|
||||||
|
updatedAt: new Date(),
|
||||||
|
name: "Semua",
|
||||||
|
value: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
return NextResponse.json(
|
||||||
|
{ success: true, data, message: "Berhasil mendapatkan data" },
|
||||||
|
{ status: 200 }
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
backendLogger.error("Master Notifikasi:", error);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ success: false, message: "Gagal mendapatkan data" },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
import { NextResponse } from "next/server";
|
|
||||||
export async function POST(request: Request) {
|
|
||||||
const WS_APIKEY = process.env.WS_APIKEY;
|
|
||||||
console.log(WS_APIKEY);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const formData = await request.formData();
|
|
||||||
|
|
||||||
const res = await fetch("https://wibu-storage.wibudev.com/api/upload", {
|
|
||||||
method: "POST",
|
|
||||||
body: formData,
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${process.env.WS_APIKEY}`,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// if (res.ok) {
|
|
||||||
// console.log("Berhasil");
|
|
||||||
// const hasil = await res.json();
|
|
||||||
// return { success: true, data: hasil.data };
|
|
||||||
// } else {
|
|
||||||
// const errorText = await res.text();
|
|
||||||
// return { success: false, data: {} };
|
|
||||||
// }
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
// try {
|
|
||||||
// const res = await fetch("https://wibu-storage.wibudev.com/api/upload", {
|
|
||||||
// method: "POST",
|
|
||||||
// body: formData,
|
|
||||||
// headers: {
|
|
||||||
// Authorization: `Bearer ${process.env.WS_APIKEY}`,
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
|
|
||||||
// if (res.ok) {
|
|
||||||
// const hasil = await res.json();
|
|
||||||
// return { success: true, data: hasil.data };
|
|
||||||
// } else {
|
|
||||||
// const errorText = await res.text();
|
|
||||||
// return { success: false, data: {} };
|
|
||||||
// }
|
|
||||||
// } catch (error) {
|
|
||||||
// console.error("Upload error:", error);
|
|
||||||
// return { success: false, data: {} };
|
|
||||||
// }
|
|
||||||
|
|
||||||
return NextResponse.json({ success: true });
|
|
||||||
}
|
|
||||||
@@ -1,21 +1,9 @@
|
|||||||
import { HomeViewNew } from "@/app_modules/home";
|
import { HomeViewNew } from "@/app_modules/home";
|
||||||
import notifikasi_countUserNotifikasi from "@/app_modules/notifikasi/fun/count/fun_count_by_id";
|
|
||||||
|
|
||||||
export default async function PageHome() {
|
export default async function PageHome() {
|
||||||
// const userLoginId = await funGetUserIdByToken();
|
|
||||||
// const dataUser = await user_getOneByUserId(userLoginId as string);
|
|
||||||
// const dataJob = await job_getTwoForHomeView();
|
|
||||||
const countNotifikasi = await notifikasi_countUserNotifikasi();
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* <HomeView
|
<HomeViewNew />
|
||||||
dataUser={dataUser as any}
|
|
||||||
dataJob={dataJob as any}
|
|
||||||
countNotifikasi={countNotifikasi}
|
|
||||||
/> */}
|
|
||||||
<HomeViewNew countNotifikasi={countNotifikasi} />
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
import { Colab_Create } from "@/app_modules/colab";
|
import { Colab_Create } from "@/app_modules/colab";
|
||||||
import colab_funGetMasterIndustri from "@/app_modules/colab/fun/master/fun_get_master_industri";
|
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
const listIndustri = await colab_funGetMasterIndustri();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Colab_Create listIndustri={listIndustri as any} />
|
<Colab_Create />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
import { CreateDonasi } from "@/app_modules/donasi";
|
import { CreateDonasiNew } from "@/app_modules/donasi";
|
||||||
import {
|
|
||||||
Donasi_getMasterDurasi,
|
|
||||||
Donasi_getMasterKategori,
|
|
||||||
} from "@/app_modules/donasi/fun";
|
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
const masterKategori = await Donasi_getMasterKategori();
|
// const masterKategori = await Donasi_getMasterKategori();
|
||||||
const masterDurasi = await Donasi_getMasterDurasi();
|
// const masterDurasi = await Donasi_getMasterDurasi();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CreateDonasi masterKategori={masterKategori} masterDurasi={masterDurasi} />
|
// <CreateDonasi masterKategori={masterKategori} masterDurasi={masterDurasi} />
|
||||||
|
<CreateDonasiNew />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
import { DonasiSayaDonasi } from "@/app_modules/donasi";
|
import DonasiSayaNew from "@/app_modules/donasi/main/donasi_saya_new";
|
||||||
import { donasi_funGetAllInvoiceByAuthorId } from "@/app_modules/donasi/fun/get/get_all_invoice_by_author_id";
|
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
const listInvoice = await donasi_funGetAllInvoiceByAuthorId({ page: 1 });
|
// const listInvoice = await donasi_funGetAllInvoiceByAuthorId({ page: 1 });
|
||||||
|
|
||||||
return <DonasiSayaDonasi listInvoice={listInvoice as any} />;
|
return (
|
||||||
|
<>
|
||||||
|
{/* <DonasiSayaDonasi listInvoice={listInvoice as any} />; */}
|
||||||
|
<DonasiSayaNew />
|
||||||
|
</>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,23 @@
|
|||||||
import { GalangDanaDonasiNew, PostingDonasi } from "@/app_modules/donasi";
|
import { GalangDanaDonasiNew } from "@/app_modules/donasi";
|
||||||
import { donasi_funGetAllStatusById } from "@/app_modules/donasi/fun";
|
|
||||||
import { donasi_funMasterStatusDonasi } from "@/app_modules/donasi/fun/master/get_status_donasi";
|
|
||||||
|
|
||||||
export default async function Page({ params }: { params: { id: string } }) {
|
export default async function Page({ params }: { params: { id: string } }) {
|
||||||
const statusId = params.id;
|
// const statusId = params.id;
|
||||||
|
|
||||||
const listStatus = await donasi_funMasterStatusDonasi();
|
// const listStatus = await donasi_funMasterStatusDonasi();
|
||||||
const dataDonasi = await donasi_funGetAllStatusById({
|
// const dataDonasi = await donasi_funGetAllStatusById({
|
||||||
page: 1,
|
// page: 1,
|
||||||
statusId: statusId,
|
// statusId: statusId,
|
||||||
});
|
// });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PostingDonasi
|
{/* <PostingDonasi
|
||||||
statusId={statusId}
|
statusId={statusId}
|
||||||
dataStatus={dataDonasi}
|
dataStatus={dataDonasi}
|
||||||
listStatus={listStatus}
|
listStatus={listStatus}
|
||||||
/>
|
/> */}
|
||||||
|
|
||||||
|
<GalangDanaDonasiNew />
|
||||||
{/* NANTI AJA LANJUT -- KEJAR TAYANG :) */}
|
|
||||||
{/* <GalangDanaDonasiNew listStatus={listStatus}/> */}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
import { InvestasiCreate } from "@/app_modules/investasi";
|
import { InvestasiCreateNew } from "@/app_modules/investasi";
|
||||||
import getPembagianDeviden from "@/app_modules/investasi/fun/master/get_pembagian_deviden";
|
|
||||||
import getPencarianInvestor from "@/app_modules/investasi/fun/master/get_pencarian_investor";
|
|
||||||
import getPeriodeDeviden from "@/app_modules/investasi/fun/master/get_periode_deviden";
|
|
||||||
import getStatusInvestasi from "@/app_modules/investasi/fun/master/get_status_investasi";
|
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
|
|
||||||
const pencarianInvestor = await getPencarianInvestor();
|
// const pencarianInvestor = await getPencarianInvestor();
|
||||||
const periodeDeviden = await getPeriodeDeviden();
|
// const periodeDeviden = await getPeriodeDeviden();
|
||||||
const pembagianDeviden = await getPembagianDeviden();
|
// const pembagianDeviden = await getPembagianDeviden();
|
||||||
const statusInvestasi = await getStatusInvestasi();
|
// const statusInvestasi = await getStatusInvestasi();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<InvestasiCreate
|
{/* <InvestasiCreate
|
||||||
pencarianInvestor={pencarianInvestor as any}
|
pencarianInvestor={pencarianInvestor as any}
|
||||||
periodeDeviden={periodeDeviden as any}
|
periodeDeviden={periodeDeviden as any}
|
||||||
pembagianDeviden={pembagianDeviden as any}
|
pembagianDeviden={pembagianDeviden as any}
|
||||||
/>
|
/> */}
|
||||||
|
<InvestasiCreateNew />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,39 +1,39 @@
|
|||||||
import { investasi_funGetOneInvestasiById } from "@/app_modules/investasi/_fun";
|
import { investasi_funGetOneInvestasiById } from "@/app_modules/investasi/_fun";
|
||||||
import { Investasi_UiEditInvestasi } from "@/app_modules/investasi/_ui";
|
import { Investasi_UiEditInvestasi, Investasi_UiEditInvestasiNew } from "@/app_modules/investasi/_ui";
|
||||||
import getPembagianDeviden from "@/app_modules/investasi/fun/master/get_pembagian_deviden";
|
import getPembagianDeviden from "@/app_modules/investasi/fun/master/get_pembagian_deviden";
|
||||||
import getPencarianInvestor from "@/app_modules/investasi/fun/master/get_pencarian_investor";
|
import getPencarianInvestor from "@/app_modules/investasi/fun/master/get_pencarian_investor";
|
||||||
import getPeriodeDeviden from "@/app_modules/investasi/fun/master/get_periode_deviden";
|
import getPeriodeDeviden from "@/app_modules/investasi/fun/master/get_periode_deviden";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
|
|
||||||
export default async function Page({ params }: { params: { id: string } }) {
|
export default async function Page({ params }: { params: { id: string } }) {
|
||||||
const investasiId = params.id;
|
// const investasiId = params.id;
|
||||||
// console.log(investasiId);
|
|
||||||
|
|
||||||
const allData = await investasi_funGetOneInvestasiById({ investasiId });
|
// const allData = await investasi_funGetOneInvestasiById({ investasiId });
|
||||||
const dataInvestasi = _.omit(allData, [
|
// const dataInvestasi = _.omit(allData, [
|
||||||
"BeritaInvestasi",
|
// "BeritaInvestasi",
|
||||||
"DokumenInvestasi",
|
// "DokumenInvestasi",
|
||||||
"MasterPembagianDeviden",
|
// "MasterPembagianDeviden",
|
||||||
"MasterPencarianInvestor",
|
// "MasterPencarianInvestor",
|
||||||
"MasterProgresInvestasi",
|
// "MasterProgresInvestasi",
|
||||||
"MasterStatusInvestasi",
|
// "MasterStatusInvestasi",
|
||||||
"ProspektusInvestasi",
|
// "ProspektusInvestasi",
|
||||||
"MasterPeriodeDeviden",
|
// "MasterPeriodeDeviden",
|
||||||
"author",
|
// "author",
|
||||||
]);
|
// ]);
|
||||||
|
|
||||||
const listPencarian = await getPencarianInvestor();
|
// const listPencarian = await getPencarianInvestor();
|
||||||
const listPeriode = await getPeriodeDeviden();
|
// const listPeriode = await getPeriodeDeviden();
|
||||||
const listPembagian = await getPembagianDeviden();
|
// const listPembagian = await getPembagianDeviden();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Investasi_UiEditInvestasi
|
{/* <Investasi_UiEditInvestasi
|
||||||
dataInvestasi={dataInvestasi}
|
dataInvestasi={dataInvestasi}
|
||||||
pembagianDeviden={listPembagian}
|
pembagianDeviden={listPembagian}
|
||||||
pencarianInvestor={listPencarian}
|
pencarianInvestor={listPencarian}
|
||||||
periodeDeviden={listPeriode}
|
periodeDeviden={listPeriode}
|
||||||
/>
|
/> */}
|
||||||
|
<Investasi_UiEditInvestasiNew />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { Investasi_UiBeranda } from "@/app_modules/investasi/_ui";
|
import { Investasi_ViewBerandaNew } from "@/app_modules/investasi/_ui";
|
||||||
import { investasi_funGetAllPublish } from "@/app_modules/investasi/fun/get_all_investasi";
|
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
const allData = await investasi_funGetAllPublish({ page: 1 });
|
// const allData = await investasi_funGetAllPublish({ page: 1 });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Investasi_UiBeranda dataInvestasi={allData as any} />
|
{/* <Investasi_UiBeranda dataInvestasi={allData as any} /> */}
|
||||||
|
<Investasi_ViewBerandaNew />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,21 @@
|
|||||||
import { investasi_funGetPortofolioByStatusId } from "@/app_modules/investasi/_fun";
|
import { Investasi_UiPortofolioNew } from "@/app_modules/investasi/_ui";
|
||||||
import { Investasi_UiPortofolio } from "@/app_modules/investasi/_ui";
|
|
||||||
import getStatusInvestasi from "@/app_modules/investasi/fun/master/get_status_investasi";
|
|
||||||
|
|
||||||
export default async function Page({ params }: { params: { id: string } }) {
|
export default async function Page({ params }: { params: { id: string } }) {
|
||||||
const statusId = params.id;
|
// const statusId = params.id;
|
||||||
const listStatus = await getStatusInvestasi();
|
// const listStatus = await getStatusInvestasi();
|
||||||
const dataPortofolio = await investasi_funGetPortofolioByStatusId({
|
// const dataPortofolio = await investasi_funGetPortofolioByStatusId({
|
||||||
page: 1,
|
// page: 1,
|
||||||
statusId: statusId,
|
// statusId: statusId,
|
||||||
});
|
// });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Investasi_UiPortofolio
|
{/* <Investasi_UiPortofolio
|
||||||
statusId={statusId}
|
statusId={statusId}
|
||||||
listStatus={listStatus as any}
|
listStatus={listStatus as any}
|
||||||
dataPortofolio={dataPortofolio as any}
|
dataPortofolio={dataPortofolio as any}
|
||||||
/>
|
/> */}
|
||||||
|
<Investasi_UiPortofolioNew />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import { investasi_funGetSuccessTransactionById } from "@/app_modules/investasi/_fun";
|
import { Investasi_ViewSahamSayaNew } from "@/app_modules/investasi/_view/main/view_saham_saya_new";
|
||||||
import { Investasi_UiSahamSaya } from "@/app_modules/investasi/_ui";
|
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
const dataSaham = await investasi_funGetSuccessTransactionById({ page: 1 });
|
// const dataSaham = await investasi_funGetSuccessTransactionById({ page: 1 });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* <InvestasiSahamTerbeli listTransaksi={listTransaksi as any} /> */}
|
{/* <InvestasiSahamTerbeli listTransaksi={listTransaksi as any} /> */}
|
||||||
<Investasi_UiSahamSaya dataSaham={dataSaham as any} />
|
{/* <Investasi_UiSahamSaya dataSaham={dataSaham as any} /> */}
|
||||||
|
<Investasi_ViewSahamSayaNew />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import getMaster_StatusTransaksiInvestasi from "@/app_modules/investasi/fun/mast
|
|||||||
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
|
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
|
||||||
import { investasi_funGetTransaksiByUserId } from "@/app_modules/investasi/_fun";
|
import { investasi_funGetTransaksiByUserId } from "@/app_modules/investasi/_fun";
|
||||||
import { Investasi_UiDaftarTransaksi } from "@/app_modules/investasi/_ui";
|
import { Investasi_UiDaftarTransaksi } from "@/app_modules/investasi/_ui";
|
||||||
|
import { Investasi_ViewDaftarTransaksiNew } from "@/app_modules/investasi/_view/main/view_transaksi_new";
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
const userLoginId = await funGetUserIdByToken();
|
const userLoginId = await funGetUserIdByToken();
|
||||||
@@ -22,7 +23,8 @@ export default async function Page() {
|
|||||||
statusTransaksi={statusTransaksi as any}
|
statusTransaksi={statusTransaksi as any}
|
||||||
listTransaksi={listTransaksi as any}
|
listTransaksi={listTransaksi as any}
|
||||||
/> */}
|
/> */}
|
||||||
<Investasi_UiDaftarTransaksi dataTransaksi={dataTransaksi} />
|
{/* <Investasi_UiDaftarTransaksi dataTransaksi={dataTransaksi} /> */}
|
||||||
|
<Investasi_ViewDaftarTransaksiNew/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,13 @@ export default async function Layout({
|
|||||||
}: {
|
}: {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
|
const userId = await newFunGetUserId();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<RealtimeProvider
|
<RealtimeProvider
|
||||||
|
userId={userId}
|
||||||
WIBU_REALTIME_TOKEN={
|
WIBU_REALTIME_TOKEN={
|
||||||
ServerEnv.value?.NEXT_PUBLIC_WIBU_REALTIME_TOKEN as string
|
ServerEnv.value?.NEXT_PUBLIC_WIBU_REALTIME_TOKEN as string
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,9 @@
|
|||||||
import {
|
import { Notifikasi_UiMain } from "@/app_modules/notifikasi/_ui";
|
||||||
Notifikasi_UiCollaboration
|
|
||||||
} from "@/app_modules/notifikasi/_ui";
|
|
||||||
import notifikasi_getByUserId from "@/app_modules/notifikasi/fun/get/get_notifiaksi_by_id";
|
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
const listNotifikasi = await notifikasi_getByUserId({
|
|
||||||
page: 1,
|
|
||||||
kategoriApp: "Collaboration",
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Notifikasi_UiCollaboration listNotifikasi={listNotifikasi} />
|
<Notifikasi_UiMain />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,9 @@
|
|||||||
import { Notifikasi_UiDonasi } from "@/app_modules/notifikasi/_ui";
|
import { Notifikasi_UiMain } from "@/app_modules/notifikasi/_ui";
|
||||||
import notifikasi_getByUserId from "@/app_modules/notifikasi/fun/get/get_notifiaksi_by_id";
|
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
const listNotifikasi = await notifikasi_getByUserId({
|
|
||||||
page: 1,
|
|
||||||
kategoriApp: "Donasi",
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Notifikasi_UiDonasi listNotifikasi={listNotifikasi} />
|
<Notifikasi_UiMain />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,9 @@
|
|||||||
import { Notifikasi_UiEvent } from "@/app_modules/notifikasi/_ui";
|
import Notifikasi_UiMain from "@/app_modules/notifikasi/_ui/ui_notifikasi";
|
||||||
import notifikasi_getByUserId from "@/app_modules/notifikasi/fun/get/get_notifiaksi_by_id";
|
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
const listNotifikasi = await notifikasi_getByUserId({
|
|
||||||
page: 1,
|
|
||||||
kategoriApp: "Event",
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Notifikasi_UiEvent listNotifikasi={listNotifikasi} />
|
<Notifikasi_UiMain />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,9 @@
|
|||||||
import { Notifikasi_UiForum } from "@/app_modules/notifikasi/_ui";
|
import { Notifikasi_UiMain } from "@/app_modules/notifikasi/_ui";
|
||||||
import notifikasi_getByUserId from "@/app_modules/notifikasi/fun/get/get_notifiaksi_by_id";
|
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
const listNotifikasi = await notifikasi_getByUserId({
|
|
||||||
page: 1,
|
|
||||||
kategoriApp: "Forum",
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Notifikasi_UiForum listNotifikasi={listNotifikasi} />
|
<Notifikasi_UiMain />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,9 @@
|
|||||||
import { Notifikasi_UiDonasi, Notifikasi_UiInvestasi } from "@/app_modules/notifikasi/_ui";
|
import { Notifikasi_UiMain } from "@/app_modules/notifikasi/_ui";
|
||||||
import notifikasi_getByUserId from "@/app_modules/notifikasi/fun/get/get_notifiaksi_by_id";
|
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
const listNotifikasi = await notifikasi_getByUserId({
|
|
||||||
page: 1,
|
|
||||||
kategoriApp: "Investasi",
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Notifikasi_UiInvestasi listNotifikasi={listNotifikasi} />
|
<Notifikasi_UiMain />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,9 @@
|
|||||||
import { Notifikasi_UiJob } from "@/app_modules/notifikasi/_ui";
|
import { Notifikasi_UiMain } from "@/app_modules/notifikasi/_ui";
|
||||||
import notifikasi_getByUserId from "@/app_modules/notifikasi/fun/get/get_notifiaksi_by_id";
|
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
const listNotifikasi = await notifikasi_getByUserId({
|
|
||||||
page: 1,
|
|
||||||
kategoriApp: "Job",
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Notifikasi_UiJob listNotifikasi={listNotifikasi} />
|
<Notifikasi_UiMain />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,15 @@
|
|||||||
import { UIGlobal_LayoutHeaderTamplate } from "@/app_modules/_global/ui";
|
import { UIGlobal_LayoutHeaderTamplate } from "@/app_modules/_global/ui";
|
||||||
import { Notifikasi_UiNewLayout } from "@/app_modules/notifikasi/_ui";
|
import { Notifikasi_UiNewLayout } from "@/app_modules/notifikasi/_ui";
|
||||||
import { notifikasi_funGetKategoriApp } from "@/app_modules/notifikasi/fun/get/fun_get_kategori_app";
|
|
||||||
|
|
||||||
export default async function Layout({
|
export default async function Layout({
|
||||||
children,
|
children,
|
||||||
}: {
|
}: {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}) {
|
}) {
|
||||||
const masterKategori = await notifikasi_funGetKategoriApp();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Notifikasi_UiNewLayout
|
<Notifikasi_UiNewLayout
|
||||||
header={<UIGlobal_LayoutHeaderTamplate title="Notifikasi" />}
|
header={<UIGlobal_LayoutHeaderTamplate title="Notifikasi" />}
|
||||||
masterKategori={masterKategori}
|
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</Notifikasi_UiNewLayout>
|
</Notifikasi_UiNewLayout>
|
||||||
|
|||||||
@@ -1,15 +1,9 @@
|
|||||||
import { Notifikasi_UiAll } from "@/app_modules/notifikasi/_ui";
|
import { Notifikasi_UiMain } from "@/app_modules/notifikasi/_ui";
|
||||||
import notifikasi_getByUserId from "@/app_modules/notifikasi/fun/get/get_notifiaksi_by_id";
|
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
const listNotifikasi = await notifikasi_getByUserId({
|
|
||||||
page: 1,
|
|
||||||
kategoriApp: "Semua",
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Notifikasi_UiAll listNotifikasi={listNotifikasi} />
|
<Notifikasi_UiMain />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,9 @@
|
|||||||
import { Notifikasi_UiVoting } from "@/app_modules/notifikasi/_ui";
|
import { Notifikasi_UiMain } from "@/app_modules/notifikasi/_ui";
|
||||||
import notifikasi_getByUserId from "@/app_modules/notifikasi/fun/get/get_notifiaksi_by_id";
|
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
const listNotifikasi = await notifikasi_getByUserId({
|
|
||||||
page: 1,
|
|
||||||
kategoriApp: "Voting",
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Notifikasi_UiVoting listNotifikasi={listNotifikasi} />
|
<Notifikasi_UiMain />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
15
src/app/lib/api_user_router/route_api_notifikasi.ts
Normal file
15
src/app/lib/api_user_router/route_api_notifikasi.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { ICategoryapp } from "@/app_modules/notifikasi/model/interface";
|
||||||
|
|
||||||
|
export const API_RouteNotifikasi = {
|
||||||
|
get_all_by_category: ({
|
||||||
|
category,
|
||||||
|
page,
|
||||||
|
}: {
|
||||||
|
category: ICategoryapp;
|
||||||
|
page: number;
|
||||||
|
}) => `/api/notifikasi/get-all-by-category?category=${category}&page=${page}`,
|
||||||
|
|
||||||
|
get_master_kategori: () => `/api/notifikasi/master`,
|
||||||
|
|
||||||
|
get_count_by_id: () => `/api/notifikasi/count`,
|
||||||
|
};
|
||||||
@@ -42,7 +42,7 @@ export type IRealtimeData = {
|
|||||||
export const gs_realtimeData = atom<IRealtimeData | null>(null);
|
export const gs_realtimeData = atom<IRealtimeData | null>(null);
|
||||||
export const gs_admin_ntf = atom<number>(0);
|
export const gs_admin_ntf = atom<number>(0);
|
||||||
export const gs_user_ntf = atom<number>(0);
|
export const gs_user_ntf = atom<number>(0);
|
||||||
export const gs_count_ntf = atom<number>(0);
|
export const gs_count_ntf = atom<number | null>(null);
|
||||||
|
|
||||||
// job
|
// job
|
||||||
export const gs_adminJob_triggerReview = atom<boolean>(false);
|
export const gs_adminJob_triggerReview = atom<boolean>(false);
|
||||||
|
|||||||
@@ -1,28 +1,30 @@
|
|||||||
import { PrismaClient } from '@prisma/client';
|
import { PrismaClient } from "@prisma/client";
|
||||||
|
|
||||||
// Singleton PrismaClient untuk pengembangan
|
// Singleton PrismaClient untuk pengembangan
|
||||||
const globalForPrisma = globalThis as unknown as {
|
const globalForPrisma = globalThis as unknown as {
|
||||||
__prisma__: PrismaClient | undefined;
|
__prisma__: PrismaClient | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const prisma = globalForPrisma.__prisma__ ?? new PrismaClient({
|
export const prisma =
|
||||||
// log: process.env.NODE_ENV === 'development' ? ['query', 'info', 'warn', 'error'] : [],
|
globalForPrisma.__prisma__ ??
|
||||||
});
|
new PrismaClient({
|
||||||
|
// log: process.env.NODE_ENV === 'development' ? ['query', 'info', 'warn', 'error'] : [],
|
||||||
|
});
|
||||||
|
|
||||||
// Gunakan PrismaClient yang sama jika sudah ada
|
// Gunakan PrismaClient yang sama jika sudah ada
|
||||||
if (process.env.NODE_ENV !== 'production') {
|
if (process.env.NODE_ENV !== "production") {
|
||||||
if (!globalForPrisma.__prisma__) {
|
if (!globalForPrisma.__prisma__) {
|
||||||
console.log('PrismaClient initialized in development mode');
|
console.log("PrismaClient initialized in development mode");
|
||||||
}
|
}
|
||||||
globalForPrisma.__prisma__ = prisma;
|
globalForPrisma.__prisma__ = prisma;
|
||||||
}
|
}
|
||||||
|
|
||||||
process.on('SIGINT', async () => {
|
process.on("SIGINT", async () => {
|
||||||
console.log('Disconnecting PrismaClient...');
|
console.log("Disconnecting PrismaClient...");
|
||||||
await prisma.$disconnect();
|
await prisma.$disconnect();3
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
// console.log('==> Test prisma');
|
// console.log("==> Test prisma");
|
||||||
|
|
||||||
export default prisma;
|
export default prisma;
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ import {
|
|||||||
gs_votingTiggerBeranda,
|
gs_votingTiggerBeranda,
|
||||||
IRealtimeData,
|
IRealtimeData,
|
||||||
} from "./global_state";
|
} from "./global_state";
|
||||||
import { newFunGetUserId } from "./new_fun_user_id";
|
|
||||||
import { useState } from "react";
|
|
||||||
|
|
||||||
// const WIBU_REALTIME_TOKEN: string | undefined =
|
// const WIBU_REALTIME_TOKEN: string | undefined =
|
||||||
// process.env.NEXT_PUBLIC_WIBU_REALTIME_TOKEN;
|
// process.env.NEXT_PUBLIC_WIBU_REALTIME_TOKEN;
|
||||||
@@ -28,15 +26,16 @@ export type TypeNotification = {
|
|||||||
type: "message" | "notification" | "trigger";
|
type: "message" | "notification" | "trigger";
|
||||||
pushNotificationTo: "ADMIN" | "USER";
|
pushNotificationTo: "ADMIN" | "USER";
|
||||||
dataMessage?: IRealtimeData;
|
dataMessage?: IRealtimeData;
|
||||||
userLoginId?: string;
|
userId?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function RealtimeProvider({
|
export default function RealtimeProvider({
|
||||||
|
userId,
|
||||||
WIBU_REALTIME_TOKEN,
|
WIBU_REALTIME_TOKEN,
|
||||||
}: {
|
}: {
|
||||||
|
userId: string;
|
||||||
WIBU_REALTIME_TOKEN: string;
|
WIBU_REALTIME_TOKEN: string;
|
||||||
}) {
|
}) {
|
||||||
const [userLoginId, setUserLoginId] = useState("");
|
|
||||||
const [dataRealtime, setDataRealtime] = useAtom(gs_realtimeData);
|
const [dataRealtime, setDataRealtime] = useAtom(gs_realtimeData);
|
||||||
const [newAdminNtf, setNewAdminNtf] = useAtom(gs_admin_ntf);
|
const [newAdminNtf, setNewAdminNtf] = useAtom(gs_admin_ntf);
|
||||||
const [newUserNtf, setNewUserNtf] = useAtom(gs_user_ntf);
|
const [newUserNtf, setNewUserNtf] = useAtom(gs_user_ntf);
|
||||||
@@ -72,15 +71,7 @@ export default function RealtimeProvider({
|
|||||||
gs_donasiTriggerBeranda
|
gs_donasiTriggerBeranda
|
||||||
);
|
);
|
||||||
|
|
||||||
async function loadUserId() {
|
|
||||||
const userId = await newFunGetUserId();
|
|
||||||
|
|
||||||
setUserLoginId(userId as string);
|
|
||||||
}
|
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
loadUserId();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
WibuRealtime.init({
|
WibuRealtime.init({
|
||||||
project: "hipmi",
|
project: "hipmi",
|
||||||
@@ -97,7 +88,7 @@ export default function RealtimeProvider({
|
|||||||
if (
|
if (
|
||||||
data.type == "notification" &&
|
data.type == "notification" &&
|
||||||
data.pushNotificationTo == "USER" &&
|
data.pushNotificationTo == "USER" &&
|
||||||
data.dataMessage?.userId == userLoginId
|
data.dataMessage?.userId == userId
|
||||||
) {
|
) {
|
||||||
setNewUserNtf((e) => e + 1);
|
setNewUserNtf((e) => e + 1);
|
||||||
setDataRealtime(data.dataMessage as any);
|
setDataRealtime(data.dataMessage as any);
|
||||||
@@ -144,7 +135,7 @@ export default function RealtimeProvider({
|
|||||||
data.type == "notification" &&
|
data.type == "notification" &&
|
||||||
data.pushNotificationTo == "USER" &&
|
data.pushNotificationTo == "USER" &&
|
||||||
data.dataMessage?.status == "Peserta Event" &&
|
data.dataMessage?.status == "Peserta Event" &&
|
||||||
userLoginId !== data.dataMessage?.userId
|
userId !== data.dataMessage?.userId
|
||||||
) {
|
) {
|
||||||
setNewUserNtf((e) => e + 1);
|
setNewUserNtf((e) => e + 1);
|
||||||
}
|
}
|
||||||
@@ -172,7 +163,7 @@ export default function RealtimeProvider({
|
|||||||
data.type == "notification" &&
|
data.type == "notification" &&
|
||||||
data.pushNotificationTo == "USER" &&
|
data.pushNotificationTo == "USER" &&
|
||||||
data.dataMessage?.status == "Voting Masuk" &&
|
data.dataMessage?.status == "Voting Masuk" &&
|
||||||
userLoginId !== data.dataMessage?.userId
|
userId !== data.dataMessage?.userId
|
||||||
) {
|
) {
|
||||||
setNewUserNtf((e) => e + 1);
|
setNewUserNtf((e) => e + 1);
|
||||||
}
|
}
|
||||||
@@ -200,9 +191,9 @@ export default function RealtimeProvider({
|
|||||||
// data.type == "notification" &&
|
// data.type == "notification" &&
|
||||||
// data.pushNotificationTo == "ADMIN" &&
|
// data.pushNotificationTo == "ADMIN" &&
|
||||||
// data.dataMessage?.status == "Menunggu" &&
|
// data.dataMessage?.status == "Menunggu" &&
|
||||||
// userLoginId !== data.dataMessage?.userId
|
// userId !== data.dataMessage?.userId
|
||||||
// ) {
|
// ) {
|
||||||
// console.log("yes");
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// ---------------------- DONASI ------------------------- //
|
// ---------------------- DONASI ------------------------- //
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ import { useShallowEffect } from "@mantine/hooks";
|
|||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
const router = useRouter()
|
const router = useRouter();
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// window.location.replace("/dev/home");
|
// window.location.replace("/dev/home");
|
||||||
router.replace("/dev/home");
|
router.replace("/dev/home", { scroll: false });
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export default function Page() {
|
|||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("file", filePP as any);
|
formData.append("file", filePP as any);
|
||||||
|
|
||||||
const res = await fetch("/api/upload", {
|
const res = await fetch("/api/image/upload", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: formData,
|
body: formData,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { MainColor } from "../color";
|
|||||||
import { MAX_SIZE } from "../lib";
|
import { MAX_SIZE } from "../lib";
|
||||||
import { PemberitahuanMaksimalFile } from "../lib/max_size";
|
import { PemberitahuanMaksimalFile } from "../lib/max_size";
|
||||||
import { ComponentGlobal_NotifikasiPeringatan } from "../notif_global";
|
import { ComponentGlobal_NotifikasiPeringatan } from "../notif_global";
|
||||||
|
import { clientLogger } from "@/util/clientLogger";
|
||||||
|
|
||||||
export function ComponentGlobal_ButtonUploadFileImage({
|
export function ComponentGlobal_ButtonUploadFileImage({
|
||||||
onSetFile,
|
onSetFile,
|
||||||
@@ -24,12 +25,13 @@ export function ComponentGlobal_ButtonUploadFileImage({
|
|||||||
|
|
||||||
if (files.size > MAX_SIZE) {
|
if (files.size > MAX_SIZE) {
|
||||||
ComponentGlobal_NotifikasiPeringatan(PemberitahuanMaksimalFile);
|
ComponentGlobal_NotifikasiPeringatan(PemberitahuanMaksimalFile);
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
onSetFile(files);
|
onSetFile(files);
|
||||||
onSetImage(buffer);
|
onSetImage(buffer);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
clientLogger.error("Upload error:", error);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
accept="image/png,image/jpeg"
|
accept="image/png,image/jpeg"
|
||||||
|
|||||||
@@ -1,24 +1,50 @@
|
|||||||
export async function funGlobal_DeleteFileById({ fileId }: { fileId: string }) {
|
import { clientLogger } from "@/util/clientLogger";
|
||||||
try {
|
|
||||||
const res = await fetch(
|
|
||||||
`https://wibu-storage.wibudev.com/api/files/${fileId}/delete`,
|
|
||||||
{
|
|
||||||
method: "DELETE",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${process.env.WS_APIKEY}`,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (res.ok) {
|
export async function funGlobal_DeleteFileById({
|
||||||
const hasil = await res.json();
|
fileId,
|
||||||
return { success: true };
|
dirId,
|
||||||
|
}: {
|
||||||
|
fileId: string;
|
||||||
|
dirId?: string;
|
||||||
|
}) {
|
||||||
|
try {
|
||||||
|
const res = await fetch("/api/image/delete", {
|
||||||
|
method: "DELETE",
|
||||||
|
body: JSON.stringify({ fileId, dirId }),
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
if (data.success) {
|
||||||
|
clientLogger.info(`File ${fileId} deleted successfully`);
|
||||||
|
return { success: true, message: "File berhasil dihapus" };
|
||||||
} else {
|
} else {
|
||||||
const errorText = await res.json();
|
return { success: false, message: data.message };
|
||||||
return { success: false };
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return { success: false };
|
|
||||||
console.error("Upload error:", error);
|
console.error("Upload error:", error);
|
||||||
|
return { success: false, message: "An unexpected error occurred" };
|
||||||
}
|
}
|
||||||
|
// try {
|
||||||
|
// const res = await fetch(
|
||||||
|
// `https://wibu-storage.wibudev.com/api/files/${fileId}/delete`,
|
||||||
|
// {
|
||||||
|
// method: "DELETE",
|
||||||
|
// headers: {
|
||||||
|
// Authorization: `Bearer ${process.env.WS_APIKEY}`,
|
||||||
|
// },
|
||||||
|
// }
|
||||||
|
// );
|
||||||
|
|
||||||
|
// if (res.ok) {
|
||||||
|
// const hasil = await res.json();
|
||||||
|
// return { success: true, message: "File berhasil dihapus" };
|
||||||
|
// } else {
|
||||||
|
// const errorText = await res.json();
|
||||||
|
// return { success: false, message: errorText.message };
|
||||||
|
// }
|
||||||
|
// } catch (error) {
|
||||||
|
// console.error("Upload error:", error);
|
||||||
|
// return { success: false, message: "An unexpected error occurred" };
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
11
src/app_modules/_global/fun/get/fun_get_directory_name.ts
Normal file
11
src/app_modules/_global/fun/get/fun_get_directory_name.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { DIRECTORY_ID } from "@/app/lib";
|
||||||
|
|
||||||
|
export async function funGetDirectoryNameByValue({
|
||||||
|
value,
|
||||||
|
}: {
|
||||||
|
value?: string | null;
|
||||||
|
}) {
|
||||||
|
if (!value) return null;
|
||||||
|
const object: any = DIRECTORY_ID;
|
||||||
|
return Object.keys(object).find((key) => object[key] === value);
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
import { funGlobal_CheckProfile } from "./fun_check_profile";
|
import { funGlobal_CheckProfile } from "./fun_check_profile";
|
||||||
|
import { funGetDirectoryNameByValue } from "./fun_get_directory_name";
|
||||||
import { funGlobal_getNomorAdmin } from "./fun_get_nomor_admin";
|
import { funGlobal_getNomorAdmin } from "./fun_get_nomor_admin";
|
||||||
import { funGetUserIdByToken } from "./fun_get_user_id_by_token";
|
import { funGetUserIdByToken } from "./fun_get_user_id_by_token";
|
||||||
import { funGlobal_getMasterKategoriApp } from "./fun_master_kategori_app";
|
import { funGlobal_getMasterKategoriApp } from "./fun_master_kategori_app";
|
||||||
@@ -8,3 +8,4 @@ export { funGlobal_getMasterKategoriApp };
|
|||||||
export { funGlobal_getNomorAdmin };
|
export { funGlobal_getNomorAdmin };
|
||||||
export { funGetUserIdByToken };
|
export { funGetUserIdByToken };
|
||||||
export { funGlobal_CheckProfile };
|
export { funGlobal_CheckProfile };
|
||||||
|
export { funGetDirectoryNameByValue };
|
||||||
|
|||||||
@@ -32,38 +32,20 @@ export async function funGlobal_UploadToStorage({
|
|||||||
console.error("File terlalu besar");
|
console.error("File terlalu besar");
|
||||||
return { success: false, message: "File size exceeds limit" };
|
return { success: false, message: "File size exceeds limit" };
|
||||||
}
|
}
|
||||||
|
|
||||||
const controller = new AbortController();
|
|
||||||
const timeoutId = setTimeout(() => controller.abort(), 30000); // Timeout 30 detik
|
|
||||||
|
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("file", file);
|
formData.append("file", file);
|
||||||
formData.append("dirId", dirId);
|
formData.append("dirId", dirId);
|
||||||
|
|
||||||
try {
|
const upload = await fetch("/api/image/upload", {
|
||||||
const res = await fetch("https://wibu-storage.wibudev.com/api/upload", {
|
method: "POST",
|
||||||
method: "POST",
|
body: formData,
|
||||||
body: formData,
|
});
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${Env_WS_APIKEY}`,
|
|
||||||
},
|
|
||||||
signal: controller.signal,
|
|
||||||
});
|
|
||||||
|
|
||||||
clearTimeout(timeoutId); // Bersihkan timeout jika selesai tepat waktu
|
const res = await upload.json();
|
||||||
|
|
||||||
if (res.ok) {
|
if (upload.ok) {
|
||||||
const dataRes = await res.json();
|
return { success: true, data: res.data, message: res.message };
|
||||||
return { success: true, data: dataRes.data };
|
} else {
|
||||||
} else {
|
return { success: false, data: {}, message: res.message };
|
||||||
const errorText = await res.text();
|
|
||||||
console.error("Error:", errorText);
|
|
||||||
return { success: false, message: errorText };
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
clearTimeout(timeoutId); //
|
|
||||||
|
|
||||||
console.error("Error:", error);
|
|
||||||
return { success: false, message: "An unexpected error occurred" };
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,18 +10,16 @@ import {
|
|||||||
Image,
|
Image,
|
||||||
rem,
|
rem,
|
||||||
ScrollArea,
|
ScrollArea,
|
||||||
Skeleton,
|
Skeleton
|
||||||
Text,
|
|
||||||
Title,
|
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import { useShallowEffect } from "@mantine/hooks";
|
import { useShallowEffect } from "@mantine/hooks";
|
||||||
import { IconX } from "@tabler/icons-react";
|
import { IconX } from "@tabler/icons-react";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { MainColor } from "../color";
|
import { MainColor } from "../color";
|
||||||
|
import ComponentGlobal_Loader from "../component/loader";
|
||||||
import UIGlobal_LayoutHeaderTamplate from "./ui_header_tamplate";
|
import UIGlobal_LayoutHeaderTamplate from "./ui_header_tamplate";
|
||||||
import { UIHeader } from "./ui_layout_tamplate";
|
import { UIHeader } from "./ui_layout_tamplate";
|
||||||
import ComponentGlobal_Loader from "../component/loader";
|
|
||||||
|
|
||||||
export function UIGlobal_ImagePreview({ fileId }: { fileId: string }) {
|
export function UIGlobal_ImagePreview({ fileId }: { fileId: string }) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import { IRealtimeData } from "@/app/lib/global_state";
|
||||||
import { RouterAdminJob } from "@/app/lib/router_admin/router_admin_job";
|
import { RouterAdminJob } from "@/app/lib/router_admin/router_admin_job";
|
||||||
import ComponentGlobal_InputCountDown from "@/app_modules/_global/component/input_countdown";
|
import ComponentGlobal_InputCountDown from "@/app_modules/_global/component/input_countdown";
|
||||||
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil";
|
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil";
|
||||||
@@ -8,7 +9,6 @@ import { ComponentAdminGlobal_TitlePage } from "@/app_modules/admin/_admin_globa
|
|||||||
import ComponentAdminGlobal_HeaderTamplate from "@/app_modules/admin/_admin_global/header_tamplate";
|
import ComponentAdminGlobal_HeaderTamplate from "@/app_modules/admin/_admin_global/header_tamplate";
|
||||||
import adminNotifikasi_funCreateToUser from "@/app_modules/admin/notifikasi/fun/create/fun_create_notif_user";
|
import adminNotifikasi_funCreateToUser from "@/app_modules/admin/notifikasi/fun/create/fun_create_notif_user";
|
||||||
import { MODEL_JOB } from "@/app_modules/job/model/interface";
|
import { MODEL_JOB } from "@/app_modules/job/model/interface";
|
||||||
import mqtt_client from "@/util/mqtt_client";
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Center,
|
Center,
|
||||||
@@ -22,11 +22,12 @@ import {
|
|||||||
Table,
|
Table,
|
||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput,
|
||||||
Textarea
|
Textarea,
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import { IconBan, IconPhotoCheck, IconSearch } from "@tabler/icons-react";
|
import { IconBan, IconPhotoCheck, IconSearch } from "@tabler/icons-react";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import { WibuRealtime } from "wibu-pkg";
|
||||||
import { AdminJob_funEditCatatanById } from "../../fun/edit/fun_edit_catatan_by_id";
|
import { AdminJob_funEditCatatanById } from "../../fun/edit/fun_edit_catatan_by_id";
|
||||||
import adminJob_getListReject from "../../fun/get/get_list_reject";
|
import adminJob_getListReject from "../../fun/get/get_list_reject";
|
||||||
|
|
||||||
@@ -311,7 +312,7 @@ async function onReject({
|
|||||||
const loadData = await adminJob_getListReject({ page: 1 });
|
const loadData = await adminJob_getListReject({ page: 1 });
|
||||||
onSetData(loadData);
|
onSetData(loadData);
|
||||||
|
|
||||||
const dataNotif = {
|
const dataNotifikasi: IRealtimeData = {
|
||||||
appId: reject.data?.id as any,
|
appId: reject.data?.id as any,
|
||||||
status: reject.data?.MasterStatus?.name as any,
|
status: reject.data?.MasterStatus?.name as any,
|
||||||
userId: reject.data?.authorId as any,
|
userId: reject.data?.authorId as any,
|
||||||
@@ -321,14 +322,15 @@ async function onReject({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const notif = await adminNotifikasi_funCreateToUser({
|
const notif = await adminNotifikasi_funCreateToUser({
|
||||||
data: dataNotif as any,
|
data: dataNotifikasi as any,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (notif.status === 201) {
|
if (notif.status === 201) {
|
||||||
mqtt_client.publish(
|
WibuRealtime.setData({
|
||||||
"USER",
|
type: "notification",
|
||||||
JSON.stringify({ userId: reject?.data?.authorId, count: 1 })
|
pushNotificationTo: "USER",
|
||||||
);
|
dataMessage: dataNotifikasi,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ComponentGlobal_NotifikasiBerhasil(reject.message);
|
ComponentGlobal_NotifikasiBerhasil(reject.message);
|
||||||
|
|||||||
@@ -65,13 +65,13 @@ export default function Register() {
|
|||||||
const result = await res.json();
|
const result = await res.json();
|
||||||
|
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
localStorage.removeItem("hipmi_auth_code_id");
|
|
||||||
ComponentGlobal_NotifikasiBerhasil(result.message);
|
ComponentGlobal_NotifikasiBerhasil(result.message);
|
||||||
router.push("/dev/home", { scroll: false });
|
localStorage.removeItem("hipmi_auth_code_id");
|
||||||
|
|
||||||
await auth_funDeleteAktivasiKodeOtpByNomor({
|
await auth_funDeleteAktivasiKodeOtpByNomor({
|
||||||
nomor: data.nomor,
|
nomor: data.nomor,
|
||||||
});
|
});
|
||||||
|
router.push("/dev/home", { scroll: false });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res.status === 400) {
|
if (res.status === 400) {
|
||||||
|
|||||||
@@ -59,11 +59,7 @@ export default function Validasi() {
|
|||||||
}
|
}
|
||||||
}, [triggerOtp]);
|
}, [triggerOtp]);
|
||||||
|
|
||||||
async function onCheckAuthCode({
|
async function onCheckAuthCode({ kodeId }: { kodeId: string }) {
|
||||||
kodeId,
|
|
||||||
}: {
|
|
||||||
kodeId: string;
|
|
||||||
}) {
|
|
||||||
const res = await fetch(`/api/auth/check?id=${kodeId}`);
|
const res = await fetch(`/api/auth/check?id=${kodeId}`);
|
||||||
const result = await res.json();
|
const result = await res.json();
|
||||||
|
|
||||||
@@ -97,37 +93,40 @@ export default function Validasi() {
|
|||||||
|
|
||||||
const result = await res.json();
|
const result = await res.json();
|
||||||
|
|
||||||
if (res.status === 200) {
|
if (res.status === 200 && result.roleId == "1") {
|
||||||
|
ComponentGlobal_NotifikasiBerhasil(result.message);
|
||||||
localStorage.removeItem("hipmi_auth_code_id");
|
localStorage.removeItem("hipmi_auth_code_id");
|
||||||
|
|
||||||
if (result.roleId === "1") {
|
|
||||||
ComponentGlobal_NotifikasiBerhasil(result.message);
|
|
||||||
router.push(RouterHome.main_home, { scroll: false });
|
|
||||||
// if (result.active === true) {
|
|
||||||
// } else {
|
|
||||||
// ComponentGlobal_NotifikasiBerhasil(result.message);
|
|
||||||
// router.push("/waiting-room", { scroll: false });
|
|
||||||
// }
|
|
||||||
} else {
|
|
||||||
ComponentGlobal_NotifikasiBerhasil("Admin Logged in");
|
|
||||||
router.push(RouterAdminDashboard.splash_admin, { scroll: false });
|
|
||||||
}
|
|
||||||
|
|
||||||
await auth_funDeleteAktivasiKodeOtpByNomor({
|
await auth_funDeleteAktivasiKodeOtpByNomor({
|
||||||
nomor: data.nomor,
|
nomor: data.nomor,
|
||||||
});
|
});
|
||||||
|
router.push(RouterHome.main_home, { scroll: false });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res.status === 200 && result.roleId != "1") {
|
||||||
|
ComponentGlobal_NotifikasiBerhasil("Admin Logged in");
|
||||||
|
localStorage.removeItem("hipmi_auth_code_id");
|
||||||
|
await auth_funDeleteAktivasiKodeOtpByNomor({
|
||||||
|
nomor: data.nomor,
|
||||||
|
});
|
||||||
|
router.push(RouterAdminDashboard.splash_admin, { scroll: false });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res.status === 404) {
|
if (res.status === 404) {
|
||||||
ComponentGlobal_NotifikasiBerhasil(result.message);
|
|
||||||
router.push("/register", { scroll: false });
|
router.push("/register", { scroll: false });
|
||||||
|
ComponentGlobal_NotifikasiBerhasil(result.message);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res.status === 400) {
|
if (res.status === 400) {
|
||||||
ComponentGlobal_NotifikasiPeringatan(result.message);
|
ComponentGlobal_NotifikasiPeringatan(result.message);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
3
src/app_modules/colab/component/index.ts
Normal file
3
src/app_modules/colab/component/index.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import { Collaboration_SkeletonCreate } from "./skeleton_view";
|
||||||
|
|
||||||
|
export { Collaboration_SkeletonCreate };
|
||||||
4
src/app_modules/colab/component/lib/api_collaboration.ts
Normal file
4
src/app_modules/colab/component/lib/api_collaboration.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export async function apiGetMasterCollaboration() {
|
||||||
|
const data = await fetch(`/api/collaboration/master`);
|
||||||
|
return await data.json().catch(() => null);
|
||||||
|
}
|
||||||
28
src/app_modules/colab/component/skeleton_view.tsx
Normal file
28
src/app_modules/colab/component/skeleton_view.tsx
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { Skeleton, Stack } from "@mantine/core";
|
||||||
|
|
||||||
|
export function Collaboration_SkeletonCreate() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack px={"xl"} spacing={"lg"}>
|
||||||
|
<Stack spacing={"xs"}>
|
||||||
|
<Skeleton height={10} width={50} />
|
||||||
|
<Skeleton height={40} />
|
||||||
|
</Stack>
|
||||||
|
<Stack spacing={"xs"}>
|
||||||
|
<Skeleton height={10} width={50} />
|
||||||
|
<Skeleton height={40} />
|
||||||
|
</Stack>
|
||||||
|
<Stack spacing={"xs"}>
|
||||||
|
<Skeleton height={10} width={50} />
|
||||||
|
<Skeleton height={130} />
|
||||||
|
</Stack>
|
||||||
|
<Stack spacing={"xs"}>
|
||||||
|
<Skeleton height={10} width={50} />
|
||||||
|
<Skeleton height={130} />
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Skeleton mt={50} height={40} radius={"xl"} />
|
||||||
|
</Stack>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -5,7 +5,15 @@ import ComponentGlobal_InputCountDown from "@/app_modules/_global/component/inpu
|
|||||||
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil";
|
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil";
|
||||||
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global/notifikasi_gagal";
|
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global/notifikasi_gagal";
|
||||||
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global/notifikasi_peringatan";
|
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global/notifikasi_peringatan";
|
||||||
import { Button, Select, Stack, TextInput, Textarea } from "@mantine/core";
|
import {
|
||||||
|
Button,
|
||||||
|
Center,
|
||||||
|
Select,
|
||||||
|
Stack,
|
||||||
|
TextInput,
|
||||||
|
Textarea,
|
||||||
|
Loader,
|
||||||
|
} from "@mantine/core";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import colab_funCreateProyek from "../fun/create/fun_create_proyek";
|
import colab_funCreateProyek from "../fun/create/fun_create_proyek";
|
||||||
@@ -13,12 +21,12 @@ import { MODEL_COLLABORATION_MASTER } from "../model/interface";
|
|||||||
import mqtt_client from "@/util/mqtt_client";
|
import mqtt_client from "@/util/mqtt_client";
|
||||||
import { useHookstate } from "@hookstate/core";
|
import { useHookstate } from "@hookstate/core";
|
||||||
import { useGsCollabCreate } from "../global_state/state";
|
import { useGsCollabCreate } from "../global_state/state";
|
||||||
|
import { useShallowEffect } from "@mantine/hooks";
|
||||||
|
import { apiGetMasterCollaboration } from "../component/lib/api_collaboration";
|
||||||
|
import { clientLogger } from "@/util/clientLogger";
|
||||||
|
import { Collaboration_SkeletonCreate } from "../component";
|
||||||
|
|
||||||
export default function Colab_Create({
|
export default function Colab_Create() {
|
||||||
listIndustri,
|
|
||||||
}: {
|
|
||||||
listIndustri: MODEL_COLLABORATION_MASTER[];
|
|
||||||
}) {
|
|
||||||
const [value, setValue] = useState({
|
const [value, setValue] = useState({
|
||||||
title: "",
|
title: "",
|
||||||
lokasi: "",
|
lokasi: "",
|
||||||
@@ -27,9 +35,38 @@ export default function Colab_Create({
|
|||||||
projectCollaborationMaster_IndustriId: 0,
|
projectCollaborationMaster_IndustriId: 0,
|
||||||
// jumlah_partisipan: 0,
|
// jumlah_partisipan: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [listIndustri, setListIndustri] = useState<
|
||||||
|
MODEL_COLLABORATION_MASTER[] | null
|
||||||
|
>(null);
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
onLoadMaster();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
async function onLoadMaster() {
|
||||||
|
try {
|
||||||
|
const respone = await apiGetMasterCollaboration();
|
||||||
|
if (respone.success) {
|
||||||
|
setListIndustri(respone.data);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
clientLogger.error("Error get master collaboration", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (listIndustri == null) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Collaboration_SkeletonCreate />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Stack px={"xl"} py={"md"}>
|
<Stack px={"xl"} pb={"md"}>
|
||||||
<TextInput
|
<TextInput
|
||||||
maxLength={100}
|
maxLength={100}
|
||||||
styles={{
|
styles={{
|
||||||
@@ -66,7 +103,7 @@ export default function Colab_Create({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Select
|
{/* <Select
|
||||||
styles={{
|
styles={{
|
||||||
label: {
|
label: {
|
||||||
color: "white",
|
color: "white",
|
||||||
@@ -85,7 +122,7 @@ export default function Colab_Create({
|
|||||||
projectCollaborationMaster_IndustriId: val as any,
|
projectCollaborationMaster_IndustriId: val as any,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/> */}
|
||||||
|
|
||||||
{/* <TextInput
|
{/* <TextInput
|
||||||
description={
|
description={
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
import { RouterDonasi } from "@/app/lib/router_hipmi/router_donasi";
|
||||||
|
import { AccentColor } from "@/app_modules/_global/color/color_pallet";
|
||||||
|
import { ComponentGlobal_LoadImageCustom } from "@/app_modules/_global/component";
|
||||||
|
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global/notifikasi_gagal";
|
||||||
|
import { Badge, Card, Grid, Group, Progress, Stack, Text } from "@mantine/core";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
import { IDataAllDonasiSaya } from "../../lib/type_donasi";
|
||||||
|
import ComponentDonasi_TampilanHitungMundur from "../tampilan_hitung_mundur";
|
||||||
|
import TampilanRupiahDonasi from "../tampilan_rupiah";
|
||||||
|
|
||||||
|
export function ComponentDonasi_CardInvoiceNew({ data, }: { data: IDataAllDonasiSaya; }) {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
async function onCekInvoice() {
|
||||||
|
if (data.donasiMaster_StatusInvoiceId === "1") {
|
||||||
|
return router.push(RouterDonasi.detail_donasi_saya + `${data?.id}`);
|
||||||
|
} else {
|
||||||
|
if (data.donasiMaster_StatusInvoiceId === "2") {
|
||||||
|
return router.push(RouterDonasi.proses_transaksi + `${data?.id}`);
|
||||||
|
} else {
|
||||||
|
if (data.donasiMaster_StatusInvoiceId === "3") {
|
||||||
|
return router.push(RouterDonasi.invoice + `${data?.id}`);
|
||||||
|
} else {
|
||||||
|
ComponentGlobal_NotifikasiGagal("Gagal Melihat Invoice");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Card
|
||||||
|
style={{
|
||||||
|
backgroundColor: AccentColor.blue,
|
||||||
|
border: `2px solid ${AccentColor.darkblue}`,
|
||||||
|
padding: "15px",
|
||||||
|
cursor: "pointer",
|
||||||
|
borderRadius: "10px",
|
||||||
|
color: "white",
|
||||||
|
marginBottom: "15px",
|
||||||
|
}}
|
||||||
|
onClick={() => onCekInvoice()}
|
||||||
|
>
|
||||||
|
<Stack>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={5}>
|
||||||
|
<Stack spacing={5}>
|
||||||
|
<Stack spacing={0}>
|
||||||
|
<Text fz={"xs"} fw={"bold"} truncate>
|
||||||
|
{data.title}
|
||||||
|
</Text>
|
||||||
|
<ComponentDonasi_TampilanHitungMundur
|
||||||
|
durasi={data.durasiDonasi}
|
||||||
|
publishTime={data.publishTime}
|
||||||
|
textSize={10}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
<Progress value={+data.progres} color="orange" />
|
||||||
|
<Group position="apart">
|
||||||
|
<Stack spacing={0}>
|
||||||
|
<Text fz={10}>Donasi Saya</Text>
|
||||||
|
<Text fz={10} fw={"bold"} c={"orange"} truncate>
|
||||||
|
<TampilanRupiahDonasi nominal={+data.nominal} />
|
||||||
|
</Text>
|
||||||
|
</Stack>
|
||||||
|
</Group>
|
||||||
|
<Badge size="xs" variant="filled" color="yellow">
|
||||||
|
<Text>{data.nameStatusInvoice}</Text>
|
||||||
|
</Badge>
|
||||||
|
</Stack>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={7}>
|
||||||
|
<ComponentGlobal_LoadImageCustom
|
||||||
|
height={150}
|
||||||
|
fileId={data.imageId}
|
||||||
|
/>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</Stack>
|
||||||
|
</Card>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -13,8 +13,6 @@ export default function ComponentDonasi_CardPublishNew({ data }: { data: any; })
|
|||||||
<>
|
<>
|
||||||
<ComponentGlobal_CardStyles
|
<ComponentGlobal_CardStyles
|
||||||
onClickHandler={() => {
|
onClickHandler={() => {
|
||||||
// DELSOON
|
|
||||||
console.log(RouterDonasi.detail_main + `${data.id}`)
|
|
||||||
router.push(RouterDonasi.detail_main + `${data.id}`)
|
router.push(RouterDonasi.detail_main + `${data.id}`)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
import { RouterDonasi } from "@/app/lib/router_hipmi/router_donasi";
|
||||||
|
import { ComponentGlobal_CardStyles, ComponentGlobal_LoadImageCustom } from "@/app_modules/_global/component";
|
||||||
|
import { Grid, Stack, Text } from "@mantine/core";
|
||||||
|
import { useParams, useRouter } from "next/navigation";
|
||||||
|
import { IDataAllDonasi } from "../../lib/type_donasi";
|
||||||
|
|
||||||
|
export function ComponentDonasi_CardStatusNew({ data }: { data: IDataAllDonasi; }) {
|
||||||
|
const router = useRouter();
|
||||||
|
const param = useParams<{ id: string }>();
|
||||||
|
|
||||||
|
function goToDetail() {
|
||||||
|
if (param.id == "2") {
|
||||||
|
router.push(RouterDonasi.detail_review + `${data.id}`);
|
||||||
|
} else if (param.id == "3") {
|
||||||
|
router.push(RouterDonasi.detail_draft + `${data.id}`);
|
||||||
|
} else if (param.id == "4") {
|
||||||
|
router.push(RouterDonasi.detail_reject + `${data.id}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ComponentGlobal_CardStyles onClickHandler={() => { goToDetail() }} >
|
||||||
|
<Stack>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={6}>
|
||||||
|
<ComponentGlobal_LoadImageCustom
|
||||||
|
fileId={data.imageId}
|
||||||
|
height={100}
|
||||||
|
/>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={6}>
|
||||||
|
<Stack spacing={"xs"}>
|
||||||
|
<Text fz={"sm"} fw={"bold"} lineClamp={2}>
|
||||||
|
{data.title}
|
||||||
|
</Text>
|
||||||
|
<Stack spacing={0}>
|
||||||
|
<Text fz={"sm"}>Target Dana</Text>
|
||||||
|
<Text fz={"sm"} fw={"bold"} c={"yellow"} lineClamp={1}>
|
||||||
|
Rp.{" "}
|
||||||
|
{new Intl.NumberFormat("id-ID", {
|
||||||
|
maximumFractionDigits: 10,
|
||||||
|
}).format(+data.target)}
|
||||||
|
</Text>
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</Stack>
|
||||||
|
</ComponentGlobal_CardStyles>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component";
|
import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component";
|
||||||
import { Box, Grid, Group, Skeleton, Stack } from "@mantine/core";
|
import { Box, Grid, Skeleton } from "@mantine/core";
|
||||||
|
|
||||||
export default function SkeletonDonasi() {
|
export default function SkeletonDonasi() {
|
||||||
return <>
|
return <>
|
||||||
|
|||||||
32
src/app_modules/donasi/component/skeleton_donasi_saya.tsx
Normal file
32
src/app_modules/donasi/component/skeleton_donasi_saya.tsx
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component";
|
||||||
|
import { Box, Grid, Skeleton } from "@mantine/core";
|
||||||
|
|
||||||
|
export default function SkeletonDonasiSaya() {
|
||||||
|
return <>
|
||||||
|
<Box>
|
||||||
|
{[...Array(3)].map((_, index) => (
|
||||||
|
<ComponentGlobal_CardStyles key={index}>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={6}>
|
||||||
|
<Box>
|
||||||
|
{[...Array(4)].map((_, index) => (
|
||||||
|
<Box key={index} py={5}>
|
||||||
|
<Grid align="center">
|
||||||
|
<Grid.Col span={12}>
|
||||||
|
<Skeleton w={"100%"} h={15} />
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</Box>
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={6}>
|
||||||
|
<Skeleton w={"100%"} height={100} radius="md" />
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</ComponentGlobal_CardStyles>
|
||||||
|
))}
|
||||||
|
</Box >
|
||||||
|
</>;
|
||||||
|
}
|
||||||
@@ -272,7 +272,7 @@ export default function CreateCeritaPenggalangDonasi({
|
|||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
withAsterisk
|
withAsterisk
|
||||||
placeholder="Maskuan nomor rekening"
|
placeholder="Masukan nomor rekening"
|
||||||
label="Nomor rekening"
|
label="Nomor rekening"
|
||||||
maxLength={100}
|
maxLength={100}
|
||||||
onChange={(val) => {
|
onChange={(val) => {
|
||||||
|
|||||||
264
src/app_modules/donasi/create/create_donasi_new.tsx
Normal file
264
src/app_modules/donasi/create/create_donasi_new.tsx
Normal file
@@ -0,0 +1,264 @@
|
|||||||
|
"use client";
|
||||||
|
import { DIRECTORY_ID } from "@/app/lib";
|
||||||
|
import { RouterDonasi } from "@/app/lib/router_hipmi/router_donasi";
|
||||||
|
import { MainColor } from "@/app_modules/_global/color/color_pallet";
|
||||||
|
import { ComponentGlobal_BoxUploadImage } from "@/app_modules/_global/component";
|
||||||
|
import ComponentGlobal_BoxInformation from "@/app_modules/_global/component/box_information";
|
||||||
|
import { funGlobal_UploadToStorage } from "@/app_modules/_global/fun";
|
||||||
|
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global";
|
||||||
|
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global/notifikasi_gagal";
|
||||||
|
import { AspectRatio, Button, FileButton, Group, Image, Select, Stack, Text, TextInput, } from "@mantine/core";
|
||||||
|
import { IconCamera, IconUpload } from "@tabler/icons-react";
|
||||||
|
import { useAtom } from "jotai";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
import { useState } from "react";
|
||||||
|
import Donasi_funCreateTemporary from "../fun/create/fun_create_donasi_temporary";
|
||||||
|
import { gs_donasi_tabs_posting } from "../global_state";
|
||||||
|
import { apiGetMasterDonasi } from "../lib/api_donasi";
|
||||||
|
import { useShallowEffect } from "@mantine/hooks";
|
||||||
|
|
||||||
|
export default function CreateDonasiNew() {
|
||||||
|
const router = useRouter();
|
||||||
|
const [loadingMaster, setLoadingMaster] = useState(true)
|
||||||
|
const [isLoading, setLoading] = useState(false);
|
||||||
|
const [kategori, setKategori] = useState<any[]>([]);
|
||||||
|
const [durasi, setDurasi] = useState<any[]>([]);
|
||||||
|
const [data, setData] = useState({
|
||||||
|
kategoriId: "",
|
||||||
|
title: "",
|
||||||
|
target: "",
|
||||||
|
durasiId: "",
|
||||||
|
});
|
||||||
|
const [targetDana, setTargetDana] = useState("");
|
||||||
|
const [file, setFile] = useState<File | null>(null);
|
||||||
|
const [img, setImg] = useState<any | null>();
|
||||||
|
const [tabsPostingDonasi, setTabsPostingDonasi] = useAtom(
|
||||||
|
gs_donasi_tabs_posting
|
||||||
|
);
|
||||||
|
|
||||||
|
async function onGetMaster() {
|
||||||
|
try {
|
||||||
|
setLoadingMaster(true)
|
||||||
|
const responseKategori = await apiGetMasterDonasi("?cat=kategori")
|
||||||
|
const responseDurasi = await apiGetMasterDonasi("?cat=durasi")
|
||||||
|
if (responseKategori.success) {
|
||||||
|
setKategori(responseKategori.data)
|
||||||
|
}
|
||||||
|
if (responseDurasi.success) {
|
||||||
|
setDurasi(responseDurasi.data)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
} finally {
|
||||||
|
setLoadingMaster(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
onGetMaster()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
async function onCreate() {
|
||||||
|
const body = {
|
||||||
|
donasiMaster_KategoriId: data.kategoriId,
|
||||||
|
donasiMaster_DurasiId: data.durasiId,
|
||||||
|
title: data.title,
|
||||||
|
target: targetDana,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_.values(body).includes(""))
|
||||||
|
return ComponentGlobal_NotifikasiPeringatan("Lengkapin Data");
|
||||||
|
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
|
const uploadImage = await funGlobal_UploadToStorage({
|
||||||
|
file: file as File,
|
||||||
|
dirId: DIRECTORY_ID.donasi_image,
|
||||||
|
});
|
||||||
|
if (!uploadImage.success) {
|
||||||
|
setLoading(false);
|
||||||
|
return ComponentGlobal_NotifikasiPeringatan("Gagal upload file gambar");
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await Donasi_funCreateTemporary({
|
||||||
|
data: body as any,
|
||||||
|
fileId: uploadImage.data.id,
|
||||||
|
});
|
||||||
|
if (res.status === 201) {
|
||||||
|
setTabsPostingDonasi("Review");
|
||||||
|
router.push(RouterDonasi.create_cerita_penggalang + `${res.donasiId}`);
|
||||||
|
} else {
|
||||||
|
ComponentGlobal_NotifikasiGagal(res.message);
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack spacing={"md"} px={"xl"}>
|
||||||
|
<ComponentGlobal_BoxInformation informasi="Lengkapi semua data di bawah untuk selanjutnya mengisi cerita Penggalangan Dana!" />
|
||||||
|
<Select
|
||||||
|
styles={{
|
||||||
|
label: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
label="Kategori"
|
||||||
|
placeholder={loadingMaster ? "Loading..." : "Pilih kategori penggalangan dana"}
|
||||||
|
withAsterisk
|
||||||
|
data={kategori.map((e) => ({
|
||||||
|
value: e.id,
|
||||||
|
label: e.name,
|
||||||
|
}))}
|
||||||
|
onChange={(val: string) =>
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
kategoriId: val,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Stack>
|
||||||
|
<TextInput
|
||||||
|
styles={{
|
||||||
|
label: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
withAsterisk
|
||||||
|
label="Judul Donasi"
|
||||||
|
placeholder="Contoh: Renovasi Masjid pada kampung, dll"
|
||||||
|
maxLength={100}
|
||||||
|
onChange={(val) => {
|
||||||
|
setData({ ...data, title: val.target.value });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
styles={{
|
||||||
|
label: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
icon={<Text fw={"bold"}>Rp.</Text>}
|
||||||
|
min={0}
|
||||||
|
withAsterisk
|
||||||
|
label="Target Dana"
|
||||||
|
placeholder="0"
|
||||||
|
value={data.target}
|
||||||
|
onChange={(val) => {
|
||||||
|
const match = val.currentTarget.value
|
||||||
|
.replace(/\./g, "")
|
||||||
|
.match(/^[0-9]+$/);
|
||||||
|
|
||||||
|
if (val.currentTarget.value === "")
|
||||||
|
return setData({
|
||||||
|
...data,
|
||||||
|
target: 0 + "",
|
||||||
|
});
|
||||||
|
if (!match?.[0]) return null;
|
||||||
|
|
||||||
|
const nilai = val.currentTarget.value.replace(/\./g, "");
|
||||||
|
const target = Intl.NumberFormat("id-ID").format(+nilai);
|
||||||
|
|
||||||
|
setTargetDana(nilai);
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
target,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Select
|
||||||
|
styles={{
|
||||||
|
label: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
label="Durasi"
|
||||||
|
placeholder={loadingMaster ? "Loading..." : "Jangka waktu penggalangan dana"}
|
||||||
|
withAsterisk
|
||||||
|
data={durasi.map((e) => ({
|
||||||
|
value: e.id,
|
||||||
|
label: e.name + " " + `hari`,
|
||||||
|
}))}
|
||||||
|
onChange={(val: string) => setData({ ...data, durasiId: val })}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Stack>
|
||||||
|
<ComponentGlobal_BoxUploadImage>
|
||||||
|
{img ? (
|
||||||
|
<AspectRatio ratio={1 / 1} mt={5} maw={300} mx={"auto"}>
|
||||||
|
<Image
|
||||||
|
style={{ maxHeight: 250 }}
|
||||||
|
alt="Foto"
|
||||||
|
height={250}
|
||||||
|
src={img}
|
||||||
|
/>
|
||||||
|
</AspectRatio>
|
||||||
|
) : (
|
||||||
|
<Stack justify="center" align="center" h={"100%"}>
|
||||||
|
<IconUpload color="white" />
|
||||||
|
<Text fz={10} fs={"italic"} c={"white"} fw={"bold"}>
|
||||||
|
Upload Gambar
|
||||||
|
</Text>
|
||||||
|
</Stack>
|
||||||
|
)}
|
||||||
|
</ComponentGlobal_BoxUploadImage>
|
||||||
|
|
||||||
|
{/* Upload Foto */}
|
||||||
|
<Group position="center">
|
||||||
|
<FileButton
|
||||||
|
onChange={async (files: any) => {
|
||||||
|
try {
|
||||||
|
const buffer = URL.createObjectURL(
|
||||||
|
new Blob([new Uint8Array(await files.arrayBuffer())])
|
||||||
|
);
|
||||||
|
setImg(buffer);
|
||||||
|
setFile(files);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
accept="image/png,image/jpeg"
|
||||||
|
>
|
||||||
|
{(props) => (
|
||||||
|
<Button
|
||||||
|
{...props}
|
||||||
|
leftIcon={<IconCamera color="black" />}
|
||||||
|
radius={50}
|
||||||
|
bg={MainColor.yellow}
|
||||||
|
color="yellow"
|
||||||
|
c={"black"}
|
||||||
|
>
|
||||||
|
Upload Gambar
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</FileButton>
|
||||||
|
</Group>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style={{
|
||||||
|
transition: "0.5s",
|
||||||
|
}}
|
||||||
|
disabled={_.values(data).includes("") || file === null ? true : false}
|
||||||
|
loaderPosition="center"
|
||||||
|
loading={isLoading ? true : false}
|
||||||
|
my={"lg"}
|
||||||
|
radius={"xl"}
|
||||||
|
onClick={() => onCreate()}
|
||||||
|
bg={MainColor.yellow}
|
||||||
|
color="yellow"
|
||||||
|
c={"black"}
|
||||||
|
>
|
||||||
|
Selanjutnya
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ import GalangDanaDonasi from "./main/galang_dana/ui_galang_dana";
|
|||||||
import GalangDanaDonasiNew from "./main/galang_dana/ui_galang_dana_new";
|
import GalangDanaDonasiNew from "./main/galang_dana/ui_galang_dana_new";
|
||||||
import DonasiSayaDonasi from "./main/donasi_saya";
|
import DonasiSayaDonasi from "./main/donasi_saya";
|
||||||
import CreateDonasi from "./create/create_donasi";
|
import CreateDonasi from "./create/create_donasi";
|
||||||
|
import CreateDonasiNew from "./create/create_donasi_new";
|
||||||
import LayoutCreateDonasi from "./create/layout";
|
import LayoutCreateDonasi from "./create/layout";
|
||||||
import DetailMainDonasi from "./detail/detail_main";
|
import DetailMainDonasi from "./detail/detail_main";
|
||||||
import LayoutDetailMainDonasi from "./detail/detail_main/layout";
|
import LayoutDetailMainDonasi from "./detail/detail_main/layout";
|
||||||
@@ -103,4 +104,5 @@ export {
|
|||||||
LayoutDonasi_EditRekening,
|
LayoutDonasi_EditRekening,
|
||||||
MainDonasiNew,
|
MainDonasiNew,
|
||||||
GalangDanaDonasiNew,
|
GalangDanaDonasiNew,
|
||||||
|
CreateDonasiNew
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,14 @@
|
|||||||
export const apiGetAllDonasi = async (path?: string) => {
|
export const apiGetAllDonasi = async (path?: string) => {
|
||||||
const response = await fetch(`/api/new/donasi${(path) ? path : ''}`)
|
const response = await fetch(`/api/new/donasi${(path) ? path : ''}`)
|
||||||
return await response.json().catch(() => null)
|
return await response.json().catch(() => null)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const apiGetMasterDonasi = async (path?: string) => {
|
||||||
|
const response = await fetch(`/api/new/donasi/master${(path) ? path : ''}`)
|
||||||
|
return await response.json().catch(() => null)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const apiGetAllDonasiSaya = async (path?: string) => {
|
||||||
|
const response = await fetch(`/api/new/donasi/invoice${(path) ? path : ''}`)
|
||||||
|
return await response.json().catch(() => null)
|
||||||
}
|
}
|
||||||
@@ -5,5 +5,19 @@ export interface IDataAllDonasi {
|
|||||||
publishTime: Date
|
publishTime: Date
|
||||||
progres: string
|
progres: string
|
||||||
terkumpul: string
|
terkumpul: string
|
||||||
|
target: string
|
||||||
nameDonasiDurasi: string
|
nameDonasiDurasi: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IDataAllDonasiSaya {
|
||||||
|
id: string
|
||||||
|
nominal: string
|
||||||
|
donasiMaster_StatusInvoiceId: string
|
||||||
|
nameStatusInvoice: string
|
||||||
|
donasiId: string
|
||||||
|
title: string
|
||||||
|
publishTime: Date
|
||||||
|
progres: string
|
||||||
|
imageId: string
|
||||||
|
durasiDonasi: string
|
||||||
}
|
}
|
||||||
@@ -37,7 +37,7 @@ export default function MainDonasiNew() {
|
|||||||
async function onLoadData({ onPublish }: { onPublish: (val: any) => void }) {
|
async function onLoadData({ onPublish }: { onPublish: (val: any) => void }) {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
const loadData = await apiGetAllDonasi(`?cat=beranda&page=1`)
|
const loadData = await apiGetAllDonasi(`?cat=beranda&page=1`)
|
||||||
onPublish(loadData);
|
onPublish(loadData.data)
|
||||||
|
|
||||||
setIsShowUpdate(false);
|
setIsShowUpdate(false);
|
||||||
setIsTriggerDonasiBeranda(false);
|
setIsTriggerDonasiBeranda(false);
|
||||||
@@ -117,7 +117,7 @@ export default function MainDonasiNew() {
|
|||||||
|
|
||||||
setActivePage((val) => val + 1);
|
setActivePage((val) => val + 1);
|
||||||
|
|
||||||
return loadData;
|
return loadData.data;
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{(item) => (
|
{(item) => (
|
||||||
|
|||||||
72
src/app_modules/donasi/main/donasi_saya_new.tsx
Normal file
72
src/app_modules/donasi/main/donasi_saya_new.tsx
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
"use client";
|
||||||
|
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
|
||||||
|
import ComponentGlobal_Loader from "@/app_modules/_global/component/loader";
|
||||||
|
import { Box, Center } from "@mantine/core";
|
||||||
|
import { useShallowEffect } from "@mantine/hooks";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { ScrollOnly } from "next-scroll-loader";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { ComponentDonasi_CardInvoiceNew } from "../component/card_view/card_invoice_new";
|
||||||
|
import SkeletonDonasiSaya from "../component/skeleton_donasi_saya";
|
||||||
|
import { apiGetAllDonasiSaya } from "../lib/api_donasi";
|
||||||
|
import { IDataAllDonasiSaya } from "../lib/type_donasi";
|
||||||
|
|
||||||
|
export default function DonasiSayaNew() {
|
||||||
|
const [data, setData] = useState<IDataAllDonasiSaya[]>([]);
|
||||||
|
const [activePage, setActivePage] = useState(1);
|
||||||
|
const [loading, setLoading] = useState(true)
|
||||||
|
|
||||||
|
async function getDataDonasiSaya() {
|
||||||
|
try {
|
||||||
|
setLoading(true)
|
||||||
|
const response = await apiGetAllDonasiSaya(`?page=1`)
|
||||||
|
if (response.success) {
|
||||||
|
setData(response.data);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
getDataDonasiSaya()
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Box>
|
||||||
|
{
|
||||||
|
loading ?
|
||||||
|
<SkeletonDonasiSaya />
|
||||||
|
:
|
||||||
|
_.isEmpty(data) ? (
|
||||||
|
<ComponentGlobal_IsEmptyData />
|
||||||
|
) : (
|
||||||
|
<ScrollOnly
|
||||||
|
height="82vh"
|
||||||
|
renderLoading={() => (
|
||||||
|
<Center>
|
||||||
|
<ComponentGlobal_Loader size={25} />
|
||||||
|
</Center>
|
||||||
|
)}
|
||||||
|
data={data}
|
||||||
|
setData={setData}
|
||||||
|
moreData={async () => {
|
||||||
|
const pageNew = activePage + 1
|
||||||
|
const loadData = await apiGetAllDonasiSaya(`?page=${pageNew}`)
|
||||||
|
setActivePage((val) => val + 1);
|
||||||
|
|
||||||
|
return loadData.data;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{(item) => <ComponentDonasi_CardInvoiceNew data={item} />}
|
||||||
|
</ScrollOnly>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
"use client";
|
||||||
|
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
|
||||||
|
import ComponentGlobal_Loader from "@/app_modules/_global/component/loader";
|
||||||
|
import { Box, Center } from "@mantine/core";
|
||||||
|
import { useShallowEffect } from "@mantine/hooks";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { ScrollOnly } from "next-scroll-loader";
|
||||||
|
import { useParams } from "next/navigation";
|
||||||
|
import { useState } from "react";
|
||||||
|
import ComponentDonasi_CardPublishNew from "../../component/card_view/card_publish_new";
|
||||||
|
import SkeletonDonasi from "../../component/skeleton_donasi";
|
||||||
|
import { apiGetAllDonasi } from "../../lib/api_donasi";
|
||||||
|
import { IDataAllDonasi } from "../../lib/type_donasi";
|
||||||
|
import { ComponentDonasi_CardStatusNew } from "../../component/card_view/card_status_new";
|
||||||
|
|
||||||
|
export default function Donasi_ViewGalangDanaNew() {
|
||||||
|
const param = useParams<{ id: string }>();;
|
||||||
|
const [data, setData] = useState<IDataAllDonasi[]>([]);
|
||||||
|
const [activePage, setActivePage] = useState(1);
|
||||||
|
const [loading, setLoading] = useState(true)
|
||||||
|
|
||||||
|
async function getDataGalangDana() {
|
||||||
|
try {
|
||||||
|
setLoading(true)
|
||||||
|
const response = await apiGetAllDonasi(`?cat=galang-dana&status=${param.id}&page=1`)
|
||||||
|
if (response.success) {
|
||||||
|
setData(response.data);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
getDataGalangDana()
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{
|
||||||
|
loading ? <SkeletonDonasi />
|
||||||
|
:
|
||||||
|
_.isEmpty(data) ? (
|
||||||
|
<ComponentGlobal_IsEmptyData />
|
||||||
|
) : (
|
||||||
|
<Box>
|
||||||
|
<ScrollOnly
|
||||||
|
height="75vh"
|
||||||
|
renderLoading={() => (
|
||||||
|
<Center>
|
||||||
|
<ComponentGlobal_Loader size={25} />
|
||||||
|
</Center>
|
||||||
|
)}
|
||||||
|
data={data}
|
||||||
|
setData={setData}
|
||||||
|
moreData={async () => {
|
||||||
|
const pageNew = activePage + 1
|
||||||
|
const loadData = await apiGetAllDonasi(`?cat=galang-dana&status=${param.id}&page=${pageNew}`)
|
||||||
|
setActivePage((val) => val + 1);
|
||||||
|
|
||||||
|
return loadData.data;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
param.id == "1" ?
|
||||||
|
(item) => (<ComponentDonasi_CardPublishNew data={item} />)
|
||||||
|
:
|
||||||
|
(item) => (<ComponentDonasi_CardStatusNew data={item} />)
|
||||||
|
|
||||||
|
}
|
||||||
|
</ScrollOnly>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,13 +1,31 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import { RouterDonasi } from "@/app/lib/router_hipmi/router_donasi";
|
import { RouterDonasi } from "@/app/lib/router_hipmi/router_donasi";
|
||||||
import { AccentColor, MainColor, } from "@/app_modules/_global/color/color_pallet";
|
import { AccentColor, MainColor, } from "@/app_modules/_global/color/color_pallet";
|
||||||
import { MODEL_NEW_DEFAULT_MASTER } from "@/app_modules/model_global/interface";
|
|
||||||
import { Stack, Tabs } from "@mantine/core";
|
import { Stack, Tabs } from "@mantine/core";
|
||||||
import { useParams, useRouter } from "next/navigation";
|
import { useParams, useRouter } from "next/navigation";
|
||||||
|
import Donasi_ViewGalangDanaNew from "./donasi_galang_dana_new";
|
||||||
|
|
||||||
export default function GalangDanaDonasiNew({listStatus,}: {listStatus: MODEL_NEW_DEFAULT_MASTER[]; }) {
|
export default function GalangDanaDonasiNew() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const param = useParams<{ id: string }>();
|
const param = useParams<{ id: string }>();
|
||||||
|
const status = [
|
||||||
|
{
|
||||||
|
id: "1",
|
||||||
|
name: "Publish"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "2",
|
||||||
|
name: "Review"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "3",
|
||||||
|
name: "Draft"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "4",
|
||||||
|
name: "Reject"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
async function onChangeStatus({ statusId }: { statusId: string }) {
|
async function onChangeStatus({ statusId }: { statusId: string }) {
|
||||||
router.replace(RouterDonasi.status_galang_dana({ id: statusId }));
|
router.replace(RouterDonasi.status_galang_dana({ id: statusId }));
|
||||||
@@ -34,7 +52,7 @@ export default function GalangDanaDonasiNew({listStatus,}: {listStatus: MODEL_NE
|
|||||||
>
|
>
|
||||||
<Stack>
|
<Stack>
|
||||||
<Tabs.List grow>
|
<Tabs.List grow>
|
||||||
{listStatus.map((e, i) => (
|
{status.map((e, i) => (
|
||||||
<Tabs.Tab
|
<Tabs.Tab
|
||||||
key={e.id}
|
key={e.id}
|
||||||
value={e.id}
|
value={e.id}
|
||||||
@@ -54,14 +72,7 @@ export default function GalangDanaDonasiNew({listStatus,}: {listStatus: MODEL_NE
|
|||||||
</Tabs.Tab>
|
</Tabs.Tab>
|
||||||
))}
|
))}
|
||||||
</Tabs.List>
|
</Tabs.List>
|
||||||
|
<Donasi_ViewGalangDanaNew />
|
||||||
{/* {param.id == "1" && <PostingPublishDonasi listPublish={dataStatus} />}
|
|
||||||
|
|
||||||
{param.id == "2" && <PostingReviewDonasi listReview={dataStatus} />}
|
|
||||||
|
|
||||||
{param.id == "3" && <PostingDraftDonasi listDraft={dataStatus} />}
|
|
||||||
|
|
||||||
{param.id == "4" && <PostingRejectDonasi listReject={dataStatus} />} */}
|
|
||||||
</Stack>
|
</Stack>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -1,7 +1,18 @@
|
|||||||
|
import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog";
|
||||||
import { AccentColor, MainColor } from "@/app_modules/_global/color";
|
import { AccentColor, MainColor } from "@/app_modules/_global/color";
|
||||||
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
|
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
|
||||||
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global";
|
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global";
|
||||||
import { ActionIcon, Box, Group, Image, Paper, SimpleGrid, Skeleton, Stack, Text } from "@mantine/core";
|
import {
|
||||||
|
ActionIcon,
|
||||||
|
Box,
|
||||||
|
Group,
|
||||||
|
Image,
|
||||||
|
Paper,
|
||||||
|
SimpleGrid,
|
||||||
|
Skeleton,
|
||||||
|
Stack,
|
||||||
|
Text,
|
||||||
|
} 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";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
@@ -11,183 +22,193 @@ import { apiGetDataHome } from "../fun/get/api_home";
|
|||||||
import { listMenuHomeBody, menuHomeJob } from "./list_menu_home";
|
import { listMenuHomeBody, menuHomeJob } from "./list_menu_home";
|
||||||
|
|
||||||
export default function BodyHome() {
|
export default function BodyHome() {
|
||||||
const router = useRouter()
|
const router = useRouter();
|
||||||
const [dataUser, setDataUser] = useState<any>({})
|
const [dataUser, setDataUser] = useState<any>({});
|
||||||
const [dataJob, setDataJob] = useState<any[]>([])
|
const [dataJob, setDataJob] = useState<any[]>([]);
|
||||||
const [loadingJob, setLoadingJob] = useState(true)
|
const [loadingJob, setLoadingJob] = useState(true);
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
cekUserLogin()
|
cekUserLogin();
|
||||||
getHomeJob()
|
getHomeJob();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
async function cekUserLogin() {
|
||||||
async function cekUserLogin() {
|
try {
|
||||||
try {
|
const response = await apiGetDataHome("?cat=cek_profile");
|
||||||
const response = await apiGetDataHome("?cat=cek_profile")
|
if (response.success) {
|
||||||
if (response.success) {
|
setDataUser(response.data);
|
||||||
setDataUser(response.data);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
}
|
}
|
||||||
}
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function getHomeJob() {
|
async function getHomeJob() {
|
||||||
try {
|
try {
|
||||||
setLoadingJob(true)
|
setLoadingJob(true);
|
||||||
const response = await apiGetDataHome("?cat=job")
|
const response = await apiGetDataHome("?cat=job");
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
setDataJob(response.data);
|
setDataJob(response.data);
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
} finally {
|
|
||||||
setLoadingJob(false)
|
|
||||||
}
|
}
|
||||||
}
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
} finally {
|
||||||
|
setLoadingJob(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Paper
|
<Paper
|
||||||
radius={"xl"}
|
radius={"xl"}
|
||||||
mb={"xs"}
|
mb={"xs"}
|
||||||
style={{
|
style={{
|
||||||
borderRadius: "10px 10px 10px 10px",
|
borderRadius: "10px 10px 10px 10px",
|
||||||
border: `2px solid ${AccentColor.blue}`,
|
border: `2px solid ${AccentColor.blue}`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Image radius={"lg"} alt="logo" src={"/aset/home/home-hipmi-new.png"} />
|
<Image radius={"lg"} alt="logo" src={"/aset/home/home-hipmi-new.png"} />
|
||||||
</Paper>
|
</Paper>
|
||||||
|
|
||||||
<Stack my={"sm"}>
|
<Stack my={"sm"}>
|
||||||
<SimpleGrid
|
<SimpleGrid cols={2} spacing="md">
|
||||||
cols={2}
|
{listMenuHomeBody.map((e, i) => (
|
||||||
spacing="md"
|
|
||||||
>
|
|
||||||
{listMenuHomeBody.map((e, i) => (
|
|
||||||
<Paper
|
|
||||||
key={e.id}
|
|
||||||
h={150}
|
|
||||||
bg={MainColor.darkblue}
|
|
||||||
style={{
|
|
||||||
borderRadius: "10px 10px 10px 10px",
|
|
||||||
border: `2px solid ${AccentColor.blue}`,
|
|
||||||
}}
|
|
||||||
onClick={() => {
|
|
||||||
if (dataUser.profile === undefined || dataUser?.profile === null) {
|
|
||||||
return ComponentGlobal_NotifikasiPeringatan(
|
|
||||||
"Lengkapi Profile"
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
if (e.link === "") {
|
|
||||||
return ComponentGlobal_NotifikasiPeringatan(
|
|
||||||
"Cooming Soon !!"
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
router.push(e.link, { scroll: false });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Stack align="center" justify="center" h={"100%"}>
|
|
||||||
<ActionIcon
|
|
||||||
size={50}
|
|
||||||
variant="transparent"
|
|
||||||
c={e.link === "" ? "gray.3" : "white"}
|
|
||||||
>
|
|
||||||
{e.icon}
|
|
||||||
</ActionIcon>
|
|
||||||
<Text c={e.link === "" ? "gray.3" : "white"} fz={"xs"}>
|
|
||||||
{e.name}
|
|
||||||
</Text>
|
|
||||||
</Stack>
|
|
||||||
</Paper>
|
|
||||||
))}
|
|
||||||
</SimpleGrid>
|
|
||||||
|
|
||||||
{/* Job View */}
|
|
||||||
<Paper
|
<Paper
|
||||||
p={"md"}
|
key={e.id}
|
||||||
w={"100%"}
|
h={150}
|
||||||
bg={MainColor.darkblue}
|
bg={MainColor.darkblue}
|
||||||
style={{
|
style={{
|
||||||
borderRadius: "10px 10px 10px 10px",
|
borderRadius: "10px 10px 10px 10px",
|
||||||
border: `2px solid ${AccentColor.blue}`,
|
border: `2px solid ${AccentColor.blue}`,
|
||||||
}}
|
}}
|
||||||
>
|
onClick={() => {
|
||||||
<Stack
|
if (
|
||||||
onClick={() => {
|
dataUser.profile == undefined ||
|
||||||
if (dataUser.profile === undefined || dataUser?.profile === null) {
|
dataUser?.profile == null ||
|
||||||
return ComponentGlobal_NotifikasiPeringatan(
|
dataJob.length == undefined ||
|
||||||
"Lengkapi Profile"
|
dataJob.length == null
|
||||||
);
|
) {
|
||||||
} else {
|
return null;
|
||||||
if (menuHomeJob.link === "") {
|
} else if (
|
||||||
return ComponentGlobal_NotifikasiPeringatan(
|
dataUser.profile == undefined ||
|
||||||
"Cooming Soon !!"
|
dataUser?.profile == null
|
||||||
);
|
) {
|
||||||
} else {
|
router.push(RouterProfile.create, { scroll: false });
|
||||||
return router.push(menuHomeJob.link, { scroll: false });
|
} else {
|
||||||
}
|
if (e.link == "") {
|
||||||
}
|
return ComponentGlobal_NotifikasiPeringatan(
|
||||||
}}
|
"Cooming Soon !!"
|
||||||
>
|
);
|
||||||
<Group>
|
} else {
|
||||||
<ActionIcon
|
router.push(e.link, { scroll: false });
|
||||||
variant="transparent"
|
|
||||||
size={40}
|
|
||||||
c={menuHomeJob.link === "" ? "gray.3" : "white"}
|
|
||||||
>
|
|
||||||
{menuHomeJob.icon}
|
|
||||||
</ActionIcon>
|
|
||||||
<Text c={menuHomeJob.link === "" ? "gray.3" : "white"}>
|
|
||||||
{menuHomeJob.name}
|
|
||||||
</Text>
|
|
||||||
</Group>
|
|
||||||
{
|
|
||||||
loadingJob ?
|
|
||||||
Array(2)
|
|
||||||
.fill(null)
|
|
||||||
.map((_, i) => (
|
|
||||||
<Box key={i} mb={"md"}>
|
|
||||||
<Skeleton height={10} mt={0} radius="xl" width={"50%"} />
|
|
||||||
<Skeleton height={10} mt={10} radius="xl" />
|
|
||||||
<Skeleton height={10} mt={10} radius="xl" />
|
|
||||||
</Box>
|
|
||||||
))
|
|
||||||
: _.isEmpty(dataJob) ?
|
|
||||||
(<ComponentGlobal_IsEmptyData text="Tidak ada data" height={10} />)
|
|
||||||
: (
|
|
||||||
<SimpleGrid cols={2} spacing="md">
|
|
||||||
{dataJob.map((e, i) => (
|
|
||||||
<Stack key={e.id}>
|
|
||||||
<Group spacing={"xs"}>
|
|
||||||
<Stack h={"100%"} align="center" justify="flex-start">
|
|
||||||
<IconUserSearch size={20} color="white" />
|
|
||||||
</Stack>
|
|
||||||
<Stack spacing={0} w={"60%"}>
|
|
||||||
<Text
|
|
||||||
lineClamp={1}
|
|
||||||
fz={"sm"}
|
|
||||||
c={MainColor.yellow}
|
|
||||||
fw={"bold"}
|
|
||||||
>
|
|
||||||
{e?.Author.username}
|
|
||||||
</Text>
|
|
||||||
<Text fz={"sm"} c={"white"} lineClamp={2}>
|
|
||||||
{e?.title}
|
|
||||||
</Text>
|
|
||||||
</Stack>
|
|
||||||
</Group>
|
|
||||||
</Stack>
|
|
||||||
))}
|
|
||||||
</SimpleGrid>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
</Stack>
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Stack align="center" justify="center" h={"100%"}>
|
||||||
|
<ActionIcon
|
||||||
|
size={50}
|
||||||
|
variant="transparent"
|
||||||
|
c={e.link == "" ? "gray.3" : "white"}
|
||||||
|
>
|
||||||
|
{e.icon}
|
||||||
|
</ActionIcon>
|
||||||
|
<Text c={e.link == "" ? "gray.3" : "white"} fz={"xs"}>
|
||||||
|
{e.name}
|
||||||
|
</Text>
|
||||||
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Stack>
|
))}
|
||||||
</Box>
|
</SimpleGrid>
|
||||||
);
|
|
||||||
}
|
{/* Job View */}
|
||||||
|
<Paper
|
||||||
|
p={"md"}
|
||||||
|
w={"100%"}
|
||||||
|
bg={MainColor.darkblue}
|
||||||
|
style={{
|
||||||
|
borderRadius: "10px 10px 10px 10px",
|
||||||
|
border: `2px solid ${AccentColor.blue}`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Stack
|
||||||
|
onClick={() => {
|
||||||
|
if (
|
||||||
|
dataUser.profile == undefined ||
|
||||||
|
dataUser?.profile == null ||
|
||||||
|
dataJob.length == undefined ||
|
||||||
|
dataJob.length == null
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
} else if (
|
||||||
|
dataUser.profile == undefined ||
|
||||||
|
dataUser?.profile == null
|
||||||
|
) {
|
||||||
|
router.push(RouterProfile.create, { scroll: false });
|
||||||
|
} else {
|
||||||
|
if (menuHomeJob.link == "") {
|
||||||
|
return ComponentGlobal_NotifikasiPeringatan(
|
||||||
|
"Cooming Soon !!"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return router.push(menuHomeJob.link, { scroll: false });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Group>
|
||||||
|
<ActionIcon
|
||||||
|
variant="transparent"
|
||||||
|
size={40}
|
||||||
|
c={menuHomeJob.link == "" ? "gray.3" : "white"}
|
||||||
|
>
|
||||||
|
{menuHomeJob.icon}
|
||||||
|
</ActionIcon>
|
||||||
|
<Text c={menuHomeJob.link == "" ? "gray.3" : "white"}>
|
||||||
|
{menuHomeJob.name}
|
||||||
|
</Text>
|
||||||
|
</Group>
|
||||||
|
{loadingJob ? (
|
||||||
|
Array(2)
|
||||||
|
.fill(null)
|
||||||
|
.map((_, i) => (
|
||||||
|
<Box key={i} mb={"md"}>
|
||||||
|
<Skeleton height={10} mt={0} radius="xl" width={"50%"} />
|
||||||
|
<Skeleton height={10} mt={10} radius="xl" />
|
||||||
|
<Skeleton height={10} mt={10} radius="xl" />
|
||||||
|
</Box>
|
||||||
|
))
|
||||||
|
) : _.isEmpty(dataJob) ? (
|
||||||
|
<ComponentGlobal_IsEmptyData text="Tidak ada data" height={10} />
|
||||||
|
) : (
|
||||||
|
<SimpleGrid cols={2} spacing="md">
|
||||||
|
{dataJob.map((e, i) => (
|
||||||
|
<Stack key={e.id}>
|
||||||
|
<Group spacing={"xs"}>
|
||||||
|
<Stack h={"100%"} align="center" justify="flex-start">
|
||||||
|
<IconUserSearch size={20} color="white" />
|
||||||
|
</Stack>
|
||||||
|
<Stack spacing={0} w={"60%"}>
|
||||||
|
<Text
|
||||||
|
lineClamp={1}
|
||||||
|
fz={"sm"}
|
||||||
|
c={MainColor.yellow}
|
||||||
|
fw={"bold"}
|
||||||
|
>
|
||||||
|
{e?.Author.username}
|
||||||
|
</Text>
|
||||||
|
<Text fz={"sm"} c={"white"} lineClamp={2}>
|
||||||
|
{e?.title}
|
||||||
|
</Text>
|
||||||
|
</Stack>
|
||||||
|
</Group>
|
||||||
|
</Stack>
|
||||||
|
))}
|
||||||
|
</SimpleGrid>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
</Stack>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,14 @@
|
|||||||
import { APIs } from "@/app/lib";
|
import { APIs } from "@/app/lib";
|
||||||
import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog";
|
import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog";
|
||||||
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global";
|
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global";
|
||||||
import { ActionIcon, Box, Center, SimpleGrid, Stack, Text } from "@mantine/core";
|
import {
|
||||||
|
ActionIcon,
|
||||||
|
Box,
|
||||||
|
Center,
|
||||||
|
SimpleGrid,
|
||||||
|
Stack,
|
||||||
|
Text,
|
||||||
|
} from "@mantine/core";
|
||||||
import { useShallowEffect } from "@mantine/hooks";
|
import { useShallowEffect } from "@mantine/hooks";
|
||||||
import { IconUserCircle } from "@tabler/icons-react";
|
import { IconUserCircle } from "@tabler/icons-react";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
@@ -11,103 +18,109 @@ import { Home_ComponentAvatarProfile } from "./comp_avatar_profile";
|
|||||||
import { listMenuHomeFooter } from "./list_menu_home";
|
import { listMenuHomeFooter } from "./list_menu_home";
|
||||||
|
|
||||||
export default function FooterHome() {
|
export default function FooterHome() {
|
||||||
const router = useRouter()
|
const router = useRouter();
|
||||||
const [dataUser, setDataUser] = useState<any>({})
|
const [dataUser, setDataUser] = useState<any>({});
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
cekUserLogin();
|
cekUserLogin();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
async function cekUserLogin() {
|
||||||
async function cekUserLogin() {
|
try {
|
||||||
try {
|
const response = await apiGetDataHome("?cat=cek_profile");
|
||||||
const response = await apiGetDataHome("?cat=cek_profile")
|
if (response.success) {
|
||||||
if (response.success) {
|
setDataUser(response.data);
|
||||||
setDataUser(response.data);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
}
|
}
|
||||||
}
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
style={{
|
style={{
|
||||||
zIndex: 99,
|
zIndex: 99,
|
||||||
borderRadius: "20px 20px 0px 0px",
|
borderRadius: "20px 20px 0px 0px",
|
||||||
}}
|
}}
|
||||||
w={"100%"}
|
w={"100%"}
|
||||||
bottom={0}
|
bottom={0}
|
||||||
h={"9vh"}
|
h={"9vh"}
|
||||||
>
|
>
|
||||||
<SimpleGrid cols={listMenuHomeFooter.length + 1}>
|
<SimpleGrid cols={listMenuHomeFooter.length + 1}>
|
||||||
{listMenuHomeFooter.map((e) => (
|
{listMenuHomeFooter.map((e) => (
|
||||||
<Center h={"9vh"} key={e.id}>
|
<Center h={"9vh"} key={e.id}>
|
||||||
<Stack align="center" spacing={0}
|
<Stack
|
||||||
onClick={() => {
|
align="center"
|
||||||
if (dataUser.profile === undefined || dataUser?.profile === null) {
|
spacing={0}
|
||||||
ComponentGlobal_NotifikasiPeringatan("Lengkapi Profile");
|
onClick={() => {
|
||||||
} else {
|
if (
|
||||||
if (e.link == "") {
|
dataUser.profile === undefined ||
|
||||||
ComponentGlobal_NotifikasiPeringatan("Cooming Soon")
|
dataUser?.profile === null
|
||||||
} else {
|
) {
|
||||||
router.push(e.link, { scroll: false })
|
return null;
|
||||||
}
|
} else if (
|
||||||
}
|
dataUser.profile === undefined ||
|
||||||
}}
|
dataUser?.profile === null
|
||||||
>
|
) {
|
||||||
<ActionIcon
|
router.push(RouterProfile.create, { scroll: false });
|
||||||
radius={"xl"}
|
} else {
|
||||||
c={e.link === "" ? "gray" : "white"}
|
if (e.link == "") {
|
||||||
variant="transparent"
|
ComponentGlobal_NotifikasiPeringatan("Cooming Soon");
|
||||||
>
|
} else {
|
||||||
{e.icon}
|
router.push(e.link, { scroll: false });
|
||||||
</ActionIcon>
|
}
|
||||||
<Text
|
}
|
||||||
lineClamp={1}
|
}}
|
||||||
c={e.link === "" ? "gray" : "white"}
|
>
|
||||||
fz={12}
|
<ActionIcon
|
||||||
>
|
radius={"xl"}
|
||||||
{e.name}
|
c={e.link === "" ? "gray" : "white"}
|
||||||
</Text>
|
variant="transparent"
|
||||||
</Stack>
|
>
|
||||||
</Center>
|
{e.icon}
|
||||||
))}
|
</ActionIcon>
|
||||||
|
<Text lineClamp={1} c={e.link === "" ? "gray" : "white"} fz={12}>
|
||||||
|
{e.name}
|
||||||
|
</Text>
|
||||||
|
</Stack>
|
||||||
|
</Center>
|
||||||
|
))}
|
||||||
|
|
||||||
<Center h={"9vh"}>
|
<Center h={"9vh"}>
|
||||||
<Stack
|
<Stack
|
||||||
align="center"
|
align="center"
|
||||||
spacing={2}
|
spacing={2}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (dataUser.profile === undefined || dataUser?.profile === null) {
|
if (
|
||||||
router.push(RouterProfile.create, { scroll: false });
|
dataUser.profile === undefined ||
|
||||||
} else {
|
dataUser?.profile === null
|
||||||
router.push(
|
) {
|
||||||
RouterProfile.katalogOLD + `${dataUser?.profile}`,
|
router.push(RouterProfile.create, { scroll: false });
|
||||||
{ scroll: false }
|
} else {
|
||||||
);
|
router.push(RouterProfile.katalogOLD + `${dataUser?.profile}`, {
|
||||||
}
|
scroll: false,
|
||||||
}}
|
});
|
||||||
>
|
}
|
||||||
<ActionIcon variant={"transparent"}>
|
}}
|
||||||
{dataUser.profile === undefined || dataUser?.profile === null
|
>
|
||||||
?
|
<ActionIcon variant={"transparent"}>
|
||||||
<IconUserCircle color="white" />
|
{dataUser.profile === undefined || dataUser?.profile === null ? (
|
||||||
:
|
<IconUserCircle color="white" />
|
||||||
<Home_ComponentAvatarProfile
|
) : (
|
||||||
url={APIs.GET({
|
<Home_ComponentAvatarProfile
|
||||||
fileId: dataUser?.imageId as string,
|
url={APIs.GET({
|
||||||
size: "50"
|
fileId: dataUser?.imageId as string,
|
||||||
})}
|
size: "50",
|
||||||
/>
|
})}
|
||||||
}
|
/>
|
||||||
</ActionIcon>
|
)}
|
||||||
<Text fz={10} c={"white"}>
|
</ActionIcon>
|
||||||
Profile
|
<Text fz={10} c={"white"}>
|
||||||
</Text>
|
Profile
|
||||||
</Stack>
|
</Text>
|
||||||
</Center>
|
</Stack>
|
||||||
</SimpleGrid>
|
</Center>
|
||||||
</Box>
|
</SimpleGrid>
|
||||||
);
|
</Box>
|
||||||
}
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
import { API_RouteNotifikasi } from "@/app/lib/api_user_router/route_api_notifikasi";
|
||||||
import { gs_count_ntf, gs_user_ntf } from "@/app/lib/global_state";
|
import { gs_count_ntf, gs_user_ntf } from "@/app/lib/global_state";
|
||||||
|
import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog";
|
||||||
import { RouterNotifikasi } from "@/app/lib/router_hipmi/router_notifikasi";
|
import { RouterNotifikasi } from "@/app/lib/router_hipmi/router_notifikasi";
|
||||||
import { RouterUserSearch } from "@/app/lib/router_hipmi/router_user_search";
|
import { RouterUserSearch } from "@/app/lib/router_hipmi/router_user_search";
|
||||||
import { ActionIcon, Indicator, Text } from "@mantine/core";
|
import { ActionIcon, Indicator, Text } from "@mantine/core";
|
||||||
@@ -9,119 +11,121 @@ import { useAtom } from "jotai";
|
|||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { MainColor } from "../_global/color";
|
import { MainColor } from "../_global/color";
|
||||||
import { ComponentGlobal_NotifikasiPeringatan } from "../_global/notif_global";
|
|
||||||
import UIGlobal_LayoutHeaderTamplate from "../_global/ui/ui_header_tamplate";
|
import UIGlobal_LayoutHeaderTamplate from "../_global/ui/ui_header_tamplate";
|
||||||
import UIGlobal_LayoutTamplate from "../_global/ui/ui_layout_tamplate";
|
import UIGlobal_LayoutTamplate from "../_global/ui/ui_layout_tamplate";
|
||||||
import notifikasi_countUserNotifikasi from "../notifikasi/fun/count/fun_count_by_id";
|
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";
|
||||||
|
|
||||||
export default function HomeViewNew({ countNotifikasi }: { countNotifikasi: number; }) {
|
export default function HomeViewNew() {
|
||||||
const [countNtf, setCountNtf] = useState(countNotifikasi);
|
const [countNtf, setCountNtf] = useAtom(gs_count_ntf);
|
||||||
const [newUserNtf, setNewUserNtf] = useAtom(gs_user_ntf);
|
const [newUserNtf, setNewUserNtf] = useAtom(gs_user_ntf);
|
||||||
const [countLoadNtf, setCountLoadNtf] = useAtom(gs_count_ntf);
|
const [dataUser, setDataUser] = useState<any>({});
|
||||||
const [dataUser, setDataUser] = useState<any>({})
|
const [categoryPage, setCategoryPage] = useAtom(gs_notifikasi_kategori_app);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
onLoadNotifikasi();
|
||||||
|
}, []);
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
onLoadNotifikasi({
|
if (countNtf != null) {
|
||||||
onLoad(val) {
|
|
||||||
setCountNtf(val);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
setCountNtf(countLoadNtf as any);
|
|
||||||
}, [countLoadNtf, setCountNtf]);
|
|
||||||
|
|
||||||
useShallowEffect(() => {
|
|
||||||
setCountNtf(countNtf + newUserNtf);
|
setCountNtf(countNtf + newUserNtf);
|
||||||
setNewUserNtf(0);
|
setNewUserNtf(0);
|
||||||
}, [newUserNtf, setCountNtf]);
|
}
|
||||||
|
}, [newUserNtf, countNtf]);
|
||||||
|
|
||||||
async function onLoadNotifikasi({ onLoad }: { onLoad: (val: any) => void }) {
|
async function onLoadNotifikasi() {
|
||||||
const loadNotif = await notifikasi_countUserNotifikasi();
|
const loadNotif = await fetch(API_RouteNotifikasi.get_count_by_id());
|
||||||
onLoad(loadNotif);
|
const data = await loadNotif.json().then((res) => res.data);
|
||||||
}
|
setCountNtf(data);
|
||||||
|
}
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
cekUserLogin();
|
cekUserLogin();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
async function cekUserLogin() {
|
||||||
async function cekUserLogin() {
|
try {
|
||||||
try {
|
const response = await apiGetDataHome("?cat=cek_profile");
|
||||||
const response = await apiGetDataHome("?cat=cek_profile")
|
if (response.success) {
|
||||||
if (response.success) {
|
setDataUser(response.data);
|
||||||
setDataUser(response.data);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
}
|
}
|
||||||
}
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<UIGlobal_LayoutTamplate
|
<UIGlobal_LayoutTamplate
|
||||||
header={
|
header={
|
||||||
<UIGlobal_LayoutHeaderTamplate
|
<UIGlobal_LayoutHeaderTamplate
|
||||||
title="HIPMI"
|
title="HIPMI"
|
||||||
customButtonLeft={
|
customButtonLeft={
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
radius={"xl"}
|
radius={"xl"}
|
||||||
variant={"transparent"}
|
disabled={countNtf == null}
|
||||||
onClick={() => {
|
variant={"transparent"}
|
||||||
if (dataUser.profile === undefined || dataUser?.profile === null) {
|
onClick={() => {
|
||||||
ComponentGlobal_NotifikasiPeringatan("Lengkapi Profile");
|
if (
|
||||||
} else {
|
dataUser.profile === undefined ||
|
||||||
router.push(RouterUserSearch.main, { scroll: false });
|
dataUser?.profile === null
|
||||||
}
|
) {
|
||||||
}}
|
router.push(RouterProfile.create, { scroll: false });
|
||||||
>
|
} else {
|
||||||
<IconUserSearch color="white" />
|
router.push(RouterUserSearch.main, { scroll: false });
|
||||||
</ActionIcon>
|
|
||||||
}
|
}
|
||||||
customButtonRight={
|
}}
|
||||||
<ActionIcon
|
>
|
||||||
variant="transparent"
|
<IconUserSearch color="white" />
|
||||||
onClick={() => {
|
</ActionIcon>
|
||||||
if (dataUser.profile === undefined || dataUser?.profile === null) {
|
|
||||||
ComponentGlobal_NotifikasiPeringatan("Lengkapi Profile");
|
|
||||||
} else {
|
|
||||||
router.push(RouterNotifikasi.categoryApp({ name: "semua" }), {
|
|
||||||
scroll: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{
|
|
||||||
countNotifikasi > 0
|
|
||||||
?
|
|
||||||
<Indicator
|
|
||||||
processing
|
|
||||||
color={MainColor.yellow}
|
|
||||||
label={
|
|
||||||
<Text fz={10} c={MainColor.darkblue}>
|
|
||||||
{countNotifikasi > 99 ? "99+" : countNotifikasi}
|
|
||||||
</Text>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<IconBell color="white" />
|
|
||||||
</Indicator>
|
|
||||||
:
|
|
||||||
<IconBell color="white" />
|
|
||||||
}
|
|
||||||
|
|
||||||
</ActionIcon>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
}
|
}
|
||||||
|
customButtonRight={
|
||||||
footer={<FooterHome />}
|
<ActionIcon
|
||||||
>
|
variant="transparent"
|
||||||
<BodyHome />
|
disabled={countNtf == null}
|
||||||
</UIGlobal_LayoutTamplate>
|
onClick={() => {
|
||||||
</>
|
if (
|
||||||
);
|
dataUser.profile === undefined ||
|
||||||
|
dataUser?.profile === null
|
||||||
|
) {
|
||||||
|
router.push(RouterProfile.create, { scroll: false });
|
||||||
|
} else {
|
||||||
|
setCategoryPage("Semua");
|
||||||
|
router.push(
|
||||||
|
RouterNotifikasi.categoryApp({ name: "semua" }),
|
||||||
|
{
|
||||||
|
scroll: false,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{countNtf != null && countNtf > 0 ? (
|
||||||
|
<Indicator
|
||||||
|
processing
|
||||||
|
color={MainColor.yellow}
|
||||||
|
label={
|
||||||
|
<Text fz={10} c={MainColor.darkblue}>
|
||||||
|
{countNtf > 99 ? "99+" : countNtf}
|
||||||
|
</Text>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<IconBell color="white" />
|
||||||
|
</Indicator>
|
||||||
|
) : (
|
||||||
|
<IconBell color="white" />
|
||||||
|
)}
|
||||||
|
</ActionIcon>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
footer={<FooterHome />}
|
||||||
|
>
|
||||||
|
<BodyHome />
|
||||||
|
</UIGlobal_LayoutTamplate>
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ export function Investasi_ComponentButtonUpdateDataInvestasi({
|
|||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
async function onUpdate() {
|
async function onUpdate() {
|
||||||
|
setIsLoading(true);
|
||||||
if (totalLembar === "0")
|
if (totalLembar === "0")
|
||||||
return ComponentGlobal_NotifikasiPeringatan("Total lembar kosong");
|
return ComponentGlobal_NotifikasiPeringatan("Total lembar kosong");
|
||||||
|
|
||||||
@@ -74,6 +75,8 @@ export function Investasi_ComponentButtonUpdateDataInvestasi({
|
|||||||
return (
|
return (
|
||||||
<Stack>
|
<Stack>
|
||||||
<Button
|
<Button
|
||||||
|
loading={isLoading}
|
||||||
|
loaderPosition="center"
|
||||||
my={50}
|
my={50}
|
||||||
radius={50}
|
radius={50}
|
||||||
bg={MainColor.yellow}
|
bg={MainColor.yellow}
|
||||||
|
|||||||
@@ -0,0 +1,108 @@
|
|||||||
|
import { NEW_RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
|
||||||
|
import { Warna } from "@/app/lib/warna";
|
||||||
|
import { MainColor } from "@/app_modules/_global/color/color_pallet";
|
||||||
|
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()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ComponentGlobal_CardStyles
|
||||||
|
onClickHandler={() => {
|
||||||
|
router.push(NEW_RouterInvestasi.detail_main({ id: data.id }), {
|
||||||
|
scroll: false,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Stack>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={6}>
|
||||||
|
<ComponentGlobal_LoadImageCustom
|
||||||
|
height={100}
|
||||||
|
fileId={data.imageId}
|
||||||
|
/>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={6}>
|
||||||
|
<Stack>
|
||||||
|
<Text fw={"bold"} align="center" lineClamp={2}>
|
||||||
|
{data?.title}
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Progress
|
||||||
|
label={(+data?.progress).toFixed(2) + " %"}
|
||||||
|
value={+data?.progress}
|
||||||
|
color={MainColor.yellow}
|
||||||
|
size="xl"
|
||||||
|
radius="xl"
|
||||||
|
styles={{
|
||||||
|
label: { color: MainColor.black },
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Group position="right">
|
||||||
|
{data?.progress === "100" ? (
|
||||||
|
<Group position="right" spacing={"xs"}>
|
||||||
|
<IconCircleCheck color="green" />
|
||||||
|
<Text
|
||||||
|
truncate
|
||||||
|
variant="text"
|
||||||
|
c={Warna.hijau_tua}
|
||||||
|
sx={{ fontFamily: "Greycliff CF, sans-serif" }}
|
||||||
|
ta="center"
|
||||||
|
fz="md"
|
||||||
|
fw={700}
|
||||||
|
>
|
||||||
|
Selesai
|
||||||
|
</Text>
|
||||||
|
</Group>
|
||||||
|
) : (
|
||||||
|
<Box>
|
||||||
|
{+data?.pencarianInvestor -
|
||||||
|
moment(new Date()).diff(
|
||||||
|
new Date(data?.countDown),
|
||||||
|
"days"
|
||||||
|
) <=
|
||||||
|
0 ? (
|
||||||
|
<Group position="right" spacing={"xs"}>
|
||||||
|
<IconXboxX color="red" />
|
||||||
|
<Text
|
||||||
|
truncate
|
||||||
|
variant="text"
|
||||||
|
c={Warna.merah}
|
||||||
|
sx={{ fontFamily: "Greycliff CF, sans-serif" }}
|
||||||
|
ta="center"
|
||||||
|
fz="md"
|
||||||
|
fw={700}
|
||||||
|
>
|
||||||
|
Waktu Habis
|
||||||
|
</Text>
|
||||||
|
</Group>
|
||||||
|
) : (
|
||||||
|
<Group position="right" spacing={"xs"}>
|
||||||
|
<Text truncate>Sisa waktu:</Text>
|
||||||
|
<Text truncate>
|
||||||
|
{Number(data?.pencarianInvestor) -
|
||||||
|
moment(new Date()).diff(
|
||||||
|
new Date(data?.countDown),
|
||||||
|
"days"
|
||||||
|
)}
|
||||||
|
</Text>
|
||||||
|
<Text truncate>Hari</Text>
|
||||||
|
</Group>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Group>
|
||||||
|
</Stack>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</Stack>
|
||||||
|
</ComponentGlobal_CardStyles>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
import { NEW_RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
|
||||||
|
import { AccentColor } from "@/app_modules/_global/color/color_pallet";
|
||||||
|
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global/notifikasi_peringatan";
|
||||||
|
import { Card, Group, Stack, Text, Title } from "@mantine/core";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
import { IDataSahamSaya } from "../../_lib/type_investasi";
|
||||||
|
|
||||||
|
export function Investasi_ComponentCardDaftarTransaksiNew({ data }: { data: IDataSahamSaya; }) {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
async function onClick({ invoiceId, statusInvoiceId, }: { invoiceId: string; statusInvoiceId: string; }) {
|
||||||
|
// Berhasil
|
||||||
|
if (statusInvoiceId === "1") {
|
||||||
|
return router.push(NEW_RouterInvestasi.transaksi_berhasil + invoiceId, {
|
||||||
|
scroll: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Proses
|
||||||
|
if (statusInvoiceId === "2") {
|
||||||
|
return router.push(NEW_RouterInvestasi.proses_transaksi + invoiceId, {
|
||||||
|
scroll: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Menunggu
|
||||||
|
if (statusInvoiceId === "3") {
|
||||||
|
return router.push(NEW_RouterInvestasi.invoice + invoiceId, {
|
||||||
|
scroll: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (statusInvoiceId === "4") {
|
||||||
|
return router.push(NEW_RouterInvestasi.transaksi_gagal + invoiceId, {
|
||||||
|
scroll: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
ComponentGlobal_NotifikasiPeringatan("Status Belum Tersedia");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Card
|
||||||
|
style={{
|
||||||
|
padding: "15px",
|
||||||
|
backgroundColor: AccentColor.darkblue,
|
||||||
|
border: `2px solid ${AccentColor.blue}`,
|
||||||
|
borderRadius: "10px",
|
||||||
|
color: "white",
|
||||||
|
}}
|
||||||
|
mb={"md"}
|
||||||
|
onClick={() =>
|
||||||
|
onClick({
|
||||||
|
invoiceId: data.id,
|
||||||
|
statusInvoiceId: data.statusInvoiceId,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Group position="apart">
|
||||||
|
<Text fw={"bold"}>{data.title}</Text>
|
||||||
|
<Text fw={"bold"}>
|
||||||
|
Rp.
|
||||||
|
{new Intl.NumberFormat("id-ID", {
|
||||||
|
maximumFractionDigits: 10,
|
||||||
|
}).format(+data.nominal)}
|
||||||
|
</Text>
|
||||||
|
</Group>
|
||||||
|
<Group position="apart">
|
||||||
|
<Stack spacing={0}>
|
||||||
|
<Text fz={"xs"} c={"gray"}>
|
||||||
|
{new Intl.DateTimeFormat("id-ID", { dateStyle: "long" }).format(new Date(data.createdAt))}
|
||||||
|
</Text>
|
||||||
|
</Stack>
|
||||||
|
<Title
|
||||||
|
order={6}
|
||||||
|
c={
|
||||||
|
data.statusInvoiceId === "1"
|
||||||
|
? "green"
|
||||||
|
: data.statusInvoiceId === "2"
|
||||||
|
? "blue"
|
||||||
|
: data.statusInvoiceId === "3"
|
||||||
|
? "orange"
|
||||||
|
: "red"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{data.statusInvoice}
|
||||||
|
</Title>
|
||||||
|
</Group>
|
||||||
|
</Card>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import { NEW_RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
|
||||||
|
import { ComponentGlobal_CardStyles, ComponentGlobal_LoadImageCustom } from "@/app_modules/_global/component";
|
||||||
|
import { Grid, Stack, Text } from "@mantine/core";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
import { IDataInvestasiBursa } from "../../_lib/type_investasi";
|
||||||
|
|
||||||
|
export function Investasi_ComponentCardPortofolio_NotPublishNew({ data, }: { data: IDataInvestasiBursa; }) {
|
||||||
|
const router = useRouter();
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ComponentGlobal_CardStyles
|
||||||
|
onClickHandler={() => {
|
||||||
|
router.push(NEW_RouterInvestasi.detail_portofolio({ id: data.id }), { scroll: false });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={8}>
|
||||||
|
<Text fw={"bold"} lineClamp={1}>
|
||||||
|
{" "}
|
||||||
|
{_.startCase(data.title)}
|
||||||
|
</Text>
|
||||||
|
<Stack spacing={0}>
|
||||||
|
<Text fz={10}>Target Dana:</Text>
|
||||||
|
<Text>
|
||||||
|
Rp.{" "}
|
||||||
|
{new Intl.NumberFormat("id-ID", {
|
||||||
|
maximumSignificantDigits: 10,
|
||||||
|
}).format(+data.targetDana)}
|
||||||
|
</Text>
|
||||||
|
</Stack>
|
||||||
|
</Grid.Col>
|
||||||
|
|
||||||
|
<Grid.Col span={4}>
|
||||||
|
<ComponentGlobal_LoadImageCustom
|
||||||
|
fileId={data.imageId}
|
||||||
|
height={80}
|
||||||
|
/>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</ComponentGlobal_CardStyles>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
import { NEW_RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
|
||||||
|
import { ComponentGlobal_LoadImageCustom } from "@/app_modules/_global/component";
|
||||||
|
import { Box, Grid, Group, Stack, Text } from "@mantine/core";
|
||||||
|
import { IconChecklist, IconCircleCheck } from "@tabler/icons-react";
|
||||||
|
import _ from "lodash";
|
||||||
|
import moment from "moment";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
import { IDataInvestasiBursa } from "../../_lib/type_investasi";
|
||||||
|
import { Investasi_ComponentStylesCard } from "../comp_card_border_and_background";
|
||||||
|
|
||||||
|
export function Investasi_ComponentCardPortofolioPublishNew({ data }: { data: IDataInvestasiBursa; }) {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Investasi_ComponentStylesCard
|
||||||
|
marginBottom={"15px"}
|
||||||
|
onClickHandler={() => {
|
||||||
|
router.push(NEW_RouterInvestasi.detail_main({ id: data?.id }), {
|
||||||
|
scroll: false,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={8}>
|
||||||
|
<Text fw={"bold"}> {_.capitalize(data?.title)}</Text>
|
||||||
|
<Stack spacing={0}>
|
||||||
|
<Text fz={10}>Target Dana:</Text>
|
||||||
|
<Text>
|
||||||
|
Rp.{" "}
|
||||||
|
{new Intl.NumberFormat("id-ID", {
|
||||||
|
maximumSignificantDigits: 10,
|
||||||
|
}).format(+data?.targetDana)}
|
||||||
|
</Text>
|
||||||
|
</Stack>
|
||||||
|
</Grid.Col>
|
||||||
|
|
||||||
|
<Grid.Col span={4}>
|
||||||
|
<ComponentGlobal_LoadImageCustom
|
||||||
|
height={80}
|
||||||
|
fileId={data?.imageId}
|
||||||
|
/>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Group position="center" mt={"md"}>
|
||||||
|
{Number(data?.pencarianInvestor) -
|
||||||
|
moment(new Date()).diff(new Date(data?.updatedAt), "days") <=
|
||||||
|
0 ? (
|
||||||
|
<Group position="right">
|
||||||
|
<IconCircleCheck color="green" />
|
||||||
|
<Text c={"green"}>Selesai</Text>
|
||||||
|
</Group>
|
||||||
|
) : (
|
||||||
|
<Group
|
||||||
|
position="center"
|
||||||
|
style={{ fontSize: 10, fontWeight: "bold" }}
|
||||||
|
>
|
||||||
|
<Group>
|
||||||
|
{Number(data?.pencarianInvestor) -
|
||||||
|
moment(new Date()).diff(new Date(data?.countDown), "days") <=
|
||||||
|
0 ? (
|
||||||
|
<Group>
|
||||||
|
<IconChecklist />
|
||||||
|
<Text>Selesai</Text>
|
||||||
|
</Group>
|
||||||
|
) : (
|
||||||
|
<Box>
|
||||||
|
Sisa Waktu : {}
|
||||||
|
{Number(data?.pencarianInvestor) -
|
||||||
|
moment(new Date()).diff(
|
||||||
|
new Date(data?.countDown),
|
||||||
|
"days"
|
||||||
|
)}{" "}
|
||||||
|
hari
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
)}
|
||||||
|
</Group>
|
||||||
|
</Investasi_ComponentStylesCard>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
import { NEW_RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
|
||||||
|
import { MainColor } from "@/app_modules/_global/color/color_pallet";
|
||||||
|
import { ComponentGlobal_TampilanAngkaRatusan, ComponentGlobal_TampilanRupiah } from "@/app_modules/_global/component";
|
||||||
|
import { Box, Progress, SimpleGrid, Stack, Text } from "@mantine/core";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
import { IDataSahamSaya } from "../../_lib/type_investasi";
|
||||||
|
import { Investasi_ComponentStylesCard } from "../comp_card_border_and_background";
|
||||||
|
|
||||||
|
export function Investasi_ComponentSahamSayaNew({ data }: { data: IDataSahamSaya; }) {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Investasi_ComponentStylesCard
|
||||||
|
onClickHandler={() => {
|
||||||
|
router.push(NEW_RouterInvestasi.detail_saham + data?.id, {
|
||||||
|
scroll: false,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
marginBottom={"15px"}
|
||||||
|
>
|
||||||
|
<SimpleGrid cols={2} spacing={"xs"}>
|
||||||
|
<Box>
|
||||||
|
<Stack spacing={0}>
|
||||||
|
<Text fw={"bold"} lineClamp={2}>
|
||||||
|
{data?.title}
|
||||||
|
</Text>
|
||||||
|
<ComponentGlobal_TampilanRupiah
|
||||||
|
nominal={+data?.nominal}
|
||||||
|
color="white"
|
||||||
|
fontSize={"xs"}
|
||||||
|
/>
|
||||||
|
<ComponentGlobal_TampilanAngkaRatusan
|
||||||
|
nominal={+data?.lembarTerbeli}
|
||||||
|
color="white"
|
||||||
|
fontSize={"xs"}
|
||||||
|
textAfter="Lembar"
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Stack justify="center">
|
||||||
|
<Progress
|
||||||
|
size={"xl"}
|
||||||
|
radius={"xl"}
|
||||||
|
color="yellow"
|
||||||
|
value={+data.progress}
|
||||||
|
label={data.progress + "%"}
|
||||||
|
styles={{
|
||||||
|
bar: {
|
||||||
|
backgroundColor: MainColor.yellow,
|
||||||
|
},
|
||||||
|
root: {
|
||||||
|
backgroundColor: "whitesmoke",
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
color: "black",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</SimpleGrid>
|
||||||
|
</Investasi_ComponentStylesCard>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
19
src/app_modules/investasi/_lib/api_interface.ts
Normal file
19
src/app_modules/investasi/_lib/api_interface.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
export const apiGetMasterInvestasi = async (path?: string) => {
|
||||||
|
const response = await fetch(`/api/new/investasi/master${(path) ? path : ''}`)
|
||||||
|
return await response.json().catch(() => null)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const apiGetOneInvestasiById = async (path: string) => {
|
||||||
|
const response = await fetch(`/api/new/investasi/${path}`)
|
||||||
|
return await response.json().catch(() => null)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const apiGetAllInvestasi = async (path?: string) => {
|
||||||
|
const response = await fetch(`/api/new/investasi${(path) ? path : ''}`)
|
||||||
|
return await response.json().catch(() => null)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const apiGetAllSahamSaya = async (path?: string) => {
|
||||||
|
const response = await fetch(`/api/new/investasi/invoice${(path) ? path : ''}`)
|
||||||
|
return await response.json().catch(() => null)
|
||||||
|
}
|
||||||
37
src/app_modules/investasi/_lib/type_investasi.ts
Normal file
37
src/app_modules/investasi/_lib/type_investasi.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
export interface IDataInvestasi {
|
||||||
|
id: string
|
||||||
|
title: string
|
||||||
|
targetDana: string
|
||||||
|
hargaLembar: string
|
||||||
|
totalLembar: string
|
||||||
|
roi: string
|
||||||
|
countDown: string
|
||||||
|
catatan: string
|
||||||
|
sisaLembar: string
|
||||||
|
imageId: string
|
||||||
|
masterPencarianInvestorId: string
|
||||||
|
masterPeriodeDevidenId: string
|
||||||
|
masterPembagianDevidenId: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IDataInvestasiBursa {
|
||||||
|
id: string
|
||||||
|
title: string
|
||||||
|
imageId: string
|
||||||
|
progress: string
|
||||||
|
countDown: string
|
||||||
|
targetDana: string
|
||||||
|
pencarianInvestor: string
|
||||||
|
updatedAt: Date
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IDataSahamSaya {
|
||||||
|
id: string
|
||||||
|
nominal: string
|
||||||
|
lembarTerbeli: string
|
||||||
|
statusInvoiceId: string
|
||||||
|
createdAt: Date
|
||||||
|
statusInvoice: string
|
||||||
|
title: string
|
||||||
|
progress: string
|
||||||
|
}
|
||||||
15
src/app_modules/investasi/_ui/edit/ui_edit_investasi_new.tsx
Normal file
15
src/app_modules/investasi/_ui/edit/ui_edit_investasi_new.tsx
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
"use client";
|
||||||
|
import { UIGlobal_LayoutHeaderTamplate, UIGlobal_LayoutTamplate, } from "@/app_modules/_global/ui";
|
||||||
|
import { Investasi_ViewEditInvestasiNew } from "../../_view/edit/vew_edit_investasi_new";
|
||||||
|
|
||||||
|
export function Investasi_UiEditInvestasiNew() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<UIGlobal_LayoutTamplate
|
||||||
|
header={<UIGlobal_LayoutHeaderTamplate title="Edit Investasi" />}
|
||||||
|
>
|
||||||
|
<Investasi_ViewEditInvestasiNew />
|
||||||
|
</UIGlobal_LayoutTamplate>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -24,6 +24,9 @@ import { Investasi_UiDaftarBerita } from "./detail/ui_daftar_berita";
|
|||||||
import { Investasi_UiRekapBerita } from "./detail/ui_rekap_berita";
|
import { Investasi_UiRekapBerita } from "./detail/ui_rekap_berita";
|
||||||
import { Investasi_UiCreateBerita } from "./create/ui_create_berita";
|
import { Investasi_UiCreateBerita } from "./create/ui_create_berita";
|
||||||
import { Investasi_UiDetailBerita } from "./detail/ui_berita";
|
import { Investasi_UiDetailBerita } from "./detail/ui_berita";
|
||||||
|
import { Investasi_UiEditInvestasiNew } from "./edit/ui_edit_investasi_new";
|
||||||
|
import { Investasi_ViewBerandaNew } from "../_view/main/view_beranda_new";
|
||||||
|
import { Investasi_UiPortofolioNew } from "./main/ui_portofolio_new";
|
||||||
|
|
||||||
export { Investasi_UiProsesPembelian };
|
export { Investasi_UiProsesPembelian };
|
||||||
export { Investasi_UiMetodePembayaran };
|
export { Investasi_UiMetodePembayaran };
|
||||||
@@ -51,3 +54,6 @@ export { Investasi_UiDaftarBerita };
|
|||||||
export { Investasi_UiRekapBerita };
|
export { Investasi_UiRekapBerita };
|
||||||
export { Investasi_UiCreateBerita };
|
export { Investasi_UiCreateBerita };
|
||||||
export { Investasi_UiDetailBerita };
|
export { Investasi_UiDetailBerita };
|
||||||
|
export { Investasi_UiEditInvestasiNew }
|
||||||
|
export { Investasi_ViewBerandaNew }
|
||||||
|
export { Investasi_UiPortofolioNew }
|
||||||
|
|||||||
77
src/app_modules/investasi/_ui/main/ui_portofolio_new.tsx
Normal file
77
src/app_modules/investasi/_ui/main/ui_portofolio_new.tsx
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
"use client";
|
||||||
|
import { NEW_RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
|
||||||
|
import { AccentColor, MainColor } from "@/app_modules/_global/color";
|
||||||
|
import { Stack, Tabs } from "@mantine/core";
|
||||||
|
import { useParams, useRouter } from "next/navigation";
|
||||||
|
import { Investasi_ViewPortofolioNew } from "../../_view/main/portofolio/view_portofolio_new";
|
||||||
|
|
||||||
|
export function Investasi_UiPortofolioNew() {
|
||||||
|
const param = useParams<{ id: string }>();
|
||||||
|
const router = useRouter();
|
||||||
|
const status = [
|
||||||
|
{
|
||||||
|
id: "1",
|
||||||
|
name: "Publish",
|
||||||
|
color: "green"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "2",
|
||||||
|
name: "Review",
|
||||||
|
color: "orange"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "3",
|
||||||
|
name: "Draft",
|
||||||
|
color: "yellow"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "4",
|
||||||
|
name: "Reject",
|
||||||
|
color: "red"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Tabs
|
||||||
|
variant="pills"
|
||||||
|
radius="xl"
|
||||||
|
defaultValue={param.id}
|
||||||
|
styles={{
|
||||||
|
tabsList: {
|
||||||
|
position: "sticky",
|
||||||
|
top: 0,
|
||||||
|
zIndex: 99,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
value={param.id}
|
||||||
|
onTabChange={(val: any) => {
|
||||||
|
router.push(NEW_RouterInvestasi.portofolio({ id: val }));
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Stack>
|
||||||
|
<Tabs.List grow mb={"xs"}>
|
||||||
|
{status.map((e) => (
|
||||||
|
<Tabs.Tab
|
||||||
|
w={"20%"}
|
||||||
|
key={e.id}
|
||||||
|
value={e.id}
|
||||||
|
fw={"bold"}
|
||||||
|
style={{
|
||||||
|
transition: "ease 0.5s ",
|
||||||
|
backgroundColor:
|
||||||
|
param.id === e.id ? MainColor.yellow : AccentColor.blue,
|
||||||
|
color: param.id === e.id ? "black" : "white",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{e.name}
|
||||||
|
</Tabs.Tab>
|
||||||
|
))}
|
||||||
|
</Tabs.List>
|
||||||
|
|
||||||
|
<Investasi_ViewPortofolioNew />
|
||||||
|
</Stack>
|
||||||
|
</Tabs>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { Box, Skeleton, Stack } from "@mantine/core";
|
||||||
|
|
||||||
|
export default function SkeletonEditInvestasi() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Box>
|
||||||
|
<Stack align="center" mb={40}>
|
||||||
|
<Skeleton height={40} width={"100%"} />
|
||||||
|
<Skeleton height={300} width={"100%"} my={"xs"} />
|
||||||
|
<Skeleton height={40} width={"40%"} radius={"lg"} />
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Stack align="center">
|
||||||
|
{[...Array(5)].map((_, index) => (
|
||||||
|
<Skeleton key={index} height={40} width={"100%"} my={"xs"} />
|
||||||
|
))}
|
||||||
|
<Skeleton height={40} width={"100%"} radius={"lg"} mt={30} />
|
||||||
|
</Stack>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
367
src/app_modules/investasi/_view/edit/vew_edit_investasi_new.tsx
Normal file
367
src/app_modules/investasi/_view/edit/vew_edit_investasi_new.tsx
Normal file
@@ -0,0 +1,367 @@
|
|||||||
|
import { MainColor } from "@/app_modules/_global/color";
|
||||||
|
import { ComponentGlobal_BoxInformation, ComponentGlobal_BoxUploadImage, ComponentGlobal_LoadImage, } from "@/app_modules/_global/component";
|
||||||
|
import { AspectRatio, Box, Button, FileButton, Group, Image, Select, Stack, Text, TextInput, } from "@mantine/core";
|
||||||
|
import { useShallowEffect } from "@mantine/hooks";
|
||||||
|
import { IconCamera } from "@tabler/icons-react";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Investasi_ComponentButtonUpdateDataInvestasi } from "../../_component";
|
||||||
|
import { apiGetMasterInvestasi, apiGetOneInvestasiById } from "../../_lib/api_interface";
|
||||||
|
import { IDataInvestasi } from "../../_lib/type_investasi";
|
||||||
|
import { useParams } from "next/navigation";
|
||||||
|
import SkeletonEditInvestasi from "./skeleton_edit_investasi";
|
||||||
|
|
||||||
|
export function Investasi_ViewEditInvestasiNew() {
|
||||||
|
const param = useParams<{ id: string }>()
|
||||||
|
const [loading, setLoading] = useState(true)
|
||||||
|
const [loadingMasterInvestor, setLoadingMasterInvestor] = useState(true)
|
||||||
|
const [loadingMasterPeriodeDeviden, setLoadingMasterPeriodeDeviden] = useState(true)
|
||||||
|
const [loadingMasterPembagianDeviden, setLoadingMasterPembagianDeviden] = useState(true)
|
||||||
|
const [periodeDeviden, setPeriodeDeviden] = useState<any[]>([]);
|
||||||
|
const [pembagianDeviden, setPembagianDeviden] = useState<any[]>([]);
|
||||||
|
const [pencarianInvestor, setPencarianInvestor] = useState<any[]>([]);
|
||||||
|
const [data, setData] = useState<IDataInvestasi>();
|
||||||
|
const [file, setFile] = useState<File | null>(null);
|
||||||
|
const [img, setImg] = useState<any | null>();
|
||||||
|
const [target, setTarget] = useState("");
|
||||||
|
const [harga, setHarga] = useState("");
|
||||||
|
const [totalLembar, setTotalLembar] = useState<any>("");
|
||||||
|
|
||||||
|
|
||||||
|
async function onGetOneInvestasiById() {
|
||||||
|
try {
|
||||||
|
setLoading(true)
|
||||||
|
const response = await apiGetOneInvestasiById(param.id)
|
||||||
|
if (response.success) {
|
||||||
|
setData(response.data)
|
||||||
|
setTotalLembar(response.data.totalLembar)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
} finally {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function onGetMasterInvestor() {
|
||||||
|
try {
|
||||||
|
setLoadingMasterInvestor(true)
|
||||||
|
const response = await apiGetMasterInvestasi("?cat=pencarian-investor")
|
||||||
|
if (response.success) {
|
||||||
|
setPencarianInvestor(response.data)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
} finally {
|
||||||
|
setLoadingMasterInvestor(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function onGetMasterPeriodeDeviden() {
|
||||||
|
try {
|
||||||
|
setLoadingMasterPeriodeDeviden(true)
|
||||||
|
const response = await apiGetMasterInvestasi("?cat=periode-deviden")
|
||||||
|
if (response.success) {
|
||||||
|
setPeriodeDeviden(response.data)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
} finally {
|
||||||
|
setLoadingMasterPeriodeDeviden(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function onGetMasterPembagianDeviden() {
|
||||||
|
try {
|
||||||
|
setLoadingMasterPembagianDeviden(true)
|
||||||
|
const response = await apiGetMasterInvestasi("?cat=pembagian-deviden")
|
||||||
|
if (response.success) {
|
||||||
|
setPembagianDeviden(response.data)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
} finally {
|
||||||
|
setLoadingMasterPembagianDeviden(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
onGetOneInvestasiById()
|
||||||
|
onGetMasterInvestor()
|
||||||
|
onGetMasterPeriodeDeviden()
|
||||||
|
onGetMasterPembagianDeviden()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
async function onTotalLembar({ target, harga, }: { target?: number | any; harga?: number | any; }) {
|
||||||
|
if (target !== 0 && harga !== 0) {
|
||||||
|
const hasil: any = target / harga;
|
||||||
|
const result = _.floor(hasil === Infinity ? 0 : hasil);
|
||||||
|
setTotalLembar(result.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack px={"sm"}>
|
||||||
|
{
|
||||||
|
loading ?
|
||||||
|
<SkeletonEditInvestasi />
|
||||||
|
:
|
||||||
|
<>
|
||||||
|
<Stack spacing={0}>
|
||||||
|
<Box mb={"sm"}>
|
||||||
|
<ComponentGlobal_BoxInformation informasi="Gambar investasi bisa berupa ilustrasi, poster atau foto terkait investasi" />
|
||||||
|
</Box>
|
||||||
|
<ComponentGlobal_BoxUploadImage>
|
||||||
|
{img ? (
|
||||||
|
<AspectRatio ratio={1 / 1} mt={5} maw={300} mx={"auto"}>
|
||||||
|
<Image style={{ maxHeight: 250 }} alt="Avatar" src={img} />
|
||||||
|
</AspectRatio>
|
||||||
|
) : (
|
||||||
|
<ComponentGlobal_LoadImage maw={300} fileId={String(data?.imageId)} />
|
||||||
|
)}
|
||||||
|
</ComponentGlobal_BoxUploadImage>
|
||||||
|
{/* Upload Foto */}
|
||||||
|
<Group position="center">
|
||||||
|
<FileButton
|
||||||
|
onChange={async (files: any) => {
|
||||||
|
try {
|
||||||
|
const buffer = URL.createObjectURL(
|
||||||
|
new Blob([new Uint8Array(await files.arrayBuffer())])
|
||||||
|
);
|
||||||
|
setImg(buffer);
|
||||||
|
setFile(files);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
accept="image/png,image/jpeg"
|
||||||
|
>
|
||||||
|
{(props) => (
|
||||||
|
<Button
|
||||||
|
{...props}
|
||||||
|
leftIcon={<IconCamera color="black" />}
|
||||||
|
radius={50}
|
||||||
|
bg={MainColor.yellow}
|
||||||
|
color="yellow"
|
||||||
|
c={"black"}
|
||||||
|
>
|
||||||
|
Upload Gambar
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</FileButton>
|
||||||
|
</Group>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
|
||||||
|
<TextInput
|
||||||
|
styles={{
|
||||||
|
label: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
withAsterisk
|
||||||
|
label="Judul Investasi"
|
||||||
|
placeholder="Judul investasi"
|
||||||
|
maxLength={100}
|
||||||
|
value={data?.title}
|
||||||
|
onChange={(val) => {
|
||||||
|
setData({
|
||||||
|
...data as any,
|
||||||
|
title: val.target.value,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextInput
|
||||||
|
styles={{
|
||||||
|
label: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
icon={<Text fw={"bold"}>Rp.</Text>}
|
||||||
|
min={0}
|
||||||
|
withAsterisk
|
||||||
|
label="Dana Dibutuhkan"
|
||||||
|
placeholder="0"
|
||||||
|
value={target ? target : data?.targetDana}
|
||||||
|
onChange={(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: +Number(data?.hargaLembar),
|
||||||
|
});
|
||||||
|
|
||||||
|
setTarget(targetNilai);
|
||||||
|
setData({
|
||||||
|
...data as any,
|
||||||
|
targetDana: nilai as string,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextInput
|
||||||
|
styles={{
|
||||||
|
label: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
icon={<Text fw={"bold"}>Rp.</Text>}
|
||||||
|
min={0}
|
||||||
|
withAsterisk
|
||||||
|
label="Harga Per Lembar"
|
||||||
|
placeholder="0"
|
||||||
|
value={harga ? harga : data?.hargaLembar}
|
||||||
|
onChange={(val) => {
|
||||||
|
try {
|
||||||
|
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: +Number(data?.targetDana),
|
||||||
|
});
|
||||||
|
|
||||||
|
setHarga(targetNilai);
|
||||||
|
setData({
|
||||||
|
...data as any,
|
||||||
|
hargaLembar: nilai as string,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextInput
|
||||||
|
description="*Total lembar dihitung dari, Target Dana / Harga Perlembar"
|
||||||
|
label="Total Lembar"
|
||||||
|
value={harga === "0" ? "0" : target === "0" ? "0" : totalLembar}
|
||||||
|
readOnly
|
||||||
|
styles={{
|
||||||
|
label: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
|
||||||
|
input: {
|
||||||
|
backgroundColor: "whitesmoke",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextInput
|
||||||
|
styles={{
|
||||||
|
label: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
rightSection={
|
||||||
|
<Text fw={"bold"} c={"gray"}>
|
||||||
|
%
|
||||||
|
</Text>
|
||||||
|
}
|
||||||
|
withAsterisk
|
||||||
|
type="number"
|
||||||
|
label={"Rasio Keuntungan / ROI %"}
|
||||||
|
placeholder="Masukan rasio keuntungan"
|
||||||
|
value={data?.roi}
|
||||||
|
onChange={(val) => {
|
||||||
|
setData({
|
||||||
|
...data as any,
|
||||||
|
roi: val.target.value,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Select
|
||||||
|
styles={{
|
||||||
|
label: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
withAsterisk
|
||||||
|
label="Pencarian Investor"
|
||||||
|
placeholder={loadingMasterInvestor ? "Loading..." : "Pilih batas waktu"}
|
||||||
|
data={pencarianInvestor.map((e) => ({
|
||||||
|
value: e.id,
|
||||||
|
label: e.name + " " + "hari",
|
||||||
|
}))}
|
||||||
|
value={data?.masterPencarianInvestorId}
|
||||||
|
onChange={(val) => {
|
||||||
|
setData({
|
||||||
|
...(data as any),
|
||||||
|
masterPencarianInvestorId: val,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Select
|
||||||
|
styles={{
|
||||||
|
label: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
withAsterisk
|
||||||
|
label="Periode Deviden"
|
||||||
|
placeholder={loadingMasterPeriodeDeviden ? "Loading..." : "Pilih batas waktu"}
|
||||||
|
data={periodeDeviden.map((e) => ({ value: e.id, label: e.name }))}
|
||||||
|
value={data?.masterPeriodeDevidenId}
|
||||||
|
onChange={(val) => {
|
||||||
|
setData({
|
||||||
|
...(data as any),
|
||||||
|
masterPeriodeDevidenId: val,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Select
|
||||||
|
styles={{
|
||||||
|
label: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
withAsterisk
|
||||||
|
label="Pembagian Deviden"
|
||||||
|
placeholder={loadingMasterPembagianDeviden ? "Loading..." : "Pilih batas waktu"}
|
||||||
|
data={pembagianDeviden.map((e) => ({
|
||||||
|
value: e.id,
|
||||||
|
label: e.name + " " + "bulan",
|
||||||
|
}))}
|
||||||
|
value={data?.masterPembagianDevidenId}
|
||||||
|
onChange={(val) => {
|
||||||
|
setData({
|
||||||
|
...(data as any),
|
||||||
|
masterPembagianDevidenId: val,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Investasi_ComponentButtonUpdateDataInvestasi
|
||||||
|
data={data as any}
|
||||||
|
file={file as any}
|
||||||
|
totalLembar={totalLembar}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
</Stack>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component";
|
||||||
|
import { Box, Grid, Skeleton } from "@mantine/core";
|
||||||
|
|
||||||
|
export default function SkeletonInvestasiPortofolio() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{[...Array(4)].map((_, index) => (
|
||||||
|
<ComponentGlobal_CardStyles key={index}>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={7}>
|
||||||
|
<Box>
|
||||||
|
{[...Array(3)].map((_, i) => (
|
||||||
|
<Box key={i} py={5}>
|
||||||
|
<Grid align="center">
|
||||||
|
<Grid.Col span={12}>
|
||||||
|
<Skeleton w={"90%"} h={23} />
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</Box>
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={5}>
|
||||||
|
<Skeleton w={"100%"} height={100} radius="md" />
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</ComponentGlobal_CardStyles>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
|
||||||
|
import ComponentGlobal_Loader from "@/app_modules/_global/component/loader";
|
||||||
|
import { Investasi_ComponentCardPortofolio_NotPublishNew } from "@/app_modules/investasi/_component/main/comp_card_portofolio_not_publish_new";
|
||||||
|
import { Investasi_ComponentCardPortofolioPublishNew } from "@/app_modules/investasi/_component/main/comp_card_portofolio_publish_new";
|
||||||
|
import { apiGetAllInvestasi } from "@/app_modules/investasi/_lib/api_interface";
|
||||||
|
import { IDataInvestasiBursa } from "@/app_modules/investasi/_lib/type_investasi";
|
||||||
|
import { Box, Center } from "@mantine/core";
|
||||||
|
import { useShallowEffect } from "@mantine/hooks";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { ScrollOnly } from "next-scroll-loader";
|
||||||
|
import { useParams } from "next/navigation";
|
||||||
|
import { useState } from "react";
|
||||||
|
import SkeletonInvestasiPortofolio from "./skeleton_portofolio";
|
||||||
|
|
||||||
|
export function Investasi_ViewPortofolioNew() {
|
||||||
|
const param = useParams<{ id: string }>();
|
||||||
|
const [data, setData] = useState<IDataInvestasiBursa[]>([]);
|
||||||
|
const [activePage, setActivePage] = useState(1);
|
||||||
|
const [loading, setLoading] = useState(true)
|
||||||
|
|
||||||
|
async function getDataInvestasi() {
|
||||||
|
try {
|
||||||
|
setLoading(true)
|
||||||
|
const response = await apiGetAllInvestasi(`?cat=portofolio&status=${param.id}&page=1`)
|
||||||
|
if (response.success) {
|
||||||
|
setData(response.data);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
getDataInvestasi()
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Box>
|
||||||
|
{
|
||||||
|
loading ?
|
||||||
|
<SkeletonInvestasiPortofolio />
|
||||||
|
:
|
||||||
|
_.isEmpty(data) ? (
|
||||||
|
<ComponentGlobal_IsEmptyData />
|
||||||
|
) : (
|
||||||
|
<ScrollOnly
|
||||||
|
height="75vh"
|
||||||
|
renderLoading={() => (
|
||||||
|
<Center>
|
||||||
|
<ComponentGlobal_Loader size={25} />
|
||||||
|
</Center>
|
||||||
|
)}
|
||||||
|
data={data}
|
||||||
|
setData={setData}
|
||||||
|
moreData={async () => {
|
||||||
|
const pageNew = activePage + 1
|
||||||
|
const loadData = await apiGetAllInvestasi(`?cat=portofolio&status=${param.id}&page=${pageNew}`)
|
||||||
|
setActivePage((val) => val + 1);
|
||||||
|
|
||||||
|
return loadData.data;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
param.id == "1" ?
|
||||||
|
(item) => (<Investasi_ComponentCardPortofolioPublishNew data={item} />)
|
||||||
|
:
|
||||||
|
(item) => (<Investasi_ComponentCardPortofolio_NotPublishNew data={item} />)
|
||||||
|
}
|
||||||
|
</ScrollOnly>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
31
src/app_modules/investasi/_view/main/skeleton_beranda.tsx
Normal file
31
src/app_modules/investasi/_view/main/skeleton_beranda.tsx
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component";
|
||||||
|
import { Box, Grid, Skeleton } from "@mantine/core";
|
||||||
|
|
||||||
|
export default function SkeletonInvestasiBursa() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{[...Array(4)].map((_, index) => (
|
||||||
|
<ComponentGlobal_CardStyles key={index}>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={6}>
|
||||||
|
<Skeleton w={"100%"} height={100} radius="md" />
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={6}>
|
||||||
|
<Box>
|
||||||
|
{[...Array(3)].map((_, i) => (
|
||||||
|
<Box key={i} py={5}>
|
||||||
|
<Grid align="center">
|
||||||
|
<Grid.Col span={12}>
|
||||||
|
<Skeleton w={"100%"} h={23} />
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</Box>
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</ComponentGlobal_CardStyles>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app_modules/investasi/_view/main/skeleton_saham_saya.tsx
Normal file
18
src/app_modules/investasi/_view/main/skeleton_saham_saya.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component";
|
||||||
|
import { Grid, Skeleton } from "@mantine/core";
|
||||||
|
|
||||||
|
export default function SkeletonInvestasiSahamSaya() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{[...Array(4)].map((_, index) => (
|
||||||
|
<ComponentGlobal_CardStyles key={index}>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={12}>
|
||||||
|
<Skeleton w={"100%"} height={70} radius="md" />
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</ComponentGlobal_CardStyles>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
97
src/app_modules/investasi/_view/main/view_beranda_new.tsx
Normal file
97
src/app_modules/investasi/_view/main/view_beranda_new.tsx
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
'use client'
|
||||||
|
import { RouterInvestasi_OLD } from "@/app/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 { Box, Center } from "@mantine/core";
|
||||||
|
import { useShallowEffect } from "@mantine/hooks";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { ScrollOnly } from "next-scroll-loader";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Investasi_ComponentButtonUpdateBeranda } from "../../_component";
|
||||||
|
import { Investasi_ComponentCardBerandaNew } from "../../_component/main/com_card_beranda_new";
|
||||||
|
import { apiGetAllInvestasi } from "../../_lib/api_interface";
|
||||||
|
import { IDataInvestasiBursa } from "../../_lib/type_investasi";
|
||||||
|
import SkeletonInvestasiBursa from "./skeleton_beranda";
|
||||||
|
|
||||||
|
export function Investasi_ViewBerandaNew() {
|
||||||
|
const [data, setData] = useState<IDataInvestasiBursa[]>([]);
|
||||||
|
const [activePage, setActivePage] = useState(1);
|
||||||
|
const [isNewPost, setIsNewPost] = useState(false);
|
||||||
|
const [loading, setLoading] = useState(true)
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
mqtt_client.subscribe("Beranda_Investasi");
|
||||||
|
|
||||||
|
mqtt_client.on("message", (topic, message) => {
|
||||||
|
const newPost = JSON.parse(message.toString());
|
||||||
|
setIsNewPost(newPost);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
|
async function getDataInvestasi() {
|
||||||
|
try {
|
||||||
|
setLoading(true)
|
||||||
|
const response = await apiGetAllInvestasi(`?cat=bursa&page=1`)
|
||||||
|
if (response.success) {
|
||||||
|
setData(response.data);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
getDataInvestasi()
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{isNewPost && (
|
||||||
|
<Investasi_ComponentButtonUpdateBeranda
|
||||||
|
onLoadData={(val) => {
|
||||||
|
setData(val.data);
|
||||||
|
setIsNewPost(val.isNewPost);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Box>
|
||||||
|
<ComponentGlobal_CreateButton path={RouterInvestasi_OLD.create} />
|
||||||
|
{
|
||||||
|
loading ? <SkeletonInvestasiBursa />
|
||||||
|
:
|
||||||
|
_.isEmpty(data) ? (
|
||||||
|
<ComponentGlobal_IsEmptyData />
|
||||||
|
) : (
|
||||||
|
<ScrollOnly
|
||||||
|
height="82vh"
|
||||||
|
renderLoading={() => (
|
||||||
|
<Center>
|
||||||
|
<ComponentGlobal_Loader size={25} />
|
||||||
|
</Center>
|
||||||
|
)}
|
||||||
|
data={data}
|
||||||
|
setData={setData}
|
||||||
|
moreData={async () => {
|
||||||
|
const pageNew = activePage + 1
|
||||||
|
const loadData = await apiGetAllInvestasi(`?cat=bursa&page=${pageNew}`);
|
||||||
|
setActivePage((val) => val + 1);
|
||||||
|
|
||||||
|
return loadData;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{(item) => <Investasi_ComponentCardBerandaNew data={item as any} />}
|
||||||
|
</ScrollOnly>
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
73
src/app_modules/investasi/_view/main/view_saham_saya_new.tsx
Normal file
73
src/app_modules/investasi/_view/main/view_saham_saya_new.tsx
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
'use client'
|
||||||
|
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
|
||||||
|
import ComponentGlobal_Loader from "@/app_modules/_global/component/loader";
|
||||||
|
import { Box, Center } from "@mantine/core";
|
||||||
|
import { useShallowEffect } from "@mantine/hooks";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { ScrollOnly } from "next-scroll-loader";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Investasi_ComponentSahamSayaNew } from "../../_component/main/comp_card_saham_saya_new";
|
||||||
|
import { apiGetAllSahamSaya } from "../../_lib/api_interface";
|
||||||
|
import { IDataSahamSaya } from "../../_lib/type_investasi";
|
||||||
|
import SkeletonInvestasiSahamSaya from "./skeleton_saham_saya";
|
||||||
|
|
||||||
|
export function Investasi_ViewSahamSayaNew() {
|
||||||
|
const [data, setData] = useState<IDataSahamSaya[]>([]);
|
||||||
|
const [activePage, setActivePage] = useState(1);
|
||||||
|
const [loading, setLoading] = useState(true)
|
||||||
|
|
||||||
|
|
||||||
|
async function getDataSahamSaya() {
|
||||||
|
try {
|
||||||
|
setLoading(true)
|
||||||
|
const response = await apiGetAllSahamSaya(`?cat=saham-saya&page=1`)
|
||||||
|
if (response.success) {
|
||||||
|
setData(response.data);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
getDataSahamSaya()
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Box>
|
||||||
|
{
|
||||||
|
loading ?
|
||||||
|
<SkeletonInvestasiSahamSaya />
|
||||||
|
:
|
||||||
|
_.isEmpty(data) ? (
|
||||||
|
<ComponentGlobal_IsEmptyData />
|
||||||
|
) : (
|
||||||
|
<ScrollOnly
|
||||||
|
height="82vh"
|
||||||
|
renderLoading={() => (
|
||||||
|
<Center>
|
||||||
|
<ComponentGlobal_Loader size={25} />
|
||||||
|
</Center>
|
||||||
|
)}
|
||||||
|
data={data}
|
||||||
|
setData={setData}
|
||||||
|
moreData={async () => {
|
||||||
|
const pageNew = activePage + 1
|
||||||
|
const loadData = await apiGetAllSahamSaya(`?cat=saham-saya&page=${pageNew}`)
|
||||||
|
setActivePage((val) => val + 1);
|
||||||
|
|
||||||
|
return loadData.data;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{(item) => <Investasi_ComponentSahamSayaNew data={item} />}
|
||||||
|
</ScrollOnly>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
72
src/app_modules/investasi/_view/main/view_transaksi_new.tsx
Normal file
72
src/app_modules/investasi/_view/main/view_transaksi_new.tsx
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
'use client'
|
||||||
|
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
|
||||||
|
import { Box, Center, Loader } from "@mantine/core";
|
||||||
|
import { useShallowEffect } from "@mantine/hooks";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { ScrollOnly } from "next-scroll-loader";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Investasi_ComponentCardDaftarTransaksiNew } from "../../_component/main/comp_card_daftar_transaksi_new";
|
||||||
|
import { apiGetAllSahamSaya } from "../../_lib/api_interface";
|
||||||
|
import { IDataSahamSaya } from "../../_lib/type_investasi";
|
||||||
|
import SkeletonInvestasiSahamSaya from "./skeleton_saham_saya";
|
||||||
|
|
||||||
|
export function Investasi_ViewDaftarTransaksiNew() {
|
||||||
|
const [data, setData] = useState<IDataSahamSaya[]>([]);
|
||||||
|
const [activePage, setActivePage] = useState(1);
|
||||||
|
const [loading, setLoading] = useState(true)
|
||||||
|
|
||||||
|
|
||||||
|
async function getDataTransaksi() {
|
||||||
|
try {
|
||||||
|
setLoading(true)
|
||||||
|
const response = await apiGetAllSahamSaya(`?cat=transaksi&page=1`)
|
||||||
|
if (response.success) {
|
||||||
|
setData(response.data);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
getDataTransaksi()
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{
|
||||||
|
loading ?
|
||||||
|
<SkeletonInvestasiSahamSaya />
|
||||||
|
:
|
||||||
|
_.isEmpty(data) ? (
|
||||||
|
<ComponentGlobal_IsEmptyData />
|
||||||
|
) : (
|
||||||
|
<Box>
|
||||||
|
<ScrollOnly
|
||||||
|
height="82vh"
|
||||||
|
renderLoading={() => (
|
||||||
|
<Center mt={"lg"}>
|
||||||
|
<Loader color={"yellow"} />
|
||||||
|
</Center>
|
||||||
|
)}
|
||||||
|
data={data}
|
||||||
|
setData={setData}
|
||||||
|
moreData={async () => {
|
||||||
|
const pageNew = activePage + 1
|
||||||
|
const loadData = await apiGetAllSahamSaya(`?cat=transaksi&page=${pageNew}`)
|
||||||
|
setActivePage((val) => val + 1);
|
||||||
|
|
||||||
|
return loadData.data;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{(item) => <Investasi_ComponentCardDaftarTransaksiNew data={item} />}
|
||||||
|
</ScrollOnly>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
413
src/app_modules/investasi/create/view_new.tsx
Normal file
413
src/app_modules/investasi/create/view_new.tsx
Normal file
@@ -0,0 +1,413 @@
|
|||||||
|
"use client";
|
||||||
|
import { MainColor } from "@/app_modules/_global/color/color_pallet";
|
||||||
|
import { ComponentGlobal_BoxInformation, ComponentGlobal_BoxUploadImage, ComponentGlobal_CardStyles, } from "@/app_modules/_global/component";
|
||||||
|
import { AspectRatio, Box, Button, Center, FileButton, Grid, Group, Image, Select, Stack, Text, TextInput, } from "@mantine/core";
|
||||||
|
import { useShallowEffect } from "@mantine/hooks";
|
||||||
|
import { IconCamera, IconCircleCheck, IconFileTypePdf, IconUpload } from "@tabler/icons-react";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Investasi_ComponentButtonCreateNewInvestasi } from "../_component";
|
||||||
|
import { apiGetMasterInvestasi } from "../_lib/api_interface";
|
||||||
|
|
||||||
|
export default function InvestasiCreateNew() {
|
||||||
|
const [loadingMasterInvestor, setLoadingMasterInvestor] = useState(true)
|
||||||
|
const [loadingMasterPeriodeDeviden, setLoadingMasterPeriodeDeviden] = useState(true)
|
||||||
|
const [loadingMasterPembagianDeviden, setLoadingMasterPembagianDeviden] = useState(true)
|
||||||
|
const [periodeDeviden, setPeriodeDeviden] = useState<any[]>([]);
|
||||||
|
const [pembagianDeviden, setPembagianDeviden] = useState<any[]>([]);
|
||||||
|
const [pencarianInvestor, setPencarianInvestor] = useState<any[]>([]);
|
||||||
|
const [fileImage, setFileImage] = useState<File | null>(null);
|
||||||
|
const [img, setImg] = useState<any | null>();
|
||||||
|
const [filePdf, setFilePdf] = useState<File | null>(null);
|
||||||
|
const [fPdf, setFPdf] = useState<any | null>(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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function onGetMasterInvestor() {
|
||||||
|
try {
|
||||||
|
setLoadingMasterInvestor(true)
|
||||||
|
const response = await apiGetMasterInvestasi("?cat=pencarian-investor")
|
||||||
|
if (response.success) {
|
||||||
|
setPencarianInvestor(response.data)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
} finally {
|
||||||
|
setLoadingMasterInvestor(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function onGetMasterPeriodeDeviden() {
|
||||||
|
try {
|
||||||
|
setLoadingMasterPeriodeDeviden(true)
|
||||||
|
const response = await apiGetMasterInvestasi("?cat=periode-deviden")
|
||||||
|
if (response.success) {
|
||||||
|
setPeriodeDeviden(response.data)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
} finally {
|
||||||
|
setLoadingMasterPeriodeDeviden(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function onGetMasterPembagianDeviden() {
|
||||||
|
try {
|
||||||
|
setLoadingMasterPembagianDeviden(true)
|
||||||
|
const response = await apiGetMasterInvestasi("?cat=pembagian-deviden")
|
||||||
|
if (response.success) {
|
||||||
|
setPembagianDeviden(response.data)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
} finally {
|
||||||
|
setLoadingMasterPembagianDeviden(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
onGetMasterInvestor()
|
||||||
|
onGetMasterPeriodeDeviden()
|
||||||
|
onGetMasterPembagianDeviden()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack px={"xs"} spacing={40}>
|
||||||
|
{/* Upload Image */}
|
||||||
|
<Stack spacing={0}>
|
||||||
|
<Box mb={"sm"}>
|
||||||
|
<ComponentGlobal_BoxInformation informasi="Gambar investasi bisa berupa ilustrasi, poster atau foto terkait investasi" />
|
||||||
|
</Box>
|
||||||
|
<ComponentGlobal_BoxUploadImage>
|
||||||
|
{img ? (
|
||||||
|
<AspectRatio ratio={1 / 1} mah={265} mx={"auto"}>
|
||||||
|
<Image
|
||||||
|
style={{ maxHeight: 250, margin: "auto", padding: "5px" }}
|
||||||
|
alt="Foto"
|
||||||
|
height={250}
|
||||||
|
src={img}
|
||||||
|
/>
|
||||||
|
</AspectRatio>
|
||||||
|
) : (
|
||||||
|
<Stack justify="center" align="center" h={"100%"}>
|
||||||
|
<IconUpload color="white" />
|
||||||
|
<Text fz={10} fs={"italic"} c={"white"} fw={"bold"}>
|
||||||
|
Upload Gambar
|
||||||
|
</Text>
|
||||||
|
</Stack>
|
||||||
|
)}
|
||||||
|
</ComponentGlobal_BoxUploadImage>
|
||||||
|
|
||||||
|
{/* Upload Foto */}
|
||||||
|
<Group position="center">
|
||||||
|
<FileButton
|
||||||
|
onChange={async (files: any) => {
|
||||||
|
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) => (
|
||||||
|
<Button
|
||||||
|
{...props}
|
||||||
|
leftIcon={<IconCamera color="black" />}
|
||||||
|
radius={50}
|
||||||
|
bg={MainColor.yellow}
|
||||||
|
color="yellow"
|
||||||
|
c={"black"}
|
||||||
|
>
|
||||||
|
Upload Gambar
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</FileButton>
|
||||||
|
</Group>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
{/* Upload File */}
|
||||||
|
<Stack spacing={"sm"}>
|
||||||
|
<ComponentGlobal_BoxInformation informasi="File prospektus wajib untuk diupload, agar calon investor paham dengan prospek investasi yang akan anda jalankan kedepan !" />
|
||||||
|
<ComponentGlobal_CardStyles marginBottom={"0px"}>
|
||||||
|
{!filePdf ? (
|
||||||
|
<Text lineClamp={1} align="center" c={"gray"}>
|
||||||
|
Upload File Prospektus
|
||||||
|
</Text>
|
||||||
|
) : (
|
||||||
|
<Grid align="center">
|
||||||
|
<Grid.Col span={2}></Grid.Col>
|
||||||
|
<Grid.Col span={"auto"}>
|
||||||
|
<Text lineClamp={1} align="center">
|
||||||
|
{filePdf.name}
|
||||||
|
</Text>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={2}>
|
||||||
|
<Center>
|
||||||
|
<IconCircleCheck color="green" />
|
||||||
|
</Center>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
|
</ComponentGlobal_CardStyles>
|
||||||
|
|
||||||
|
<Group position="center">
|
||||||
|
<FileButton
|
||||||
|
accept={"application/pdf"}
|
||||||
|
onChange={async (files: any) => {
|
||||||
|
try {
|
||||||
|
const buffer = URL.createObjectURL(
|
||||||
|
new Blob([new Uint8Array(await files.arrayBuffer())])
|
||||||
|
);
|
||||||
|
setFPdf(buffer);
|
||||||
|
setFilePdf(files);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{(props) => (
|
||||||
|
<Button
|
||||||
|
leftIcon={<IconFileTypePdf />}
|
||||||
|
{...props}
|
||||||
|
radius={"xl"}
|
||||||
|
bg={MainColor.yellow}
|
||||||
|
color="yellow"
|
||||||
|
c={"black"}
|
||||||
|
>
|
||||||
|
Upload File
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</FileButton>
|
||||||
|
</Group>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Stack>
|
||||||
|
<TextInput
|
||||||
|
styles={{
|
||||||
|
label: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
withAsterisk
|
||||||
|
label="Judul Investasi"
|
||||||
|
placeholder="Judul investasi"
|
||||||
|
maxLength={100}
|
||||||
|
onChange={(val) => {
|
||||||
|
setValue({
|
||||||
|
...value,
|
||||||
|
title: val.target.value,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextInput
|
||||||
|
styles={{
|
||||||
|
label: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
icon={<Text fw={"bold"}>Rp.</Text>}
|
||||||
|
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,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextInput
|
||||||
|
styles={{
|
||||||
|
label: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
icon={<Text fw={"bold"}>Rp.</Text>}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextInput
|
||||||
|
description="*Total lembar dihitung dari, Target Dana / Harga Perlembar"
|
||||||
|
label="Total Lembar"
|
||||||
|
value={harga === "0" ? "0" : target === "0" ? 0 : totalLembar}
|
||||||
|
readOnly
|
||||||
|
styles={{
|
||||||
|
label: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextInput
|
||||||
|
styles={{
|
||||||
|
label: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
rightSection={
|
||||||
|
<Text fw={"bold"} c={"gray"}>
|
||||||
|
%
|
||||||
|
</Text>
|
||||||
|
}
|
||||||
|
withAsterisk
|
||||||
|
type="number"
|
||||||
|
label={"Rasio Keuntungan / ROI %"}
|
||||||
|
placeholder="Masukan rasio keuntungan"
|
||||||
|
onChange={(val) => {
|
||||||
|
setValue({
|
||||||
|
...value,
|
||||||
|
roi: _.toNumber(val.target.value),
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Select
|
||||||
|
styles={{
|
||||||
|
label: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
withAsterisk
|
||||||
|
label="Pencarian Investor"
|
||||||
|
placeholder={loadingMasterInvestor ? "Loading..." : "Pilih batas waktu"}
|
||||||
|
data={pencarianInvestor.map((e) => ({
|
||||||
|
value: e.id,
|
||||||
|
label: e.name + " " + "hari",
|
||||||
|
}))}
|
||||||
|
onChange={(val) => {
|
||||||
|
setValue({
|
||||||
|
...(value as any),
|
||||||
|
pencarianInvestorId: val,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Select
|
||||||
|
styles={{
|
||||||
|
label: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
withAsterisk
|
||||||
|
label="Periode Deviden"
|
||||||
|
placeholder={loadingMasterPeriodeDeviden ? "Loading..." : "Pilih batas waktu"}
|
||||||
|
data={periodeDeviden.map((e) => ({ value: e.id, label: e.name }))}
|
||||||
|
onChange={(val) => {
|
||||||
|
setValue({
|
||||||
|
...(value as any),
|
||||||
|
periodeDevidenId: val,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Select
|
||||||
|
styles={{
|
||||||
|
label: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
withAsterisk
|
||||||
|
label="Pembagian Deviden"
|
||||||
|
placeholder={loadingMasterPembagianDeviden ? "Loading..." : "Pilih batas waktu"}
|
||||||
|
data={pembagianDeviden.map((e) => ({
|
||||||
|
value: e.id,
|
||||||
|
label: e.name + " " + "bulan",
|
||||||
|
}))}
|
||||||
|
onChange={(val) => {
|
||||||
|
setValue({
|
||||||
|
...(value as any),
|
||||||
|
pembagianDevidenId: val,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Investasi_ComponentButtonCreateNewInvestasi
|
||||||
|
data={value}
|
||||||
|
totalLembar={totalLembar}
|
||||||
|
fileImage={fileImage as any}
|
||||||
|
filePdf={filePdf as any}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user