Compare commits
19 Commits
amalia/02-
...
amalia/09-
| Author | SHA1 | Date | |
|---|---|---|---|
| d52453c530 | |||
| 1853cb573c | |||
| 83291676d3 | |||
| 1509d1b702 | |||
| 8d6a0d3981 | |||
| d20307fc0b | |||
| 060f96e7b2 | |||
| a15724756e | |||
| c8de5d185a | |||
| 5fa364be24 | |||
| 4768007df3 | |||
| 9793794ff2 | |||
| d0aaa5561c | |||
| 90042d13dd | |||
| 596565ba8e | |||
| 22663acaae | |||
| d3354e3e74 | |||
| c3ab4d05ae | |||
| 270001aa4f |
1
.gitignore
vendored
@@ -45,3 +45,4 @@ x.sh
|
||||
|
||||
google-services.json
|
||||
service-account.json
|
||||
|
||||
|
||||
@@ -92,8 +92,8 @@ android {
|
||||
applicationId 'mobiledarmasaba.app'
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 1
|
||||
versionName "1.0.0"
|
||||
versionCode 6
|
||||
versionName "1.0.2"
|
||||
}
|
||||
signingConfigs {
|
||||
debug {
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO"/>
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
|
||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 115 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 186 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 360 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 575 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 8.1 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 218 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 6.3 KiB |
@@ -1,5 +1,5 @@
|
||||
<resources>
|
||||
<string name="app_name">mobile-darmasaba</string>
|
||||
<string name="app_name">Desa+</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_status_bar_translucent" translatable="false">false</string>
|
||||
|
||||
@@ -31,7 +31,7 @@ extensions.configure(com.facebook.react.ReactSettingsExtension) { ex ->
|
||||
}
|
||||
expoAutolinking.useExpoModules()
|
||||
|
||||
rootProject.name = 'mobile-darmasaba'
|
||||
rootProject.name = 'Desa+'
|
||||
|
||||
expoAutolinking.useExpoVersionCatalog()
|
||||
|
||||
|
||||
@@ -2,12 +2,12 @@ import 'dotenv/config';
|
||||
|
||||
export default {
|
||||
expo: {
|
||||
name: "mobile-darmasaba",
|
||||
name: "Desa+",
|
||||
slug: "mobile-darmasaba",
|
||||
version: "1.0.1",
|
||||
version: "1.0.3",
|
||||
jsEngine: "jsc",
|
||||
orientation: "portrait",
|
||||
icon: "./assets/images/icon.png",
|
||||
icon: "./assets/images/logo-icon-small.png",
|
||||
scheme: "myapp",
|
||||
userInterfaceStyle: "automatic",
|
||||
newArchEnabled: false,
|
||||
@@ -15,18 +15,26 @@ export default {
|
||||
supportsTablet: true,
|
||||
bundleIdentifier: "mobiledarmasaba.app",
|
||||
infoPlist: {
|
||||
ITSAppUsesNonExemptEncryption: false
|
||||
ITSAppUsesNonExemptEncryption: false,
|
||||
CFBundleDisplayName: "Desa+"
|
||||
},
|
||||
googleServicesFile: "./ios/mobiledarmasaba/GoogleService-Info.plist"
|
||||
googleServicesFile: "./ios/Desa/GoogleService-Info.plist"
|
||||
},
|
||||
android: {
|
||||
package: "mobiledarmasaba.app",
|
||||
versionCode: 2,
|
||||
versionCode: 7,
|
||||
adaptiveIcon: {
|
||||
foregroundImage: "./assets/images/splash-icon.png",
|
||||
foregroundImage: "./assets/images/logo-icon-small.png",
|
||||
backgroundColor: "#ffffff"
|
||||
},
|
||||
googleServicesFile: "./google-services.json"
|
||||
googleServicesFile: "./google-services.json",
|
||||
permissions: [
|
||||
"READ_EXTERNAL_STORAGE",
|
||||
"WRITE_EXTERNAL_STORAGE",
|
||||
"READ_MEDIA_IMAGES", // Android 13+
|
||||
"READ_MEDIA_VIDEO", // Android 13+
|
||||
"READ_MEDIA_AUDIO" // Android 13+
|
||||
]
|
||||
},
|
||||
web: {
|
||||
bundler: "metro",
|
||||
@@ -38,7 +46,7 @@ export default {
|
||||
[
|
||||
"expo-splash-screen",
|
||||
{
|
||||
image: "./assets/images/splash-icon.png",
|
||||
image: "./assets/images/logo-icon-small.png",
|
||||
imageWidth: 200,
|
||||
resizeMode: "contain",
|
||||
backgroundColor: "#ffffff"
|
||||
@@ -51,7 +59,7 @@ export default {
|
||||
"@react-native-firebase/app",
|
||||
{
|
||||
ios: {
|
||||
googleServicesFile: "./ios/mobiledarmasaba/GoogleService-Info.plist"
|
||||
googleServicesFile: "./ios/Desa/GoogleService-Info.plist"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -8,7 +8,7 @@ import { useAuthSession } from "@/providers/AuthProvider";
|
||||
import { Entypo, MaterialIcons } from "@expo/vector-icons";
|
||||
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Dimensions, SafeAreaView, ScrollView, View } from "react-native";
|
||||
import { Dimensions, RefreshControl, SafeAreaView, ScrollView, View } from "react-native";
|
||||
import RenderHTML from 'react-native-render-html';
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
@@ -28,6 +28,7 @@ export default function DetailAnnouncement() {
|
||||
const contentWidth = Dimensions.get('window').width
|
||||
const [loading, setLoading] = useState(true)
|
||||
const arrSkeleton = Array.from({ length: 2 }, (_, index) => index)
|
||||
const [refreshing, setRefreshing] = useState(false)
|
||||
|
||||
async function handleLoad(loading: boolean) {
|
||||
try {
|
||||
@@ -56,6 +57,13 @@ export default function DetailAnnouncement() {
|
||||
return htmlRegex.test(text);
|
||||
};
|
||||
|
||||
const handleRefresh = async () => {
|
||||
setRefreshing(true)
|
||||
handleLoad(false)
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
setRefreshing(false)
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeAreaView>
|
||||
<Stack.Screen
|
||||
@@ -66,7 +74,16 @@ export default function DetailAnnouncement() {
|
||||
headerRight: () => entityUser.role != 'user' && entityUser.role != 'coadmin' ? <HeaderRightAnnouncementDetail id={id} /> : <></>,
|
||||
}}
|
||||
/>
|
||||
<ScrollView>
|
||||
<ScrollView
|
||||
showsVerticalScrollIndicator={false}
|
||||
style={[Styles.h100]}
|
||||
refreshControl={
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={() => handleRefresh()}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<View style={[Styles.p15]}>
|
||||
<View style={[Styles.wrapPaper]}>
|
||||
{
|
||||
|
||||
@@ -110,8 +110,11 @@ export default function CreateAnnouncement() {
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<ScrollView>
|
||||
<View style={[Styles.p15, Styles.mb100]}>
|
||||
<ScrollView
|
||||
showsVerticalScrollIndicator={false}
|
||||
style={[Styles.h100]}
|
||||
>
|
||||
<View style={[Styles.p15]}>
|
||||
<InputForm
|
||||
label="Judul"
|
||||
type="default"
|
||||
|
||||
@@ -153,8 +153,11 @@ export default function EditAnnouncement() {
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<ScrollView>
|
||||
<View style={[Styles.p15, Styles.mb100]}>
|
||||
<ScrollView
|
||||
showsVerticalScrollIndicator={false}
|
||||
style={[Styles.h100]}
|
||||
>
|
||||
<View style={[Styles.p15]}>
|
||||
<InputForm
|
||||
label="Judul"
|
||||
type="default"
|
||||
|
||||
@@ -130,7 +130,7 @@ export default function EditBanner() {
|
||||
category="update" />,
|
||||
}}
|
||||
/>
|
||||
<ScrollView>
|
||||
<ScrollView showsVerticalScrollIndicator={false} style={[Styles.h100]}>
|
||||
<View style={[Styles.p15, Styles.mb100]}>
|
||||
<View style={[Styles.mb15]}>
|
||||
{selectedImage != undefined ? (
|
||||
|
||||
@@ -117,8 +117,8 @@ export default function CreateBanner() {
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<ScrollView>
|
||||
<View style={[Styles.p15, Styles.mb100]}>
|
||||
<ScrollView showsVerticalScrollIndicator={false} style={[Styles.h100]}>
|
||||
<View style={[Styles.p15]}>
|
||||
<View style={[Styles.mb15]}>
|
||||
{selectedImage != undefined ? (
|
||||
<Pressable onPress={pickImageAsync}>
|
||||
|
||||
@@ -139,7 +139,7 @@ export default function DetailDiscussionGeneral() {
|
||||
}}
|
||||
/>
|
||||
<View style={{ flex: 1 }}>
|
||||
<ScrollView>
|
||||
<ScrollView showsVerticalScrollIndicator={false}>
|
||||
<View style={[Styles.p15, Styles.mb100]}>
|
||||
{
|
||||
loading ?
|
||||
|
||||
@@ -116,7 +116,7 @@ export default function AddMemberDiscussionDetail() {
|
||||
selectMember.length > 0
|
||||
?
|
||||
<View>
|
||||
<ScrollView horizontal style={[Styles.mb10, Styles.pv10]}>
|
||||
<ScrollView horizontal style={[Styles.mb10, Styles.pv10]} showsHorizontalScrollIndicator={false}>
|
||||
{
|
||||
selectMember.map((item: any, index: any) => (
|
||||
<ImageWithLabel
|
||||
@@ -133,7 +133,9 @@ export default function AddMemberDiscussionDetail() {
|
||||
:
|
||||
<Text style={[Styles.textDefault, Styles.cGray, Styles.pv05, { textAlign: 'center' }]}>Tidak ada member yang dipilih</Text>
|
||||
}
|
||||
<ScrollView>
|
||||
<ScrollView
|
||||
showsVerticalScrollIndicator={false}
|
||||
>
|
||||
|
||||
{
|
||||
data.length > 0 ?
|
||||
|
||||
@@ -142,7 +142,7 @@ export default function CreateDiscussionGeneral() {
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<ScrollView>
|
||||
<ScrollView showsVerticalScrollIndicator={false} style={[Styles.h100]}>
|
||||
<View style={[Styles.p15, Styles.mb100]}>
|
||||
{
|
||||
(entityUser.role == "supadmin" ||
|
||||
|
||||
@@ -119,7 +119,7 @@ export default function EditDiscussionGeneral() {
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<ScrollView>
|
||||
<ScrollView showsVerticalScrollIndicator={false} style={[Styles.h100]}>
|
||||
<View style={[Styles.p15]}>
|
||||
<InputForm
|
||||
label="Judul"
|
||||
|
||||
@@ -123,7 +123,7 @@ export default function AddMemberCalendarEvent() {
|
||||
selectMember.length > 0
|
||||
?
|
||||
<View>
|
||||
<ScrollView horizontal style={[Styles.mb10, Styles.pv10]}>
|
||||
<ScrollView horizontal style={[Styles.mb10, Styles.pv10]} showsHorizontalScrollIndicator={false}>
|
||||
{
|
||||
selectMember.map((item: any, index: any) => (
|
||||
<ImageWithLabel
|
||||
@@ -140,7 +140,9 @@ export default function AddMemberCalendarEvent() {
|
||||
:
|
||||
<Text style={[Styles.textDefault, Styles.cGray, Styles.pv05, { textAlign: 'center' }]}>Tidak ada member yang dipilih</Text>
|
||||
}
|
||||
<ScrollView>
|
||||
<ScrollView
|
||||
showsVerticalScrollIndicator={false}
|
||||
>
|
||||
{
|
||||
data.length > 0 ?
|
||||
data.map((item: any, index: any) => {
|
||||
|
||||
@@ -112,7 +112,7 @@ export default function CreateCalendarAddMember() {
|
||||
selectMember.length > 0
|
||||
?
|
||||
<View>
|
||||
<ScrollView horizontal style={[Styles.mb10, Styles.pv10]}>
|
||||
<ScrollView horizontal style={[Styles.mb10, Styles.pv10]} showsHorizontalScrollIndicator={false}>
|
||||
{
|
||||
selectMember.map((item: any, index: any) => (
|
||||
<ImageWithLabel
|
||||
@@ -129,7 +129,9 @@ export default function CreateCalendarAddMember() {
|
||||
:
|
||||
<Text style={[Styles.textDefault, Styles.cGray, Styles.pv05, { textAlign: 'center' }]}>Tidak ada member yang dipilih</Text>
|
||||
}
|
||||
<ScrollView>
|
||||
<ScrollView
|
||||
showsVerticalScrollIndicator={false}
|
||||
>
|
||||
|
||||
{
|
||||
data.length > 0 ?
|
||||
|
||||
@@ -93,6 +93,7 @@ export default function DiscussionDivisionEdit() {
|
||||
required
|
||||
value={data}
|
||||
onChange={setData}
|
||||
multiline
|
||||
/>
|
||||
</View>
|
||||
</ScrollView>
|
||||
|
||||
@@ -56,7 +56,14 @@ export default function CreateDiscussionDivision() {
|
||||
/>
|
||||
<ScrollView>
|
||||
<View style={[Styles.p15, Styles.mb100]}>
|
||||
<InputForm label="Diskusi" type="default" placeholder="Hal yang didiskusikan" required onChange={setDesc} />
|
||||
<InputForm
|
||||
label="Diskusi"
|
||||
type="default"
|
||||
placeholder="Hal yang didiskusikan"
|
||||
required
|
||||
onChange={setDesc}
|
||||
multiline
|
||||
/>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</SafeAreaView>
|
||||
|
||||
@@ -118,7 +118,7 @@ export default function AddMemberTask() {
|
||||
selectMember.length > 0
|
||||
?
|
||||
<View>
|
||||
<ScrollView horizontal style={[Styles.mb10, Styles.pv10]}>
|
||||
<ScrollView horizontal style={[Styles.mb10, Styles.pv10]} showsHorizontalScrollIndicator={false}>
|
||||
{
|
||||
selectMember.map((item: any, index: any) => (
|
||||
<ImageWithLabel
|
||||
@@ -135,7 +135,9 @@ export default function AddMemberTask() {
|
||||
:
|
||||
<Text style={[Styles.textDefault, Styles.cGray, Styles.pv05, { textAlign: 'center' }]}>Tidak ada member yang dipilih</Text>
|
||||
}
|
||||
<ScrollView>
|
||||
<ScrollView
|
||||
showsVerticalScrollIndicator={false}
|
||||
>
|
||||
|
||||
{
|
||||
data.length > 0 ?
|
||||
|
||||
@@ -88,7 +88,7 @@ export default function AddMemberCreateTask() {
|
||||
selectMember.length > 0
|
||||
?
|
||||
<View>
|
||||
<ScrollView horizontal style={[Styles.mb10, Styles.pv10]}>
|
||||
<ScrollView horizontal style={[Styles.mb10, Styles.pv10]} showsHorizontalScrollIndicator={false}>
|
||||
{
|
||||
selectMember.map((item: any, index: any) => (
|
||||
<ImageWithLabel
|
||||
@@ -105,7 +105,9 @@ export default function AddMemberCreateTask() {
|
||||
:
|
||||
<Text style={[Styles.textDefault, Styles.cGray, Styles.pv05, { textAlign: 'center' }]}>Tidak ada member yang dipilih</Text>
|
||||
}
|
||||
<ScrollView>
|
||||
<ScrollView
|
||||
showsVerticalScrollIndicator={false}
|
||||
>
|
||||
|
||||
{
|
||||
data.length > 0 ?
|
||||
|
||||
@@ -106,7 +106,7 @@ export default function ListTask() {
|
||||
return (
|
||||
<View style={[Styles.p15, { flex: 1 }]}>
|
||||
<View>
|
||||
<ScrollView horizontal style={[Styles.mb10]}>
|
||||
<ScrollView horizontal style={[Styles.mb10]} showsHorizontalScrollIndicator={false}>
|
||||
<ButtonTab
|
||||
active={statusFix}
|
||||
value="0"
|
||||
|
||||
@@ -119,7 +119,7 @@ export default function AddMemberDivision() {
|
||||
selectMember.length > 0
|
||||
?
|
||||
<View>
|
||||
<ScrollView horizontal style={[Styles.mb10, Styles.pv10]}>
|
||||
<ScrollView horizontal style={[Styles.mb10, Styles.pv10]} showsHorizontalScrollIndicator={false}>
|
||||
{
|
||||
selectMember.map((item: any, index: any) => (
|
||||
<ImageWithLabel
|
||||
@@ -136,7 +136,9 @@ export default function AddMemberDivision() {
|
||||
:
|
||||
<Text style={[Styles.textDefault, Styles.cGray, Styles.pv05, { textAlign: 'center' }]}>Tidak ada member yang dipilih</Text>
|
||||
}
|
||||
<ScrollView>
|
||||
<ScrollView
|
||||
showsVerticalScrollIndicator={false}
|
||||
>
|
||||
|
||||
{
|
||||
data.length > 0 ?
|
||||
|
||||
@@ -10,7 +10,7 @@ import { apiGetDivisionOneDetail } from "@/lib/api"
|
||||
import { useAuthSession } from "@/providers/AuthProvider"
|
||||
import { router, Stack, useLocalSearchParams } from "expo-router"
|
||||
import { useEffect, useState } from "react"
|
||||
import { SafeAreaView, ScrollView, View } from "react-native"
|
||||
import { RefreshControl, SafeAreaView, ScrollView, View } from "react-native"
|
||||
|
||||
type Props = {
|
||||
id: string,
|
||||
@@ -26,11 +26,12 @@ export default function DetailDivisionFitur() {
|
||||
const { id } = useLocalSearchParams<{ id: string }>()
|
||||
const [data, setData] = useState<Props>()
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [refreshing, setRefreshing] = useState(false)
|
||||
|
||||
|
||||
async function handleLoad() {
|
||||
async function handleLoad(loading: boolean) {
|
||||
try {
|
||||
setLoading(true)
|
||||
setLoading(loading)
|
||||
const hasil = await decryptToken(String(token?.current))
|
||||
const response = await apiGetDivisionOneDetail({ user: hasil, id })
|
||||
setData(response.data.division)
|
||||
@@ -42,9 +43,16 @@ export default function DetailDivisionFitur() {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
handleLoad()
|
||||
handleLoad(true)
|
||||
}, [])
|
||||
|
||||
const handleRefresh = async () => {
|
||||
setRefreshing(true)
|
||||
handleLoad(false)
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
setRefreshing(false)
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeAreaView>
|
||||
<Stack.Screen
|
||||
@@ -55,13 +63,21 @@ export default function DetailDivisionFitur() {
|
||||
headerRight: () => <HeaderRightDivisionDetail id={id} />,
|
||||
}}
|
||||
/>
|
||||
<ScrollView>
|
||||
<CaraouselHome />
|
||||
<ScrollView
|
||||
refreshControl={
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
/>
|
||||
}
|
||||
showsVerticalScrollIndicator={false}
|
||||
>
|
||||
<CaraouselHome refreshing={refreshing} />
|
||||
<View style={[Styles.ph15, Styles.mb100]}>
|
||||
<FiturDivisionDetail />
|
||||
<TaskDivisionDetail />
|
||||
<FileDivisionDetail />
|
||||
<DiscussionDivisionDetail />
|
||||
<FiturDivisionDetail refreshing={refreshing}/>
|
||||
<TaskDivisionDetail refreshing={refreshing}/>
|
||||
<FileDivisionDetail refreshing={refreshing}/>
|
||||
<DiscussionDivisionDetail refreshing={refreshing}/>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</SafeAreaView>
|
||||
|
||||
@@ -81,7 +81,7 @@ export default function CreateDivisionAddMember() {
|
||||
selectMember.length > 0
|
||||
?
|
||||
<View>
|
||||
<ScrollView horizontal style={[Styles.mb10, Styles.pv10]}>
|
||||
<ScrollView horizontal style={[Styles.mb10, Styles.pv10]} showsHorizontalScrollIndicator={false}>
|
||||
{
|
||||
selectMember.map((item: any, index: any) => (
|
||||
<ImageWithLabel
|
||||
@@ -98,7 +98,9 @@ export default function CreateDivisionAddMember() {
|
||||
:
|
||||
<Text style={[Styles.textDefault, Styles.cGray, Styles.pv05, { textAlign: 'center' }]}>Tidak ada member yang dipilih</Text>
|
||||
}
|
||||
<ScrollView>
|
||||
<ScrollView
|
||||
showsVerticalScrollIndicator={false}
|
||||
>
|
||||
|
||||
{
|
||||
data.length > 0 ?
|
||||
|
||||
@@ -13,8 +13,8 @@ import { apiGetProfile } from "@/lib/api";
|
||||
import { setEntities } from "@/lib/entitiesSlice";
|
||||
import { useAuthSession } from "@/providers/AuthProvider";
|
||||
import { Stack } from "expo-router";
|
||||
import { useEffect } from "react";
|
||||
import { Platform, SafeAreaView, ScrollView, View } from "react-native";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Platform, RefreshControl, SafeAreaView, ScrollView, View } from "react-native";
|
||||
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
|
||||
@@ -24,6 +24,7 @@ export default function Home() {
|
||||
const dispatch = useDispatch()
|
||||
const { token, decryptToken, signOut } = useAuthSession()
|
||||
const insets = useSafeAreaInsets()
|
||||
const [refreshing, setRefreshing] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
handleUserLogin()
|
||||
@@ -38,6 +39,13 @@ export default function Home() {
|
||||
});
|
||||
}
|
||||
|
||||
const handleRefresh = async () => {
|
||||
setRefreshing(true)
|
||||
handleUserLogin()
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
setRefreshing(false)
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeAreaView>
|
||||
<Stack.Screen
|
||||
@@ -52,16 +60,24 @@ export default function Home() {
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<ScrollView>
|
||||
<CaraouselHome />
|
||||
<ScrollView
|
||||
refreshControl={
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
/>
|
||||
}
|
||||
showsVerticalScrollIndicator={false}
|
||||
>
|
||||
<CaraouselHome refreshing={refreshing}/>
|
||||
<View style={[Styles.ph15, Styles.mb100]}>
|
||||
<FiturHome />
|
||||
<ProjectHome />
|
||||
<DivisionHome />
|
||||
<ChartProgresHome />
|
||||
<ChartDokumenHome />
|
||||
<EventHome />
|
||||
<DisccussionHome />
|
||||
<ProjectHome refreshing={refreshing}/>
|
||||
<DivisionHome refreshing={refreshing}/>
|
||||
<ChartProgresHome refreshing={refreshing}/>
|
||||
<ChartDokumenHome refreshing={refreshing}/>
|
||||
<EventHome refreshing={refreshing}/>
|
||||
<DisccussionHome refreshing={refreshing}/>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</SafeAreaView>
|
||||
|
||||
@@ -231,7 +231,7 @@ export default function CreateMember() {
|
||||
behavior={Platform.OS === 'ios' ? 'padding' : undefined}
|
||||
keyboardVerticalOffset={headerHeight}
|
||||
>
|
||||
<ScrollView>
|
||||
<ScrollView showsVerticalScrollIndicator={false}>
|
||||
<View style={[Styles.p15]}>
|
||||
<View style={{ justifyContent: "center", alignItems: "center" }}>
|
||||
{selectedImage != undefined ? (
|
||||
|
||||
@@ -264,8 +264,8 @@ export default function EditMember() {
|
||||
behavior={Platform.OS === 'ios' ? 'padding' : undefined}
|
||||
keyboardVerticalOffset={headerHeight}
|
||||
>
|
||||
<ScrollView>
|
||||
<View style={[Styles.p15, Styles.mb100]}>
|
||||
<ScrollView showsVerticalScrollIndicator={false} style={[Styles.h100]}>
|
||||
<View style={[Styles.p15]}>
|
||||
<View style={{ justifyContent: "center", alignItems: "center" }}>
|
||||
{
|
||||
errorImg ?
|
||||
|
||||
@@ -9,7 +9,7 @@ import { pushToPage } from "@/lib/pushToPage";
|
||||
import { useAuthSession } from "@/providers/AuthProvider";
|
||||
import { Feather } from "@expo/vector-icons";
|
||||
import { useEffect, useState } from "react";
|
||||
import { SafeAreaView, View, VirtualizedList } from "react-native";
|
||||
import { RefreshControl, SafeAreaView, View, VirtualizedList } from "react-native";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
|
||||
type Props = {
|
||||
@@ -31,6 +31,7 @@ export default function Notification() {
|
||||
const arrSkeleton = Array.from({ length: 5 }, (_, index) => index)
|
||||
const dispatch = useDispatch()
|
||||
const updateNotification = useSelector((state: any) => state.notificationUpdate)
|
||||
const [refreshing, setRefreshing] = useState(false)
|
||||
|
||||
async function handleLoad(loading: boolean, thisPage: number) {
|
||||
try {
|
||||
@@ -88,33 +89,12 @@ export default function Notification() {
|
||||
}
|
||||
}
|
||||
|
||||
// function pushToPage(category: string, idContent: string) {
|
||||
// const cat = category.split('/')
|
||||
// if (cat.length > 1) {
|
||||
// if (cat[2] == 'calendar') {
|
||||
// router.push(`/division/${cat[1]}/calendar/${idContent}`)
|
||||
// } else if (cat[2] == 'discussion') {
|
||||
// router.push(`/division/${cat[1]}/discussion/${idContent}`)
|
||||
// } else if (cat[2] == 'document') {
|
||||
// router.push(`/division/${cat[1]}/document/${idContent}`)
|
||||
// } else if (cat[2] == 'task') {
|
||||
// router.push(`/division/${cat[1]}/task/${idContent}`)
|
||||
// }
|
||||
// } else {
|
||||
// if (cat[0] == 'announcement') {
|
||||
// router.push(`/announcement/${idContent}`)
|
||||
// } else if (cat[0] == 'discussion-general') {
|
||||
// router.push(`/discussion/${idContent}`)
|
||||
// } else if (cat[0] == 'division') {
|
||||
// router.push(`/division/${idContent}`)
|
||||
// } else if (cat[0] == 'member') {
|
||||
// router.push(`/member/${idContent}`)
|
||||
// } else if (cat[0] == 'project') {
|
||||
// router.push(`/project/${idContent}`)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
const handleRefresh = async () => {
|
||||
setRefreshing(true)
|
||||
handleLoad(false, 1)
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
setRefreshing(false)
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeAreaView>
|
||||
@@ -156,6 +136,12 @@ export default function Notification() {
|
||||
onEndReached={loadMoreData}
|
||||
onEndReachedThreshold={0.5}
|
||||
showsVerticalScrollIndicator={false}
|
||||
refreshControl={
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
:
|
||||
<Text style={[Styles.textDefault, Styles.cGray, { textAlign: 'center' }]}>Tidak ada data</Text>
|
||||
|
||||
@@ -38,7 +38,7 @@ export default function Profile() {
|
||||
/>
|
||||
}}
|
||||
/>
|
||||
<ScrollView>
|
||||
<ScrollView style={[Styles.h100]}>
|
||||
<View style={{ flexDirection: 'column' }}>
|
||||
<View style={[Styles.wrapHeadViewMember]}>
|
||||
<Image
|
||||
|
||||
@@ -117,7 +117,7 @@ export default function AddMemberProject() {
|
||||
selectMember.length > 0
|
||||
?
|
||||
<View>
|
||||
<ScrollView horizontal style={[Styles.mb10, Styles.pv10]}>
|
||||
<ScrollView horizontal style={[Styles.mb10, Styles.pv10]} showsHorizontalScrollIndicator={false}>
|
||||
{
|
||||
selectMember.map((item: any, index: any) => (
|
||||
<ImageWithLabel
|
||||
@@ -134,35 +134,43 @@ export default function AddMemberProject() {
|
||||
:
|
||||
<Text style={[Styles.textDefault, Styles.cGray, Styles.pv05, { textAlign: 'center' }]}>Tidak ada member yang dipilih</Text>
|
||||
}
|
||||
<ScrollView>
|
||||
<ScrollView
|
||||
showsVerticalScrollIndicator={false}
|
||||
style={[Styles.h100]}
|
||||
>
|
||||
{
|
||||
data.length > 0 ?
|
||||
data.map((item: any, index: any) => {
|
||||
const found = dataOld.some((i: any) => i.idUser == item.id)
|
||||
return (
|
||||
<Pressable
|
||||
key={index}
|
||||
style={[Styles.itemSelectModal]}
|
||||
onPress={() => {
|
||||
!found && onChoose(item.id, item.name, item.img)
|
||||
}}
|
||||
>
|
||||
<View style={[Styles.rowItemsCenter, Styles.w80]}>
|
||||
<ImageUser src={`${ConstEnv.url_storage}/files/${item.img}`} border />
|
||||
<View style={[Styles.ml10]}>
|
||||
<Text style={[Styles.textDefault]} numberOfLines={1}>{item.name}</Text>
|
||||
<View style={[Styles.mb100]}>
|
||||
{
|
||||
data.map((item: any, index: any) => {
|
||||
const found = dataOld.some((i: any) => i.idUser == item.id)
|
||||
return (
|
||||
<Pressable
|
||||
key={index}
|
||||
style={[Styles.itemSelectModal]}
|
||||
onPress={() => {
|
||||
!found && onChoose(item.id, item.name, item.img)
|
||||
}}
|
||||
>
|
||||
<View style={[Styles.rowItemsCenter, Styles.w80]}>
|
||||
<ImageUser src={`${ConstEnv.url_storage}/files/${item.img}`} border />
|
||||
<View style={[Styles.ml10]}>
|
||||
<Text style={[Styles.textDefault]} numberOfLines={1}>{item.name}</Text>
|
||||
{
|
||||
found && <Text style={[Styles.textInformation, Styles.cGray]}>sudah menjadi anggota</Text>
|
||||
}
|
||||
</View>
|
||||
</View>
|
||||
{
|
||||
found && <Text style={[Styles.textInformation, Styles.cGray]}>sudah menjadi anggota</Text>
|
||||
selectMember.some((i: any) => i.idUser == item.id) && <AntDesign name="check" size={20} color={'black'} />
|
||||
}
|
||||
</View>
|
||||
</View>
|
||||
{
|
||||
selectMember.some((i: any) => i.idUser == item.id) && <AntDesign name="check" size={20} color={'black'} />
|
||||
}
|
||||
</Pressable>
|
||||
)
|
||||
}
|
||||
)
|
||||
</Pressable>
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
</View>
|
||||
|
||||
:
|
||||
<Text style={[Styles.textDefault, { textAlign: 'center' }]}>Tidak ada data</Text>
|
||||
}
|
||||
|
||||
@@ -88,8 +88,11 @@ export default function ProjectCancel() {
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<ScrollView>
|
||||
<View style={[Styles.p15, Styles.mb100]}>
|
||||
<ScrollView
|
||||
showsVerticalScrollIndicator={false}
|
||||
style={[Styles.h100]}
|
||||
>
|
||||
<View style={[Styles.p15]}>
|
||||
<InputForm
|
||||
label="Alasan Pembatalan"
|
||||
type="default"
|
||||
@@ -99,6 +102,7 @@ export default function ProjectCancel() {
|
||||
error={error}
|
||||
errorText="Alasan pembatalan harus diisi"
|
||||
onChange={(val) => onValidation(val)}
|
||||
multiline
|
||||
/>
|
||||
</View>
|
||||
</ScrollView>
|
||||
|
||||
@@ -107,8 +107,11 @@ export default function ReportProject() {
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<ScrollView>
|
||||
<View style={[Styles.p15, Styles.mb100]}>
|
||||
<ScrollView
|
||||
showsVerticalScrollIndicator={false}
|
||||
style={[Styles.h100]}
|
||||
>
|
||||
<View style={[Styles.p15]}>
|
||||
<InputForm
|
||||
label="Laporan Kegiatan"
|
||||
type="default"
|
||||
|
||||
@@ -205,8 +205,11 @@ export default function CreateProject() {
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<ScrollView>
|
||||
<View style={[Styles.p15, Styles.mb100]}>
|
||||
<ScrollView
|
||||
showsVerticalScrollIndicator={false}
|
||||
style={[Styles.h100]}
|
||||
>
|
||||
<View style={[Styles.p15]}>
|
||||
{
|
||||
(entityUser.role == "supadmin" || entityUser.role == "developer")
|
||||
&&
|
||||
|
||||
@@ -95,7 +95,7 @@ export default function AddMemberCreateProject() {
|
||||
selectMember.length > 0
|
||||
?
|
||||
<View>
|
||||
<ScrollView horizontal style={[Styles.mb10, Styles.pv10]}>
|
||||
<ScrollView horizontal style={[Styles.mb10, Styles.pv10]} showsHorizontalScrollIndicator={false}>
|
||||
{
|
||||
selectMember.map((item: any, index: any) => (
|
||||
<ImageWithLabel
|
||||
@@ -112,7 +112,9 @@ export default function AddMemberCreateProject() {
|
||||
:
|
||||
<Text style={[Styles.textDefault, Styles.cGray, Styles.pv05, { textAlign: 'center' }]}>Tidak ada member yang dipilih</Text>
|
||||
}
|
||||
<ScrollView>
|
||||
<ScrollView
|
||||
showsVerticalScrollIndicator={false}
|
||||
>
|
||||
|
||||
{
|
||||
data.length > 0 ?
|
||||
|
||||
@@ -120,7 +120,7 @@ export default function ListProject() {
|
||||
return (
|
||||
<View style={[Styles.p15, { flex: 1 }]}>
|
||||
<View>
|
||||
<ScrollView horizontal style={[Styles.mb10]}>
|
||||
<ScrollView horizontal style={[Styles.mb10]} showsHorizontalScrollIndicator={false}>
|
||||
<ButtonTab
|
||||
active={statusFix}
|
||||
value="0"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import BorderBottomItem from "@/components/borderBottomItem";
|
||||
import ButtonBackHeader from "@/components/buttonBackHeader";
|
||||
import ImageUser from "@/components/imageNew";
|
||||
import InputSearch from "@/components/inputSearch";
|
||||
import Text from '@/components/Text';
|
||||
import { ColorsStatus } from "@/constants/ColorsStatus";
|
||||
@@ -9,8 +10,8 @@ import { apiGetSearch } from "@/lib/api";
|
||||
import { useAuthSession } from "@/providers/AuthProvider";
|
||||
import { AntDesign, MaterialIcons } from "@expo/vector-icons";
|
||||
import { router, Stack } from "expo-router";
|
||||
import { useState } from "react";
|
||||
import { FlatList, Image, SafeAreaView, View } from "react-native";
|
||||
import React, { useState } from "react";
|
||||
import { RefreshControl, SafeAreaView, ScrollView, View } from "react-native";
|
||||
import Toast from "react-native-toast-message";
|
||||
|
||||
type PropsUser = {
|
||||
@@ -40,10 +41,13 @@ export default function Search() {
|
||||
const [dataUser, setDataUser] = useState<PropsUser[]>([])
|
||||
const [dataDivisi, setDataDivisi] = useState<PropDivisi[]>([])
|
||||
const [dataProject, setDataProject] = useState<PropProject[]>([])
|
||||
const [refreshing, setRefreshing] = useState(false)
|
||||
const [search, setSearch] = useState('')
|
||||
|
||||
async function handleSearch(cari: string) {
|
||||
try {
|
||||
if (cari.length > 3) {
|
||||
setSearch(cari)
|
||||
if (cari.length >= 3) {
|
||||
const user = await decryptToken(String(token?.current))
|
||||
const hasil = await apiGetSearch({ text: cari, user: user })
|
||||
if (hasil.success) {
|
||||
@@ -65,6 +69,14 @@ export default function Search() {
|
||||
}
|
||||
|
||||
|
||||
const handleRefresh = async () => {
|
||||
setRefreshing(true)
|
||||
handleSearch(search)
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
setRefreshing(false)
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<SafeAreaView>
|
||||
@@ -80,41 +92,44 @@ export default function Search() {
|
||||
{
|
||||
dataProject.length + dataDivisi.length + dataUser.length > 0
|
||||
?
|
||||
<View style={[Styles.wrapPaper, Styles.mb100]}>
|
||||
<ScrollView
|
||||
style={[Styles.h100]}
|
||||
refreshControl={
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
/>
|
||||
}
|
||||
>
|
||||
{
|
||||
dataUser.length > 0 &&
|
||||
<View style={[Styles.mb05]}>
|
||||
<View style={[Styles.mv05, Styles.p10]}>
|
||||
<Text>ANGGOTA</Text>
|
||||
<FlatList
|
||||
data={dataUser}
|
||||
keyExtractor={(item) => String(item.id)}
|
||||
renderItem={({ item }) => (
|
||||
{
|
||||
dataUser.map((item, index) => (
|
||||
<BorderBottomItem
|
||||
key={index}
|
||||
borderType="bottom"
|
||||
icon={<Image
|
||||
source={{ uri: `${ConstEnv.url_storage}/files/${item.img}` }}
|
||||
style={[Styles.userProfileSmall]}
|
||||
/>}
|
||||
icon={<ImageUser src={`${ConstEnv.url_storage}/files/${item.img}`} />}
|
||||
title={item.name}
|
||||
subtitle={`${item.group}-${item.position}`}
|
||||
onPress={() => {
|
||||
router.push(`/member/${item.id}`)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</View>
|
||||
}
|
||||
|
||||
{
|
||||
dataDivisi.length > 0 &&
|
||||
<View style={[Styles.mb05]}>
|
||||
<View style={[Styles.mv05, Styles.p10]}>
|
||||
<Text>DIVISI</Text>
|
||||
<FlatList
|
||||
data={dataDivisi}
|
||||
keyExtractor={(item) => String(item.id)}
|
||||
renderItem={({ item }) => (
|
||||
{
|
||||
dataDivisi.map((item, index) => (
|
||||
<BorderBottomItem
|
||||
key={index}
|
||||
borderType="bottom"
|
||||
icon={
|
||||
<View style={[Styles.iconContent, ColorsStatus.primary]}>
|
||||
@@ -127,21 +142,20 @@ export default function Search() {
|
||||
router.push(`/division/${item.id}`)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</View>
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
dataProject.length > 0 &&
|
||||
<View style={[Styles.mb10]}>
|
||||
<View style={[Styles.mv05, Styles.p10]}>
|
||||
<Text>KEGIATAN</Text>
|
||||
<FlatList
|
||||
data={dataProject}
|
||||
keyExtractor={(item) => String(item.id)}
|
||||
renderItem={({ item }) => (
|
||||
{
|
||||
dataProject.map((item, index) => (
|
||||
<BorderBottomItem
|
||||
key={index}
|
||||
borderType="bottom"
|
||||
icon={
|
||||
<View style={[Styles.iconContent, ColorsStatus.primary]}>
|
||||
@@ -154,13 +168,11 @@ export default function Search() {
|
||||
router.push(`/project/${item.id}`)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</View>
|
||||
}
|
||||
|
||||
|
||||
</View>
|
||||
</ScrollView>
|
||||
:
|
||||
<View style={[Styles.contentItemCenter, Styles.mt10]}>
|
||||
<Text style={[Styles.textInformation, Styles.cGray]}>Tidak ada data</Text>
|
||||
|
||||
@@ -27,10 +27,12 @@ export default function Index() {
|
||||
<View style={Styles.wrapLogin} >
|
||||
<View style={{ alignItems: "center", marginVertical: 50 }}>
|
||||
<Image
|
||||
source={require("../assets/images/splash-icon.png")}
|
||||
style={{ width: 130, height: 130 }}
|
||||
source={require("../assets/images/logo.png")}
|
||||
style={[{ width: 300, height: 150 }]}
|
||||
width={270}
|
||||
height={110}
|
||||
/>
|
||||
<Text style={[Styles.textSubtitle]}>PERBEKEL DARMASABA</Text>
|
||||
{/* <Text style={[Styles.textSubtitle]}>PERBEKEL DARMASABA</Text> */}
|
||||
</View>
|
||||
<View style={[Styles.mb30]}>
|
||||
<Text style={[Styles.textDefaultSemiBold]}>Verifikasi Nomor Telepon</Text>
|
||||
|
||||
BIN
assets/images/logo-clean.png
Normal file
|
After Width: | Height: | Size: 63 KiB |
BIN
assets/images/logo-icon-small.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
assets/images/logo-icon.png
Normal file
|
After Width: | Height: | Size: 9.7 KiB |
BIN
assets/images/logo.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
38
bump-version.js
Normal file
@@ -0,0 +1,38 @@
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const configPath = path.join(__dirname, "app.config.js");
|
||||
let configFile = fs.readFileSync(configPath, "utf8");
|
||||
|
||||
// --- Update versionCode ---
|
||||
const codeRegex = /versionCode:\s*(\d+)/;
|
||||
const codeMatch = configFile.match(codeRegex);
|
||||
|
||||
if (!codeMatch) {
|
||||
console.error("❌ Tidak menemukan versionCode di app.config.js");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const currentCode = parseInt(codeMatch[1], 10);
|
||||
const newCode = currentCode + 1;
|
||||
configFile = configFile.replace(codeRegex, `versionCode: ${newCode}`);
|
||||
|
||||
// --- Update versionName ---
|
||||
const nameRegex = /version:\s*"(.*?)"/;
|
||||
const nameMatch = configFile.match(nameRegex);
|
||||
|
||||
if (!nameMatch) {
|
||||
console.error("❌ Tidak menemukan version di app.config.js");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let [major, minor, patch] = nameMatch[1].split(".").map(Number);
|
||||
patch += 1; // bump patch version
|
||||
const newName = `${major}.${minor}.${patch}`;
|
||||
configFile = configFile.replace(nameRegex, `version: "${newName}"`);
|
||||
|
||||
// --- Simpan file ---
|
||||
fs.writeFileSync(configPath, configFile, "utf8");
|
||||
|
||||
console.log(`✅ versionCode: ${currentCode} → ${newCode}`);
|
||||
console.log(`✅ versionName: ${nameMatch[1]} → ${newName}`);
|
||||
@@ -53,12 +53,14 @@ export default function ViewLogin({ onValidate }: Props) {
|
||||
<StatusBar style={Platform.OS === 'ios' ? 'auto' : 'light'} translucent={false} backgroundColor="black" />
|
||||
<ToastCustom />
|
||||
<View style={[Styles.p20, Styles.h100]}>
|
||||
<View style={{ alignItems: "center", marginVertical: 50 }}>
|
||||
<View style={{ alignItems: "center", marginTop: 70, marginBottom: 50 }}>
|
||||
<Image
|
||||
source={require("../../assets/images/splash-icon.png")}
|
||||
style={{ width: 130, height: 130 }}
|
||||
source={require("../../assets/images/logo.png")}
|
||||
style={[{ width: 300, height: 150 }]}
|
||||
width={270}
|
||||
height={110}
|
||||
/>
|
||||
<Text style={[Styles.textSubtitle]}>PERBEKEL DARMASABA</Text>
|
||||
{/* <Text style={[Styles.textSubtitle2]}>Digitalisasi Desa Transparansi Kerja</Text> */}
|
||||
</View>
|
||||
<InputForm
|
||||
onChange={(val) => {
|
||||
|
||||
@@ -57,15 +57,17 @@ export default function ViewVerification({ phone, otp }: Props) {
|
||||
|
||||
return (
|
||||
<>
|
||||
<StatusBar style={Platform.OS === 'ios' ? 'auto' : 'light'} translucent={false} backgroundColor="black"/>
|
||||
<StatusBar style={Platform.OS === 'ios' ? 'auto' : 'light'} translucent={false} backgroundColor="black" />
|
||||
<ToastCustom />
|
||||
<View style={Styles.wrapLogin} >
|
||||
<View style={{ alignItems: "center", marginVertical: 50 }}>
|
||||
<View style={{ alignItems: "center", marginTop: 70, marginBottom: 50 }}>
|
||||
<Image
|
||||
source={require("../../assets/images/splash-icon.png")}
|
||||
style={{ width: 130, height: 130 }}
|
||||
source={require("../../assets/images/logo.png")}
|
||||
style={[{ width: 300, height: 150 }]}
|
||||
width={270}
|
||||
height={110}
|
||||
/>
|
||||
<Text style={[Styles.textSubtitle]}>PERBEKEL DARMASABA</Text>
|
||||
{/* <Text style={[Styles.textSubtitle]}>PERBEKEL DARMASABA</Text> */}
|
||||
</View>
|
||||
<View style={[Styles.mb30]}>
|
||||
<Text style={[Styles.textDefaultSemiBold]}>Verifikasi Nomor Telepon</Text>
|
||||
|
||||
@@ -16,15 +16,15 @@ type Props = {
|
||||
date: string;
|
||||
};
|
||||
|
||||
export default function DiscussionDivisionDetail() {
|
||||
export default function DiscussionDivisionDetail({ refreshing }: { refreshing: boolean }) {
|
||||
const { token, decryptToken } = useAuthSession();
|
||||
const { id } = useLocalSearchParams<{ id: string }>();
|
||||
const [data, setData] = useState<Props[]>([]);
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
async function handleLoad() {
|
||||
async function handleLoad(loading: boolean) {
|
||||
try {
|
||||
setLoading(true)
|
||||
setLoading(loading)
|
||||
const hasil = await decryptToken(String(token?.current));
|
||||
const response = await apiGetDivisionOneFeature({
|
||||
user: hasil,
|
||||
@@ -40,8 +40,15 @@ export default function DiscussionDivisionDetail() {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
handleLoad();
|
||||
}, []);
|
||||
if (refreshing)
|
||||
handleLoad(false)
|
||||
}, [refreshing])
|
||||
|
||||
useEffect(() => {
|
||||
handleLoad(true)
|
||||
}, [])
|
||||
|
||||
|
||||
return (
|
||||
<View style={[Styles.mb15]}>
|
||||
<Text style={[Styles.textDefaultSemiBold, Styles.mv10]}>Diskusi</Text>
|
||||
|
||||
@@ -24,7 +24,7 @@ type Props = {
|
||||
idStorage: string
|
||||
}
|
||||
|
||||
export default function FileDivisionDetail() {
|
||||
export default function FileDivisionDetail({ refreshing }: { refreshing: boolean }) {
|
||||
const ref = React.useRef<ICarouselInstance>(null);
|
||||
const width = Dimensions.get("window").width;
|
||||
const [data, setData] = useState<Props[]>([])
|
||||
@@ -33,9 +33,9 @@ export default function FileDivisionDetail() {
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [loadingOpen, setLoadingOpen] = useState(false)
|
||||
|
||||
async function handleLoad() {
|
||||
async function handleLoad(loading: boolean) {
|
||||
try {
|
||||
setLoading(true)
|
||||
setLoading(loading)
|
||||
const hasil = await decryptToken(String(token?.current))
|
||||
const response = await apiGetDivisionOneFeature({ user: hasil, id, cat: 'new-file' })
|
||||
setData(response.data)
|
||||
@@ -47,7 +47,12 @@ export default function FileDivisionDetail() {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
handleLoad()
|
||||
if (refreshing)
|
||||
handleLoad(false)
|
||||
}, [refreshing])
|
||||
|
||||
useEffect(() => {
|
||||
handleLoad(true)
|
||||
}, [])
|
||||
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ type Props = {
|
||||
kalender: number
|
||||
}
|
||||
|
||||
export default function FiturDivisionDetail() {
|
||||
export default function FiturDivisionDetail({ refreshing }: { refreshing: boolean }) {
|
||||
const { token, decryptToken } = useAuthSession()
|
||||
const { id } = useLocalSearchParams<{ id: string }>()
|
||||
const [data, setData] = useState<Props>({
|
||||
@@ -36,7 +36,10 @@ export default function FiturDivisionDetail() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (refreshing)
|
||||
handleLoad()
|
||||
}, [refreshing])
|
||||
|
||||
useEffect(() => {
|
||||
handleLoad()
|
||||
|
||||
@@ -18,7 +18,7 @@ type Props = {
|
||||
projectTitle: string
|
||||
}
|
||||
|
||||
export default function TaskDivisionDetail() {
|
||||
export default function TaskDivisionDetail({ refreshing }: { refreshing: boolean }) {
|
||||
const { token, decryptToken } = useAuthSession()
|
||||
const { id } = useLocalSearchParams<{ id: string }>()
|
||||
const [data, setData] = useState<Props[]>([])
|
||||
@@ -26,9 +26,9 @@ export default function TaskDivisionDetail() {
|
||||
const width = Dimensions.get("window").width;
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
async function handleLoad() {
|
||||
async function handleLoad(loading: boolean) {
|
||||
try {
|
||||
setLoading(true)
|
||||
setLoading(loading)
|
||||
const hasil = await decryptToken(String(token?.current))
|
||||
const response = await apiGetDivisionOneFeature({ user: hasil, id, cat: 'today-task' })
|
||||
setData(response.data)
|
||||
@@ -40,7 +40,12 @@ export default function TaskDivisionDetail() {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
handleLoad()
|
||||
if (refreshing)
|
||||
handleLoad(false)
|
||||
}, [refreshing])
|
||||
|
||||
useEffect(() => {
|
||||
handleLoad(true)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
|
||||
@@ -11,7 +11,7 @@ import Carousel, { ICarouselInstance } from "react-native-reanimated-carousel";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import Text from "../Text";
|
||||
|
||||
export default function CaraouselHome() {
|
||||
export default function CaraouselHome({ refreshing }: { refreshing: boolean }) {
|
||||
const { decryptToken, token } = useAuthSession()
|
||||
const ref = React.useRef<ICarouselInstance>(null);
|
||||
const width = Dimensions.get("window").width;
|
||||
@@ -37,6 +37,11 @@ export default function CaraouselHome() {
|
||||
dispatch(setEntityUser({ role: response.data.idUserRole, admin: false }))
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (refreshing)
|
||||
handleBannerView()
|
||||
}, [refreshing]);
|
||||
|
||||
useEffect(() => {
|
||||
handleBannerView()
|
||||
}, [dispatch]);
|
||||
|
||||
@@ -13,7 +13,7 @@ type Props = {
|
||||
frontColor: string;
|
||||
}[]
|
||||
|
||||
export default function ChartDokumenHome() {
|
||||
export default function ChartDokumenHome({ refreshing }: { refreshing: boolean }) {
|
||||
const [loading, setLoading] = useState(true)
|
||||
const { decryptToken, token } = useAuthSession()
|
||||
const [data, setData] = useState<Props>([])
|
||||
@@ -25,9 +25,9 @@ export default function ChartDokumenHome() {
|
||||
const width = Dimensions.get("window").width;
|
||||
|
||||
|
||||
async function handleData() {
|
||||
async function handleData(loading: boolean) {
|
||||
try {
|
||||
setLoading(true)
|
||||
setLoading(loading)
|
||||
const hasil = await decryptToken(String(token?.current))
|
||||
const response = await apiGetDataHome({ cat: "dokumen", user: hasil })
|
||||
const maxValue = response.data.reduce((max: number, obj: { value: number; }) => Math.max(max, obj.value), -Infinity);
|
||||
@@ -47,7 +47,12 @@ export default function ChartDokumenHome() {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
handleData()
|
||||
if (refreshing)
|
||||
handleData(false)
|
||||
}, [refreshing]);
|
||||
|
||||
useEffect(() => {
|
||||
handleData(true)
|
||||
}, []);
|
||||
|
||||
return (
|
||||
|
||||
@@ -13,14 +13,14 @@ type Props = {
|
||||
color: string;
|
||||
}[]
|
||||
|
||||
export default function ChartProgresHome() {
|
||||
export default function ChartProgresHome({ refreshing }: { refreshing: boolean }) {
|
||||
const { decryptToken, token } = useAuthSession()
|
||||
const [data, setData] = useState<Props>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
async function handleData() {
|
||||
async function handleData(loading: boolean) {
|
||||
try {
|
||||
setLoading(true)
|
||||
setLoading(loading)
|
||||
const hasil = await decryptToken(String(token?.current))
|
||||
const response = await apiGetDataHome({ cat: "progress", user: hasil })
|
||||
const convertedArray = response.data.map((item: { color: any; text: any; value: any; }) => ({
|
||||
@@ -37,7 +37,12 @@ export default function ChartProgresHome() {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
handleData()
|
||||
if (refreshing)
|
||||
handleData(false)
|
||||
}, [refreshing]);
|
||||
|
||||
useEffect(() => {
|
||||
handleData(true)
|
||||
}, []);
|
||||
|
||||
return (
|
||||
|
||||
@@ -17,15 +17,15 @@ type Props = {
|
||||
user: string
|
||||
}
|
||||
|
||||
export default function DisccussionHome() {
|
||||
export default function DisccussionHome({ refreshing }: { refreshing: boolean }) {
|
||||
const { decryptToken, token } = useAuthSession()
|
||||
const [data, setData] = useState<Props[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
|
||||
async function handleData() {
|
||||
async function handleData(loading: boolean) {
|
||||
try {
|
||||
setLoading(true)
|
||||
setLoading(loading)
|
||||
const hasil = await decryptToken(String(token?.current))
|
||||
const response = await apiGetDataHome({ cat: "discussion", user: hasil })
|
||||
setData(response.data)
|
||||
@@ -37,7 +37,12 @@ export default function DisccussionHome() {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
handleData()
|
||||
if (refreshing)
|
||||
handleData(false)
|
||||
}, [refreshing]);
|
||||
|
||||
useEffect(() => {
|
||||
handleData(true)
|
||||
}, []);
|
||||
|
||||
return (
|
||||
|
||||
@@ -15,7 +15,7 @@ type Props = {
|
||||
jumlah: number
|
||||
}
|
||||
|
||||
export default function DivisionHome() {
|
||||
export default function DivisionHome({ refreshing }: { refreshing: boolean }) {
|
||||
const { decryptToken, token } = useAuthSession()
|
||||
const ref = React.useRef<ICarouselInstance>(null)
|
||||
const width = Dimensions.get("window").width
|
||||
@@ -23,9 +23,9 @@ export default function DivisionHome() {
|
||||
const [loading, setLoading] = useState(true)
|
||||
const arrSkeleton = Array.from({ length: 2 }, (_, index) => index)
|
||||
|
||||
async function handleData() {
|
||||
async function handleData(loading: boolean) {
|
||||
try {
|
||||
setLoading(true)
|
||||
setLoading(loading)
|
||||
const hasil = await decryptToken(String(token?.current))
|
||||
const response = await apiGetDataHome({ cat: "division", user: hasil })
|
||||
setData(response.data)
|
||||
@@ -37,14 +37,19 @@ export default function DivisionHome() {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
handleData()
|
||||
if (refreshing)
|
||||
handleData(false)
|
||||
}, [refreshing]);
|
||||
|
||||
useEffect(() => {
|
||||
handleData(true)
|
||||
}, []);
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<View style={[Styles.mb15]}>
|
||||
<Text style={[Styles.textDefaultSemiBold, Styles.mv10]}>Divisi Teraktif</Text>
|
||||
<Text style={[Styles.textDefaultSemiBold, Styles.mb10]}>Divisi Teraktif</Text>
|
||||
{
|
||||
loading ?
|
||||
arrSkeleton.map((item, index) => (
|
||||
|
||||
@@ -22,14 +22,14 @@ type Props = {
|
||||
user_name: string
|
||||
}
|
||||
|
||||
export default function EventHome() {
|
||||
export default function EventHome({ refreshing }: { refreshing: boolean }) {
|
||||
const { decryptToken, token } = useAuthSession()
|
||||
const [data, setData] = useState<Props[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
async function handleData() {
|
||||
async function handleData(loading: boolean) {
|
||||
try {
|
||||
setLoading(true)
|
||||
setLoading(loading)
|
||||
const hasil = await decryptToken(String(token?.current))
|
||||
const response = await apiGetDataHome({ cat: "event", user: hasil })
|
||||
setData(response.data)
|
||||
@@ -41,7 +41,12 @@ export default function EventHome() {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
handleData()
|
||||
if (refreshing)
|
||||
handleData(false)
|
||||
}, [refreshing]);
|
||||
|
||||
useEffect(() => {
|
||||
handleData(true)
|
||||
}, []);
|
||||
|
||||
return (
|
||||
|
||||
@@ -20,16 +20,16 @@ type Props = {
|
||||
createdAt: string
|
||||
}
|
||||
|
||||
export default function ProjectHome() {
|
||||
export default function ProjectHome({ refreshing }: { refreshing: boolean }) {
|
||||
const { decryptToken, token } = useAuthSession()
|
||||
const ref = React.useRef<ICarouselInstance>(null);
|
||||
const width = Dimensions.get("window").width;
|
||||
const [data, setData] = useState<Props[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
async function handleData() {
|
||||
async function handleData(loading: boolean) {
|
||||
try {
|
||||
setLoading(true)
|
||||
setLoading(loading)
|
||||
const hasil = await decryptToken(String(token?.current))
|
||||
const response = await apiGetDataHome({ cat: "kegiatan", user: hasil })
|
||||
setData(response.data)
|
||||
@@ -41,12 +41,17 @@ export default function ProjectHome() {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
handleData()
|
||||
if (refreshing)
|
||||
handleData(false)
|
||||
}, [refreshing]);
|
||||
|
||||
useEffect(() => {
|
||||
handleData(true)
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<View style={[Styles.mb15]}>
|
||||
<Text style={[Styles.textDefaultSemiBold, Styles.mv10]}>Kegiatan Terupdate</Text>
|
||||
<Text style={[Styles.textDefaultSemiBold, Styles.mb10]}>Kegiatan Terupdate</Text>
|
||||
{
|
||||
loading ? (<Skeleton width={100} height={150} borderRadius={10} widthType="percent" />)
|
||||
:
|
||||
|
||||
@@ -33,6 +33,7 @@ export default function ModalFilter({ open, close, page, category }: Props) {
|
||||
const { token, decryptToken } = useAuthSession()
|
||||
const dispatch = useDispatch()
|
||||
const entities = useSelector((state: any) => state.filterGroup)
|
||||
const update = useSelector((state: any) => state.groupUpdate)
|
||||
const [chooseGroup, setChooseGroup] = useState('')
|
||||
|
||||
async function handleLoad() {
|
||||
@@ -42,10 +43,8 @@ export default function ModalFilter({ open, close, page, category }: Props) {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (entities.length == 0) {
|
||||
handleLoad()
|
||||
}
|
||||
}, [dispatch]);
|
||||
}, [dispatch, update]);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ export default function ModalSelect({ open, close, title, category, idParent, on
|
||||
selectMember.length > 0
|
||||
?
|
||||
<View>
|
||||
<ScrollView horizontal style={[Styles.mb10, Styles.pv10]}>
|
||||
<ScrollView horizontal style={[Styles.mb10, Styles.pv10]} showsHorizontalScrollIndicator={false}>
|
||||
{
|
||||
selectMember.map((item: any, index: any) => (
|
||||
<ImageWithLabel
|
||||
@@ -154,7 +154,7 @@ export default function ModalSelect({ open, close, title, category, idParent, on
|
||||
}
|
||||
</>
|
||||
}
|
||||
<ScrollView>
|
||||
<ScrollView showsVerticalScrollIndicator={false}>
|
||||
<View>
|
||||
{
|
||||
category != 'status-task' ?
|
||||
|
||||
@@ -44,6 +44,9 @@ const Styles = StyleSheet.create({
|
||||
fontSize: 20,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
textSubtitle2: {
|
||||
fontSize: 20,
|
||||
},
|
||||
textLink: {
|
||||
fontSize: 14,
|
||||
color: '#0a7ea4',
|
||||
|
||||
4
eas.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"cli": {
|
||||
"version": ">= 16.10.0",
|
||||
"appVersionSource": "remote"
|
||||
"appVersionSource": "local"
|
||||
},
|
||||
"build": {
|
||||
"development": {
|
||||
@@ -53,4 +53,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,9 +15,9 @@
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "mobiledarmasaba.app"
|
||||
BlueprintName = "mobiledarmasaba"
|
||||
ReferencedContainer = "container:mobiledarmasaba.xcodeproj">
|
||||
BuildableName = "Desa.app"
|
||||
BlueprintName = "Desa"
|
||||
ReferencedContainer = "container:Desa.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
@@ -33,9 +33,9 @@
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "00E356ED1AD99517003FC87E"
|
||||
BuildableName = "mobiledarmasabaTests.xctest"
|
||||
BlueprintName = "mobiledarmasabaTests"
|
||||
ReferencedContainer = "container:mobiledarmasaba.xcodeproj">
|
||||
BuildableName = "DesaTests.xctest"
|
||||
BlueprintName = "DesaTests"
|
||||
ReferencedContainer = "container:Desa.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
@@ -55,9 +55,9 @@
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "mobiledarmasaba.app"
|
||||
BlueprintName = "mobiledarmasaba"
|
||||
ReferencedContainer = "container:mobiledarmasaba.xcodeproj">
|
||||
BuildableName = "Desa.app"
|
||||
BlueprintName = "Desa"
|
||||
ReferencedContainer = "container:Desa.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
@@ -72,9 +72,9 @@
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "mobiledarmasaba.app"
|
||||
BlueprintName = "mobiledarmasaba"
|
||||
ReferencedContainer = "container:mobiledarmasaba.xcodeproj">
|
||||
BuildableName = "Desa.app"
|
||||
BlueprintName = "Desa"
|
||||
ReferencedContainer = "container:Desa.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
@@ -2,7 +2,7 @@
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:mobiledarmasaba.xcodeproj">
|
||||
location = "group:Desa.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:Pods/Pods.xcodeproj">
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict/>
|
||||
</plist>
|
||||
<dict/>
|
||||
</plist>
|
||||
|
After Width: | Height: | Size: 38 KiB |
BIN
ios/Desa/Images.xcassets/SplashScreenLogo.imageset/image.png
vendored
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
ios/Desa/Images.xcassets/SplashScreenLogo.imageset/image@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 9.0 KiB |
BIN
ios/Desa/Images.xcassets/SplashScreenLogo.imageset/image@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 15 KiB |
@@ -7,7 +7,7 @@
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>mobile-darmasaba</string>
|
||||
<string>Desa+</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
@@ -19,7 +19,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0.0</string>
|
||||
<string>1.0.2</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
@@ -53,6 +53,14 @@
|
||||
<key>NSAllowsLocalNetworking</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Allow $(PRODUCT_NAME) to access your camera</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>Allow $(PRODUCT_NAME) to access your microphone</string>
|
||||
<key>NSPhotoLibraryAddUsageDescription</key>
|
||||
<string>Allow $(PRODUCT_NAME) to save photos</string>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string>Allow $(PRODUCT_NAME) to access your photos</string>
|
||||
<key>NSUserActivityTypes</key>
|
||||
<array>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route</string>
|
||||
@@ -13,7 +13,7 @@ install! 'cocoapods',
|
||||
|
||||
prepare_react_native_project!
|
||||
|
||||
target 'mobiledarmasaba' do
|
||||
target 'Desa' do
|
||||
use_expo_modules!
|
||||
|
||||
if ENV['EXPO_USE_COMMUNITY_AUTOLINKING'] == '1'
|
||||
@@ -27,12 +27,11 @@ target 'mobiledarmasaba' do
|
||||
'--platform',
|
||||
'ios'
|
||||
]
|
||||
|
||||
pod 'FirebaseDatabase', :modular_headers => true
|
||||
pod 'FirebaseCore', :modular_headers => true
|
||||
pod 'FirebaseAppCheckInterop', :modular_headers => true
|
||||
pod 'leveldb-library', :modular_headers => true
|
||||
pod 'GoogleUtilities', :modular_headers => true
|
||||
pod 'FirebaseAppCheckInterop', :modular_headers => true
|
||||
pod 'leveldb-library', :modular_headers => true
|
||||
pod 'GoogleUtilities', :modular_headers => true
|
||||
end
|
||||
|
||||
config = use_native_modules!(config_command)
|
||||
|
||||