From 76845b71b4cb0fc8a5787cd3fed31c4bd8cc15b9 Mon Sep 17 00:00:00 2001 From: bagasbanuna Date: Wed, 18 Feb 2026 14:28:15 +0800 Subject: [PATCH] ## Perubahan Tampilan Admin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### File Baru (4) - `screens/Admin/Voting/ScreenVotingStatus.tsx` - `screens/Admin/Voting/ScreenVotingHistory.tsx` - `screens/Admin/Voting/ScreenEventTypeOfEvent.tsx` - `screens/Admin/Voting/BoxVotingStatus.tsx` ### File Diubah (3) - `app/(application)/admin/voting/[status]/status.tsx` → 5 baris - `app/(application)/admin/voting/history.tsx` → 5 baris - `app/(application)/admin/event/type-of-event.tsx` → 5 baris ### API Updates (2) - `service/api-admin/api-admin-voting.ts` → tambah param `page` - `service/api-admin/api-master-admin.ts` → tambah param `page` ## Fitur Baru - Pagination (infinite scroll) - Pull-to-Refresh - Skeleton Loading - Empty State - Search Functionality ### No Issue" --- QWEN.md | 169 +++++++++++++++--- app.config.js | 2 +- .../(user)/portofolio/[id]/index.tsx | 32 ++-- .../admin/collaboration/[id]/[status].tsx | 36 ++-- .../admin/event/type-of-event.tsx | 128 +------------ .../[id]/[status]/transaction-detail.tsx | 24 +-- app/(application)/admin/maps.tsx | 29 +-- .../admin/super-admin/[id]/index.tsx | 24 +-- .../admin/user-access/[id]/index.tsx | 22 +-- .../admin/voting/[id]/[status]/index.tsx | 31 ++-- .../admin/voting/[status]/status.tsx | 116 +----------- app/(application)/admin/voting/history.tsx | 103 +---------- bun.lock | 34 +--- components/_ShareComponent/GridTwoView.tsx | 12 +- docs/CHANGE_LOG.md | 28 +++ docs/prompt-for-qwen-code.md | 24 +-- ios/HIPMIBadungConnect/Info.plist | 2 +- package.json | 2 +- screens/Admin/Voting/BoxVotingStatus.tsx | 54 ++++++ .../Admin/Voting/ScreenEventTypeOfEvent.tsx | 152 ++++++++++++++++ screens/Admin/Voting/ScreenVotingHistory.tsx | 102 +++++++++++ screens/Admin/Voting/ScreenVotingStatus.tsx | 110 ++++++++++++ screens/Maps/MapsView.tsx | 38 ++-- service/api-admin/api-admin-voting.ts | 4 +- service/api-admin/api-master-admin.ts | 4 +- 25 files changed, 751 insertions(+), 531 deletions(-) create mode 100644 docs/CHANGE_LOG.md create mode 100644 screens/Admin/Voting/BoxVotingStatus.tsx create mode 100644 screens/Admin/Voting/ScreenEventTypeOfEvent.tsx create mode 100644 screens/Admin/Voting/ScreenVotingHistory.tsx create mode 100644 screens/Admin/Voting/ScreenVotingStatus.tsx diff --git a/QWEN.md b/QWEN.md index 41c3cd5..cdaccdf 100644 --- a/QWEN.md +++ b/QWEN.md @@ -35,6 +35,7 @@ hipmi-mobile/ │ └── ... ├── assets/ # Images, icons, and static assets ├── constants/ # Constants and configuration values +├── helpers/ # Helper functions (pagination, etc.) ├── hooks/ # Custom React hooks ├── lib/ # Utility libraries ├── navigation/ # Navigation configuration @@ -49,6 +50,8 @@ hipmi-mobile/ - Node.js (with bun as the package manager) - Expo CLI - iOS Simulator or Android Emulator (for native builds) +- Android Studio (for Android builds) +- Xcode (for iOS builds, macOS only) ### Setup and Development @@ -76,28 +79,79 @@ hipmi-mobile/ bun run lint ``` -### Environment Variables -The application uses environment variables defined in the app.config.js file: +### Build Commands + +#### EAS Build (Production) +```bash +# Production build +eas build --profile production + +# Preview build +eas build --profile preview + +# Development build +eas build --profile development +``` + +#### Local Native Builds +```bash +# Generate native folders (iOS & Android) +npx expo prebuild + +# iOS specific +bunx expo prebuild --platform ios +open ios/HIPMIBADUNG.xcworkspace + +# Android specific +bunx expo prebuild --platform android +``` + +#### Version Management +```bash +# Patch version update +npm version patch +``` + +### Android Debugging +```bash +# List connected devices +adb devices + +# Install APK to device/emulator +adb install android/app/build/outputs/apk/debug/app-debug.apk + +# Install to specific device +adb -s install android/app/build/outputs/apk/debug/app-debug.apk +``` + +## Environment Variables + +The application uses environment variables defined in the `app.config.js` file: - `API_BASE_URL`: Base URL for API endpoints - `BASE_URL`: Base application URL - `DEEP_LINK_URL`: URL for deep linking functionality -### EAS Build Configuration +Create a `.env` file in the project root with these variables. + +## EAS Build Configuration + The project uses Expo Application Services (EAS) for building and deploying: -- Development builds with development client -- Preview builds for internal distribution -- Production builds for app stores +- **Development**: Development builds with development client +- **Preview**: Internal distribution builds (APK for Android) +- **Production**: App store builds (App Bundle for Android, IPA for iOS) + +Configuration is in `eas.json`. ## Features and Functionality -The application appears to include several key modules: -- **Authentication**: Login, registration, and verification flows -- **Admin Panel**: Administrative functions +The application includes several key modules: +- **Authentication**: Login with phone number, OTP verification, registration, terms acceptance +- **Admin Panel**: Administrative functions for managing content and users - **Collaboration**: Tools for member collaboration - **Events**: Event management and calendar - **Forum**: Discussion forums - **Maps**: Location-based services with Mapbox integration -- **Donations**: Donation functionality +- **Donations**: Donation functionality with fund disbursement tracking - **Job Board**: Employment opportunities - **Investment**: Investment-related features - **Voting**: Voting systems @@ -109,18 +163,50 @@ The application appears to include several key modules: ### Coding Standards - TypeScript is used throughout the project for type safety - Component-based architecture with reusable components -- Context API for state management +- Context API for state management (AuthContext) - File-based routing with Expo Router - Consistent naming conventions using camelCase for variables and PascalCase for components +- Path aliases: `@/*` maps to project root + +### Architecture Patterns + +#### Screen Components +- Screen components are stored in `/screens` directory organized by feature +- Route files in `/app` import and use screen components +- Example pattern: + ```tsx + // app/some-route.tsx + import SomeScreen from "@/screens/Feature/ScreenSome"; + + export default function SomeRoute() { + return ; + } + ``` + +#### Wrapper Components +- `NewWrapper` component is used for consistent screen layouts +- Located at `components/_ShareComponent/NewWrapper.tsx` + +#### Pagination Pattern +- Use `hooks/use-pagination.tsx` and `helpers/paginationHelpers.tsx` +- Helper functions: `createSkeletonList`, `createEmptyState`, `createLoadingFooter`, `createPaginationComponents` +- API functions should accept `page` parameter (default: "1") + +### API Service Structure +- Base API configuration: `service/api-config.ts` +- Client APIs: `service/api-client/` +- Admin APIs: `service/api-admin/` +- All API calls use axios with interceptors for auth token injection ### Testing - Linting is configured with ESLint -- Standard Expo linting configuration is used +- Standard Expo linting configuration ### Security - Firebase is integrated for authentication and messaging - Camera and location permissions are properly configured - Deep linking is secured with app domain associations +- Auth tokens stored in AsyncStorage ## Key Dependencies @@ -133,6 +219,9 @@ The application appears to include several key modules: - `react-native-toast-message`: Toast notifications - `react-native-otp-entry`: OTP input components - `react-native-qrcode-svg`: QR code generation +- `axios`: HTTP client for API calls +- `lodash`: Utility library +- `moti`: Animation library ### Development Dependencies - `@types/*`: TypeScript type definitions @@ -142,28 +231,52 @@ The application appears to include several key modules: ## Platform Support The application is configured to support: -- **iOS**: With tablet support and proper permissions -- **Android**: With adaptive icons and intent filters for deep linking +- **iOS**: + - Bundle identifier: `com.anonymous.hipmi-mobile` + - Supports tablets + - Build number: 21 + - Google Services integration + - Associated domains for deep linking +- **Android**: + - Package name: `com.bip.hipmimobileapp` + - Version code: 4 + - Adaptive icons + - Edge-to-edge display enabled + - Intent filters for HTTPS deep linking - **Web**: Static output configuration for web deployment ## Special Configurations -### iOS Configuration -- Bundle identifier: `com.anonymous.hipmi-mobile` -- Supports tablets -- Google Services integration -- Location permission handling -- Associated domains for deep linking - -### Android Configuration -- Package name: `com.bip.hipmimobileapp` -- Adaptive icons -- Edge-to-edge display enabled -- Intent filters for HTTPS deep linking -- Google Services integration +### Deep Linking +- Scheme: `hipmimobile://` +- Associated domains: `applinks:cld-dkr-staging-hipmi.wibudev.com` +- Configured for both iOS and Android ### Maps Integration The application uses Mapbox for mapping functionality with the `@rnmapbox/maps` plugin. ### Push Notifications -Firebase Cloud Messaging is integrated for push notifications with proper configuration for both iOS and Android platforms. \ No newline at end of file +Firebase Cloud Messaging is integrated for push notifications with proper configuration for both iOS and Android platforms. + +### Camera +Camera permissions configured for both iOS and Android with microphone access for recording. + +## Common Development Tasks + +### Adding a New Screen +1. Create screen component in appropriate `/screens` subdirectory +2. Add route in `/app` directory if needed +3. Configure navigation in `AppRoot.tsx` if custom header is needed + +### Adding API Endpoint +1. Add function in appropriate service file (`service/api-client/` or `service/api-admin/`) +2. Use `apiConfig` axios instance for requests +3. Include proper error handling + +### Refactoring Pattern (from docs/prompt-for-qwen-code.md) +When moving code from route files to screen components: +1. Create new file in `screens//` directory +2. Rename function with prefix (e.g., `Admin_`, `Donation_`) +3. Use `NewWrapper` component for consistent layout +4. Apply pagination helpers if displaying lists +5. Import and call from original route file diff --git a/app.config.js b/app.config.js index 6400171..82e67ec 100644 --- a/app.config.js +++ b/app.config.js @@ -21,7 +21,7 @@ export default { "Aplikasi membutuhkan akses lokasi untuk menampilkan peta.", }, associatedDomains: ["applinks:cld-dkr-staging-hipmi.wibudev.com"], - buildNumber: "20", + buildNumber: "21", }, android: { diff --git a/app/(application)/(user)/portofolio/[id]/index.tsx b/app/(application)/(user)/portofolio/[id]/index.tsx index 70a4307..ecffdfa 100644 --- a/app/(application)/(user)/portofolio/[id]/index.tsx +++ b/app/(application)/(user)/portofolio/[id]/index.tsx @@ -1,12 +1,12 @@ /* eslint-disable react-hooks/exhaustive-deps */ import { - ButtonCustom, - DrawerCustom, - DummyLandscapeImage, - LoaderCustom, - Spacing, - StackCustom, - TextCustom, + ButtonCustom, + DrawerCustom, + DummyLandscapeImage, + LoaderCustom, + Spacing, + StackCustom, + TextCustom, } from "@/components"; import LeftButtonCustom from "@/components/Button/BackButton"; import GridTwoView from "@/components/_ShareComponent/GridTwoView"; @@ -49,7 +49,7 @@ export default function Portofolio() { useCallback(() => { onLoadData(id as string); onLoadUserByToken(); - }, [id]) + }, [id]), ); async function onLoadData(id: string) { @@ -144,27 +144,27 @@ export default function Portofolio() { } - rightIcon={{data?.BusinessMaps?.namePin}} + rightItem={{data?.BusinessMaps?.namePin}} /> } - rightIcon={ + rightItem={ {data?.MasterBidangBisnis?.name} } /> @@ -172,26 +172,26 @@ export default function Portofolio() { } - rightIcon={{data?.tlpn}} + rightItem={{data?.tlpn}} /> } - rightIcon={{data?.alamatKantor}} + rightItem={{data?.alamatKantor}} /> diff --git a/app/(application)/admin/collaboration/[id]/[status].tsx b/app/(application)/admin/collaboration/[id]/[status].tsx index 3300cf3..0bd2471 100644 --- a/app/(application)/admin/collaboration/[id]/[status].tsx +++ b/app/(application)/admin/collaboration/[id]/[status].tsx @@ -1,12 +1,12 @@ /* eslint-disable react-hooks/exhaustive-deps */ import { - BaseBox, - BoxButtonOnFooter, - ButtonCustom, - Grid, - StackCustom, - TextCustom, - ViewWrapper, + BaseBox, + BoxButtonOnFooter, + ButtonCustom, + Grid, + StackCustom, + TextCustom, + ViewWrapper, } from "@/components"; import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle"; import GridTwoView from "@/components/_ShareComponent/GridTwoView"; @@ -22,7 +22,7 @@ export default function AdminCollaborationPublish() { useFocusEffect( useCallback(() => { handlerLoadData(); - }, [status]) + }, [status]), ); const handlerLoadData = async () => { @@ -78,16 +78,16 @@ export default function AdminCollaborationPublish() { - {data?.report && ( - - Catatan report} - rightIcon={{data?.report}} - /> - - )} + {data?.report && ( + + Catatan report} + rightItem={{data?.report}} + /> + + )} ); diff --git a/app/(application)/admin/event/type-of-event.tsx b/app/(application)/admin/event/type-of-event.tsx index 8a0c8c6..ef14a84 100644 --- a/app/(application)/admin/event/type-of-event.tsx +++ b/app/(application)/admin/event/type-of-event.tsx @@ -1,129 +1,5 @@ -import { - ActionIcon, - BadgeCustom, - CenterCustom, - LoaderCustom, - Spacing, - StackCustom, - TextCustom, - ViewWrapper -} from "@/components"; -import { IconEdit } from "@/components/_Icon"; -import AdminActionIconPlus from "@/components/_ShareComponent/Admin/ActionIconPlus"; -import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage"; -import AdminTitlePage from "@/components/_ShareComponent/Admin/TitlePage"; -import { GridViewCustomSpan } from "@/components/_ShareComponent/GridViewCustomSpan"; -import { ICON_SIZE_BUTTON } from "@/constants/constans-value"; -import { apiAdminMasterTypeOfEvent } from "@/service/api-admin/api-master-admin"; -import { colorActivationForBadge } from "@/utils/colorActivationForBadge"; -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_ScreenEventTypeOfEvent } from "@/screens/Admin/Voting/ScreenEventTypeOfEvent"; export default function AdminEventTypeOfEvent() { - const [listData, setListData] = useState(null); - const [loadData, setLoadData] = useState(false); - - useFocusEffect( - useCallback(() => { - onLoadData(); - }, []) - ); - - const onLoadData = async () => { - try { - setLoadData(true); - const response = await apiAdminMasterTypeOfEvent(); - - if (response.success) { - setListData(response.data); - } - } catch (error) { - console.log("[ERROR]",error); - setListData([]); - } finally { - setLoadData(false); - } - }; - - return ( - <> - }> - { - router.push(`/admin/event/type-create`); - }} - /> - } - /> - - <> - - Aksi - - } - component2={Status} - component3={Tipe Acara} - /> - - - - - {loadData ? ( - - ) : _.isEmpty(listData) ? ( - - Belum ada data - - ) : ( - listData?.map((item, index) => ( - - - - } - onPress={() => { - router.push(`/admin/event/type-update?id=${item.id}`); - }} - /> - - } - style2={{ alignItems: "center" }} - component2={ - - - {item?.active ? "Aktif" : "Tidak Aktif"} - - - } - component3={{item.name}} - /> - - )) - )} - - - - - ); + return ; } diff --git a/app/(application)/admin/investment/[id]/[status]/transaction-detail.tsx b/app/(application)/admin/investment/[id]/[status]/transaction-detail.tsx index 583c248..f751825 100644 --- a/app/(application)/admin/investment/[id]/[status]/transaction-detail.tsx +++ b/app/(application)/admin/investment/[id]/[status]/transaction-detail.tsx @@ -1,13 +1,13 @@ /* eslint-disable react-hooks/exhaustive-deps */ import { - AlertDefaultSystem, - BadgeCustom, - BaseBox, - ButtonCustom, - Spacing, - StackCustom, - TextCustom, - ViewWrapper, + AlertDefaultSystem, + BadgeCustom, + BaseBox, + ButtonCustom, + Spacing, + StackCustom, + TextCustom, + ViewWrapper, } from "@/components"; import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle"; import { GridSpan_4_8 } from "@/components/_ShareComponent/GridSpan_4_8"; @@ -15,8 +15,8 @@ import GridTwoView from "@/components/_ShareComponent/GridTwoView"; import { MainColor } from "@/constants/color-palet"; import { useAuth } from "@/hooks/use-auth"; import { - apiAdminInvestmentGetOneInvoiceById, - apiAdminInvestmentUpdateInvoice, + apiAdminInvestmentGetOneInvoiceById, + apiAdminInvestmentUpdateInvoice, } from "@/service/api-admin/api-admin-investment"; import { colorBadgeTransaction } from "@/utils/colorBadge"; import { dateTimeView } from "@/utils/dateTimeView"; @@ -158,7 +158,7 @@ export default function AdminInvestmentTransactionDetail() { spanRight={6} styleLeft={{ paddingRight: 10 }} styleRight={{ paddingLeft: 10 }} - leftIcon={ + leftItem={ } - rightIcon={ + rightItem={ { handlerLoadList(); - }, []) + }, []), ); const handlerLoadList = async () => { @@ -144,52 +153,52 @@ export default function AdminMaps() { } - rightIcon={{selected.namePin}} + rightItem={{selected.namePin}} /> } - rightIcon={{selected.bidangBisnis}} + rightItem={{selected.bidangBisnis}} /> } - rightIcon={+{selected.nomorTelepon}} + rightItem={+{selected.nomorTelepon}} /> } - rightIcon={{selected.alamatBisnis}} + rightItem={{selected.alamatBisnis}} /> diff --git a/app/(application)/admin/super-admin/[id]/index.tsx b/app/(application)/admin/super-admin/[id]/index.tsx index 9e40471..0aaa08c 100644 --- a/app/(application)/admin/super-admin/[id]/index.tsx +++ b/app/(application)/admin/super-admin/[id]/index.tsx @@ -1,17 +1,17 @@ /* eslint-disable react-hooks/exhaustive-deps */ import { - BoxButtonOnFooter, - ButtonCustom, - LoaderCustom, - StackCustom, - TextCustom, - ViewWrapper, + BoxButtonOnFooter, + ButtonCustom, + LoaderCustom, + StackCustom, + TextCustom, + ViewWrapper, } from "@/components"; import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle"; import GridTwoView from "@/components/_ShareComponent/GridTwoView"; import { - apiAdminUserAccessGetById, - apiAdminUserAccessUpdateStatus, + apiAdminUserAccessGetById, + apiAdminUserAccessUpdateStatus, } from "@/service/api-admin/api-admin-user-access"; import { router, useFocusEffect, useLocalSearchParams } from "expo-router"; import { useCallback, useState } from "react"; @@ -26,7 +26,7 @@ export default function SuperAdminDetail() { useFocusEffect( useCallback(() => { onLoadData(); - }, [id]) + }, [id]), ); const onLoadData = async () => { @@ -48,7 +48,7 @@ export default function SuperAdminDetail() { const response = await apiAdminUserAccessUpdateStatus({ id: id as string, role: data?.masterUserRoleId === "2" ? "user" : "admin", - category: "role" + category: "role", }); if (!response.success) { @@ -102,8 +102,8 @@ export default function SuperAdminDetail() { key={index} spanLeft={4} spanRight={8} - leftIcon={{item?.label}} - rightIcon={{item?.value}} + leftItem={{item?.label}} + rightItem={{item?.value}} /> ))} diff --git a/app/(application)/admin/user-access/[id]/index.tsx b/app/(application)/admin/user-access/[id]/index.tsx index 827b3d4..87d3a22 100644 --- a/app/(application)/admin/user-access/[id]/index.tsx +++ b/app/(application)/admin/user-access/[id]/index.tsx @@ -1,18 +1,18 @@ /* eslint-disable react-hooks/exhaustive-deps */ import { - BoxButtonOnFooter, - ButtonCustom, - LoaderCustom, - StackCustom, - TextCustom, - ViewWrapper, + BoxButtonOnFooter, + ButtonCustom, + LoaderCustom, + StackCustom, + TextCustom, + ViewWrapper, } from "@/components"; import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle"; import GridTwoView from "@/components/_ShareComponent/GridTwoView"; import { useAuth } from "@/hooks/use-auth"; import { - apiAdminUserAccessGetById, - apiAdminUserAccessUpdateStatus, + apiAdminUserAccessGetById, + apiAdminUserAccessUpdateStatus, } from "@/service/api-admin/api-admin-user-access"; import { router, useFocusEffect, useLocalSearchParams } from "expo-router"; import { useCallback, useState } from "react"; @@ -28,7 +28,7 @@ export default function AdminUserAccessDetail() { useFocusEffect( useCallback(() => { onLoadData(); - }, [id]) + }, [id]), ); const onLoadData = async () => { @@ -102,8 +102,8 @@ export default function AdminUserAccessDetail() { key={index} spanLeft={4} spanRight={8} - leftIcon={{item?.label}} - rightIcon={{item?.value}} + leftItem={{item?.label}} + rightItem={{item?.value}} /> ))} diff --git a/app/(application)/admin/voting/[id]/[status]/index.tsx b/app/(application)/admin/voting/[id]/[status]/index.tsx index fc60321..d69fb3d 100644 --- a/app/(application)/admin/voting/[id]/[status]/index.tsx +++ b/app/(application)/admin/voting/[id]/[status]/index.tsx @@ -5,6 +5,7 @@ import { BaseBox, CircleContainer, Grid, + NewWrapper, Spacing, StackCustom, TextCustom, @@ -13,7 +14,7 @@ import { import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle"; import AdminButtonReject from "@/components/_ShareComponent/Admin/ButtonReject"; import AdminButtonReview from "@/components/_ShareComponent/Admin/ButtonReview"; -import { GridSpan_4_8 } from "@/components/_ShareComponent/GridSpan_4_8"; +import GridTwoView from "@/components/_ShareComponent/GridTwoView"; import ReportBox from "@/components/Box/ReportBox"; import { MainColor } from "@/constants/color-palet"; import { useAuth } from "@/hooks/use-auth"; @@ -40,7 +41,7 @@ export default function AdminVotingDetail() { useFocusEffect( useCallback(() => { onLoadData(); - }, [id]) + }, [id]), ); const onLoadData = async () => { @@ -169,26 +170,28 @@ export default function AdminVotingDetail() { return ( <> - } > {listData.map((item, i) => ( - {item.label}} - value={{item.value}} + spanLeft={5} + spanRight={7} + leftItem={{item.label}} + rightItem={{item.value}} /> ))} - {status === "publish" || - (status === "history" && ( - - - Hasil Voting + {(status === "publish" || status === "history") && ( + + + Hasil Voting @@ -209,11 +212,11 @@ export default function AdminVotingDetail() { - ) + ), )} - ))} + )} {data && data?.catatan && @@ -250,7 +253,7 @@ export default function AdminVotingDetail() { /> )} - + ); } diff --git a/app/(application)/admin/voting/[status]/status.tsx b/app/(application)/admin/voting/[status]/status.tsx index 5c89295..7180b89 100644 --- a/app/(application)/admin/voting/[status]/status.tsx +++ b/app/(application)/admin/voting/[status]/status.tsx @@ -1,117 +1,5 @@ -/* eslint-disable react-hooks/exhaustive-deps */ -import { - ActionIcon, - LoaderCustom, - SearchInput, - StackCustom, - TextCustom, - ViewWrapper, -} from "@/components"; -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 { ICON_SIZE_BUTTON } from "@/constants/constans-value"; -import { apiAdminVoting } from "@/service/api-admin/api-admin-voting"; -import { Octicons } from "@expo/vector-icons"; -import { router, useFocusEffect, useLocalSearchParams } from "expo-router"; -import _ from "lodash"; -import { useCallback, useState } from "react"; -import { Divider } from "react-native-paper"; +import { Admin_ScreenVotingStatus } from "@/screens/Admin/Voting/ScreenVotingStatus"; export default function AdminVotingStatus() { - const { status } = useLocalSearchParams(); - const [list, setList] = useState(null); - const [loadList, setLoadList] = useState(false); - const [search, setSearch] = useState(""); - - useFocusEffect( - useCallback(() => { - onLoadData(); - }, [status, search]) - ); - - const onLoadData = async () => { - try { - setLoadList(true); - const response = await apiAdminVoting({ - category: status as "publish" | "review" | "reject" as any, - search, - }); - - if (response.success) { - setList(response.data); - } - } catch (error) { - console.log("[ERROR]", error); - } finally { - setLoadList(false); - } - }; - - const rightComponent = ( - - ); - return ( - <> - }> - - - - - - - {loadList ? ( - - ) : _.isEmpty(list) ? ( - - Belum ada data - - ) : ( - list.map((item: any, i: number) => ( - - } - onPress={() => { - router.push(`/admin/voting/${item.id}/${status}`); - }} - /> - } - value2={ - - {item?.Author?.username || "-"} - - } - value3={ - - {item?.title || "-"} - - } - /> - )) - )} - - - - ); + return ; } diff --git a/app/(application)/admin/voting/history.tsx b/app/(application)/admin/voting/history.tsx index 1930004..e738fdd 100644 --- a/app/(application)/admin/voting/history.tsx +++ b/app/(application)/admin/voting/history.tsx @@ -1,104 +1,5 @@ -/* eslint-disable react-hooks/exhaustive-deps */ -import { - ActionIcon, - LoaderCustom, - SearchInput, - StackCustom, - TextCustom, - ViewWrapper -} from "@/components"; -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 { ICON_SIZE_BUTTON } from "@/constants/constans-value"; -import { apiAdminVoting } from "@/service/api-admin/api-admin-voting"; -import { Octicons } from "@expo/vector-icons"; -import { router, useFocusEffect } from "expo-router"; -import _ from "lodash"; -import { useCallback, useState } from "react"; -import { Divider } from "react-native-paper"; +import { Admin_ScreenVotingHistory } from "@/screens/Admin/Voting/ScreenVotingHistory"; export default function AdminVotingHistory() { - const [list, setList] = useState(null); - const [loadList, setLoadList] = useState(false); - const [search, setSearch] = useState(""); - - useFocusEffect( - useCallback(() => { - onLoadData(); - }, [ search]) - ); - - const onLoadData = async () => { - try { - setLoadList(true); - const response = await apiAdminVoting({ - category: "history", - search, - }); - - if (response.success) { - setList(response.data); - } - } catch (error) { - console.log("[ERROR]", error); - } finally { - setLoadList(false); - } - }; - - const rightComponent = ( - - ); - return ( - <> - }> - - - - - - - {loadList ? : _.isEmpty(list) ? Belum ada data : list.map((item: any, i: number) => ( - - } - onPress={() => { - router.push(`/admin/voting/${item.id}/history`); - }} - /> - } - value2={{item?.Author?.username || "-"}} - value3={ - - {item?.title || "-"} - - } - /> - ))} - - - - ); + return ; } diff --git a/bun.lock b/bun.lock index bb28bc7..0fb9e3e 100644 --- a/bun.lock +++ b/bun.lock @@ -45,7 +45,7 @@ "moti": "^0.30.0", "react": "19.1.0", "react-dom": "19.1.0", - "react-native": "0.81.4", + "react-native": "0.81.5", "react-native-dotenv": "^3.4.11", "react-native-gesture-handler": "~2.28.0", "react-native-international-phone-number": "^0.9.3", @@ -702,21 +702,21 @@ "@react-native-firebase/messaging": ["@react-native-firebase/messaging@23.8.6", "", { "peerDependencies": { "@react-native-firebase/app": "23.8.6", "expo": ">=47.0.0" }, "optionalPeers": ["expo"] }, "sha512-48eW4OFl+XKRgxmgwhNCCT7zUGttm3oAxKJxVQ2Iv9o+wVUTQCLELK3ihC/OrTwCWomM9ylIICqKaK4pdmA22Q=="], - "@react-native/assets-registry": ["@react-native/assets-registry@0.81.4", "", {}, "sha512-AMcDadefBIjD10BRqkWw+W/VdvXEomR6aEZ0fhQRAv7igrBzb4PTn4vHKYg+sUK0e3wa74kcMy2DLc/HtnGcMA=="], + "@react-native/assets-registry": ["@react-native/assets-registry@0.81.5", "", {}, "sha512-705B6x/5Kxm1RKRvSv0ADYWm5JOnoiQ1ufW7h8uu2E6G9Of/eE6hP/Ivw3U5jI16ERqZxiKQwk34VJbB0niX9w=="], "@react-native/babel-plugin-codegen": ["@react-native/babel-plugin-codegen@0.83.2", "", { "dependencies": { "@babel/traverse": "^7.25.3", "@react-native/codegen": "0.83.2" } }, "sha512-XbcN/BEa64pVlb0Hb/E/Ph2SepjVN/FcNKrJcQvtaKZA6mBSO8pW8Eircdlr61/KBH94LihHbQoQDzkQFpeaTg=="], "@react-native/babel-preset": ["@react-native/babel-preset@0.83.2", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-default-from": "^7.24.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-transform-arrow-functions": "^7.24.7", "@babel/plugin-transform-async-generator-functions": "^7.25.4", "@babel/plugin-transform-async-to-generator": "^7.24.7", "@babel/plugin-transform-block-scoping": "^7.25.0", "@babel/plugin-transform-class-properties": "^7.25.4", "@babel/plugin-transform-classes": "^7.25.4", "@babel/plugin-transform-computed-properties": "^7.24.7", "@babel/plugin-transform-destructuring": "^7.24.8", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/plugin-transform-for-of": "^7.24.7", "@babel/plugin-transform-function-name": "^7.25.1", "@babel/plugin-transform-literals": "^7.25.2", "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", "@babel/plugin-transform-numeric-separator": "^7.24.7", "@babel/plugin-transform-object-rest-spread": "^7.24.7", "@babel/plugin-transform-optional-catch-binding": "^7.24.7", "@babel/plugin-transform-optional-chaining": "^7.24.8", "@babel/plugin-transform-parameters": "^7.24.7", "@babel/plugin-transform-private-methods": "^7.24.7", "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@babel/plugin-transform-react-display-name": "^7.24.7", "@babel/plugin-transform-react-jsx": "^7.25.2", "@babel/plugin-transform-react-jsx-self": "^7.24.7", "@babel/plugin-transform-react-jsx-source": "^7.24.7", "@babel/plugin-transform-regenerator": "^7.24.7", "@babel/plugin-transform-runtime": "^7.24.7", "@babel/plugin-transform-shorthand-properties": "^7.24.7", "@babel/plugin-transform-spread": "^7.24.7", "@babel/plugin-transform-sticky-regex": "^7.24.7", "@babel/plugin-transform-typescript": "^7.25.2", "@babel/plugin-transform-unicode-regex": "^7.24.7", "@babel/template": "^7.25.0", "@react-native/babel-plugin-codegen": "0.83.2", "babel-plugin-syntax-hermes-parser": "0.32.0", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" } }, "sha512-X/RAXDfe6W+om/Fw1i6htTxQXFhBJ2jgNOWx3WpI3KbjeIWbq7ib6vrpTeIAW2NUMg+K3mML1NzgD4dpZeqdjA=="], - "@react-native/codegen": ["@react-native/codegen@0.81.4", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/parser": "^7.25.3", "glob": "^7.1.1", "hermes-parser": "0.29.1", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "yargs": "^17.6.2" } }, "sha512-LWTGUTzFu+qOQnvkzBP52B90Ym3stZT8IFCzzUrppz8Iwglg83FCtDZAR4yLHI29VY/x/+pkcWAMCl3739XHdw=="], + "@react-native/codegen": ["@react-native/codegen@0.81.5", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/parser": "^7.25.3", "glob": "^7.1.1", "hermes-parser": "0.29.1", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "yargs": "^17.6.2" } }, "sha512-a2TDA03Up8lpSa9sh5VRGCQDXgCTOyDOFH+aqyinxp1HChG8uk89/G+nkJ9FPd0rqgi25eCTR16TWdS3b+fA6g=="], - "@react-native/community-cli-plugin": ["@react-native/community-cli-plugin@0.81.4", "", { "dependencies": { "@react-native/dev-middleware": "0.81.4", "debug": "^4.4.0", "invariant": "^2.2.4", "metro": "^0.83.1", "metro-config": "^0.83.1", "metro-core": "^0.83.1", "semver": "^7.1.3" }, "peerDependencies": { "@react-native-community/cli": "*", "@react-native/metro-config": "*" }, "optionalPeers": ["@react-native-community/cli", "@react-native/metro-config"] }, "sha512-8mpnvfcLcnVh+t1ok6V9eozWo8Ut+TZhz8ylJ6gF9d6q9EGDQX6s8jenan5Yv/pzN4vQEKI4ib2pTf/FELw+SA=="], + "@react-native/community-cli-plugin": ["@react-native/community-cli-plugin@0.81.5", "", { "dependencies": { "@react-native/dev-middleware": "0.81.5", "debug": "^4.4.0", "invariant": "^2.2.4", "metro": "^0.83.1", "metro-config": "^0.83.1", "metro-core": "^0.83.1", "semver": "^7.1.3" }, "peerDependencies": { "@react-native-community/cli": "*", "@react-native/metro-config": "*" }, "optionalPeers": ["@react-native-community/cli", "@react-native/metro-config"] }, "sha512-yWRlmEOtcyvSZ4+OvqPabt+NS36vg0K/WADTQLhrYrm9qdZSuXmq8PmdJWz/68wAqKQ+4KTILiq2kjRQwnyhQw=="], "@react-native/debugger-frontend": ["@react-native/debugger-frontend@0.81.5", "", {}, "sha512-bnd9FSdWKx2ncklOetCgrlwqSGhMHP2zOxObJbOWXoj7GHEmih4MKarBo5/a8gX8EfA1EwRATdfNBQ81DY+h+w=="], "@react-native/dev-middleware": ["@react-native/dev-middleware@0.81.5", "", { "dependencies": { "@isaacs/ttlcache": "^1.4.1", "@react-native/debugger-frontend": "0.81.5", "chrome-launcher": "^0.15.2", "chromium-edge-launcher": "^0.2.0", "connect": "^3.6.5", "debug": "^4.4.0", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "open": "^7.0.3", "serve-static": "^1.16.2", "ws": "^6.2.3" } }, "sha512-WfPfZzboYgo/TUtysuD5xyANzzfka8Ebni6RIb2wDxhb56ERi7qDrE4xGhtPsjCL4pQBXSVxyIlCy0d8I6EgGA=="], - "@react-native/gradle-plugin": ["@react-native/gradle-plugin@0.81.4", "", {}, "sha512-T7fPcQvDDCSusZFVSg6H1oVDKb/NnVYLnsqkcHsAF2C2KGXyo3J7slH/tJAwNfj/7EOA2OgcWxfC1frgn9TQvw=="], + "@react-native/gradle-plugin": ["@react-native/gradle-plugin@0.81.5", "", {}, "sha512-hORRlNBj+ReNMLo9jme3yQ6JQf4GZpVEBLxmTXGGlIL78MAezDZr5/uq9dwElSbcGmLEgeiax6e174Fie6qPLg=="], "@react-native/js-polyfills": ["@react-native/js-polyfills@0.83.2", "", {}, "sha512-dk6fIY2OrKW/2Nk2HydfYNrQau8g6LOtd7NVBrgaqa+lvuRyIML5iimShP5qPqQnx2ofHuzjFw+Ya0b5Q7nDbA=="], @@ -726,7 +726,7 @@ "@react-native/normalize-colors": ["@react-native/normalize-colors@0.81.5", "", {}, "sha512-0HuJ8YtqlTVRXGZuGeBejLE04wSQsibpTI+RGOyVqxZvgtlLLC/Ssw0UmbHhT4lYMp2fhdtvKZSs5emWB1zR/g=="], - "@react-native/virtualized-lists": ["@react-native/virtualized-lists@0.81.4", "", { "dependencies": { "invariant": "^2.2.4", "nullthrows": "^1.1.1" }, "peerDependencies": { "@types/react": "^19.1.0", "react": "*", "react-native": "*" }, "optionalPeers": ["@types/react"] }, "sha512-hBM+rMyL6Wm1Q4f/WpqGsaCojKSNUBqAXLABNGoWm1vabZ7cSnARMxBvA/2vo3hLcoR4v7zDK8tkKm9+O0LjVA=="], + "@react-native/virtualized-lists": ["@react-native/virtualized-lists@0.81.5", "", { "dependencies": { "invariant": "^2.2.4", "nullthrows": "^1.1.1" }, "peerDependencies": { "@types/react": "^19.1.0", "react": "*", "react-native": "*" }, "optionalPeers": ["@types/react"] }, "sha512-UVXgV/db25OPIvwZySeToXD/9sKKhOdkcWmmf4Jh8iBZuyfML+/5CasaZ1E7Lqg6g3uqVQq75NqIwkYmORJMPw=="], "@react-navigation/bottom-tabs": ["@react-navigation/bottom-tabs@7.13.0", "", { "dependencies": { "@react-navigation/elements": "^2.9.5", "color": "^4.2.3", "sf-symbols-typescript": "^2.1.0" }, "peerDependencies": { "@react-navigation/native": "^7.1.28", "react": ">= 18.2.0", "react-native": "*", "react-native-safe-area-context": ">= 4.0.0", "react-native-screens": ">= 4.0.0" } }, "sha512-qxxjRDpjhZ4vIZqG4rBU1Vx2jgOAO/ciUKc9sJqVlTM005E2E+aK1EaE3lGaBDyZxTpjonollAucZcqL7OTscQ=="], @@ -2104,7 +2104,7 @@ "react-is": ["react-is@19.2.4", "", {}, "sha512-W+EWGn2v0ApPKgKKCy/7s7WHXkboGcsrXE+2joLyVxkbyVQfO3MUEaUQDHoSmb8TFFrSKYa9mw64WZHNHSDzYA=="], - "react-native": ["react-native@0.81.4", "", { "dependencies": { "@jest/create-cache-key-function": "^29.7.0", "@react-native/assets-registry": "0.81.4", "@react-native/codegen": "0.81.4", "@react-native/community-cli-plugin": "0.81.4", "@react-native/gradle-plugin": "0.81.4", "@react-native/js-polyfills": "0.81.4", "@react-native/normalize-colors": "0.81.4", "@react-native/virtualized-lists": "0.81.4", "abort-controller": "^3.0.0", "anser": "^1.4.9", "ansi-regex": "^5.0.0", "babel-jest": "^29.7.0", "babel-plugin-syntax-hermes-parser": "0.29.1", "base64-js": "^1.5.1", "commander": "^12.0.0", "flow-enums-runtime": "^0.0.6", "glob": "^7.1.1", "invariant": "^2.2.4", "jest-environment-node": "^29.7.0", "memoize-one": "^5.0.0", "metro-runtime": "^0.83.1", "metro-source-map": "^0.83.1", "nullthrows": "^1.1.1", "pretty-format": "^29.7.0", "promise": "^8.3.0", "react-devtools-core": "^6.1.5", "react-refresh": "^0.14.0", "regenerator-runtime": "^0.13.2", "scheduler": "0.26.0", "semver": "^7.1.3", "stacktrace-parser": "^0.1.10", "whatwg-fetch": "^3.0.0", "ws": "^6.2.3", "yargs": "^17.6.2" }, "peerDependencies": { "@types/react": "^19.1.0", "react": "^19.1.0" }, "optionalPeers": ["@types/react"], "bin": { "react-native": "cli.js" } }, "sha512-bt5bz3A/+Cv46KcjV0VQa+fo7MKxs17RCcpzjftINlen4ZDUl0I6Ut+brQ2FToa5oD0IB0xvQHfmsg2EDqsZdQ=="], + "react-native": ["react-native@0.81.5", "", { "dependencies": { "@jest/create-cache-key-function": "^29.7.0", "@react-native/assets-registry": "0.81.5", "@react-native/codegen": "0.81.5", "@react-native/community-cli-plugin": "0.81.5", "@react-native/gradle-plugin": "0.81.5", "@react-native/js-polyfills": "0.81.5", "@react-native/normalize-colors": "0.81.5", "@react-native/virtualized-lists": "0.81.5", "abort-controller": "^3.0.0", "anser": "^1.4.9", "ansi-regex": "^5.0.0", "babel-jest": "^29.7.0", "babel-plugin-syntax-hermes-parser": "0.29.1", "base64-js": "^1.5.1", "commander": "^12.0.0", "flow-enums-runtime": "^0.0.6", "glob": "^7.1.1", "invariant": "^2.2.4", "jest-environment-node": "^29.7.0", "memoize-one": "^5.0.0", "metro-runtime": "^0.83.1", "metro-source-map": "^0.83.1", "nullthrows": "^1.1.1", "pretty-format": "^29.7.0", "promise": "^8.3.0", "react-devtools-core": "^6.1.5", "react-refresh": "^0.14.0", "regenerator-runtime": "^0.13.2", "scheduler": "0.26.0", "semver": "^7.1.3", "stacktrace-parser": "^0.1.10", "whatwg-fetch": "^3.0.0", "ws": "^6.2.3", "yargs": "^17.6.2" }, "peerDependencies": { "@types/react": "^19.1.0", "react": "^19.1.0" }, "optionalPeers": ["@types/react"], "bin": { "react-native": "cli.js" } }, "sha512-1w+/oSjEXZjMqsIvmkCRsOc8UBYv163bTWKTI8+1mxztvQPhCRYGTvZ/PL1w16xXHneIj/SLGfxWg2GWN2uexw=="], "react-native-country-codes-picker": ["react-native-country-codes-picker@2.3.5", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-dDQhd0bVvlmgb84NPhTOmTk5UVYPHtk3lqZI+BPb61H1rC2IDrTvPWENg6u1DMGliqWHQDBYpeH37zvxxQL71w=="], @@ -2688,8 +2688,6 @@ "@react-native/codegen/hermes-parser": ["hermes-parser@0.29.1", "", { "dependencies": { "hermes-estree": "0.29.1" } }, "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA=="], - "@react-native/community-cli-plugin/@react-native/dev-middleware": ["@react-native/dev-middleware@0.81.4", "", { "dependencies": { "@isaacs/ttlcache": "^1.4.1", "@react-native/debugger-frontend": "0.81.4", "chrome-launcher": "^0.15.2", "chromium-edge-launcher": "^0.2.0", "connect": "^3.6.5", "debug": "^4.4.0", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "open": "^7.0.3", "serve-static": "^1.16.2", "ws": "^6.2.3" } }, "sha512-hu1Wu5R28FT7nHXs2wWXvQ++7W7zq5GPY83llajgPlYKznyPLAY/7bArc5rAzNB7b0kwnlaoPQKlvD/VP9LZug=="], - "@react-native/community-cli-plugin/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], "@react-native/dev-middleware/open": ["open@7.4.2", "", { "dependencies": { "is-docker": "^2.0.0", "is-wsl": "^2.1.1" } }, "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q=="], @@ -2902,9 +2900,7 @@ "react-devtools-core/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="], - "react-native/@react-native/js-polyfills": ["@react-native/js-polyfills@0.81.4", "", {}, "sha512-sr42FaypKXJHMVHhgSbu2f/ZJfrLzgaoQ+HdpRvKEiEh2mhFf6XzZwecyLBvWqf2pMPZa+CpPfNPiejXjKEy8w=="], - - "react-native/@react-native/normalize-colors": ["@react-native/normalize-colors@0.81.4", "", {}, "sha512-9nRRHO1H+tcFqjb9gAM105Urtgcanbta2tuqCVY0NATHeFPDEAB7gPyiLxCHKMi1NbhP6TH0kxgSWXKZl1cyRg=="], + "react-native/@react-native/js-polyfills": ["@react-native/js-polyfills@0.81.5", "", {}, "sha512-fB7M1CMOCIUudTRuj7kzxIBTVw2KXnsgbQ6+4cbqSxo8NmRRhA0Ul4ZUzZj3rFd3VznTL4Brmocv1oiN0bWZ8w=="], "react-native/commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="], @@ -3062,10 +3058,6 @@ "@react-native/codegen/hermes-parser/hermes-estree": ["hermes-estree@0.29.1", "", {}, "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ=="], - "@react-native/community-cli-plugin/@react-native/dev-middleware/@react-native/debugger-frontend": ["@react-native/debugger-frontend@0.81.4", "", {}, "sha512-SU05w1wD0nKdQFcuNC9D6De0ITnINCi8MEnx9RsTD2e4wN83ukoC7FpXaPCYyP6+VjFt5tUKDPgP1O7iaNXCqg=="], - - "@react-native/community-cli-plugin/@react-native/dev-middleware/open": ["open@7.4.2", "", { "dependencies": { "is-docker": "^2.0.0", "is-wsl": "^2.1.1" } }, "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q=="], - "@react-native/dev-middleware/open/is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="], "@testing-library/react-native/pretty-format/@jest/schemas": ["@jest/schemas@30.0.5", "", { "dependencies": { "@sinclair/typebox": "^0.34.0" } }, "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA=="], @@ -3224,8 +3216,6 @@ "@istanbuljs/load-nyc-config/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="], - "@react-native/community-cli-plugin/@react-native/dev-middleware/open/is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="], - "@testing-library/react-native/pretty-format/@jest/schemas/@sinclair/typebox": ["@sinclair/typebox@0.34.48", "", {}, "sha512-kKJTNuK3AQOrgjjotVxMrCn1sUJwM76wMszfq1kdU4uYVJjvEWuFQ6HgvLt4Xz3fSmZlTOxJ/Ie13KnIcWQXFA=="], "babel-preset-expo/@react-native/babel-preset/@react-native/babel-plugin-codegen/@react-native/codegen": ["@react-native/codegen@0.79.6", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/parser": "^7.25.3", "glob": "^7.1.1", "hermes-parser": "0.25.1", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "yargs": "^17.6.2" } }, "sha512-iRBX8Lgbqypwnfba7s6opeUwVyaR23mowh9ILw7EcT2oLz3RqMmjJdrbVpWhGSMGq2qkPfqAH7bhO8C7O+xfjQ=="], @@ -3298,8 +3288,6 @@ "babel-preset-expo/@react-native/babel-preset/@react-native/babel-plugin-codegen/@react-native/codegen/hermes-parser": ["hermes-parser@0.25.1", "", { "dependencies": { "hermes-estree": "0.25.1" } }, "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA=="], - "expo/babel-preset-expo/@react-native/babel-preset/@react-native/babel-plugin-codegen/@react-native/codegen": ["@react-native/codegen@0.81.5", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/parser": "^7.25.3", "glob": "^7.1.1", "hermes-parser": "0.29.1", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "yargs": "^17.6.2" } }, "sha512-a2TDA03Up8lpSa9sh5VRGCQDXgCTOyDOFH+aqyinxp1HChG8uk89/G+nkJ9FPd0rqgi25eCTR16TWdS3b+fA6g=="], - "logkitty/yargs/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="], "pkg-dir/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], @@ -3326,10 +3314,6 @@ "babel-preset-expo/@react-native/babel-preset/@react-native/babel-plugin-codegen/@react-native/codegen/hermes-parser/hermes-estree": ["hermes-estree@0.25.1", "", {}, "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw=="], - "expo/babel-preset-expo/@react-native/babel-preset/@react-native/babel-plugin-codegen/@react-native/codegen/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], - - "expo/babel-preset-expo/@react-native/babel-preset/@react-native/babel-plugin-codegen/@react-native/codegen/hermes-parser": ["hermes-parser@0.29.1", "", { "dependencies": { "hermes-estree": "0.29.1" } }, "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA=="], - "logkitty/yargs/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], "qrcode/yargs/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], @@ -3343,7 +3327,5 @@ "@expo/fingerprint/glob/minimatch/brace-expansion/balanced-match/jackspeak/@isaacs/cliui": ["@isaacs/cliui@9.0.0", "", {}, "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg=="], "@expo/metro-config/glob/minimatch/brace-expansion/balanced-match/jackspeak/@isaacs/cliui": ["@isaacs/cliui@9.0.0", "", {}, "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg=="], - - "expo/babel-preset-expo/@react-native/babel-preset/@react-native/babel-plugin-codegen/@react-native/codegen/hermes-parser/hermes-estree": ["hermes-estree@0.29.1", "", {}, "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ=="], } } diff --git a/components/_ShareComponent/GridTwoView.tsx b/components/_ShareComponent/GridTwoView.tsx index d919d17..b66ab71 100644 --- a/components/_ShareComponent/GridTwoView.tsx +++ b/components/_ShareComponent/GridTwoView.tsx @@ -4,15 +4,15 @@ import Grid from "../Grid/GridCustom"; export default function GridTwoView({ spanLeft = 6, spanRight = 6, - leftIcon, - rightIcon, + leftItem, + rightItem, styleLeft, styleRight, }: { spanLeft?: number; spanRight?: number; - leftIcon?: React.ReactNode; - rightIcon?: React.ReactNode; + leftItem?: React.ReactNode; + rightItem?: React.ReactNode; styleLeft?: ViewStyle; styleRight?: ViewStyle; }) { @@ -24,13 +24,13 @@ export default function GridTwoView({ span={spanLeft} style={styleLeft ? { ...baseStyle, ...styleLeft } : baseStyle} > - {leftIcon} + {leftItem} - {rightIcon} + {rightItem} ); diff --git a/docs/CHANGE_LOG.md b/docs/CHANGE_LOG.md new file mode 100644 index 0000000..d49eac9 --- /dev/null +++ b/docs/CHANGE_LOG.md @@ -0,0 +1,28 @@ +# CHANGE LOG - fixed-admin/18-feb-26 + +## Perubahan Tampilan Admin + +### File Baru (4) +- `screens/Admin/Voting/ScreenVotingStatus.tsx` +- `screens/Admin/Voting/ScreenVotingHistory.tsx` +- `screens/Admin/Voting/ScreenEventTypeOfEvent.tsx` +- `screens/Admin/Voting/BoxVotingStatus.tsx` + +### File Diubah (3) +- `app/(application)/admin/voting/[status]/status.tsx` → 5 baris +- `app/(application)/admin/voting/history.tsx` → 5 baris +- `app/(application)/admin/event/type-of-event.tsx` → 5 baris + +### API Updates (2) +- `service/api-admin/api-admin-voting.ts` → tambah param `page` +- `service/api-admin/api-master-admin.ts` → tambah param `page` + +## Fitur Baru +- Pagination (infinite scroll) +- Pull-to-Refresh +- Skeleton Loading +- Empty State +- Search Functionality + +## Stats ++305 baris, -531 baris (net: -226) diff --git a/docs/prompt-for-qwen-code.md b/docs/prompt-for-qwen-code.md index 4e774ee..bc68619 100644 --- a/docs/prompt-for-qwen-code.md +++ b/docs/prompt-for-qwen-code.md @@ -53,18 +53,12 @@ Terapkan NewWrapper pada file: app/(application)/(user)/donation/create.tsx Component yang digunakan: components/_ShareComponent/NewWrapper.tsx - - - -Gunakan bahasa indonesia pada cli agar saya mudah membacanya.eclar - - -File source: app/(application)/admin/event/[id]/list-of-participants.tsx -Folder tujuan: screens/Admin/Event -Nama file utama: ScreenEventListOfParticipants.tsx -Nama function utama: Admin_ScreenEventListOfParticipants +File source: app/(application)/admin/event/type-of-event.tsx +Folder tujuan: screens/Admin/Voting +Nama file utama: ScreenEventTypeOfEvent.tsx +Nama function utama: Admin_ScreenEventTypeOfEvent 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" @@ -72,8 +66,8 @@ Analisa juga file "Nama file utama" , jika belum menggunakan NewWrapper pada fil -Function fecth: apiAdminEventListOfParticipants -File function fetch: service/api-admin/api-admin-event.ts +Function fecth: apiAdminMasterTypeOfEvent +File function fetch: service/api-admin/api-master-admin.ts Terapkan pagination pada file "Nama file utama" Komponen pagination yang digunaka berada pada file hooks/use-pagination.tsx dan helpers/paginationHelpers.tsx @@ -84,6 +78,10 @@ Kemudian rapikan code nya pisah komponen seperti render item dan lainnya agar le Gunakan bahasa indonesia pada cli agar saya mudah membacanya. + +File refrensi: screens/Admin/Event/ScreenVotingStatus.tsx +Anda bisa menggunakan refrensi dari "File refrensi" jika butuh pemahaman dengan tipe fitur yang hampir sama + Terapkan NewWrapper pada file: screens/Admin/App-Information/InformationBankSection.tsx Component yang digunakan: components/_ShareComponent/NewWrapper.tsx @@ -95,6 +93,8 @@ Terapkan pagination pada file "Nama file utama" Komponen pagination yang digunaka berada pada file hooks/use-pagination.tsx dan helpers/paginationHelpers.tsx Perbaiki fetch "Function fecth" , pada file "File function fetch" Jika tidak ada props page maka tambahkan props page dan default page: "1" ( string ) + + File Utama: screens/Admin/App-Information/InformationBankSection.tsx Terapkan FlatList dan pagination pada file "File Utama" diff --git a/ios/HIPMIBadungConnect/Info.plist b/ios/HIPMIBadungConnect/Info.plist index 8c55873..9f0f327 100644 --- a/ios/HIPMIBadungConnect/Info.plist +++ b/ios/HIPMIBadungConnect/Info.plist @@ -39,7 +39,7 @@ CFBundleVersion - 20 + 21 ITSAppUsesNonExemptEncryption LSMinimumSystemVersion diff --git a/package.json b/package.json index 990b206..b1a150a 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "moti": "^0.30.0", "react": "19.1.0", "react-dom": "19.1.0", - "react-native": "0.81.4", + "react-native": "0.81.5", "react-native-dotenv": "^3.4.11", "react-native-gesture-handler": "~2.28.0", "react-native-international-phone-number": "^0.9.3", diff --git a/screens/Admin/Voting/BoxVotingStatus.tsx b/screens/Admin/Voting/BoxVotingStatus.tsx new file mode 100644 index 0000000..9aa9fc5 --- /dev/null +++ b/screens/Admin/Voting/BoxVotingStatus.tsx @@ -0,0 +1,54 @@ +import { Divider, StackCustom, TextCustom } from "@/components"; +import AdminBasicBox from "@/components/_ShareComponent/Admin/AdminBasicBox"; +import { GridSpan_4_8 } from "@/components/_ShareComponent/GridSpan_4_8"; +import { dateTimeView } from "@/utils/dateTimeView"; +import { router } from "expo-router"; +import { View } from "react-native"; + +interface BoxVotingStatusProps { + item: any; + status?: string; + path: any; +} + +export default function Admin_BoxVotingStatus({ + item, + status, + path, +}: BoxVotingStatusProps) { + return ( + <> + { + router.push(path); + }} + > + + + + {item?.title || "-"} + + + + Mulai} + value={ + + {dateTimeView({ date: item?.awalVote }) || "-"} + + } + /> + Berakhir} + value={ + + {dateTimeView({ date: item?.akhirVote }) || "-"} + + } + /> + + + + ); +} diff --git a/screens/Admin/Voting/ScreenEventTypeOfEvent.tsx b/screens/Admin/Voting/ScreenEventTypeOfEvent.tsx new file mode 100644 index 0000000..c2945be --- /dev/null +++ b/screens/Admin/Voting/ScreenEventTypeOfEvent.tsx @@ -0,0 +1,152 @@ +import { BadgeCustom, TextCustom } from "@/components"; +import AdminActionIconPlus from "@/components/_ShareComponent/Admin/ActionIconPlus"; +import AdminBasicBox from "@/components/_ShareComponent/Admin/AdminBasicBox"; +import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage"; +import GridTwoView from "@/components/_ShareComponent/GridTwoView"; +import { GridViewCustomSpan } from "@/components/_ShareComponent/GridViewCustomSpan"; +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 { apiAdminMasterTypeOfEvent } from "@/service/api-admin/api-master-admin"; +import { router, useFocusEffect } from "expo-router"; +import { useCallback, useMemo, useState } from "react"; +import { RefreshControl, View } from "react-native"; + +export function Admin_ScreenEventTypeOfEvent() { + const [search, setSearch] = useState(""); + + // Gunakan hook pagination + const pagination = usePagination({ + fetchFunction: async (page, searchQuery) => { + const response = await apiAdminMasterTypeOfEvent({ + page: String(page), + }); + + if (response.success) { + return { data: response.data }; + } else { + return { data: [] }; + } + }, + pageSize: PAGINATION_DEFAULT_TAKE, + searchQuery: search, + dependencies: [], + }); + + // Komponen action plus untuk header + const rightComponent = useMemo( + () => ( + { + router.push(`/admin/event/type-create`); + }} + /> + ), + [], + ); + + // Header component untuk title + const headerComponent = useMemo( + () => ( + + ), + [rightComponent], + ); + + // Render header tabel (Aksi, Status, Tipe Acara) + const renderTableHeader = useMemo( + () => ( + <> + + Aksi + + } + component2={ + + Status + + } + component3={Tipe Acara} + /> + + ), + [], + ); + + // Render item untuk daftar tipe event (mengikuti pattern InformationBankSection) + const renderItem = useCallback( + ({ item, index }: { item: any; index: number }) => ( + { + router.push(`/admin/event/type-update?id=${item.id}`); + }} + style={{ marginHorizontal: 10, marginVertical: 5 }} + > + {item?.name || "-"}} + rightItem={ + + {item?.active ? ( + Aktif + ) : ( + Tidak Aktif + )} + + } + spanLeft={8} + spanRight={4} + styleRight={{ + alignItems: "flex-end", + }} + /> + + ), + [], + ); + + useFocusEffect( + useCallback(() => { + pagination.onRefresh(); + }, []), + ); + + // Buat komponen-komponen pagination + const { ListEmptyComponent, ListFooterComponent } = + createPaginationComponents({ + loading: pagination.loading, + refreshing: pagination.refreshing, + listData: pagination.listData, + searchQuery: search, + emptyMessage: "Belum ada data", + emptySearchMessage: "Tidak ada hasil pencarian", + isInitialLoad: pagination.isInitialLoad, + skeletonCount: PAGINATION_DEFAULT_TAKE, + skeletonHeight: 100, + }); + + return ( + item.id?.toString() || `fallback-${item.id}`} + headerComponent={headerComponent} + ListEmptyComponent={ListEmptyComponent} + ListFooterComponent={ListFooterComponent} + onEndReached={pagination.loadMore} + refreshControl={ + + } + /> + ); +} diff --git a/screens/Admin/Voting/ScreenVotingHistory.tsx b/screens/Admin/Voting/ScreenVotingHistory.tsx new file mode 100644 index 0000000..9642fba --- /dev/null +++ b/screens/Admin/Voting/ScreenVotingHistory.tsx @@ -0,0 +1,102 @@ +import { SearchInput } from "@/components"; +import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage"; +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 { apiAdminVoting } from "@/service/api-admin/api-admin-voting"; +import { useCallback, useMemo, useState } from "react"; +import { RefreshControl } from "react-native"; +import Admin_BoxVotingStatus from "./BoxVotingStatus"; + +export function Admin_ScreenVotingHistory() { + const [search, setSearch] = useState(""); + + // Gunakan hook pagination + const pagination = usePagination({ + fetchFunction: async (page, searchQuery) => { + const response = await apiAdminVoting({ + category: "history", + 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 untuk header + const rightComponent = useMemo( + () => ( + setSearch(value)} + /> + ), + [search], + ); + + const renderItem = useCallback( + ({ item, index }: { item: any; index: number }) => ( + + ), + [], + ); + + // Header component dengan judul voting history + const headerComponent = useMemo( + () => ( + + ), + [rightComponent], + ); + + // Buat komponen-komponen pagination + const { ListEmptyComponent, ListFooterComponent } = + createPaginationComponents({ + loading: pagination.loading, + refreshing: pagination.refreshing, + listData: pagination.listData, + searchQuery: search, + emptyMessage: "Belum ada data", + emptySearchMessage: "Tidak ada hasil pencarian", + isInitialLoad: pagination.isInitialLoad, + skeletonCount: PAGINATION_DEFAULT_TAKE, + skeletonHeight: 80, + }); + + return ( + item.id?.toString() || `fallback-${item.id}`} + headerComponent={headerComponent} + ListEmptyComponent={ListEmptyComponent} + ListFooterComponent={ListFooterComponent} + onEndReached={pagination.loadMore} + refreshControl={ + + } + /> + ); +} diff --git a/screens/Admin/Voting/ScreenVotingStatus.tsx b/screens/Admin/Voting/ScreenVotingStatus.tsx new file mode 100644 index 0000000..05c6f73 --- /dev/null +++ b/screens/Admin/Voting/ScreenVotingStatus.tsx @@ -0,0 +1,110 @@ +import { SearchInput } from "@/components"; +import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage"; +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 { apiAdminVoting } from "@/service/api-admin/api-admin-voting"; +import { useLocalSearchParams } from "expo-router"; +import _ from "lodash"; +import { useCallback, useMemo, useState } from "react"; +import { RefreshControl } from "react-native"; +import Admin_BoxVotingStatus from "./BoxVotingStatus"; + +export function Admin_ScreenVotingStatus() { + const { status } = useLocalSearchParams(); + const [search, setSearch] = useState(""); + + // Gunakan hook pagination + const pagination = usePagination({ + fetchFunction: async (page, searchQuery) => { + const response = await apiAdminVoting({ + category: status as any, + search: searchQuery, + page: String(page), + }); + + if (response.success) { + return { data: response.data }; + } else { + return { data: [] }; + } + }, + pageSize: PAGINATION_DEFAULT_TAKE, + searchQuery: search, + dependencies: [status], + }); + + // Komponen search input untuk header + const rightComponent = useMemo( + () => ( + setSearch(value)} + /> + ), + [search], + ); + + // Render item untuk daftar voting + const renderItem = useCallback( + ({ item, index }: { item: any; index: number }) => ( + + ), + [status], + ); + + // Header component dengan judul status voting + const headerComponent = useMemo( + () => ( + + ), + [status, rightComponent], + ); + + // Buat komponen-komponen pagination + const { ListEmptyComponent, ListFooterComponent } = + createPaginationComponents({ + loading: pagination.loading, + refreshing: pagination.refreshing, + listData: pagination.listData, + searchQuery: search, + emptyMessage: "Belum ada data", + emptySearchMessage: "Tidak ada hasil pencarian", + isInitialLoad: pagination.isInitialLoad, + skeletonCount: PAGINATION_DEFAULT_TAKE, + skeletonHeight: 80, + }); + + return ( + item.id?.toString() || `fallback-${item.id}`} + headerComponent={headerComponent} + ListEmptyComponent={ListEmptyComponent} + ListFooterComponent={ListFooterComponent} + onEndReached={pagination.loadMore} + refreshControl={ + + } + /> + ); +} diff --git a/screens/Maps/MapsView.tsx b/screens/Maps/MapsView.tsx index 282d30c..0901e8d 100644 --- a/screens/Maps/MapsView.tsx +++ b/screens/Maps/MapsView.tsx @@ -1,12 +1,12 @@ import { - ViewWrapper, - DrawerCustom, - DummyLandscapeImage, - Spacing, - StackCustom, - TextCustom, - Grid, - ButtonCustom, + ButtonCustom, + DrawerCustom, + DummyLandscapeImage, + Grid, + Spacing, + StackCustom, + TextCustom, + ViewWrapper, } from "@/components"; import GridTwoView from "@/components/_ShareComponent/GridTwoView"; import API_IMAGE from "@/constants/api-storage"; @@ -15,8 +15,8 @@ import { apiMapsGetAll } from "@/service/api-client/api-maps"; import { openInDeviceMaps } from "@/utils/openInDeviceMaps"; import { FontAwesome, Ionicons } from "@expo/vector-icons"; import { Image } from "expo-image"; -import { useFocusEffect, router } from "expo-router"; -import { useState, useCallback } from "react"; +import { router, useFocusEffect } from "expo-router"; +import { useCallback, useState } from "react"; import { View } from "react-native"; import MapView, { Marker } from "react-native-maps"; @@ -47,7 +47,7 @@ export default function MapsView() { useFocusEffect( useCallback(() => { handlerLoadList(); - }, []) + }, []), ); const handlerLoadList = async () => { @@ -146,52 +146,52 @@ export default function MapsView() { } - rightIcon={{selected.namePin}} + rightItem={{selected.namePin}} /> } - rightIcon={{selected.bidangBisnis}} + rightItem={{selected.bidangBisnis}} /> } - rightIcon={{selected.nomorTelepon}} + rightItem={{selected.nomorTelepon}} /> } - rightIcon={{selected.alamatBisnis}} + rightItem={{selected.alamatBisnis}} /> diff --git a/service/api-admin/api-admin-voting.ts b/service/api-admin/api-admin-voting.ts index ddd70e0..c41a40b 100644 --- a/service/api-admin/api-admin-voting.ts +++ b/service/api-admin/api-admin-voting.ts @@ -4,13 +4,15 @@ import { apiConfig } from "../api-config"; export async function apiAdminVoting({ category, search, + page = "1", }: { category: "dashboard" | "history" | "publish" | "review" | "report"; search?: string; + page?: string; }) { try { const response = await apiConfig.get( - `/mobile/admin/voting?category=${category}&search=${search}` + `/mobile/admin/voting?category=${category}&search=${search}&page=${page}` ); return response.data; } catch (error) { diff --git a/service/api-admin/api-master-admin.ts b/service/api-admin/api-master-admin.ts index f354195..8c3b1b6 100644 --- a/service/api-admin/api-master-admin.ts +++ b/service/api-admin/api-master-admin.ts @@ -135,9 +135,9 @@ export async function apiAdminMasterBusinessFieldCreate({ // ================== END BUSINNES FIELD ================== // // ================== START EVENT ================== // -export async function apiAdminMasterTypeOfEvent() { +export async function apiAdminMasterTypeOfEvent({ page = "1" }: { page?: string }) { try { - const response = await apiConfig.get(`/mobile/admin/master/type-of-event`); + const response = await apiConfig.get(`/mobile/admin/master/type-of-event?page=${page}`); return response.data; } catch (error) { throw error;