Merge pull request #275 from bipproduction/Nico/04-feb-25
API Table Investasi Admin
This commit is contained in:
164
src/app/api/admin/investasi/[status]/route.ts
Normal file
164
src/app/api/admin/investasi/[status]/route.ts
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
import { prisma } from "@/app/lib";
|
||||||
|
import _ from "lodash";
|
||||||
|
import moment from "moment";
|
||||||
|
import { NextResponse } from "next/server";
|
||||||
|
|
||||||
|
export async function GET(request: Request, { params }: {
|
||||||
|
params: { status: string }
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
const method = request.method;
|
||||||
|
if (method !== "GET") {
|
||||||
|
return NextResponse.json({
|
||||||
|
success: false,
|
||||||
|
message: "Method not allowed",
|
||||||
|
},
|
||||||
|
{ status: 405 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const { status } = params;
|
||||||
|
const { searchParams } = new URL(request.url);
|
||||||
|
const search = searchParams.get("search");
|
||||||
|
const page = searchParams.get("page");
|
||||||
|
const takeData = 10
|
||||||
|
const skipData = Number(page) * takeData - takeData;
|
||||||
|
|
||||||
|
console.log("Ini Status", status);
|
||||||
|
console.log("Ini Page", page)
|
||||||
|
|
||||||
|
try {
|
||||||
|
let fixData;
|
||||||
|
const fixStatus = _.startCase(status);
|
||||||
|
|
||||||
|
if (!page && !search) {
|
||||||
|
fixData = await prisma.investasi.findMany({
|
||||||
|
orderBy: {
|
||||||
|
updatedAt: "desc",
|
||||||
|
},
|
||||||
|
where: {
|
||||||
|
active: true,
|
||||||
|
MasterStatusInvestasi: {
|
||||||
|
name: fixStatus
|
||||||
|
},
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
author: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
username: true,
|
||||||
|
Profile: {
|
||||||
|
select: {
|
||||||
|
name: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MasterStatusInvestasi: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else if (!page && search) {
|
||||||
|
fixData = await prisma.investasi.findMany({
|
||||||
|
orderBy: {
|
||||||
|
updatedAt: "desc",
|
||||||
|
},
|
||||||
|
where: {
|
||||||
|
active: true,
|
||||||
|
MasterStatusInvestasi: {
|
||||||
|
name: fixStatus
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
contains: search,
|
||||||
|
mode: "insensitive",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
author: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
username: true,
|
||||||
|
Profile: {
|
||||||
|
select: {
|
||||||
|
name: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MasterStatusInvestasi: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else if (page && !search) {
|
||||||
|
|
||||||
|
const data = await prisma.investasi.findMany({
|
||||||
|
take: takeData,
|
||||||
|
skip: skipData,
|
||||||
|
orderBy: [
|
||||||
|
{
|
||||||
|
countDown: "desc",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
where: {
|
||||||
|
active: true,
|
||||||
|
MasterStatusInvestasi: {
|
||||||
|
name: fixStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
MasterStatusInvestasi: true,
|
||||||
|
BeritaInvestasi: true,
|
||||||
|
DokumenInvestasi: true,
|
||||||
|
ProspektusInvestasi: true,
|
||||||
|
MasterPembagianDeviden: true,
|
||||||
|
MasterPencarianInvestor: true,
|
||||||
|
MasterPeriodeDeviden: true,
|
||||||
|
author: true,
|
||||||
|
Investasi_Invoice: {
|
||||||
|
where: {
|
||||||
|
statusInvoiceId: "2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const nCount = await prisma.investasi.count({
|
||||||
|
where: {
|
||||||
|
active: true,
|
||||||
|
MasterStatusInvestasi: {
|
||||||
|
name: fixStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("data >", data)
|
||||||
|
|
||||||
|
fixData = {
|
||||||
|
data: data,
|
||||||
|
nPage: _.ceil(nCount / takeData),
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({
|
||||||
|
success: true,
|
||||||
|
message: "Success",
|
||||||
|
data: fixData,
|
||||||
|
},
|
||||||
|
{ status: 200 }
|
||||||
|
)
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
return NextResponse.json({
|
||||||
|
success: false,
|
||||||
|
message: "Failed",
|
||||||
|
reason: (error as Error).message,
|
||||||
|
},
|
||||||
|
{ status: 500 }
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,10 +2,10 @@ import { Admin_TableRejectInvestasi } from "@/app_modules/admin/investasi";
|
|||||||
import { adminInvestasi_funGetAllReject } from "@/app_modules/admin/investasi/fun/get/get_all_reject";
|
import { adminInvestasi_funGetAllReject } from "@/app_modules/admin/investasi/fun/get/get_all_reject";
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
const dataInvestsi = await adminInvestasi_funGetAllReject({page: 1});
|
// const dataInvestsi = await adminInvestasi_funGetAllReject({page: 1});
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Admin_TableRejectInvestasi dataInvestsi={dataInvestsi as any} />
|
<Admin_TableRejectInvestasi />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ import { Admin_TableReviewInvestasi } from "@/app_modules/admin/investasi";
|
|||||||
import { adminInvestasi_funGetAllReview } from "@/app_modules/admin/investasi/fun/get/get_all_review";
|
import { adminInvestasi_funGetAllReview } from "@/app_modules/admin/investasi/fun/get/get_all_review";
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
const dataInvestsi = await adminInvestasi_funGetAllReview({ page: 1 });
|
// const dataInvestsi = await adminInvestasi_funGetAllReview({ page: 1 });
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Admin_TableReviewInvestasi dataInvestsi={dataInvestsi as any} />
|
<Admin_TableReviewInvestasi />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ import adminNotifikasi_funCreateToUser from "../../notifikasi/fun/create/fun_cre
|
|||||||
import { adminEvent_funGetListReview } from "../fun";
|
import { adminEvent_funGetListReview } from "../fun";
|
||||||
import { AdminEvent_funEditStatusPublishById } from "../fun/edit/fun_edit_status_publish_by_id";
|
import { AdminEvent_funEditStatusPublishById } from "../fun/edit/fun_edit_status_publish_by_id";
|
||||||
import { AdminEvent_funEditCatatanById } from "../fun/edit/fun_edit_status_reject_by_id";
|
import { AdminEvent_funEditCatatanById } from "../fun/edit/fun_edit_status_reject_by_id";
|
||||||
|
import { AdminColor } from "@/app_modules/_global/color/color_pallet";
|
||||||
|
|
||||||
export default function AdminEvent_ComponentTableReview() {
|
export default function AdminEvent_ComponentTableReview() {
|
||||||
const [data, setData] = useState<MODEL_EVENT[] | null>(null);
|
const [data, setData] = useState<MODEL_EVENT[] | null>(null);
|
||||||
@@ -261,28 +262,28 @@ export default function AdminEvent_ComponentTableReview() {
|
|||||||
return data.map((e, i) => (
|
return data.map((e, i) => (
|
||||||
<tr key={i}>
|
<tr key={i}>
|
||||||
<td>
|
<td>
|
||||||
<Center w={200}>
|
<Center c={AdminColor.white} w={200}>
|
||||||
<Text>{e?.Author?.username}</Text>
|
<Text>{e?.Author?.username}</Text>
|
||||||
</Center>
|
</Center>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<Center w={200}>
|
<Center c={AdminColor.white} w={200}>
|
||||||
<Text lineClamp={2}>{e.title}</Text>
|
<Text lineClamp={2}>{e.title}</Text>
|
||||||
</Center>
|
</Center>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<Center w={200}>
|
<Center c={AdminColor.white} w={200}>
|
||||||
<Text>{e.lokasi}</Text>
|
<Text>{e.lokasi}</Text>
|
||||||
</Center>
|
</Center>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<Center w={200}>
|
<Center c={AdminColor.white} w={200}>
|
||||||
<Text>{e.EventMaster_TipeAcara.name}</Text>
|
<Text>{e.EventMaster_TipeAcara.name}</Text>
|
||||||
</Center>
|
</Center>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<Center w={200}>
|
<Center c={AdminColor.white} w={200}>
|
||||||
<Text align="center">
|
<Text align="center">
|
||||||
{new Intl.DateTimeFormat("id-ID", {
|
{new Intl.DateTimeFormat("id-ID", {
|
||||||
dateStyle: "full",
|
dateStyle: "full",
|
||||||
@@ -297,7 +298,7 @@ export default function AdminEvent_ComponentTableReview() {
|
|||||||
</Center>
|
</Center>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<Center w={200}>
|
<Center c={AdminColor.white} w={200}>
|
||||||
<Text align="center">
|
<Text align="center">
|
||||||
{new Intl.DateTimeFormat("id-ID", {
|
{new Intl.DateTimeFormat("id-ID", {
|
||||||
dateStyle: "full",
|
dateStyle: "full",
|
||||||
@@ -313,7 +314,7 @@ export default function AdminEvent_ComponentTableReview() {
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<Center w={400}>
|
<Center c={AdminColor.white} w={400}>
|
||||||
<Spoiler
|
<Spoiler
|
||||||
hideLabel="sembunyikan"
|
hideLabel="sembunyikan"
|
||||||
maxHeight={50}
|
maxHeight={50}
|
||||||
@@ -371,7 +372,7 @@ export default function AdminEvent_ComponentTableReview() {
|
|||||||
<Stack spacing={"xs"} h={"100%"}>
|
<Stack spacing={"xs"} h={"100%"}>
|
||||||
<ComponentAdminGlobal_TitlePage
|
<ComponentAdminGlobal_TitlePage
|
||||||
name="Review"
|
name="Review"
|
||||||
color={"orange.5"}
|
color={AdminColor.softBlue}
|
||||||
component={
|
component={
|
||||||
<TextInput
|
<TextInput
|
||||||
disabled={!data}
|
disabled={!data}
|
||||||
@@ -387,7 +388,7 @@ export default function AdminEvent_ComponentTableReview() {
|
|||||||
{!data ? (
|
{!data ? (
|
||||||
<CustomSkeleton height={"80vh"} width="100%" />
|
<CustomSkeleton height={"80vh"} width="100%" />
|
||||||
) : (
|
) : (
|
||||||
<Paper p={"md"} withBorder shadow="lg" h={"80vh"}>
|
<Paper p={"md"} bg={AdminColor.softBlue} h={"80vh"}>
|
||||||
{isShowReload && (
|
{isShowReload && (
|
||||||
<Affix position={{ top: rem(200) }} w={"100%"}>
|
<Affix position={{ top: rem(200) }} w={"100%"}>
|
||||||
<Center>
|
<Center>
|
||||||
@@ -416,35 +417,33 @@ export default function AdminEvent_ComponentTableReview() {
|
|||||||
horizontalSpacing={"md"}
|
horizontalSpacing={"md"}
|
||||||
p={"md"}
|
p={"md"}
|
||||||
w={1500}
|
w={1500}
|
||||||
striped
|
|
||||||
highlightOnHover
|
|
||||||
>
|
>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
<Center>Username</Center>
|
<Center c={AdminColor.white}>Username</Center>
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<Center>Judul</Center>
|
<Center c={AdminColor.white}>Judul</Center>
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<Center>Lokasi</Center>
|
<Center c={AdminColor.white}>Lokasi</Center>
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<Center>Tipe Acara</Center>
|
<Center c={AdminColor.white}>Tipe Acara</Center>
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<Center>Tanggal & Waktu Mulai</Center>
|
<Center c={AdminColor.white}>Tanggal & Waktu Mulai</Center>
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<Center>Tanggal & Waktu Selesai</Center>
|
<Center c={AdminColor.white}>Tanggal & Waktu Selesai</Center>
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<Center>Deskripsi</Center>
|
<Center c={AdminColor.white}>Deskripsi</Center>
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
<Center>Aksi</Center>
|
<Center c={AdminColor.white}>Aksi</Center>
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|||||||
@@ -137,20 +137,20 @@ function TableStatus() {
|
|||||||
return data.map((e, i) => (
|
return data.map((e, i) => (
|
||||||
<tr key={i}>
|
<tr key={i}>
|
||||||
<td>
|
<td>
|
||||||
<Center w={200}>{e?.Author?.username}</Center>
|
<Center c={AdminColor.white} w={200}>{e?.Author?.username}</Center>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<Center w={200}>{e.title}</Center>
|
<Center c={AdminColor.white} w={200}>{e.title}</Center>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<Center w={200}>{e.lokasi}</Center>
|
<Center c={AdminColor.white} w={200}>{e.lokasi}</Center>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<Center w={200}>{e.EventMaster_TipeAcara.name}</Center>
|
<Center c={AdminColor.white} w={200}>{e.EventMaster_TipeAcara.name}</Center>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<Center w={200}>
|
<Center c={AdminColor.white} w={200}>
|
||||||
<Text align="center">
|
<Text align="center">
|
||||||
{new Intl.DateTimeFormat("id-ID", {
|
{new Intl.DateTimeFormat("id-ID", {
|
||||||
dateStyle: "full",
|
dateStyle: "full",
|
||||||
@@ -165,7 +165,7 @@ function TableStatus() {
|
|||||||
</Center>
|
</Center>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<Center w={200}>
|
<Center c={AdminColor.white} w={200}>
|
||||||
<Text align="center">
|
<Text align="center">
|
||||||
{new Intl.DateTimeFormat("id-ID", {
|
{new Intl.DateTimeFormat("id-ID", {
|
||||||
dateStyle: "full",
|
dateStyle: "full",
|
||||||
@@ -181,7 +181,7 @@ function TableStatus() {
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<Center w={500}>
|
<Center c={AdminColor.white} w={500}>
|
||||||
<Spoiler
|
<Spoiler
|
||||||
hideLabel="sembunyikan"
|
hideLabel="sembunyikan"
|
||||||
maxHeight={50}
|
maxHeight={50}
|
||||||
@@ -193,7 +193,7 @@ function TableStatus() {
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{" "}
|
{" "}
|
||||||
<Center w={400}>
|
<Center c={AdminColor.white} w={400}>
|
||||||
<Spoiler
|
<Spoiler
|
||||||
hideLabel="sembunyikan"
|
hideLabel="sembunyikan"
|
||||||
maxHeight={50}
|
maxHeight={50}
|
||||||
@@ -227,7 +227,7 @@ function TableStatus() {
|
|||||||
<Stack spacing={"xs"} h={"100%"}>
|
<Stack spacing={"xs"} h={"100%"}>
|
||||||
<ComponentAdminGlobal_TitlePage
|
<ComponentAdminGlobal_TitlePage
|
||||||
name="Reject"
|
name="Reject"
|
||||||
color={"red.5"}
|
color={AdminColor.softBlue}
|
||||||
component={
|
component={
|
||||||
<TextInput
|
<TextInput
|
||||||
disabled={!data}
|
disabled={!data}
|
||||||
@@ -244,44 +244,43 @@ function TableStatus() {
|
|||||||
{!data ? (
|
{!data ? (
|
||||||
<CustomSkeleton height={"80vh"} width="100%" />
|
<CustomSkeleton height={"80vh"} width="100%" />
|
||||||
) : (
|
) : (
|
||||||
<Paper p={"md"} withBorder shadow="lg" h={"80vh"}>
|
<Paper p={"md"} bg={AdminColor.softBlue} h={"80vh"}>
|
||||||
<ScrollArea w={"100%"} h={"90%"}>
|
<ScrollArea w={"100%"} h={"90%"}>
|
||||||
<Table
|
<Table
|
||||||
verticalSpacing={"md"}
|
verticalSpacing={"md"}
|
||||||
horizontalSpacing={"md"}
|
horizontalSpacing={"md"}
|
||||||
p={"md"}
|
p={"md"}
|
||||||
w={1500}
|
w={1500}
|
||||||
striped
|
|
||||||
highlightOnHover
|
|
||||||
>
|
>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
<Center>Username</Center>
|
<Center c={AdminColor.white}>Username</Center>
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<Center>Judul</Center>
|
<Center c={AdminColor.white}>Judul</Center>
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<Center>Lokasi</Center>
|
<Center c={AdminColor.white}>Lokasi</Center>
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<Center>Tipe Acara</Center>
|
<Center c={AdminColor.white}>Tipe Acara</Center>
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<Center>Tanggal & Waktu Mulai</Center>
|
<Center c={AdminColor.white}>Tanggal & Waktu Mulai</Center>
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<Center>Tanggal & Waktu Selesai</Center>
|
<Center c={AdminColor.white}>Tanggal & Waktu Selesai</Center>
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<Center>Cacatan</Center>
|
<Center c={AdminColor.white}>Cacatan</Center>
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<Center>Deskripsi</Center>
|
<Center c={AdminColor.white}>Deskripsi</Center>
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<Center>Aksi</Center>
|
<Center c={AdminColor.white}>Aksi</Center>
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
export {
|
||||||
|
apiGetAdminInvestasiCountDashboard,
|
||||||
|
apiGetAdminInvestasiByStatus,
|
||||||
|
}
|
||||||
|
const apiGetAdminInvestasiCountDashboard = async ({ name }:
|
||||||
|
{ name: "Publish" | "Review" | "Reject" }) => {
|
||||||
|
|
||||||
|
|
||||||
|
const { token } = await fetch("/api/get-cookie").then((res) => res.json());
|
||||||
|
if (!token) return await token.json().catch(() => null);
|
||||||
|
|
||||||
|
|
||||||
|
const response = await fetch(`/api/admin/investasi/dashboard/${name}`, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "application/json",
|
||||||
|
"Access-Control-Allow-Origin": "*",
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return await response.json().catch(() => null);
|
||||||
|
};
|
||||||
|
|
||||||
|
const apiGetAdminInvestasiByStatus = async ({ status, page, search }: {
|
||||||
|
status: "Publish" | "Review" | "Reject",
|
||||||
|
page: string,
|
||||||
|
search: string
|
||||||
|
}) => {
|
||||||
|
console.log("dgsdg")
|
||||||
|
const { token } = await fetch("/api/get-cookie").then((res) => res.json());
|
||||||
|
if (!token) return await token.json().catch(() => null);
|
||||||
|
console.log("Ini token", token)
|
||||||
|
console.log("Ini Page", page)
|
||||||
|
console.log("Ini Search", search)
|
||||||
|
|
||||||
|
|
||||||
|
const isPage = page ? `?page=${page}` : "";
|
||||||
|
const isSearch = search ? `&search=${search}` : "";
|
||||||
|
const response = await fetch(`/api/admin/investasi/${status}${isPage}${isSearch}`, {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "application/json",
|
||||||
|
"Access-Control-Allow-Origin": "*",
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
console.log("Ini response", response)
|
||||||
|
return await response.json().catch(() => null);
|
||||||
|
}
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
const apiGetInvestasiCountDashboard = async ({ name }:
|
|
||||||
{ name: "Publish" | "Review" | "Reject" }) => {
|
|
||||||
|
|
||||||
|
|
||||||
const { token } = await fetch("/api/get-cookie").then((res) => res.json());
|
|
||||||
if (!token) return await token.json().catch(() => null);
|
|
||||||
|
|
||||||
|
|
||||||
const response = await fetch(`/api/admin/investasi/dashboard/${name}`, {
|
|
||||||
method: "GET",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
Accept: "application/json",
|
|
||||||
"Access-Control-Allow-Origin": "*",
|
|
||||||
Authorization: `Bearer ${token}`,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
return await response.json().catch(() => null);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default apiGetInvestasiCountDashboard;
|
|
||||||
@@ -25,6 +25,10 @@ import { adminInvestasi_funGetAllPublish } from "../fun/get/get_all_publish";
|
|||||||
import { ComponentAdminGlobal_TitlePage } from "../../_admin_global/_component";
|
import { ComponentAdminGlobal_TitlePage } from "../../_admin_global/_component";
|
||||||
import { MainColor } from "@/app_modules/_global/color";
|
import { MainColor } from "@/app_modules/_global/color";
|
||||||
import { AccentColor, AdminColor } from "@/app_modules/_global/color/color_pallet";
|
import { AccentColor, AdminColor } from "@/app_modules/_global/color/color_pallet";
|
||||||
|
import { apiGetAdminInvestasiByStatus } from "../_lib/api_fetch_admin_investasi";
|
||||||
|
import { useShallowEffect } from "@mantine/hooks";
|
||||||
|
import { clientLogger } from "@/util/clientLogger";
|
||||||
|
import CustomSkeleton from "@/app_modules/components/CustomSkeleton";
|
||||||
|
|
||||||
export default function Admin_TablePublishInvestasi({
|
export default function Admin_TablePublishInvestasi({
|
||||||
dataInvestsi,
|
dataInvestsi,
|
||||||
@@ -50,83 +54,116 @@ function TableView({ listData }: { listData: any }) {
|
|||||||
const [isSearch, setSearch] = useState("");
|
const [isSearch, setSearch] = useState("");
|
||||||
const [isLoading, setLoading] = useState(false);
|
const [isLoading, setLoading] = useState(false);
|
||||||
const [idData, setIdData] = useState("");
|
const [idData, setIdData] = useState("");
|
||||||
|
const [origin, setOrigin] = useState("");
|
||||||
|
|
||||||
async function onSearch(s: string) {
|
useShallowEffect(() => {
|
||||||
setSearch(s);
|
if (typeof window !== "undefined") {
|
||||||
|
setOrigin(window.location.origin);
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
const loadInitialData = async () => {
|
||||||
|
try {
|
||||||
|
const response = await apiGetAdminInvestasiByStatus({
|
||||||
|
status: "Publish",
|
||||||
|
page: `${activePage}`,
|
||||||
|
search: isSearch,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response?.success && response?.data?.data) {
|
||||||
|
setData(response.data.data);
|
||||||
|
setNPage(response.data.nPage || 1);
|
||||||
|
} else {
|
||||||
|
console.error("Invalid data format received:", response);
|
||||||
|
setData([]);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
clientLogger.error("Error get data table publish", error);
|
||||||
|
setData([]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
loadInitialData();
|
||||||
|
}, [activePage, isSearch]);
|
||||||
|
const onSearch = async (searchTerm: string) => {
|
||||||
|
setSearch(searchTerm);
|
||||||
setActivePage(1);
|
setActivePage(1);
|
||||||
const loadData = await adminInvestasi_funGetAllPublish({
|
|
||||||
page: 1,
|
|
||||||
search: s,
|
|
||||||
});
|
|
||||||
setData(loadData.data as any);
|
|
||||||
setNPage(loadData.nPage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onPageClick(p: any) {
|
const onPageClick = (page: number) => {
|
||||||
setActivePage(p);
|
setActivePage(page)
|
||||||
const loadData = await adminInvestasi_funGetAllPublish({
|
|
||||||
search: isSearch,
|
|
||||||
page: p,
|
|
||||||
});
|
|
||||||
setData(loadData.data as any);
|
|
||||||
setNPage(loadData.nPage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const tableBody = data.map((e) => (
|
const renderTableBody = () => {
|
||||||
<tr key={e.id}>
|
if(!Array.isArray(data) || data.length === 0) {
|
||||||
<td>
|
return (
|
||||||
<Center w={200}>
|
<tr>
|
||||||
<Text c={AccentColor.white} lineClamp={1}>{e.author.username}</Text>
|
<td colSpan={12}>
|
||||||
</Center>
|
<Center>
|
||||||
</td>
|
<Text color={"gray"}>Tidak ada data</Text>
|
||||||
<td>
|
</Center>
|
||||||
<Center w={400}>
|
</td>
|
||||||
<Text c={AccentColor.white} lineClamp={1}>{e.title}</Text>
|
</tr>
|
||||||
</Center>
|
);
|
||||||
</td>
|
}
|
||||||
<td>
|
return data.map((e, i) => (
|
||||||
<Center c={AccentColor.white} w={200}>{_.toNumber(e.progress).toFixed(2)} %</Center>
|
<tr key={i}>
|
||||||
</td>
|
<td>
|
||||||
<td>
|
<Center w={200}>
|
||||||
<Center c={AccentColor.white} w={200}>
|
<Text c={AccentColor.white} lineClamp={1}>{e.author.username}</Text>
|
||||||
{new Intl.NumberFormat("id-ID", {
|
</Center>
|
||||||
maximumFractionDigits: 10,
|
</td>
|
||||||
}).format(+e.sisaLembar)}
|
<td>
|
||||||
</Center>
|
<Center w={400}>
|
||||||
</td>
|
<Text c={AccentColor.white} lineClamp={1}>{e.title}</Text>
|
||||||
<td>
|
</Center>
|
||||||
<Center c={AccentColor.white} w={200}>
|
</td>
|
||||||
{new Intl.NumberFormat("id-ID", {
|
<td>
|
||||||
maximumFractionDigits: 10,
|
<Center c={AccentColor.white} w={200}>{_.toNumber(e.progress).toFixed(2)} %</Center>
|
||||||
}).format(+e.totalLembar)}
|
</td>
|
||||||
</Center>
|
<td>
|
||||||
</td>
|
<Center c={AccentColor.white} w={200}>
|
||||||
<td>
|
{new Intl.NumberFormat("id-ID", {
|
||||||
<Center w={200}>
|
maximumFractionDigits: 10,
|
||||||
<Text c={AccentColor.white} lineClamp={1}>{e.Investasi_Invoice.length}</Text>
|
}).format(+e.sisaLembar)}
|
||||||
</Center>
|
</Center>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<Center w={200}>
|
<Center c={AccentColor.white} w={200}>
|
||||||
<Button
|
{new Intl.NumberFormat("id-ID", {
|
||||||
loading={isLoading && idData === e.id}
|
maximumFractionDigits: 10,
|
||||||
loaderPosition="center"
|
}).format(+e.totalLembar)}
|
||||||
bg={"green"}
|
</Center>
|
||||||
color="green"
|
</td>
|
||||||
radius={"xl"}
|
<td>
|
||||||
leftIcon={<IconEyeCheck size={20} />}
|
<Center w={200}>
|
||||||
onClick={() => {
|
<Text c={AccentColor.white} lineClamp={1}>{e.Investasi_Invoice.length}</Text>
|
||||||
setIdData(e.id);
|
</Center>
|
||||||
setLoading(true);
|
</td>
|
||||||
router.push(RouterAdminInvestasi.detail_publish + `${e.id}`);
|
<td>
|
||||||
}}
|
<Center w={200}>
|
||||||
>
|
<Button
|
||||||
Detail
|
loading={isLoading && idData === e.id}
|
||||||
</Button>
|
loaderPosition="center"
|
||||||
</Center>
|
bg={"green"}
|
||||||
</td>
|
color="green"
|
||||||
</tr>
|
radius={"xl"}
|
||||||
));
|
leftIcon={<IconEyeCheck size={20} />}
|
||||||
|
onClick={() => {
|
||||||
|
setIdData(e.id);
|
||||||
|
setLoading(true);
|
||||||
|
router.push(RouterAdminInvestasi.detail_publish + `${e.id}`);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Detail
|
||||||
|
</Button>
|
||||||
|
</Center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -164,8 +201,8 @@ function TableView({ listData }: { listData: any }) {
|
|||||||
/>
|
/>
|
||||||
</Group> */}
|
</Group> */}
|
||||||
|
|
||||||
{_.isEmpty(data) ? (
|
{!data ? (
|
||||||
<ComponentAdminGlobal_IsEmptyData />
|
<CustomSkeleton height={"80vh"} width={"100%"} />
|
||||||
) : (
|
) : (
|
||||||
<Paper bg={AdminColor.softBlue} p={"md"} shadow="lg" h={"80vh"}>
|
<Paper bg={AdminColor.softBlue} p={"md"} shadow="lg" h={"80vh"}>
|
||||||
<ScrollArea w={"100%"} h={"90%"} offsetScrollbars>
|
<ScrollArea w={"100%"} h={"90%"} offsetScrollbars>
|
||||||
@@ -203,7 +240,7 @@ function TableView({ listData }: { listData: any }) {
|
|||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>{tableBody}</tbody>
|
<tbody>{renderTableBody()}</tbody>
|
||||||
</Table>
|
</Table>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
<Center mt={"xl"}>
|
<Center mt={"xl"}>
|
||||||
|
|||||||
@@ -31,162 +31,186 @@ import { RouterAdminInvestasi } from "@/app/lib/router_admin/router_admin_invest
|
|||||||
import { ComponentAdminGlobal_TitlePage } from "../../_admin_global/_component";
|
import { ComponentAdminGlobal_TitlePage } from "../../_admin_global/_component";
|
||||||
import { MainColor } from "@/app_modules/_global/color";
|
import { MainColor } from "@/app_modules/_global/color";
|
||||||
import { AccentColor, AdminColor } from "@/app_modules/_global/color/color_pallet";
|
import { AccentColor, AdminColor } from "@/app_modules/_global/color/color_pallet";
|
||||||
|
import { useShallowEffect } from "@mantine/hooks";
|
||||||
|
import { clientLogger } from "@/util/clientLogger";
|
||||||
|
import { apiGetAdminInvestasiByStatus } from "../_lib/api_fetch_admin_investasi";
|
||||||
|
import CustomSkeleton from "@/app_modules/components/CustomSkeleton";
|
||||||
|
|
||||||
export default function Admin_TableRejectInvestasi({
|
export default function Admin_TableRejectInvestasi() {
|
||||||
dataInvestsi,
|
|
||||||
}: {
|
|
||||||
dataInvestsi: any[];
|
|
||||||
}) {
|
|
||||||
const [investasi, setInvestasi] = useState(dataInvestsi);
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Stack>
|
<Stack>
|
||||||
<ComponentAdminGlobal_HeaderTamplate name="Investasi" />
|
<ComponentAdminGlobal_HeaderTamplate name="Investasi" />
|
||||||
<TableView listData={dataInvestsi} />
|
<TableView/>
|
||||||
</Stack>
|
</Stack>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
const tableBody = investasi.map((e) =>
|
// const tableBody = investasi.map((e) =>
|
||||||
e.MasterStatusInvestasi.id === "4" ? (
|
// e.MasterStatusInvestasi.id === "4" ? (
|
||||||
<tr key={e.id}>
|
// <tr key={e.id}>
|
||||||
<td>
|
// <td>
|
||||||
<Group position="left">
|
// <Group position="left">
|
||||||
<Avatar variant="outline" radius={"xl"} />
|
// <Avatar variant="outline" radius={"xl"} />
|
||||||
<Text>{e.author.username}</Text>
|
// <Text>{e.author.username}</Text>
|
||||||
</Group>
|
// </Group>
|
||||||
</td>
|
// </td>
|
||||||
<td>{_.capitalize(e.title)}</td>
|
// <td>{_.capitalize(e.title)}</td>
|
||||||
<td>{e.catatan}</td>
|
// <td>{e.catatan}</td>
|
||||||
<td>
|
// <td>
|
||||||
<Center>
|
// <Center>
|
||||||
<Tooltip label="Konfirmasi" withArrow position="bottom">
|
// <Tooltip label="Konfirmasi" withArrow position="bottom">
|
||||||
<ActionIcon
|
// <ActionIcon
|
||||||
variant="transparent"
|
// variant="transparent"
|
||||||
onClick={() =>
|
// onClick={() =>
|
||||||
router.push(RouterAdminInvestasi_OLD.konfirmasi + `${e.id}`)
|
// router.push(RouterAdminInvestasi_OLD.konfirmasi + `${e.id}`)
|
||||||
}
|
// }
|
||||||
>
|
// >
|
||||||
<IconEdit color="green" />
|
// <IconEdit color="green" />
|
||||||
</ActionIcon>
|
// </ActionIcon>
|
||||||
</Tooltip>
|
// </Tooltip>
|
||||||
</Center>
|
// </Center>
|
||||||
</td>
|
// </td>
|
||||||
</tr>
|
// </tr>
|
||||||
) : (
|
// ) : (
|
||||||
""
|
// ""
|
||||||
)
|
// )
|
||||||
);
|
// );
|
||||||
|
|
||||||
return (
|
// return (
|
||||||
<>
|
// <>
|
||||||
<Stack>
|
// <Stack>
|
||||||
<ActionIcon
|
// <ActionIcon
|
||||||
variant="outline"
|
// variant="outline"
|
||||||
onClick={() => router.push(RouterAdminInvestasi_OLD.main_investasi)}
|
// onClick={() => router.push(RouterAdminInvestasi_OLD.main_investasi)}
|
||||||
>
|
// >
|
||||||
<IconChevronLeft />
|
// <IconChevronLeft />
|
||||||
</ActionIcon>
|
// </ActionIcon>
|
||||||
<Box>
|
// <Box>
|
||||||
<ScrollArea w={"100%"}>
|
// <ScrollArea w={"100%"}>
|
||||||
<Badge color="red" variant="light" radius={0} size={"xl"}>
|
// <Badge color="red" variant="light" radius={0} size={"xl"}>
|
||||||
Reject
|
// Reject
|
||||||
</Badge>
|
// </Badge>
|
||||||
<Table
|
// <Table
|
||||||
withBorder
|
// withBorder
|
||||||
highlightOnHover
|
// highlightOnHover
|
||||||
verticalSpacing={"md"}
|
// verticalSpacing={"md"}
|
||||||
horizontalSpacing={"md"}
|
// horizontalSpacing={"md"}
|
||||||
>
|
// >
|
||||||
<thead>
|
// <thead>
|
||||||
<tr>
|
// <tr>
|
||||||
<th>Username</th>
|
// <th>Username</th>
|
||||||
<th>Nama Proyek Investasi</th>
|
// <th>Nama Proyek Investasi</th>
|
||||||
<th>Catatan</th>
|
// <th>Catatan</th>
|
||||||
<th>
|
// <th>
|
||||||
<Center>Aksi</Center>
|
// <Center>Aksi</Center>
|
||||||
</th>
|
// </th>
|
||||||
</tr>
|
// </tr>
|
||||||
</thead>
|
// </thead>
|
||||||
<tbody>{tableBody}</tbody>
|
// <tbody>{tableBody}</tbody>
|
||||||
</Table>
|
// </Table>
|
||||||
</ScrollArea>
|
// </ScrollArea>
|
||||||
</Box>
|
// </Box>
|
||||||
</Stack>
|
// </Stack>
|
||||||
</>
|
// </>
|
||||||
);
|
// );
|
||||||
}
|
}
|
||||||
|
|
||||||
function TableView({ listData }: { listData: any }) {
|
function TableView() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [data, setData] = useState<MODEL_INVESTASI[]>(listData.data);
|
const [data, setData] = useState<MODEL_INVESTASI[] | null > (null);
|
||||||
const [nPage, setNPage] = useState(listData.nPage);
|
const [nPage, setNPage] = useState(1);
|
||||||
const [activePage, setActivePage] = useState(1);
|
const [activePage, setActivePage] = useState(1);
|
||||||
const [isSearch, setSearch] = useState("");
|
const [isSearch, setSearch] = useState("");
|
||||||
const [isLoading, setLoading] = useState(false);
|
const [isLoading, setLoading] = useState(false);
|
||||||
const [idData, setIdData] = useState("");
|
const [idData, setIdData] = useState("");
|
||||||
|
|
||||||
async function onSearch(s: string) {
|
|
||||||
setSearch(s);
|
useShallowEffect(() => {
|
||||||
|
const loadInitialData = async () => {
|
||||||
|
try {
|
||||||
|
const response = await apiGetAdminInvestasiByStatus({
|
||||||
|
status: "Reject",
|
||||||
|
page: `${activePage}`,
|
||||||
|
search: isSearch,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response?.success && response?.data.data) {
|
||||||
|
setData(response.data.data);
|
||||||
|
setNPage(response.data.nPage || 1);
|
||||||
|
} else {
|
||||||
|
console.error("Invalid data format recieved:", response);
|
||||||
|
setData([]);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
clientLogger.error("Error get data reject", error);
|
||||||
|
setData([]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loadInitialData();
|
||||||
|
}, [activePage, isSearch]);
|
||||||
|
const onSearch = async (searchTerm: string) => {
|
||||||
|
setSearch(searchTerm);
|
||||||
setActivePage(1);
|
setActivePage(1);
|
||||||
const loadData = await adminInvestasi_funGetAllReject({
|
|
||||||
page: 1,
|
|
||||||
search: s,
|
|
||||||
});
|
|
||||||
setData(loadData.data as any);
|
|
||||||
setNPage(loadData.nPage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onPageClick(p: any) {
|
async function onPageClick(page: number) {
|
||||||
setActivePage(p);
|
setActivePage(page);
|
||||||
const loadData = await adminInvestasi_funGetAllReject({
|
|
||||||
search: isSearch,
|
|
||||||
page: p,
|
|
||||||
});
|
|
||||||
setData(loadData.data as any);
|
|
||||||
setNPage(loadData.nPage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const tableBody = data.map((e) => (
|
const renderTableBody = () => {
|
||||||
<tr key={e.id}>
|
if (!Array.isArray(data) || data.length === 0) {
|
||||||
<td>
|
return (
|
||||||
<Center w={200}>
|
<tr>
|
||||||
<Text c={AccentColor.white} lineClamp={1}>{e.author.username}</Text>
|
<td colSpan={12}>
|
||||||
</Center>
|
<Center>
|
||||||
</td>
|
<Text color="gray">Tidak ada data</Text>
|
||||||
<td>
|
</Center>
|
||||||
<Center w={400}>
|
</td>
|
||||||
<Text c={AccentColor.white} lineClamp={1}>{e.title}</Text>
|
</tr>
|
||||||
</Center>
|
)
|
||||||
</td>
|
}
|
||||||
<td>
|
return data.map((e, i) => (
|
||||||
<Center w={400}>
|
<tr key={i}>
|
||||||
<Text c={AccentColor.white} lineClamp={1}>{e.catatan}</Text>
|
<td>
|
||||||
</Center>
|
<Center w={200}>
|
||||||
</td>
|
<Text c={AccentColor.white} lineClamp={1}>{e.author.username}</Text>
|
||||||
|
</Center>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Center w={400}>
|
||||||
|
<Text c={AccentColor.white} lineClamp={1}>{e.title}</Text>
|
||||||
|
</Center>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Center w={400}>
|
||||||
|
<Text c={AccentColor.white} lineClamp={1}>{e.catatan}</Text>
|
||||||
|
</Center>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<Center w={200}>
|
||||||
|
<Button
|
||||||
|
loading={isLoading && idData === e.id}
|
||||||
|
loaderPosition="center"
|
||||||
|
color="green"
|
||||||
|
leftIcon={<IconEyeCheck size={20}/>}
|
||||||
|
radius={"xl"}
|
||||||
|
onClick={() => {
|
||||||
|
setIdData(e.id);
|
||||||
|
setLoading(true);
|
||||||
|
router.push(RouterAdminInvestasi.detail_reject + `${e.id}`);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Detail
|
||||||
|
</Button>
|
||||||
|
</Center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
<td>
|
|
||||||
<Center w={200}>
|
|
||||||
<Button
|
|
||||||
loading={isLoading && idData === e.id}
|
|
||||||
loaderPosition="center"
|
|
||||||
color="green"
|
|
||||||
leftIcon={<IconEyeCheck size={20}/>}
|
|
||||||
radius={"xl"}
|
|
||||||
onClick={() => {
|
|
||||||
setIdData(e.id);
|
|
||||||
setLoading(true);
|
|
||||||
router.push(RouterAdminInvestasi.detail_reject + `${e.id}`);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Detail
|
|
||||||
</Button>
|
|
||||||
</Center>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
));
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -224,8 +248,8 @@ function TableView({ listData }: { listData: any }) {
|
|||||||
/>
|
/>
|
||||||
</Group> */}
|
</Group> */}
|
||||||
|
|
||||||
{_.isEmpty(data) ? (
|
{!data ? (
|
||||||
<ComponentAdminGlobal_IsEmptyData />
|
<CustomSkeleton height={"80vh"} width="100%" />
|
||||||
) : (
|
) : (
|
||||||
<Paper p={"md"} bg={AdminColor.softBlue} shadow="lg" h={"80vh"}>
|
<Paper p={"md"} bg={AdminColor.softBlue} shadow="lg" h={"80vh"}>
|
||||||
<ScrollArea w={"100%"} h={"90%"} offsetScrollbars>
|
<ScrollArea w={"100%"} h={"90%"} offsetScrollbars>
|
||||||
@@ -253,7 +277,7 @@ function TableView({ listData }: { listData: any }) {
|
|||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>{tableBody}</tbody>
|
<tbody>{renderTableBody()}</tbody>
|
||||||
</Table>
|
</Table>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
<Center mt={"xl"}>
|
<Center mt={"xl"}>
|
||||||
|
|||||||
@@ -30,26 +30,25 @@ import ComponentAdminGlobal_TampilanRupiahDonasi from "../../_admin_global/tampi
|
|||||||
import { adminInvestasi_funGetAllReview } from "../fun/get/get_all_review";
|
import { adminInvestasi_funGetAllReview } from "../fun/get/get_all_review";
|
||||||
import { ComponentAdminGlobal_TitlePage } from "../../_admin_global/_component";
|
import { ComponentAdminGlobal_TitlePage } from "../../_admin_global/_component";
|
||||||
import { AdminColor } from "@/app_modules/_global/color/color_pallet";
|
import { AdminColor } from "@/app_modules/_global/color/color_pallet";
|
||||||
|
import { apiGetAdminInvestasiByStatus } from "../_lib/api_fetch_admin_investasi";
|
||||||
|
import { clientLogger } from "@/util/clientLogger";
|
||||||
|
import CustomSkeleton from "@/app_modules/components/CustomSkeleton";
|
||||||
|
|
||||||
export default function Admin_TableReviewInvestasi({
|
export default function Admin_TableReviewInvestasi() {
|
||||||
dataInvestsi,
|
|
||||||
}: {
|
|
||||||
dataInvestsi: any[];
|
|
||||||
}) {
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Stack>
|
<Stack>
|
||||||
<ComponentAdminGlobal_HeaderTamplate name="Investasi" />
|
<ComponentAdminGlobal_HeaderTamplate name="Investasi" />
|
||||||
<TableView listData={dataInvestsi} />
|
<TableView />
|
||||||
</Stack>
|
</Stack>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function TableView({ listData }: { listData: any }) {
|
function TableView() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [data, setData] = useState<MODEL_INVESTASI[]>(listData.data);
|
const [data, setData] = useState<MODEL_INVESTASI[] | null>(null);
|
||||||
const [nPage, setNPage] = useState(listData.nPage);
|
const [nPage, setNPage] = useState<number>(1);
|
||||||
const [activePage, setActivePage] = useState(1);
|
const [activePage, setActivePage] = useState(1);
|
||||||
const [isSearch, setSearch] = useState("");
|
const [isSearch, setSearch] = useState("");
|
||||||
const [isLoading, setLoading] = useState(false);
|
const [isLoading, setLoading] = useState(false);
|
||||||
@@ -62,94 +61,108 @@ function TableView({ listData }: { listData: any }) {
|
|||||||
const [isLoadingReload, setLoadingReload] = useState(false);
|
const [isLoadingReload, setLoadingReload] = useState(false);
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
if (isAdminInvestasi_TriggerReview) {
|
loadInitialData();
|
||||||
setIsShowReload(false);
|
}, [activePage, isSearch]);
|
||||||
setIsAdminInvestasi_TriggerReview(false)
|
const loadInitialData = async () => {
|
||||||
}
|
try {
|
||||||
}, [isAdminInvestasi_TriggerReview]);
|
const response = await apiGetAdminInvestasiByStatus({
|
||||||
|
status: "Review",
|
||||||
|
page: `${activePage}`,
|
||||||
|
search: isSearch,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response?.success && response?.data?.data) {
|
||||||
|
setData(response.data.data)
|
||||||
|
setNPage(response.data.nPage || 1)
|
||||||
|
} else {
|
||||||
|
console.error("Invalid data format received:", response);
|
||||||
|
setData([]);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
clientLogger.error("Error get data table review", error);
|
||||||
|
setData([]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const onSearch = async (searchTerm: string) => {
|
||||||
|
setSearch(searchTerm);
|
||||||
|
setActivePage(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const onPageClick = (page: number) => {
|
||||||
|
setActivePage(page);
|
||||||
|
}
|
||||||
async function onLoadData() {
|
async function onLoadData() {
|
||||||
const loadData = await adminInvestasi_funGetAllReview({ page: 1 });
|
loadInitialData();
|
||||||
setData(loadData.data as any);
|
setLoading(false);
|
||||||
setNPage(loadData.nPage);
|
|
||||||
setLoadingReload(false);
|
|
||||||
setIsShowReload(false);
|
setIsShowReload(false);
|
||||||
setIsAdminInvestasi_TriggerReview(false);
|
setIsAdminInvestasi_TriggerReview(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onSearch(s: string) {
|
const renderTableBody = () => {
|
||||||
setSearch(s);
|
if (!Array.isArray(data) || data.length === 0) {
|
||||||
setActivePage(1);
|
return (
|
||||||
const loadData = await adminInvestasi_funGetAllReview({
|
<tr>
|
||||||
page: 1,
|
<td colSpan={12}>
|
||||||
search: s,
|
<Center>
|
||||||
});
|
<Text color="gray">Tidak ada data</Text>
|
||||||
setData(loadData.data as any);
|
</Center>
|
||||||
setNPage(loadData.nPage);
|
</td>
|
||||||
|
</tr>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return data.map((e, i) => (
|
||||||
|
<tr key={i}>
|
||||||
|
<td>
|
||||||
|
<Center c={AccentColor.white} w={200}>
|
||||||
|
<Text lineClamp={1}>{e.author.username}</Text>
|
||||||
|
</Center>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Center c={AccentColor.white} w={400}>
|
||||||
|
<Text lineClamp={1}>{e.title}</Text>
|
||||||
|
</Center>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Center c={AccentColor.white} w={200}>
|
||||||
|
<Text lineClamp={1}>{e.roi} %</Text>
|
||||||
|
</Center>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Center c={AccentColor.white} w={200}>
|
||||||
|
<ComponentAdminGlobal_TampilanRupiahDonasi
|
||||||
|
nominal={_.toNumber(e.targetDana)}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Center c={AccentColor.white} w={200}>
|
||||||
|
<ComponentAdminGlobal_TampilanRupiahDonasi
|
||||||
|
nominal={_.toNumber(e.hargaLembar)}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Center w={200}>
|
||||||
|
<Button
|
||||||
|
loading={isLoading && idData === e.id}
|
||||||
|
loaderPosition="center"
|
||||||
|
color="green"
|
||||||
|
leftIcon={<IconEyeCheck size={20} />}
|
||||||
|
radius={"xl"}
|
||||||
|
onClick={() => {
|
||||||
|
setIdData(e.id);
|
||||||
|
setLoading(true);
|
||||||
|
router.push(RouterAdminInvestasi_OLD.konfirmasi + `${e.id}`);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Detail
|
||||||
|
</Button>
|
||||||
|
</Center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onPageClick(p: any) {
|
|
||||||
setActivePage(p);
|
|
||||||
const loadData = await adminInvestasi_funGetAllReview({
|
|
||||||
search: isSearch,
|
|
||||||
page: p,
|
|
||||||
});
|
|
||||||
setData(loadData.data as any);
|
|
||||||
setNPage(loadData.nPage);
|
|
||||||
}
|
|
||||||
|
|
||||||
const tableBody = data.map((e) => (
|
|
||||||
<tr key={e.id}>
|
|
||||||
<td>
|
|
||||||
<Center c={AccentColor.white} w={200}>
|
|
||||||
<Text lineClamp={1}>{e.author.username}</Text>
|
|
||||||
</Center>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<Center c={AccentColor.white} w={400}>
|
|
||||||
<Text lineClamp={1}>{e.title}</Text>
|
|
||||||
</Center>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<Center c={AccentColor.white} w={200}>
|
|
||||||
<Text lineClamp={1}>{e.roi} %</Text>
|
|
||||||
</Center>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<Center c={AccentColor.white} w={200}>
|
|
||||||
<ComponentAdminGlobal_TampilanRupiahDonasi
|
|
||||||
nominal={_.toNumber(e.targetDana)}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<Center c={AccentColor.white} w={200}>
|
|
||||||
<ComponentAdminGlobal_TampilanRupiahDonasi
|
|
||||||
nominal={_.toNumber(e.hargaLembar)}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<Center w={200}>
|
|
||||||
<Button
|
|
||||||
loading={isLoading && idData === e.id}
|
|
||||||
loaderPosition="center"
|
|
||||||
color="green"
|
|
||||||
leftIcon={<IconEyeCheck size={20}/>}
|
|
||||||
radius={"xl"}
|
|
||||||
onClick={() => {
|
|
||||||
setIdData(e.id);
|
|
||||||
setLoading(true);
|
|
||||||
router.push(RouterAdminInvestasi_OLD.konfirmasi + `${e.id}`);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Detail
|
|
||||||
</Button>
|
|
||||||
</Center>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
));
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Stack spacing={"xs"} h={"100%"}>
|
<Stack spacing={"xs"} h={"100%"}>
|
||||||
@@ -158,13 +171,13 @@ function TableView({ listData }: { listData: any }) {
|
|||||||
color={AdminColor.softBlue}
|
color={AdminColor.softBlue}
|
||||||
component={
|
component={
|
||||||
<TextInput
|
<TextInput
|
||||||
icon={<IconSearch size={20} />}
|
icon={<IconSearch size={20} />}
|
||||||
radius={"xl"}
|
radius={"xl"}
|
||||||
placeholder="Cari nama proyek"
|
placeholder="Cari nama proyek"
|
||||||
onChange={(val) => {
|
onChange={(val) => {
|
||||||
onSearch(val.currentTarget.value);
|
onSearch(val.currentTarget.value);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
{/* <Group
|
{/* <Group
|
||||||
@@ -186,8 +199,8 @@ function TableView({ listData }: { listData: any }) {
|
|||||||
/>
|
/>
|
||||||
</Group> */}
|
</Group> */}
|
||||||
|
|
||||||
{_.isEmpty(data) ? (
|
{!data ? (
|
||||||
<ComponentAdminGlobal_IsEmptyData />
|
<CustomSkeleton height={"80vh"} width={"100%"} />
|
||||||
) : (
|
) : (
|
||||||
<Paper p={"md"} bg={AdminColor.softBlue} shadow="lg" h={"80vh"}>
|
<Paper p={"md"} bg={AdminColor.softBlue} shadow="lg" h={"80vh"}>
|
||||||
{isShowReload && (
|
{isShowReload && (
|
||||||
@@ -245,7 +258,7 @@ function TableView({ listData }: { listData: any }) {
|
|||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>{tableBody}</tbody>
|
<tbody>{renderTableBody()}</tbody>
|
||||||
</Table>
|
</Table>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
<Center mt={"xl"}>
|
<Center mt={"xl"}>
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ import { clientLogger } from "@/util/clientLogger";
|
|||||||
import CustomSkeleton from "@/app_modules/components/CustomSkeleton";
|
import CustomSkeleton from "@/app_modules/components/CustomSkeleton";
|
||||||
import global_limit from "@/app/lib/limit";
|
import global_limit from "@/app/lib/limit";
|
||||||
import { useShallowEffect } from "@mantine/hooks";
|
import { useShallowEffect } from "@mantine/hooks";
|
||||||
import apiGetInvestasiCountDashboard from "../_lib/api_fetch_count_status";
|
import { apiGetAdminInvestasiCountDashboard } from "../_lib/api_fetch_admin_investasi";
|
||||||
|
|
||||||
|
|
||||||
export default function Admin_Investasi({
|
export default function Admin_Investasi({
|
||||||
listInvestasi,
|
listInvestasi,
|
||||||
@@ -88,7 +89,7 @@ export default function Admin_Investasi({
|
|||||||
async function onLoadCountPublish() {
|
async function onLoadCountPublish() {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
const response = await apiGetInvestasiCountDashboard({
|
const response = await apiGetAdminInvestasiCountDashboard({
|
||||||
name: "Publish",
|
name: "Publish",
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -103,7 +104,7 @@ export default function Admin_Investasi({
|
|||||||
}
|
}
|
||||||
async function onLoadCountReview() {
|
async function onLoadCountReview() {
|
||||||
try {
|
try {
|
||||||
const response = await apiGetInvestasiCountDashboard({
|
const response = await apiGetAdminInvestasiCountDashboard({
|
||||||
name: "Review",
|
name: "Review",
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -116,7 +117,7 @@ export default function Admin_Investasi({
|
|||||||
}
|
}
|
||||||
async function onLoadCountReject() {
|
async function onLoadCountReject() {
|
||||||
try {
|
try {
|
||||||
const response = await apiGetInvestasiCountDashboard({
|
const response = await apiGetAdminInvestasiCountDashboard({
|
||||||
name: "Reject",
|
name: "Reject",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ const middlewareConfig: MiddlewareConfig = {
|
|||||||
// "/api/admin/voting/dashboard/*",
|
// "/api/admin/voting/dashboard/*",
|
||||||
// "/api/admin/job/dashboard/*",
|
// "/api/admin/job/dashboard/*",
|
||||||
// "/api/admin/forum/dashboard/*",
|
// "/api/admin/forum/dashboard/*",
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Akses awal
|
// Akses awal
|
||||||
|
|||||||
82
templates/ff.config.json
Normal file
82
templates/ff.config.json
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
{
|
||||||
|
"name": "base",
|
||||||
|
"configs": [
|
||||||
|
{
|
||||||
|
"name": "bloc",
|
||||||
|
"commands": [
|
||||||
|
{
|
||||||
|
"name": "[FF] New Big Pack Bloc",
|
||||||
|
"templates": ["*"],
|
||||||
|
"key": "bigpack",
|
||||||
|
"files": [
|
||||||
|
"bloc",
|
||||||
|
"event",
|
||||||
|
"index",
|
||||||
|
"model",
|
||||||
|
"page",
|
||||||
|
"provider",
|
||||||
|
"repository",
|
||||||
|
"screen",
|
||||||
|
"state"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "[FF] New Small Pack Bloc",
|
||||||
|
"templates": ["*"],
|
||||||
|
"key": "smallpack",
|
||||||
|
"files": ["bloc", "event", "index", "page", "screen", "state"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "[FF] New Bloc",
|
||||||
|
"templates": ["*"],
|
||||||
|
"files": ["bloc"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "[FF] New Event",
|
||||||
|
"templates": ["*"],
|
||||||
|
"files": ["event"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "[FF] New Model",
|
||||||
|
"templates": ["*"],
|
||||||
|
"files": ["model"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "[FF] New Page",
|
||||||
|
"templates": ["*"],
|
||||||
|
"files": ["page"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "[FF] New Provider",
|
||||||
|
"templates": ["*"],
|
||||||
|
"files": ["provider"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "[FF] New Repository",
|
||||||
|
"templates": ["*"],
|
||||||
|
"files": ["repository"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "[FF] New Screen",
|
||||||
|
"templates": ["*"],
|
||||||
|
"files": ["screen"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "[FF] New State",
|
||||||
|
"templates": ["*"],
|
||||||
|
"files": ["state"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "[FF] New Index",
|
||||||
|
"templates": ["*"],
|
||||||
|
"files": ["index"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "[FF] New Navigate(Navme)",
|
||||||
|
"templates": ["navigate"],
|
||||||
|
"files": ["navigate"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
16
templates/ff_bloc/bloc.tmpl
Normal file
16
templates/ff_bloc/bloc.tmpl
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import 'package:ff_bloc/ff_bloc.dart';
|
||||||
|
|
||||||
|
import 'package:${appName}${relative}/index.dart';
|
||||||
|
|
||||||
|
class ${upperName}Bloc extends FFBloc<${upperName}Event, ${upperName}State> {
|
||||||
|
${upperName}Bloc({
|
||||||
|
required this.provider,
|
||||||
|
super.initialState = const ${upperName}State(),
|
||||||
|
});
|
||||||
|
/// Use this for all requests to backend - you can mock it in tests
|
||||||
|
final ${upperName}Provider provider;
|
||||||
|
|
||||||
|
@override
|
||||||
|
${upperName}State onErrorState(Object error) => state.copy(error: error, isLoading: false);
|
||||||
|
|
||||||
|
}
|
||||||
78
templates/ff_bloc/event.tmpl
Normal file
78
templates/ff_bloc/event.tmpl
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:ff_bloc/ff_bloc.dart';
|
||||||
|
|
||||||
|
import 'package:${appName}${relative}/index.dart';
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
abstract class ${upperName}Event implements FFBlocEvent<${upperName}State, ${upperName}Bloc> {}
|
||||||
|
|
||||||
|
/// Initial Event with load data
|
||||||
|
class Load${upperName}Event extends ${upperName}Event {
|
||||||
|
Load${upperName}Event({required this.id});
|
||||||
|
final String? id;
|
||||||
|
|
||||||
|
static const String _name = 'Load${upperName}Event';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => _name;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<${upperName}State> applyAsync({required ${upperName}Bloc bloc}) async* {
|
||||||
|
// set loading true for show loading
|
||||||
|
yield bloc.state.copyWithoutError(isLoading: true);
|
||||||
|
// fetch data
|
||||||
|
final result = await bloc.provider.fetchAsync(id);
|
||||||
|
// set data to state
|
||||||
|
yield bloc.state.copyWithoutError(
|
||||||
|
isLoading: false,
|
||||||
|
data: ${upperName}ViewModel(items: result),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Add${upperName}Event extends ${upperName}Event {
|
||||||
|
static const String _name = 'Add${upperName}Event';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => _name;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<${upperName}State> applyAsync({required ${upperName}Bloc bloc}) async* {
|
||||||
|
yield bloc.state.copyWithoutError(isLoading: true);
|
||||||
|
final result = await bloc.provider.addMore(bloc.state.data?.items);
|
||||||
|
yield bloc.state.copyWithoutError(
|
||||||
|
isLoading: false,
|
||||||
|
data: ${upperName}ViewModel(items: result),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ErrorYouAwesomeEvent extends YouAwesomeEvent {
|
||||||
|
static const String _name = 'ErrorYouAwesomeEvent';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => _name;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<YouAwesomeState> applyAsync({required YouAwesomeBloc bloc}) async* {
|
||||||
|
throw Exception('Test error');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Clear${upperName}Event extends ${upperName}Event {
|
||||||
|
static const String _name = 'Clear${upperName}Event';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => _name;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<${upperName}State> applyAsync({required ${upperName}Bloc bloc}) async* {
|
||||||
|
yield bloc.state.copyWithoutError(isLoading: true);
|
||||||
|
yield bloc.state.copyWithoutData(
|
||||||
|
isLoading: false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
0
templates/ff_bloc/index.tmpl
Normal file
0
templates/ff_bloc/index.tmpl
Normal file
51
templates/ff_bloc/model.tmpl
Normal file
51
templates/ff_bloc/model.tmpl
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
// ignore: depend_on_referenced_packages
|
||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
|
||||||
|
class ${upperName}Model extends Equatable {
|
||||||
|
const ${upperName}Model({
|
||||||
|
required this.name,
|
||||||
|
});
|
||||||
|
final String name;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [ name];
|
||||||
|
|
||||||
|
Map<dynamic, dynamic> toMap() {
|
||||||
|
return {
|
||||||
|
'name': name,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static ${upperName}Model? fromMap(Map<dynamic, dynamic>? map) {
|
||||||
|
if (map == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ${upperName}Model(
|
||||||
|
name: map['name']!.toString(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class ${upperName}ViewModel extends Equatable {
|
||||||
|
const ${upperName}ViewModel({
|
||||||
|
// TODO(all): add all required constructor parameters
|
||||||
|
required this.items,
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO(all): declare your fields here
|
||||||
|
final List<${upperName}Model>? items;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [items /*TODO(all): List all fields here*/];
|
||||||
|
|
||||||
|
// TODO(all): implement copyWith
|
||||||
|
${upperName}ViewModel copyWith({
|
||||||
|
List<${upperName}Model>? items,
|
||||||
|
}) {
|
||||||
|
return ${upperName}ViewModel(
|
||||||
|
items: items ?? this.items,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
57
templates/ff_bloc/page.tmpl
Normal file
57
templates/ff_bloc/page.tmpl
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:${appName}${relative}/index.dart';
|
||||||
|
|
||||||
|
|
||||||
|
class ${upperName}Page extends StatefulWidget {
|
||||||
|
const ${upperName}Page({
|
||||||
|
required this.bloc,
|
||||||
|
super.key
|
||||||
|
});
|
||||||
|
static const String routeName = '/${privateName}';
|
||||||
|
|
||||||
|
final ${upperName}Bloc? bloc;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<${upperName}Page> createState() => _${upperName}PageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _${upperName}PageState extends State<${upperName}Page> {
|
||||||
|
|
||||||
|
${upperName}Bloc? _bloc;
|
||||||
|
${upperName}Bloc get bloc {
|
||||||
|
// get it by DI in real code.
|
||||||
|
_bloc ??= widget.bloc ?? ${upperName}Bloc();
|
||||||
|
return _bloc!;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
centerTitle: true,
|
||||||
|
title: const Text('${upperName}'),
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.error),
|
||||||
|
onPressed: () {
|
||||||
|
bloc.add(ErrorYouAwesomeEvent());
|
||||||
|
},
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.add),
|
||||||
|
onPressed: () {
|
||||||
|
bloc.add(Add${upperName}Event());
|
||||||
|
},
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.clear),
|
||||||
|
onPressed: () {
|
||||||
|
bloc.add(Clear${upperName}Event());
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
body: ${upperName}Screen(bloc: bloc),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
26
templates/ff_bloc/provider.tmpl
Normal file
26
templates/ff_bloc/provider.tmpl
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
import 'package:${appName}${relative}/index.dart';
|
||||||
|
|
||||||
|
class ${upperName}Provider {
|
||||||
|
|
||||||
|
Future<List<${upperName}Model>?> fetchAsync(String? id) async {
|
||||||
|
// write logic here to send request to server
|
||||||
|
if (id == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return [${upperName}Model(name: id)];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Future<List<${upperName}Model>?> addMore(List<${upperName}Model>? now) async {
|
||||||
|
// write logic here to send request to server
|
||||||
|
final result = [
|
||||||
|
...(now ?? <${upperName}Model>[]),
|
||||||
|
${upperName}Model(name: now?.length.toString() ?? '0')
|
||||||
|
];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
126
templates/ff_bloc/screen.tmpl
Normal file
126
templates/ff_bloc/screen.tmpl
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:${appName}${relative}/index.dart';
|
||||||
|
|
||||||
|
|
||||||
|
class ${upperName}Screen extends StatefulWidget {
|
||||||
|
const ${upperName}Screen({
|
||||||
|
required this.bloc,
|
||||||
|
super.key,
|
||||||
|
}) ;
|
||||||
|
|
||||||
|
@protected
|
||||||
|
final ${upperName}Bloc bloc;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<${upperName}Screen> createState() {
|
||||||
|
return ${upperName}ScreenState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ${upperName}ScreenState extends State<${upperName}Screen> {
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
// load data on init widget if bloc has not data
|
||||||
|
if (!widget.bloc.state.hasData) {
|
||||||
|
_load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
// dispose bloc if you use subscriptions in bloc
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocBuilder<${upperName}Bloc, ${upperName}State>(
|
||||||
|
bloc: widget.bloc,
|
||||||
|
builder: (
|
||||||
|
BuildContext context,
|
||||||
|
${upperName}State currentState,
|
||||||
|
) {
|
||||||
|
// declaration of bloc states
|
||||||
|
return currentState.when(
|
||||||
|
onLoading: ()=>const CircularProgressIndicator(),
|
||||||
|
onEmpty: (data) => _Empty(),
|
||||||
|
onData: (data) => _BodyList(data: data),
|
||||||
|
onError: (e) => Center(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Text(e.toString()),
|
||||||
|
TextButton(
|
||||||
|
onPressed: _load,
|
||||||
|
child: const Text('ReLoad'),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _load() {
|
||||||
|
widget.bloc.add(Load${upperName}Event(id:'1'));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class _BodyList extends StatefulWidget {
|
||||||
|
const _BodyList({required this.data});
|
||||||
|
|
||||||
|
final ${upperName}ViewModel data;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<_BodyList> createState() => _BodyListState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _BodyListState extends State<_BodyList> {
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
|
return CustomScrollView(
|
||||||
|
// primary: true,
|
||||||
|
slivers: [
|
||||||
|
const SliverToBoxAdapter(child: Divider()),
|
||||||
|
SliverList(
|
||||||
|
delegate: SliverChildBuilderDelegate(
|
||||||
|
(BuildContext context, int index) {
|
||||||
|
final item = widget.data.items![index];
|
||||||
|
if (index == 0) {
|
||||||
|
return Text('Header $index, id = '+item.name);
|
||||||
|
}
|
||||||
|
return Text('Index = $index, id = '+item.name);
|
||||||
|
},
|
||||||
|
childCount: widget.data.items!.length,
|
||||||
|
))]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class _Empty extends StatelessWidget {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
children: <Widget>[
|
||||||
|
Text('Empty'),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
15
templates/ff_bloc/state.tmpl
Normal file
15
templates/ff_bloc/state.tmpl
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import 'package:ff_bloc/ff_bloc.dart';
|
||||||
|
|
||||||
|
import 'package:${appName}${relative}/index.dart';
|
||||||
|
|
||||||
|
class ${upperName}State extends FFState<${upperName}State, ${upperName}ViewModel> {
|
||||||
|
const ${upperName}State({
|
||||||
|
super.version = 0,
|
||||||
|
super.isLoading = false,
|
||||||
|
super.data,
|
||||||
|
super.error,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
StateCopyFactory<${upperName}State, ${upperName}ViewModel> getCopyFactory() => ${upperName}State.new;
|
||||||
|
}
|
||||||
37
templates/mutable/bloc.tmpl
Normal file
37
templates/mutable/bloc.tmpl
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:developer' as developer;
|
||||||
|
|
||||||
|
import 'package:bloc/bloc.dart';
|
||||||
|
import 'package:${appName}${relative}/index.dart';
|
||||||
|
|
||||||
|
class ${upperName}Bloc extends Bloc<${upperName}Event, ${upperName}State> {
|
||||||
|
// todo: check singleton for logic in project
|
||||||
|
// use GetIt for DI in projct
|
||||||
|
static final ${upperName}Bloc _${privateName}BlocSingleton = ${upperName}Bloc._internal();
|
||||||
|
factory ${upperName}Bloc() {
|
||||||
|
return _${privateName}BlocSingleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
${upperName}Bloc._internal(): super(Un${upperName}State(0)){
|
||||||
|
on<${upperName}Event>((event, emit) {
|
||||||
|
return emit.forEach<${upperName}State>(
|
||||||
|
event.applyAsync(currentState: state, bloc: this),
|
||||||
|
onData: (state) => state,
|
||||||
|
onError: (error, stackTrace) {
|
||||||
|
developer.log('$error', name: '${upperName}Bloc', error: error, stackTrace: stackTrace);
|
||||||
|
return Error${upperName}State(0, error.toString());
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> close() async{
|
||||||
|
// dispose objects
|
||||||
|
await super.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
${upperName}State get initialState => Un${upperName}State(0);
|
||||||
|
|
||||||
|
}
|
||||||
42
templates/mutable/event.tmpl
Normal file
42
templates/mutable/event.tmpl
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:developer' as developer;
|
||||||
|
|
||||||
|
import 'package:${appName}${relative}/index.dart';
|
||||||
|
import 'package:meta/meta.dart';
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
abstract class ${upperName}Event {
|
||||||
|
Stream<${upperName}State> applyAsync(
|
||||||
|
{${upperName}State currentState, ${upperName}Bloc bloc});
|
||||||
|
final ${upperName}Repository _${privateName}Repository = ${upperName}Repository();
|
||||||
|
}
|
||||||
|
|
||||||
|
class Un${upperName}Event extends ${upperName}Event {
|
||||||
|
@override
|
||||||
|
Stream<${upperName}State> applyAsync({${upperName}State? currentState, ${upperName}Bloc? bloc}) async* {
|
||||||
|
yield Un${upperName}State(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Load${upperName}Event extends ${upperName}Event {
|
||||||
|
|
||||||
|
final bool isError;
|
||||||
|
@override
|
||||||
|
String toString() => 'Load${upperName}Event';
|
||||||
|
|
||||||
|
Load${upperName}Event(this.isError);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<${upperName}State> applyAsync(
|
||||||
|
{${upperName}State? currentState, ${upperName}Bloc? bloc}) async* {
|
||||||
|
try {
|
||||||
|
yield Un${upperName}State(0);
|
||||||
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
|
_${privateName}Repository.test(isError);
|
||||||
|
yield In${upperName}State(0, 'Hello world');
|
||||||
|
} catch (_, stackTrace) {
|
||||||
|
developer.log('$_', name: 'Load${upperName}Event', error: _, stackTrace: stackTrace);
|
||||||
|
yield Error${upperName}State(0, _.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
0
templates/mutable/index.tmpl
Normal file
0
templates/mutable/index.tmpl
Normal file
47
templates/mutable/model.tmpl
Normal file
47
templates/mutable/model.tmpl
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
|
||||||
|
/// generate by https://javiercbk.github.io/json_to_dart/
|
||||||
|
class Autogenerated${upperName} {
|
||||||
|
final List<${upperName}Model> results;
|
||||||
|
|
||||||
|
Autogenerated${upperName}({required this.results});
|
||||||
|
|
||||||
|
factory Autogenerated${upperName}.fromJson(Map<String, dynamic> json) {
|
||||||
|
var temp = <YouAwesomeModel>[];
|
||||||
|
if (json['results'] != null) {
|
||||||
|
temp = <${upperName}Model>[];
|
||||||
|
json['results'].forEach((v) {
|
||||||
|
temp.add(${upperName}Model.fromJson(v as Map<String, dynamic>));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Autogenerated${upperName}(results: temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final data = <String, dynamic>{};
|
||||||
|
data['results'] = results.map((v) => v.toJson()).toList();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ${upperName}Model extends Equatable {
|
||||||
|
final int id;
|
||||||
|
final String name;
|
||||||
|
|
||||||
|
${upperName}Model(this.id, this.name);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [id, name];
|
||||||
|
|
||||||
|
factory ${upperName}Model.fromJson(Map<String, dynamic> json) {
|
||||||
|
return ${upperName}Model(json['id'] as int, json['name'] as String);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final data = <String, dynamic>{};
|
||||||
|
data['id'] = id;
|
||||||
|
data['name'] = name;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
23
templates/mutable/page.tmpl
Normal file
23
templates/mutable/page.tmpl
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:${appName}${relative}/index.dart';
|
||||||
|
|
||||||
|
class ${upperName}Page extends StatefulWidget {
|
||||||
|
static const String routeName = '/${privateName}';
|
||||||
|
|
||||||
|
@override
|
||||||
|
_${upperName}PageState createState() => _${upperName}PageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _${upperName}PageState extends State<${upperName}Page> {
|
||||||
|
final _${privateName}Bloc = ${upperName}Bloc();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text('${upperName}'),
|
||||||
|
),
|
||||||
|
body: ${upperName}Screen(${privateName}Bloc: _${privateName}Bloc),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
20
templates/mutable/provider.tmpl
Normal file
20
templates/mutable/provider.tmpl
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
class ${upperName}Provider {
|
||||||
|
Future<void> loadAsync(String token) async {
|
||||||
|
/// write from keystore/keychain
|
||||||
|
await Future.delayed(Duration(seconds: 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> saveAsync(String token) async {
|
||||||
|
/// write from keystore/keychain
|
||||||
|
await Future.delayed(Duration(seconds: 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test(bool isError) {
|
||||||
|
if (isError == true){
|
||||||
|
throw Exception('manual error');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
11
templates/mutable/repository.tmpl
Normal file
11
templates/mutable/repository.tmpl
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import 'package:${appName}${relative}/index.dart';
|
||||||
|
|
||||||
|
class ${upperName}Repository {
|
||||||
|
final ${upperName}Provider _${privateName}Provider = ${upperName}Provider();
|
||||||
|
|
||||||
|
${upperName}Repository();
|
||||||
|
|
||||||
|
void test(bool isError) {
|
||||||
|
_${privateName}Provider.test(isError);
|
||||||
|
}
|
||||||
|
}
|
||||||
97
templates/mutable/screen.tmpl
Normal file
97
templates/mutable/screen.tmpl
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:${appName}${relative}/index.dart';
|
||||||
|
|
||||||
|
class ${upperName}Screen extends StatefulWidget {
|
||||||
|
const ${upperName}Screen({
|
||||||
|
required ${upperName}Bloc ${privateName}Bloc,
|
||||||
|
Key? key,
|
||||||
|
}) : _${privateName}Bloc = ${privateName}Bloc,
|
||||||
|
super(key: key);
|
||||||
|
|
||||||
|
final ${upperName}Bloc _${privateName}Bloc;
|
||||||
|
|
||||||
|
@override
|
||||||
|
${upperName}ScreenState createState() {
|
||||||
|
return ${upperName}ScreenState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ${upperName}ScreenState extends State<${upperName}Screen> {
|
||||||
|
${upperName}ScreenState();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_load();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocBuilder<${upperName}Bloc, ${upperName}State>(
|
||||||
|
bloc: widget._${privateName}Bloc,
|
||||||
|
builder: (
|
||||||
|
BuildContext context,
|
||||||
|
${upperName}State currentState,
|
||||||
|
) {
|
||||||
|
if (currentState is Un${upperName}State) {
|
||||||
|
return Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (currentState is Error${upperName}State) {
|
||||||
|
return Center(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
Text(currentState.errorMessage),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 32.0),
|
||||||
|
child: ElevatedButton(
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
backgroundColor: Colors.blue,
|
||||||
|
),
|
||||||
|
child: Text('reload'),
|
||||||
|
onPressed: _load,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if (currentState is In${upperName}State) {
|
||||||
|
return Center(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
Text(currentState.hello),
|
||||||
|
const Text('Flutter files: done'),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 32.0),
|
||||||
|
child: ElevatedButton(
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
backgroundColor: Colors.red,
|
||||||
|
),
|
||||||
|
child: Text('throw error'),
|
||||||
|
onPressed: () => _load(true),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
);
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _load([bool isError = false]) {
|
||||||
|
widget._${privateName}Bloc.add(Load${upperName}Event(isError));
|
||||||
|
}
|
||||||
|
}
|
||||||
83
templates/mutable/state.tmpl
Normal file
83
templates/mutable/state.tmpl
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
|
||||||
|
abstract class ${upperName}State extends Equatable {
|
||||||
|
${upperName}State(this.version);
|
||||||
|
|
||||||
|
/// notify change state without deep clone state
|
||||||
|
final int version;
|
||||||
|
|
||||||
|
/// Copy object for use in action
|
||||||
|
/// if need use deep clone
|
||||||
|
${upperName}State getStateCopy();
|
||||||
|
|
||||||
|
${upperName}State getNewVersion();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [version];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// UnInitialized
|
||||||
|
class Un${upperName}State extends ${upperName}State {
|
||||||
|
|
||||||
|
Un${upperName}State(int version) : super(version);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'Un${upperName}State';
|
||||||
|
|
||||||
|
@override
|
||||||
|
Un${upperName}State getStateCopy() {
|
||||||
|
return Un${upperName}State(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Un${upperName}State getNewVersion() {
|
||||||
|
return Un${upperName}State(version+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initialized
|
||||||
|
class In${upperName}State extends ${upperName}State {
|
||||||
|
|
||||||
|
In${upperName}State(int version, this.hello) : super(version);
|
||||||
|
|
||||||
|
final String hello;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'In${upperName}State $hello';
|
||||||
|
|
||||||
|
@override
|
||||||
|
In${upperName}State getStateCopy() {
|
||||||
|
return In${upperName}State(version, hello);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
In${upperName}State getNewVersion() {
|
||||||
|
return In${upperName}State(version+1, hello);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [version, hello];
|
||||||
|
}
|
||||||
|
|
||||||
|
class Error${upperName}State extends ${upperName}State {
|
||||||
|
Error${upperName}State(int version, this.errorMessage): super(version);
|
||||||
|
|
||||||
|
final String errorMessage;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'Error${upperName}State';
|
||||||
|
|
||||||
|
@override
|
||||||
|
Error${upperName}State getStateCopy() {
|
||||||
|
return Error${upperName}State(version, errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Error${upperName}State getNewVersion() {
|
||||||
|
return Error${upperName}State(version+1,
|
||||||
|
errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [version, errorMessage];
|
||||||
|
}
|
||||||
33
templates/navigate/navigate.tmpl
Normal file
33
templates/navigate/navigate.tmpl
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:navme/navme.dart';
|
||||||
|
import 'package:navme/helpers.dart';
|
||||||
|
|
||||||
|
import 'index.dart';
|
||||||
|
|
||||||
|
class ${upperName}Navigate {
|
||||||
|
// base path
|
||||||
|
static String path = '${privateName}';
|
||||||
|
|
||||||
|
// config for configurate Router
|
||||||
|
static RouteConfig routeConfig = RouteConfig(
|
||||||
|
state: (Uri? uri) => RouteState(uri: path.toUri()),
|
||||||
|
// condition for using this page
|
||||||
|
isThisPage: (RouteState state) {
|
||||||
|
if (state?.firstPath == path) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
// settigs from url
|
||||||
|
settings: (RouteState state) {
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
// get Page for Router
|
||||||
|
page: ({RouteState? state}) {
|
||||||
|
return MaterialPage(
|
||||||
|
key: const ValueKey('${upperName}Page'),
|
||||||
|
child: ${upperName}Page(),
|
||||||
|
name: '${upperName}Page');
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
21
templates/simple/bloc.tmpl
Normal file
21
templates/simple/bloc.tmpl
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:developer' as developer;
|
||||||
|
|
||||||
|
import 'package:bloc/bloc.dart';
|
||||||
|
import 'package:${appName}${relative}/index.dart';
|
||||||
|
|
||||||
|
class ${upperName}Bloc extends Bloc<${upperName}Event, ${upperName}State> {
|
||||||
|
|
||||||
|
${upperName}Bloc(${upperName}State initialState) : super(initialState){
|
||||||
|
on<${upperName}Event>((event, emit) {
|
||||||
|
return emit.forEach<${upperName}State>(
|
||||||
|
event.applyAsync(currentState: state, bloc: this),
|
||||||
|
onData: (state) => state,
|
||||||
|
onError: (error, stackTrace) {
|
||||||
|
developer.log('$error', name: '${upperName}Bloc', error: error, stackTrace: stackTrace);
|
||||||
|
return Error${upperName}State(error.toString());
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
34
templates/simple/event.tmpl
Normal file
34
templates/simple/event.tmpl
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:developer' as developer;
|
||||||
|
|
||||||
|
import 'package:${appName}${relative}/index.dart';
|
||||||
|
import 'package:meta/meta.dart';
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
abstract class ${upperName}Event {
|
||||||
|
Stream<${upperName}State> applyAsync(
|
||||||
|
{${upperName}State currentState, ${upperName}Bloc bloc});
|
||||||
|
}
|
||||||
|
|
||||||
|
class Un${upperName}Event extends ${upperName}Event {
|
||||||
|
@override
|
||||||
|
Stream<${upperName}State> applyAsync({${upperName}State? currentState, ${upperName}Bloc? bloc}) async* {
|
||||||
|
yield Un${upperName}State();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Load${upperName}Event extends ${upperName}Event {
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<${upperName}State> applyAsync(
|
||||||
|
{${upperName}State? currentState, ${upperName}Bloc? bloc}) async* {
|
||||||
|
try {
|
||||||
|
yield Un${upperName}State();
|
||||||
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
|
yield In${upperName}State('Hello world');
|
||||||
|
} catch (_, stackTrace) {
|
||||||
|
developer.log('$_', name: 'Load${upperName}Event', error: _, stackTrace: stackTrace);
|
||||||
|
yield Error${upperName}State( _.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
0
templates/simple/index.tmpl
Normal file
0
templates/simple/index.tmpl
Normal file
13
templates/simple/model.tmpl
Normal file
13
templates/simple/model.tmpl
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
|
||||||
|
/// use https://marketplace.visualstudio.com/items?itemName=BendixMa.dart-data-class-generator
|
||||||
|
class ${upperName}Model extends Equatable {
|
||||||
|
final int id;
|
||||||
|
final String name;
|
||||||
|
|
||||||
|
${upperName}Model(this.id, this.name);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [id, name];
|
||||||
|
|
||||||
|
}
|
||||||
23
templates/simple/page.tmpl
Normal file
23
templates/simple/page.tmpl
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:${appName}${relative}/index.dart';
|
||||||
|
|
||||||
|
class ${upperName}Page extends StatefulWidget {
|
||||||
|
static const String routeName = '/${privateName}';
|
||||||
|
|
||||||
|
@override
|
||||||
|
_${upperName}PageState createState() => _${upperName}PageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _${upperName}PageState extends State<${upperName}Page> {
|
||||||
|
final _${privateName}Bloc = ${upperName}Bloc(Un${upperName}State());
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text('${upperName}'),
|
||||||
|
),
|
||||||
|
body: ${upperName}Screen(${privateName}Bloc: _${privateName}Bloc),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
20
templates/simple/provider.tmpl
Normal file
20
templates/simple/provider.tmpl
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
class ${upperName}Provider {
|
||||||
|
Future<void> loadAsync(String token) async {
|
||||||
|
/// write from keystore/keychain
|
||||||
|
await Future.delayed(Duration(seconds: 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> saveAsync(String token) async {
|
||||||
|
/// write from keystore/keychain
|
||||||
|
await Future.delayed(Duration(seconds: 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test(bool isError) {
|
||||||
|
if (isError == true){
|
||||||
|
throw Exception('manual error');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
11
templates/simple/repository.tmpl
Normal file
11
templates/simple/repository.tmpl
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import 'package:${appName}${relative}/index.dart';
|
||||||
|
|
||||||
|
class ${upperName}Repository {
|
||||||
|
final ${upperName}Provider _${privateName}Provider = ${upperName}Provider();
|
||||||
|
|
||||||
|
${upperName}Repository();
|
||||||
|
|
||||||
|
void test(bool isError) {
|
||||||
|
_${privateName}Provider.test(isError);
|
||||||
|
}
|
||||||
|
}
|
||||||
84
templates/simple/screen.tmpl
Normal file
84
templates/simple/screen.tmpl
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:${appName}${relative}/index.dart';
|
||||||
|
|
||||||
|
class ${upperName}Screen extends StatefulWidget {
|
||||||
|
const ${upperName}Screen({
|
||||||
|
required ${upperName}Bloc ${privateName}Bloc,
|
||||||
|
Key? key,
|
||||||
|
}) : _${privateName}Bloc = ${privateName}Bloc,
|
||||||
|
super(key: key);
|
||||||
|
|
||||||
|
final ${upperName}Bloc _${privateName}Bloc;
|
||||||
|
|
||||||
|
@override
|
||||||
|
${upperName}ScreenState createState() {
|
||||||
|
return ${upperName}ScreenState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ${upperName}ScreenState extends State<${upperName}Screen> {
|
||||||
|
${upperName}ScreenState();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_load();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocBuilder<${upperName}Bloc, ${upperName}State>(
|
||||||
|
bloc: widget._${privateName}Bloc,
|
||||||
|
builder: (
|
||||||
|
BuildContext context,
|
||||||
|
${upperName}State currentState,
|
||||||
|
) {
|
||||||
|
if (currentState is Un${upperName}State) {
|
||||||
|
return Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (currentState is Error${upperName}State) {
|
||||||
|
return Center(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
Text(currentState.errorMessage ),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 32.0),
|
||||||
|
child: RaisedButton(
|
||||||
|
color: Colors.blue,
|
||||||
|
child: Text('reload'),
|
||||||
|
onPressed: _load,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if (currentState is In${upperName}State) {
|
||||||
|
return Center(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
Text(currentState.hello),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
);
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _load() {
|
||||||
|
widget._${privateName}Bloc.add(Load${upperName}Event());
|
||||||
|
}
|
||||||
|
}
|
||||||
42
templates/simple/state.tmpl
Normal file
42
templates/simple/state.tmpl
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
|
||||||
|
abstract class ${upperName}State extends Equatable {
|
||||||
|
${upperName}State();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// UnInitialized
|
||||||
|
class Un${upperName}State extends ${upperName}State {
|
||||||
|
|
||||||
|
Un${upperName}State();
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'Un${upperName}State';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initialized
|
||||||
|
class In${upperName}State extends ${upperName}State {
|
||||||
|
In${upperName}State(this.hello);
|
||||||
|
|
||||||
|
final String hello;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'In${upperName}State $hello';
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [hello];
|
||||||
|
}
|
||||||
|
|
||||||
|
class Error${upperName}State extends ${upperName}State {
|
||||||
|
Error${upperName}State(this.errorMessage);
|
||||||
|
|
||||||
|
final String errorMessage;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'Error${upperName}State';
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [errorMessage];
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user