fix responsive admin

deksripsi:
- app infomation
- user serach
- project collaboration
This commit is contained in:
2025-04-16 11:15:00 +08:00
parent 8a72a3398d
commit f41cbba21f
14 changed files with 759 additions and 498 deletions

View File

@@ -0,0 +1,32 @@
import { NextResponse } from "next/server";
import { prisma } from "@/lib";
export { GET };
async function GET(request: Request) {
try {
const data = await prisma.masterBank.findMany({
orderBy: {
createdAt: "desc",
},
});
return NextResponse.json(
{ success: true, message: "Berhasil mendapatkan data", data: data },
{ status: 200 }
);
} catch (error) {
console.error(
"Error Get Master Bank >>",
error || (error as Error).message
);
return NextResponse.json(
{
success: false,
message: "API Error Get Master Bank ",
reason: (error as Error).message,
},
{ status: 500 }
);
}
}

View File

@@ -0,0 +1,32 @@
import { NextResponse } from "next/server";
import { prisma } from "@/lib";
export { GET };
async function GET(request: Request) {
try {
const data = await prisma.masterBidangBisnis.findMany({
orderBy: {
createdAt: "desc",
},
});
return NextResponse.json(
{ success: true, message: "Berhasil mendapatkan data", data: data },
{ status: 200 }
);
} catch (error) {
console.error(
"Error Get Master Bidang Bisnis >>",
error || (error as Error).message
);
return NextResponse.json(
{
success: false,
message: "API Error Get Master Bidang Bisnis ",
reason: (error as Error).message,
},
{ status: 500 }
);
}
}

View File

@@ -1,18 +1,9 @@
import { adminAppInformation_funGetBidangBisnis } from "@/app_modules/admin/app_info/fun";
import adminAppInformation_getMasterBank from "@/app_modules/admin/app_info/fun/master/get_list_bank";
import adminAppInformation_getNomorAdmin from "@/app_modules/admin/app_info/fun/master/get_nomor_admin";
import { AdminAppInformation_UiMain } from "@/app_modules/admin/app_info/ui";
export default async function Page() {
const listBank = await adminAppInformation_getMasterBank();
const dataBidangBisnis = await adminAppInformation_funGetBidangBisnis()
return (
<>
<AdminAppInformation_UiMain
listBank={listBank}
dataBidangBisnis={dataBidangBisnis}
/>
<AdminAppInformation_UiMain />
</>
);
}

View File

