Fixed UI Admin
Admin Forum Pages - app/(application)/admin/forum/[id]/list-report-posting.tsx - app/(application)/admin/forum/posting.tsx - app/(application)/admin/forum/report-comment.tsx - app/(application)/admin/forum/report-posting.tsx Admin Forum Service - service/api-admin/api-admin-forum.ts Docs - docs/prompt-for-qwen-code.md New Admin Screens - screens/Admin/Forum/ ### No Issue
This commit is contained in:
@@ -1,283 +1,5 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import {
|
||||
ActionIcon,
|
||||
AlertDefaultSystem,
|
||||
BadgeCustom,
|
||||
BaseBox,
|
||||
CenterCustom,
|
||||
DrawerCustom,
|
||||
LoaderCustom,
|
||||
MenuDrawerDynamicGrid,
|
||||
StackCustom,
|
||||
TextCustom,
|
||||
ViewWrapper,
|
||||
} from "@/components";
|
||||
import { IconDot, IconView } from "@/components/_Icon/IconComponent";
|
||||
import { IconTrash } from "@/components/_Icon/IconTrash";
|
||||
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
|
||||
import { GridSpan_4_8 } from "@/components/_ShareComponent/GridSpan_4_8";
|
||||
import { GridSpan_NewComponent } from "@/components/_ShareComponent/GridSpan_NewComponent";
|
||||
import { MainColor } from "@/constants/color-palet";
|
||||
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
|
||||
import { useAuth } from "@/hooks/use-auth";
|
||||
import {
|
||||
apiAdminForumDeactivatePosting,
|
||||
apiAdminForumListReportPostingById,
|
||||
apiAdminForumPostingById,
|
||||
} from "@/service/api-admin/api-admin-forum";
|
||||
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||
import _ from "lodash";
|
||||
import { useCallback, useState } from "react";
|
||||
import { View } from "react-native";
|
||||
import { Divider } from "react-native-paper";
|
||||
import Toast from "react-native-toast-message";
|
||||
import { Admin_ScreenForumDetailReportPosting } from "@/screens/Admin/Forum/ScreenForumDetailReportPosting";
|
||||
|
||||
export default function AdminForumReportPosting() {
|
||||
const { user } = useAuth();
|
||||
const { id } = useLocalSearchParams();
|
||||
const [openDrawerPage, setOpenDrawerPage] = useState(false);
|
||||
const [openDrawerAction, setOpenDrawerAction] = useState(false);
|
||||
|
||||
const [data, setData] = useState<any | null>(null);
|
||||
const [listReport, setListReport] = useState<any[] | null>(null);
|
||||
const [loadListReport, setLoadListReport] = useState(false);
|
||||
const [selectedReport, setSelectedReport] = useState({
|
||||
id: "",
|
||||
username: "",
|
||||
kategori: "",
|
||||
keterangan: "",
|
||||
deskripsi: "",
|
||||
});
|
||||
|
||||
useFocusEffect(
|
||||
useCallback(() => {
|
||||
onLoadData();
|
||||
}, [id])
|
||||
);
|
||||
|
||||
const onLoadData = async () => {
|
||||
try {
|
||||
setLoadListReport(true);
|
||||
const response = await apiAdminForumPostingById({
|
||||
id: id as string,
|
||||
});
|
||||
|
||||
const responseReport = await apiAdminForumListReportPostingById({
|
||||
id: id as string,
|
||||
});
|
||||
|
||||
if (response.success) {
|
||||
setData(response.data);
|
||||
}
|
||||
|
||||
if (responseReport.success) {
|
||||
setListReport(responseReport.data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("[ERROR]", error);
|
||||
} finally {
|
||||
setLoadListReport(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<ViewWrapper
|
||||
headerComponent={
|
||||
<AdminBackButtonAntTitle
|
||||
title="Report Posting"
|
||||
rightComponent={
|
||||
<ActionIcon
|
||||
icon={<IconDot size={16} color={MainColor.darkblue} />}
|
||||
onPress={() => setOpenDrawerPage(true)}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<BaseBox>
|
||||
<StackCustom gap={"sm"}>
|
||||
<GridSpan_NewComponent
|
||||
text1={<TextCustom bold>Username</TextCustom>}
|
||||
text2={<TextCustom>{data?.Author?.username || "-"}</TextCustom>}
|
||||
/>
|
||||
|
||||
<GridSpan_NewComponent
|
||||
text1={<TextCustom bold>Status</TextCustom>}
|
||||
text2={
|
||||
data && data?.ForumMaster_StatusPosting?.status ? (
|
||||
<BadgeCustom
|
||||
color={
|
||||
data?.ForumMaster_StatusPosting?.status === "Open"
|
||||
? MainColor.green
|
||||
: MainColor.red
|
||||
}
|
||||
>
|
||||
{data?.ForumMaster_StatusPosting?.status === "Open"
|
||||
? "Open"
|
||||
: "Close"}
|
||||
</BadgeCustom>
|
||||
) : (
|
||||
<TextCustom>{"-"}</TextCustom>
|
||||
)
|
||||
}
|
||||
/>
|
||||
|
||||
<GridSpan_NewComponent
|
||||
text1={<TextCustom bold>Postingan</TextCustom>}
|
||||
text2={<TextCustom>{data?.diskusi || "-"}</TextCustom>}
|
||||
/>
|
||||
</StackCustom>
|
||||
</BaseBox>
|
||||
|
||||
<AdminComp_BoxTitle title="Daftar Report Posting" />
|
||||
<StackCustom gap={"sm"}>
|
||||
<GridSpan_NewComponent
|
||||
text1={
|
||||
<TextCustom bold align="center">
|
||||
Aksi
|
||||
</TextCustom>
|
||||
}
|
||||
text2={<TextCustom bold>Pelapor</TextCustom>}
|
||||
text3={<TextCustom bold>Kategori Report</TextCustom>}
|
||||
/>
|
||||
<Divider />
|
||||
{loadListReport ? (
|
||||
<LoaderCustom />
|
||||
) : _.isEmpty(listReport) ? (
|
||||
<TextCustom align="center" color={"gray"}>
|
||||
Belum ada report
|
||||
</TextCustom>
|
||||
) : (
|
||||
listReport?.map((item: any, index: number) => (
|
||||
<View key={index}>
|
||||
<GridSpan_NewComponent
|
||||
text1={
|
||||
<CenterCustom>
|
||||
<ActionIcon
|
||||
icon={
|
||||
<IconView size={ICON_SIZE_BUTTON} color="black" />
|
||||
}
|
||||
onPress={() => {
|
||||
setOpenDrawerAction(true);
|
||||
setSelectedReport({
|
||||
id: item?.id,
|
||||
username: item?.User?.username,
|
||||
kategori: item?.ForumMaster_KategoriReport?.title,
|
||||
keterangan:
|
||||
item?.ForumMaster_KategoriReport?.deskripsi,
|
||||
deskripsi: item?.deskripsi,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</CenterCustom>
|
||||
}
|
||||
text2={
|
||||
<TextCustom truncate>
|
||||
{item?.User?.username || "-"}
|
||||
</TextCustom>
|
||||
}
|
||||
text3={
|
||||
<TextCustom truncate={2}>
|
||||
{item?.ForumMaster_KategoriReport?.title || "-"}
|
||||
</TextCustom>
|
||||
}
|
||||
/>
|
||||
<Divider />
|
||||
</View>
|
||||
))
|
||||
)}
|
||||
</StackCustom>
|
||||
</ViewWrapper>
|
||||
|
||||
<DrawerCustom
|
||||
isVisible={openDrawerPage}
|
||||
closeDrawer={() => setOpenDrawerPage(false)}
|
||||
height={"auto"}
|
||||
>
|
||||
<MenuDrawerDynamicGrid
|
||||
data={[
|
||||
{
|
||||
icon: <IconTrash />,
|
||||
label: "Hapus Posting",
|
||||
value: "delete",
|
||||
path: "",
|
||||
color: MainColor.red,
|
||||
},
|
||||
]}
|
||||
onPressItem={(item) => {
|
||||
AlertDefaultSystem({
|
||||
title: "Hapus Posting",
|
||||
message: "Apakah Anda yakin ingin menghapus posting ini?",
|
||||
textLeft: "Batal",
|
||||
textRight: "Hapus",
|
||||
onPressRight: async () => {
|
||||
const response = await apiAdminForumDeactivatePosting({
|
||||
id: id as string,
|
||||
data: {
|
||||
senderId: user?.id as string,
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.success) {
|
||||
Toast.show({
|
||||
type: "error",
|
||||
text1: "Posting gagal dihapus",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
setOpenDrawerPage(false);
|
||||
Toast.show({
|
||||
type: "success",
|
||||
text1: "Posting berhasil dihapus",
|
||||
});
|
||||
router.back();
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</DrawerCustom>
|
||||
|
||||
<DrawerCustom
|
||||
isVisible={openDrawerAction}
|
||||
closeDrawer={() => setOpenDrawerAction(false)}
|
||||
height={"auto"}
|
||||
>
|
||||
<StackCustom>
|
||||
<GridSpan_4_8
|
||||
label={<TextCustom bold>Pelapor</TextCustom>}
|
||||
value={<TextCustom>{selectedReport?.username || "-"}</TextCustom>}
|
||||
/>
|
||||
|
||||
{selectedReport?.kategori && (
|
||||
<>
|
||||
<GridSpan_4_8
|
||||
label={<TextCustom bold>Kategori Report</TextCustom>}
|
||||
value={
|
||||
<TextCustom>{selectedReport?.kategori || "-"}</TextCustom>
|
||||
}
|
||||
/>
|
||||
<GridSpan_4_8
|
||||
label={<TextCustom bold>Keterangan</TextCustom>}
|
||||
value={
|
||||
<TextCustom>{selectedReport?.keterangan || "-"}</TextCustom>
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
{selectedReport?.deskripsi && (
|
||||
<GridSpan_4_8
|
||||
label={<TextCustom bold>Deskripsi</TextCustom>}
|
||||
value={
|
||||
<TextCustom>{selectedReport?.deskripsi || "-"}</TextCustom>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</StackCustom>
|
||||
</DrawerCustom>
|
||||
</>
|
||||
);
|
||||
export default function AdminForumDetailReportPosting() {
|
||||
return <Admin_ScreenForumDetailReportPosting />;
|
||||
}
|
||||
|
||||
@@ -1,121 +1,5 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import {
|
||||
ClickableCustom,
|
||||
LoaderCustom,
|
||||
SearchInput,
|
||||
Spacing,
|
||||
StackCustom,
|
||||
TextCustom,
|
||||
ViewWrapper,
|
||||
} from "@/components";
|
||||
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
|
||||
import AdminTitlePage from "@/components/_ShareComponent/Admin/TitlePage";
|
||||
import { GridSpan_4_8 } from "@/components/_ShareComponent/GridSpan_4_8";
|
||||
import { GridSpan_NewComponent } from "@/components/_ShareComponent/GridSpan_NewComponent";
|
||||
import { apiAdminForum } from "@/service/api-admin/api-admin-forum";
|
||||
import { router, useFocusEffect } from "expo-router";
|
||||
import _ from "lodash";
|
||||
import { useCallback, useState } from "react";
|
||||
import { View } from "react-native";
|
||||
import { Divider } from "react-native-paper";
|
||||
import { Admin_ScreenForumPosting } from "@/screens/Admin/Forum/ScreenForumPosting";
|
||||
|
||||
export default function AdminForumPosting() {
|
||||
const [list, setList] = useState<any | null>(null);
|
||||
const [loadList, setLoadList] = useState(false);
|
||||
const [search, setSearch] = useState("");
|
||||
|
||||
useFocusEffect(
|
||||
useCallback(() => {
|
||||
handlerLoadList();
|
||||
}, [search])
|
||||
);
|
||||
|
||||
const handlerLoadList = async () => {
|
||||
try {
|
||||
setLoadList(true);
|
||||
const response = await apiAdminForum({
|
||||
category: "posting",
|
||||
search: search,
|
||||
});
|
||||
|
||||
console.log("DATA", JSON.stringify(response, null, 2));
|
||||
|
||||
if (response.success) {
|
||||
setList(response.data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("[ERROR]", error);
|
||||
} finally {
|
||||
setLoadList(false);
|
||||
}
|
||||
};
|
||||
|
||||
const rightComponent = (
|
||||
<SearchInput
|
||||
containerStyle={{ width: "100%", marginBottom: 0 }}
|
||||
placeholder="Cari postingan"
|
||||
value={search}
|
||||
onChangeText={setSearch}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ViewWrapper headerComponent={<AdminTitlePage title="Forum" />}>
|
||||
<AdminComp_BoxTitle title={"Posting"} rightComponent={rightComponent} />
|
||||
<GridSpan_NewComponent
|
||||
text1={<TextCustom bold truncate>Username</TextCustom>}
|
||||
text2={<TextCustom bold truncate> Postingan</TextCustom>}
|
||||
text3={<TextCustom bold align="center" truncate> Report Posting</TextCustom>}
|
||||
text4={<TextCustom bold align="center" truncate> Komentar</TextCustom>}
|
||||
/>
|
||||
<Divider />
|
||||
<Spacing />
|
||||
<StackCustom>
|
||||
{loadList ? (
|
||||
<LoaderCustom />
|
||||
) : _.isEmpty(list) ? (
|
||||
<TextCustom align="center" color="gray">
|
||||
Belum ada data
|
||||
</TextCustom>
|
||||
) : (
|
||||
list?.map((item: any, index: number) => (
|
||||
<View key={index}>
|
||||
<ClickableCustom
|
||||
onPress={() => {
|
||||
router.push(`/admin/forum/${item.id}`);
|
||||
}}
|
||||
>
|
||||
<GridSpan_NewComponent
|
||||
text1={
|
||||
<TextCustom truncate={1}>
|
||||
{item?.Author?.username || "-"}
|
||||
</TextCustom>
|
||||
}
|
||||
text2={
|
||||
<TextCustom truncate>
|
||||
{item?.diskusi || "-"}
|
||||
</TextCustom>
|
||||
}
|
||||
text3={
|
||||
<TextCustom align="center" truncate={2}>
|
||||
{item?.reportPosting || "-"}
|
||||
</TextCustom>
|
||||
}
|
||||
text4={
|
||||
<TextCustom align="center" truncate={2}>
|
||||
{item?.komentar || "-"}
|
||||
</TextCustom>
|
||||
}
|
||||
/>
|
||||
|
||||
</ClickableCustom>
|
||||
<Divider />
|
||||
</View>
|
||||
))
|
||||
)}
|
||||
</StackCustom>
|
||||
</ViewWrapper>
|
||||
</>
|
||||
);
|
||||
return <Admin_ScreenForumPosting />;
|
||||
}
|
||||
|
||||
@@ -1,137 +1,5 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import {
|
||||
ActionIcon,
|
||||
ClickableCustom,
|
||||
LoaderCustom,
|
||||
SearchInput,
|
||||
Spacing,
|
||||
StackCustom,
|
||||
TextCustom,
|
||||
ViewWrapper,
|
||||
} from "@/components";
|
||||
import { IconView } from "@/components/_Icon/IconComponent";
|
||||
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
|
||||
import AdminTitleTable from "@/components/_ShareComponent/Admin/TableTitle";
|
||||
import AdminTableValue from "@/components/_ShareComponent/Admin/TableValue";
|
||||
import AdminTitlePage from "@/components/_ShareComponent/Admin/TitlePage";
|
||||
import { GridSpan_NewComponent } from "@/components/_ShareComponent/GridSpan_NewComponent";
|
||||
import { MainColor } from "@/constants/color-palet";
|
||||
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
|
||||
import { apiAdminForum } from "@/service/api-admin/api-admin-forum";
|
||||
import { router, useFocusEffect } from "expo-router";
|
||||
import _ from "lodash";
|
||||
import { useCallback, useState } from "react";
|
||||
import { View } from "react-native";
|
||||
import { Divider } from "react-native-paper";
|
||||
import { Admin_ScreenForumReportComment } from "@/screens/Admin/Forum/ScreenForumReportComment";
|
||||
|
||||
export default function AdminForumReportComment() {
|
||||
const [listData, setListData] = useState<any[] | null>(null);
|
||||
const [loadList, setLoadList] = useState<boolean>(false);
|
||||
const [search, setSearch] = useState<string>("");
|
||||
|
||||
useFocusEffect(
|
||||
useCallback(() => {
|
||||
onLoadData();
|
||||
}, [search])
|
||||
);
|
||||
|
||||
const onLoadData = async () => {
|
||||
try {
|
||||
setLoadList(true);
|
||||
|
||||
const response = await apiAdminForum({
|
||||
category: "report_comment",
|
||||
search: search,
|
||||
});
|
||||
|
||||
if (response.success) {
|
||||
setListData(response.data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("[ERROR]", error);
|
||||
} finally {
|
||||
setLoadList(false);
|
||||
}
|
||||
};
|
||||
|
||||
const rightComponent = (
|
||||
<SearchInput
|
||||
containerStyle={{ width: "100%", marginBottom: 0 }}
|
||||
placeholder="Cari Komentar"
|
||||
value={search}
|
||||
onChangeText={setSearch}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ViewWrapper headerComponent={<AdminTitlePage title="Forum" />}>
|
||||
<AdminComp_BoxTitle
|
||||
title="Report Komentar"
|
||||
rightComponent={rightComponent}
|
||||
/>
|
||||
|
||||
<GridSpan_NewComponent
|
||||
text1={
|
||||
<TextCustom bold truncate>
|
||||
Pelapor
|
||||
</TextCustom>
|
||||
}
|
||||
text2={
|
||||
<TextCustom bold truncate>
|
||||
Komentar
|
||||
</TextCustom>
|
||||
}
|
||||
text3={
|
||||
<TextCustom bold truncate>
|
||||
Jenis Laporan
|
||||
</TextCustom>
|
||||
}
|
||||
/>
|
||||
<Divider />
|
||||
<Spacing />
|
||||
<StackCustom gap={"lg"}>
|
||||
{loadList ? (
|
||||
<LoaderCustom />
|
||||
) : _.isEmpty(listData) ? (
|
||||
<TextCustom align="center" color="gray">
|
||||
Belum ada data
|
||||
</TextCustom>
|
||||
) : (
|
||||
listData?.map((item: any, index: number) => (
|
||||
<View key={index}>
|
||||
<ClickableCustom
|
||||
onPress={() => {
|
||||
router.push(
|
||||
`/admin/forum/${item?.Forum_Komentar?.id}/list-report-comment`
|
||||
);
|
||||
}}
|
||||
>
|
||||
<GridSpan_NewComponent
|
||||
text1={
|
||||
<TextCustom truncate={1}>
|
||||
{item?.User?.username || "-"}
|
||||
</TextCustom>
|
||||
}
|
||||
text2={
|
||||
<TextCustom truncate={2}>
|
||||
{item?.Forum_Komentar?.komentar || "-"}
|
||||
</TextCustom>
|
||||
}
|
||||
text3={
|
||||
<TextCustom truncate={2}>
|
||||
{item?.ForumMaster_KategoriReport?.title || "-"}
|
||||
</TextCustom>
|
||||
}
|
||||
/>
|
||||
</ClickableCustom>
|
||||
<Spacing />
|
||||
<Divider />
|
||||
</View>
|
||||
))
|
||||
)}
|
||||
</StackCustom>
|
||||
</ViewWrapper>
|
||||
</>
|
||||
);
|
||||
return <Admin_ScreenForumReportComment />;
|
||||
}
|
||||
|
||||
@@ -1,124 +1,5 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import {
|
||||
ActionIcon,
|
||||
ClickableCustom,
|
||||
Divider,
|
||||
LoaderCustom,
|
||||
SearchInput,
|
||||
StackCustom,
|
||||
TextCustom,
|
||||
ViewWrapper,
|
||||
} from "@/components";
|
||||
import { IconView } from "@/components/_Icon/IconComponent";
|
||||
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
|
||||
import AdminTitleTable from "@/components/_ShareComponent/Admin/TableTitle";
|
||||
import AdminTableValue from "@/components/_ShareComponent/Admin/TableValue";
|
||||
import AdminTitlePage from "@/components/_ShareComponent/Admin/TitlePage";
|
||||
import { GridSpan_NewComponent } from "@/components/_ShareComponent/GridSpan_NewComponent";
|
||||
import { MainColor } from "@/constants/color-palet";
|
||||
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
|
||||
import { apiAdminForum } from "@/service/api-admin/api-admin-forum";
|
||||
import { router, useFocusEffect } from "expo-router";
|
||||
import _ from "lodash";
|
||||
import { useCallback, useState } from "react";
|
||||
import { View } from "react-native";
|
||||
import { Admin_ScreenForumReportPosting } from "@/screens/Admin/Forum/ScreenForumReportPosting";
|
||||
|
||||
export default function AdminForumReportPosting() {
|
||||
const [listData, setListData] = useState<any[] | null>(null);
|
||||
const [loadList, setLoadList] = useState<boolean>(false);
|
||||
const [search, setSearch] = useState<string>("");
|
||||
|
||||
useFocusEffect(
|
||||
useCallback(() => {
|
||||
onLoadData();
|
||||
}, [search])
|
||||
);
|
||||
|
||||
const onLoadData = async () => {
|
||||
try {
|
||||
setLoadList(true);
|
||||
|
||||
const response = await apiAdminForum({
|
||||
category: "report_posting",
|
||||
search: search,
|
||||
});
|
||||
|
||||
if (response.success) {
|
||||
setListData(response.data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("[ERROR]", error);
|
||||
} finally {
|
||||
setLoadList(false);
|
||||
}
|
||||
};
|
||||
|
||||
const rightComponent = (
|
||||
<SearchInput
|
||||
containerStyle={{ width: "100%", marginBottom: 0 }}
|
||||
placeholder="Cari Postingan"
|
||||
value={search}
|
||||
onChangeText={setSearch}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ViewWrapper headerComponent={<AdminTitlePage title="Forum" />}>
|
||||
<AdminComp_BoxTitle
|
||||
title="Report Posting"
|
||||
rightComponent={rightComponent}
|
||||
/>
|
||||
|
||||
<GridSpan_NewComponent
|
||||
text1={
|
||||
<TextCustom bold truncate>
|
||||
Pelapor
|
||||
</TextCustom>
|
||||
}
|
||||
text2={
|
||||
<TextCustom bold truncate>
|
||||
Postingan
|
||||
</TextCustom>
|
||||
}
|
||||
/>
|
||||
<Divider />
|
||||
<StackCustom>
|
||||
{loadList ? (
|
||||
<LoaderCustom />
|
||||
) : _.isEmpty(listData) ? (
|
||||
<TextCustom align="center" color="gray">
|
||||
Belum ada data
|
||||
</TextCustom>
|
||||
) : (
|
||||
listData?.map((item: any, index: number) => (
|
||||
<View key={index}>
|
||||
<ClickableCustom
|
||||
onPress={() => {
|
||||
router.push(
|
||||
`/admin/forum/${item?.Forum_Posting?.id}/list-report-posting`
|
||||
);
|
||||
}}
|
||||
>
|
||||
<GridSpan_NewComponent
|
||||
text1={
|
||||
<TextCustom truncate={1}>
|
||||
{item?.User?.username || "-"}
|
||||
</TextCustom>
|
||||
}
|
||||
text2={
|
||||
<TextCustom truncate={1}>
|
||||
{item?.Forum_Posting?.diskusi || "-"}
|
||||
</TextCustom>
|
||||
}
|
||||
/>
|
||||
</ClickableCustom>
|
||||
<Divider />
|
||||
</View>
|
||||
))
|
||||
)}
|
||||
</StackCustom>
|
||||
</ViewWrapper>
|
||||
</>
|
||||
);
|
||||
return <Admin_ScreenForumReportPosting />;
|
||||
}
|
||||
|
||||
@@ -55,10 +55,10 @@ Component yang digunakan: components/_ShareComponent/NewWrapper.tsx
|
||||
|
||||
<!-- START Prompt Admin Refactoring -->
|
||||
<!-- Pindah kode ke Screen Component -->
|
||||
File source: app/(application)/admin/investment/[id]/list-of-investor.tsx
|
||||
Folder tujuan: screens/Admin/Investment
|
||||
Nama file utama: ScreenInvestmentListOfInvestor.tsx
|
||||
Nama function utama: Admin_ScreenInvestmentListOfInvestor
|
||||
File source: app/(application)/admin/forum/[id]/list-report-posting.tsx
|
||||
Folder tujuan: screens/Admin/Forum
|
||||
Nama file utama: ScreenForumDetailReportPosting.tsx
|
||||
Nama function utama: Admin_ScreenForumDetailReportPosting
|
||||
File komponen wrapper: components/_ShareComponent/NewWrapper.tsx
|
||||
|
||||
Buat file baru pada "Folder tujuan" dengan nama "Nama file utama" dan ubah nama function menjadi "Nama function utama" kemudian clean code, import dan panggil function tersebut pada file "File source"
|
||||
@@ -66,8 +66,8 @@ Analisa juga file "Nama file utama" , jika belum menggunakan NewWrapper pada fil
|
||||
|
||||
|
||||
<!-- Penerapan Pagination -->
|
||||
Function fecth: apiAdminInvestmentListOfInvestor
|
||||
File function fetch: service/api-admin/api-admin-investment.ts
|
||||
Function fecth: apiAdminForumListReportPostingById
|
||||
File function fetch: service/api-admin/api-admin-forum.ts
|
||||
|
||||
Terapkan pagination pada file "Nama file utama"
|
||||
Komponen pagination yang digunaka berada pada file hooks/use-pagination.tsx dan helpers/paginationHelpers.tsx
|
||||
@@ -80,11 +80,14 @@ Gunakan bahasa indonesia pada cli agar saya mudah membacanya.
|
||||
<!-- END Prompt Admin Refactoring -->
|
||||
|
||||
<!-- Additional -->
|
||||
File refrensi: screens/Admin/Donation/ScreenDonationListOfDonatur.tsx
|
||||
File refrensi: screens/Admin/Forum/ScreenForumReportPosting.tsx
|
||||
Anda bisa menggunakan refrensi dari "File refrensi" jika butuh pemahaman dengan tipe fitur yang hampir sama
|
||||
|
||||
Untuk refrensi tampilan Box bisa anda gunakan dari file: screens/Admin/Donation/BoxDonationListOfDonatur.tsx dan buatkan komponen yang mirip untuk list of donatur dengan nama file: BoxDonationListOfInvestor.tsx
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- Use Prompt Now -->
|
||||
Terapkan NewWrapper pada file: screens/Admin/App-Information/InformationBankSection.tsx
|
||||
Component yang digunakan: components/_ShareComponent/NewWrapper.tsx
|
||||
|
||||
339
screens/Admin/Forum/ScreenForumDetailReportPosting.tsx
Normal file
339
screens/Admin/Forum/ScreenForumDetailReportPosting.tsx
Normal file
@@ -0,0 +1,339 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import {
|
||||
ActionIcon,
|
||||
AlertDefaultSystem,
|
||||
BadgeCustom,
|
||||
BaseBox,
|
||||
CenterCustom,
|
||||
DrawerCustom,
|
||||
MenuDrawerDynamicGrid,
|
||||
StackCustom,
|
||||
TextCustom,
|
||||
} from "@/components";
|
||||
import { IconDot, IconView } from "@/components/_Icon/IconComponent";
|
||||
import { IconTrash } from "@/components/_Icon/IconTrash";
|
||||
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
|
||||
import { GridSpan_4_8 } from "@/components/_ShareComponent/GridSpan_4_8";
|
||||
import { GridSpan_NewComponent } from "@/components/_ShareComponent/GridSpan_NewComponent";
|
||||
import NewWrapper from "@/components/_ShareComponent/NewWrapper";
|
||||
import { MainColor } from "@/constants/color-palet";
|
||||
import {
|
||||
ICON_SIZE_BUTTON,
|
||||
PAGINATION_DEFAULT_TAKE,
|
||||
} from "@/constants/constans-value";
|
||||
import { createPaginationComponents } from "@/helpers/paginationHelpers";
|
||||
import { usePagination } from "@/hooks/use-pagination";
|
||||
import { useAuth } from "@/hooks/use-auth";
|
||||
import {
|
||||
apiAdminForumDeactivatePosting,
|
||||
apiAdminForumListReportPostingById,
|
||||
apiAdminForumPostingById,
|
||||
} from "@/service/api-admin/api-admin-forum";
|
||||
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||
import _ from "lodash";
|
||||
import { useCallback, useMemo, useState } from "react";
|
||||
import { RefreshControl, View } from "react-native";
|
||||
import { Divider } from "react-native-paper";
|
||||
import Toast from "react-native-toast-message";
|
||||
|
||||
export function Admin_ScreenForumDetailReportPosting() {
|
||||
const { user } = useAuth();
|
||||
const { id } = useLocalSearchParams();
|
||||
const [openDrawerPage, setOpenDrawerPage] = useState(false);
|
||||
const [openDrawerAction, setOpenDrawerAction] = useState(false);
|
||||
const [data, setData] = useState<any | null>(null);
|
||||
const [selectedReport, setSelectedReport] = useState({
|
||||
id: "",
|
||||
username: "",
|
||||
kategori: "",
|
||||
keterangan: "",
|
||||
deskripsi: "",
|
||||
});
|
||||
|
||||
// Load data postingan saat screen fokus
|
||||
useFocusEffect(
|
||||
useCallback(() => {
|
||||
onLoadDataPosting();
|
||||
}, [id])
|
||||
);
|
||||
|
||||
// Pagination untuk list report
|
||||
const pagination = usePagination({
|
||||
fetchFunction: async (page, searchQuery) => {
|
||||
const response = await apiAdminForumListReportPostingById({
|
||||
id: id as string,
|
||||
page: String(page),
|
||||
});
|
||||
|
||||
if (response.success) {
|
||||
return { data: response.data };
|
||||
}
|
||||
return { data: [] };
|
||||
},
|
||||
pageSize: PAGINATION_DEFAULT_TAKE,
|
||||
dependencies: [id],
|
||||
});
|
||||
|
||||
const onLoadDataPosting = async () => {
|
||||
try {
|
||||
const response = await apiAdminForumPostingById({
|
||||
id: id as string,
|
||||
});
|
||||
|
||||
if (response.success) {
|
||||
setData(response.data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("[ERROR]", error);
|
||||
}
|
||||
};
|
||||
|
||||
// Render item untuk daftar report
|
||||
const renderItem = useCallback(
|
||||
({ item }: { item: any }) => (
|
||||
<View>
|
||||
<GridSpan_NewComponent
|
||||
text1={
|
||||
<CenterCustom>
|
||||
<ActionIcon
|
||||
icon={<IconView size={ICON_SIZE_BUTTON} color="black" />}
|
||||
onPress={() => {
|
||||
setOpenDrawerAction(true);
|
||||
setSelectedReport({
|
||||
id: item?.id,
|
||||
username: item?.User?.username,
|
||||
kategori: item?.ForumMaster_KategoriReport?.title,
|
||||
keterangan: item?.ForumMaster_KategoriReport?.deskripsi,
|
||||
deskripsi: item?.deskripsi,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</CenterCustom>
|
||||
}
|
||||
text2={
|
||||
<TextCustom truncate>
|
||||
{item?.User?.username || "-"}
|
||||
</TextCustom>
|
||||
}
|
||||
text3={
|
||||
<TextCustom truncate={2}>
|
||||
{item?.ForumMaster_KategoriReport?.title || "-"}
|
||||
</TextCustom>
|
||||
}
|
||||
/>
|
||||
<Divider />
|
||||
</View>
|
||||
),
|
||||
[]
|
||||
);
|
||||
|
||||
// Header component dengan detail postingan
|
||||
const headerComponent = useMemo(
|
||||
() => (
|
||||
<AdminBackButtonAntTitle
|
||||
title="Detail Report Posting"
|
||||
rightComponent={
|
||||
<ActionIcon
|
||||
icon={<IconDot size={16} color={MainColor.darkblue} />}
|
||||
onPress={() => setOpenDrawerPage(true)}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
),
|
||||
[]
|
||||
);
|
||||
|
||||
// Detail postingan component
|
||||
const postingDetailComponent = useMemo(
|
||||
() => (
|
||||
<BaseBox>
|
||||
<StackCustom gap={"sm"}>
|
||||
<GridSpan_NewComponent
|
||||
text1={<TextCustom bold>Username</TextCustom>}
|
||||
text2={<TextCustom>{data?.Author?.username || "-"}</TextCustom>}
|
||||
/>
|
||||
|
||||
<GridSpan_NewComponent
|
||||
text1={<TextCustom bold>Status</TextCustom>}
|
||||
text2={
|
||||
data && data?.ForumMaster_StatusPosting?.status ? (
|
||||
<BadgeCustom
|
||||
color={
|
||||
data?.ForumMaster_StatusPosting?.status === "Open"
|
||||
? MainColor.green
|
||||
: MainColor.red
|
||||
}
|
||||
>
|
||||
{data?.ForumMaster_StatusPosting?.status === "Open"
|
||||
? "Open"
|
||||
: "Close"}
|
||||
</BadgeCustom>
|
||||
) : (
|
||||
<TextCustom>{"-"}</TextCustom>
|
||||
)
|
||||
}
|
||||
/>
|
||||
|
||||
<GridSpan_NewComponent
|
||||
text1={<TextCustom bold>Postingan</TextCustom>}
|
||||
text2={<TextCustom>{data?.diskusi || "-"}</TextCustom>}
|
||||
/>
|
||||
</StackCustom>
|
||||
</BaseBox>
|
||||
),
|
||||
[data]
|
||||
);
|
||||
|
||||
// Box title untuk daftar report
|
||||
const reportListTitleComponent = useMemo(
|
||||
() => <AdminComp_BoxTitle title="Daftar Report Posting" />,
|
||||
[]
|
||||
);
|
||||
|
||||
// Header untuk kolom daftar report
|
||||
const reportListHeaderComponent = useMemo(
|
||||
() => (
|
||||
<StackCustom gap={"sm"}>
|
||||
{postingDetailComponent}
|
||||
{reportListTitleComponent}
|
||||
<GridSpan_NewComponent
|
||||
text1={
|
||||
<TextCustom bold align="center">
|
||||
Aksi
|
||||
</TextCustom>
|
||||
}
|
||||
text2={<TextCustom bold>Pelapor</TextCustom>}
|
||||
text3={<TextCustom bold>Kategori Report</TextCustom>}
|
||||
/>
|
||||
<Divider />
|
||||
</StackCustom>
|
||||
),
|
||||
[postingDetailComponent, reportListTitleComponent]
|
||||
);
|
||||
|
||||
// Buat komponen-komponen pagination
|
||||
const { ListEmptyComponent, ListFooterComponent } =
|
||||
createPaginationComponents({
|
||||
loading: pagination.loading,
|
||||
refreshing: pagination.refreshing,
|
||||
listData: pagination.listData,
|
||||
emptyMessage: "Belum ada report",
|
||||
emptySearchMessage: "Tidak ada hasil pencarian",
|
||||
isInitialLoad: pagination.isInitialLoad,
|
||||
skeletonCount: PAGINATION_DEFAULT_TAKE,
|
||||
skeletonHeight: 100,
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<NewWrapper
|
||||
listData={pagination.listData}
|
||||
renderItem={renderItem}
|
||||
headerComponent={headerComponent}
|
||||
ListHeaderComponent={reportListHeaderComponent}
|
||||
ListEmptyComponent={ListEmptyComponent}
|
||||
ListFooterComponent={ListFooterComponent}
|
||||
onEndReached={pagination.loadMore}
|
||||
refreshControl={
|
||||
<RefreshControl
|
||||
refreshing={pagination.refreshing}
|
||||
onRefresh={pagination.onRefresh}
|
||||
tintColor={MainColor.yellow}
|
||||
colors={[MainColor.yellow]}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
||||
{/* Drawer untuk menu halaman (hapus posting) */}
|
||||
<DrawerCustom
|
||||
isVisible={openDrawerPage}
|
||||
closeDrawer={() => setOpenDrawerPage(false)}
|
||||
height={"auto"}
|
||||
>
|
||||
<MenuDrawerDynamicGrid
|
||||
data={[
|
||||
{
|
||||
icon: <IconTrash />,
|
||||
label: "Hapus Posting",
|
||||
value: "delete",
|
||||
path: "",
|
||||
color: MainColor.red,
|
||||
},
|
||||
]}
|
||||
onPressItem={(item) => {
|
||||
AlertDefaultSystem({
|
||||
title: "Hapus Posting",
|
||||
message: "Apakah Anda yakin ingin menghapus posting ini?",
|
||||
textLeft: "Batal",
|
||||
textRight: "Hapus",
|
||||
onPressRight: async () => {
|
||||
const response = await apiAdminForumDeactivatePosting({
|
||||
id: id as string,
|
||||
data: {
|
||||
senderId: user?.id as string,
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.success) {
|
||||
Toast.show({
|
||||
type: "error",
|
||||
text1: "Posting gagal dihapus",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
setOpenDrawerPage(false);
|
||||
Toast.show({
|
||||
type: "success",
|
||||
text1: "Posting berhasil dihapus",
|
||||
});
|
||||
router.back();
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</DrawerCustom>
|
||||
|
||||
{/* Drawer untuk detail report */}
|
||||
<DrawerCustom
|
||||
isVisible={openDrawerAction}
|
||||
closeDrawer={() => setOpenDrawerAction(false)}
|
||||
height={"auto"}
|
||||
>
|
||||
<StackCustom>
|
||||
<GridSpan_4_8
|
||||
label={<TextCustom bold>Pelapor</TextCustom>}
|
||||
value={<TextCustom>{selectedReport?.username || "-"}</TextCustom>}
|
||||
/>
|
||||
|
||||
{selectedReport?.kategori && (
|
||||
<>
|
||||
<GridSpan_4_8
|
||||
label={<TextCustom bold>Kategori Report</TextCustom>}
|
||||
value={
|
||||
<TextCustom>{selectedReport?.kategori || "-"}</TextCustom>
|
||||
}
|
||||
/>
|
||||
<GridSpan_4_8
|
||||
label={<TextCustom bold>Keterangan</TextCustom>}
|
||||
value={
|
||||
<TextCustom>{selectedReport?.keterangan || "-"}</TextCustom>
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
{selectedReport?.deskripsi && (
|
||||
<GridSpan_4_8
|
||||
label={<TextCustom bold>Deskripsi</TextCustom>}
|
||||
value={
|
||||
<TextCustom>{selectedReport?.deskripsi || "-"}</TextCustom>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</StackCustom>
|
||||
</DrawerCustom>
|
||||
</>
|
||||
);
|
||||
}
|
||||
133
screens/Admin/Forum/ScreenForumPosting.tsx
Normal file
133
screens/Admin/Forum/ScreenForumPosting.tsx
Normal file
@@ -0,0 +1,133 @@
|
||||
import {
|
||||
SearchInput, StackCustom,
|
||||
TextCustom
|
||||
} from "@/components";
|
||||
import AdminBasicBox from "@/components/_ShareComponent/Admin/AdminBasicBox";
|
||||
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
|
||||
import { GridSpan_4_8 } from "@/components/_ShareComponent/GridSpan_4_8";
|
||||
import NewWrapper from "@/components/_ShareComponent/NewWrapper";
|
||||
import { MainColor } from "@/constants/color-palet";
|
||||
import { PAGINATION_DEFAULT_TAKE } from "@/constants/constans-value";
|
||||
import { createPaginationComponents } from "@/helpers/paginationHelpers";
|
||||
import { usePagination } from "@/hooks/use-pagination";
|
||||
import { apiAdminForum } from "@/service/api-admin/api-admin-forum";
|
||||
import { router } from "expo-router";
|
||||
import { useCallback, useMemo, useState } from "react";
|
||||
import { RefreshControl, View } from "react-native";
|
||||
import { Divider } from "react-native-paper";
|
||||
|
||||
export function Admin_ScreenForumPosting() {
|
||||
const [search, setSearch] = useState("");
|
||||
|
||||
// Gunakan hook pagination
|
||||
const pagination = usePagination({
|
||||
fetchFunction: async (page, searchQuery) => {
|
||||
const response = await apiAdminForum({
|
||||
category: "posting",
|
||||
search: searchQuery || "",
|
||||
page: String(page),
|
||||
});
|
||||
|
||||
if (response.success) {
|
||||
return { data: response.data };
|
||||
} else {
|
||||
return { data: [] };
|
||||
}
|
||||
},
|
||||
pageSize: PAGINATION_DEFAULT_TAKE,
|
||||
searchQuery: search,
|
||||
dependencies: [],
|
||||
});
|
||||
|
||||
// Komponen search input
|
||||
const searchComponent = useMemo(
|
||||
() => (
|
||||
<SearchInput
|
||||
containerStyle={{ width: "100%", marginBottom: 0 }}
|
||||
placeholder="Cari postingan"
|
||||
value={search}
|
||||
onChangeText={setSearch}
|
||||
/>
|
||||
),
|
||||
[search],
|
||||
);
|
||||
|
||||
// Header component
|
||||
const headerComponent = useMemo(
|
||||
() => (
|
||||
<AdminComp_BoxTitle
|
||||
title={"Forum Posting"}
|
||||
rightComponent={searchComponent}
|
||||
/>
|
||||
),
|
||||
[searchComponent],
|
||||
);
|
||||
|
||||
// Render item untuk daftar posting
|
||||
const renderItem = useCallback(
|
||||
({ item, index }: { item: any; index: number }) => (
|
||||
<AdminBasicBox
|
||||
style={{ marginHorizontal: 5, marginVertical: 5 }}
|
||||
onPress={() => {
|
||||
router.push(`/admin/forum/${item.id}`);
|
||||
}}
|
||||
>
|
||||
<StackCustom gap={0}>
|
||||
<View style={{ paddingBlock: 8 }}>
|
||||
<TextCustom size={"large"} bold truncate={2}>
|
||||
{item?.diskusi || "-"}
|
||||
</TextCustom>
|
||||
</View>
|
||||
<Divider />
|
||||
<GridSpan_4_8
|
||||
label={<TextCustom>Komentar</TextCustom>}
|
||||
value={
|
||||
<TextCustom truncate={1}>{item?.komentar || "-"}</TextCustom>
|
||||
}
|
||||
/>
|
||||
<GridSpan_4_8
|
||||
label={<TextCustom>Report</TextCustom>}
|
||||
value={
|
||||
<TextCustom truncate={1}>{item?.reportPosting || "-"}</TextCustom>
|
||||
}
|
||||
/>
|
||||
</StackCustom>
|
||||
</AdminBasicBox>
|
||||
),
|
||||
[],
|
||||
);
|
||||
|
||||
// Buat komponen-komponen pagination
|
||||
const { ListEmptyComponent, ListFooterComponent } =
|
||||
createPaginationComponents({
|
||||
loading: pagination.loading,
|
||||
refreshing: pagination.refreshing,
|
||||
listData: pagination.listData,
|
||||
searchQuery: search,
|
||||
emptyMessage: "Belum ada data posting",
|
||||
emptySearchMessage: "Tidak ada hasil pencarian",
|
||||
isInitialLoad: pagination.isInitialLoad,
|
||||
skeletonCount: PAGINATION_DEFAULT_TAKE,
|
||||
skeletonHeight: 100,
|
||||
});
|
||||
|
||||
return (
|
||||
<NewWrapper
|
||||
listData={pagination.listData}
|
||||
renderItem={renderItem}
|
||||
keyExtractor={(item: any) => item.id?.toString() || `fallback-${item.id}`}
|
||||
headerComponent={headerComponent}
|
||||
ListEmptyComponent={ListEmptyComponent}
|
||||
ListFooterComponent={ListFooterComponent}
|
||||
onEndReached={pagination.loadMore}
|
||||
refreshControl={
|
||||
<RefreshControl
|
||||
refreshing={pagination.refreshing}
|
||||
onRefresh={pagination.onRefresh}
|
||||
tintColor={MainColor.yellow}
|
||||
colors={[MainColor.yellow]}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
156
screens/Admin/Forum/ScreenForumReportComment.tsx
Normal file
156
screens/Admin/Forum/ScreenForumReportComment.tsx
Normal file
@@ -0,0 +1,156 @@
|
||||
import { SearchInput, StackCustom, TextCustom } from "@/components";
|
||||
import AdminBasicBox from "@/components/_ShareComponent/Admin/AdminBasicBox";
|
||||
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
|
||||
import { GridSpan_4_8 } from "@/components/_ShareComponent/GridSpan_4_8";
|
||||
import NewWrapper from "@/components/_ShareComponent/NewWrapper";
|
||||
import { PAGINATION_DEFAULT_TAKE } from "@/constants/constans-value";
|
||||
import { createPaginationComponents } from "@/helpers/paginationHelpers";
|
||||
import { usePagination } from "@/hooks/use-pagination";
|
||||
import { apiAdminForum } from "@/service/api-admin/api-admin-forum";
|
||||
import { router } from "expo-router";
|
||||
import { useCallback, useMemo, useState } from "react";
|
||||
import { RefreshControl } from "react-native";
|
||||
import { Divider } from "react-native-paper";
|
||||
|
||||
export function Admin_ScreenForumReportComment() {
|
||||
const [search, setSearch] = useState("");
|
||||
|
||||
// Gunakan hook pagination
|
||||
const pagination = usePagination({
|
||||
fetchFunction: async (page, searchQuery) => {
|
||||
const response = await apiAdminForum({
|
||||
category: "report_comment",
|
||||
search: searchQuery || "",
|
||||
page: String(page),
|
||||
});
|
||||
|
||||
if (response.success) {
|
||||
console.log("CEK", JSON.stringify(response.data, null, 2));
|
||||
return { data: response.data };
|
||||
} else {
|
||||
return { data: [] };
|
||||
}
|
||||
},
|
||||
pageSize: PAGINATION_DEFAULT_TAKE,
|
||||
searchQuery: search,
|
||||
dependencies: [],
|
||||
});
|
||||
|
||||
// Komponen search input
|
||||
const searchComponent = useMemo(
|
||||
() => (
|
||||
<SearchInput
|
||||
containerStyle={{ width: "100%", marginBottom: 0 }}
|
||||
placeholder="Cari Komentar"
|
||||
value={search}
|
||||
onChangeText={setSearch}
|
||||
/>
|
||||
),
|
||||
[search],
|
||||
);
|
||||
|
||||
// Header component dengan box title
|
||||
const headerComponent = useMemo(
|
||||
() => (
|
||||
<AdminComp_BoxTitle
|
||||
title="Report Komentar"
|
||||
rightComponent={searchComponent}
|
||||
/>
|
||||
),
|
||||
[searchComponent],
|
||||
);
|
||||
|
||||
// Render item untuk daftar report comment
|
||||
const renderItem = useCallback(
|
||||
({ item, index }: { item: any; index: number }) => (
|
||||
<AdminBasicBox
|
||||
key={index}
|
||||
style={{ marginHorizontal: 5, marginVertical: 5 }}
|
||||
onPress={() => {
|
||||
router.push(
|
||||
`/admin/forum/${item?.Forum_Komentar?.id}/list-report-comment`,
|
||||
);
|
||||
}}
|
||||
>
|
||||
<StackCustom gap={0}>
|
||||
<GridSpan_4_8
|
||||
label={<TextCustom>Pelapor</TextCustom>}
|
||||
value={
|
||||
<TextCustom truncate={1}>
|
||||
{item?.User?.username || "-"}
|
||||
</TextCustom>
|
||||
}
|
||||
/>
|
||||
<GridSpan_4_8
|
||||
label={<TextCustom>Komentar</TextCustom>}
|
||||
value={
|
||||
<TextCustom truncate={2}>
|
||||
{item?.Forum_Komentar?.komentar || "-"}
|
||||
</TextCustom>
|
||||
}
|
||||
/>
|
||||
{item?.deskripsi ?
|
||||
<GridSpan_4_8
|
||||
label={<TextCustom>Deskripsi</TextCustom>}
|
||||
value={
|
||||
<TextCustom truncate={2}>
|
||||
{item?.deskripsi|| "-"}
|
||||
</TextCustom>
|
||||
}
|
||||
/> : <GridSpan_4_8
|
||||
label={<TextCustom>Jenis Laporan</TextCustom>}
|
||||
value={
|
||||
<TextCustom truncate={2}>
|
||||
{item?.ForumMaster_KategoriReport?.title || "-"}
|
||||
</TextCustom>
|
||||
}
|
||||
/>
|
||||
}
|
||||
{/* <GridSpan_4_8
|
||||
label={<TextCustom>Jenis Laporan</TextCustom>}
|
||||
value={
|
||||
<TextCustom truncate={2}>
|
||||
{item?.ForumMaster_KategoriReport?.title || "-"}
|
||||
</TextCustom>
|
||||
}
|
||||
/> */}
|
||||
</StackCustom>
|
||||
</AdminBasicBox>
|
||||
),
|
||||
[],
|
||||
);
|
||||
|
||||
// Buat komponen-komponen pagination
|
||||
const { ListEmptyComponent, ListFooterComponent } =
|
||||
createPaginationComponents({
|
||||
loading: pagination.loading,
|
||||
refreshing: pagination.refreshing,
|
||||
listData: pagination.listData,
|
||||
searchQuery: search,
|
||||
emptyMessage: "Belum ada data report komentar",
|
||||
emptySearchMessage: "Tidak ada hasil pencarian",
|
||||
isInitialLoad: pagination.isInitialLoad,
|
||||
skeletonCount: PAGINATION_DEFAULT_TAKE,
|
||||
skeletonHeight: 100,
|
||||
});
|
||||
|
||||
return (
|
||||
<NewWrapper
|
||||
listData={pagination.listData}
|
||||
renderItem={renderItem}
|
||||
keyExtractor={(item: any) => item.id?.toString() || `fallback-${item.id}`}
|
||||
headerComponent={headerComponent}
|
||||
ListEmptyComponent={ListEmptyComponent}
|
||||
ListFooterComponent={ListFooterComponent}
|
||||
onEndReached={pagination.loadMore}
|
||||
refreshControl={
|
||||
<RefreshControl
|
||||
refreshing={pagination.refreshing}
|
||||
onRefresh={pagination.onRefresh}
|
||||
tintColor="#E1B525"
|
||||
colors={["#E1B525"]}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
130
screens/Admin/Forum/ScreenForumReportPosting.tsx
Normal file
130
screens/Admin/Forum/ScreenForumReportPosting.tsx
Normal file
@@ -0,0 +1,130 @@
|
||||
import { SearchInput, StackCustom, TextCustom } from "@/components";
|
||||
import AdminBasicBox from "@/components/_ShareComponent/Admin/AdminBasicBox";
|
||||
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
|
||||
import { GridSpan_4_8 } from "@/components/_ShareComponent/GridSpan_4_8";
|
||||
import NewWrapper from "@/components/_ShareComponent/NewWrapper";
|
||||
import { MainColor } from "@/constants/color-palet";
|
||||
import { PAGINATION_DEFAULT_TAKE } from "@/constants/constans-value";
|
||||
import { createPaginationComponents } from "@/helpers/paginationHelpers";
|
||||
import { usePagination } from "@/hooks/use-pagination";
|
||||
import { apiAdminForum } from "@/service/api-admin/api-admin-forum";
|
||||
import { router } from "expo-router";
|
||||
import { useCallback, useMemo, useState } from "react";
|
||||
import { RefreshControl } from "react-native";
|
||||
|
||||
export function Admin_ScreenForumReportPosting() {
|
||||
const [search, setSearch] = useState("");
|
||||
|
||||
// Gunakan hook pagination
|
||||
const pagination = usePagination({
|
||||
fetchFunction: async (page, searchQuery) => {
|
||||
const response = await apiAdminForum({
|
||||
category: "report_posting",
|
||||
search: searchQuery || "",
|
||||
page: String(page),
|
||||
});
|
||||
|
||||
if (response.success) {
|
||||
return { data: response.data };
|
||||
} else {
|
||||
return { data: [] };
|
||||
}
|
||||
},
|
||||
pageSize: PAGINATION_DEFAULT_TAKE,
|
||||
searchQuery: search,
|
||||
dependencies: [],
|
||||
});
|
||||
|
||||
// Komponen search input
|
||||
const searchComponent = useMemo(
|
||||
() => (
|
||||
<SearchInput
|
||||
containerStyle={{ width: "100%", marginBottom: 0 }}
|
||||
placeholder="Cari Postingan"
|
||||
value={search}
|
||||
onChangeText={setSearch}
|
||||
/>
|
||||
),
|
||||
[search],
|
||||
);
|
||||
|
||||
// Box title component
|
||||
const headerComponent = useMemo(
|
||||
() => (
|
||||
<AdminComp_BoxTitle
|
||||
title="Report Posting"
|
||||
rightComponent={searchComponent}
|
||||
/>
|
||||
),
|
||||
[searchComponent],
|
||||
);
|
||||
|
||||
// Render item untuk daftar report posting
|
||||
const renderItem = useCallback(
|
||||
({ item, index }: { item: any; index: number }) => (
|
||||
<AdminBasicBox
|
||||
key={index}
|
||||
style={{ marginHorizontal: 5, marginVertical: 5 }}
|
||||
onPress={() => {
|
||||
router.push(
|
||||
`/admin/forum/${item?.Forum_Posting?.id}/list-report-posting`,
|
||||
);
|
||||
}}
|
||||
>
|
||||
<StackCustom gap={0}>
|
||||
<GridSpan_4_8
|
||||
label={<TextCustom>Pelapor</TextCustom>}
|
||||
value={
|
||||
<TextCustom truncate={1}>
|
||||
{item?.User?.username || "-"}
|
||||
</TextCustom>
|
||||
}
|
||||
/>
|
||||
<GridSpan_4_8
|
||||
label={<TextCustom>Postingan</TextCustom>}
|
||||
value={
|
||||
<TextCustom truncate={2}>
|
||||
{item?.Forum_Posting?.diskusi || "-"}
|
||||
</TextCustom>
|
||||
}
|
||||
/>
|
||||
</StackCustom>
|
||||
</AdminBasicBox>
|
||||
),
|
||||
[],
|
||||
);
|
||||
|
||||
// Buat komponen-komponen pagination
|
||||
const { ListEmptyComponent, ListFooterComponent } =
|
||||
createPaginationComponents({
|
||||
loading: pagination.loading,
|
||||
refreshing: pagination.refreshing,
|
||||
listData: pagination.listData,
|
||||
searchQuery: search,
|
||||
emptyMessage: "Belum ada data report posting",
|
||||
emptySearchMessage: "Tidak ada hasil pencarian",
|
||||
isInitialLoad: pagination.isInitialLoad,
|
||||
skeletonCount: PAGINATION_DEFAULT_TAKE,
|
||||
skeletonHeight: 100,
|
||||
});
|
||||
|
||||
return (
|
||||
<NewWrapper
|
||||
listData={pagination.listData}
|
||||
renderItem={renderItem}
|
||||
keyExtractor={(item: any) => item.id?.toString() || `fallback-${item.id}`}
|
||||
headerComponent={headerComponent}
|
||||
ListEmptyComponent={ListEmptyComponent}
|
||||
ListFooterComponent={ListFooterComponent}
|
||||
onEndReached={pagination.loadMore}
|
||||
refreshControl={
|
||||
<RefreshControl
|
||||
refreshing={pagination.refreshing}
|
||||
onRefresh={pagination.onRefresh}
|
||||
tintColor={MainColor.yellow}
|
||||
colors={[MainColor.yellow]}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -3,13 +3,15 @@ import { apiConfig } from "../api-config";
|
||||
export async function apiAdminForum({
|
||||
category,
|
||||
search,
|
||||
page = "1",
|
||||
}: {
|
||||
category: "dashboard" | "posting" | "report_posting" | "report_comment";
|
||||
search?: string;
|
||||
page?: string;
|
||||
}) {
|
||||
try {
|
||||
const response = await apiConfig.get(
|
||||
`/mobile/admin/forum?category=${category}&search=${search}`
|
||||
`/mobile/admin/forum?category=${category}&search=${search}&page=${page}`
|
||||
);
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
@@ -78,12 +80,14 @@ export async function apiAdminForumDeactivateComment({
|
||||
|
||||
export async function apiAdminForumListReportPostingById({
|
||||
id,
|
||||
page = "1",
|
||||
}: {
|
||||
id: string;
|
||||
page?: string;
|
||||
}) {
|
||||
try {
|
||||
const response = await apiConfig.get(
|
||||
`/mobile/admin/forum/${id}/report-posting`
|
||||
`/mobile/admin/forum/${id}/report-posting?page=${page}`
|
||||
);
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user