Compare commits
68 Commits
api/23-oct
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 60e5c0663c | |||
| 2c0198b1b7 | |||
| 573b525352 | |||
| ae0bf4dd60 | |||
| 6f9481c7c9 | |||
| bb63f7fa9a | |||
| cccb44a835 | |||
| 0f5862ce70 | |||
| 9742c1849a | |||
| 624bd49f69 | |||
| 2446e9d51a | |||
| 2265ef64cc | |||
| ab5733f336 | |||
| f5e30087ed | |||
| fbd096af9c | |||
| a93f97ed6a | |||
| 5019b00f59 | |||
| 858b441a8c | |||
| 249ada221b | |||
| 98aaa126a1 | |||
| 19814315a4 | |||
| 69452ff4e7 | |||
| 33ec892ec8 | |||
| 77ef3a055e | |||
| 8a900e9469 | |||
| aba3ad8ded | |||
| d471682ae7 | |||
| 00eea71248 | |||
| 41e648d8f3 | |||
| 7799c7720d | |||
| 0c4deac6e2 | |||
| 2926b6eac1 | |||
| 676b8a38be | |||
| 0a2aa71013 | |||
| 868e96a54a | |||
| 059b4d053a | |||
| 637d444c5c | |||
| a614cfaac9 | |||
| 76debfd6a6 | |||
| 8c3aec8e57 | |||
| 1a7ad58505 | |||
| 1ade69ff2f | |||
| 97ea6ab799 | |||
| 4e9ce07759 | |||
| 7612be7366 | |||
| 8f659c2b7e | |||
| 61bca7cfe1 | |||
| 5af85c3a8b | |||
| a8807d88ad | |||
| 5d36429aa4 | |||
| ec49999f99 | |||
| 867e82c6fa | |||
| f9f996f195 | |||
| 98394309e6 | |||
| 4625831377 | |||
| ebd6107c36 | |||
| f23cfe1107 | |||
| f9d9b5fbaa | |||
| b3209dc7ee | |||
| 31c1b35173 | |||
| 1e1b18f860 | |||
| de0280367f | |||
| 5d4328a139 | |||
| c8b14b816f | |||
| 125bf16605 | |||
| 73a803f2e8 | |||
| 1bcd1a044f | |||
| 1e0b72de22 |
@@ -82,6 +82,14 @@ def enableMinifyInReleaseBuilds = (findProperty('android.enableMinifyInReleaseBu
|
|||||||
def jscFlavor = 'io.github.react-native-community:jsc-android:2026004.+'
|
def jscFlavor = 'io.github.react-native-community:jsc-android:2026004.+'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
|
// @generated begin @rnmapbox/maps-libcpp - expo prebuild (DO NOT MODIFY) sync-e24830a5a3e854b398227dfe9630aabfaa1cadd1
|
||||||
|
packagingOptions {
|
||||||
|
pickFirst 'lib/x86/libc++_shared.so'
|
||||||
|
pickFirst 'lib/x86_64/libc++_shared.so'
|
||||||
|
pickFirst 'lib/arm64-v8a/libc++_shared.so'
|
||||||
|
pickFirst 'lib/armeabi-v7a/libc++_shared.so'
|
||||||
|
}
|
||||||
|
// @generated end @rnmapbox/maps-libcpp
|
||||||
ndkVersion rootProject.ext.ndkVersion
|
ndkVersion rootProject.ext.ndkVersion
|
||||||
|
|
||||||
buildToolsVersion rootProject.ext.buildToolsVersion
|
buildToolsVersion rootProject.ext.buildToolsVersion
|
||||||
@@ -92,8 +100,8 @@ android {
|
|||||||
applicationId 'com.bip.hipmimobileapp'
|
applicationId 'com.bip.hipmimobileapp'
|
||||||
minSdkVersion rootProject.ext.minSdkVersion
|
minSdkVersion rootProject.ext.minSdkVersion
|
||||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||||
versionCode 1
|
versionCode 3
|
||||||
versionName "1.0.0"
|
versionName "1.0.1"
|
||||||
|
|
||||||
buildConfigField "String", "REACT_NATIVE_RELEASE_LEVEL", "\"${findProperty('reactNativeReleaseLevel') ?: 'stable'}\""
|
buildConfigField "String", "REACT_NATIVE_RELEASE_LEVEL", "\"${findProperty('reactNativeReleaseLevel') ?: 'stable'}\""
|
||||||
}
|
}
|
||||||
@@ -180,3 +188,5 @@ dependencies {
|
|||||||
implementation jscFlavor
|
implementation jscFlavor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
apply plugin: 'com.google.gms.google-services'
|
||||||
29
android/app/google-services.json
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"project_info": {
|
||||||
|
"project_number": "608461535079",
|
||||||
|
"project_id": "hipmi-badung-connect",
|
||||||
|
"storage_bucket": "hipmi-badung-connect.firebasestorage.app"
|
||||||
|
},
|
||||||
|
"client": [
|
||||||
|
{
|
||||||
|
"client_info": {
|
||||||
|
"mobilesdk_app_id": "1:608461535079:android:4ff12ddc283fb3746761c2",
|
||||||
|
"android_client_info": {
|
||||||
|
"package_name": "com.bip.hipmimobileapp"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"oauth_client": [],
|
||||||
|
"api_key": [
|
||||||
|
{
|
||||||
|
"current_key": "AIzaSyBiDtIk3Q9zffFwIdJ5cjqY7e4390JGSkM"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"services": {
|
||||||
|
"appinvite_service": {
|
||||||
|
"other_platform_oauth_client": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"configuration_version": "1"
|
||||||
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
||||||
<uses-permission android:name="android.permission.CAMERA"/>
|
<uses-permission android:name="android.permission.CAMERA"/>
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||||
@@ -14,6 +16,10 @@
|
|||||||
</intent>
|
</intent>
|
||||||
</queries>
|
</queries>
|
||||||
<application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="true" android:theme="@style/AppTheme" android:supportsRtl="true" android:enableOnBackInvokedCallback="false">
|
<application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="true" android:theme="@style/AppTheme" android:supportsRtl="true" android:enableOnBackInvokedCallback="false">
|
||||||
|
<meta-data android:name="com.google.firebase.messaging.default_notification_color" android:resource="@color/notification_icon_color"/>
|
||||||
|
<meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/notification_icon"/>
|
||||||
|
<meta-data android:name="expo.modules.notifications.default_notification_color" android:resource="@color/notification_icon_color"/>
|
||||||
|
<meta-data android:name="expo.modules.notifications.default_notification_icon" android:resource="@drawable/notification_icon"/>
|
||||||
<meta-data android:name="expo.modules.updates.ENABLED" android:value="false"/>
|
<meta-data android:name="expo.modules.updates.ENABLED" android:value="false"/>
|
||||||
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_CHECK_ON_LAUNCH" android:value="ALWAYS"/>
|
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_CHECK_ON_LAUNCH" android:value="ALWAYS"/>
|
||||||
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_LAUNCH_WAIT_MS" android:value="0"/>
|
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_LAUNCH_WAIT_MS" android:value="0"/>
|
||||||
@@ -29,6 +35,12 @@
|
|||||||
<data android:scheme="hipmimobile"/>
|
<data android:scheme="hipmimobile"/>
|
||||||
<data android:scheme="exp+hipmi-mobile"/>
|
<data android:scheme="exp+hipmi-mobile"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
<intent-filter android:autoVerify="true" data-generated="true">
|
||||||
|
<action android:name="android.intent.action.VIEW"/>
|
||||||
|
<data android:scheme="https" android:host="cld-dkr-staging-hipmi.wibudev.com" android:pathPrefix="/"/>
|
||||||
|
<category android:name="android.intent.category.BROWSABLE"/>
|
||||||
|
<category android:name="android.intent.category.DEFAULT"/>
|
||||||
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
BIN
android/app/src/main/res/drawable-hdpi/notification_icon.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 55 KiB |
BIN
android/app/src/main/res/drawable-mdpi/notification_icon.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 30 KiB |
BIN
android/app/src/main/res/drawable-xhdpi/notification_icon.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 84 KiB |
BIN
android/app/src/main/res/drawable-xxhdpi/notification_icon.png
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 154 KiB |
BIN
android/app/src/main/res/drawable-xxxhdpi/notification_icon.png
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
|
Before Width: | Height: | Size: 151 KiB After Width: | Height: | Size: 231 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 89 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 30 KiB |
@@ -3,4 +3,5 @@
|
|||||||
<color name="iconBackground">#ffffff</color>
|
<color name="iconBackground">#ffffff</color>
|
||||||
<color name="colorPrimary">#023c69</color>
|
<color name="colorPrimary">#023c69</color>
|
||||||
<color name="colorPrimaryDark">#ffffff</color>
|
<color name="colorPrimaryDark">#ffffff</color>
|
||||||
|
<color name="notification_icon_color">#ffffff</color>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">HIPMI BADUNG</string>
|
<string name="app_name">HIPMI Badung Connect</string>
|
||||||
<string name="expo_system_ui_user_interface_style" translatable="false">automatic</string>
|
<string name="expo_system_ui_user_interface_style" translatable="false">automatic</string>
|
||||||
<string name="expo_splash_screen_resize_mode" translatable="false">contain</string>
|
<string name="expo_splash_screen_resize_mode" translatable="false">contain</string>
|
||||||
<string name="expo_splash_screen_status_bar_translucent" translatable="false">false</string>
|
<string name="expo_splash_screen_status_bar_translucent" translatable="false">false</string>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ buildscript {
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
|
classpath 'com.google.gms:google-services:4.4.1'
|
||||||
classpath('com.android.tools.build:gradle')
|
classpath('com.android.tools.build:gradle')
|
||||||
classpath('com.facebook.react:react-native-gradle-plugin')
|
classpath('com.facebook.react:react-native-gradle-plugin')
|
||||||
classpath('org.jetbrains.kotlin:kotlin-gradle-plugin')
|
classpath('org.jetbrains.kotlin:kotlin-gradle-plugin')
|
||||||
@@ -22,3 +23,25 @@ allprojects {
|
|||||||
|
|
||||||
apply plugin: "expo-root-project"
|
apply plugin: "expo-root-project"
|
||||||
apply plugin: "com.facebook.react.rootproject"
|
apply plugin: "com.facebook.react.rootproject"
|
||||||
|
// @generated begin @rnmapbox/maps-v2-maven - expo prebuild (DO NOT MODIFY) sync-d4ccbfdff48fdba3138b02a8ba41b9722af001d8
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
url 'https://api.mapbox.com/downloads/v2/releases/maven'
|
||||||
|
// Authentication is no longer required as per Mapbox's removal of download token requirement
|
||||||
|
// See: https://github.com/mapbox/mapbox-maps-flutter/issues/775
|
||||||
|
// Keeping this as optional for backward compatibility
|
||||||
|
def token = project.properties['MAPBOX_DOWNLOADS_TOKEN'] ?: System.getenv('RNMAPBOX_MAPS_DOWNLOAD_TOKEN')
|
||||||
|
if (token) {
|
||||||
|
authentication { basic(BasicAuthentication) }
|
||||||
|
credentials {
|
||||||
|
username = 'mapbox'
|
||||||
|
password = token
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// @generated end @rnmapbox/maps-v2-maven
|
||||||
@@ -31,7 +31,7 @@ extensions.configure(com.facebook.react.ReactSettingsExtension) { ex ->
|
|||||||
}
|
}
|
||||||
expoAutolinking.useExpoModules()
|
expoAutolinking.useExpoModules()
|
||||||
|
|
||||||
rootProject.name = 'HIPMI BADUNG'
|
rootProject.name = 'HIPMI Badung Connect'
|
||||||
|
|
||||||
expoAutolinking.useExpoVersionCatalog()
|
expoAutolinking.useExpoVersionCatalog()
|
||||||
|
|
||||||
|
|||||||
@@ -1,61 +1,92 @@
|
|||||||
// app.config.js
|
// app.config.js
|
||||||
require('dotenv').config();
|
require("dotenv").config();
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'HIPMI BADUNG',
|
name: "HIPMI Badung Connect",
|
||||||
slug: 'hipmi-mobile',
|
slug: "hipmi-mobile",
|
||||||
version: '1.0.0',
|
version: "1.0.1",
|
||||||
orientation: 'portrait',
|
orientation: "portrait",
|
||||||
icon: './assets/images/icon.png',
|
icon: "./assets/images/icon.png",
|
||||||
scheme: 'hipmimobile',
|
scheme: "hipmimobile",
|
||||||
userInterfaceStyle: 'automatic',
|
userInterfaceStyle: "automatic",
|
||||||
newArchEnabled: true,
|
newArchEnabled: true,
|
||||||
|
|
||||||
ios: {
|
ios: {
|
||||||
supportsTablet: true,
|
supportsTablet: true,
|
||||||
bundleIdentifier: 'com.anonymous.hipmi-mobile',
|
bundleIdentifier: "com.anonymous.hipmi-mobile",
|
||||||
|
googleServicesFile: "./ios/HIPMIBadungConnect/GoogleService-Info.plist",
|
||||||
infoPlist: {
|
infoPlist: {
|
||||||
ITSAppUsesNonExemptEncryption: false,
|
ITSAppUsesNonExemptEncryption: false,
|
||||||
|
NSLocationWhenInUseUsageDescription:
|
||||||
|
"Aplikasi membutuhkan akses lokasi untuk menampilkan peta.",
|
||||||
},
|
},
|
||||||
|
associatedDomains: ["applinks:cld-dkr-staging-hipmi.wibudev.com"],
|
||||||
|
buildNumber: "15",
|
||||||
},
|
},
|
||||||
|
|
||||||
android: {
|
android: {
|
||||||
|
googleServicesFile: "./google-services.json",
|
||||||
adaptiveIcon: {
|
adaptiveIcon: {
|
||||||
foregroundImage: './assets/images/splash-icon.png',
|
foregroundImage: "./assets/images/splash-icon.png",
|
||||||
backgroundColor: '#ffffff',
|
backgroundColor: "#ffffff",
|
||||||
},
|
},
|
||||||
edgeToEdgeEnabled: true,
|
edgeToEdgeEnabled: true,
|
||||||
package: 'com.bip.hipmimobileapp',
|
package: "com.bip.hipmimobileapp",
|
||||||
|
versionCode: 3,
|
||||||
// softwareKeyboardLayoutMode: 'resize', // option: untuk mengatur keyboard pada room chst collaboration
|
// softwareKeyboardLayoutMode: 'resize', // option: untuk mengatur keyboard pada room chst collaboration
|
||||||
|
intentFilters: [
|
||||||
|
{
|
||||||
|
action: "VIEW",
|
||||||
|
autoVerify: true, // wajib untuk App Links
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
scheme: "https",
|
||||||
|
host: "cld-dkr-staging-hipmi.wibudev.com",
|
||||||
|
pathPrefix: "/",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
category: ["BROWSABLE", "DEFAULT"],
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
web: {
|
web: {
|
||||||
bundler: 'metro',
|
bundler: "metro",
|
||||||
output: 'static',
|
output: "static",
|
||||||
favicon: './assets/images/favicon.png',
|
favicon: "./assets/images/favicon.png",
|
||||||
},
|
},
|
||||||
|
|
||||||
plugins: [
|
plugins: [
|
||||||
'expo-router',
|
"expo-router",
|
||||||
'expo-web-browser',
|
"expo-web-browser",
|
||||||
[
|
[
|
||||||
'expo-splash-screen',
|
"expo-splash-screen",
|
||||||
{
|
{
|
||||||
image: './assets/images/splash-icon.png',
|
image: "./assets/images/splash-icon.png",
|
||||||
imageWidth: 200,
|
imageWidth: 200,
|
||||||
resizeMode: 'contain',
|
resizeMode: "contain",
|
||||||
backgroundColor: '#ffffff',
|
backgroundColor: "#ffffff",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'expo-camera',
|
"expo-camera",
|
||||||
{
|
{
|
||||||
cameraPermission: 'Allow $(PRODUCT_NAME) to access your camera',
|
cameraPermission: "Allow $(PRODUCT_NAME) to access your camera",
|
||||||
microphonePermission: 'Allow $(PRODUCT_NAME) to access your microphone',
|
microphonePermission: "Allow $(PRODUCT_NAME) to access your microphone",
|
||||||
recordAudioAndroid: true,
|
recordAudioAndroid: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'expo-font',
|
"expo-font",
|
||||||
|
"@rnmapbox/maps",
|
||||||
|
"@react-native-firebase/app",
|
||||||
|
[
|
||||||
|
"expo-notifications",
|
||||||
|
{
|
||||||
|
icon: "./assets/images/icon.png",
|
||||||
|
color: "#ffffff",
|
||||||
|
iosDisplayInForeground: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
experiments: {
|
experiments: {
|
||||||
@@ -65,7 +96,7 @@ export default {
|
|||||||
extra: {
|
extra: {
|
||||||
router: {},
|
router: {},
|
||||||
eas: {
|
eas: {
|
||||||
projectId: '5cf15964-4889-4755-b8ed-b99c61d614d1',
|
projectId: "5cf15964-4889-4755-b8ed-b99c61d614d1",
|
||||||
},
|
},
|
||||||
// Tambahkan environment variables ke sini
|
// Tambahkan environment variables ke sini
|
||||||
API_BASE_URL: process.env.API_BASE_URL,
|
API_BASE_URL: process.env.API_BASE_URL,
|
||||||
|
|||||||
@@ -10,6 +10,13 @@ export default function UserLayout() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Stack screenOptions={HeaderStyles}>
|
<Stack screenOptions={HeaderStyles}>
|
||||||
|
<Stack.Screen
|
||||||
|
name="delete-account"
|
||||||
|
options={{
|
||||||
|
title: "Hapus Akun",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name="waiting-room"
|
name="waiting-room"
|
||||||
options={{
|
options={{
|
||||||
@@ -588,6 +595,13 @@ export default function UserLayout() {
|
|||||||
headerLeft: () => <BackButton />,
|
headerLeft: () => <BackButton />,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="forum/terms"
|
||||||
|
options={{
|
||||||
|
title: "Syarat & Ketentuan Forum",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
{/* ========== Maps Section ========= */}
|
{/* ========== Maps Section ========= */}
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ export default function CollaborationCreate() {
|
|||||||
<TextAreaCustom
|
<TextAreaCustom
|
||||||
required
|
required
|
||||||
label="Keuntungan Proyek"
|
label="Keuntungan Proyek"
|
||||||
placeholder="Masukan keuntungan proyek"
|
placeholder="Masukan keuntungan proyek, contoh: Meningkatkan relasi bisnis , menjamin kualitas produk, meningkatkan kinerja dan lain lain"
|
||||||
showCount
|
showCount
|
||||||
maxLength={1000}
|
maxLength={1000}
|
||||||
value={data?.benefit}
|
value={data?.benefit}
|
||||||
|
|||||||
111
app/(application)/(user)/delete-account.tsx
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
import {
|
||||||
|
AlertDefaultSystem,
|
||||||
|
BaseBox,
|
||||||
|
ButtonCustom,
|
||||||
|
CenterCustom,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
|
import { apiDeleteUser } from "@/service/api-client/api-user";
|
||||||
|
import { Image } from "expo-image";
|
||||||
|
import { useLocalSearchParams } from "expo-router/build/hooks";
|
||||||
|
import { useState } from "react";
|
||||||
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
|
export default function DeleteAccount() {
|
||||||
|
const { token, logout, user } = useAuth();
|
||||||
|
const { phone } = useLocalSearchParams();
|
||||||
|
const [text, setText] = useState("");
|
||||||
|
const [isLoading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
const deleteAccount = async () => {
|
||||||
|
if (text !== "Delete Account") {
|
||||||
|
return Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Ketik 'Delete Account' untuk menghapus akun",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
AlertDefaultSystem({
|
||||||
|
title: "Anda yakin akan menghapus akun ini?",
|
||||||
|
message:
|
||||||
|
"Semua data yang pernah anda buat akan terhapus secara permanen !",
|
||||||
|
textLeft: "Batal",
|
||||||
|
textRight: "Ya",
|
||||||
|
onPressRight: async () => {
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
const response = await apiDeleteUser({ id: user?.id as string });
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
console.log("RESPONSE >> ", response);
|
||||||
|
Toast.show({
|
||||||
|
type: "success",
|
||||||
|
text1: "Akun berhasil dihapus",
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
logout();
|
||||||
|
setLoading(false);
|
||||||
|
}, 2000);
|
||||||
|
} else {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Gagal menghapus akun",
|
||||||
|
});
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("ERROR >> ", error);
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ViewWrapper>
|
||||||
|
<StackCustom>
|
||||||
|
<BaseBox>
|
||||||
|
<StackCustom>
|
||||||
|
<CenterCustom>
|
||||||
|
<Image
|
||||||
|
source={require("@/assets/images/constants/logo-hipmi.png")}
|
||||||
|
style={{
|
||||||
|
width: 150,
|
||||||
|
height: 150,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</CenterCustom>
|
||||||
|
<TextCustom align="center">
|
||||||
|
Anda akan menghapus akun dengan nomor +{phone}
|
||||||
|
</TextCustom>
|
||||||
|
<TextCustom align="center">
|
||||||
|
Ketik 'Delete Account' untuk menghapus akun
|
||||||
|
</TextCustom>
|
||||||
|
<TextInputCustom
|
||||||
|
value={text}
|
||||||
|
onChangeText={setText}
|
||||||
|
placeholder="Ketik 'Delete Account'"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ButtonCustom
|
||||||
|
backgroundColor="red"
|
||||||
|
textColor="white"
|
||||||
|
onPress={deleteAccount}
|
||||||
|
isLoading={isLoading}
|
||||||
|
disabled={isLoading}
|
||||||
|
>
|
||||||
|
Submit
|
||||||
|
</ButtonCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
</StackCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import {
|
import {
|
||||||
BaseBox,
|
BaseBox,
|
||||||
Grid,
|
Grid,
|
||||||
@@ -7,11 +8,60 @@ import {
|
|||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import { MainColor } from "@/constants/color-palet";
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { apiDonationGetInvoiceById } from "@/service/api-client/api-donation";
|
||||||
import { GStyles } from "@/styles/global-styles";
|
import { GStyles } from "@/styles/global-styles";
|
||||||
|
import { dateTimeView } from "@/utils/dateTimeView";
|
||||||
|
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
|
||||||
import { FontAwesome6 } from "@expo/vector-icons";
|
import { FontAwesome6 } from "@expo/vector-icons";
|
||||||
import dayjs from "dayjs";
|
import { useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useCallback, useState } from "react";
|
||||||
|
|
||||||
export default function DonasiFailed() {
|
export default function DonasiFailed() {
|
||||||
|
const { id, invoiceId } = useLocalSearchParams();
|
||||||
|
const [data, setData] = useState<any>(null);
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
onLoadData();
|
||||||
|
}, [id, invoiceId])
|
||||||
|
);
|
||||||
|
|
||||||
|
const onLoadData = async () => {
|
||||||
|
try {
|
||||||
|
const response = await apiDonationGetInvoiceById({
|
||||||
|
id: invoiceId as string,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("[DATA]", JSON.stringify(response.data, null, 2));
|
||||||
|
setData(response.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const listData = [
|
||||||
|
{
|
||||||
|
label: "Bank",
|
||||||
|
value: (data && data?.MasterBank?.namaBank) || "-",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Rekening Penerima",
|
||||||
|
value: (data && data?.MasterBank?.namaAkun) || "-",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "No Rekening",
|
||||||
|
value: (data && data?.MasterBank?.norek) || "-",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Jumlah Donasi",
|
||||||
|
value: (data && formatCurrencyDisplay(data?.nominal)) || "-",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Tanggal",
|
||||||
|
value: (data && dateTimeView({ date: data?.createdAt })) || "-",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ViewWrapper>
|
<ViewWrapper>
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
@@ -58,26 +108,3 @@ export default function DonasiFailed() {
|
|||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const listData = [
|
|
||||||
{
|
|
||||||
label: "Bank",
|
|
||||||
value: " BCA",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Rekening Penerima",
|
|
||||||
value: "Himpunan Pengusaha Muda Indonesia",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "No Rekening",
|
|
||||||
value: "2304235678854332",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Jumlah Donasi",
|
|
||||||
value: "Rp. 750.000",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Tanggal",
|
|
||||||
value: `${dayjs(new Date()).format("DD/MM/YYYY")}`,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ export default function DonationInvoice() {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<TextCustom size="xlarge" bold color="yellow">
|
<TextCustom size="xlarge" bold color="yellow">
|
||||||
{data?.DonasiMaster_Bank?.norek}
|
{data?.MasterBank?.norek}
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
<Grid.Col
|
<Grid.Col
|
||||||
@@ -131,7 +131,7 @@ export default function DonationInvoice() {
|
|||||||
alignItems: "flex-end",
|
alignItems: "flex-end",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CopyButton textToCopy={data?.DonasiMaster_Bank?.norek} />
|
<CopyButton textToCopy={data?.MasterBank?.norek} />
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
</Grid>
|
</Grid>
|
||||||
</BaseBox>
|
</BaseBox>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import {
|
import {
|
||||||
BaseBox,
|
BaseBox,
|
||||||
Grid,
|
Grid,
|
||||||
@@ -7,11 +8,60 @@ import {
|
|||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import { MainColor } from "@/constants/color-palet";
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { apiDonationGetInvoiceById } from "@/service/api-client/api-donation";
|
||||||
import { GStyles } from "@/styles/global-styles";
|
import { GStyles } from "@/styles/global-styles";
|
||||||
|
import { dateTimeView } from "@/utils/dateTimeView";
|
||||||
|
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
|
||||||
import { FontAwesome6 } from "@expo/vector-icons";
|
import { FontAwesome6 } from "@expo/vector-icons";
|
||||||
import dayjs from "dayjs";
|
import { useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useCallback, useState } from "react";
|
||||||
|
|
||||||
export default function DonationSuccess() {
|
export default function DonationSuccess() {
|
||||||
|
const { id, invoiceId } = useLocalSearchParams();
|
||||||
|
const [data, setData] = useState<any>(null);
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
onLoadData();
|
||||||
|
}, [id, invoiceId])
|
||||||
|
);
|
||||||
|
|
||||||
|
const onLoadData = async () => {
|
||||||
|
try {
|
||||||
|
const response = await apiDonationGetInvoiceById({
|
||||||
|
id: invoiceId as string,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("[DATA]", JSON.stringify(response.data, null, 2));
|
||||||
|
setData(response.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const listData = [
|
||||||
|
{
|
||||||
|
label: "Bank",
|
||||||
|
value: (data && data?.MasterBank?.namaBank) || "-",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Rekening Penerima",
|
||||||
|
value: (data && data?.MasterBank?.namaAkun) || "-",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "No Rekening",
|
||||||
|
value: (data && data?.MasterBank?.norek) || "-",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Jumlah Donasi",
|
||||||
|
value: (data && formatCurrencyDisplay(data?.nominal)) || "-",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Tanggal",
|
||||||
|
value: (data && dateTimeView({ date: data?.createdAt })) || "-",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ViewWrapper>
|
<ViewWrapper>
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
@@ -59,25 +109,4 @@ export default function DonationSuccess() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const listData = [
|
|
||||||
{
|
|
||||||
label: "Bank",
|
|
||||||
value: " BCA",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Rekening Penerima",
|
|
||||||
value: "Himpunan Pengusaha Muda Indonesia",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "No Rekening",
|
|
||||||
value: "2304235678854332",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Jumlah Donasi",
|
|
||||||
value: "Rp. 750.000",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Tanggal",
|
|
||||||
value: `${dayjs(new Date()).format("DD/MM/YYYY")}`,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|||||||
@@ -1,17 +1,71 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import {
|
import {
|
||||||
BaseBox,
|
BaseBox,
|
||||||
ButtonCenteredOnly,
|
ButtonCenteredOnly,
|
||||||
Grid,
|
Grid,
|
||||||
InformationBox,
|
InformationBox,
|
||||||
|
LoaderCustom,
|
||||||
StackCustom,
|
StackCustom,
|
||||||
TextCustom,
|
TextCustom,
|
||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
|
import {
|
||||||
|
apiDonationDisbursementOfFundsListById,
|
||||||
|
apiDonationGetOne,
|
||||||
|
} from "@/service/api-client/api-donation";
|
||||||
|
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { router, useLocalSearchParams } from "expo-router";
|
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
|
import _ from "lodash";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
|
||||||
export default function DonationFundDisbursement() {
|
export default function DonationFundDisbursement() {
|
||||||
const { id } = useLocalSearchParams();
|
const { id } = useLocalSearchParams();
|
||||||
|
|
||||||
|
const [data, setData] = useState({
|
||||||
|
totalPencairan: 0,
|
||||||
|
akumulasiPencairan: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
const [listData, setListData] = React.useState<any[] | null>(null);
|
||||||
|
const [loadData, setLoadData] = React.useState(false);
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
React.useCallback(() => {
|
||||||
|
onLoadData();
|
||||||
|
}, [id])
|
||||||
|
);
|
||||||
|
|
||||||
|
const onLoadData = async () => {
|
||||||
|
try {
|
||||||
|
setLoadData(true);
|
||||||
|
|
||||||
|
const responseData = await apiDonationGetOne({
|
||||||
|
id: id as string,
|
||||||
|
category: "permanent",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (responseData.success) {
|
||||||
|
setData({
|
||||||
|
totalPencairan: responseData.data.totalPencairan,
|
||||||
|
akumulasiPencairan: responseData.data.akumulasiPencairan,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const responseList = await apiDonationDisbursementOfFundsListById({
|
||||||
|
id: id as string,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (responseList.success) {
|
||||||
|
setListData(responseList.data);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
} finally {
|
||||||
|
setLoadData(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ViewWrapper>
|
<ViewWrapper>
|
||||||
@@ -20,39 +74,41 @@ export default function DonationFundDisbursement() {
|
|||||||
<Grid>
|
<Grid>
|
||||||
<Grid.Col span={6}>
|
<Grid.Col span={6}>
|
||||||
<TextCustom bold color="yellow">
|
<TextCustom bold color="yellow">
|
||||||
Rp. 0
|
Rp. {formatCurrencyDisplay(data?.totalPencairan)}
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
<TextCustom size="small">Total Pencairan Dana</TextCustom>
|
<TextCustom size="small">Total Pencairan Dana</TextCustom>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
<Grid.Col span={6}>
|
<Grid.Col span={6}>
|
||||||
<TextCustom bold color="yellow">
|
<TextCustom bold color="yellow">
|
||||||
0 kali
|
{data?.akumulasiPencairan} kali
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
<TextCustom size="small">Akumulasi Pencairan</TextCustom>
|
<TextCustom size="small">Akumulasi Pencairan</TextCustom>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
</Grid>
|
</Grid>
|
||||||
</BaseBox>
|
</BaseBox>
|
||||||
|
|
||||||
{Array.from({ length: 10 }).map((_, index) => (
|
{loadData ? (
|
||||||
|
<LoaderCustom />
|
||||||
|
) : _.isEmpty(listData) ? (
|
||||||
|
<TextCustom align="center" color="gray">
|
||||||
|
Belum ada data
|
||||||
|
</TextCustom>
|
||||||
|
) : (
|
||||||
|
listData?.map((item, index) => (
|
||||||
<BaseBox key={index}>
|
<BaseBox key={index}>
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.Col span={8}>
|
<Grid.Col span={8}>
|
||||||
<TextCustom bold>Pencairan ke - {index + 1}</TextCustom>
|
<TextCustom bold>{item?.title}</TextCustom>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
<Grid.Col span={4} style={{ alignItems: "flex-end" }}>
|
<Grid.Col span={4} style={{ alignItems: "flex-end" }}>
|
||||||
<TextCustom>{dayjs().format("DD MMM YYYY")}</TextCustom>
|
<TextCustom>{dayjs(item?.createdAt).format("DD MMM YYYY")}</TextCustom>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
</Grid>
|
</Grid>
|
||||||
<TextCustom>
|
<TextCustom>{item?.deskripsi}</TextCustom>
|
||||||
Lorem ipsum dolor sit amet consectetur adipisicing elit.
|
|
||||||
Nesciunt dolor ad sit? Eaque rem nihil natus, id, esse possimus
|
|
||||||
perferendis provident velit illo consectetur distinctio ab
|
|
||||||
accusantium quis earum omnis!
|
|
||||||
</TextCustom>
|
|
||||||
<ButtonCenteredOnly
|
<ButtonCenteredOnly
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
router.navigate(`/(application)/(file)/${id}`);
|
router.navigate(`/(application)/(image)/preview-image/${item?.imageId}`);
|
||||||
}}
|
}}
|
||||||
icon="file-text"
|
icon="file-text"
|
||||||
>
|
>
|
||||||
@@ -60,7 +116,8 @@ export default function DonationFundDisbursement() {
|
|||||||
</ButtonCenteredOnly>
|
</ButtonCenteredOnly>
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
</BaseBox>
|
</BaseBox>
|
||||||
))}
|
))
|
||||||
|
)}
|
||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -16,20 +16,19 @@ import Donation_ComponentInfoFundrising from "@/screens/Donation/ComponentInfoFu
|
|||||||
import Donation_ComponentStoryFunrising from "@/screens/Donation/ComponentStoryFunrising";
|
import Donation_ComponentStoryFunrising from "@/screens/Donation/ComponentStoryFunrising";
|
||||||
import Donation_ProgressSection from "@/screens/Donation/ProgressSection";
|
import Donation_ProgressSection from "@/screens/Donation/ProgressSection";
|
||||||
import { apiDonationGetOne } from "@/service/api-client/api-donation";
|
import { apiDonationGetOne } from "@/service/api-client/api-donation";
|
||||||
|
import { countDownAndCondition } from "@/utils/countDownAndCondition";
|
||||||
import {
|
import {
|
||||||
router,
|
router,
|
||||||
Stack,
|
Stack,
|
||||||
useFocusEffect,
|
useFocusEffect,
|
||||||
useLocalSearchParams,
|
useLocalSearchParams,
|
||||||
} from "expo-router";
|
} from "expo-router";
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
|
|
||||||
export default function DonasiDetailBeranda() {
|
export default function DonasiDetailBeranda() {
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
const { id } = useLocalSearchParams();
|
const { id } = useLocalSearchParams();
|
||||||
console.log("ID ", id);
|
|
||||||
const [openDrawer, setOpenDrawer] = useState(false);
|
const [openDrawer, setOpenDrawer] = useState(false);
|
||||||
|
|
||||||
const [data, setData] = useState<any>();
|
const [data, setData] = useState<any>();
|
||||||
|
|
||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
@@ -45,21 +44,41 @@ export default function DonasiDetailBeranda() {
|
|||||||
category: "permanent",
|
category: "permanent",
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("[RES GET ONE]", JSON.stringify(response.data, null, 2));
|
|
||||||
|
|
||||||
setData(response.data);
|
setData(response.data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("[ERROR]", error);
|
console.log("[ERROR]", error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const [value, setValue] = useState({
|
||||||
|
sisa: 0,
|
||||||
|
reminder: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
updateCountDown();
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
const updateCountDown = () => {
|
||||||
|
const countDown = countDownAndCondition({
|
||||||
|
duration: data?.DonasiMaster_Durasi?.name,
|
||||||
|
publishTime: data?.publishTime,
|
||||||
|
});
|
||||||
|
|
||||||
|
setValue({
|
||||||
|
sisa: countDown.durationDay,
|
||||||
|
reminder: countDown.reminder,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const buttonSection = (
|
const buttonSection = (
|
||||||
<>
|
<>
|
||||||
<BoxButtonOnFooter>
|
<BoxButtonOnFooter>
|
||||||
<ButtonCustom
|
<ButtonCustom
|
||||||
|
disabled={value?.reminder}
|
||||||
onPress={() => router.navigate(`/donation/${id}/(transaction-flow)`)}
|
onPress={() => router.navigate(`/donation/${id}/(transaction-flow)`)}
|
||||||
>
|
>
|
||||||
Donasi
|
{value?.reminder ? "Waktu berakhir" : "Donasi"}
|
||||||
</ButtonCustom>
|
</ButtonCustom>
|
||||||
</BoxButtonOnFooter>
|
</BoxButtonOnFooter>
|
||||||
</>
|
</>
|
||||||
@@ -80,8 +99,10 @@ export default function DonasiDetailBeranda() {
|
|||||||
<ViewWrapper footerComponent={buttonSection}>
|
<ViewWrapper footerComponent={buttonSection}>
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
<Donation_ComponentBoxDetailData
|
<Donation_ComponentBoxDetailData
|
||||||
|
sisaHari={value.sisa}
|
||||||
|
reminder={value.reminder}
|
||||||
data={data}
|
data={data}
|
||||||
bottomSection={<Donation_ProgressSection id={id as string} />}
|
bottomSection={<Donation_ProgressSection id={id as string} progres={Number(data?.progres) || 0} />}
|
||||||
/>
|
/>
|
||||||
<Donation_ComponentInfoFundrising dataAuthor={data?.Author} />
|
<Donation_ComponentInfoFundrising dataAuthor={data?.Author} />
|
||||||
<Donation_ComponentStoryFunrising
|
<Donation_ComponentStoryFunrising
|
||||||
|
|||||||
@@ -1,19 +1,62 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import {
|
import {
|
||||||
BaseBox,
|
BaseBox,
|
||||||
Grid,
|
Grid,
|
||||||
|
LoaderCustom,
|
||||||
|
Spacing,
|
||||||
StackCustom,
|
StackCustom,
|
||||||
TextCustom,
|
TextCustom,
|
||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import { MainColor } from "@/constants/color-palet";
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { apiAdminDonationListOfDonaturById } from "@/service/api-admin/api-admin-donation";
|
||||||
|
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
|
||||||
import { FontAwesome6 } from "@expo/vector-icons";
|
import { FontAwesome6 } from "@expo/vector-icons";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
|
import { useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { useCallback, useState } from "react";
|
||||||
|
|
||||||
export default function Donation_ListOfDonatur() {
|
export default function Donation_ListOfDonatur() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const [listData, setListData] = useState<any[] | null>(null);
|
||||||
|
const [loadData, setLoadData] = useState(false);
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
onLoadData();
|
||||||
|
}, [id])
|
||||||
|
);
|
||||||
|
|
||||||
|
const onLoadData = async () => {
|
||||||
|
try {
|
||||||
|
setLoadData(true);
|
||||||
|
const response = await apiAdminDonationListOfDonaturById({
|
||||||
|
id: id as string,
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
setListData(response.data);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
} finally {
|
||||||
|
setLoadData(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ViewWrapper>
|
<ViewWrapper>
|
||||||
{Array.from({ length: 10 }).map((_, index) => (
|
{loadData ? (
|
||||||
|
<LoaderCustom />
|
||||||
|
) : _.isEmpty(listData) ? (
|
||||||
|
<TextCustom bold align="center">
|
||||||
|
Belum ada donatur
|
||||||
|
</TextCustom>
|
||||||
|
) : (
|
||||||
|
listData?.map((item: any, index: number) => (
|
||||||
<BaseBox key={index}>
|
<BaseBox key={index}>
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.Col
|
<Grid.Col
|
||||||
@@ -27,20 +70,24 @@ export default function Donation_ListOfDonatur() {
|
|||||||
/>
|
/>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
<Grid.Col span={9}>
|
<Grid.Col span={9}>
|
||||||
<StackCustom gap={"xs"}>
|
|
||||||
<TextCustom bold size="large">
|
<TextCustom bold size="large">
|
||||||
Username
|
{item?.Author?.username || "-"}
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
<TextCustom>Berdonas sebesar </TextCustom>
|
<Spacing/>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<TextCustom size={"small"}>Berdonas sebesar </TextCustom>
|
||||||
<TextCustom bold size="large" color="yellow">
|
<TextCustom bold size="large" color="yellow">
|
||||||
Rp. 100.000
|
Rp. {formatCurrencyDisplay(item?.nominal)}
|
||||||
|
</TextCustom>
|
||||||
|
<TextCustom>
|
||||||
|
{dayjs(item?.createdAt).format("DD MMM YYYY, HH:mm")}
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
<TextCustom>{dayjs().format("DD MMM YYYY")}</TextCustom>
|
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
</Grid>
|
</Grid>
|
||||||
</BaseBox>
|
</BaseBox>
|
||||||
))}
|
))
|
||||||
|
)}
|
||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -74,8 +74,6 @@ export default function UserEventConfirmation() {
|
|||||||
userId: user?.id as string,
|
userId: user?.id as string,
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("[RES CONFIRMATION]", JSON.stringify(response, null, 2));
|
|
||||||
|
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
setData(response.data?.dataEvent);
|
setData(response.data?.dataEvent);
|
||||||
setPeserta(response.data?.peserta);
|
setPeserta(response.data?.peserta);
|
||||||
@@ -142,11 +140,11 @@ export default function UserEventConfirmation() {
|
|||||||
return (
|
return (
|
||||||
<TamplateBox data={data}>
|
<TamplateBox data={data}>
|
||||||
<TamplateText
|
<TamplateText
|
||||||
text={`Event telah selesai, anda terdaftar sebagai peserta dan${
|
text={`Event telah selesai, anda terdaftar sebagai peserta dan ${
|
||||||
konfirmasi
|
konfirmasi
|
||||||
? "Anda telah mengonfirmasi kehadiran."
|
? "Anda telah mengonfirmasi kehadiran."
|
||||||
: "Anda tidak mengonfirmasi kehadiran."
|
: "Anda tidak mengonfirmasi kehadiran."
|
||||||
}. Terima kasih atas perhatian dan minat Anda. Kami berharap dapat bertemu di acara kami berikutnya.`}
|
} Terima kasih atas perhatian dan minat Anda. Kami berharap dapat bertemu di acara kami berikutnya.`}
|
||||||
/>
|
/>
|
||||||
<BackToOtherPath
|
<BackToOtherPath
|
||||||
path="event"
|
path="event"
|
||||||
@@ -173,14 +171,16 @@ export default function UserEventConfirmation() {
|
|||||||
if (isWithinConfirmationWindow && peserta === true) {
|
if (isWithinConfirmationWindow && peserta === true) {
|
||||||
if (konfirmasi === false) {
|
if (konfirmasi === false) {
|
||||||
return (
|
return (
|
||||||
<TamplateBox data={data}>
|
<UserParticipan_And_DuringEvent
|
||||||
<TamplateText text="Konfirmasi Kehadiran" />
|
id={data.id}
|
||||||
</TamplateBox>
|
userId={user?.id as string}
|
||||||
|
data={data}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<TamplateBox data={data}>
|
<TamplateBox data={data}>
|
||||||
<TamplateText text="Anda telah mengonfirmasi kehadiran." />
|
<TamplateText text="Terimakasih telah mengonfirmasi kehadiran. Silahkan lihat peserta lain pada halaman event atau kembali ke halaman home. Selamat menikmati acara dan selamat berpartisipasi." />
|
||||||
<BackToOtherPath
|
<BackToOtherPath
|
||||||
path="event"
|
path="event"
|
||||||
id={data.id}
|
id={data.id}
|
||||||
@@ -192,7 +192,7 @@ export default function UserEventConfirmation() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<TamplateBox data={data}>
|
<TamplateBox data={data}>
|
||||||
<TamplateText text="Anda terdaftar sebagai peserta. Konfirmasi kehadiran dibuka 1 jam sebelum acara dimulai." />
|
<TamplateText text="Anda telah terdaftar sebagai peserta pada Event ini. Konfirmasi kehadiran dibuka 1 jam sebelum acara dimulai." />
|
||||||
<BackToOtherPath
|
<BackToOtherPath
|
||||||
path="event"
|
path="event"
|
||||||
id={data.id}
|
id={data.id}
|
||||||
@@ -261,16 +261,16 @@ export default function UserEventConfirmation() {
|
|||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
options={{
|
options={{
|
||||||
title: "Konfirmasi Event",
|
title: "Konfirmasi Event",
|
||||||
headerLeft: () => (
|
// headerLeft: () => (
|
||||||
<Ionicons
|
// <Ionicons
|
||||||
name="arrow-back"
|
// name="arrow-back"
|
||||||
size={20}
|
// size={20}
|
||||||
color={MainColor.yellow}
|
// color={MainColor.yellow}
|
||||||
onPress={() =>
|
// onPress={() =>
|
||||||
router.navigate("/(application)/(user)/event/create")
|
// router.navigate("/(application)/(user)/event/create")
|
||||||
}
|
// }
|
||||||
/>
|
// />
|
||||||
),
|
// ),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<ViewWrapper>{handlerReturn()}</ViewWrapper>
|
<ViewWrapper>{handlerReturn()}</ViewWrapper>
|
||||||
@@ -326,7 +326,7 @@ const TamplateBox = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const TamplateText = ({ text }: { text: string }) => {
|
const TamplateText = ({ text }: { text: React.ReactNode }) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TextCustom align="center">{text}</TextCustom>
|
<TextCustom align="center">{text}</TextCustom>
|
||||||
@@ -442,7 +442,7 @@ const NotStarted_And_UserNotParticipan = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 🟡 ZONA ACARA BERLANGSUNG
|
// 🟡 ZONA ACARA BERLANGSUNG
|
||||||
// Acara sedang berlangsung & belum terdaftar
|
// Acara sedang berlangsung & belum terdaftar & user harus join dan konfirmasi
|
||||||
const UserNotParticipan_And_DuringEvent = ({
|
const UserNotParticipan_And_DuringEvent = ({
|
||||||
id,
|
id,
|
||||||
userId,
|
userId,
|
||||||
@@ -464,8 +464,6 @@ const UserNotParticipan_And_DuringEvent = ({
|
|||||||
category: "join_and_confirm",
|
category: "join_and_confirm",
|
||||||
});
|
});
|
||||||
|
|
||||||
// console.log("[RES JOIN & CONFIRMATION EVENT]", response);
|
|
||||||
|
|
||||||
if (!response.success) {
|
if (!response.success) {
|
||||||
Toast.show({
|
Toast.show({
|
||||||
type: "error",
|
type: "error",
|
||||||
@@ -498,3 +496,59 @@ const UserNotParticipan_And_DuringEvent = ({
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// 🟡 ZONA ACARA BERLANGSUN
|
||||||
|
// User sudah terdaftar & Event sedang berlangsung & user harus konfirmasi
|
||||||
|
const UserParticipan_And_DuringEvent = ({
|
||||||
|
id,
|
||||||
|
userId,
|
||||||
|
data,
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
userId: string;
|
||||||
|
data: DataEvent;
|
||||||
|
}) => {
|
||||||
|
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const handlerSubmit = async () => {
|
||||||
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
|
||||||
|
const response = await apiEventConfirmationAction({
|
||||||
|
id: id as string,
|
||||||
|
userId: userId as string,
|
||||||
|
category: "confirmation",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.success) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Anda gagal konfirmasi",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toast.show({
|
||||||
|
type: "success",
|
||||||
|
text1: "Anda berhasil konfirmasi",
|
||||||
|
});
|
||||||
|
router.navigate(`/(application)/(user)/event/${id}/publish`);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR JOIN & CONFIRMATION EVENT]", error);
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<TamplateBox data={data}>
|
||||||
|
<TamplateText text="Anda sudah terdaftar sebagai peserta & Event sedang berlangsung. Silahkan konfirmasi kehadiran" />
|
||||||
|
|
||||||
|
<ButtonCustom onPress={() => handlerSubmit()} isLoading={isLoading}>
|
||||||
|
Konfirmasi
|
||||||
|
</ButtonCustom>
|
||||||
|
</TamplateBox>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import {
|
|||||||
import { apiMasterEventType } from "@/service/api-client/api-master";
|
import { apiMasterEventType } from "@/service/api-client/api-master";
|
||||||
import { DateTimePickerEvent } from "@react-native-community/datetimepicker";
|
import { DateTimePickerEvent } from "@react-native-community/datetimepicker";
|
||||||
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
import React, { useCallback, useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import Toast from "react-native-toast-message";
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function EventEdit() {
|
export default function EventEdit() {
|
||||||
@@ -55,6 +55,7 @@ export default function EventEdit() {
|
|||||||
try {
|
try {
|
||||||
setIsLoadData(true);
|
setIsLoadData(true);
|
||||||
const response = await apiEventGetOne({ id: id as string });
|
const response = await apiEventGetOne({ id: id as string });
|
||||||
|
console.log("[DATA BY ID]", JSON.stringify(response, null, 2));
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
setData(response.data);
|
setData(response.data);
|
||||||
setSelectedDate(new Date(response.data.tanggal));
|
setSelectedDate(new Date(response.data.tanggal));
|
||||||
@@ -209,7 +210,7 @@ export default function EventEdit() {
|
|||||||
minimumDate={new Date(Date.now())}
|
minimumDate={new Date(Date.now())}
|
||||||
label="Tanggal & Waktu Mulai"
|
label="Tanggal & Waktu Mulai"
|
||||||
required
|
required
|
||||||
value={selectedDate as any}
|
value={selectedDate}
|
||||||
onChange={(date: any) => {
|
onChange={(date: any) => {
|
||||||
setSelectedDate(date as any);
|
setSelectedDate(date as any);
|
||||||
}}
|
}}
|
||||||
@@ -254,7 +255,6 @@ export default function EventEdit() {
|
|||||||
placeholder="Masukkan deskripsi event"
|
placeholder="Masukkan deskripsi event"
|
||||||
required
|
required
|
||||||
showCount
|
showCount
|
||||||
maxLength={100}
|
|
||||||
value={data?.deskripsi}
|
value={data?.deskripsi}
|
||||||
onChangeText={(value) => setData({ ...data, deskripsi: value })}
|
onChangeText={(value) => setData({ ...data, deskripsi: value })}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -11,29 +11,30 @@ import {
|
|||||||
apiEventGetOne,
|
apiEventGetOne,
|
||||||
apiEventListOfParticipants,
|
apiEventListOfParticipants,
|
||||||
} from "@/service/api-client/api-event";
|
} from "@/service/api-client/api-event";
|
||||||
import { useLocalSearchParams } from "expo-router";
|
import dayjs, { Dayjs } from "dayjs";
|
||||||
import { useEffect, useState } from "react";
|
import { useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { useCallback, useState } from "react";
|
||||||
import { View } from "react-native";
|
import { View } from "react-native";
|
||||||
|
|
||||||
export default function EventListOfParticipants() {
|
export default function EventListOfParticipants() {
|
||||||
const { id } = useLocalSearchParams();
|
const { id } = useLocalSearchParams();
|
||||||
const [startDate, setStartDate] = useState();
|
const [startDate, setStartDate] = useState<Dayjs | undefined>();
|
||||||
const [listData, setListData] = useState([]);
|
const [listData, setListData] = useState<any[] | null>(null);
|
||||||
const [isLoadData, setIsLoadData] = useState(false);
|
const [loadtData, setLoadData] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
handlerLoadData();
|
handlerLoadData();
|
||||||
}, [id]);
|
}, [id])
|
||||||
|
);
|
||||||
|
|
||||||
const handlerLoadData = () => {
|
const handlerLoadData = () => {
|
||||||
try {
|
try {
|
||||||
setIsLoadData(true);
|
|
||||||
onLoadData();
|
onLoadData();
|
||||||
onLoadList();
|
onLoadList();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("[ERROR]", error);
|
console.log("[ERROR]", error);
|
||||||
} finally {
|
|
||||||
setIsLoadData(false);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -41,7 +42,8 @@ export default function EventListOfParticipants() {
|
|||||||
try {
|
try {
|
||||||
const response = await apiEventGetOne({ id: id as string });
|
const response = await apiEventGetOne({ id: id as string });
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
setStartDate(response.data.tanggal);
|
const date = dayjs(response.data.tanggal);
|
||||||
|
setStartDate(date);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("[ERROR]", error);
|
console.log("[ERROR]", error);
|
||||||
@@ -50,30 +52,36 @@ export default function EventListOfParticipants() {
|
|||||||
|
|
||||||
const onLoadList = async () => {
|
const onLoadList = async () => {
|
||||||
try {
|
try {
|
||||||
|
setLoadData(true);
|
||||||
const response = await apiEventListOfParticipants({ id: id as string });
|
const response = await apiEventListOfParticipants({ id: id as string });
|
||||||
|
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
setListData(response.data);
|
setListData(response.data);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("[ERROR]", error);
|
console.log("[ERROR]", error);
|
||||||
|
} finally {
|
||||||
|
setLoadData(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ViewWrapper>
|
<ViewWrapper>
|
||||||
{isLoadData ? (
|
{loadtData && !listData ? (
|
||||||
<LoaderCustom />
|
<LoaderCustom />
|
||||||
) : listData.length === 0 ? (
|
) : _.isEmpty(listData) ? (
|
||||||
<TextCustom align="center">Belum ada peserta</TextCustom>
|
<TextCustom align="center" color="gray">
|
||||||
|
Belum ada peserta
|
||||||
|
</TextCustom>
|
||||||
) : (
|
) : (
|
||||||
listData.map((item: any, index: number) => (
|
listData?.map((item: any, index: number) => (
|
||||||
<BaseBox key={index}>
|
<BaseBox key={index}>
|
||||||
<AvatarUsernameAndOtherComponent
|
<AvatarUsernameAndOtherComponent
|
||||||
avatar={item?.User?.Profile?.imageId}
|
avatar={item?.User?.Profile?.imageId}
|
||||||
name={item?.User?.username}
|
name={item?.User?.username}
|
||||||
avatarHref={`/profile/${item?.User?.Profile?.id}`}
|
avatarHref={`/profile/${item?.User?.Profile?.id}`}
|
||||||
rightComponent={
|
rightComponent={
|
||||||
new Date().getTime() > new Date(startDate as any).getTime() ? (
|
startDate && startDate.subtract(1, "hour").diff(dayjs()) < 0 ? (
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
justifyContent: "flex-end",
|
justifyContent: "flex-end",
|
||||||
|
|||||||
@@ -71,8 +71,6 @@ export default function EventDetailPublish() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("[participans]", isParticipant);
|
|
||||||
|
|
||||||
const handlePress = (item: IMenuDrawerItem) => {
|
const handlePress = (item: IMenuDrawerItem) => {
|
||||||
console.log("PATH ", item.path);
|
console.log("PATH ", item.path);
|
||||||
router.navigate(item.path as any);
|
router.navigate(item.path as any);
|
||||||
@@ -139,7 +137,7 @@ export default function EventDetailPublish() {
|
|||||||
<>
|
<>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
options={{
|
options={{
|
||||||
title: `Event publish`,
|
title: `Event Publish`,
|
||||||
headerLeft: () => <LeftButtonCustom />,
|
headerLeft: () => <LeftButtonCustom />,
|
||||||
headerRight: () => <DotButton onPress={() => setOpenDrawer(true)} />,
|
headerRight: () => <DotButton onPress={() => setOpenDrawer(true)} />,
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ export default function EventCreate() {
|
|||||||
const response = await apiEventCreate(newData);
|
const response = await apiEventCreate(newData);
|
||||||
console.log("Response", JSON.stringify(response, null, 2));
|
console.log("Response", JSON.stringify(response, null, 2));
|
||||||
|
|
||||||
router.navigate("/event/status");
|
router.replace("/event/status");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -118,6 +118,7 @@ export default function EventCreate() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const buttonSubmit = (
|
const buttonSubmit = (
|
||||||
<ButtonCustom
|
<ButtonCustom
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
@@ -144,7 +145,7 @@ export default function EventCreate() {
|
|||||||
label: item.name,
|
label: item.name,
|
||||||
value: item.id,
|
value: item.id,
|
||||||
}))}
|
}))}
|
||||||
value={data?.eventMaster_TipeAcaraId || ""}
|
value={data?.eventMaster_TipeAcaraId || null}
|
||||||
onChange={(value: any) =>
|
onChange={(value: any) =>
|
||||||
setData({ ...data, eventMaster_TipeAcaraId: value })
|
setData({ ...data, eventMaster_TipeAcaraId: value })
|
||||||
}
|
}
|
||||||
@@ -191,7 +192,7 @@ export default function EventCreate() {
|
|||||||
placeholder="Masukkan deskripsi event"
|
placeholder="Masukkan deskripsi event"
|
||||||
required
|
required
|
||||||
showCount
|
showCount
|
||||||
maxLength={1000}
|
value={data?.deskripsi || ""}
|
||||||
onChangeText={(value: any) =>
|
onChangeText={(value: any) =>
|
||||||
setData({ ...data, deskripsi: value })
|
setData({ ...data, deskripsi: value })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,12 @@ import {
|
|||||||
TextAreaCustom,
|
TextAreaCustom,
|
||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
|
import AlertWarning from "@/components/Alert/AlertWarning";
|
||||||
import { apiForumGetOne, apiForumUpdate } from "@/service/api-client/api-forum";
|
import { apiForumGetOne, apiForumUpdate } from "@/service/api-client/api-forum";
|
||||||
|
import { isBadContent } from "@/utils/badWordsIndonesia";
|
||||||
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useState } from "react";
|
||||||
|
import { Alert } from "react-native";
|
||||||
import Toast from "react-native-toast-message";
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function ForumEdit() {
|
export default function ForumEdit() {
|
||||||
@@ -43,6 +46,12 @@ export default function ForumEdit() {
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isBadContent(text)) {
|
||||||
|
AlertWarning({});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
const response = await apiForumUpdate({
|
const response = await apiForumUpdate({
|
||||||
|
|||||||
@@ -1,142 +1,12 @@
|
|||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import {
|
import View_Forumku from "@/screens/Forum/ViewForumku";
|
||||||
AvatarComp,
|
import View_Forumku2 from "@/screens/Forum/ViewForumku2";
|
||||||
ButtonCustom,
|
|
||||||
CenterCustom,
|
|
||||||
DrawerCustom,
|
|
||||||
FloatingButton,
|
|
||||||
Grid,
|
|
||||||
LoaderCustom,
|
|
||||||
StackCustom,
|
|
||||||
TextCustom,
|
|
||||||
ViewWrapper,
|
|
||||||
} from "@/components";
|
|
||||||
import { useAuth } from "@/hooks/use-auth";
|
|
||||||
import Forum_BoxDetailSection from "@/screens/Forum/DiscussionBoxSection";
|
|
||||||
import Forum_MenuDrawerBerandaSection from "@/screens/Forum/MenuDrawerSection.tsx/MenuBeranda";
|
|
||||||
import { apiForumGetAll } from "@/service/api-client/api-forum";
|
|
||||||
import { apiUser } from "@/service/api-client/api-user";
|
|
||||||
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
|
||||||
import _ from "lodash";
|
|
||||||
import { useCallback, useState } from "react";
|
|
||||||
|
|
||||||
export default function Forumku() {
|
export default function Forumku() {
|
||||||
const { id } = useLocalSearchParams();
|
|
||||||
const { user } = useAuth();
|
|
||||||
const [openDrawer, setOpenDrawer] = useState(false);
|
|
||||||
const [status, setStatus] = useState("");
|
|
||||||
const [listData, setListData] = useState<any | null>(null);
|
|
||||||
const [dataUser, setDataUser] = useState<any | null>(null);
|
|
||||||
const [loadingGetList, setLoadingGetList] = useState(false);
|
|
||||||
|
|
||||||
useFocusEffect(
|
|
||||||
useCallback(() => {
|
|
||||||
onLoadData();
|
|
||||||
onLoadDataProfile(id as string);
|
|
||||||
}, [id])
|
|
||||||
);
|
|
||||||
|
|
||||||
const onLoadDataProfile = async (id: string) => {
|
|
||||||
try {
|
|
||||||
const response = await apiUser(id);
|
|
||||||
|
|
||||||
setDataUser(response.data);
|
|
||||||
} catch (error) {
|
|
||||||
console.log("[ERROR]", error);
|
|
||||||
} finally {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onLoadData = async () => {
|
|
||||||
try {
|
|
||||||
setLoadingGetList(true);
|
|
||||||
const response = await apiForumGetAll({
|
|
||||||
search: "",
|
|
||||||
authorId: id as string,
|
|
||||||
});
|
|
||||||
|
|
||||||
setListData(response.data);
|
|
||||||
} catch (error) {
|
|
||||||
console.log("[ERROR]", error);
|
|
||||||
} finally {
|
|
||||||
setLoadingGetList(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ViewWrapper
|
{/* <View_Forumku /> */}
|
||||||
floatingButton={
|
<View_Forumku2 />
|
||||||
user?.id === id && (
|
|
||||||
<FloatingButton
|
|
||||||
onPress={() =>
|
|
||||||
router.navigate("/(application)/(user)/forum/create")
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<StackCustom>
|
|
||||||
<CenterCustom>
|
|
||||||
<AvatarComp
|
|
||||||
fileId={dataUser?.Profile?.imageId}
|
|
||||||
href={`/(application)/(image)/preview-image/${dataUser?.Profile?.imageId}`}
|
|
||||||
size="xl"
|
|
||||||
/>
|
|
||||||
</CenterCustom>
|
|
||||||
|
|
||||||
<Grid>
|
|
||||||
<Grid.Col span={6}>
|
|
||||||
<TextCustom bold truncate>
|
|
||||||
@{dataUser?.username || "-"}
|
|
||||||
</TextCustom>
|
|
||||||
<TextCustom>{listData?.length || "0"} postingan</TextCustom>
|
|
||||||
</Grid.Col>
|
|
||||||
<Grid.Col span={6} style={{ alignItems: "flex-end" }}>
|
|
||||||
<ButtonCustom href={`/profile/${dataUser?.Profile?.id}`}>
|
|
||||||
Kunjungi Profile
|
|
||||||
</ButtonCustom>
|
|
||||||
</Grid.Col>
|
|
||||||
</Grid>
|
|
||||||
{loadingGetList ? (
|
|
||||||
<LoaderCustom />
|
|
||||||
) : _.isEmpty(listData) ? (
|
|
||||||
<TextCustom> Tidak ada diskusi</TextCustom>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
{listData?.map((item: any, index: number) => (
|
|
||||||
<Forum_BoxDetailSection
|
|
||||||
isRightComponent={false}
|
|
||||||
key={index}
|
|
||||||
data={item}
|
|
||||||
isTruncate={true}
|
|
||||||
href={`/forum/${item.id}`}
|
|
||||||
onSetData={(value) => {
|
|
||||||
setOpenDrawer(value.setOpenDrawer);
|
|
||||||
setStatus(value.setStatus);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</StackCustom>
|
|
||||||
</ViewWrapper>
|
|
||||||
|
|
||||||
{/* Drawer Komponen Eksternal */}
|
|
||||||
<DrawerCustom
|
|
||||||
height={"auto"}
|
|
||||||
isVisible={openDrawer}
|
|
||||||
closeDrawer={() => setOpenDrawer(false)}
|
|
||||||
>
|
|
||||||
<Forum_MenuDrawerBerandaSection
|
|
||||||
id={id as string}
|
|
||||||
status={status}
|
|
||||||
setIsDrawerOpen={() => {
|
|
||||||
setOpenDrawer(false);
|
|
||||||
}}
|
|
||||||
authorId={id as string}
|
|
||||||
/>
|
|
||||||
</DrawerCustom>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
TextCustom,
|
TextCustom,
|
||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
|
import AlertWarning from "@/components/Alert/AlertWarning";
|
||||||
import { useAuth } from "@/hooks/use-auth";
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
import Forum_CommentarBoxSection from "@/screens/Forum/CommentarBoxSection";
|
import Forum_CommentarBoxSection from "@/screens/Forum/CommentarBoxSection";
|
||||||
import Forum_BoxDetailSection from "@/screens/Forum/DiscussionBoxSection";
|
import Forum_BoxDetailSection from "@/screens/Forum/DiscussionBoxSection";
|
||||||
@@ -18,9 +19,11 @@ import {
|
|||||||
apiForumGetOne,
|
apiForumGetOne,
|
||||||
apiForumUpdateStatus,
|
apiForumUpdateStatus,
|
||||||
} from "@/service/api-client/api-forum";
|
} from "@/service/api-client/api-forum";
|
||||||
|
import { isBadContent } from "@/utils/badWordsIndonesia";
|
||||||
import { useFocusEffect, useLocalSearchParams } from "expo-router";
|
import { useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { useCallback, useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
|
import { Alert } from "react-native";
|
||||||
|
|
||||||
interface CommentProps {
|
interface CommentProps {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -110,11 +113,15 @@ export default function ForumDetail() {
|
|||||||
|
|
||||||
// Create Commentar
|
// Create Commentar
|
||||||
const handlerCreateCommentar = async () => {
|
const handlerCreateCommentar = async () => {
|
||||||
|
if (isBadContent(text)) {
|
||||||
|
AlertWarning({});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const newData = {
|
const newData = {
|
||||||
comment: text,
|
comment: text,
|
||||||
authorId: user?.id,
|
authorId: user?.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setLoadingComment(true);
|
setLoadingComment(true);
|
||||||
const response = await apiForumCreateComment({
|
const response = await apiForumCreateComment({
|
||||||
@@ -223,6 +230,7 @@ export default function ForumDetail() {
|
|||||||
>
|
>
|
||||||
<Forum_MenuDrawerBerandaSection
|
<Forum_MenuDrawerBerandaSection
|
||||||
id={dataId}
|
id={dataId}
|
||||||
|
authorUsername={data?.Author?.username as string}
|
||||||
status={status}
|
status={status}
|
||||||
setIsDrawerOpen={() => {
|
setIsDrawerOpen={() => {
|
||||||
setOpenDrawer(false);
|
setOpenDrawer(false);
|
||||||
|
|||||||
@@ -2,12 +2,15 @@ import {
|
|||||||
BoxButtonOnFooter,
|
BoxButtonOnFooter,
|
||||||
ButtonCustom,
|
ButtonCustom,
|
||||||
TextAreaCustom,
|
TextAreaCustom,
|
||||||
ViewWrapper,
|
ViewWrapper
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
|
import AlertWarning from "@/components/Alert/AlertWarning";
|
||||||
import { useAuth } from "@/hooks/use-auth";
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
import { apiForumCreate } from "@/service/api-client/api-forum";
|
import { apiForumCreate } from "@/service/api-client/api-forum";
|
||||||
|
import { isBadContent } from "@/utils/badWordsIndonesia";
|
||||||
import { router } from "expo-router";
|
import { router } from "expo-router";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import { Alert } from "react-native";
|
||||||
import Toast from "react-native-toast-message";
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function ForumCreate() {
|
export default function ForumCreate() {
|
||||||
@@ -16,11 +19,16 @@ export default function ForumCreate() {
|
|||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
const handlerSubmit = async () => {
|
const handlerSubmit = async () => {
|
||||||
|
|
||||||
|
if (isBadContent(text)) {
|
||||||
|
AlertWarning({})
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const newData = {
|
const newData = {
|
||||||
diskusi: text,
|
diskusi: text,
|
||||||
authorId: user?.id,
|
authorId: user?.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
const response = await apiForumCreate({ data: newData });
|
const response = await apiForumCreate({ data: newData });
|
||||||
|
|||||||
@@ -1,129 +1,12 @@
|
|||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import {
|
import Forum_ViewBeranda from "@/screens/Forum/ViewBeranda";
|
||||||
AvatarComp,
|
import Forum_ViewBeranda2 from "@/screens/Forum/ViewBeranda2";
|
||||||
BackButton,
|
|
||||||
DrawerCustom,
|
|
||||||
LoaderCustom,
|
|
||||||
SearchInput,
|
|
||||||
TextCustom,
|
|
||||||
ViewWrapper,
|
|
||||||
} from "@/components";
|
|
||||||
import FloatingButton from "@/components/Button/FloatingButton";
|
|
||||||
import { useAuth } from "@/hooks/use-auth";
|
|
||||||
import Forum_BoxDetailSection from "@/screens/Forum/DiscussionBoxSection";
|
|
||||||
import Forum_MenuDrawerBerandaSection from "@/screens/Forum/MenuDrawerSection.tsx/MenuBeranda";
|
|
||||||
import { apiForumGetAll } from "@/service/api-client/api-forum";
|
|
||||||
import { apiUser } from "@/service/api-client/api-user";
|
|
||||||
import { router, Stack, useFocusEffect } from "expo-router";
|
|
||||||
import _ from "lodash";
|
|
||||||
import { useCallback, useState } from "react";
|
|
||||||
|
|
||||||
export default function Forum() {
|
export default function Forum() {
|
||||||
const [openDrawer, setOpenDrawer] = useState(false);
|
|
||||||
const [status, setStatus] = useState("");
|
|
||||||
const { user } = useAuth();
|
|
||||||
const [dataUser, setDataUser] = useState<any>();
|
|
||||||
const [listData, setListData] = useState<any[]>();
|
|
||||||
const [loadingGetList, setLoadingGetList] = useState(false);
|
|
||||||
const [search, setSearch] = useState("");
|
|
||||||
const [dataId, setDataId] = useState("");
|
|
||||||
const [authorId, setAuthorId] = useState("");
|
|
||||||
|
|
||||||
useFocusEffect(
|
|
||||||
useCallback(() => {
|
|
||||||
onLoadData();
|
|
||||||
onLoadDataProfile(user?.id as string);
|
|
||||||
}, [user?.id, search])
|
|
||||||
);
|
|
||||||
|
|
||||||
const onLoadDataProfile = async (id: string) => {
|
|
||||||
const response = await apiUser(id);
|
|
||||||
setDataUser(response.data);
|
|
||||||
};
|
|
||||||
|
|
||||||
const onLoadData = async () => {
|
|
||||||
try {
|
|
||||||
setLoadingGetList(true);
|
|
||||||
const response = await apiForumGetAll({ search: search });
|
|
||||||
|
|
||||||
setListData(response.data);
|
|
||||||
} catch (error) {
|
|
||||||
console.log("[ERROR]", error);
|
|
||||||
} finally {
|
|
||||||
setLoadingGetList(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Stack.Screen
|
{/* <Forum_ViewBeranda /> */}
|
||||||
options={{
|
<Forum_ViewBeranda2 />
|
||||||
title: "Forum",
|
|
||||||
headerLeft: () => <BackButton />,
|
|
||||||
headerRight: () => (
|
|
||||||
<AvatarComp
|
|
||||||
fileId={dataUser?.Profile?.imageId}
|
|
||||||
size="base"
|
|
||||||
href={`/forum/${user?.id}/forumku`}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ViewWrapper
|
|
||||||
headerComponent={
|
|
||||||
<SearchInput
|
|
||||||
placeholder="Cari topik diskusi"
|
|
||||||
onChangeText={(e) => setSearch(e)}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
floatingButton={
|
|
||||||
<FloatingButton
|
|
||||||
onPress={() =>
|
|
||||||
router.navigate("/(application)/(user)/forum/create")
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{loadingGetList ? (
|
|
||||||
<LoaderCustom />
|
|
||||||
) : _.isEmpty(listData) ? (
|
|
||||||
<TextCustom align="center" color="gray">
|
|
||||||
Tidak ada diskusi
|
|
||||||
</TextCustom>
|
|
||||||
) : (
|
|
||||||
listData?.map((e: any, i: number) => (
|
|
||||||
<Forum_BoxDetailSection
|
|
||||||
key={i}
|
|
||||||
data={e}
|
|
||||||
onSetData={() => {
|
|
||||||
setDataId(e.id);
|
|
||||||
setOpenDrawer(true);
|
|
||||||
setStatus(e.ForumMaster_StatusPosting?.status);
|
|
||||||
setAuthorId(e.Author?.id);
|
|
||||||
}}
|
|
||||||
isTruncate={true}
|
|
||||||
href={`/forum/${e.id}`}
|
|
||||||
isRightComponent={false}
|
|
||||||
/>
|
|
||||||
))
|
|
||||||
)}
|
|
||||||
</ViewWrapper>
|
|
||||||
|
|
||||||
<DrawerCustom
|
|
||||||
height={"auto"}
|
|
||||||
isVisible={openDrawer}
|
|
||||||
closeDrawer={() => setOpenDrawer(false)}
|
|
||||||
>
|
|
||||||
<Forum_MenuDrawerBerandaSection
|
|
||||||
id={dataId}
|
|
||||||
authorId={authorId}
|
|
||||||
status={status}
|
|
||||||
setIsDrawerOpen={() => {
|
|
||||||
setOpenDrawer(false);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</DrawerCustom>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
202
app/(application)/(user)/forum/terms.tsx
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
import {
|
||||||
|
BaseBox,
|
||||||
|
ButtonCustom,
|
||||||
|
CheckboxCustom,
|
||||||
|
NewWrapper,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
} from "@/components";
|
||||||
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
|
import { apiAcceptForumTerms } from "@/service/api-client/api-user";
|
||||||
|
import { GStyles } from "@/styles/global-styles";
|
||||||
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { View } from "react-native";
|
||||||
|
import { Text } from "react-native-paper";
|
||||||
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
|
export default function ForumSplash() {
|
||||||
|
const { user } = useAuth();
|
||||||
|
const [term, setTerm] = useState(false);
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
const respone = await apiAcceptForumTerms({
|
||||||
|
category: "Forum",
|
||||||
|
userId: user?.id as any,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (respone.success) {
|
||||||
|
Toast.show({
|
||||||
|
type: "success",
|
||||||
|
text1: "Berhasil",
|
||||||
|
text2: "Terima kasih telah menerima syarat & ketentuan forum ini",
|
||||||
|
});
|
||||||
|
|
||||||
|
router.replace("/(application)/forum");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Gagal",
|
||||||
|
text2: "Terjadi kesalahan, silahkan coba lagi",
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NewWrapper>
|
||||||
|
{/* <TextCustom bold>HIPMI Badung Connect</TextCustom> . */}
|
||||||
|
|
||||||
|
<BaseBox>
|
||||||
|
<StackCustom>
|
||||||
|
<TextCustom>
|
||||||
|
Dengan mengakses dan menggunakan Forum HIPMI Badung Connect, Anda
|
||||||
|
secara sadar menyetujui ketentuan berikut:
|
||||||
|
</TextCustom>
|
||||||
|
|
||||||
|
<TextCustom bold>
|
||||||
|
1. Dilarang keras memposting konten yang mengandung:
|
||||||
|
</TextCustom>
|
||||||
|
<View style={{ paddingInline: 10 }}>
|
||||||
|
{forumTerms1.map((term, index) => (
|
||||||
|
<View
|
||||||
|
key={index}
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: 10,
|
||||||
|
paddingBottom: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Ionicons name="radio-button-on" color={"white"} />
|
||||||
|
<TextCustom>{term.text}</TextCustom>
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<TextCustom bold>
|
||||||
|
2. Setiap pengguna bertanggung jawab penuh atas konten yang
|
||||||
|
diunggah. Konten yang melanggar ketentuan ini dapat dihapus kapan
|
||||||
|
saja tanpa pemberitahuan.
|
||||||
|
</TextCustom>
|
||||||
|
|
||||||
|
<TextCustom bold>
|
||||||
|
3. Jika Anda menemukan konten tidak pantas, segera:
|
||||||
|
</TextCustom>
|
||||||
|
<View style={{ paddingInline: 10 }}>
|
||||||
|
{forumTerms2.map((term, index) => (
|
||||||
|
<View
|
||||||
|
key={index}
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: 10,
|
||||||
|
paddingBottom: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Ionicons name="radio-button-on" color={"white"} />
|
||||||
|
<TextCustom>{term.text}</TextCustom>
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<TextCustom bold>
|
||||||
|
4. Gunakan fitur “Blokir Pengguna” di profil pengguna terkait
|
||||||
|
</TextCustom>
|
||||||
|
<View style={{ paddingInline: 10 }}>
|
||||||
|
{forumTerms3.map((term, index) => (
|
||||||
|
<View
|
||||||
|
key={index}
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: 10,
|
||||||
|
paddingBottom: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Ionicons name="radio-button-on" color={"white"} />
|
||||||
|
<TextCustom>{term.text}</TextCustom>
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<TextCustom>
|
||||||
|
Pelanggaran terhadap ketentuan ini berakibat{" "}
|
||||||
|
<TextCustom bold>pencabutan akses</TextCustom> ke Forum dan/atau{" "}
|
||||||
|
<TextCustom bold>pemblokiran akun secara permanen</TextCustom> tanpa
|
||||||
|
pemberitahuan lebih lanjut.
|
||||||
|
</TextCustom>
|
||||||
|
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
marginTop: 16,
|
||||||
|
marginBottom: 16,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CheckboxCustom value={term} onChange={() => setTerm(!term)} />
|
||||||
|
|
||||||
|
<Text style={GStyles.textLabel}>
|
||||||
|
Saya telah membaca dan menyetujui Syarat & Ketentuan Forum ini
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<ButtonCustom
|
||||||
|
disabled={!term || loading}
|
||||||
|
onPress={() => {
|
||||||
|
handleSubmit();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Lanjut
|
||||||
|
</ButtonCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
</NewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Data dalam format JSON (bisa juga diimpor dari file terpisah)
|
||||||
|
interface Term {
|
||||||
|
text: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const forumTerms1: Term[] = [
|
||||||
|
{
|
||||||
|
text: "Ujaran kebencian, diskriminasi, atau konten SARA (Suku, Agama, Ras, Antar-golongan)",
|
||||||
|
},
|
||||||
|
{ text: "Kata kasar, pelecehan, ancaman, atau bullying" },
|
||||||
|
{ text: "Pornografi, hoaks, spam, atau informasi menyesatkan" },
|
||||||
|
{ text: "Promosi aktivitas ilegal seperti perjudian atau narkoba" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const forumTerms2: Term[] = [
|
||||||
|
{
|
||||||
|
text: "Gunakan tombol “Laporkan” di setiap postingan, atau",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "Gunakan fitur “Blokir Pengguna” di profil pengguna terkait.",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const forumTerms3: Term[] = [
|
||||||
|
{
|
||||||
|
text: "Meninjau setiap laporan dalam waktu 24 jam",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "Menghapus konten yang melanggar",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "Memblokir akun pelanggar sesuai tingkat pelanggaran",
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -11,31 +11,52 @@ import Home_FeatureSection from "@/screens/Home/topFeatureSection";
|
|||||||
import { apiUser } from "@/service/api-client/api-user";
|
import { apiUser } from "@/service/api-client/api-user";
|
||||||
import { apiVersion } from "@/service/api-config";
|
import { apiVersion } from "@/service/api-config";
|
||||||
import { Ionicons } from "@expo/vector-icons";
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
import { Redirect, router, Stack } from "expo-router";
|
import { Redirect, router, Stack, useFocusEffect } from "expo-router";
|
||||||
import { useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
|
import { RefreshControl } from "react-native";
|
||||||
|
|
||||||
export default function Application() {
|
export default function Application() {
|
||||||
const { token, user } = useAuth();
|
const { token, user, userData } = useAuth();
|
||||||
|
|
||||||
const [data, setData] = useState<any>();
|
const [data, setData] = useState<any>();
|
||||||
|
const [refreshing, setRefreshing] = useState(false);
|
||||||
|
console.log("[User] >>", JSON.stringify(user?.id, null, 2));
|
||||||
|
|
||||||
useEffect(() => {
|
// ‼️ Untuk cek apakah: 1. user ada, 2. user punya profile, 3. accept temrs of forum nya ada atau tidak
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
onLoadData();
|
onLoadData();
|
||||||
checkVersion();
|
checkVersion();
|
||||||
}, []);
|
userData(token as string);
|
||||||
|
}, [user?.id, token])
|
||||||
|
);
|
||||||
|
|
||||||
async function onLoadData() {
|
async function onLoadData() {
|
||||||
const response = await apiUser(user?.id as string);
|
const response = await apiUser(user?.id as string);
|
||||||
console.log("Response profile >>", JSON.stringify(response?.data?.Profile, null, 2));
|
console.log(
|
||||||
|
"[Profile ID]>>",
|
||||||
|
JSON.stringify(response?.data?.Profile?.id, null, 2)
|
||||||
|
);
|
||||||
|
|
||||||
setData(response.data);
|
setData(response.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
const checkVersion = async () => {
|
const checkVersion = async () => {
|
||||||
const response = await apiVersion();
|
const response = await apiVersion();
|
||||||
console.log("Version >>", JSON.stringify(response.data, null, 2));
|
console.log("[Version] >>", JSON.stringify(response.data, null, 2));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onRefresh = useCallback(() => {
|
||||||
|
setRefreshing(true);
|
||||||
|
onLoadData();
|
||||||
|
checkVersion();
|
||||||
|
setRefreshing(false);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (user && user?.termsOfServiceAccepted === false) {
|
||||||
|
console.log("User is not accept term service");
|
||||||
|
return <Redirect href={`/terms-agreement`} />;
|
||||||
|
}
|
||||||
|
|
||||||
if (data && data?.active === false) {
|
if (data && data?.active === false) {
|
||||||
console.log("User is not active");
|
console.log("User is not active");
|
||||||
return <Redirect href={`/waiting-room`} />;
|
return <Redirect href={`/waiting-room`} />;
|
||||||
@@ -63,9 +84,10 @@ export default function Application() {
|
|||||||
),
|
),
|
||||||
headerRight: () => (
|
headerRight: () => (
|
||||||
<Ionicons
|
<Ionicons
|
||||||
|
disabled={true}
|
||||||
name="notifications"
|
name="notifications"
|
||||||
size={20}
|
size={20}
|
||||||
color={MainColor.yellow}
|
color={MainColor.placeholder}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
router.push("/notifications");
|
router.push("/notifications");
|
||||||
}}
|
}}
|
||||||
@@ -74,8 +96,16 @@ export default function Application() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<ViewWrapper
|
<ViewWrapper
|
||||||
|
refreshControl={
|
||||||
|
<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
|
||||||
|
}
|
||||||
footerComponent={
|
footerComponent={
|
||||||
<TabSection tabs={tabsHome(data?.Profile?.id as string)} />
|
<TabSection
|
||||||
|
tabs={tabsHome({
|
||||||
|
acceptedForumTermsAt: data?.acceptedForumTermsAt,
|
||||||
|
profileId: data?.Profile?.id,
|
||||||
|
})}
|
||||||
|
/>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
|
|||||||
@@ -1,23 +1,14 @@
|
|||||||
import {
|
import {
|
||||||
BaseBox,
|
|
||||||
FloatingButton,
|
FloatingButton,
|
||||||
Grid,
|
|
||||||
LoaderCustom,
|
LoaderCustom,
|
||||||
ProgressCustom,
|
ViewWrapper
|
||||||
StackCustom,
|
|
||||||
TextCustom,
|
|
||||||
ViewWrapper,
|
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import API_STRORAGE from "@/constants/base-url-api-strorage";
|
import NoDataText from "@/components/_ShareComponent/NoDataText";
|
||||||
import DUMMY_IMAGE from "@/constants/dummy-image-value";
|
import Investment_BoxBerandaSection from "@/screens/Invesment/BoxBerandaSection";
|
||||||
import { apiInvestmentGetAll } from "@/service/api-client/api-investment";
|
import { apiInvestmentGetAll } from "@/service/api-client/api-investment";
|
||||||
import { Ionicons } from "@expo/vector-icons";
|
|
||||||
import dayjs from "dayjs";
|
|
||||||
import { Image } from "expo-image";
|
|
||||||
import { router, useFocusEffect } from "expo-router";
|
import { router, useFocusEffect } from "expo-router";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useState } from "react";
|
||||||
import { View } from "react-native";
|
|
||||||
|
|
||||||
export default function InvestmentBursa() {
|
export default function InvestmentBursa() {
|
||||||
const [list, setList] = useState<any[] | null>(null);
|
const [list, setList] = useState<any[] | null>(null);
|
||||||
@@ -32,8 +23,10 @@ export default function InvestmentBursa() {
|
|||||||
const onLoadList = async () => {
|
const onLoadList = async () => {
|
||||||
try {
|
try {
|
||||||
setLoadingList(true);
|
setLoadingList(true);
|
||||||
const response = await apiInvestmentGetAll();
|
const response = await apiInvestmentGetAll({
|
||||||
console.log("[DATA LIST]", JSON.stringify(response.data, null, 2));
|
category: "bursa"
|
||||||
|
});
|
||||||
|
// console.log("[DATA LIST]", JSON.stringify(response.data, null, 2));
|
||||||
setList(response.data);
|
setList(response.data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("[ERROR]", error);
|
console.log("[ERROR]", error);
|
||||||
@@ -52,95 +45,12 @@ export default function InvestmentBursa() {
|
|||||||
{loadingList ? (
|
{loadingList ? (
|
||||||
<LoaderCustom />
|
<LoaderCustom />
|
||||||
) : _.isEmpty(list) ? (
|
) : _.isEmpty(list) ? (
|
||||||
<TextCustom>Belum ada data</TextCustom>
|
<NoDataText />
|
||||||
) : (
|
) : (
|
||||||
list?.map((item: any, index: number) => (
|
list?.map((item: any, index: number) => (
|
||||||
<BaseBox
|
<Investment_BoxBerandaSection id={item.id} data={item} key={index} />
|
||||||
key={index}
|
|
||||||
paddingTop={7}
|
|
||||||
paddingBottom={7}
|
|
||||||
href={`/investment/${item.id}`}
|
|
||||||
>
|
|
||||||
<Grid>
|
|
||||||
<Grid.Col span={5}>
|
|
||||||
<Image
|
|
||||||
source={
|
|
||||||
item && item.imageId
|
|
||||||
? API_STRORAGE.GET({ fileId: item.imageId })
|
|
||||||
: DUMMY_IMAGE.background
|
|
||||||
}
|
|
||||||
style={{ width: "auto", height: 100, borderRadius: 10 }}
|
|
||||||
/>
|
|
||||||
</Grid.Col>
|
|
||||||
<Grid.Col span={1}>
|
|
||||||
<View />
|
|
||||||
</Grid.Col>
|
|
||||||
<Grid.Col span={6}>
|
|
||||||
<StackCustom>
|
|
||||||
<TextCustom truncate={2}>{item.title}</TextCustom>
|
|
||||||
<ProgressCustom
|
|
||||||
label={`${item.progress}%`}
|
|
||||||
value={item.progress}
|
|
||||||
size="lg"
|
|
||||||
/>
|
|
||||||
{Number(item?.pencarianInvestor) -
|
|
||||||
dayjs().diff(dayjs(item.countDown), "days") <=
|
|
||||||
0 ? (
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
flexDirection: "row",
|
|
||||||
alignItems: "center",
|
|
||||||
gap: 5,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Ionicons
|
|
||||||
name="alert-circle-outline"
|
|
||||||
size={16}
|
|
||||||
color="red"
|
|
||||||
/>
|
|
||||||
<TextCustom color="red" size="small">
|
|
||||||
Periode Investasi Selesai
|
|
||||||
</TextCustom>
|
|
||||||
</View>
|
|
||||||
) : (
|
|
||||||
<TextCustom>
|
|
||||||
Sisa waktu:{" "}
|
|
||||||
{Number(item?.pencarianInvestor) -
|
|
||||||
dayjs().diff(dayjs(item.countDown), "days")}{" "}
|
|
||||||
hari
|
|
||||||
</TextCustom>
|
|
||||||
)}
|
|
||||||
</StackCustom>
|
|
||||||
</Grid.Col>
|
|
||||||
</Grid>
|
|
||||||
</BaseBox>
|
|
||||||
))
|
))
|
||||||
)}
|
)}
|
||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// <View style={{ padding: 20, gap: 16 }}>
|
|
||||||
// <TextCustom>Progress 70%</TextCustom>
|
|
||||||
// <ProgressCustom value={70} color="primary" size="md" />
|
|
||||||
|
|
||||||
// <TextCustom>Success Progress</TextCustom>
|
|
||||||
// <ProgressCustom value={40} color="success" size="lg" />
|
|
||||||
|
|
||||||
// <TextCustom>Warning Progress (small)</TextCustom>
|
|
||||||
// <ProgressCustom value={90} color="warning" size="sm" />
|
|
||||||
|
|
||||||
// <TextCustom>Error Indeterminate</TextCustom>
|
|
||||||
// <ProgressCustom value={null} color="error" size="md" />
|
|
||||||
|
|
||||||
// <TextCustom>Custom Radius</TextCustom>
|
|
||||||
// <ProgressCustom value={60} color="info" size="xl" radius={4} />
|
|
||||||
|
|
||||||
// <ProgressCustom value={70} color="primary" size="lg" />
|
|
||||||
|
|
||||||
// <ProgressCustom value={45} color="success" size="md" label="Halfway!" />
|
|
||||||
|
|
||||||
// <ProgressCustom value={90} color="warning" size="lg" showLabel={false} />
|
|
||||||
|
|
||||||
// <ProgressCustom value={null} color="error" size="sm" label="Loading..." />
|
|
||||||
// </View>;
|
|
||||||
|
|||||||
@@ -1,33 +1,80 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import {
|
import {
|
||||||
BaseBox,
|
BaseBox,
|
||||||
Grid,
|
Grid,
|
||||||
|
LoaderCustom,
|
||||||
ProgressCustom,
|
ProgressCustom,
|
||||||
Spacing,
|
Spacing,
|
||||||
StackCustom,
|
StackCustom,
|
||||||
TextCustom,
|
TextCustom,
|
||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import { router } from "expo-router";
|
import NoDataText from "@/components/_ShareComponent/NoDataText";
|
||||||
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
|
import {
|
||||||
|
apiInvestmentGetAll
|
||||||
|
} from "@/service/api-client/api-investment";
|
||||||
|
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
|
||||||
|
import { router, useFocusEffect } from "expo-router";
|
||||||
|
import _ from "lodash";
|
||||||
|
import React, { useCallback, useState } from "react";
|
||||||
import { View } from "react-native";
|
import { View } from "react-native";
|
||||||
|
|
||||||
export default function InvestmentMyHolding() {
|
export default function InvestmentMyHolding() {
|
||||||
|
const { user } = useAuth();
|
||||||
|
const [list, setList] = useState<any[] | null>(null);
|
||||||
|
const [loadingList, setLoadingList] = useState(false);
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
onLoadList();
|
||||||
|
}, [user?.id])
|
||||||
|
);
|
||||||
|
|
||||||
|
const onLoadList = async () => {
|
||||||
|
try {
|
||||||
|
setLoadingList(true);
|
||||||
|
const response = await apiInvestmentGetAll({
|
||||||
|
category: "my-holding",
|
||||||
|
authorId: user?.id,
|
||||||
|
});
|
||||||
|
console.log("[DATA LIST]", JSON.stringify(response.data, null, 2));
|
||||||
|
setList(response.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
} finally {
|
||||||
|
setLoadingList(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ViewWrapper hideFooter>
|
<ViewWrapper hideFooter>
|
||||||
{Array.from({ length: 10 }).map((_, index) => (
|
{loadingList ? (
|
||||||
<BaseBox key={index} paddingTop={7} paddingBottom={7} onPress={() => router.push(`/investment/${index}/(my-holding)/holding-${index}`)}>
|
<LoaderCustom />
|
||||||
|
) : _.isEmpty(list) ? (
|
||||||
|
<NoDataText />
|
||||||
|
) : (
|
||||||
|
list?.map((item, index) => (
|
||||||
|
<BaseBox
|
||||||
|
key={index}
|
||||||
|
paddingTop={7}
|
||||||
|
paddingBottom={7}
|
||||||
|
onPress={() =>
|
||||||
|
router.push(`/investment/${item?.id}/(my-holding)/${item?.id}`)
|
||||||
|
}
|
||||||
|
>
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.Col span={6}>
|
<Grid.Col span={6}>
|
||||||
<StackCustom gap={"xs"}>
|
<StackCustom gap={"xs"}>
|
||||||
<TextCustom truncate={2}>
|
<TextCustom truncate={2}>{item?.title}</TextCustom>
|
||||||
Title here : Lorem ipsum dolor sit amet consectetur
|
|
||||||
adipisicing elit. Omnis, exercitationem, sequi enim quod
|
|
||||||
distinctio maiores laudantium amet, quidem atque repellat sit
|
|
||||||
vitae qui aliquam est veritatis laborum eum voluptatum totam!
|
|
||||||
</TextCustom>
|
|
||||||
|
|
||||||
<Spacing height={5} />
|
<Spacing height={5} />
|
||||||
<TextCustom size="small">Rp. 7.500.000</TextCustom>
|
<TextCustom size="small">
|
||||||
<TextCustom size="small">300 Lembar</TextCustom>
|
Rp. {formatCurrencyDisplay(item?.nominal)}
|
||||||
|
</TextCustom>
|
||||||
|
<TextCustom size="small">
|
||||||
|
{item?.lembarTerbeli} Lembar
|
||||||
|
</TextCustom>
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
<Grid.Col span={1}>
|
<Grid.Col span={1}>
|
||||||
@@ -40,11 +87,16 @@ export default function InvestmentMyHolding() {
|
|||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ProgressCustom value={(index % 5) * 20} size="lg" />
|
<ProgressCustom
|
||||||
|
value={item?.progress}
|
||||||
|
label={`${item?.progress}%`}
|
||||||
|
size="lg"
|
||||||
|
/>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
</Grid>
|
</Grid>
|
||||||
</BaseBox>
|
</BaseBox>
|
||||||
))}
|
))
|
||||||
|
)}
|
||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
TextCustom,
|
TextCustom,
|
||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
|
import NoDataText from "@/components/_ShareComponent/NoDataText";
|
||||||
import { useAuth } from "@/hooks/use-auth";
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
import { apiInvestmentGetInvoice } from "@/service/api-client/api-investment";
|
import { apiInvestmentGetInvoice } from "@/service/api-client/api-investment";
|
||||||
import { GStyles } from "@/styles/global-styles";
|
import { GStyles } from "@/styles/global-styles";
|
||||||
@@ -74,7 +75,7 @@ export default function InvestmentTransaction() {
|
|||||||
{loadList ? (
|
{loadList ? (
|
||||||
<LoaderCustom />
|
<LoaderCustom />
|
||||||
) : _.isEmpty(list) ? (
|
) : _.isEmpty(list) ? (
|
||||||
<TextCustom>Tidak ada data</TextCustom>
|
<NoDataText/>
|
||||||
) : (
|
) : (
|
||||||
list.map((item: any, i: number) => (
|
list.map((item: any, i: number) => (
|
||||||
<BaseBox
|
<BaseBox
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import {
|
import {
|
||||||
BackButton,
|
BackButton,
|
||||||
BaseBox,
|
BaseBox,
|
||||||
@@ -13,17 +14,43 @@ import { IconDocument, IconEdit, IconNews } from "@/components/_Icon";
|
|||||||
import { IMenuDrawerItem } from "@/components/_Interface/types";
|
import { IMenuDrawerItem } from "@/components/_Interface/types";
|
||||||
import { MainColor } from "@/constants/color-palet";
|
import { MainColor } from "@/constants/color-palet";
|
||||||
import { ICON_SIZE_MEDIUM } from "@/constants/constans-value";
|
import { ICON_SIZE_MEDIUM } from "@/constants/constans-value";
|
||||||
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
import Invesment_ComponentBoxOnBottomDetail from "@/screens/Invesment/ComponentBoxOnBottomDetail";
|
import Invesment_ComponentBoxOnBottomDetail from "@/screens/Invesment/ComponentBoxOnBottomDetail";
|
||||||
import Invesment_DetailDataPublishSection from "@/screens/Invesment/DetailDataPublishSection";
|
import Invesment_DetailDataPublishSection from "@/screens/Invesment/DetailDataPublishSection";
|
||||||
|
import { apiInvestmentGetInvoice } from "@/service/api-client/api-investment";
|
||||||
|
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
|
||||||
import { AntDesign, MaterialIcons } from "@expo/vector-icons";
|
import { AntDesign, MaterialIcons } from "@expo/vector-icons";
|
||||||
import { router, Stack, useLocalSearchParams } from "expo-router";
|
import { router, Stack, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { useState } from "react";
|
import { useCallback, useState } from "react";
|
||||||
|
|
||||||
export default function InvestmentDetailHolding() {
|
export default function InvestmentDetailHolding() {
|
||||||
|
const { user } = useAuth();
|
||||||
const { id, status } = useLocalSearchParams();
|
const { id, status } = useLocalSearchParams();
|
||||||
const [openDrawerDraft, setOpenDrawerDraft] = useState(false);
|
const [openDrawerDraft, setOpenDrawerDraft] = useState(false);
|
||||||
const [openDrawerPublish, setOpenDrawerPublish] = useState(false);
|
const [openDrawerPublish, setOpenDrawerPublish] = useState(false);
|
||||||
|
const [data, setData] = useState<any>(null);
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
onLoadData();
|
||||||
|
}, [id, status])
|
||||||
|
);
|
||||||
|
|
||||||
|
const onLoadData = async () => {
|
||||||
|
try {
|
||||||
|
const response = await apiInvestmentGetInvoice({
|
||||||
|
id: id as string,
|
||||||
|
authorId: user?.id,
|
||||||
|
category: "invoice",
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("[DATA]", JSON.stringify(response.data, null, 2));
|
||||||
|
setData(response.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handlePressDraft = (item: IMenuDrawerItem) => {
|
const handlePressDraft = (item: IMenuDrawerItem) => {
|
||||||
console.log("PATH >> ", item.path);
|
console.log("PATH >> ", item.path);
|
||||||
@@ -39,7 +66,8 @@ export default function InvestmentDetailHolding() {
|
|||||||
|
|
||||||
const bottomSection = (
|
const bottomSection = (
|
||||||
<Invesment_ComponentBoxOnBottomDetail
|
<Invesment_ComponentBoxOnBottomDetail
|
||||||
id={id as string}
|
prospectusId={id as string}
|
||||||
|
id={data?.Investasi?.id as string}
|
||||||
status={"publish"}
|
status={"publish"}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@@ -64,10 +92,12 @@ export default function InvestmentDetailHolding() {
|
|||||||
<StackCustom gap={"xs"}>
|
<StackCustom gap={"xs"}>
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.Col span={6}>
|
<Grid.Col span={6}>
|
||||||
<TextCustom bold>Nila Transaksi</TextCustom>
|
<TextCustom bold>Nilai Transaksi</TextCustom>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
<Grid.Col span={6}>
|
<Grid.Col span={6}>
|
||||||
<TextCustom bold>Rp. 7.500.000</TextCustom>
|
<TextCustom bold>
|
||||||
|
Rp. {data ? formatCurrencyDisplay(data?.nominal) : ""}
|
||||||
|
</TextCustom>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid>
|
<Grid>
|
||||||
@@ -75,12 +105,16 @@ export default function InvestmentDetailHolding() {
|
|||||||
<TextCustom bold>Saham Terbeli</TextCustom>
|
<TextCustom bold>Saham Terbeli</TextCustom>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
<Grid.Col span={6}>
|
<Grid.Col span={6}>
|
||||||
<TextCustom bold>300 Lembar</TextCustom>
|
<TextCustom bold>
|
||||||
|
{data ? data?.lembarTerbeli : ""} Lembar
|
||||||
|
</TextCustom>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
</Grid>
|
</Grid>
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
</BaseBox>
|
</BaseBox>
|
||||||
|
|
||||||
<Invesment_DetailDataPublishSection
|
<Invesment_DetailDataPublishSection
|
||||||
|
data={data && data?.Investasi}
|
||||||
status={"publish"}
|
status={"publish"}
|
||||||
bottomSection={bottomSection}
|
bottomSection={bottomSection}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,9 +1,73 @@
|
|||||||
import { BaseBox, Grid, Spacing, StackCustom, TextCustom, ViewWrapper } from "@/components";
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
|
import {
|
||||||
|
BaseBox,
|
||||||
|
Grid,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
import { MainColor } from "@/constants/color-palet";
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { apiInvestmentGetInvoice } from "@/service/api-client/api-investment";
|
||||||
import { GStyles } from "@/styles/global-styles";
|
import { GStyles } from "@/styles/global-styles";
|
||||||
|
import { dateTimeView } from "@/utils/dateTimeView";
|
||||||
|
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
|
||||||
import { FontAwesome6 } from "@expo/vector-icons";
|
import { FontAwesome6 } from "@expo/vector-icons";
|
||||||
|
import { useLocalSearchParams, useFocusEffect } from "expo-router";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
export default function InvestmentFailed() {
|
export default function InvestmentFailed() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
console.log("[ID]", id);
|
||||||
|
|
||||||
|
const [data, setData] = React.useState<any | null>(null);
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
React.useCallback(() => {
|
||||||
|
onLoadData();
|
||||||
|
}, [id])
|
||||||
|
);
|
||||||
|
const onLoadData = async () => {
|
||||||
|
try {
|
||||||
|
const response = await apiInvestmentGetInvoice({
|
||||||
|
id: id as string,
|
||||||
|
category: "invoice",
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("[RES INVOICE]", JSON.stringify(response.data, null, 2));
|
||||||
|
setData(response.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const listData = [
|
||||||
|
{
|
||||||
|
label: "Bank",
|
||||||
|
value: (data && data?.MasterBank?.namaBank) || "-",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Rekening Penerima",
|
||||||
|
value: (data && data?.MasterBank?.namaAkun) || "-",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "No Rekening",
|
||||||
|
value: (data && data?.MasterBank?.norek) || "-",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Jumlah",
|
||||||
|
value: `Rp ${data && formatCurrencyDisplay(data?.nominal)}` || "-",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Tanggal",
|
||||||
|
value: (data && dateTimeView({ date: data?.createdAt })) || "-",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Lembar Terbeli",
|
||||||
|
value: (data && formatCurrencyDisplay(data?.lembarTerbeli)) || "-",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ViewWrapper>
|
<ViewWrapper>
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
@@ -11,8 +75,7 @@ export default function InvestmentFailed() {
|
|||||||
<StackCustom>
|
<StackCustom>
|
||||||
<TextCustom bold align="center">
|
<TextCustom bold align="center">
|
||||||
Transaksi anda gagal karena bukti transfer tidak sesuai dengan
|
Transaksi anda gagal karena bukti transfer tidak sesuai dengan
|
||||||
data kami. Jika ini masalah khusus silahkan hubungi pada kontak
|
data kami. Hubungi admin untuk memperbaiki masalah ini.
|
||||||
whatsapp kami.
|
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
|
|
||||||
<FontAwesome6
|
<FontAwesome6
|
||||||
@@ -50,30 +113,3 @@ export default function InvestmentFailed() {
|
|||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const listData = [
|
|
||||||
{
|
|
||||||
label: "Bank",
|
|
||||||
value: " BCA",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Rekening Penerima",
|
|
||||||
value: "Himpunan Pengusaha Muda Indonesia",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "No Rekening",
|
|
||||||
value: "2304235678854332",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Jumlah",
|
|
||||||
value: "Rp. 1.000.000",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Tanggal",
|
|
||||||
value: "2022-01-01",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Lembar Terbeli",
|
|
||||||
value: "100",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|||||||
@@ -108,7 +108,9 @@ export default function InvestmentInvest() {
|
|||||||
<TextCustom>Sisa Lembar Saham</TextCustom>
|
<TextCustom>Sisa Lembar Saham</TextCustom>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
<Grid.Col span={6} style={{ alignItems: "flex-end" }}>
|
<Grid.Col span={6} style={{ alignItems: "flex-end" }}>
|
||||||
<TextCustom>{data?.sisaLembar || "-"}</TextCustom>
|
<TextCustom>
|
||||||
|
{data && formatCurrencyDisplay(data?.sisaLembar) || "-"}
|
||||||
|
</TextCustom>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid>
|
<Grid>
|
||||||
@@ -116,7 +118,9 @@ export default function InvestmentInvest() {
|
|||||||
<TextCustom>Harga Per Lembar</TextCustom>
|
<TextCustom>Harga Per Lembar</TextCustom>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
<Grid.Col span={6} style={{ alignItems: "flex-end" }}>
|
<Grid.Col span={6} style={{ alignItems: "flex-end" }}>
|
||||||
<TextCustom>{data?.hargaLembar || "-"}</TextCustom>
|
<TextCustom>
|
||||||
|
{data && formatCurrencyDisplay(data?.hargaLembar) || "-"}
|
||||||
|
</TextCustom>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid>
|
<Grid>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import {
|
import {
|
||||||
BaseBox,
|
BaseBox,
|
||||||
Grid,
|
Grid,
|
||||||
@@ -7,10 +8,66 @@ import {
|
|||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import { MainColor } from "@/constants/color-palet";
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { apiInvestmentGetInvoice } from "@/service/api-client/api-investment";
|
||||||
import { GStyles } from "@/styles/global-styles";
|
import { GStyles } from "@/styles/global-styles";
|
||||||
|
import { dateTimeView } from "@/utils/dateTimeView";
|
||||||
|
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
|
||||||
import { FontAwesome6 } from "@expo/vector-icons";
|
import { FontAwesome6 } from "@expo/vector-icons";
|
||||||
|
import { useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
export default function InvestmentSuccess() {
|
export default function InvestmentSuccess() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
console.log("[ID]", id);
|
||||||
|
|
||||||
|
const [data, setData] = React.useState<any | null>(null);
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
React.useCallback(() => {
|
||||||
|
onLoadData();
|
||||||
|
}, [id])
|
||||||
|
);
|
||||||
|
const onLoadData = async () => {
|
||||||
|
try {
|
||||||
|
const response = await apiInvestmentGetInvoice({
|
||||||
|
id: id as string,
|
||||||
|
category: "invoice",
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("[RES INVOICE]", JSON.stringify(response.data, null, 2));
|
||||||
|
setData(response.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const listData = [
|
||||||
|
{
|
||||||
|
label: "Bank",
|
||||||
|
value: (data && data?.MasterBank?.namaBank) || "-",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Rekening Penerima",
|
||||||
|
value: (data && data?.MasterBank?.namaAkun) || "-",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "No Rekening",
|
||||||
|
value: (data && data?.MasterBank?.norek) || "-",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Jumlah",
|
||||||
|
value: `Rp ${data && formatCurrencyDisplay(data?.nominal)}` || "-",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Tanggal",
|
||||||
|
value: (data && dateTimeView({ date: data?.createdAt })) || "-",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Lembar Terbeli",
|
||||||
|
value: (data && formatCurrencyDisplay(data?.lembarTerbeli)) || "-",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ViewWrapper>
|
<ViewWrapper>
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
@@ -35,8 +92,7 @@ export default function InvestmentSuccess() {
|
|||||||
Detail Transaksi
|
Detail Transaksi
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
|
|
||||||
<Spacing/>
|
<Spacing />
|
||||||
|
|
||||||
|
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
{listData.map((item, i) => (
|
{listData.map((item, i) => (
|
||||||
@@ -45,7 +101,9 @@ export default function InvestmentSuccess() {
|
|||||||
<TextCustom bold>{item.label}</TextCustom>
|
<TextCustom bold>{item.label}</TextCustom>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
<Grid.Col span={7}>
|
<Grid.Col span={7}>
|
||||||
<TextCustom style={{paddingLeft: 10}}>{item.value}</TextCustom>
|
<TextCustom style={{ paddingLeft: 10 }}>
|
||||||
|
{item.value}
|
||||||
|
</TextCustom>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
</Grid>
|
</Grid>
|
||||||
))}
|
))}
|
||||||
@@ -55,30 +113,3 @@ export default function InvestmentSuccess() {
|
|||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const listData = [
|
|
||||||
{
|
|
||||||
label: "Bank",
|
|
||||||
value: " BCA",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Rekening Penerima",
|
|
||||||
value: "Himpunan Pengusaha Muda Indonesia",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "No Rekening",
|
|
||||||
value: "2304235678854332",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Jumlah",
|
|
||||||
value: "Rp. 1.000.000",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Tanggal",
|
|
||||||
value: "2022-01-01",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Lembar Terbeli",
|
|
||||||
value: "100",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import Investment_ButtonInvestasiSection from "@/screens/Invesment/ButtonInvesta
|
|||||||
import Invesment_ComponentBoxOnBottomDetail from "@/screens/Invesment/ComponentBoxOnBottomDetail";
|
import Invesment_ComponentBoxOnBottomDetail from "@/screens/Invesment/ComponentBoxOnBottomDetail";
|
||||||
import Invesment_DetailDataPublishSection from "@/screens/Invesment/DetailDataPublishSection";
|
import Invesment_DetailDataPublishSection from "@/screens/Invesment/DetailDataPublishSection";
|
||||||
import { apiInvestmentGetOne } from "@/service/api-client/api-investment";
|
import { apiInvestmentGetOne } from "@/service/api-client/api-investment";
|
||||||
|
import { countDownAndCondition } from "@/utils/countDownAndCondition";
|
||||||
import { AntDesign, MaterialIcons } from "@expo/vector-icons";
|
import { AntDesign, MaterialIcons } from "@expo/vector-icons";
|
||||||
import {
|
import {
|
||||||
router,
|
router,
|
||||||
@@ -23,7 +24,7 @@ import {
|
|||||||
useLocalSearchParams,
|
useLocalSearchParams,
|
||||||
} from "expo-router";
|
} from "expo-router";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
|
|
||||||
export default function InvestmentDetail() {
|
export default function InvestmentDetail() {
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
@@ -62,6 +63,31 @@ export default function InvestmentDetail() {
|
|||||||
setOpenDrawerPublish(false);
|
setOpenDrawerPublish(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const [value, setValue] = useState({
|
||||||
|
sisa: 0,
|
||||||
|
reminder: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
updateCountDown();
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
console.log("[DATA DETAIL]", JSON.stringify(data, null, 2));
|
||||||
|
|
||||||
|
const updateCountDown = () => {
|
||||||
|
const countDown = countDownAndCondition({
|
||||||
|
duration: data?.MasterPencarianInvestor.name,
|
||||||
|
publishTime: data?.countDown,
|
||||||
|
});
|
||||||
|
|
||||||
|
setValue({
|
||||||
|
sisa: countDown.durationDay,
|
||||||
|
reminder: countDown.reminder,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const bottomSection = (
|
const bottomSection = (
|
||||||
<Invesment_ComponentBoxOnBottomDetail
|
<Invesment_ComponentBoxOnBottomDetail
|
||||||
id={id as string}
|
id={id as string}
|
||||||
@@ -71,7 +97,7 @@ export default function InvestmentDetail() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const buttonSection = (
|
const buttonSection = (
|
||||||
<Investment_ButtonInvestasiSection id={id as string} isMine={user?.id === data?.author?.id} />
|
<Investment_ButtonInvestasiSection id={id as string} isMine={user?.id === data?.author?.id} reminder={value.reminder} />
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,20 +1,66 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import {
|
import {
|
||||||
AvatarUsernameAndOtherComponent,
|
AvatarUsernameAndOtherComponent,
|
||||||
BoxWithHeaderSection,
|
BoxWithHeaderSection,
|
||||||
|
LoaderCustom,
|
||||||
TextCustom,
|
TextCustom,
|
||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
|
import NoDataText from "@/components/_ShareComponent/NoDataText";
|
||||||
|
import { apiInvestmentGetInvestorById } from "@/service/api-client/api-investment";
|
||||||
|
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
|
||||||
|
import { useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { useCallback, useState } from "react";
|
||||||
|
|
||||||
export default function InvestmentInvestor() {
|
export default function InvestmentInvestor() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const [list, setList] = useState<any[] | null>(null);
|
||||||
|
const [loadingList, setLoadingList] = useState(false);
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
onLoadList();
|
||||||
|
}, [id])
|
||||||
|
);
|
||||||
|
|
||||||
|
const onLoadList = async () => {
|
||||||
|
try {
|
||||||
|
setLoadingList(true);
|
||||||
|
const response = await apiInvestmentGetInvestorById({
|
||||||
|
id: id as string,
|
||||||
|
})
|
||||||
|
console.log("[DATA LIST]", JSON.stringify(response.data, null, 2));
|
||||||
|
setList(response.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
} finally {
|
||||||
|
setLoadingList(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ViewWrapper>
|
<ViewWrapper>
|
||||||
{Array.from({ length: 10 }).map((_, index) => (
|
{loadingList ? (
|
||||||
|
<LoaderCustom />
|
||||||
|
) : _.isEmpty(list) ? (
|
||||||
|
<NoDataText />
|
||||||
|
) : (
|
||||||
|
list?.map((item: any, index: number) => (
|
||||||
<BoxWithHeaderSection key={index}>
|
<BoxWithHeaderSection key={index}>
|
||||||
<AvatarUsernameAndOtherComponent />
|
<AvatarUsernameAndOtherComponent
|
||||||
<TextCustom bold>Rp. 7.000.000</TextCustom>
|
avatar={item?.Author?.Profile?.imageId}
|
||||||
|
name={item?.Author?.username}
|
||||||
|
avatarHref={`/profile/${item?.Author?.Profile?.id}`}
|
||||||
|
/>
|
||||||
|
<TextCustom bold>
|
||||||
|
Rp. {formatCurrencyDisplay(item?.nominal)}
|
||||||
|
</TextCustom>
|
||||||
</BoxWithHeaderSection>
|
</BoxWithHeaderSection>
|
||||||
))}
|
))
|
||||||
|
)}
|
||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,32 +1,6 @@
|
|||||||
import {
|
import MapsView from "@/screens/Maps/MapsView";
|
||||||
ButtonCustom,
|
import MapsView2 from "@/screens/Maps/MapsView2";
|
||||||
DrawerCustom,
|
import { Text, View } from "react-native";
|
||||||
DummyLandscapeImage,
|
|
||||||
Grid,
|
|
||||||
Spacing,
|
|
||||||
StackCustom,
|
|
||||||
TextCustom,
|
|
||||||
ViewWrapper,
|
|
||||||
} from "@/components";
|
|
||||||
import GridTwoView from "@/components/_ShareComponent/GridTwoView";
|
|
||||||
import API_IMAGE from "@/constants/api-storage";
|
|
||||||
import { ICON_SIZE_SMALL } from "@/constants/constans-value";
|
|
||||||
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 { router, useFocusEffect } from "expo-router";
|
|
||||||
import { useCallback, useState } from "react";
|
|
||||||
import { View } from "react-native";
|
|
||||||
import MapView, { Marker } from "react-native-maps";
|
|
||||||
|
|
||||||
const defaultRegion = {
|
|
||||||
latitude: -8.737109,
|
|
||||||
longitude: 115.1756897,
|
|
||||||
latitudeDelta: 0.1,
|
|
||||||
longitudeDelta: 0.1,
|
|
||||||
height: 300,
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface LocationItem {
|
export interface LocationItem {
|
||||||
id: string | number;
|
id: string | number;
|
||||||
@@ -37,198 +11,11 @@ export interface LocationItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function Maps() {
|
export default function Maps() {
|
||||||
const [list, setList] = useState<any[] | null>(null);
|
|
||||||
const [loadList, setLoadList] = useState(false);
|
|
||||||
const [openDrawer, setOpenDrawer] = useState(false);
|
|
||||||
const [selected, setSelected] = useState({
|
|
||||||
id: "",
|
|
||||||
bidangBisnis: "",
|
|
||||||
nomorTelepon: "",
|
|
||||||
alamatBisnis: "",
|
|
||||||
namePin: "",
|
|
||||||
imageId: "",
|
|
||||||
portofolioId: "",
|
|
||||||
latitude: 0,
|
|
||||||
longitude: 0,
|
|
||||||
});
|
|
||||||
|
|
||||||
useFocusEffect(
|
|
||||||
useCallback(() => {
|
|
||||||
handlerLoadList();
|
|
||||||
}, [])
|
|
||||||
);
|
|
||||||
|
|
||||||
const handlerLoadList = async () => {
|
|
||||||
try {
|
|
||||||
setLoadList(true);
|
|
||||||
const response = await apiMapsGetAll();
|
|
||||||
|
|
||||||
if (response.success) {
|
|
||||||
setList(response.data);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log("[ERROR]", error);
|
|
||||||
} finally {
|
|
||||||
setLoadList(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ViewWrapper style={{ paddingInline: 0, paddingBlock: 0 }}>
|
<MapsView />
|
||||||
{/* <MapCustom height={"100%"} /> */}
|
{/* <MapsView2 />, */}
|
||||||
<View style={{ flex: 1 }}>
|
{/* <View style={{ flex: 1, backgroundColor: "gray" }}><Text style={{ color: "white" }}>Map disabled</Text></View> */}
|
||||||
{loadList ? (
|
|
||||||
<MapView
|
|
||||||
initialRegion={defaultRegion}
|
|
||||||
style={{
|
|
||||||
width: "100%",
|
|
||||||
height: "100%",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<MapView
|
|
||||||
initialRegion={defaultRegion}
|
|
||||||
style={{
|
|
||||||
width: "100%",
|
|
||||||
height: "100%",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{list?.map((item: any, index: number) => {
|
|
||||||
return (
|
|
||||||
<Marker
|
|
||||||
key={item?.id}
|
|
||||||
coordinate={{
|
|
||||||
latitude: item?.latitude,
|
|
||||||
longitude: item?.longitude,
|
|
||||||
}}
|
|
||||||
title={item?.namePin}
|
|
||||||
onPress={() => {
|
|
||||||
setOpenDrawer(true);
|
|
||||||
setSelected({
|
|
||||||
id: item?.id,
|
|
||||||
bidangBisnis:
|
|
||||||
item?.Portofolio?.MasterBidangBisnis?.name,
|
|
||||||
nomorTelepon: item?.Portofolio?.tlpn,
|
|
||||||
alamatBisnis: item?.Portofolio?.alamatKantor,
|
|
||||||
namePin: item?.namePin,
|
|
||||||
imageId: item?.imageId,
|
|
||||||
portofolioId: item?.Portofolio?.id,
|
|
||||||
latitude: item?.latitude,
|
|
||||||
longitude: item?.longitude,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
// Gunakan gambar kustom jika tersedia
|
|
||||||
>
|
|
||||||
<View style={{}}>
|
|
||||||
<Image
|
|
||||||
source={{
|
|
||||||
uri: API_IMAGE.GET({
|
|
||||||
fileId: item?.Portofolio?.logoId,
|
|
||||||
}),
|
|
||||||
}}
|
|
||||||
style={{
|
|
||||||
width: 30,
|
|
||||||
height: 30,
|
|
||||||
borderRadius: 100,
|
|
||||||
borderWidth: 1,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
</Marker>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</MapView>
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
</ViewWrapper>
|
|
||||||
|
|
||||||
<DrawerCustom
|
|
||||||
isVisible={openDrawer}
|
|
||||||
closeDrawer={() => setOpenDrawer(false)}
|
|
||||||
height={"auto"}
|
|
||||||
>
|
|
||||||
<DummyLandscapeImage height={200} imageId={selected.imageId} />
|
|
||||||
<Spacing />
|
|
||||||
<StackCustom gap={"xs"}>
|
|
||||||
<GridTwoView
|
|
||||||
spanLeft={2}
|
|
||||||
spanRight={10}
|
|
||||||
leftIcon={
|
|
||||||
<FontAwesome
|
|
||||||
name="building-o"
|
|
||||||
size={ICON_SIZE_SMALL}
|
|
||||||
color="white"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
rightIcon={<TextCustom>{selected.namePin}</TextCustom>}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<GridTwoView
|
|
||||||
spanLeft={2}
|
|
||||||
spanRight={10}
|
|
||||||
leftIcon={
|
|
||||||
<Ionicons
|
|
||||||
name="list-outline"
|
|
||||||
size={ICON_SIZE_SMALL}
|
|
||||||
color="white"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
rightIcon={<TextCustom>{selected.bidangBisnis}</TextCustom>}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<GridTwoView
|
|
||||||
spanLeft={2}
|
|
||||||
spanRight={10}
|
|
||||||
leftIcon={
|
|
||||||
<Ionicons
|
|
||||||
name="call-outline"
|
|
||||||
size={ICON_SIZE_SMALL}
|
|
||||||
color="white"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
rightIcon={<TextCustom>{selected.nomorTelepon}</TextCustom>}
|
|
||||||
/>
|
|
||||||
<GridTwoView
|
|
||||||
spanLeft={2}
|
|
||||||
spanRight={10}
|
|
||||||
leftIcon={
|
|
||||||
<Ionicons
|
|
||||||
name="location-outline"
|
|
||||||
size={ICON_SIZE_SMALL}
|
|
||||||
color="white"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
rightIcon={<TextCustom>{selected.alamatBisnis}</TextCustom>}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Grid>
|
|
||||||
<Grid.Col span={6} style={{ paddingRight: 10 }}>
|
|
||||||
<ButtonCustom
|
|
||||||
onPress={() => {
|
|
||||||
setOpenDrawer(false);
|
|
||||||
router.push(`/portofolio/${selected.portofolioId}`);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Detail
|
|
||||||
</ButtonCustom>
|
|
||||||
</Grid.Col>
|
|
||||||
<Grid.Col span={6} style={{ paddingLeft: 10 }}>
|
|
||||||
<ButtonCustom
|
|
||||||
onPress={() => {
|
|
||||||
openInDeviceMaps({
|
|
||||||
latitude: selected.latitude,
|
|
||||||
longitude: selected.longitude,
|
|
||||||
title: selected.namePin,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Buka Maps
|
|
||||||
</ButtonCustom>
|
|
||||||
</Grid.Col>
|
|
||||||
</Grid>
|
|
||||||
</StackCustom>
|
|
||||||
</DrawerCustom>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,9 +31,9 @@ import {
|
|||||||
import pickImage from "@/utils/pickImage";
|
import pickImage from "@/utils/pickImage";
|
||||||
import { Ionicons } from "@expo/vector-icons";
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
import { Image } from "expo-image";
|
import { Image } from "expo-image";
|
||||||
import { useLocalSearchParams } from "expo-router";
|
import { useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import { Text, TouchableOpacity, View } from "react-native";
|
import { Text, TouchableOpacity, View } from "react-native";
|
||||||
import PhoneInput, { ICountry } from "react-native-international-phone-number";
|
import PhoneInput, { ICountry } from "react-native-international-phone-number";
|
||||||
import { Avatar } from "react-native-paper";
|
import { Avatar } from "react-native-paper";
|
||||||
@@ -76,7 +76,7 @@ export default function PortofolioCreate() {
|
|||||||
function handleInputValue(phoneNumber: string) {
|
function handleInputValue(phoneNumber: string) {
|
||||||
setInputValue(phoneNumber);
|
setInputValue(phoneNumber);
|
||||||
const callingCode = selectedCountry?.callingCode.replace(/^\+/, "") || "";
|
const callingCode = selectedCountry?.callingCode.replace(/^\+/, "") || "";
|
||||||
const fixNumber = inputValue.replace(/\s+/g, "");
|
let fixNumber = inputValue.replace(/\s+/g, "").replace(/^0+/, "");
|
||||||
const realNumber = callingCode + fixNumber;
|
const realNumber = callingCode + fixNumber;
|
||||||
setData({ ...data, tlpn: realNumber });
|
setData({ ...data, tlpn: realNumber });
|
||||||
}
|
}
|
||||||
@@ -85,10 +85,12 @@ export default function PortofolioCreate() {
|
|||||||
setSelectedCountry(country);
|
setSelectedCountry(country);
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
onLoadMaster();
|
onLoadMaster();
|
||||||
onLoadMasterSubBidangBisnis();
|
onLoadMasterSubBidangBisnis();
|
||||||
}, []);
|
}, [])
|
||||||
|
);
|
||||||
|
|
||||||
const onLoadMaster = async () => {
|
const onLoadMaster = async () => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -244,7 +244,7 @@ export default function PortofolioEdit() {
|
|||||||
|
|
||||||
const handleSubmitUpdate = async () => {
|
const handleSubmitUpdate = async () => {
|
||||||
const callingCode = selectedCountry?.callingCode.replace(/^\+/, "") || "";
|
const callingCode = selectedCountry?.callingCode.replace(/^\+/, "") || "";
|
||||||
const fixNumber = data.tlpn.replace(/\s+/g, "");
|
let fixNumber = data.tlpn.replace(/\s+/g, "").replace(/^0+/, "");
|
||||||
const realNumber = callingCode + fixNumber;
|
const realNumber = callingCode + fixNumber;
|
||||||
|
|
||||||
const newData: IFormData = {
|
const newData: IFormData = {
|
||||||
|
|||||||
148
app/(application)/(user)/profile/[id]/blocked-list.tsx
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
import {
|
||||||
|
AvatarUsernameAndOtherComponent,
|
||||||
|
BadgeCustom,
|
||||||
|
ClickableCustom,
|
||||||
|
Divider,
|
||||||
|
SelectCustom,
|
||||||
|
TextCustom,
|
||||||
|
} from "@/components";
|
||||||
|
import ListEmptyComponent from "@/components/_ShareComponent/ListEmptyComponent";
|
||||||
|
import ListLoaderFooterComponent from "@/components/_ShareComponent/ListLoaderFooterComponent";
|
||||||
|
import ListSkeletonComponent from "@/components/_ShareComponent/ListSkeletonComponent";
|
||||||
|
import NewWrapper from "@/components/_ShareComponent/NewWrapper";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
|
import { usePaginatedApi } from "@/hooks/use-paginated-api";
|
||||||
|
import { apiGetBlocked } from "@/service/api-client/api-blocked";
|
||||||
|
import { apiMasterAppCategory } from "@/service/api-client/api-master";
|
||||||
|
import { router, useFocusEffect } from "expo-router";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { useCallback, useEffect, useRef, useState } from "react";
|
||||||
|
import { RefreshControl, View } from "react-native";
|
||||||
|
|
||||||
|
const PAGE_SIZE = 10;
|
||||||
|
export default function ProfileBlockedList() {
|
||||||
|
const { user } = useAuth();
|
||||||
|
const [masterApp, setMasterApp] = useState<any[]>([]);
|
||||||
|
const isInitialMount = useRef(true);
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: listData,
|
||||||
|
loading,
|
||||||
|
refreshing,
|
||||||
|
hasMore,
|
||||||
|
search,
|
||||||
|
setSearch,
|
||||||
|
onRefresh,
|
||||||
|
loadMore,
|
||||||
|
} = usePaginatedApi({
|
||||||
|
fetcher: async (params: { page: number; search?: string }) => {
|
||||||
|
const response = await apiGetBlocked({
|
||||||
|
id: user?.id as any,
|
||||||
|
search: search,
|
||||||
|
page: String(params.page) as any,
|
||||||
|
});
|
||||||
|
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
initialSearch: "",
|
||||||
|
pageSize: PAGE_SIZE,
|
||||||
|
dependencies: [user?.id],
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchMasterApp();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// 🔁 Refresh otomatis saat kembali ke halaman ini
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
if (isInitialMount.current) {
|
||||||
|
// Skip saat pertama kali mount
|
||||||
|
isInitialMount.current = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Hanya refresh saat kembali dari screen lain
|
||||||
|
onRefresh();
|
||||||
|
}, [onRefresh])
|
||||||
|
);
|
||||||
|
|
||||||
|
const fetchMasterApp = async () => {
|
||||||
|
const response = await apiMasterAppCategory();
|
||||||
|
setMasterApp(response.data);
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderHeader = () => (
|
||||||
|
<SelectCustom
|
||||||
|
placeholder="Pilih Kategori Fitur"
|
||||||
|
data={masterApp.map((item) => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.id,
|
||||||
|
}))}
|
||||||
|
value={search === "" ? undefined : search}
|
||||||
|
onChange={(value) => {
|
||||||
|
setSearch(value as any);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
const renderItem = ({ item }: { item: any }) => (
|
||||||
|
<>
|
||||||
|
<ClickableCustom
|
||||||
|
onPress={() => {
|
||||||
|
router.push(`/profile/${item.id}/detail-blocked`);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
paddingInline: 8,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AvatarUsernameAndOtherComponent
|
||||||
|
avatarHref={`/profile/${item?.blocked?.Profile?.id}`}
|
||||||
|
avatar={item?.blocked?.Profile?.imageId}
|
||||||
|
name={item?.blocked?.username}
|
||||||
|
rightComponent={
|
||||||
|
<View style={{ flexDirection: "row", gap: 4 }}>
|
||||||
|
<BadgeCustom>
|
||||||
|
<TextCustom size={"small"} bold truncate>
|
||||||
|
{item?.menuFeature?.name}
|
||||||
|
</TextCustom>
|
||||||
|
</BadgeCustom>
|
||||||
|
</View>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Divider color="gray" />
|
||||||
|
</View>
|
||||||
|
</ClickableCustom>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<NewWrapper
|
||||||
|
// headerComponent={renderHeader()}
|
||||||
|
listData={listData}
|
||||||
|
renderItem={renderItem}
|
||||||
|
onEndReached={loadMore}
|
||||||
|
refreshControl={
|
||||||
|
<RefreshControl
|
||||||
|
progressBackgroundColor={MainColor.yellow}
|
||||||
|
refreshing={refreshing}
|
||||||
|
onRefresh={onRefresh}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
ListFooterComponent={
|
||||||
|
hasMore && !refreshing ? <ListLoaderFooterComponent /> : null
|
||||||
|
}
|
||||||
|
ListEmptyComponent={
|
||||||
|
!loading && _.isEmpty(listData) ? (
|
||||||
|
<ListSkeletonComponent />
|
||||||
|
) : (
|
||||||
|
<ListEmptyComponent />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
93
app/(application)/(user)/profile/[id]/detail-blocked.tsx
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
import {
|
||||||
|
AlertDefaultSystem,
|
||||||
|
AvatarUsernameAndOtherComponent,
|
||||||
|
BaseBox,
|
||||||
|
BoxButtonOnFooter,
|
||||||
|
BoxWithHeaderSection,
|
||||||
|
ButtonCustom,
|
||||||
|
NewWrapper,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
} from "@/components";
|
||||||
|
import AvatarAndBackground from "@/screens/Profile/AvatarAndBackground";
|
||||||
|
import {
|
||||||
|
apiGetBlockedById,
|
||||||
|
apiUnblock,
|
||||||
|
} from "@/service/api-client/api-blocked";
|
||||||
|
import { router, useLocalSearchParams } from "expo-router";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
export default function ProfileDetailBlocked() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const [data, setData] = useState<any>(null);
|
||||||
|
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchData();
|
||||||
|
}, [id]);
|
||||||
|
|
||||||
|
const fetchData = async () => {
|
||||||
|
const response = await apiGetBlockedById({ id: String(id) });
|
||||||
|
// console.log("[RESPONSE >>]", JSON.stringify(response, null, 2));
|
||||||
|
setData(response.data);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
await apiUnblock({ id: String(id) });
|
||||||
|
router.back();
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR >>]", JSON.stringify(error, null, 2));
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<NewWrapper
|
||||||
|
footerComponent={
|
||||||
|
<BoxButtonOnFooter>
|
||||||
|
<ButtonCustom
|
||||||
|
isLoading={isLoading}
|
||||||
|
onPress={() => {
|
||||||
|
AlertDefaultSystem({
|
||||||
|
title: "Buka Blokir",
|
||||||
|
message: "Apakah anda yakin ingin membuka blokir ini?",
|
||||||
|
textLeft: "Tidak",
|
||||||
|
textRight: "Ya",
|
||||||
|
onPressRight: () => {
|
||||||
|
handleSubmit();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Buka Blokir
|
||||||
|
</ButtonCustom>
|
||||||
|
</BoxButtonOnFooter>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<BoxWithHeaderSection>
|
||||||
|
<StackCustom>
|
||||||
|
<AvatarUsernameAndOtherComponent
|
||||||
|
avatarHref={`/profile/${data?.blocked?.Profile?.id}`}
|
||||||
|
avatar={data?.blocked?.Profile?.imageId}
|
||||||
|
name={data?.blocked?.username}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextCustom align="center">
|
||||||
|
Jika anda membuka blokir ini maka semua postingan terkait user ini
|
||||||
|
akan muncul kembali di beranda
|
||||||
|
<TextCustom bold color="red">
|
||||||
|
{" "}
|
||||||
|
{_.upperCase(data?.menuFeature?.name)}
|
||||||
|
</TextCustom>
|
||||||
|
</TextCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</BoxWithHeaderSection>
|
||||||
|
</NewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -64,6 +64,7 @@ export default function Profile() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onLoadPortofolio = async (id: string) => {
|
const onLoadPortofolio = async (id: string) => {
|
||||||
|
try {
|
||||||
const response = await apiGetPortofolio({ id: id });
|
const response = await apiGetPortofolio({ id: id });
|
||||||
const lastTwoByDate = response.data
|
const lastTwoByDate = response.data
|
||||||
.sort(
|
.sort(
|
||||||
@@ -72,6 +73,9 @@ export default function Profile() {
|
|||||||
) // urut desc
|
) // urut desc
|
||||||
.slice(0, 2);
|
.slice(0, 2);
|
||||||
setListPortofolio(lastTwoByDate);
|
setListPortofolio(lastTwoByDate);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -33,6 +33,16 @@ export default function ProfileLayout() {
|
|||||||
name="create"
|
name="create"
|
||||||
options={{ title: "Buat Profile", headerBackVisible: false }}
|
options={{ title: "Buat Profile", headerBackVisible: false }}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Stack.Screen
|
||||||
|
name="[id]/blocked-list"
|
||||||
|
options={{ title: "Blocked List", headerLeft: () => <BackButton /> }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Stack.Screen
|
||||||
|
name="[id]/detail-blocked"
|
||||||
|
options={{ title: "Detail Blokir", headerLeft: () => <BackButton /> }}
|
||||||
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
TextCustom,
|
TextCustom,
|
||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
import Voting_BoxPublishSection from "@/screens/Voting/BoxPublishSection";
|
import Voting_BoxPublishSection from "@/screens/Voting/BoxPublishSection";
|
||||||
import { apiVotingGetAll } from "@/service/api-client/api-voting";
|
import { apiVotingGetAll } from "@/service/api-client/api-voting";
|
||||||
import { router, useFocusEffect } from "expo-router";
|
import { router, useFocusEffect } from "expo-router";
|
||||||
@@ -13,6 +14,7 @@ import _ from "lodash";
|
|||||||
import { useCallback, useState } from "react";
|
import { useCallback, useState } from "react";
|
||||||
|
|
||||||
export default function VotingBeranda() {
|
export default function VotingBeranda() {
|
||||||
|
const { user } = useAuth();
|
||||||
const [listData, setListData] = useState<any>([]);
|
const [listData, setListData] = useState<any>([]);
|
||||||
const [loadingGetData, setLoadingGetData] = useState(false);
|
const [loadingGetData, setLoadingGetData] = useState(false);
|
||||||
const [search, setSearch] = useState("");
|
const [search, setSearch] = useState("");
|
||||||
@@ -29,6 +31,7 @@ export default function VotingBeranda() {
|
|||||||
const response = await apiVotingGetAll({
|
const response = await apiVotingGetAll({
|
||||||
search,
|
search,
|
||||||
category: "beranda",
|
category: "beranda",
|
||||||
|
userLoginId: user?.id,
|
||||||
});
|
});
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
setListData(response.data);
|
setListData(response.data);
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ export default function VotingDetailStatus() {
|
|||||||
|
|
||||||
{data &&
|
{data &&
|
||||||
data?.catatan &&
|
data?.catatan &&
|
||||||
(status === "draft" || status === "rejected") && (
|
(status === "draft" || status === "reject") && (
|
||||||
<ReportBox text={data?.catatan} />
|
<ReportBox text={data?.catatan} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ export default function VotingCreate() {
|
|||||||
<StackCustom gap={"xs"}>
|
<StackCustom gap={"xs"}>
|
||||||
<TextInputCustom
|
<TextInputCustom
|
||||||
label="Judul Voting"
|
label="Judul Voting"
|
||||||
placeholder="MasukanJudul Voting"
|
placeholder="Masukan Judul Voting"
|
||||||
required
|
required
|
||||||
value={data.title}
|
value={data.title}
|
||||||
onChangeText={(value: any) => setData({ ...data, title: value })}
|
onChangeText={(value: any) => setData({ ...data, title: value })}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
ButtonCenteredOnly,
|
ButtonCenteredOnly,
|
||||||
ButtonCustom,
|
ButtonCustom,
|
||||||
InformationBox,
|
InformationBox,
|
||||||
|
NewWrapper,
|
||||||
StackCustom,
|
StackCustom,
|
||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
@@ -12,6 +13,7 @@ import { useAuth } from "@/hooks/use-auth";
|
|||||||
import { apiUser } from "@/service/api-client/api-user";
|
import { apiUser } from "@/service/api-client/api-user";
|
||||||
import { Ionicons } from "@expo/vector-icons";
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
import { router } from "expo-router";
|
import { router } from "expo-router";
|
||||||
|
import { RefreshControl } from "react-native";
|
||||||
import Toast from "react-native-toast-message";
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function WaitingRoom() {
|
export default function WaitingRoom() {
|
||||||
@@ -33,7 +35,7 @@ export default function WaitingRoom() {
|
|||||||
} else {
|
} else {
|
||||||
Toast.show({
|
Toast.show({
|
||||||
type: "success",
|
type: "success",
|
||||||
text1: "Akun anda telah aktif", // text2: "Anda berhasil login",
|
text1: "Selamat ! Akun anda telah aktif", // text2: "Anda berhasil login",
|
||||||
});
|
});
|
||||||
router.replace(`/(application)/(user)/profile/create`);
|
router.replace(`/(application)/(user)/profile/create`);
|
||||||
}
|
}
|
||||||
@@ -82,10 +84,18 @@ export default function WaitingRoom() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ViewWrapper footerComponent={logoutButton()}>
|
<NewWrapper
|
||||||
|
footerComponent={logoutButton()}
|
||||||
|
refreshControl={
|
||||||
|
<RefreshControl refreshing={isLoading} onRefresh={handleCheck} />
|
||||||
|
}
|
||||||
|
>
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
<InformationBox text="Permohonan akses Anda sedang dalam proses verifikasi oleh admin. Harap tunggu, Anda akan menerima pemberitahuan melalui Whatsapp setelah disetujui." />
|
<InformationBox
|
||||||
<ButtonCenteredOnly
|
text="Akun Anda sedang menunggu aktivasi.
|
||||||
|
Silakan tunggu beberapa saat. Untuk memperbarui status, tarik layar ke bawah."
|
||||||
|
/>
|
||||||
|
{/* <ButtonCenteredOnly
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
handleCheck();
|
handleCheck();
|
||||||
@@ -93,9 +103,9 @@ export default function WaitingRoom() {
|
|||||||
icon="refresh-ccw"
|
icon="refresh-ccw"
|
||||||
>
|
>
|
||||||
Check
|
Check
|
||||||
</ButtonCenteredOnly>
|
</ButtonCenteredOnly> */}
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
</ViewWrapper>
|
</NewWrapper>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ export default function ApplicationLayout() {
|
|||||||
<Stack.Screen name="admin" options={{ headerShown: false }} />
|
<Stack.Screen name="admin" options={{ headerShown: false }} />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{/* Take Picture */}
|
{/* Take Picture */}
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name="(image)/take-picture/[id]/index"
|
name="(image)/take-picture/[id]/index"
|
||||||
|
|||||||
@@ -0,0 +1,129 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
|
import {
|
||||||
|
BoxButtonOnFooter,
|
||||||
|
ButtonCustom,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import {
|
||||||
|
apiAdminMasterBusinessFieldById,
|
||||||
|
apiAdminMasterBusinessFieldUpdate,
|
||||||
|
} from "@/service/api-admin/api-master-admin";
|
||||||
|
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useCallback, useState } from "react";
|
||||||
|
import { Switch } from "react-native-paper";
|
||||||
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
|
export default function AdminAppInformation_BusinessFieldDetail() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const [data, setData] = useState<any | null>(null);
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
onLoadDetail();
|
||||||
|
}, [id])
|
||||||
|
);
|
||||||
|
|
||||||
|
const onLoadDetail = async () => {
|
||||||
|
try {
|
||||||
|
const response = await apiAdminMasterBusinessFieldById({
|
||||||
|
id: id as string,
|
||||||
|
category: "bidang"
|
||||||
|
});
|
||||||
|
|
||||||
|
setData(response.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
setData(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlerSubmit = async () => {
|
||||||
|
if (!data.name) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Lengkapi Data",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
const response = await apiAdminMasterBusinessFieldUpdate({
|
||||||
|
id: id as string,
|
||||||
|
data: data,
|
||||||
|
category: "bidang",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.success) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Gagal update data",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toast.show({
|
||||||
|
type: "success",
|
||||||
|
text1: "Data berhasil di update",
|
||||||
|
});
|
||||||
|
router.back();
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const buttonSubmit = (
|
||||||
|
<BoxButtonOnFooter>
|
||||||
|
<ButtonCustom
|
||||||
|
disabled={!data?.name}
|
||||||
|
isLoading={isLoading}
|
||||||
|
onPress={() => handlerSubmit()}
|
||||||
|
>
|
||||||
|
Update
|
||||||
|
</ButtonCustom>
|
||||||
|
</BoxButtonOnFooter>
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ViewWrapper footerComponent={buttonSubmit}>
|
||||||
|
<StackCustom>
|
||||||
|
<AdminBackButtonAntTitle title="Update Bidang Bisnis" />
|
||||||
|
|
||||||
|
<TextInputCustom
|
||||||
|
label="Nama Bidang Bisnis"
|
||||||
|
placeholder="Masukan Nama Bidang Bisnis"
|
||||||
|
required
|
||||||
|
value={data?.name}
|
||||||
|
onChangeText={(value) => setData({ ...data, name: value })}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<StackCustom
|
||||||
|
gap={"sm"}
|
||||||
|
style={{
|
||||||
|
alignContent: "flex-start",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TextCustom>Status</TextCustom>
|
||||||
|
|
||||||
|
<Switch
|
||||||
|
style={{
|
||||||
|
alignSelf: "flex-start",
|
||||||
|
}}
|
||||||
|
color={MainColor.yellow}
|
||||||
|
value={data?.active}
|
||||||
|
onValueChange={(value) => setData({ ...data, active: value })}
|
||||||
|
/>
|
||||||
|
</StackCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,22 +1,22 @@
|
|||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import {
|
import {
|
||||||
BoxButtonOnFooter,
|
ActionIcon,
|
||||||
ButtonCustom,
|
BaseBox,
|
||||||
|
CenterCustom,
|
||||||
|
LoaderCustom,
|
||||||
|
Spacing,
|
||||||
StackCustom,
|
StackCustom,
|
||||||
TextCustom,
|
TextCustom,
|
||||||
TextInputCustom,
|
|
||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
|
import { IconEdit } from "@/components/_Icon";
|
||||||
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||||
|
import { GridSpan_NewComponent } from "@/components/_ShareComponent/GridSpan_NewComponent";
|
||||||
import { MainColor } from "@/constants/color-palet";
|
import { MainColor } from "@/constants/color-palet";
|
||||||
import {
|
import { apiAdminMasterBusinessFieldById } from "@/service/api-admin/api-master-admin";
|
||||||
apiAdminMasterBusinessFieldById,
|
|
||||||
apiAdminMasterBusinessFieldUpdate,
|
|
||||||
} from "@/service/api-admin/api-master-admin";
|
|
||||||
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useState } from "react";
|
||||||
import { Switch } from "react-native-paper";
|
import { Divider } from "react-native-paper";
|
||||||
import Toast from "react-native-toast-message";
|
|
||||||
|
|
||||||
export default function AdminAppInformation_BusinessFieldDetail() {
|
export default function AdminAppInformation_BusinessFieldDetail() {
|
||||||
const { id } = useLocalSearchParams();
|
const { id } = useLocalSearchParams();
|
||||||
@@ -33,8 +33,11 @@ export default function AdminAppInformation_BusinessFieldDetail() {
|
|||||||
try {
|
try {
|
||||||
const response = await apiAdminMasterBusinessFieldById({
|
const response = await apiAdminMasterBusinessFieldById({
|
||||||
id: id as string,
|
id: id as string,
|
||||||
|
category: "all",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log("Response >>", JSON.stringify(response, null, 2));
|
||||||
|
|
||||||
setData(response.data);
|
setData(response.data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("[ERROR]", error);
|
console.log("[ERROR]", error);
|
||||||
@@ -42,73 +45,89 @@ export default function AdminAppInformation_BusinessFieldDetail() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlerSubmit = async () => {
|
|
||||||
if (!data.name) {
|
|
||||||
Toast.show({
|
|
||||||
type: "error",
|
|
||||||
text1: "Lengkapi Data",
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
setIsLoading(true);
|
|
||||||
const response = await apiAdminMasterBusinessFieldUpdate({
|
|
||||||
id: id as string,
|
|
||||||
data: data,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.success) {
|
|
||||||
Toast.show({
|
|
||||||
type: "error",
|
|
||||||
text1: "Gagal update data",
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Toast.show({
|
|
||||||
type: "success",
|
|
||||||
text1: "Data berhasil di update",
|
|
||||||
});
|
|
||||||
router.back();
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
} finally {
|
|
||||||
setIsLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const buttonSubmit = (
|
|
||||||
<BoxButtonOnFooter>
|
|
||||||
<ButtonCustom
|
|
||||||
disabled={!data?.name}
|
|
||||||
isLoading={isLoading}
|
|
||||||
onPress={() => handlerSubmit()}
|
|
||||||
>
|
|
||||||
Update
|
|
||||||
</ButtonCustom>
|
|
||||||
</BoxButtonOnFooter>
|
|
||||||
);
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ViewWrapper footerComponent={buttonSubmit}>
|
<ViewWrapper>
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
<AdminBackButtonAntTitle title="Update Bidang Bisnis" />
|
<AdminBackButtonAntTitle title="Detail Bidang & Sub Bidang" />
|
||||||
|
|
||||||
<TextInputCustom
|
{!data ? (
|
||||||
label="Nama Bidang Bisnis"
|
<LoaderCustom />
|
||||||
placeholder="Masukan Nama Bidang Bisnis"
|
) : (
|
||||||
required
|
<StackCustom gap={"xs"}>
|
||||||
value={data?.name}
|
<TextCustom bold>Nama Bidang</TextCustom>
|
||||||
onChangeText={(value) => setData({ ...data, name: value })}
|
<Spacing height={5} />
|
||||||
|
<BaseBox>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<TextCustom bold>
|
||||||
|
Status: {data?.bidang?.active ? "Aktif" : "Tidak Aktif"}
|
||||||
|
</TextCustom>
|
||||||
|
<GridSpan_NewComponent
|
||||||
|
span1={10}
|
||||||
|
span2={2}
|
||||||
|
text1={
|
||||||
|
<TextCustom bold size={"large"}>
|
||||||
|
{data?.bidang?.name}
|
||||||
|
</TextCustom>
|
||||||
|
}
|
||||||
|
text2={
|
||||||
|
<CenterCustom>
|
||||||
|
<ActionIcon
|
||||||
|
icon={<IconEdit size={16} color={MainColor.black} />}
|
||||||
|
onPress={() =>
|
||||||
|
router.push(
|
||||||
|
`/admin/app-information/business-field/${id}/bidang-update`
|
||||||
|
)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
|
</CenterCustom>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
{/* <Divider /> */}
|
||||||
|
<Spacing height={5} />
|
||||||
|
|
||||||
<TextCustom>Status Aktivasi</TextCustom>
|
<TextCustom bold>Sub Bidang Bisnis</TextCustom>
|
||||||
<Switch
|
<Spacing height={5} />
|
||||||
color={MainColor.yellow}
|
|
||||||
value={data?.active}
|
{data?.subBidang?.map((item: any, index: number) => (
|
||||||
onValueChange={(value) => setData({ ...data, active: value })}
|
<BaseBox key={index}>
|
||||||
|
<StackCustom gap={0}>
|
||||||
|
<TextCustom bold>
|
||||||
|
Status: {item?.isActive ? "Aktif" : "Tidak Aktif"}
|
||||||
|
</TextCustom>
|
||||||
|
|
||||||
|
<GridSpan_NewComponent
|
||||||
|
span1={10}
|
||||||
|
span2={2}
|
||||||
|
text1={
|
||||||
|
<TextCustom bold size={"large"}>
|
||||||
|
{item.name}
|
||||||
|
</TextCustom>
|
||||||
|
}
|
||||||
|
text2={
|
||||||
|
<CenterCustom>
|
||||||
|
<ActionIcon
|
||||||
|
icon={
|
||||||
|
<IconEdit size={16} color={MainColor.black} />
|
||||||
|
}
|
||||||
|
onPress={() =>
|
||||||
|
router.push(
|
||||||
|
`/admin/app-information/business-field/${item?.id}/sub-bidang-update`
|
||||||
|
)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
|
</CenterCustom>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
))}
|
||||||
|
</StackCustom>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* <TextCustom>{JSON.stringify(data, null, 2)}</TextCustom> */}
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -0,0 +1,135 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
|
import {
|
||||||
|
BoxButtonOnFooter,
|
||||||
|
ButtonCustom,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import {
|
||||||
|
apiAdminMasterBusinessFieldById,
|
||||||
|
apiAdminMasterBusinessFieldUpdate,
|
||||||
|
} from "@/service/api-admin/api-master-admin";
|
||||||
|
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useCallback, useState } from "react";
|
||||||
|
import { Switch } from "react-native-paper";
|
||||||
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
|
export default function AdminAppInformation_BusinessFieldDetail() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const [data, setData] = useState<any | null>(null);
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
onLoadDetail();
|
||||||
|
}, [id])
|
||||||
|
);
|
||||||
|
|
||||||
|
const onLoadDetail = async () => {
|
||||||
|
try {
|
||||||
|
const response = await apiAdminMasterBusinessFieldById({
|
||||||
|
id: id as string,
|
||||||
|
category: "sub-bidang",
|
||||||
|
subBidangId: id as string,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("Response >>", JSON.stringify(response, null, 2));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
setData(response.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
setData(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlerSubmit = async () => {
|
||||||
|
if (!data.name) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Lengkapi Data",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
const response = await apiAdminMasterBusinessFieldUpdate({
|
||||||
|
id: id as string,
|
||||||
|
data: data,
|
||||||
|
category: "sub-bidang",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.success) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Gagal update data",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toast.show({
|
||||||
|
type: "success",
|
||||||
|
text1: "Data berhasil di update",
|
||||||
|
});
|
||||||
|
router.back();
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const buttonSubmit = (
|
||||||
|
<BoxButtonOnFooter>
|
||||||
|
<ButtonCustom
|
||||||
|
disabled={!data?.name}
|
||||||
|
isLoading={isLoading}
|
||||||
|
onPress={() => handlerSubmit()}
|
||||||
|
>
|
||||||
|
Update
|
||||||
|
</ButtonCustom>
|
||||||
|
</BoxButtonOnFooter>
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ViewWrapper footerComponent={buttonSubmit}>
|
||||||
|
<StackCustom>
|
||||||
|
<AdminBackButtonAntTitle title="Update Bidang Bisnis" />
|
||||||
|
|
||||||
|
<TextInputCustom
|
||||||
|
label="Nama Bidang Bisnis"
|
||||||
|
placeholder="Masukan Nama Bidang Bisnis"
|
||||||
|
required
|
||||||
|
value={data?.name}
|
||||||
|
onChangeText={(value) => setData({ ...data, name: value })}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<StackCustom
|
||||||
|
gap={"sm"}
|
||||||
|
style={{
|
||||||
|
alignContent: "flex-start",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TextCustom>Status</TextCustom>
|
||||||
|
|
||||||
|
<Switch
|
||||||
|
style={{
|
||||||
|
alignSelf: "flex-start",
|
||||||
|
}}
|
||||||
|
color={MainColor.yellow}
|
||||||
|
value={data?.isActive}
|
||||||
|
onValueChange={(value) => setData({ ...data, isActive: value })}
|
||||||
|
/>
|
||||||
|
</StackCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,40 +1,81 @@
|
|||||||
import {
|
import {
|
||||||
|
ActionIcon,
|
||||||
BoxButtonOnFooter,
|
BoxButtonOnFooter,
|
||||||
ButtonCustom,
|
ButtonCustom,
|
||||||
|
CenterCustom,
|
||||||
|
Grid,
|
||||||
|
Spacing,
|
||||||
StackCustom,
|
StackCustom,
|
||||||
TextInputCustom,
|
TextInputCustom,
|
||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { ICON_SIZE_XLARGE } from "@/constants/constans-value";
|
||||||
import { apiAdminMasterBusinessFieldCreate } from "@/service/api-admin/api-master-admin";
|
import { apiAdminMasterBusinessFieldCreate } from "@/service/api-admin/api-master-admin";
|
||||||
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
import { router } from "expo-router";
|
import { router } from "expo-router";
|
||||||
|
import _ from "lodash";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import { View } from "react-native";
|
||||||
|
import { Divider } from "react-native-paper";
|
||||||
import Toast from "react-native-toast-message";
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function AdminAppInformation_BusinessFieldCreate() {
|
export default function AdminAppInformation_BusinessFieldCreate() {
|
||||||
const [data, setData] = useState<any>({
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
const [bidang, setBidang] = useState<any>({
|
||||||
name: "",
|
name: "",
|
||||||
});
|
});
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [subBidang, setSubBidang] = useState<any[]>([
|
||||||
|
{
|
||||||
|
name: "",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
const handlerSubmit = async () => {
|
const handlerSubmit = async () => {
|
||||||
if (!data.name) {
|
if (!bidang.name) {
|
||||||
Toast.show({
|
Toast.show({
|
||||||
type: "error",
|
type: "error",
|
||||||
text1: "Lengkapi Data",
|
text1: "Lengkapi Data",
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (subBidang[0].name === "") {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Lengkapi Sub Bidang",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
const response = await apiAdminMasterBusinessFieldCreate({ data: data });
|
|
||||||
|
const newData = {
|
||||||
|
bidang: bidang,
|
||||||
|
subBidang: subBidang,
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log("[DATA]", newData);
|
||||||
|
|
||||||
|
const response = await apiAdminMasterBusinessFieldCreate({
|
||||||
|
data: newData,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("[RESPONSE]", response);
|
||||||
|
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
Toast.show({
|
Toast.show({
|
||||||
type: "success",
|
type: "success",
|
||||||
text1: "Data berhasil di tambah",
|
text1: "Data berhasil di tambah",
|
||||||
});
|
});
|
||||||
router.back();
|
// router.back();
|
||||||
|
} else {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Gagal tambah data",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("[ERROR]", error);
|
console.log("[ERROR]", error);
|
||||||
@@ -50,6 +91,7 @@ export default function AdminAppInformation_BusinessFieldCreate() {
|
|||||||
const buttonSubmit = (
|
const buttonSubmit = (
|
||||||
<BoxButtonOnFooter>
|
<BoxButtonOnFooter>
|
||||||
<ButtonCustom
|
<ButtonCustom
|
||||||
|
disabled={subBidang[0].name === ""}
|
||||||
onPress={() => handlerSubmit()}
|
onPress={() => handlerSubmit()}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
>
|
>
|
||||||
@@ -60,16 +102,70 @@ export default function AdminAppInformation_BusinessFieldCreate() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ViewWrapper footerComponent={buttonSubmit}>
|
<ViewWrapper footerComponent={buttonSubmit}>
|
||||||
<StackCustom>
|
<StackCustom gap={"xs"}>
|
||||||
<AdminBackButtonAntTitle title="Tambah Bidang Bisnis" />
|
<AdminBackButtonAntTitle title="Tambah Bidang Bisnis" />
|
||||||
|
|
||||||
<TextInputCustom
|
<TextInputCustom
|
||||||
label="Nama Bidang Bisnis"
|
label="Nama Bidang Bisnis"
|
||||||
placeholder="Masukan Nama Bidang Bisnis"
|
placeholder="Masukan Nama Bidang Bisnis"
|
||||||
required
|
required
|
||||||
value={data.name}
|
value={bidang.name}
|
||||||
onChangeText={(value) => setData({ ...data, name: value })}
|
onChangeText={(value) => setBidang({ ...bidang, name: value })}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
<Spacing height={5} />
|
||||||
|
|
||||||
|
{subBidang.map((item, index) => (
|
||||||
|
<TextInputCustom
|
||||||
|
key={index}
|
||||||
|
label="Nama Sub Bidang"
|
||||||
|
placeholder="Masukan Nama Sub Bidang"
|
||||||
|
required
|
||||||
|
value={item.name}
|
||||||
|
onChangeText={(value) => {
|
||||||
|
const list = _.clone(subBidang);
|
||||||
|
list[index].name = value;
|
||||||
|
setSubBidang(list);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<CenterCustom>
|
||||||
|
<View
|
||||||
|
style={{ flexDirection: "row", alignItems: "center", gap: 10 }}
|
||||||
|
>
|
||||||
|
<ActionIcon
|
||||||
|
onPress={() => {
|
||||||
|
setSubBidang([...subBidang, { name: "" }]);
|
||||||
|
}}
|
||||||
|
icon={
|
||||||
|
<Ionicons
|
||||||
|
name="add-circle-outline"
|
||||||
|
size={ICON_SIZE_XLARGE}
|
||||||
|
color={MainColor.black}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
size="xl"
|
||||||
|
/>
|
||||||
|
<ActionIcon
|
||||||
|
disabled={subBidang.length <= 1}
|
||||||
|
onPress={() => {
|
||||||
|
const list = _.clone(subBidang);
|
||||||
|
list.pop();
|
||||||
|
setSubBidang(list);
|
||||||
|
}}
|
||||||
|
icon={
|
||||||
|
<Ionicons
|
||||||
|
name="remove-circle-outline"
|
||||||
|
size={ICON_SIZE_XLARGE}
|
||||||
|
color={MainColor.black}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
size="xl"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</CenterCustom>
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ const listPage = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "2",
|
id: "2",
|
||||||
label: "Bidang Bisnis",
|
label: "Bidang & Sub Bidang",
|
||||||
value: "business",
|
value: "business",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,11 +2,13 @@
|
|||||||
import {
|
import {
|
||||||
BaseBox,
|
BaseBox,
|
||||||
Grid,
|
Grid,
|
||||||
|
Spacing,
|
||||||
StackCustom,
|
StackCustom,
|
||||||
TextCustom,
|
TextCustom,
|
||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||||
|
import { GridSpan_4_8 } from "@/components/_ShareComponent/GridSpan_4_8";
|
||||||
import { apiAdminCollaborationGetById } from "@/service/api-admin/api-admin-collaboration";
|
import { apiAdminCollaborationGetById } from "@/service/api-admin/api-admin-collaboration";
|
||||||
import { useFocusEffect, useLocalSearchParams } from "expo-router";
|
import { useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useState } from "react";
|
||||||
@@ -28,6 +30,8 @@ export default function AdminCollaborationGroup() {
|
|||||||
category: "group",
|
category: "group",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log("[DATA]", JSON.stringify(response.data, null, 2));
|
||||||
|
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
setData(response.data);
|
setData(response.data);
|
||||||
}
|
}
|
||||||
@@ -59,38 +63,33 @@ export default function AdminCollaborationGroup() {
|
|||||||
))}
|
))}
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
</BaseBox>
|
</BaseBox>
|
||||||
|
|
||||||
|
<TextCustom bold>Anggota</TextCustom>
|
||||||
|
<Spacing height={5}/>
|
||||||
<BaseBox>
|
<BaseBox>
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
<TextCustom align="center">Anggota</TextCustom>
|
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={6} style={{ justifyContent: "center", paddingRight: 10 }}>
|
||||||
|
<TextCustom bold>Nomor</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={6} style={{ justifyContent: "center" }}>
|
||||||
|
<TextCustom bold>Username</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
{data?.ProjectCollaboration_AnggotaRoomChat?.map(
|
{data?.ProjectCollaboration_AnggotaRoomChat?.map(
|
||||||
(item: any, index: number) => (
|
(item: any, index: number) => (
|
||||||
<StackCustom key={index} gap={0}>
|
<Grid key={index}>
|
||||||
<Grid>
|
<Grid.Col span={6} style={{ justifyContent: "center", paddingRight: 10 }}>
|
||||||
<Grid.Col
|
<TextCustom bold truncate>+{item?.User?.nomor || "-"}</TextCustom>
|
||||||
span={4}
|
|
||||||
style={{ justifyContent: "center", paddingRight: 10 }}
|
|
||||||
>
|
|
||||||
<TextCustom bold>Nama</TextCustom>
|
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
<Grid.Col span={8} style={{ justifyContent: "center" }}>
|
<Grid.Col span={6} style={{ justifyContent: "center" }}>
|
||||||
<TextCustom>
|
<TextCustom bold>
|
||||||
{item?.User?.Profile?.name || "-"}
|
{item?.User?.username || "-"}
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid>
|
|
||||||
<Grid.Col
|
|
||||||
span={4}
|
|
||||||
style={{ justifyContent: "center", paddingRight: 10 }}
|
|
||||||
>
|
|
||||||
<TextCustom bold>Username</TextCustom>
|
|
||||||
</Grid.Col>
|
|
||||||
<Grid.Col span={8} style={{ justifyContent: "center" }}>
|
|
||||||
<TextCustom>{item?.User?.username || "-"}</TextCustom>
|
|
||||||
</Grid.Col>
|
|
||||||
</Grid>
|
|
||||||
</StackCustom>
|
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
|
|||||||
@@ -1,17 +1,14 @@
|
|||||||
import {
|
import {
|
||||||
ActionIcon,
|
ClickableCustom,
|
||||||
LoaderCustom,
|
LoaderCustom,
|
||||||
StackCustom,
|
StackCustom,
|
||||||
TextCustom,
|
TextCustom,
|
||||||
ViewWrapper
|
ViewWrapper
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
|
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 AdminTitlePage from "@/components/_ShareComponent/Admin/TitlePage";
|
||||||
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
|
import { GridSpan_NewComponent } from "@/components/_ShareComponent/GridSpan_NewComponent";
|
||||||
import { apiAdminCollaboration } from "@/service/api-admin/api-admin-collaboration";
|
import { apiAdminCollaboration } from "@/service/api-admin/api-admin-collaboration";
|
||||||
import { Octicons } from "@expo/vector-icons";
|
|
||||||
import { router, useFocusEffect } from "expo-router";
|
import { router, useFocusEffect } from "expo-router";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useState } from "react";
|
||||||
@@ -51,10 +48,19 @@ export default function AdminCollaborationGroup() {
|
|||||||
<StackCustom>
|
<StackCustom>
|
||||||
<AdminComp_BoxTitle title="Group" />
|
<AdminComp_BoxTitle title="Group" />
|
||||||
<>
|
<>
|
||||||
<AdminTitleTable
|
<GridSpan_NewComponent
|
||||||
title1="Aksi"
|
span1={6}
|
||||||
title2="Jumlah peserta"
|
span2={6}
|
||||||
title3="Nama group"
|
text1={
|
||||||
|
<TextCustom bold truncate align="center">
|
||||||
|
Jumlah Anggota
|
||||||
|
</TextCustom>
|
||||||
|
}
|
||||||
|
text2={
|
||||||
|
<TextCustom bold truncate>
|
||||||
|
Nama Group
|
||||||
|
</TextCustom>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
<Divider />
|
<Divider />
|
||||||
|
|
||||||
@@ -67,31 +73,27 @@ export default function AdminCollaborationGroup() {
|
|||||||
) : (
|
) : (
|
||||||
list?.map((item: any, index: number) => (
|
list?.map((item: any, index: number) => (
|
||||||
<View key={index}>
|
<View key={index}>
|
||||||
<AdminTableValue
|
<ClickableCustom
|
||||||
value1={
|
|
||||||
<ActionIcon
|
|
||||||
icon={
|
|
||||||
<Octicons
|
|
||||||
name="eye"
|
|
||||||
size={ICON_SIZE_BUTTON}
|
|
||||||
color="black"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
router.push(`/admin/collaboration/${item.id}/group`);
|
router.push(`/admin/collaboration/${item.id}/group`);
|
||||||
}}
|
}}
|
||||||
/>
|
>
|
||||||
}
|
<GridSpan_NewComponent
|
||||||
value2={
|
span1={6}
|
||||||
<TextCustom truncate={1}>
|
span2={6}
|
||||||
|
text1={
|
||||||
|
<TextCustom truncate={1} align="center">
|
||||||
{item?.ProjectCollaboration_AnggotaRoomChat?.length ||
|
{item?.ProjectCollaboration_AnggotaRoomChat?.length ||
|
||||||
"-"}
|
"-"}
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
}
|
}
|
||||||
value3={
|
text2={
|
||||||
<TextCustom truncate={2}>{item?.name || "-"}</TextCustom>
|
<TextCustom truncate={2}>
|
||||||
|
{item?.name || "-"}
|
||||||
|
</TextCustom>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
</ClickableCustom>
|
||||||
</View>
|
</View>
|
||||||
))
|
))
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import {
|
import {
|
||||||
ActionIcon,
|
ActionIcon,
|
||||||
|
ClickableCustom,
|
||||||
LoaderCustom,
|
LoaderCustom,
|
||||||
|
Spacing,
|
||||||
StackCustom,
|
StackCustom,
|
||||||
TextCustom,
|
TextCustom,
|
||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
@@ -9,6 +11,7 @@ import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage"
|
|||||||
import AdminTitleTable from "@/components/_ShareComponent/Admin/TableTitle";
|
import AdminTitleTable from "@/components/_ShareComponent/Admin/TableTitle";
|
||||||
import AdminTableValue from "@/components/_ShareComponent/Admin/TableValue";
|
import AdminTableValue from "@/components/_ShareComponent/Admin/TableValue";
|
||||||
import AdminTitlePage from "@/components/_ShareComponent/Admin/TitlePage";
|
import AdminTitlePage from "@/components/_ShareComponent/Admin/TitlePage";
|
||||||
|
import { GridSpan_NewComponent } from "@/components/_ShareComponent/GridSpan_NewComponent";
|
||||||
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
|
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
|
||||||
import { apiAdminCollaboration } from "@/service/api-admin/api-admin-collaboration";
|
import { apiAdminCollaboration } from "@/service/api-admin/api-admin-collaboration";
|
||||||
import { Octicons } from "@expo/vector-icons";
|
import { Octicons } from "@expo/vector-icons";
|
||||||
@@ -51,11 +54,7 @@ export default function AdminCollaborationPublish() {
|
|||||||
<StackCustom>
|
<StackCustom>
|
||||||
<AdminComp_BoxTitle title="Publish" />
|
<AdminComp_BoxTitle title="Publish" />
|
||||||
|
|
||||||
<AdminTitleTable
|
<GridSpan_NewComponent text1={<TextCustom bold>Username</TextCustom>} text2={<TextCustom bold>Judul Proyek</TextCustom>} />
|
||||||
title1="Aksi"
|
|
||||||
title2="Username"
|
|
||||||
title3="Judul Proyek"
|
|
||||||
/>
|
|
||||||
{/* <Spacing height={10} /> */}
|
{/* <Spacing height={10} /> */}
|
||||||
<Divider />
|
<Divider />
|
||||||
|
|
||||||
@@ -68,32 +67,26 @@ export default function AdminCollaborationPublish() {
|
|||||||
) : (
|
) : (
|
||||||
list?.map((item: any, index: number) => (
|
list?.map((item: any, index: number) => (
|
||||||
<View key={index}>
|
<View key={index}>
|
||||||
<AdminTableValue
|
<ClickableCustom
|
||||||
value1={
|
|
||||||
<ActionIcon
|
|
||||||
icon={
|
|
||||||
<Octicons
|
|
||||||
name="eye"
|
|
||||||
size={ICON_SIZE_BUTTON}
|
|
||||||
color="black"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
router.push(`/admin/collaboration/${item?.id}/publish`);
|
router.push(`/admin/collaboration/${item?.id}/publish`);
|
||||||
}}
|
}}
|
||||||
/>
|
>
|
||||||
}
|
<GridSpan_NewComponent
|
||||||
value2={
|
text1={
|
||||||
<TextCustom align="center" truncate={1}>
|
<TextCustom truncate={1}>
|
||||||
{item?.Author?.username || "-"}{" "}
|
{item?.Author?.username || "-"}{" "}
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
}
|
}
|
||||||
value3={
|
text2={
|
||||||
<TextCustom align="center" truncate={2}>
|
<TextCustom truncate={2}>
|
||||||
{item?.title || "-"}
|
{item?.title || "-"}
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
</ClickableCustom>
|
||||||
|
<Spacing height={8}/>
|
||||||
|
<Divider/>
|
||||||
</View>
|
</View>
|
||||||
))
|
))
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import {
|
import {
|
||||||
ActionIcon,
|
ActionIcon,
|
||||||
AlertDefaultSystem,
|
AlertDefaultSystem,
|
||||||
@@ -17,98 +18,154 @@ import { IconDot, IconList } from "@/components/_Icon/IconComponent";
|
|||||||
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||||
import AdminButtonReject from "@/components/_ShareComponent/Admin/ButtonReject";
|
import AdminButtonReject from "@/components/_ShareComponent/Admin/ButtonReject";
|
||||||
import AdminButtonReview from "@/components/_ShareComponent/Admin/ButtonReview";
|
import AdminButtonReview from "@/components/_ShareComponent/Admin/ButtonReview";
|
||||||
import { GridDetail_4_8 } from "@/components/_ShareComponent/GridDetail_4_8";
|
import { GridSpan_4_8 } from "@/components/_ShareComponent/GridSpan_4_8";
|
||||||
import { MainColor } from "@/constants/color-palet";
|
import ReportBox from "@/components/Box/ReportBox";
|
||||||
import { ICON_SIZE_BUTTON, TEXT_SIZE_LARGE } from "@/constants/constans-value";
|
import { ICON_SIZE_BUTTON, TEXT_SIZE_LARGE } from "@/constants/constans-value";
|
||||||
import AdminDonation_BoxOfDonationStory from "@/screens/Admin/Donation/BoxOfDonationStory";
|
import AdminDonation_BoxOfDonationStory from "@/screens/Admin/Donation/BoxOfDonationStory";
|
||||||
|
import { funUpdateStatusDonation } from "@/screens/Admin/Donation/funDonationUpdateStatus";
|
||||||
|
import { apiAdminDonationDetailById } from "@/service/api-admin/api-admin-donation";
|
||||||
|
import { colorBadgeStatus } from "@/utils/colorBadge";
|
||||||
|
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
|
||||||
import { Ionicons } from "@expo/vector-icons";
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
import { router, useLocalSearchParams } from "expo-router";
|
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { View } from "react-native";
|
import { View } from "react-native";
|
||||||
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function AdminDonationDetail() {
|
export default function AdminDonationDetail() {
|
||||||
const { id, status } = useLocalSearchParams();
|
const { id, status } = useLocalSearchParams();
|
||||||
const [openDrawer, setOpenDrawer] = React.useState(false);
|
const [openDrawer, setOpenDrawer] = React.useState(false);
|
||||||
|
|
||||||
const colorBadge = () => {
|
const [data, setData] = React.useState<any | null>(null);
|
||||||
if (status === "publish") {
|
const [countDonatur, setCountDonatur] = React.useState(0);
|
||||||
return MainColor.green;
|
const [isLoading, setIsLoading] = React.useState(false);
|
||||||
} else if (status === "review") {
|
|
||||||
return MainColor.orange;
|
useFocusEffect(
|
||||||
} else if (status === "reject") {
|
React.useCallback(() => {
|
||||||
return MainColor.red;
|
onLoadData();
|
||||||
} else {
|
}, [id])
|
||||||
return MainColor.placeholder;
|
);
|
||||||
|
|
||||||
|
const onLoadData = async () => {
|
||||||
|
try {
|
||||||
|
const response = await apiAdminDonationDetailById({
|
||||||
|
id: id as string,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
setData(response.data.donasi);
|
||||||
|
setCountDonatur(response.data.donatur);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
setData(null);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const listData = [
|
const listData = [
|
||||||
{
|
{
|
||||||
label: "Penggalang Dana",
|
label: "Penggalang Dana",
|
||||||
value: `Bagas Banuna ${id}`,
|
value: (data && data?.Author?.username) || "-",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Judul",
|
label: "Judul",
|
||||||
value: `Donasi Lorem ipsum dolor sit amet, consectetur adipisicing elit.`,
|
value: (data && data?.title) || "-",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Status",
|
label: "Status",
|
||||||
value: (
|
value:
|
||||||
<BadgeCustom color={colorBadge()}>
|
data && data?.DonasiMaster_Status?.name ? (
|
||||||
{_.startCase(status as string)}
|
<BadgeCustom
|
||||||
|
color={colorBadgeStatus({
|
||||||
|
status: data?.DonasiMaster_Status?.name,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{_.startCase(data?.DonasiMaster_Status?.name)}
|
||||||
</BadgeCustom>
|
</BadgeCustom>
|
||||||
|
) : (
|
||||||
|
"-"
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Durasi",
|
label: "Durasi",
|
||||||
value: "30 Hari",
|
value: (data && data?.DonasiMaster_Durasi?.name) + " hari" || "-",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Target Dana",
|
label: "Target Dana",
|
||||||
value: "Rp 10.000.000",
|
value:
|
||||||
|
data && data?.target
|
||||||
|
? `Rp. ${formatCurrencyDisplay(data?.target)}`
|
||||||
|
: "-",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Kategori",
|
label: "Kategori",
|
||||||
value: "Kategori Donasi",
|
value: (data && data?.DonasiMaster_Ketegori?.name) || "-",
|
||||||
},
|
},
|
||||||
// {
|
|
||||||
// label: "Total Donatur",
|
|
||||||
// value: "-",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// label: "Progress",
|
|
||||||
// value: "0 %",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// label: "Dana Terkumpul",
|
|
||||||
// value: "Rp 0",
|
|
||||||
// },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const listPencarianDana = [
|
const listPencarianDana = [
|
||||||
{
|
{
|
||||||
label: "Total Dana Dicairkan",
|
label: "Total Dana Dicairkan",
|
||||||
value: "Rp 0",
|
value: `Rp ${(data && formatCurrencyDisplay(data?.totalPencairan)) || 0}`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Sisa Dana",
|
label: "Sisa Dana Masuk",
|
||||||
value: "Rp 0",
|
value: `Rp ${
|
||||||
|
(data &&
|
||||||
|
formatCurrencyDisplay(data?.terkumpul - data?.totalPencairan)) ||
|
||||||
|
0
|
||||||
|
}`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Akumulasi Pencairan",
|
label: "Akumulasi Pencairan",
|
||||||
value: "0 kali",
|
value: `${(data && data?.akumulasiPencairan) || 0} kali`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Bank Tujuan",
|
label: "Bank Tujuan",
|
||||||
value: "BNI",
|
value: (data && data?.namaBank) || "-",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Nomor Rekening",
|
label: "Nomor Rekening",
|
||||||
value: "123456789",
|
value: (data && data?.rekening) || "-",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const handleReport = async ({
|
||||||
|
changeStatus,
|
||||||
|
}: {
|
||||||
|
changeStatus: "publish" | "review" | "reject";
|
||||||
|
}) => {
|
||||||
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
const response = await funUpdateStatusDonation({
|
||||||
|
id: id as string,
|
||||||
|
changeStatus,
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.success) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Update status gagal",
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toast.show({
|
||||||
|
type: "success",
|
||||||
|
text1: "Update status berhasil",
|
||||||
|
});
|
||||||
|
|
||||||
|
router.back();
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const rightComponent = (
|
const rightComponent = (
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
icon={<IconDot size={ICON_SIZE_BUTTON} />}
|
icon={<IconDot size={ICON_SIZE_BUTTON} />}
|
||||||
@@ -118,8 +175,6 @@ export default function AdminDonationDetail() {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ViewWrapper
|
<ViewWrapper
|
||||||
@@ -140,18 +195,27 @@ export default function AdminDonationDetail() {
|
|||||||
|
|
||||||
<StackCustom gap={5}>
|
<StackCustom gap={5}>
|
||||||
{listPencarianDana.map((item, i) => (
|
{listPencarianDana.map((item, i) => (
|
||||||
<GridDetail_4_8
|
<GridSpan_4_8
|
||||||
key={i}
|
key={i}
|
||||||
label={<TextCustom bold>{item.label}</TextCustom>}
|
label={<TextCustom bold>{item.label}</TextCustom>}
|
||||||
value={<TextCustom>{item.value}</TextCustom>}
|
value={<TextCustom>{item.value}</TextCustom>}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
|
|
||||||
<ButtonCustom
|
<ButtonCustom
|
||||||
iconLeft={
|
iconLeft={
|
||||||
<Ionicons name="cash-outline" size={ICON_SIZE_BUTTON} />
|
<Ionicons name="cash-outline" size={ICON_SIZE_BUTTON} />
|
||||||
}
|
}
|
||||||
|
disabled={data?.terkumpul - data?.totalPencairan <= 0}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
|
if (data?.terkumpul - data?.totalPencairan <= 0) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Tidak ada dana yang tersisa",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
router.push(`/admin/donation/${id}/disbursement-of-funds`);
|
router.push(`/admin/donation/${id}/disbursement-of-funds`);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -161,16 +225,32 @@ export default function AdminDonationDetail() {
|
|||||||
</BaseBox>
|
</BaseBox>
|
||||||
|
|
||||||
<BaseBox>
|
<BaseBox>
|
||||||
<ProgressCustom size="lg" />
|
<ProgressCustom
|
||||||
<Spacing />
|
size="lg"
|
||||||
<StackCustom gap={"xs"}>
|
value={Number(data?.progres) || 0}
|
||||||
<GridDetail_4_8
|
showLabel={true}
|
||||||
label={<TextCustom bold>Jumlah Donatur</TextCustom>}
|
label={data?.progres + "%"}
|
||||||
value={<TextCustom>0 orang</TextCustom>}
|
animated
|
||||||
|
color="primary"
|
||||||
/>
|
/>
|
||||||
<GridDetail_4_8
|
<Spacing />
|
||||||
|
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<GridSpan_4_8
|
||||||
|
label={<TextCustom bold>Jumlah Donatur</TextCustom>}
|
||||||
|
value={
|
||||||
|
<TextCustom>
|
||||||
|
{countDonatur ? countDonatur : 0} orang
|
||||||
|
</TextCustom>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<GridSpan_4_8
|
||||||
label={<TextCustom bold>Dana Terkumpul</TextCustom>}
|
label={<TextCustom bold>Dana Terkumpul</TextCustom>}
|
||||||
value={<TextCustom>Rp 0</TextCustom>}
|
value={
|
||||||
|
<TextCustom>
|
||||||
|
Rp {formatCurrencyDisplay(data?.terkumpul || 0)}
|
||||||
|
</TextCustom>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
</BaseBox>
|
</BaseBox>
|
||||||
@@ -179,9 +259,9 @@ export default function AdminDonationDetail() {
|
|||||||
|
|
||||||
<BaseBox>
|
<BaseBox>
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
<DummyLandscapeImage />
|
<DummyLandscapeImage imageId={data?.imageId || ""} />
|
||||||
{listData.map((item, i) => (
|
{listData.map((item, i) => (
|
||||||
<GridDetail_4_8
|
<GridSpan_4_8
|
||||||
key={i}
|
key={i}
|
||||||
label={<TextCustom bold>{item.label}</TextCustom>}
|
label={<TextCustom bold>{item.label}</TextCustom>}
|
||||||
value={<TextCustom>{item.value}</TextCustom>}
|
value={<TextCustom>{item.value}</TextCustom>}
|
||||||
@@ -190,27 +270,33 @@ export default function AdminDonationDetail() {
|
|||||||
</StackCustom>
|
</StackCustom>
|
||||||
</BaseBox>
|
</BaseBox>
|
||||||
|
|
||||||
|
<AdminDonation_BoxOfDonationStory data={data?.CeritaDonasi as any} />
|
||||||
|
|
||||||
|
{data &&
|
||||||
|
data?.catatan &&
|
||||||
|
(status === "review" || status === "reject") && (
|
||||||
|
<ReportBox text={data?.catatan} />
|
||||||
|
)}
|
||||||
|
|
||||||
{status === "review" && (
|
{status === "review" && (
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
<AdminDonation_BoxOfDonationStory />
|
|
||||||
|
|
||||||
<AdminButtonReview
|
<AdminButtonReview
|
||||||
|
isLoading={isLoading}
|
||||||
onPublish={() => {
|
onPublish={() => {
|
||||||
AlertDefaultSystem({
|
AlertDefaultSystem({
|
||||||
title: "Publish",
|
title: "Publish",
|
||||||
message: "Apakah anda yakin ingin mempublikasikan data ini?",
|
message: "Apakah anda yakin ingin mempublikasikan data ini?",
|
||||||
textLeft: "Batal",
|
textLeft: "Batal",
|
||||||
textRight: "Ya",
|
textRight: "Ya",
|
||||||
onPressLeft: () => {
|
|
||||||
router.back();
|
|
||||||
},
|
|
||||||
onPressRight: () => {
|
onPressRight: () => {
|
||||||
router.back();
|
handleReport({ changeStatus: "publish" });
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
onReject={() => {
|
onReject={() => {
|
||||||
router.push(`/admin/donation/${id}/reject-input`);
|
router.push(
|
||||||
|
`/admin/donation/${id}/reject-input?status=${status}`
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
@@ -218,12 +304,12 @@ export default function AdminDonationDetail() {
|
|||||||
|
|
||||||
{status === "reject" && (
|
{status === "reject" && (
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
<AdminDonation_BoxOfDonationStory />
|
|
||||||
|
|
||||||
<AdminButtonReject
|
<AdminButtonReject
|
||||||
title="Tambah Catatan"
|
title="Tambah Catatan"
|
||||||
onReject={() => {
|
onReject={() => {
|
||||||
router.push(`/admin/donation/${id}/reject-input`);
|
router.push(
|
||||||
|
`/admin/donation/${id}/reject-input?status=${status}`
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
|
|||||||
@@ -8,52 +8,163 @@ import {
|
|||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||||
import { GridDetail_4_8 } from "@/components/_ShareComponent/GridDetail_4_8";
|
import { GridSpan_4_8 } from "@/components/_ShareComponent/GridSpan_4_8";
|
||||||
import { MainColor } from "@/constants/color-palet";
|
import {
|
||||||
import dayjs from "dayjs";
|
apiAdminDonationInvoiceDetailById,
|
||||||
import { router, useLocalSearchParams } from "expo-router";
|
apiAdminDonationInvoiceUpdateById,
|
||||||
|
} from "@/service/api-admin/api-admin-donation";
|
||||||
|
import { colorBadgeTransaction } from "@/utils/colorBadge";
|
||||||
|
import { dateTimeView } from "@/utils/dateTimeView";
|
||||||
|
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
|
||||||
|
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { useCallback, useState } from "react";
|
||||||
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function AdminDonasiTransactionDetail() {
|
export default function AdminDonasiTransactionDetail() {
|
||||||
const { id } = useLocalSearchParams();
|
const { id, status } = useLocalSearchParams();
|
||||||
|
console.log("[STATUS]", id, status);
|
||||||
|
|
||||||
const buttonAction = (
|
const [data, setData] = useState<any | null>(null);
|
||||||
|
const [isLoading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
onLoadData();
|
||||||
|
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [id])
|
||||||
|
);
|
||||||
|
|
||||||
|
const onLoadData = async () => {
|
||||||
|
try {
|
||||||
|
const response = await apiAdminDonationInvoiceDetailById({
|
||||||
|
id: id as string,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("[GET INVOICE BY ID]", JSON.stringify(response, null, 2));
|
||||||
|
if (response.success) {
|
||||||
|
setData(response.data);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlerSubmit = async () => {
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
const newData = {
|
||||||
|
donationId: data?.donasiId,
|
||||||
|
nominal: data?.nominal,
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await apiAdminDonationInvoiceUpdateById({
|
||||||
|
id: id as string,
|
||||||
|
data: newData,
|
||||||
|
status: "berhasil",
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("[UPDATE INVOICE]", JSON.stringify(response, null, 2));
|
||||||
|
|
||||||
|
if (!response.success) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: response.message,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Toast.show({
|
||||||
|
type: "success",
|
||||||
|
text1: response.message,
|
||||||
|
});
|
||||||
|
router.back();
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const buttonAction = () => {
|
||||||
|
if (data && data?.DonasiMaster_StatusInvoice?.name === "Menunggu") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data && data?.DonasiMaster_StatusInvoice?.name === "Proses") {
|
||||||
|
return (
|
||||||
<BoxButtonOnFooter>
|
<BoxButtonOnFooter>
|
||||||
<ButtonCustom onPress={() => router.back()}>Terima</ButtonCustom>
|
<ButtonCustom
|
||||||
|
isLoading={isLoading}
|
||||||
|
onPress={() => {
|
||||||
|
handlerSubmit();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Terima donasi
|
||||||
|
</ButtonCustom>
|
||||||
</BoxButtonOnFooter>
|
</BoxButtonOnFooter>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BoxButtonOnFooter>
|
||||||
|
<ButtonCustom disabled>
|
||||||
|
{data?.DonasiMaster_StatusInvoice?.name}
|
||||||
|
</ButtonCustom>
|
||||||
|
</BoxButtonOnFooter>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const listData = [
|
const listData = [
|
||||||
{
|
{
|
||||||
label: "Donatur",
|
label: "Donatur",
|
||||||
value: "Bagas Banuna",
|
value: (data && data?.Author?.username) || "-",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Bank",
|
label: "Bank",
|
||||||
value: "BCA",
|
value: (data && data?.MasterBank?.namaBank) || "-",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Jumlah Donasi",
|
label: "Jumlah Donasi",
|
||||||
value: "Rp. 1.000.000",
|
value: `Rp. ${
|
||||||
|
(data && data?.nominal && formatCurrencyDisplay(data?.nominal)) || "-"
|
||||||
|
}`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Status",
|
label: "Status",
|
||||||
value: <BadgeCustom color={MainColor.green}>Berhasil</BadgeCustom>,
|
value:
|
||||||
|
(data && data?.DonasiMaster_StatusInvoice?.name && (
|
||||||
|
<BadgeCustom
|
||||||
|
color={colorBadgeTransaction({
|
||||||
|
status: data?.DonasiMaster_StatusInvoice?.name as any,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{_.startCase(
|
||||||
|
(data?.DonasiMaster_StatusInvoice?.name as any) || "-"
|
||||||
|
)}
|
||||||
|
</BadgeCustom>
|
||||||
|
)) ||
|
||||||
|
"-",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Tanggal",
|
label: "Tanggal",
|
||||||
value: dayjs().format("DD-MM-YYYY HH:mm:ss"),
|
value: (data && dateTimeView({ date: data?.createdAt })) || "-",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Bukti Transfer",
|
label: "Bukti Transfer",
|
||||||
value: (
|
value:
|
||||||
|
(data && data?.imageId && (
|
||||||
<ButtonCustom
|
<ButtonCustom
|
||||||
onPress={() =>
|
onPress={() =>
|
||||||
router.push(`/(application)/(image)/preview-image/${id}`)
|
router.push(
|
||||||
|
`/(application)/(image)/preview-image/${data?.imageId}`
|
||||||
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Cek
|
Cek
|
||||||
</ButtonCustom>
|
</ButtonCustom>
|
||||||
),
|
)) ||
|
||||||
|
"-",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -61,12 +172,12 @@ export default function AdminDonasiTransactionDetail() {
|
|||||||
<>
|
<>
|
||||||
<ViewWrapper
|
<ViewWrapper
|
||||||
headerComponent={<AdminBackButtonAntTitle title="Detail Transaksi" />}
|
headerComponent={<AdminBackButtonAntTitle title="Detail Transaksi" />}
|
||||||
footerComponent={buttonAction}
|
footerComponent={buttonAction()}
|
||||||
>
|
>
|
||||||
<BaseBox>
|
<BaseBox>
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
{listData.map((item, index) => (
|
{listData.map((item, index) => (
|
||||||
<GridDetail_4_8
|
<GridSpan_4_8
|
||||||
key={index}
|
key={index}
|
||||||
label={<TextCustom bold>{item.label}</TextCustom>}
|
label={<TextCustom bold>{item.label}</TextCustom>}
|
||||||
value={<TextCustom>{item.value}</TextCustom>}
|
value={<TextCustom>{item.value}</TextCustom>}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import {
|
import {
|
||||||
BaseBox,
|
BaseBox,
|
||||||
ButtonCustom,
|
ButtonCustom,
|
||||||
@@ -6,28 +7,54 @@ import {
|
|||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||||
import { GridDetail_4_8 } from "@/components/_ShareComponent/GridDetail_4_8";
|
import { GridSpan_4_8 } from "@/components/_ShareComponent/GridSpan_4_8";
|
||||||
import dayjs from "dayjs";
|
import { apiAdminDonationDisbursementOfFundsListById } from "@/service/api-admin/api-admin-donation";
|
||||||
import { router, useLocalSearchParams } from "expo-router";
|
import { dateTimeView } from "@/utils/dateTimeView";
|
||||||
|
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
|
||||||
|
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
|
import React, { useCallback } from "react";
|
||||||
|
|
||||||
export default function AdminDonationDetailDisbursementOfFunds() {
|
export default function AdminDonationDetailDisbursementOfFunds() {
|
||||||
const { id } = useLocalSearchParams();
|
const { id } = useLocalSearchParams();
|
||||||
|
const [data, setData] = React.useState<any | null>(null);
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
onLoadData();
|
||||||
|
}, [id])
|
||||||
|
);
|
||||||
|
|
||||||
|
const onLoadData = async () => {
|
||||||
|
try {
|
||||||
|
const response = await apiAdminDonationDisbursementOfFundsListById({
|
||||||
|
id: id as string,
|
||||||
|
category: "get-one",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
setData(response.data);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const listData = [
|
const listData = [
|
||||||
{
|
{
|
||||||
label: "Nominal",
|
label: "Nominal",
|
||||||
value: "Rp 1.000.000",
|
value: `Rp ${(data && formatCurrencyDisplay(data?.nominalCair)) || 0}`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Tanggal",
|
label: "Tanggal",
|
||||||
value: dayjs().format("DD-MM-YYYY HH:mm"),
|
value: dateTimeView({ date: data?.createdAt }),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Judul",
|
label: "Judul",
|
||||||
value: `Judul Pencairan Dana ${id}`,
|
value: (data && data?.title) || "-",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Deskripsi",
|
label: "Deskripsi",
|
||||||
value: `Lorem ipsum dolor sit amet consectetur adipisicing elit. Itaque velit eos facere a dicta nemo repellendus harum laboriosam quos, earum reprehenderit. Nisi sapiente, quo earum quis alias ullam temporibus quidem.`,
|
value: (data && data?.deskripsi) || "-",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
return (
|
return (
|
||||||
@@ -39,8 +66,8 @@ export default function AdminDonationDetailDisbursementOfFunds() {
|
|||||||
>
|
>
|
||||||
<BaseBox>
|
<BaseBox>
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
{listData.map((item, index) => (
|
{listData?.map((item, index) => (
|
||||||
<GridDetail_4_8
|
<GridSpan_4_8
|
||||||
key={index}
|
key={index}
|
||||||
label={<TextCustom bold>{item.label}</TextCustom>}
|
label={<TextCustom bold>{item.label}</TextCustom>}
|
||||||
value={<TextCustom>{item.value}</TextCustom>}
|
value={<TextCustom>{item.value}</TextCustom>}
|
||||||
@@ -51,7 +78,7 @@ export default function AdminDonationDetailDisbursementOfFunds() {
|
|||||||
|
|
||||||
<ButtonCustom
|
<ButtonCustom
|
||||||
onPress={() =>
|
onPress={() =>
|
||||||
router.push(`/(application)/(image)/preview-image/${id}`)
|
router.push(`/(application)/(image)/preview-image/${data?.imageId}`)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Cek Bukti Transaksi
|
Cek Bukti Transaksi
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import {
|
import {
|
||||||
BaseBox,
|
BaseBox,
|
||||||
BoxButtonOnFooter,
|
BoxButtonOnFooter,
|
||||||
@@ -12,15 +13,122 @@ import {
|
|||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||||
import { router, useLocalSearchParams } from "expo-router";
|
import DIRECTORY_ID from "@/constants/directory-id";
|
||||||
|
import { apiAdminDonationDetailById, apiAdminDonationDisbursementOfFundsCreated } from "@/service/api-admin/api-admin-donation";
|
||||||
|
import { uploadFileService } from "@/service/upload-service";
|
||||||
|
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
|
||||||
|
import pickFile from "@/utils/pickFile";
|
||||||
|
import { Image } from "expo-image";
|
||||||
|
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
|
import React from "react";
|
||||||
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function AdminDonationDisbursementOfFunds() {
|
export default function AdminDonationDisbursementOfFunds() {
|
||||||
const { id } = useLocalSearchParams();
|
const { id } = useLocalSearchParams();
|
||||||
const handleSubmit = (
|
|
||||||
|
const [data, setData] = React.useState<any | null>(null);
|
||||||
|
const [isLoading, setIsLoading] = React.useState(false);
|
||||||
|
|
||||||
|
const [value, setValue] = React.useState({
|
||||||
|
nominalCair: "",
|
||||||
|
title: "",
|
||||||
|
deskripsi: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const [image, setImage] = React.useState<any | null>(null);
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
React.useCallback(() => {
|
||||||
|
onLoadData();
|
||||||
|
}, [id])
|
||||||
|
);
|
||||||
|
|
||||||
|
const onLoadData = async () => {
|
||||||
|
try {
|
||||||
|
const response = await apiAdminDonationDetailById({
|
||||||
|
id: id as string,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
setData(response.data.donasi);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
setData(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
if (!image) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Harap upload bukti transfer",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!value.nominalCair || !value.title || !value.deskripsi) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Harap isi semua data",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
const uploadImage = await uploadFileService({
|
||||||
|
dirId: DIRECTORY_ID.donasi_bukti_trf_pencairan_dana,
|
||||||
|
imageUri: image.uri,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!uploadFileService) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Gagal mengunggah gambar",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const imageId = uploadImage.data.id;
|
||||||
|
|
||||||
|
const newData = {
|
||||||
|
...value,
|
||||||
|
imageId: imageId,
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await apiAdminDonationDisbursementOfFundsCreated({
|
||||||
|
id: id as string,
|
||||||
|
data: newData,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.success) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: response.message,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toast.show({
|
||||||
|
type: "success",
|
||||||
|
text1: "Pencairan dana berhasil disimpan",
|
||||||
|
});
|
||||||
|
|
||||||
|
router.back();
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const buttonSubmit = (
|
||||||
<BoxButtonOnFooter>
|
<BoxButtonOnFooter>
|
||||||
<ButtonCustom
|
<ButtonCustom
|
||||||
|
isLoading={isLoading}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
router.back();
|
handleSubmit();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Simpan
|
Simpan
|
||||||
@@ -31,7 +139,7 @@ export default function AdminDonationDisbursementOfFunds() {
|
|||||||
return (
|
return (
|
||||||
<ViewWrapper
|
<ViewWrapper
|
||||||
headerComponent={<AdminBackButtonAntTitle title="Pencairan Dana" />}
|
headerComponent={<AdminBackButtonAntTitle title="Pencairan Dana" />}
|
||||||
footerComponent={handleSubmit}
|
footerComponent={buttonSubmit}
|
||||||
>
|
>
|
||||||
<BaseBox>
|
<BaseBox>
|
||||||
<StackCustom gap="md">
|
<StackCustom gap="md">
|
||||||
@@ -39,7 +147,7 @@ export default function AdminDonationDisbursementOfFunds() {
|
|||||||
Dana Tersisa
|
Dana Tersisa
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
<TextCustom align="center" bold size="large">
|
<TextCustom align="center" bold size="large">
|
||||||
Rp 1.000.000
|
Rp {formatCurrencyDisplay(data?.terkumpul - data?.totalPencairan)}
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
</BaseBox>
|
</BaseBox>
|
||||||
@@ -56,9 +164,27 @@ export default function AdminDonationDisbursementOfFunds() {
|
|||||||
label="Nominal"
|
label="Nominal"
|
||||||
placeholder="0"
|
placeholder="0"
|
||||||
iconLeft={"Rp"}
|
iconLeft={"Rp"}
|
||||||
|
value={value.nominalCair}
|
||||||
|
onChangeText={(text) => {
|
||||||
|
setValue({
|
||||||
|
...value,
|
||||||
|
nominalCair: text,
|
||||||
|
});
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TextInputCustom required label="Judul" placeholder="Masukan judul" />
|
<TextInputCustom
|
||||||
|
required
|
||||||
|
label="Judul"
|
||||||
|
placeholder="Masukan judul"
|
||||||
|
value={value.title}
|
||||||
|
onChangeText={(text) => {
|
||||||
|
setValue({
|
||||||
|
...value,
|
||||||
|
title: text,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
<TextAreaCustom
|
<TextAreaCustom
|
||||||
required
|
required
|
||||||
@@ -66,20 +192,37 @@ export default function AdminDonationDisbursementOfFunds() {
|
|||||||
placeholder="Masukan deskripsi"
|
placeholder="Masukan deskripsi"
|
||||||
showCount
|
showCount
|
||||||
maxLength={500}
|
maxLength={500}
|
||||||
|
value={value.deskripsi}
|
||||||
|
onChangeText={(text) => {
|
||||||
|
setValue({
|
||||||
|
...value,
|
||||||
|
deskripsi: text,
|
||||||
|
});
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
</BaseBox>
|
</BaseBox>
|
||||||
<InformationBox text="Wajib menyertakan bukti transfer" />
|
|
||||||
|
|
||||||
|
<Spacing />
|
||||||
|
|
||||||
|
<InformationBox text="Wajib menyertakan bukti transfer" />
|
||||||
<ButtonCenteredOnly
|
<ButtonCenteredOnly
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
router.push(`/(application)/(image)/take-picture/${id}`);
|
pickFile({
|
||||||
|
allowedType: "image",
|
||||||
|
aspectRatio: [9, 16],
|
||||||
|
setImageUri: (file) => {
|
||||||
|
setImage(file);
|
||||||
|
},
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
icon="upload"
|
icon="upload"
|
||||||
>
|
>
|
||||||
Upload
|
Upload
|
||||||
</ButtonCenteredOnly>
|
</ButtonCenteredOnly>
|
||||||
<Spacing />
|
<Spacing />
|
||||||
|
<Image source={image?.uri} style={{ width: "100%", height: 300 }} />
|
||||||
|
<Spacing />
|
||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,54 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import {
|
import {
|
||||||
ActionIcon,
|
ActionIcon,
|
||||||
CenterCustom,
|
CenterCustom,
|
||||||
Divider,
|
Divider,
|
||||||
|
LoaderCustom,
|
||||||
StackCustom,
|
StackCustom,
|
||||||
TextCustom,
|
TextCustom,
|
||||||
ViewWrapper
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import { IconView } from "@/components/_Icon/IconComponent";
|
import { IconView } from "@/components/_Icon/IconComponent";
|
||||||
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||||
import { GridViewCustomSpan } from "@/components/_ShareComponent/GridViewCustomSpan";
|
import { GridViewCustomSpan } from "@/components/_ShareComponent/GridViewCustomSpan";
|
||||||
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
|
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
|
||||||
|
import { apiAdminDonationDisbursementOfFundsListById } from "@/service/api-admin/api-admin-donation";
|
||||||
|
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { router, useLocalSearchParams } from "expo-router";
|
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
|
import _ from "lodash";
|
||||||
|
import React, { useCallback } from "react";
|
||||||
import { View } from "react-native";
|
import { View } from "react-native";
|
||||||
|
|
||||||
export default function AdminDonasiListOfDisbursementOfFunds() {
|
export default function AdminDonasiListOfDisbursementOfFunds() {
|
||||||
const { id } = useLocalSearchParams();
|
const { id } = useLocalSearchParams();
|
||||||
|
const [listData, setListData] = React.useState<any[] | null>(null);
|
||||||
|
const [loadData, setLoadData] = React.useState(false);
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
onLoadData();
|
||||||
|
}, [id])
|
||||||
|
);
|
||||||
|
|
||||||
|
const onLoadData = async () => {
|
||||||
|
try {
|
||||||
|
setLoadData(true);
|
||||||
|
const response = await apiAdminDonationDisbursementOfFundsListById({
|
||||||
|
id: id as string,
|
||||||
|
category: "get-all",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
setListData(response.data);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
} finally {
|
||||||
|
setLoadData(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ViewWrapper
|
<ViewWrapper
|
||||||
@@ -45,7 +78,14 @@ export default function AdminDonasiListOfDisbursementOfFunds() {
|
|||||||
/>
|
/>
|
||||||
<Divider />
|
<Divider />
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
{Array.from({ length: 10 }).map((_, index) => (
|
{loadData ? (
|
||||||
|
<LoaderCustom />
|
||||||
|
) : _.isEmpty(listData) ? (
|
||||||
|
<TextCustom align="center" color="gray">
|
||||||
|
Belum ada data
|
||||||
|
</TextCustom>
|
||||||
|
) : (
|
||||||
|
listData?.map((item, index) => (
|
||||||
<View key={index}>
|
<View key={index}>
|
||||||
<GridViewCustomSpan
|
<GridViewCustomSpan
|
||||||
span1={3}
|
span1={3}
|
||||||
@@ -54,27 +94,31 @@ export default function AdminDonasiListOfDisbursementOfFunds() {
|
|||||||
component1={
|
component1={
|
||||||
<CenterCustom>
|
<CenterCustom>
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
icon={<IconView size={ICON_SIZE_BUTTON} color="black" />}
|
icon={
|
||||||
|
<IconView size={ICON_SIZE_BUTTON} color="black" />
|
||||||
|
}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
router.push(
|
router.push(
|
||||||
`/admin/donation/${id}/detail-disbursement-of-funds`
|
`/admin/donation/${item?.id}/detail-disbursement-of-funds`
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</CenterCustom>
|
</CenterCustom>
|
||||||
}
|
}
|
||||||
component2={
|
component2={
|
||||||
<TextCustom bold align="center" truncate>
|
<TextCustom align="center" truncate>
|
||||||
{dayjs()
|
{dayjs(item?.createdAt).format("DD-MM-YYYY")}
|
||||||
.add(index + 1, "day")
|
</TextCustom>
|
||||||
.format("DD-MM-YYYY HH:mm")}
|
}
|
||||||
|
component3={
|
||||||
|
<TextCustom align="center" truncate>
|
||||||
|
Rp. {formatCurrencyDisplay(item?.nominalCair)}
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
}
|
}
|
||||||
component3={<TextCustom>Rp. 1.000.000</TextCustom>}
|
|
||||||
/>
|
/>
|
||||||
<Divider />
|
|
||||||
</View>
|
</View>
|
||||||
))}
|
))
|
||||||
|
)}
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import {
|
import {
|
||||||
ActionIcon,
|
ActionIcon,
|
||||||
BadgeCustom,
|
BadgeCustom,
|
||||||
CenterCustom,
|
CenterCustom,
|
||||||
|
LoaderCustom,
|
||||||
SelectCustom,
|
SelectCustom,
|
||||||
StackCustom,
|
StackCustom,
|
||||||
TextCustom,
|
TextCustom,
|
||||||
@@ -10,23 +12,91 @@ import {
|
|||||||
import { IconView } from "@/components/_Icon/IconComponent";
|
import { IconView } from "@/components/_Icon/IconComponent";
|
||||||
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||||
import { GridViewCustomSpan } from "@/components/_ShareComponent/GridViewCustomSpan";
|
import { GridViewCustomSpan } from "@/components/_ShareComponent/GridViewCustomSpan";
|
||||||
import { MainColor } from "@/constants/color-palet";
|
|
||||||
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
|
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
|
||||||
import { dummyMasterStatusTransaction } from "@/lib/dummy-data/_master/status-transaction";
|
import { apiAdminDonationListOfDonatur } from "@/service/api-admin/api-admin-donation";
|
||||||
import { router, useLocalSearchParams } from "expo-router";
|
import { apiMasterTransaction } from "@/service/api-client/api-master";
|
||||||
import React from "react";
|
import { colorBadgeTransaction } from "@/utils/colorBadge";
|
||||||
|
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
|
import _ from "lodash";
|
||||||
|
import React, { useEffect } from "react";
|
||||||
import { View } from "react-native";
|
import { View } from "react-native";
|
||||||
import { Divider } from "react-native-paper";
|
import { Divider } from "react-native-paper";
|
||||||
|
|
||||||
export default function AdminDonasiListOfDonatur() {
|
export default function AdminDonasiListOfDonatur() {
|
||||||
const { id } = useLocalSearchParams();
|
const { id } = useLocalSearchParams();
|
||||||
|
const [listData, setListData] = React.useState<any[] | null>(null);
|
||||||
|
const [loadData, setLoadData] = React.useState(false);
|
||||||
|
const [master, setMaster] = React.useState<any[]>([]);
|
||||||
|
|
||||||
|
const [selectValue, setSelectValue] = React.useState<string | null>(null);
|
||||||
|
const [selectedStatus, setSelectedStatus] = React.useState<string | null>(
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
React.useCallback(() => {
|
||||||
|
onLoadData();
|
||||||
|
}, [id, selectValue])
|
||||||
|
);
|
||||||
|
|
||||||
|
const onLoadData = async () => {
|
||||||
|
try {
|
||||||
|
setLoadData(true);
|
||||||
|
const response = await apiAdminDonationListOfDonatur({
|
||||||
|
id: id as string,
|
||||||
|
status: selectedStatus as any,
|
||||||
|
});
|
||||||
|
// console.log("[LIST OF DONATUR]", JSON.stringify(response, null, 2));
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
setListData(response.data);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
setListData([]);
|
||||||
|
} finally {
|
||||||
|
setLoadData(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
onLoadMaster();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const onLoadMaster = async () => {
|
||||||
|
try {
|
||||||
|
const response = await apiMasterTransaction();
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
setMaster(response.data);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
setMaster([]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const searchComponent = (
|
const searchComponent = (
|
||||||
<View style={{ flexDirection: "row", gap: 5 }}>
|
<View style={{ flexDirection: "row", gap: 5 }}>
|
||||||
<SelectCustom
|
<SelectCustom
|
||||||
placeholder="Pilih status transaksi"
|
placeholder="Pilih status transaksi"
|
||||||
data={dummyMasterStatusTransaction}
|
data={
|
||||||
onChange={(value) => console.log(value)}
|
_.isEmpty(master)
|
||||||
|
? []
|
||||||
|
: master?.map((item: any) => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.id,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
value={selectValue}
|
||||||
|
onChange={(value: any) => {
|
||||||
|
setSelectValue(value);
|
||||||
|
const nameSelected = master.find((item: any) => item.id === value);
|
||||||
|
const statusChooses = _.lowerCase(nameSelected?.name);
|
||||||
|
setSelectedStatus(statusChooses);
|
||||||
|
}}
|
||||||
styleContainer={{ width: "100%", marginBottom: 0 }}
|
styleContainer={{ width: "100%", marginBottom: 0 }}
|
||||||
|
allowClear
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
@@ -37,6 +107,7 @@ export default function AdminDonasiListOfDonatur() {
|
|||||||
<AdminBackButtonAntTitle newComponent={searchComponent} />
|
<AdminBackButtonAntTitle newComponent={searchComponent} />
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
<StackCustom>
|
||||||
<GridViewCustomSpan
|
<GridViewCustomSpan
|
||||||
span1={3}
|
span1={3}
|
||||||
span2={5}
|
span2={5}
|
||||||
@@ -59,7 +130,14 @@ export default function AdminDonasiListOfDonatur() {
|
|||||||
/>
|
/>
|
||||||
<Divider />
|
<Divider />
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
{Array.from({ length: 10 }).map((_, index) => (
|
{loadData ? (
|
||||||
|
<LoaderCustom />
|
||||||
|
) : _.isEmpty(listData) ? (
|
||||||
|
<TextCustom align="center" color="gray">
|
||||||
|
Belum ada data
|
||||||
|
</TextCustom>
|
||||||
|
) : (
|
||||||
|
listData?.map((item: any, index: number) => (
|
||||||
<View key={index}>
|
<View key={index}>
|
||||||
<GridViewCustomSpan
|
<GridViewCustomSpan
|
||||||
span1={3}
|
span1={3}
|
||||||
@@ -68,10 +146,14 @@ export default function AdminDonasiListOfDonatur() {
|
|||||||
component1={
|
component1={
|
||||||
<CenterCustom>
|
<CenterCustom>
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
icon={<IconView size={ICON_SIZE_BUTTON} color="black" />}
|
icon={
|
||||||
|
<IconView size={ICON_SIZE_BUTTON} color="black" />
|
||||||
|
}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
router.push(
|
router.push(
|
||||||
`/admin/donation/${id}/berhasil/transaction-detail`
|
`/admin/donation/${item?.id}/${_.lowerCase(
|
||||||
|
item?.DonasiMaster_StatusInvoice?.name
|
||||||
|
)}/transaction-detail`
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -79,21 +161,24 @@ export default function AdminDonasiListOfDonatur() {
|
|||||||
}
|
}
|
||||||
component2={
|
component2={
|
||||||
<TextCustom bold align="center" truncate>
|
<TextCustom bold align="center" truncate>
|
||||||
Bagas Banuna
|
{item?.Author?.username || "-"}
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
}
|
}
|
||||||
component3={
|
component3={
|
||||||
<BadgeCustom
|
<BadgeCustom
|
||||||
style={{ alignSelf: "center" }}
|
style={{ alignSelf: "center" }}
|
||||||
color={MainColor.green}
|
color={colorBadgeTransaction({
|
||||||
|
status: item?.DonasiMaster_StatusInvoice?.name,
|
||||||
|
})}
|
||||||
>
|
>
|
||||||
Berhasil
|
{item?.DonasiMaster_StatusInvoice?.name}
|
||||||
</BadgeCustom>
|
</BadgeCustom>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Divider />
|
|
||||||
</View>
|
</View>
|
||||||
))}
|
))
|
||||||
|
)}
|
||||||
|
</StackCustom>
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import {
|
import {
|
||||||
AlertDefaultSystem,
|
AlertDefaultSystem,
|
||||||
BoxButtonOnFooter,
|
BoxButtonOnFooter,
|
||||||
@@ -6,15 +7,84 @@ import {
|
|||||||
} from "@/components";
|
} from "@/components";
|
||||||
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||||
import AdminButtonReject from "@/components/_ShareComponent/Admin/ButtonReject";
|
import AdminButtonReject from "@/components/_ShareComponent/Admin/ButtonReject";
|
||||||
import { router, useLocalSearchParams } from "expo-router";
|
import { funUpdateStatusDonation } from "@/screens/Admin/Donation/funDonationUpdateStatus";
|
||||||
import { useState } from "react";
|
import {
|
||||||
|
apiAdminDonationDetailById
|
||||||
|
} from "@/service/api-admin/api-admin-donation";
|
||||||
|
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
|
import React from "react";
|
||||||
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function AdminDonationRejectInput() {
|
export default function AdminDonationRejectInput() {
|
||||||
const { id } = useLocalSearchParams();
|
const { id, status } = useLocalSearchParams();
|
||||||
const [value, setValue] = useState(id as string);
|
|
||||||
|
const [data, setData] = React.useState<any | null>(null);
|
||||||
|
const [isLoading, setIsLoading] = React.useState(false);
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
React.useCallback(() => {
|
||||||
|
onLoadData();
|
||||||
|
}, [id])
|
||||||
|
);
|
||||||
|
|
||||||
|
const onLoadData = async () => {
|
||||||
|
try {
|
||||||
|
const response = await apiAdminDonationDetailById({
|
||||||
|
id: id as string,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
setData(response.data.catatan);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
setData(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleReport = async ({
|
||||||
|
changeStatus,
|
||||||
|
}: {
|
||||||
|
changeStatus: "publish" | "review" | "reject";
|
||||||
|
}) => {
|
||||||
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
const response = await funUpdateStatusDonation({
|
||||||
|
id: id as string,
|
||||||
|
changeStatus,
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.success) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Report gagal",
|
||||||
|
});
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Toast.show({
|
||||||
|
type: "success",
|
||||||
|
text1: "Report berhasil",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (status === "review") {
|
||||||
|
router.replace(`/admin/donation/reject/status`);
|
||||||
|
} else if (status === "reject") {
|
||||||
|
router.back();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const buttonSubmit = (
|
const buttonSubmit = (
|
||||||
<BoxButtonOnFooter>
|
<BoxButtonOnFooter>
|
||||||
<AdminButtonReject
|
<AdminButtonReject
|
||||||
|
isLoading={isLoading}
|
||||||
title="Reject"
|
title="Reject"
|
||||||
onReject={() =>
|
onReject={() =>
|
||||||
AlertDefaultSystem({
|
AlertDefaultSystem({
|
||||||
@@ -22,12 +92,9 @@ export default function AdminDonationRejectInput() {
|
|||||||
message: "Apakah anda yakin ingin menolak data ini?",
|
message: "Apakah anda yakin ingin menolak data ini?",
|
||||||
textLeft: "Batal",
|
textLeft: "Batal",
|
||||||
textRight: "Ya",
|
textRight: "Ya",
|
||||||
onPressLeft: () => {
|
|
||||||
router.back();
|
|
||||||
},
|
|
||||||
onPressRight: () => {
|
onPressRight: () => {
|
||||||
console.log("value:", value);
|
handleReport({ changeStatus: "reject" });
|
||||||
router.replace(`/admin/donation/reject/status`);
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -42,8 +109,8 @@ export default function AdminDonationRejectInput() {
|
|||||||
headerComponent={<AdminBackButtonAntTitle title="Penolakan Donasi" />}
|
headerComponent={<AdminBackButtonAntTitle title="Penolakan Donasi" />}
|
||||||
>
|
>
|
||||||
<TextAreaCustom
|
<TextAreaCustom
|
||||||
value={value}
|
value={data}
|
||||||
onChangeText={setValue}
|
onChangeText={setData}
|
||||||
placeholder="Masukan alasan"
|
placeholder="Masukan alasan"
|
||||||
required
|
required
|
||||||
showCount
|
showCount
|
||||||
|
|||||||
@@ -1,69 +1,116 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import {
|
import {
|
||||||
ActionIcon,
|
ActionIcon,
|
||||||
|
LoaderCustom,
|
||||||
SearchInput,
|
SearchInput,
|
||||||
Spacing,
|
StackCustom,
|
||||||
TextCustom,
|
TextCustom,
|
||||||
ViewWrapper
|
ViewWrapper
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
|
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
|
||||||
import AdminTitleTable from "@/components/_ShareComponent/Admin/TableTitle";
|
import AdminTitleTable from "@/components/_ShareComponent/Admin/TableTitle";
|
||||||
import AdminTableValue from "@/components/_ShareComponent/Admin/TableValue";
|
import AdminTableValue from "@/components/_ShareComponent/Admin/TableValue";
|
||||||
|
import AdminTitlePage from "@/components/_ShareComponent/Admin/TitlePage";
|
||||||
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
|
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
|
||||||
|
import { apiAdminDonation } from "@/service/api-admin/api-admin-donation";
|
||||||
import { Octicons } from "@expo/vector-icons";
|
import { Octicons } from "@expo/vector-icons";
|
||||||
import { router, useLocalSearchParams } from "expo-router";
|
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
|
import { useCallback, useState } from "react";
|
||||||
import { Divider } from "react-native-paper";
|
import { Divider } from "react-native-paper";
|
||||||
|
|
||||||
export default function AdminDonationStatus() {
|
export default function AdminDonationStatus() {
|
||||||
const { status } = useLocalSearchParams();
|
const { status } = useLocalSearchParams();
|
||||||
|
console.log("[STATUS]", status);
|
||||||
|
|
||||||
|
const [data, setData] = useState<any | null>(null);
|
||||||
|
const [search, setSearch] = useState<string>("");
|
||||||
|
const [loadData, setLoadData] = useState<boolean>(false);
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
onLoadData();
|
||||||
|
}, [status, search])
|
||||||
|
);
|
||||||
|
|
||||||
|
const onLoadData = async () => {
|
||||||
|
try {
|
||||||
|
setLoadData(true);
|
||||||
|
const response = await apiAdminDonation({
|
||||||
|
category: status as "publish" | "review" | "reject",
|
||||||
|
search,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("[RES]", JSON.stringify(response, null, 2));
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
setData(response.data);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
setData([]);
|
||||||
|
} finally {
|
||||||
|
setLoadData(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const rightComponent = (
|
const rightComponent = (
|
||||||
<SearchInput
|
<SearchInput
|
||||||
containerStyle={{ width: "100%", marginBottom: 0 }}
|
containerStyle={{ width: "100%", marginBottom: 0 }}
|
||||||
placeholder="Cari"
|
placeholder="Cari"
|
||||||
|
value={search}
|
||||||
|
onChangeText={(value) => setSearch(value)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ViewWrapper
|
<ViewWrapper headerComponent={<AdminTitlePage title="Donasi" />}>
|
||||||
headerComponent={
|
<StackCustom gap={"sm"}>
|
||||||
<AdminComp_BoxTitle
|
<AdminComp_BoxTitle
|
||||||
title={`Donasi ${_.startCase(status as string)}`}
|
title={`${_.startCase(status as string)}`}
|
||||||
rightComponent={rightComponent}
|
rightComponent={rightComponent}
|
||||||
/>
|
/>
|
||||||
}
|
|
||||||
>
|
|
||||||
<AdminTitleTable
|
<AdminTitleTable
|
||||||
title1="Aksi"
|
title1="Aksi"
|
||||||
title2="Username"
|
title2="Username"
|
||||||
title3="Judul Donasi"
|
title3="Judul Donasi"
|
||||||
/>
|
/>
|
||||||
<Spacing />
|
|
||||||
<Divider />
|
<Divider />
|
||||||
|
|
||||||
{Array.from({ length: 10 }).map((_, index) => (
|
{loadData ? (
|
||||||
|
<LoaderCustom />
|
||||||
|
) : _.isEmpty(data) ? (
|
||||||
|
<TextCustom align="center" size="small" color="gray">
|
||||||
|
Belum ada data
|
||||||
|
</TextCustom>
|
||||||
|
) : (
|
||||||
|
data?.map((item: any, index: number) => (
|
||||||
<AdminTableValue
|
<AdminTableValue
|
||||||
key={index}
|
key={index}
|
||||||
value1={
|
value1={
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
icon={
|
icon={
|
||||||
<Octicons name="eye" size={ICON_SIZE_BUTTON} color="black" />
|
<Octicons
|
||||||
|
name="eye"
|
||||||
|
size={ICON_SIZE_BUTTON}
|
||||||
|
color="black"
|
||||||
|
/>
|
||||||
}
|
}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
router.push(`/admin/donation/${index}/${status}`);
|
router.push(`/admin/donation/${item.id}/${status}`);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
value2={<TextCustom truncate={1}>Username username</TextCustom>}
|
value2={<TextCustom truncate={1}>{item?.Author?.username || "-"}</TextCustom>}
|
||||||
value3={
|
value3={
|
||||||
<TextCustom truncate={2}>
|
<TextCustom truncate={2}>
|
||||||
Lorem ipsum dolor sit amet consectetur adipisicing elit.
|
{item?.title || "-"}
|
||||||
Blanditiis asperiores quidem deleniti architecto eaque et
|
|
||||||
nostrum, ad consequuntur eveniet quisquam quae voluptatum
|
|
||||||
ducimus! Dolorem nobis modi officia debitis, beatae mollitia.
|
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
))}
|
))
|
||||||
|
)}
|
||||||
|
</StackCustom>
|
||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,17 +1,56 @@
|
|||||||
import {
|
import {
|
||||||
BoxButtonOnFooter,
|
BoxButtonOnFooter,
|
||||||
ButtonCustom,
|
ButtonCustom,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
TextInputCustom,
|
TextInputCustom,
|
||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { apiAdminMasterDonationCategoryCreate } from "@/service/api-admin/api-master-admin";
|
||||||
import { useRouter } from "expo-router";
|
import { useRouter } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Switch } from "react-native-paper";
|
||||||
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function AdminDonationCategoryCreate() {
|
export default function AdminDonationCategoryCreate() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [data, setData] = useState({
|
||||||
|
name: "",
|
||||||
|
active: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmit = async () => {
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
const response = await apiAdminMasterDonationCategoryCreate({ data });
|
||||||
|
if (response.success) {
|
||||||
|
Toast.show({
|
||||||
|
type: "success",
|
||||||
|
text2: "Data berhasil disimpan",
|
||||||
|
});
|
||||||
|
router.back();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Gagal menyimpan data",
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[Error]", error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const buttonSubmit = (
|
const buttonSubmit = (
|
||||||
<BoxButtonOnFooter>
|
<BoxButtonOnFooter>
|
||||||
<ButtonCustom onPress={() => router.back()}>Simpan</ButtonCustom>
|
<ButtonCustom isLoading={loading} onPress={onSubmit}>
|
||||||
|
Simpan
|
||||||
|
</ButtonCustom>
|
||||||
</BoxButtonOnFooter>
|
</BoxButtonOnFooter>
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
@@ -20,7 +59,23 @@ export default function AdminDonationCategoryCreate() {
|
|||||||
headerComponent={<AdminBackButtonAntTitle title="Tambah Kategori" />}
|
headerComponent={<AdminBackButtonAntTitle title="Tambah Kategori" />}
|
||||||
footerComponent={buttonSubmit}
|
footerComponent={buttonSubmit}
|
||||||
>
|
>
|
||||||
<TextInputCustom placeholder="Masukkan Kategori" />
|
<TextInputCustom
|
||||||
|
label=""
|
||||||
|
placeholder="Masukkan Kategori"
|
||||||
|
value={data.name}
|
||||||
|
onChangeText={(text) => setData({ ...data, name: text })}
|
||||||
|
/>
|
||||||
|
<StackCustom gap={"sm"}>
|
||||||
|
<TextCustom>Status</TextCustom>
|
||||||
|
<Switch
|
||||||
|
style={{
|
||||||
|
alignSelf: "flex-start",
|
||||||
|
}}
|
||||||
|
color={MainColor.yellow}
|
||||||
|
value={data.active}
|
||||||
|
onValueChange={(value) => setData({ ...data, active: value })}
|
||||||
|
/>
|
||||||
|
</StackCustom>
|
||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,21 +1,76 @@
|
|||||||
import {
|
import {
|
||||||
|
AlertDefaultSystem,
|
||||||
BoxButtonOnFooter,
|
BoxButtonOnFooter,
|
||||||
ButtonCustom,
|
ButtonCustom,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
TextInputCustom,
|
TextInputCustom,
|
||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import {
|
||||||
|
apiAdminMasterDonationCategoryById,
|
||||||
|
apiAdminMasterDonationCategoryUpdate,
|
||||||
|
} from "@/service/api-admin/api-master-admin";
|
||||||
import { useLocalSearchParams, useRouter } from "expo-router";
|
import { useLocalSearchParams, useRouter } from "expo-router";
|
||||||
import { useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
|
import { Switch } from "react-native-paper";
|
||||||
|
|
||||||
export default function AdminDonationCategoryUpdate() {
|
export default function AdminDonationCategoryUpdate() {
|
||||||
|
const router = useRouter();
|
||||||
const { id } = useLocalSearchParams();
|
const { id } = useLocalSearchParams();
|
||||||
const [value, setValue] = useState(id);
|
const [value, setValue] = useState(id);
|
||||||
|
|
||||||
const router = useRouter();
|
const [data, setData] = useState<any>(null);
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchData = async () => {
|
||||||
|
const response = await apiAdminMasterDonationCategoryById({
|
||||||
|
id: id as any,
|
||||||
|
});
|
||||||
|
console.log(JSON.stringify(response.data, null, 2));
|
||||||
|
|
||||||
|
setData(response.data);
|
||||||
|
};
|
||||||
|
fetchData();
|
||||||
|
}, [id]);
|
||||||
|
|
||||||
|
const handlerSubmit = async () => {
|
||||||
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
const response = await apiAdminMasterDonationCategoryUpdate({
|
||||||
|
id: id as any,
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
console.log(JSON.stringify(response.data, null, 2));
|
||||||
|
router.back();
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const buttonSubmit = (
|
const buttonSubmit = (
|
||||||
<BoxButtonOnFooter>
|
<BoxButtonOnFooter>
|
||||||
<ButtonCustom onPress={() => router.back()}>Update</ButtonCustom>
|
<ButtonCustom
|
||||||
|
disabled={isLoading || data?.name === ""}
|
||||||
|
isLoading={isLoading}
|
||||||
|
onPress={() => {
|
||||||
|
AlertDefaultSystem({
|
||||||
|
title: "Update Data",
|
||||||
|
message: "Apakah anda yakin ingin mengupdate data ini?",
|
||||||
|
textLeft: "Batal",
|
||||||
|
textRight: "Ya",
|
||||||
|
onPressLeft: () => {},
|
||||||
|
onPressRight: () => handlerSubmit(),
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Update
|
||||||
|
</ButtonCustom>
|
||||||
</BoxButtonOnFooter>
|
</BoxButtonOnFooter>
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
@@ -25,10 +80,28 @@ export default function AdminDonationCategoryUpdate() {
|
|||||||
footerComponent={buttonSubmit}
|
footerComponent={buttonSubmit}
|
||||||
>
|
>
|
||||||
<TextInputCustom
|
<TextInputCustom
|
||||||
|
label="Nama Kategori"
|
||||||
placeholder="Masukkan Kategori"
|
placeholder="Masukkan Kategori"
|
||||||
value={value as any}
|
value={data?.name}
|
||||||
onChangeText={setValue}
|
onChangeText={(value) => setData({ ...data, name: value })}
|
||||||
/>
|
/>
|
||||||
|
<StackCustom
|
||||||
|
gap={"sm"}
|
||||||
|
style={{
|
||||||
|
alignContent: "flex-start",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TextCustom>Status</TextCustom>
|
||||||
|
|
||||||
|
<Switch
|
||||||
|
style={{
|
||||||
|
alignSelf: "flex-start",
|
||||||
|
}}
|
||||||
|
color={MainColor.yellow}
|
||||||
|
value={data?.active}
|
||||||
|
onValueChange={(value) => setData({ ...data, active: value })}
|
||||||
|
/>
|
||||||
|
</StackCustom>
|
||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,27 +1,65 @@
|
|||||||
import {
|
import {
|
||||||
ActionIcon,
|
BadgeCustom,
|
||||||
BaseBox,
|
|
||||||
CenterCustom,
|
CenterCustom,
|
||||||
|
ClickableCustom,
|
||||||
Spacing,
|
Spacing,
|
||||||
StackCustom,
|
StackCustom,
|
||||||
TextCustom,
|
TextCustom,
|
||||||
ViewWrapper,
|
ViewWrapper
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import { IconEdit } from "@/components/_Icon";
|
|
||||||
import AdminActionIconPlus from "@/components/_ShareComponent/Admin/ActionIconPlus";
|
import AdminActionIconPlus from "@/components/_ShareComponent/Admin/ActionIconPlus";
|
||||||
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
|
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
|
||||||
import AdminTitlePage from "@/components/_ShareComponent/Admin/TitlePage";
|
import AdminTitlePage from "@/components/_ShareComponent/Admin/TitlePage";
|
||||||
import { GridView_3_3_6 } from "@/components/_ShareComponent/GridView_3_3_6";
|
import { GridSpan_4_8 } from "@/components/_ShareComponent/GridSpan_4_8";
|
||||||
import { MainColor } from "@/constants/color-palet";
|
import { apiAdminMasterDonationCategory } from "@/service/api-admin/api-master-admin";
|
||||||
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
|
import { colorActivationForBadge } from "@/utils/colorActivationForBadge";
|
||||||
import { View } from "react-native";
|
import { router, useFocusEffect } from "expo-router";
|
||||||
import { Divider, Switch } from "react-native-paper";
|
import { useCallback, useState } from "react";
|
||||||
import { router } from "expo-router";
|
import { RefreshControl, View } from "react-native";
|
||||||
|
import { Divider } from "react-native-paper";
|
||||||
|
|
||||||
export default function AdminDonationCategory() {
|
export default function AdminDonationCategory() {
|
||||||
|
const [listData, setListData] = useState<any[]>([]);
|
||||||
|
const [refreshing, setRefreshing] = useState(false);
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
fetchMaster();
|
||||||
|
}, [])
|
||||||
|
);
|
||||||
|
|
||||||
|
const fetchMaster = async () => {
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
const response = await apiAdminMasterDonationCategory();
|
||||||
|
if (response.success) {
|
||||||
|
console.log(JSON.stringify(response.data, null, 2));
|
||||||
|
setListData(response.data);
|
||||||
|
} else {
|
||||||
|
setListData([]);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[Error]", error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onRefresh = async () => {
|
||||||
|
setRefreshing(true);
|
||||||
|
await fetchMaster();
|
||||||
|
setRefreshing(false);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ViewWrapper headerComponent={<AdminTitlePage title="Donasi" />}>
|
<ViewWrapper
|
||||||
|
refreshControl={
|
||||||
|
<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
|
||||||
|
}
|
||||||
|
headerComponent={<AdminTitlePage title="Donasi" />}
|
||||||
|
>
|
||||||
<AdminComp_BoxTitle
|
<AdminComp_BoxTitle
|
||||||
title="Kategori"
|
title="Kategori"
|
||||||
rightComponent={
|
rightComponent={
|
||||||
@@ -33,81 +71,65 @@ export default function AdminDonationCategory() {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<BaseBox>
|
<View>
|
||||||
<GridView_3_3_6
|
<GridSpan_4_8
|
||||||
component1={
|
label={<TextCustom bold>Status</TextCustom>}
|
||||||
<TextCustom bold align="center">
|
value={<TextCustom bold>Kategori</TextCustom>}
|
||||||
Aksi
|
|
||||||
</TextCustom>
|
|
||||||
}
|
|
||||||
component2={<TextCustom bold>Status</TextCustom>}
|
|
||||||
component3={<TextCustom bold>Kategori</TextCustom>}
|
|
||||||
/>
|
/>
|
||||||
|
{/* <Grid>
|
||||||
|
<Grid.Col style={{ paddingLeft: 10 }} span={4}>
|
||||||
|
<TextCustom bold>Status</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={8}>
|
||||||
|
<TextCustom bold>Kategori</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid> */}
|
||||||
|
|
||||||
<Divider />
|
<Divider />
|
||||||
<Spacing />
|
<Spacing />
|
||||||
|
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
{listData.map((item, index) => (
|
{listData.map((item, index) => (
|
||||||
<View key={index}>
|
<ClickableCustom
|
||||||
<GridView_3_3_6
|
|
||||||
component1={
|
|
||||||
<CenterCustom>
|
|
||||||
<ActionIcon
|
|
||||||
icon={
|
|
||||||
<IconEdit size={ICON_SIZE_BUTTON} color="black" />
|
|
||||||
}
|
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
router.push(`/admin/donation/category-update?id=${index}`);
|
router.push(`/admin/donation/category-update?id=${item.id}`);
|
||||||
}}
|
}}
|
||||||
/>
|
key={index}
|
||||||
|
>
|
||||||
|
<GridSpan_4_8
|
||||||
|
label={
|
||||||
|
<CenterCustom>
|
||||||
|
<BadgeCustom
|
||||||
|
color={colorActivationForBadge({
|
||||||
|
status: item.active,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{item.active ? "Aktif" : "Tidak Aktif"}
|
||||||
|
</BadgeCustom>
|
||||||
</CenterCustom>
|
</CenterCustom>
|
||||||
}
|
}
|
||||||
component2={
|
value={<TextCustom>{item.name}</TextCustom>}
|
||||||
<Switch
|
|
||||||
value={true}
|
|
||||||
onValueChange={(item) => {
|
|
||||||
console.log(item);
|
|
||||||
}}
|
|
||||||
color={MainColor.yellow}
|
|
||||||
|
|
||||||
/>
|
/>
|
||||||
}
|
{/* <Grid containerStyle={{ paddingBottom: 10 }}>
|
||||||
component3={<TextCustom bold>{item.label}</TextCustom>}
|
<Grid.Col span={4} style={{ paddingLeft: 10 }}>
|
||||||
/>
|
<CenterCustom>
|
||||||
<Spacing height={10} />
|
<BadgeCustom
|
||||||
|
color={item.active ? MainColor.green : MainColor.red}
|
||||||
|
>
|
||||||
|
{item.active ? "Aktif" : "Tidak Aktif"}
|
||||||
|
</BadgeCustom>
|
||||||
|
</CenterCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={8}>
|
||||||
|
<TextCustom bold>{item.name}</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid> */}
|
||||||
<Divider />
|
<Divider />
|
||||||
</View>
|
</ClickableCustom>
|
||||||
))}
|
))}
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
</BaseBox>
|
</View>
|
||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const listData = [
|
|
||||||
{
|
|
||||||
label: "Kegiatan Sosial",
|
|
||||||
value: "kegiatan_sosial",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Pendidikan",
|
|
||||||
value: "pendidikan",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Kesehatan",
|
|
||||||
value: "kesehatan",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Kebudayaan",
|
|
||||||
value: "kebudayaan",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Bencana Alami",
|
|
||||||
value: "bencana_alami",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Lainnya",
|
|
||||||
value: "lainnya",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|||||||
@@ -8,8 +8,60 @@ import {
|
|||||||
import AdminComp_BoxDashboard from "@/components/_ShareComponent/Admin/BoxDashboard";
|
import AdminComp_BoxDashboard from "@/components/_ShareComponent/Admin/BoxDashboard";
|
||||||
import AdminTitlePage from "@/components/_ShareComponent/Admin/TitlePage";
|
import AdminTitlePage from "@/components/_ShareComponent/Admin/TitlePage";
|
||||||
import { MainColor } from "@/constants/color-palet";
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { apiAdminDonation } from "@/service/api-admin/api-admin-donation";
|
||||||
|
import { useFocusEffect } from "expo-router";
|
||||||
|
import { useState, useCallback } from "react";
|
||||||
|
|
||||||
export default function AdminDonation() {
|
export default function AdminDonation() {
|
||||||
|
const [data, setData] = useState<any | null>(null);
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
onLoadData();
|
||||||
|
}, [])
|
||||||
|
);
|
||||||
|
|
||||||
|
const onLoadData = async () => {
|
||||||
|
try {
|
||||||
|
|
||||||
|
const response = await apiAdminDonation({
|
||||||
|
category: "dashboard",
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("[RES]", JSON.stringify(response, null, 2));
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
setData(response.data);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
setData([]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const listData = [
|
||||||
|
{
|
||||||
|
label: "Publish",
|
||||||
|
value: (data && data.publish) || 0,
|
||||||
|
icon: <IconPublish size={25} color={MainColor.green} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Review",
|
||||||
|
value: (data && data.review) || 0,
|
||||||
|
icon: <IconReview size={25} color={MainColor.orange} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Reject",
|
||||||
|
value: (data && data.reject) || 0,
|
||||||
|
icon: <IconReject size={25} color={MainColor.red} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Kategori",
|
||||||
|
value: (data && data.categoryDonation) || 0,
|
||||||
|
icon: <IconList size={25} color={MainColor.white_gray} />,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ViewWrapper>
|
<ViewWrapper>
|
||||||
@@ -24,26 +76,3 @@ export default function AdminDonation() {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const listData = [
|
|
||||||
{
|
|
||||||
label: "Publish",
|
|
||||||
value: 4,
|
|
||||||
icon: <IconPublish size={25} color={MainColor.green} />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Review",
|
|
||||||
value: 7,
|
|
||||||
icon: <IconReview size={25} color={MainColor.orange} />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Reject",
|
|
||||||
value: 5,
|
|
||||||
icon: <IconReject size={25} color={MainColor.red} />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Kategori",
|
|
||||||
value: 4,
|
|
||||||
icon: <IconList size={25} color={MainColor.white_gray} />,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
BadgeCustom,
|
BadgeCustom,
|
||||||
BaseBox,
|
BaseBox,
|
||||||
DrawerCustom,
|
DrawerCustom,
|
||||||
|
LoaderCustom,
|
||||||
MenuDrawerDynamicGrid,
|
MenuDrawerDynamicGrid,
|
||||||
Spacing,
|
Spacing,
|
||||||
StackCustom,
|
StackCustom,
|
||||||
@@ -15,32 +16,34 @@ import { IconDot, IconList } from "@/components/_Icon/IconComponent";
|
|||||||
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||||
import AdminButtonReject from "@/components/_ShareComponent/Admin/ButtonReject";
|
import AdminButtonReject from "@/components/_ShareComponent/Admin/ButtonReject";
|
||||||
import AdminButtonReview from "@/components/_ShareComponent/Admin/ButtonReview";
|
import AdminButtonReview from "@/components/_ShareComponent/Admin/ButtonReview";
|
||||||
import { GridDetail_4_8 } from "@/components/_ShareComponent/GridDetail_4_8";
|
import { GridSpan_4_8 } from "@/components/_ShareComponent/GridSpan_4_8";
|
||||||
import ReportBox from "@/components/Box/ReportBox";
|
import ReportBox from "@/components/Box/ReportBox";
|
||||||
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
|
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
|
||||||
import { useAuth } from "@/hooks/use-auth";
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
import { funUpdateStatusEvent } from "@/screens/Admin/Event/funUpdateStatus";
|
import { funUpdateStatusEvent } from "@/screens/Admin/Event/funUpdateStatus";
|
||||||
import { apiAdminEventById } from "@/service/api-admin/api-admin-event";
|
import { apiAdminEventById } from "@/service/api-admin/api-admin-event";
|
||||||
import { DEEP_LINK_URL } from "@/service/api-config";
|
import { DEEP_LINK_URL } from "@/service/api-config";
|
||||||
import { colorBadge } from "@/utils/colorBadge";
|
import { colorBadgeStatus } from "@/utils/colorBadge";
|
||||||
import { dateTimeView } from "@/utils/dateTimeView";
|
import { dateTimeView } from "@/utils/dateTimeView";
|
||||||
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import React, { useCallback } from "react";
|
import React, { useCallback } from "react";
|
||||||
import QRCode from "react-native-qrcode-svg";
|
import QRCode from "react-native-qrcode-svg";
|
||||||
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function AdminEventDetail() {
|
export default function AdminEventDetail() {
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
const { id, status } = useLocalSearchParams();
|
const { id, status } = useLocalSearchParams();
|
||||||
|
|
||||||
console.log("[ID QRCODE]", id);
|
|
||||||
console.log("[STATUS Detail]", status);
|
|
||||||
const [openDrawer, setOpenDrawer] = React.useState(false);
|
const [openDrawer, setOpenDrawer] = React.useState(false);
|
||||||
const newURL = DEEP_LINK_URL
|
|
||||||
console.log("[DEEP LINK URL]", newURL);
|
|
||||||
|
|
||||||
const [data, setData] = React.useState<any | null>(null);
|
const [data, setData] = React.useState<any | null>(null);
|
||||||
const deepLinkURL = `${DEEP_LINK_URL}/--/event/${id}/confirmation?userId=${user?.id}`;
|
const [loadData, setLoadData] = React.useState(false);
|
||||||
|
const deepLinkURL = `${DEEP_LINK_URL}/event/${id}/confirmation?userId=${user?.id}`;
|
||||||
|
const deepLinkURLDEV = `${DEEP_LINK_URL}/--/event/${id}/confirmation?userId=${user?.id}`;
|
||||||
|
|
||||||
|
const isDevLink = process.env.NODE_ENV === "development" ? deepLinkURLDEV : deepLinkURL;
|
||||||
|
|
||||||
|
|
||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
useCallback(() => {
|
useCallback(() => {
|
||||||
onLoadData();
|
onLoadData();
|
||||||
@@ -48,17 +51,18 @@ export default function AdminEventDetail() {
|
|||||||
);
|
);
|
||||||
const onLoadData = async () => {
|
const onLoadData = async () => {
|
||||||
try {
|
try {
|
||||||
|
setLoadData(true);
|
||||||
const response = await apiAdminEventById({
|
const response = await apiAdminEventById({
|
||||||
id: id as string,
|
id: id as string,
|
||||||
});
|
});
|
||||||
|
|
||||||
// console.log(`[RES DATA BY ID: ${id}]`, JSON.stringify(response, null, 2));
|
|
||||||
|
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
setData(response.data);
|
setData(response.data);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("[ERROR]", error);
|
console.log("[ERROR]", error);
|
||||||
|
} finally {
|
||||||
|
setLoadData(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -75,7 +79,7 @@ export default function AdminEventDetail() {
|
|||||||
label: "Status",
|
label: "Status",
|
||||||
value:
|
value:
|
||||||
(data && (
|
(data && (
|
||||||
<BadgeCustom color={colorBadge({ status: status as string })}>
|
<BadgeCustom color={colorBadgeStatus({ status: status as string })}>
|
||||||
{_.startCase(status as string)}
|
{_.startCase(status as string)}
|
||||||
</BadgeCustom>
|
</BadgeCustom>
|
||||||
)) ||
|
)) ||
|
||||||
@@ -124,11 +128,19 @@ export default function AdminEventDetail() {
|
|||||||
changeStatus: "publish",
|
changeStatus: "publish",
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("[RES PUBLISH]", JSON.stringify(response, null, 2));
|
if (!response.success) {
|
||||||
|
Toast.show({
|
||||||
if (response.success) {
|
type: "error",
|
||||||
router.back();
|
text1: "Gagal mempublikasikan event",
|
||||||
|
});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Toast.show({
|
||||||
|
type: "success",
|
||||||
|
text1: "Event berhasil dipublikasikan",
|
||||||
|
});
|
||||||
|
router.back();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("[ERROR]", error);
|
console.log("[ERROR]", error);
|
||||||
}
|
}
|
||||||
@@ -149,7 +161,7 @@ export default function AdminEventDetail() {
|
|||||||
<BaseBox>
|
<BaseBox>
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
{listData.map((item, i) => (
|
{listData.map((item, i) => (
|
||||||
<GridDetail_4_8
|
<GridSpan_4_8
|
||||||
key={i}
|
key={i}
|
||||||
label={<TextCustom bold>{item.label}</TextCustom>}
|
label={<TextCustom bold>{item.label}</TextCustom>}
|
||||||
value={<TextCustom>{item.value}</TextCustom>}
|
value={<TextCustom>{item.value}</TextCustom>}
|
||||||
@@ -170,8 +182,11 @@ export default function AdminEventDetail() {
|
|||||||
<BaseBox>
|
<BaseBox>
|
||||||
<StackCustom style={{ alignItems: "center" }}>
|
<StackCustom style={{ alignItems: "center" }}>
|
||||||
<TextCustom bold>QR Code Event</TextCustom>
|
<TextCustom bold>QR Code Event</TextCustom>
|
||||||
|
{loadData ? (
|
||||||
|
<LoaderCustom />
|
||||||
|
) : (
|
||||||
<QRCode
|
<QRCode
|
||||||
value={deepLinkURL}
|
value={isDevLink}
|
||||||
size={200}
|
size={200}
|
||||||
// logo={require("@/assets/images/logo-hipmi.png")}
|
// logo={require("@/assets/images/logo-hipmi.png")}
|
||||||
// logoSize={70}
|
// logoSize={70}
|
||||||
@@ -179,6 +194,9 @@ export default function AdminEventDetail() {
|
|||||||
// logoBorderRadius={50}
|
// logoBorderRadius={50}
|
||||||
// color="black"
|
// color="black"
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<TextCustom align="center">{isDevLink}</TextCustom>
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
</BaseBox>
|
</BaseBox>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,41 +1,104 @@
|
|||||||
import { BadgeCustom, BaseBox, Grid, TextCustom, ViewWrapper } from "@/components";
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
|
import {
|
||||||
|
BadgeCustom,
|
||||||
|
BaseBox,
|
||||||
|
Grid,
|
||||||
|
LoaderCustom,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||||
import { MainColor } from "@/constants/color-palet";
|
import { apiAdminEventListOfParticipants } from "@/service/api-admin/api-admin-event";
|
||||||
|
import dayjs, { Dayjs } from "dayjs";
|
||||||
|
import { useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { View } from "moti";
|
||||||
|
import { useCallback, useState } from "react";
|
||||||
|
|
||||||
export default function AdminEventListOfParticipants() {
|
export default function AdminEventListOfParticipants() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const [listData, setListData] = useState<any[] | null>(null);
|
||||||
|
const [loadData, setLoadData] = useState(false);
|
||||||
|
const [startDate, setStartDate] = useState<Dayjs | undefined>();
|
||||||
|
|
||||||
const isPresent = ({id}: {id: number}) => {
|
useFocusEffect(
|
||||||
const check = id % 3 * 3;
|
useCallback(() => {
|
||||||
if (check === 0) {
|
onLoadData();
|
||||||
return true;
|
}, [id])
|
||||||
} else {
|
);
|
||||||
return false;
|
|
||||||
|
const onLoadData = async () => {
|
||||||
|
try {
|
||||||
|
setLoadData(true);
|
||||||
|
const response = await apiAdminEventListOfParticipants({
|
||||||
|
id: id as string,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("[DATA]", JSON.stringify(response, null, 2));
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
setListData(response.data);
|
||||||
|
setStartDate(dayjs(response.data.Event.tanggal));
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
} finally {
|
||||||
|
setLoadData(false);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ViewWrapper
|
<ViewWrapper
|
||||||
headerComponent={<AdminBackButtonAntTitle title="Daftar Peserta" />}
|
headerComponent={<AdminBackButtonAntTitle title="Daftar Peserta" />}
|
||||||
>
|
>
|
||||||
{Array.from({ length: 10 }).map((item, index) => (
|
{loadData ? (
|
||||||
|
<LoaderCustom />
|
||||||
|
) : _.isEmpty(listData) ? (
|
||||||
|
<TextCustom align="center" color="gray">
|
||||||
|
Belum ada peserta
|
||||||
|
</TextCustom>
|
||||||
|
) : (
|
||||||
|
listData?.map((item: any, index: number) => (
|
||||||
<BaseBox key={index}>
|
<BaseBox key={index}>
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.Col span={6}>
|
<Grid.Col span={6}>
|
||||||
<TextCustom bold>Username {index + 1}</TextCustom>
|
<StackCustom gap={"sm"}>
|
||||||
<TextCustom>+6282123456789</TextCustom>
|
<TextCustom bold truncate>
|
||||||
|
{item?.User?.username}
|
||||||
|
</TextCustom>
|
||||||
|
<TextCustom>+{item?.User?.nomor}</TextCustom>
|
||||||
|
</StackCustom>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
<Grid.Col span={6} style={{ justifyContent: "center" }}>
|
<Grid.Col span={6} style={{ justifyContent: "center" }}>
|
||||||
|
{startDate &&
|
||||||
|
startDate.subtract(1, "hour").diff(dayjs()) < 0 ? (
|
||||||
<BadgeCustom
|
<BadgeCustom
|
||||||
style={{ alignSelf: "flex-end" }}
|
style={{ alignSelf: "flex-end" }}
|
||||||
color={isPresent({id: index}) ? MainColor.green : MainColor.red}
|
color={item?.isPresent ? "green" : "red"}
|
||||||
>
|
>
|
||||||
{isPresent({id: index}) ? "Hadir" : "Tidak Hadir"}
|
{item?.isPresent ? "Hadir" : "Tidak Hadir"}
|
||||||
</BadgeCustom>
|
</BadgeCustom>
|
||||||
|
) : (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
justifyContent: "flex-end",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<BadgeCustom
|
||||||
|
style={{ alignSelf: "flex-end" }}
|
||||||
|
color="gray"
|
||||||
|
>
|
||||||
|
-
|
||||||
|
</BadgeCustom>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
</Grid>
|
</Grid>
|
||||||
</BaseBox>
|
</BaseBox>
|
||||||
))}
|
))
|
||||||
|
)}
|
||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import {
|
import {
|
||||||
ActionIcon,
|
ActionIcon,
|
||||||
|
ClickableCustom,
|
||||||
LoaderCustom,
|
LoaderCustom,
|
||||||
SearchInput,
|
SearchInput,
|
||||||
StackCustom,
|
StackCustom,
|
||||||
TextCustom,
|
TextCustom,
|
||||||
ViewWrapper
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
|
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
|
||||||
import AdminTitleTable from "@/components/_ShareComponent/Admin/TableTitle";
|
import AdminTitleTable from "@/components/_ShareComponent/Admin/TableTitle";
|
||||||
@@ -13,6 +14,7 @@ import AdminTableValue from "@/components/_ShareComponent/Admin/TableValue";
|
|||||||
import AdminTitlePage from "@/components/_ShareComponent/Admin/TitlePage";
|
import AdminTitlePage from "@/components/_ShareComponent/Admin/TitlePage";
|
||||||
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
|
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
|
||||||
import { apiAdminEvent } from "@/service/api-admin/api-admin-event";
|
import { apiAdminEvent } from "@/service/api-admin/api-admin-event";
|
||||||
|
import { dateTimeView } from "@/utils/dateTimeView";
|
||||||
import { Octicons } from "@expo/vector-icons";
|
import { Octicons } from "@expo/vector-icons";
|
||||||
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
@@ -74,8 +76,8 @@ export default function AdminEventStatus() {
|
|||||||
|
|
||||||
<StackCustom gap={"sm"}>
|
<StackCustom gap={"sm"}>
|
||||||
<AdminTitleTable
|
<AdminTitleTable
|
||||||
title1="Aksi"
|
title1="Username"
|
||||||
title2="Username"
|
title2="Tanggal"
|
||||||
title3="Judul Event"
|
title3="Judul Event"
|
||||||
/>
|
/>
|
||||||
<Divider />
|
<Divider />
|
||||||
@@ -83,36 +85,47 @@ export default function AdminEventStatus() {
|
|||||||
{loadData ? (
|
{loadData ? (
|
||||||
<LoaderCustom />
|
<LoaderCustom />
|
||||||
) : _.isEmpty(listData) ? (
|
) : _.isEmpty(listData) ? (
|
||||||
<TextCustom align="center" size="small" color="gray">Belum ada data</TextCustom>
|
<TextCustom align="center" size="small" color="gray">
|
||||||
|
Belum ada data
|
||||||
|
</TextCustom>
|
||||||
) : (
|
) : (
|
||||||
listData?.map((item, index) => (
|
listData?.map((item, index) => (
|
||||||
<AdminTableValue
|
<ClickableCustom
|
||||||
key={index}
|
key={index}
|
||||||
value1={
|
|
||||||
<ActionIcon
|
|
||||||
icon={
|
|
||||||
<Octicons
|
|
||||||
name="eye"
|
|
||||||
size={ICON_SIZE_BUTTON}
|
|
||||||
color="black"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
router.push(`/admin/event/${item.id}/${status}`);
|
router.push(`/admin/event/${item.id}/${status}`);
|
||||||
}}
|
}}
|
||||||
/>
|
>
|
||||||
}
|
<AdminTableValue
|
||||||
value2={
|
key={index}
|
||||||
|
value1={
|
||||||
<TextCustom truncate={1}>
|
<TextCustom truncate={1}>
|
||||||
{item?.Author?.username || "-"}
|
{item?.Author?.username || "-"}
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
|
// <ActionIcon
|
||||||
|
// icon={
|
||||||
|
// <Octicons
|
||||||
|
// name="eye"
|
||||||
|
// size={ICON_SIZE_BUTTON}
|
||||||
|
// color="black"
|
||||||
|
// />
|
||||||
|
// }
|
||||||
|
// onPress={() => {
|
||||||
|
// router.push(`/admin/event/${item.id}/${status}`);
|
||||||
|
// }}
|
||||||
|
// />
|
||||||
}
|
}
|
||||||
value3={
|
value2={
|
||||||
<TextCustom align="center" truncate={2}>
|
<TextCustom truncate={1}>
|
||||||
{item?.title || "-"}
|
{dateTimeView({ date: item?.tanggal })}
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
}
|
}
|
||||||
|
value3={
|
||||||
|
<TextCustom truncate={2}>{item?.title || "-"}</TextCustom>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
|
<Divider/>
|
||||||
|
</ClickableCustom>
|
||||||
))
|
))
|
||||||
)}
|
)}
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
|
|||||||
@@ -5,13 +5,48 @@ import {
|
|||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||||
|
import { apiEventCreateTypeOfEvent } from "@/service/api-admin/api-master-admin";
|
||||||
import { useRouter } from "expo-router";
|
import { useRouter } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function AdminEventTypeOfEventCreate() {
|
export default function AdminEventTypeOfEventCreate() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const [value, setValue] = useState("");
|
||||||
|
const [isLoading, setLoading] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const handlerSubmit = async () => {
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
const response = await apiEventCreateTypeOfEvent({
|
||||||
|
data: value,
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
if (!response.success) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Gagal menambahkan tipe acara",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Toast.show({
|
||||||
|
type: "success",
|
||||||
|
text1: "Berhasil menambahkan tipe acara",
|
||||||
|
});
|
||||||
|
router.back();
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR CREATE TYPE EVENT]", error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const buttonSubmit = (
|
const buttonSubmit = (
|
||||||
<BoxButtonOnFooter>
|
<BoxButtonOnFooter>
|
||||||
<ButtonCustom onPress={() => router.back()}>Simpan</ButtonCustom>
|
<ButtonCustom isLoading={isLoading} onPress={() => handlerSubmit()}>
|
||||||
|
Simpan
|
||||||
|
</ButtonCustom>
|
||||||
</BoxButtonOnFooter>
|
</BoxButtonOnFooter>
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
@@ -20,7 +55,11 @@ export default function AdminEventTypeOfEventCreate() {
|
|||||||
headerComponent={<AdminBackButtonAntTitle title="Tambah Tipe Acara" />}
|
headerComponent={<AdminBackButtonAntTitle title="Tambah Tipe Acara" />}
|
||||||
footerComponent={buttonSubmit}
|
footerComponent={buttonSubmit}
|
||||||
>
|
>
|
||||||
<TextInputCustom placeholder="Masukkan Tipe Acara" />
|
<TextInputCustom
|
||||||
|
placeholder="Masukkan Tipe Acara"
|
||||||
|
value={value}
|
||||||
|
onChangeText={setValue}
|
||||||
|
/>
|
||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,23 +1,53 @@
|
|||||||
import {
|
import {
|
||||||
ActionIcon,
|
ActionIcon,
|
||||||
BaseBox,
|
BadgeCustom,
|
||||||
CenterCustom,
|
CenterCustom,
|
||||||
|
LoaderCustom,
|
||||||
Spacing,
|
Spacing,
|
||||||
StackCustom,
|
StackCustom,
|
||||||
TextCustom,
|
TextCustom,
|
||||||
ViewWrapper,
|
ViewWrapper
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import { IconEdit } from "@/components/_Icon";
|
import { IconEdit } from "@/components/_Icon";
|
||||||
import AdminActionIconPlus from "@/components/_ShareComponent/Admin/ActionIconPlus";
|
import AdminActionIconPlus from "@/components/_ShareComponent/Admin/ActionIconPlus";
|
||||||
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
|
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
|
||||||
import AdminTitlePage from "@/components/_ShareComponent/Admin/TitlePage";
|
import AdminTitlePage from "@/components/_ShareComponent/Admin/TitlePage";
|
||||||
import { GridDetail_4_8 } from "@/components/_ShareComponent/GridDetail_4_8";
|
import { GridViewCustomSpan } from "@/components/_ShareComponent/GridViewCustomSpan";
|
||||||
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
|
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
|
||||||
import { router } from "expo-router";
|
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 { View } from "react-native";
|
||||||
import { Divider } from "react-native-paper";
|
import { Divider } from "react-native-paper";
|
||||||
|
|
||||||
export default function AdminEventTypeOfEvent() {
|
export default function AdminEventTypeOfEvent() {
|
||||||
|
const [listData, setListData] = useState<any[] | null>(null);
|
||||||
|
const [loadData, setLoadData] = useState<boolean>(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 (
|
return (
|
||||||
<>
|
<>
|
||||||
<ViewWrapper headerComponent={<AdminTitlePage title="Event" />}>
|
<ViewWrapper headerComponent={<AdminTitlePage title="Event" />}>
|
||||||
@@ -32,73 +62,68 @@ export default function AdminEventTypeOfEvent() {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<BaseBox>
|
<>
|
||||||
<GridDetail_4_8
|
<GridViewCustomSpan
|
||||||
label={
|
span1={2}
|
||||||
|
span2={5}
|
||||||
|
span3={5}
|
||||||
|
component1={
|
||||||
<TextCustom bold align="center">
|
<TextCustom bold align="center">
|
||||||
Aksi
|
Aksi
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
}
|
}
|
||||||
value={<TextCustom bold>Tipe Acara</TextCustom>}
|
component2={<TextCustom bold align="center">Status</TextCustom>}
|
||||||
|
component3={<TextCustom bold>Tipe Acara</TextCustom>}
|
||||||
/>
|
/>
|
||||||
<Divider />
|
<Divider />
|
||||||
<Spacing />
|
<Spacing />
|
||||||
|
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
{listData.map((item, index) => (
|
{loadData ? (
|
||||||
|
<LoaderCustom />
|
||||||
|
) : _.isEmpty(listData) ? (
|
||||||
|
<TextCustom align="center" color="gray">
|
||||||
|
Belum ada data
|
||||||
|
</TextCustom>
|
||||||
|
) : (
|
||||||
|
listData?.map((item, index) => (
|
||||||
<View key={index}>
|
<View key={index}>
|
||||||
<GridDetail_4_8
|
<GridViewCustomSpan
|
||||||
label={
|
span1={2}
|
||||||
|
span2={5}
|
||||||
|
span3={5}
|
||||||
|
component1={
|
||||||
<CenterCustom>
|
<CenterCustom>
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
icon={
|
icon={
|
||||||
<IconEdit size={ICON_SIZE_BUTTON} color="black" />
|
<IconEdit size={ICON_SIZE_BUTTON} color="black" />
|
||||||
}
|
}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
router.push(`/admin/event/type-update?id=${index}`);
|
router.push(`/admin/event/type-update?id=${item.id}`);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</CenterCustom>
|
</CenterCustom>
|
||||||
}
|
}
|
||||||
value={<TextCustom bold>{item.label}</TextCustom>}
|
style2={{ alignItems: "center" }}
|
||||||
|
component2={
|
||||||
|
<CenterCustom>
|
||||||
|
<BadgeCustom
|
||||||
|
color={colorActivationForBadge({
|
||||||
|
status: item?.active,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{item?.active ? "Aktif" : "Tidak Aktif"}
|
||||||
|
</BadgeCustom>
|
||||||
|
</CenterCustom>
|
||||||
|
}
|
||||||
|
component3={<TextCustom >{item.name}</TextCustom>}
|
||||||
/>
|
/>
|
||||||
<Divider />
|
|
||||||
</View>
|
</View>
|
||||||
))}
|
))
|
||||||
|
)}
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
</BaseBox>
|
</>
|
||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const listData = [
|
|
||||||
{
|
|
||||||
label: "Seminar",
|
|
||||||
value: "seminar",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Workshop",
|
|
||||||
value: "workshop",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Konferensi",
|
|
||||||
value: "konferensi",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Lomba",
|
|
||||||
value: "lomba",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Pameran",
|
|
||||||
value: "pameran",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Pesta",
|
|
||||||
value: "pesta",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Pertandingan",
|
|
||||||
value: "pertandingan",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|||||||