@@ -1,8 +1,6 @@
import { AdminUserAccess_View } from "@/app_modules/admin/user-access";
export default async function Page() {
// const listUser = await adminUserAccess_getListUser({ page: 1 });
return (
<>
<AdminUserAccess_View />

View File

@@ -2,19 +2,25 @@ import { SimpleGrid } from "@mantine/core";
export function Admin_V3_ComponentBreakpoint({
children,
cols
cols,
sm,
md,
lg,
}: {
children: React.ReactNode;
cols?: number;
sm?: number;
md?: number;
lg?: number;
}) {
return (
<>
<SimpleGrid
cols={cols || 2}
breakpoints={[
{ maxWidth: "sm", cols: 1 },
{ maxWidth: "md", cols: 1 },
{ maxWidth: "lg", cols: 1 },
{ maxWidth: "sm", cols: sm || 1 },
{ maxWidth: "md", cols: md || 1 },
{ maxWidth: "lg", cols: lg || 1 },
]}
spacing={"lg"}
verticalSpacing={"lg"}

View File

@@ -11,21 +11,21 @@ export function AdminAppInformation_ComponentTitlePageBank({
<>
<ComponentAdminGlobal_TitlePage
name="Informasi Bank"
component={
<Button
w={120}
leftIcon={<IconCirclePlus />}
radius={"xl"}
onClick={() => {
onEventListener({
isCreate: true,
isUpdate: false,
});
}}
>
Tambah
</Button>
}
// component={
// <Button
// w={120}
// leftIcon={<IconCirclePlus />}
// radius={"xl"}
// onClick={() => {
// onEventListener({
// isCreate: true,
// isUpdate: false,
// });
// }}
// >
// Tambah
// </Button>
// }
/>
</>
);

View File

@@ -0,0 +1,71 @@
export {
apiGetMasterAdminBank,
apiGetMasterAdminBidangBisnis,
};
const apiGetMasterAdminBank = async () => {
try {
// Fetch token from cookie
const { token } = await fetch("/api/get-cookie").then((res) => res.json());
if (!token) {
console.error("No token found");
return null;
}
const response = await fetch(`/api/admin/master/bank`, {
method: "GET",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
Authorization: `Bearer ${token}`,
},
});
// Check if the response is OK
if (!response.ok) {
const errorData = await response.json().catch(() => null);
console.error("Failed to get master admin bank", response.statusText, errorData);
throw new Error(errorData?.message || "Failed to get master admin bank");
}
// Return the JSON response
return await response.json();
} catch (error) {
console.error("Error get master admin bank", error);
throw error; // Re-throw the error to handle it in the calling function
}
};
const apiGetMasterAdminBidangBisnis = async () => {
try {
// Fetch token from cookie
const { token } = await fetch("/api/get-cookie").then((res) => res.json());
if (!token) {
console.error("No token found");
return null;
}
const response = await fetch(`/api/admin/master/bidang-bisnis`, {
method: "GET",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
Authorization: `Bearer ${token}`,
},
});
// Check if the response is OK
if (!response.ok) {
const errorData = await response.json().catch(() => null);
console.error("Failed to get master admin bidang bisnis", response.statusText, errorData);
throw new Error(errorData?.message || "Failed to get master admin bidang bisnis");
}
// Return the JSON response
return await response.json();
} catch (error) {
console.error("Error get master admin bidang bisnis", error);
throw error; // Re-throw the error to handle it in the calling function
}
};

View File

@@ -1,9 +1,7 @@
import { atom } from "jotai";
import { atomWithStorage } from "jotai/utils";
/**
* @param index | 0 - 3 | 1: Whatsapp, 2: Bank, 3: Bidang Bisnis
*/
export const gs_app_information_menu = atomWithStorage(
"gs_app_information_menu",
"1"
);
export const gs_app_information_menu = atomWithStorage("gs_app_informations_menu","2");

View File

@@ -1,29 +1,25 @@
"use client";
import {
AccentColor,
AdminColor,
} from "@/app_modules/_global/color/color_pallet";
import { Button, Group, Stack } from "@mantine/core";
import { useAtom } from "jotai";
import ComponentAdminGlobal_HeaderTamplate from "../../_admin_global/header_tamplate";
import { gs_app_information_menu } from "../lib";
import {
AdminAppInformation_ViewInfoBank,
AdminAppInformation_ViewInformasiWhatApps,
AdminAppInformation_ViewKategoriPortofolio,
} from "../view";
import { AccentColor, AdminColor, MainColor } from "@/app_modules/_global/color/color_pallet";
export default function AdminAppInformation_UiMain({
listBank,
dataBidangBisnis,
}: {
listBank: any[];
dataBidangBisnis: any[];
}) {
export default function AdminAppInformation_UiMain() {
const [selectPage, setSelectPage] = useAtom(gs_app_information_menu);
const listPage = [
{
id: "1",
name: "Whatsapp",
},
// {
// id: "1",
// name: "Whatsapp",
// },
{
id: "2",
name: "Informasi Bank",
@@ -58,18 +54,12 @@ export default function AdminAppInformation_UiMain({
))}
</Group>
{selectPage === "1" && (
{/* {selectPage === "1" && (
<AdminAppInformation_ViewInformasiWhatApps />
)}
)} */}
{selectPage === "2" && (
<AdminAppInformation_ViewInfoBank listBank={listBank} />
)}
{selectPage === "3" && (
<AdminAppInformation_ViewKategoriPortofolio
dataBidangBisnis={dataBidangBisnis}
/>
)}
{selectPage === "2" && <AdminAppInformation_ViewInfoBank />}
{selectPage === "3" && <AdminAppInformation_ViewKategoriPortofolio />}
</Stack>
</>
);

View File

@@ -1,13 +1,16 @@
"use client";
import { AccentColor } from "@/app_modules/_global/color";
import {
AdminColor,
MainColor,
} from "@/app_modules/_global/color/color_pallet";
import { MODEL_MASTER_BANK } from "@/app_modules/investasi/_lib/interface";
import {
ActionIcon,
Box,
Button,
Center,
Grid,
Group,
Modal,
Paper,
ScrollArea,
Stack,
@@ -16,29 +19,30 @@ import {
Text,
TextInput,
Title,
Tooltip,
} from "@mantine/core";
import { IconEdit } from "@tabler/icons-react";
import _ from "lodash";
import { useState } from "react";
import { Admin_ComponentModal } from "../../_admin_global/_component/comp_admin_modal";
import { ComponentAdminGlobal_NotifikasiBerhasil } from "../../_admin_global/admin_notifikasi/notifikasi_berhasil";
import { ComponentAdminGlobal_NotifikasiGagal } from "../../_admin_global/admin_notifikasi/notifikasi_gagal";
import { Admin_V3_ComponentBreakpoint } from "../../_components_v3/comp_simple_grid_breakpoint";
import { AdminAppInformation_ComponentTitlePageBank } from "../component";
import adminAppInformation_createBank from "../fun/create/fun_create_new_bank";
import adminAppInformation_getMasterBank from "../fun/master/get_list_bank";
import adminAppInformation_updateStatusBankById from "../fun/update/fun_udpate_status_bank";
import adminAppInformation_updateDataBankById from "../fun/update/fun_update_data_bank";
import { AccentColor } from "@/app_modules/_global/color";
import { AdminColor } from "@/app_modules/_global/color/color_pallet";
import { useShallowEffect } from "@mantine/hooks";
export default function AdminAppInformation_ViewInfoBank({
listBank,
}: {
listBank: MODEL_MASTER_BANK[];
}) {
const [data, setData] = useState(listBank);
const [isCreate, setIsCreate] = useState(false);
import CustomSkeleton from "@/app_modules/components/CustomSkeleton";
import { apiGetMasterAdminBank } from "../lib/api_fetch_master";
export default function AdminAppInformation_ViewInfoBank() {
const [data, setData] = useState<MODEL_MASTER_BANK[] | null>(null);
const [isCreate, setIsCreate] = useState(true);
const [isLoadingCreate, setLoadingCreate] = useState(false);
const [isLoadingUpdate, setLoadingUpdate] = useState(false);
const [isLoadingActivation, setLoadingActivation] = useState(false);
const [newData, setNewData] = useState<any>({
namaBank: "",
@@ -60,35 +64,70 @@ export default function AdminAppInformation_ViewInfoBank({
active: "",
});
useShallowEffect(() => {
handleLoadData();
}, []);
async function handleLoadData() {
try {
const response = await apiGetMasterAdminBank();
if (response && response.success) {
setData(response.data);
} else {
setData([]);
}
} catch (error) {
console.log("Error load data", error);
setData([]);
}
}
async function onCreate() {
const create = await adminAppInformation_createBank({ data: newData });
if (create.status === 200) {
try {
try {
setLoadingCreate(true);
const create = await adminAppInformation_createBank({ data: newData });
if (create.status === 200) {
setNewData({
namaBank: "",
namaAkun: "",
norek: "",
});
const loadData = await adminAppInformation_getMasterBank();
setData(loadData);
} catch (error) {
console.log(error);
} finally {
setLoadingCreate(true);
ComponentAdminGlobal_NotifikasiBerhasil(create.message);
} else {
ComponentAdminGlobal_NotifikasiGagal(create.message);
}
} else {
ComponentAdminGlobal_NotifikasiGagal(create.message);
} catch (error) {
console.log(error);
} finally {
setLoadingCreate(false);
}
setIsCreate(false);
}
async function onUpdate() {
const updt = await adminAppInformation_updateDataBankById({
data: updateData as any,
});
if (updt.status === 200) {
const loadData = await adminAppInformation_getMasterBank();
setData(loadData);
ComponentAdminGlobal_NotifikasiBerhasil(updt.message);
setIsUpdate(false);
} else {
ComponentAdminGlobal_NotifikasiGagal(updt.message);
try {
setLoadingUpdate(true);
const updt = await adminAppInformation_updateDataBankById({
data: updateData as any,
});
if (updt.status === 200) {
const loadData = await adminAppInformation_getMasterBank();
setData(loadData);
setIsUpdate(false);
setIsCreate(true);
ComponentAdminGlobal_NotifikasiBerhasil(updt.message);
} else {
ComponentAdminGlobal_NotifikasiGagal(updt.message);
}
} catch (error) {
console.log("Error update data bank", error);
} finally {
setLoadingUpdate(false);
}
}
@@ -104,36 +143,71 @@ export default function AdminAppInformation_ViewInfoBank({
isActive: value,
};
const updt = await adminAppInformation_updateStatusBankById({
data: data as any,
});
try {
setLoadingActivation(true);
const updt = await adminAppInformation_updateStatusBankById({
data: data as any,
});
if (updt.status === 200) {
const loadData = await adminAppInformation_getMasterBank();
setData(loadData);
ComponentAdminGlobal_NotifikasiBerhasil(updt.message);
setIsActivation(false);
} else {
ComponentAdminGlobal_NotifikasiGagal(updt.message);
if (updt.status === 200) {
const loadData = await adminAppInformation_getMasterBank();
setData(loadData);
ComponentAdminGlobal_NotifikasiBerhasil(updt.message);
setIsActivation(false);
} else {
ComponentAdminGlobal_NotifikasiGagal(updt.message);
}
} catch (error) {
console.log("Error update status bank", error);
} finally {
setLoadingActivation(false);
}
}
const rowTable = _.isEmpty(data) ? (
<tr>
<Center>
<Text>Tidak ada data</Text>
</Center>
</tr>
) : (
data.map((e, i) => (
const rowTable = () => {
if (!Array.isArray(data) || data.length === 0) {
return (
<tr>
<td colSpan={12}>
<Center>
<Text color={"gray"}>Tidak ada data</Text>
</Center>
</td>
</tr>
);
}
return data.map((e, i) => (
<tr key={i}>
<td>
<Center c={AccentColor.white} w={150}>
<Text>{e?.namaBank}</Text>
</Center>
<Stack align="center" justify="center">
<Button
leftIcon={<IconEdit />}
radius={"xl"}
bg={MainColor.green}
color="green"
onClick={() => {
setIsUpdate(true);
setIsCreate(false);
setUpdateData({
id: e?.id,
namaBank: e?.namaBank,
namaAkun: e?.namaAkun,
norek: e?.norek,
});
}}
>
Edit
</Button>
{/* <ActionIcon variant="transparent">
<Tooltip label="Edit">
<IconEdit color={AdminColor.green} />
</Tooltip>
</ActionIcon> */}
</Stack>
</td>
<td>
<Center>
<Box>
<Switch
color="orange"
onLabel="ON"
@@ -147,106 +221,57 @@ export default function AdminAppInformation_ViewInfoBank({
});
}}
/>
</Center>
</td>
<td>
<Center c={AccentColor.white}>
<Text>{e?.namaAkun}</Text>
</Center>
</td>
<td>
<Center c={AccentColor.white}>
<Text>{e?.norek}</Text>
</Center>
</Box>
</td>
<td>
<Stack align="center" justify="center">
<ActionIcon
radius={"xl"}
variant="transparent"
onClick={() => {
setIsUpdate(true);
setIsCreate(false);
setUpdateData({
id: e?.id,
namaBank: e?.namaBank,
namaAkun: e?.namaAkun,
norek: e?.norek,
});
}}
>
<Tooltip label="Edit">
<IconEdit color={AccentColor.white} />
</Tooltip>
</ActionIcon>
</Stack>
<Box c={AccentColor.white} w={100}>
<Text>{e?.namaBank}</Text>
</Box>
</td>
<td>
<Box c={AccentColor.white} w={150}>
<Text>{e?.namaAkun}</Text>
</Box>
</td>
<td>
<Box c={AccentColor.white}>
<Text>{e?.norek}</Text>
</Box>
</td>
</tr>
))
);
));
};
return (
<>
<Stack>
<Stack spacing={"xs"}>
<AdminAppInformation_ComponentTitlePageBank
onEventListener={(val: { isCreate: any; isUpdate: any }) => {
setIsCreate(val.isCreate);
setIsUpdate(val.isUpdate);
}}
/>
</Stack>
<AdminAppInformation_ComponentTitlePageBank
onEventListener={(val: { isCreate: any; isUpdate: any }) => {
setIsCreate(val.isCreate);
setIsUpdate(val.isUpdate);
}}
/>
<Grid>
<Grid.Col span={9}>
<Paper p={"md"} bg={AdminColor.softBlue} h={"65vh"}>
<ScrollArea w={"100%"} h={"90%"} offsetScrollbars>
<Table
verticalSpacing={"xs"}
horizontalSpacing={"md"}
p={"md"}
w={1000}
>
<thead>
<tr>
<th>
<Center c={AdminColor.white} w={150}>Bank</Center>
</th>
<th>
<Center c={AdminColor.white}>Status</Center>
</th>
<th>
<Center c={AdminColor.white}>Nama Rekening</Center>
</th>
<th>
<Center c={AdminColor.white}>Nomor Rekening</Center>
</th>
<th>
<Center c={AdminColor.white}>Aksi</Center>
</th>
</tr>
</thead>
<tbody>{rowTable}</tbody>
</Table>
</ScrollArea>
</Paper>
</Grid.Col>
<Grid.Col span={3}>
{isCreate ? (
<Admin_V3_ComponentBreakpoint>
<div>
{isCreate && (
<Paper p={"md"} bg={AdminColor.softBlue} shadow="lg">
<Stack>
<Center>
<Title c={AccentColor.white} order={5}>Tambah Daftar Bank</Title>
<Title c={AccentColor.white} order={5}>
Tambah Daftar Bank
</Title>
</Center>
<TextInput
label={"Nama Bank"}
value={newData.namaBank}
styles={{
label: {
color: AdminColor.white,}
color: AdminColor.white,
},
}}
placeholder="Masukan nama bank"
onChange={(val) => {
@@ -259,9 +284,11 @@ export default function AdminAppInformation_ViewInfoBank({
<TextInput
label={"Nama Rekening"}
value={newData.namaAkun}
styles={{
label: {
color: AdminColor.white,}
color: AdminColor.white,
},
}}
placeholder="Masukan nama rekening"
onChange={(val) => {
@@ -274,9 +301,11 @@ export default function AdminAppInformation_ViewInfoBank({
<TextInput
label={"Nomor Rekening Bank"}
value={newData.norek}
styles={{
label: {
color: AdminColor.white,}
color: AdminColor.white,
},
}}
placeholder=" Masukan nomor rekening bank"
type="number"
@@ -288,19 +317,20 @@ export default function AdminAppInformation_ViewInfoBank({
}}
/>
<Group position="right" align="flex-end">
<Button
{/* <Button
radius={"xl"}
onClick={() => {
setIsCreate(false);
}}
>
Batal
</Button>
</Button> */}
<Button
loading={isLoadingCreate}
loaderPosition="center"
style={{ transition: "0.5s" }}
disabled={_.values(newData).includes("") ? true : false}
disabled={_.values(newData).includes("") || !data}
radius={"xl"}
color="green"
onClick={() => {
@@ -312,21 +342,22 @@ export default function AdminAppInformation_ViewInfoBank({
</Group>
</Stack>
</Paper>
) : (
""
)}
{isUpdate ? (
{isUpdate && (
<Paper p={"md"} bg={AdminColor.softBlue} shadow="lg">
<Stack>
<Center>
<Title c={AdminColor.white} order={5}>Update Data Bank</Title>
<Title c={AdminColor.white} order={5}>
Update Data Bank
</Title>
</Center>
<TextInput
label={"Nama Bank"}
styles={{
label: {
color: AdminColor.white,}
color: AdminColor.white,
},
}}
placeholder="Masukan nama bank"
value={updateData.namaBank}
@@ -340,7 +371,8 @@ export default function AdminAppInformation_ViewInfoBank({
label={"Nama Rekening"}
styles={{
label: {
color: AdminColor.white,}
color: AdminColor.white,
},
}}
placeholder="Masukan nama rekening"
value={updateData.namaAkun}
@@ -354,7 +386,8 @@ export default function AdminAppInformation_ViewInfoBank({
label={"Nomor Rekening Bank"}
styles={{
label: {
color: AdminColor.white,}
color: AdminColor.white,
},
}}
placeholder=" Masukan nomor rekening bank"
type="number"
@@ -369,11 +402,14 @@ export default function AdminAppInformation_ViewInfoBank({
radius={"xl"}
onClick={() => {
setIsUpdate(false);
setIsCreate(true);
}}
>
Batal
</Button>
<Button
loading={isLoadingUpdate}
loaderPosition="center"
style={{ transition: "0.5s" }}
disabled={
updateData?.namaBank === "" ||
@@ -393,21 +429,52 @@ export default function AdminAppInformation_ViewInfoBank({
</Group>
</Stack>
</Paper>
) : (
""
)}
</Grid.Col>
</Grid>
</div>
</Admin_V3_ComponentBreakpoint>
<Admin_V3_ComponentBreakpoint cols={1}>
{!data ? (
<CustomSkeleton height={"80vh"} width="100%" />
) : (
<Paper p={"md"} bg={AdminColor.softBlue} h={"65vh"}>
<ScrollArea w={"100%"} h={"90%"} offsetScrollbars>
<Table verticalSpacing={"xs"} horizontalSpacing={"md"} p={"md"}>
<thead>
<tr>
<th>
<Center c={AdminColor.white}>Aksi</Center>
</th>
<th>
<Text c={AdminColor.white}>Status</Text>
</th>
<th>
<Text c={AdminColor.white} w={100}>
Bank
</Text>
</th>
<th>
<Text c={AdminColor.white}>Nama Rekening</Text>
</th>
<th>
<Text c={AdminColor.white}>Nomor Rekening</Text>
</th>
</tr>
</thead>
<tbody>{rowTable()}</tbody>
</Table>
</ScrollArea>
</Paper>
)}
</Admin_V3_ComponentBreakpoint>
{/* Activasi bank */}
<Modal
centered
withCloseButton={false}
<Admin_ComponentModal
opened={isActivation}
onClose={() => setIsActivation(false)}
>
<Stack align="center">
<Title order={5}>
<Title order={5} c={MainColor.white}>
Anda ingin{" "}
{updateStatus.active ? (
<Text span inherit>
@@ -425,6 +492,8 @@ export default function AdminAppInformation_ViewInfoBank({
Batal
</Button>
<Button
loading={isLoadingActivation}
loaderPosition="center"
color="green"
radius={"xl"}
onClick={() => {
@@ -438,7 +507,7 @@ export default function AdminAppInformation_ViewInfoBank({
</Button>
</Group>
</Stack>
</Modal>
</Admin_ComponentModal>
</Stack>
</>
);

View File

@@ -14,6 +14,7 @@ import {
Grid,
Group,
Paper,
SimpleGrid,
Stack,
TextInput,
Title,
@@ -25,6 +26,7 @@ import { useState } from "react";
import { ComponentAdminGlobal_NotifikasiBerhasil } from "../../_admin_global/admin_notifikasi/notifikasi_berhasil";
import { ComponentAdminGlobal_NotifikasiGagal } from "../../_admin_global/admin_notifikasi/notifikasi_gagal";
import adminAppInformation_funUpdateNomorAdmin from "../fun/update/fun_update_nomor";
import { Admin_V3_ComponentBreakpoint } from "../../_components_v3/comp_simple_grid_breakpoint";
export default function AdminAppInformation_ViewInformasiWhatApps() {
const [dataNomor, setDataNomor] = useState<any | null>(null);
@@ -89,90 +91,84 @@ export default function AdminAppInformation_ViewInformasiWhatApps() {
</Group>
</Stack>
<Grid>
<Grid.Col span={4}>
{!dataNomor ? (
<CustomSkeleton height={100} width={300} />
) : (
<Paper bg={AdminColor.softBlue} p={"md"}>
<Stack>
<Paper
c={AdminColor.white}
bg={AccentColor.darkblue}
p={"xl"}
>
<Group position="apart">
<Title order={2}>{`+${dataNomor?.nomor}`}</Title>
<Tooltip label={"Edit"}>
<ActionIcon
style={{ transition: "0.2s" }}
variant="transparent"
radius={"xl"}
onClick={() => {
toggle();
setUpdateNomor(dataNomor?.nomor);
}}
>
<IconEdit
style={{
transition: "0.2s",
}}
color={opened ? "gray" : AdminColor.white}
/>
</ActionIcon>
</Tooltip>
</Group>
</Paper>
<Collapse
in={opened}
transitionDuration={300}
transitionTimingFunction="linear"
>
<Stack>
<TextInput
type="number"
placeholder="Update nomor admin"
icon={<IconPhone />}
value={updateNomor}
label={
<Title c="white" order={6}>
Nomor Aktif Admin
</Title>
}
onChange={(val) => {
setUpdateNomor(val.currentTarget.value);
{!dataNomor ? (
<CustomSkeleton height={100} width={300} />
) : (
<Admin_V3_ComponentBreakpoint cols={3} md={2} lg={2}>
<Paper bg={AdminColor.softBlue} p={"md"}>
<Stack>
<Paper c={AdminColor.white} bg={AccentColor.darkblue} p={"xl"}>
<Group position="apart" spacing={0}>
<Tooltip label={"Edit"}>
<ActionIcon
style={{ transition: "0.2s" }}
variant="transparent"
radius={"xl"}
onClick={() => {
toggle();
setUpdateNomor(dataNomor?.nomor);
}}
/>
<Group position="right">
<Button
style={{ transition: "0.2s" }}
radius={"xl"}
onClick={() => {
toggle();
>
<IconEdit
style={{
transition: "0.2s",
}}
>
Batal
</Button>
<Button
style={{ transition: "0.2s" }}
disabled={updateNomor === "" ? true : false}
color="green"
radius={"xl"}
onClick={() => {
onUpdate();
}}
>
Update
</Button>
</Group>
</Stack>
</Collapse>
</Stack>
</Paper>
)}
</Grid.Col>
</Grid>
color={opened ? "gray" : AdminColor.white}
/>
</ActionIcon>
</Tooltip>
<Title order={3}>{`+${dataNomor?.nomor}`}</Title>
</Group>
</Paper>
<Collapse
in={opened}
transitionDuration={300}
transitionTimingFunction="linear"
>
<Stack>
<TextInput
type="number"
placeholder="Update nomor admin"
icon={<IconPhone />}
value={updateNomor}
label={
<Title c="white" order={6}>
Nomor Aktif Admin
</Title>
}
onChange={(val) => {
setUpdateNomor(val.currentTarget.value);
}}
/>
<Group position="right">
<Button
style={{ transition: "0.2s" }}
radius={"xl"}
onClick={() => {
toggle();
}}
>
Batal
</Button>
<Button
style={{ transition: "0.2s" }}
disabled={updateNomor === "" ? true : false}
color="green"
radius={"xl"}
onClick={() => {
onUpdate();
}}
>
Update
</Button>
</Group>
</Stack>
</Collapse>
</Stack>
</Paper>
</Admin_V3_ComponentBreakpoint>
)}
</Stack>
</>
);

View File

@@ -1,68 +1,90 @@
import {
AdminColor,
MainColor,
} from "@/app_modules/_global/color/color_pallet";
import { MODEL_DEFAULT_MASTER_OLD } from "@/app_modules/model_global/interface";
import {
ActionIcon,
Button,
Center,
Grid,
Group,
Modal,
Paper,
ScrollArea,
Stack,
Switch,
Table,
Text,
TextInput,
Title,
Tooltip,
Box,
Button,
Center,
Group,
Paper,
ScrollArea,
Stack,
Switch,
Table,
Text,
TextInput,
Title,
} from "@mantine/core";
import { IconCirclePlus, IconEdit } from "@tabler/icons-react";
import { IconEdit } from "@tabler/icons-react";
import { useState } from "react";
import { ComponentAdminGlobal_TitlePage } from "../../_admin_global/_component";
import { Admin_ComponentModal } from "../../_admin_global/_component/comp_admin_modal";
import { ComponentAdminGlobal_NotifikasiBerhasil } from "../../_admin_global/admin_notifikasi/notifikasi_berhasil";
import { ComponentAdminGlobal_NotifikasiGagal } from "../../_admin_global/admin_notifikasi/notifikasi_gagal";
import { Admin_V3_ComponentBreakpoint } from "../../_components_v3/comp_simple_grid_breakpoint";
import {
adminAppInformation_funCreateBidangBisnis,
adminAppInformation_funGetBidangBisnis,
adminAppInformation_funUpdateBidangBisnis,
adminAppInformation_funCreateBidangBisnis,
adminAppInformation_funGetBidangBisnis,
adminAppInformation_funUpdateBidangBisnis,
} from "../fun";
import { AdminColor } from "@/app_modules/_global/color/color_pallet";
import { useShallowEffect } from "@mantine/hooks";
import { apiGetMasterAdminBidangBisnis } from "../lib/api_fetch_master";
import CustomSkeleton from "@/app_modules/components/CustomSkeleton";
export function AdminAppInformation_ViewKategoriPortofolio({
dataBidangBisnis,
}: {
dataBidangBisnis: MODEL_DEFAULT_MASTER_OLD[];
}) {
const [data, setData] = useState(dataBidangBisnis);
export function AdminAppInformation_ViewKategoriPortofolio() {
const [data, setData] = useState<MODEL_DEFAULT_MASTER_OLD[] | null>(null);
useShallowEffect(() => {
handleLoadData();
}, []);
async function handleLoadData() {
try {
const response = await apiGetMasterAdminBidangBisnis();
if (response && response.success) {
setData(response.data);
} else {
setData([]);
}
} catch (error) {
console.log("Error load data", error);
setData([]);
}
}
// Create
const [isLoadingCreate, setLoadingCreate] = useState(false);
const [isCreate, setIsCreate] = useState(false);
const [isCreate, setIsCreate] = useState(true);
const [newData, setNewData] = useState("");
async function onCreate() {
const create = await adminAppInformation_funCreateBidangBisnis({
name: newData,
});
try {
const create = await adminAppInformation_funCreateBidangBisnis({
name: newData,
});
if (create.status === 201) {
try {
if (create.status === 201) {
setLoadingCreate(true);
const loadData = await adminAppInformation_funGetBidangBisnis();
setData(loadData);
} catch (error) {
console.log(error);
} finally {
setNewData("");
setLoadingCreate(false);
ComponentAdminGlobal_NotifikasiBerhasil(create.message);
} else {
ComponentAdminGlobal_NotifikasiGagal(create.message);
}
} else {
ComponentAdminGlobal_NotifikasiGagal(create.message);
} catch (error) {
console.log(error);
ComponentAdminGlobal_NotifikasiGagal("Gagal menambah bidang bisnis");
} finally {
setLoadingCreate(false);
}
}
// Update Data
const [isLoadingUpdate, setLoadingUpdate] = useState(false);
const [isUpdate, setIsUpdate] = useState(false);
const [updateData, setUpdateData] = useState({
id: "",
@@ -70,22 +92,25 @@ export function AdminAppInformation_ViewKategoriPortofolio({
});
async function onUpdate() {
const updt = await adminAppInformation_funUpdateBidangBisnis({
data: updateData as any,
});
if (updt?.status === 200) {
try {
setLoadingUpdate(true);
try {
setLoadingUpdate(true);
const updt = await adminAppInformation_funUpdateBidangBisnis({
data: updateData as any,
});
if (updt?.status === 200) {
const loadData = await adminAppInformation_funGetBidangBisnis();
setData(loadData);
} catch (error) {
console.log(error);
} finally {
setLoadingUpdate(false);
ComponentAdminGlobal_NotifikasiBerhasil(updt.message);
} else {
ComponentAdminGlobal_NotifikasiGagal(updt?.message as any);
}
} else {
ComponentAdminGlobal_NotifikasiGagal(updt?.message as any);
} catch (error) {
console.log(error);
} finally {
setIsUpdate(false);
setIsCreate(true);
setLoadingUpdate(false);
}
}
@@ -95,6 +120,7 @@ export function AdminAppInformation_ViewKategoriPortofolio({
id: "",
active: null,
});
const [isLoadingActivation, setLoadingActivation] = useState(false);
async function onUpdateActivation({
id,
@@ -103,56 +129,60 @@ export function AdminAppInformation_ViewKategoriPortofolio({
id: string;
active: boolean;
}) {
const updt = await adminAppInformation_funUpdateBidangBisnis({
data: { id: id, active: active },
});
try {
setLoadingActivation(true);
const updt = await adminAppInformation_funUpdateBidangBisnis({
data: { id: id, active: active },
});
if (updt?.status === 200) {
try {
setLoadingUpdate(true);
if (updt?.status === 200) {
const loadData = await adminAppInformation_funGetBidangBisnis();
setData(loadData);
} catch (error) {
console.log(error);
} finally {
setOpenModal(false);
setLoadingUpdate(false);
setLoadingActivation(false);
ComponentAdminGlobal_NotifikasiBerhasil(updt?.message);
} else {
ComponentAdminGlobal_NotifikasiGagal(updt?.message as any);
}
} else {
ComponentAdminGlobal_NotifikasiGagal(updt?.message as any);
} catch (error) {
console.log(error);
ComponentAdminGlobal_NotifikasiGagal("Gagal mengupdate status");
}
}
// Row Table
const rowTable = data.map((e, i) => (
<tr key={i}>
<td>
<Center>
<Text c={AdminColor.white}>{e?.name}</Text>
</Center>
</td>
<td>
<Center>
<Switch
color="orange"
onLabel="ON"
offLabel="OFF"
checked={e?.active}
onChange={(val) => {
setOpenModal(true);
setUpdateStatus({
id: e?.id,
active: val.currentTarget.checked as any,
});
}}
/>
</Center>
</td>
<td>
<Stack align="center" justify="center">
<ActionIcon
const rowTable = () => {
if (!Array.isArray(data) || data.length === 0) {
return (
<tr>
<td colSpan={12}>
<Center>
<Text color={"gray"}>Tidak ada data</Text>
</Center>
</td>
</tr>
);
}
return data.map((e, i) => (
<tr key={i}>
<td>
<Stack align="center" justify="center">
<Button
leftIcon={<IconEdit />}
radius={"xl"}
bg={MainColor.green}
color="green"
onClick={() => {
setIsUpdate(true);
setIsCreate(false);
setUpdateData({
id: e?.id,
name: e?.name,
});
}}
>
Edit
</Button>
{/* <ActionIcon
radius={"xl"}
variant="transparent"
onClick={() => {
@@ -167,68 +197,66 @@ export function AdminAppInformation_ViewKategoriPortofolio({
<Tooltip label="Edit">
<IconEdit color={AdminColor.white} />
</Tooltip>
</ActionIcon>
</Stack>
</td>
</tr>
));
</ActionIcon> */}
</Stack>
</td>
<td>
<Center>
<Switch
color="orange"
onLabel="ON"
offLabel="OFF"
checked={e?.active}
onChange={(val) => {
setOpenModal(true);
setUpdateStatus({
id: e?.id,
active: val.currentTarget.checked as any,
});
}}
/>
</Center>
</td>
<td>
<Box>
<Text c={AdminColor.white}>{e?.name}</Text>
</Box>
</td>
</tr>
));
};
return (
<>
<Stack>
<ComponentAdminGlobal_TitlePage
name="Kategori Bidang Bisnis"
component={
<Button
radius={"xl"}
leftIcon={<IconCirclePlus />}
onClick={() => {
setIsCreate(true);
setIsUpdate(false);
}}
>
Tambah
</Button>
}
// component={
// <Button
// radius={"xl"}
// leftIcon={<IconCirclePlus />}
// onClick={() => {
// setIsCreate(true);
// setIsUpdate(false);
// }}
// >
// Tambah
// </Button>
// }
/>
<Grid>
<Grid.Col span={9}>
<Paper p={"md"} bg={AdminColor.softBlue} h={"65vh"}>
<ScrollArea w={"100%"} h={"90%"} offsetScrollbars>
<Table
verticalSpacing={"xs"}
horizontalSpacing={"md"}
p={"md"}
w={"100%"}
>
<thead>
<tr>
<th>
<Center c={AdminColor.white}>Kategori</Center>
</th>
<th>
<Center c={AdminColor.white}>Status</Center>
</th>
<th>
<Center c={AdminColor.white}>Aksi</Center>
</th>
</tr>
</thead>
<tbody>{rowTable}</tbody>
</Table>
</ScrollArea>
</Paper>
</Grid.Col>
<Grid.Col span={3}>
<Admin_V3_ComponentBreakpoint>
<div>
{/* Form Create */}
{isCreate ? (
<Paper p={"md"} bg={AdminColor.softBlue} shadow="lg">
<Stack>
<Center>
<Title c={AdminColor.white} order={5}>Tambah Bidang Bisnis</Title>
<Title c={AdminColor.white} order={5}>
Tambah Bidang Bisnis
</Title>
</Center>
<TextInput
@@ -240,19 +268,19 @@ export function AdminAppInformation_ViewKategoriPortofolio({
/>
<Group position="right" align="flex-end">
<Button
{/* <Button
radius={"xl"}
onClick={() => {
setIsCreate(false);
}}
>
Batal
</Button>
</Button> */}
<Button
loading={isLoadingCreate}
loaderPosition="center"
style={{ transition: "0.5s" }}
disabled={newData == ""}
disabled={newData == "" || !data}
radius={"xl"}
color="green"
onClick={() => {
@@ -267,12 +295,15 @@ export function AdminAppInformation_ViewKategoriPortofolio({
) : (
""
)}
{/* Form Update */}
{isUpdate ? (
<Paper p={"md"} bg={AdminColor.softBlue} shadow="lg">
<Stack>
<Center>
<Title c={AdminColor.white} order={5}>Update Bidang Bisnis</Title>
<Title c={AdminColor.white} order={5}>
Update Bidang Bisnis
</Title>
</Center>
<TextInput
placeholder="Masukan bidang bisnis"
@@ -288,11 +319,14 @@ export function AdminAppInformation_ViewKategoriPortofolio({
radius={"xl"}
onClick={() => {
setIsUpdate(false);
setIsCreate(true);
}}
>
Batal
</Button>
<Button
loading={isLoadingUpdate}
loaderPosition="center"
style={{ transition: "0.5s" }}
disabled={updateData?.name === ""}
radius={"xl"}
@@ -309,19 +343,47 @@ export function AdminAppInformation_ViewKategoriPortofolio({
) : (
""
)}
</Grid.Col>
</Grid>
</div>
{!data ? (
<CustomSkeleton height={"80vh"} width="100%" />
) : (
<Paper p={"md"} bg={AdminColor.softBlue} h={"65vh"}>
<ScrollArea w={"100%"} h={"90%"} offsetScrollbars>
<Table
verticalSpacing={"xs"}
horizontalSpacing={"md"}
p={"md"}
w={"100%"}
>
<thead>
<tr>
<th>
<Center c={AdminColor.white}>Status</Center>
</th>
<th>
<Center c={AdminColor.white}>Aksi</Center>
</th>
<th>
<Text c={AdminColor.white}>Kategori</Text>
</th>
</tr>
</thead>
<tbody>{rowTable()}</tbody>
</Table>
</ScrollArea>
</Paper>
)}
</Admin_V3_ComponentBreakpoint>
</Stack>
{/* Activasi bank */}
<Modal
centered
withCloseButton={false}
<Admin_ComponentModal
opened={openModal}
onClose={() => setOpenModal(false)}
>
<Stack align="center">
<Title order={5}>
<Title order={5} c={MainColor.white}>
Anda ingin{" "}
{updateStatus.active ? (
<Text span inherit>
@@ -339,6 +401,8 @@ export function AdminAppInformation_ViewKategoriPortofolio({
Batal
</Button>
<Button
loading={isLoadingActivation}
loaderPosition="center"
color="green"
radius={"xl"}
onClick={() => {
@@ -352,7 +416,7 @@ export function AdminAppInformation_ViewKategoriPortofolio({
</Button>
</Group>
</Stack>
</Modal>
</Admin_ComponentModal>
</>
);
}

View File

@@ -19,7 +19,7 @@ import {
TextInput,
Title,
Text,
Box
Box,
} from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import { IconSearch } from "@tabler/icons-react";
@@ -30,7 +30,7 @@ import adminUserAccess_funEditAccess from "../fun/edit/fun_edit_access";
import { Admin_V3_ComponentPaginationBreakpoint } from "../../_components_v3/comp_pagination_breakpoint";
export default function AdminUserAccess_View() {
const [data, setData] = useState<MODEL_USER[]>([]);
const [data, setData] = useState<MODEL_USER[] | null>(null);
const [nPage, setNPage] = useState(1);
const [isActivePage, setActivePage] = useState(1);
const [isSearch, setSearch] = useState("");
@@ -124,51 +124,65 @@ export default function AdminUserAccess_View() {
}
}
const tableBody = data.map((e, i) => (
<tr key={e.id}>
<td>
<Box w={200}>
<Text c={AdminColor.white}>{e.username}</Text>
</Box>
</td>
<td>
<Box w={200}>
<Text c={AdminColor.white}>+{e.nomor}</Text>
</Box>
</td>
<td>
{e.active === false ? (
<Center>
<Button
loaderPosition="center"
loading={isLoadingAccess && userId === e.id}
radius={"xl"}
color="Green"
onClick={() => {
onAccess(e.id, e.nomor);
}}
>
Grand Access
</Button>
</Center>
) : (
<Center>
<Button
loaderPosition="center"
loading={isLoadingDelete && userId === e.id}
radius={"xl"}
color="red"
onClick={() => {
onDelete(e.id);
}}
>
Delete Access
</Button>
</Center>
)}
</td>
</tr>
));
const tableBody = () => {
if (!Array.isArray(data) || data.length === 0) {
return (
<tr>
<td colSpan={12}>
<Center>
<Text color={"gray"}>Tidak ada data</Text>
</Center>
</td>
</tr>
);
}
return data.map((e, i) => (
<tr key={e.id}>
<td>
<Box w={200}>
<Text c={AdminColor.white}>{e.username}</Text>
</Box>
</td>
<td>
<Box w={200}>
<Text c={AdminColor.white}>+{e.nomor}</Text>
</Box>
</td>
<td>
{e.active === false ? (
<Center>
<Button
loaderPosition="center"
loading={isLoadingAccess && userId === e.id}
radius={"xl"}
color="Green"
onClick={() => {
onAccess(e.id, e.nomor);
}}
>
Grand Access
</Button>
</Center>
) : (
<Center>
<Button
loaderPosition="center"
loading={isLoadingDelete && userId === e.id}
radius={"xl"}
color="red"
onClick={() => {
onDelete(e.id);
}}
>
Delete Access
</Button>
</Center>
)}
</td>
</tr>
));
};
return (
<>
@@ -191,7 +205,7 @@ export default function AdminUserAccess_View() {
/>
</Group>
{!data.length ? (
{!data ? (
<CustomSkeleton height={"80vh"} width="100%" />
) : (
<Paper p={"md"} bg={AdminColor.softBlue} h={"80vh"}>
@@ -210,7 +224,7 @@ export default function AdminUserAccess_View() {
</th>
</tr>
</thead>
<tbody>{tableBody}</tbody>
<tbody>{tableBody()}</tbody>
</Table>
</ScrollArea>
<Admin_V3_ComponentPaginationBreakpoint

View File

@@ -34,7 +34,7 @@ const apiGetAllForum = async ({
// Check if the response is OK
if (!response.ok) {
const errorData = await response.json().catch(() => null);
console.error("Failed to get all forum:", response.statusText, errorData);
console.error("Failed to get all forum", response.statusText, errorData);
throw new Error(errorData?.message || "Failed to get all forum");
}