Merge pull request 'amalia/24-sept-25' (#41) from amalia/24-sept-25 into join

Reviewed-on: bip/mobile-darmasaba#41
This commit is contained in:
2025-09-24 17:39:23 +08:00
12 changed files with 283 additions and 244 deletions

View File

@@ -210,10 +210,11 @@ export default function DetailDiscussionGeneral() {
disable={(data?.status === 2 || !data?.isActive || (!memberDiscussion && (entityUser.role == "user" || entityUser.role == "coadmin")))} disable={(data?.status === 2 || !data?.isActive || (!memberDiscussion && (entityUser.role == "user" || entityUser.role == "coadmin")))}
type="default" type="default"
round round
placeholder="Kirim Komentar" placeholder="Kirim Komentar2"
bg="white" bg="white"
onChange={setKomentar} onChange={setKomentar}
value={komentar} value={komentar}
multiline
itemRight={ itemRight={
<Pressable onPress={() => { <Pressable onPress={() => {
(komentar != '' && data?.status === 1 && data?.isActive && (memberDiscussion || (entityUser.role != "user" && entityUser.role != "coadmin"))) (komentar != '' && data?.status === 1 && data?.isActive && (memberDiscussion || (entityUser.role != "user" && entityUser.role != "coadmin")))

View File

@@ -304,6 +304,7 @@ export default function DiscussionDetail() {
bg="white" bg="white"
type="default" type="default"
round round
multiline
placeholder="Kirim Komentar" placeholder="Kirim Komentar"
onChange={setKomentar} onChange={setKomentar}
value={komentar} value={komentar}

View File

@@ -9,6 +9,7 @@ import { setFormCreateDivision } from "@/lib/divisionCreate";
import { setUpdateDivision } from "@/lib/divisionUpdate"; import { setUpdateDivision } from "@/lib/divisionUpdate";
import { useAuthSession } from "@/providers/AuthProvider"; import { useAuthSession } from "@/providers/AuthProvider";
import { AntDesign } from "@expo/vector-icons"; import { AntDesign } from "@expo/vector-icons";
import { StackActions, useNavigation } from "@react-navigation/native";
import { router, Stack, useLocalSearchParams } from "expo-router"; import { router, Stack, useLocalSearchParams } from "expo-router";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { Pressable, SafeAreaView, ScrollView, View } from "react-native"; import { Pressable, SafeAreaView, ScrollView, View } from "react-native";
@@ -23,6 +24,7 @@ type Props = {
export default function CreateDivisionAddAdmin() { export default function CreateDivisionAddAdmin() {
const { token, decryptToken } = useAuthSession() const { token, decryptToken } = useAuthSession()
const navigation = useNavigation()
const { id } = useLocalSearchParams<{ id: string }>() const { id } = useLocalSearchParams<{ id: string }>()
const [dataOld, setDataOld] = useState<Props[]>([]) const [dataOld, setDataOld] = useState<Props[]>([])
const [data, setData] = useState<Props[]>([]) const [data, setData] = useState<Props[]>([])
@@ -57,7 +59,8 @@ export default function CreateDivisionAddAdmin() {
Toast.show({ type: 'small', text1: 'Berhasil membuat divisi', }) Toast.show({ type: 'small', text1: 'Berhasil membuat divisi', })
dispatch(setFormCreateDivision({ admin: [], member: [], data: { idGroup: '', name: '', desc: '' } })) dispatch(setFormCreateDivision({ admin: [], member: [], data: { idGroup: '', name: '', desc: '' } }))
dispatch(setUpdateDivision(!updateDivision)) dispatch(setUpdateDivision(!updateDivision))
router.replace(`/division/`) navigation.dispatch(StackActions.pop(3))
// router.replace(`/division/`)
} else { } else {
Toast.show({ type: 'small', text1: response.message, }) Toast.show({ type: 'small', text1: response.message, })
} }

View File

@@ -10,11 +10,14 @@ import { apiEditProfile, apiGetProfile } from "@/lib/api";
import { setEntities } from "@/lib/entitiesSlice"; import { setEntities } from "@/lib/entitiesSlice";
import { useAuthSession } from "@/providers/AuthProvider"; import { useAuthSession } from "@/providers/AuthProvider";
import { MaterialCommunityIcons } from "@expo/vector-icons"; import { MaterialCommunityIcons } from "@expo/vector-icons";
import { useHeaderHeight } from "@react-navigation/elements";
import * as ImagePicker from "expo-image-picker"; import * as ImagePicker from "expo-image-picker";
import { router, Stack } from "expo-router"; import { router, Stack } from "expo-router";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { import {
Image, Image,
KeyboardAvoidingView,
Platform,
Pressable, Pressable,
SafeAreaView, SafeAreaView,
ScrollView, ScrollView,
@@ -37,6 +40,7 @@ type Props = {
}; };
export default function EditProfile() { export default function EditProfile() {
const headerHeight = useHeaderHeight()
const dispatch = useDispatch() const dispatch = useDispatch()
const entities = useSelector((state: any) => state.entities) const entities = useSelector((state: any) => state.entities)
const { token, decryptToken } = useAuthSession() const { token, decryptToken } = useAuthSession()
@@ -231,7 +235,12 @@ export default function EditProfile() {
), ),
}} }}
/> />
<ScrollView style={[Styles.h100]}> <KeyboardAvoidingView
style={[Styles.h100]}
behavior={Platform.OS === 'ios' ? 'padding' : undefined}
keyboardVerticalOffset={headerHeight}
>
<ScrollView showsVerticalScrollIndicator={false}>
<View style={[Styles.p15]}> <View style={[Styles.p15]}>
<View style={{ justifyContent: "center", alignItems: "center" }}> <View style={{ justifyContent: "center", alignItems: "center" }}>
{ {
@@ -341,6 +350,7 @@ export default function EditProfile() {
/> />
</View> </View>
</ScrollView> </ScrollView>
</KeyboardAvoidingView>
<ModalSelect <ModalSelect
category={valSelect} category={valSelect}

View File

@@ -193,16 +193,19 @@ export default function ListProject() {
</Pressable> </Pressable>
</View> </View>
<View style={[Styles.mv05]}> <View style={[Styles.mv05]}>
{
entityUser.role != 'cosupadmin' && entityUser.role != 'admin' &&
<Text>Filter : <Text>Filter :
{ {
(entityUser.role == "supadmin" || entityUser.role == "developer") && nameGroup (entityUser.role == "supadmin" || entityUser.role == "developer") && nameGroup
} }
{ {
(entityUser.role == 'user' || entityUser.role == 'coadmin' || entityUser.role == 'cosupadmin') (entityUser.role == 'user' || entityUser.role == 'coadmin')
? (cat == 'null' || cat == 'undefined' || cat == undefined || cat == '' || cat == 'data-saya') ? 'Kegiatan Saya' : 'Semua Kegiatan' ? (cat == 'null' || cat == 'undefined' || cat == undefined || cat == '' || cat == 'data-saya') ? 'Kegiatan Saya' : 'Semua Kegiatan'
: '' : ''
} }
</Text> </Text>
}
</View> </View>
</View> </View>
<View style={[{ flex: 2 }]}> <View style={[{ flex: 2 }]}>

View File

@@ -35,6 +35,7 @@ export default function DrawerBottom({ isVisible, setVisible, title, children, a
backdropTransitionInTiming={500} backdropTransitionInTiming={500}
backdropTransitionOutTiming={500} backdropTransitionOutTiming={500}
useNativeDriverForBackdrop={true} useNativeDriverForBackdrop={true}
propagateSwipe={true}
> >
{ {
keyboard ? keyboard ?
@@ -62,7 +63,7 @@ export default function DrawerBottom({ isVisible, setVisible, title, children, a
<MaterialIcons name="close" color="black" size={22} /> <MaterialIcons name="close" color="black" size={22} />
</Pressable> </Pressable>
</View> </View>
<View style={Styles.contentContainer}> <View style={[Styles.contentContainer, { flex: 1 }]}>
{children} {children}
</View> </View>
</View> </View>

View File

@@ -40,6 +40,7 @@ export function InputForm({ label, value, placeholder, onChange, info, disable,
<View style={[ <View style={[
Styles.inputRoundForm, Styles.inputRoundForm,
itemRight != undefined ? Styles.inputRoundFormRight : Styles.inputRoundFormLeft, itemRight != undefined ? Styles.inputRoundFormRight : Styles.inputRoundFormLeft,
multiline && { alignItems: 'flex-end' },
round && Styles.round30, round && Styles.round30,
{ backgroundColor: bg && bg == 'white' ? 'white' : 'transparent' }, { backgroundColor: bg && bg == 'white' ? 'white' : 'transparent' },
error && { borderColor: "red" }, error && { borderColor: "red" },
@@ -53,7 +54,17 @@ export function InputForm({ label, value, placeholder, onChange, info, disable,
keyboardType={type} keyboardType={type}
onChangeText={onChange} onChangeText={onChange}
placeholderTextColor={'gray'} placeholderTextColor={'gray'}
style={[Styles.mh05, { width: width ? lebar * width / 100 : lebar * 0.78, color: 'black' }, Platform.OS == 'ios' ? { paddingVertical: 1 } : { paddingVertical: 5 }]} multiline={multiline}
numberOfLines={3}
style={[
Styles.mh05,
multiline && { height: '100%', paddingTop: 3 },
{ width: width ? lebar * width / 100 : lebar * 0.78, color: 'black' },
Platform.OS == 'ios' ? { paddingVertical: 1 } : { paddingVertical: 5 },
multiline && {
maxHeight: 100, // batas maksimal
}
]}
/> />
</View> </View>
{error && (<Text style={[Styles.textInformation, Styles.cError, Styles.mt05]}>{errorText}</Text>)} {error && (<Text style={[Styles.textInformation, Styles.cError, Styles.mt05]}>{errorText}</Text>)}

View File

@@ -30,6 +30,8 @@ export default function HeaderRightProjectList() {
}} }}
/> />
} }
{
(entityUser.role == "user" || entityUser.role == "coadmin" || entityUser.role == "supadmin" || entityUser.role == "developer") &&
<MenuItemRow <MenuItemRow
icon={<AntDesign name="filter" color="black" size={25} />} icon={<AntDesign name="filter" color="black" size={25} />}
title="Filter" title="Filter"
@@ -40,6 +42,8 @@ export default function HeaderRightProjectList() {
}, 600) }, 600)
}} }}
/> />
}
</View> </View>
</DrawerBottom> </DrawerBottom>
<ModalFilter <ModalFilter

View File

@@ -394,7 +394,7 @@
); );
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
PRODUCT_BUNDLE_IDENTIFIER = mobiledarmasaba.app; PRODUCT_BUNDLE_IDENTIFIER = mobiledarmasaba.app;
PRODUCT_NAME = "Desa"; PRODUCT_NAME = Desa;
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Desa/Desa-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Desa/Desa-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -429,7 +429,7 @@
); );
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
PRODUCT_BUNDLE_IDENTIFIER = mobiledarmasaba.app; PRODUCT_BUNDLE_IDENTIFIER = mobiledarmasaba.app;
PRODUCT_NAME = "Desa"; PRODUCT_NAME = Desa;
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Desa/Desa-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Desa/Desa-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;

View File

@@ -1,5 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?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"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict/> <dict>
<key>aps-environment</key>
<string>development</string>
</dict>
</plist> </plist>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?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"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>CADisableMinimumFrameDurationOnPhone</key> <key>CADisableMinimumFrameDurationOnPhone</key>
<true/> <true/>
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
@@ -65,6 +65,10 @@
<array> <array>
<string>$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route</string> <string>$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route</string>
</array> </array>
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
</array>
<key>UILaunchStoryboardName</key> <key>UILaunchStoryboardName</key>
<string>SplashScreen</string> <string>SplashScreen</string>
<key>UIRequiredDeviceCapabilities</key> <key>UIRequiredDeviceCapabilities</key>
@@ -91,5 +95,5 @@
<string>Automatic</string> <string>Automatic</string>
<key>UIViewControllerBasedStatusBarAppearance</key> <key>UIViewControllerBasedStatusBarAppearance</key>
<false/> <false/>
</dict> </dict>
</plist> </plist>

View File

@@ -5,7 +5,6 @@ import AsyncStorage from '@react-native-async-storage/async-storage';
import CryptoES from "crypto-es"; import CryptoES from "crypto-es";
import { router } from "expo-router"; import { router } from "expo-router";
import { createContext, MutableRefObject, ReactNode, useCallback, useContext, useEffect, useRef, useState } from 'react'; import { createContext, MutableRefObject, ReactNode, useCallback, useContext, useEffect, useRef, useState } from 'react';
import { Platform } from 'react-native';
const AuthContext = createContext<{ const AuthContext = createContext<{
signIn: (arg0: string) => void; signIn: (arg0: string) => void;
@@ -57,13 +56,13 @@ export default function AuthProvider({ children }: { children: ReactNode }): Rea
const permission = await requestPermission() const permission = await requestPermission()
if (permission) { if (permission) {
try { try {
// COMING SOON // if (Platform.OS === 'android') {
if (Platform.OS === 'android') {
const tokenDevice = await getToken() const tokenDevice = await getToken()
const register = await apiRegisteredToken({ user: hasil, token: String(tokenDevice) }) const register = await apiRegisteredToken({ user: hasil, token: String(tokenDevice) })
}else{ // }else{
const register = await apiRegisteredToken({ user: hasil, token: "" }) // const tokenDevice = await getToken()
} // const register = await apiRegisteredToken({ user: hasil, token: String(tokenDevice) })
// }
} catch (error) { } catch (error) {
console.error(error) console.error(error)
} finally { } finally {
@@ -82,13 +81,12 @@ export default function AuthProvider({ children }: { children: ReactNode }): Rea
const signOut = useCallback(async () => { const signOut = useCallback(async () => {
try { try {
const hasil = await decryptToken(String(tokenRef.current)) const hasil = await decryptToken(String(tokenRef.current))
// COMING SOON // if (Platform.OS === 'android') {
if (Platform.OS === 'android') {
const token = await getToken() const token = await getToken()
const response = await apiUnregisteredToken({ user: hasil, token: String(token) }) const response = await apiUnregisteredToken({ user: hasil, token: String(token) })
}else{ // }else{
const response = await apiUnregisteredToken({ user: hasil, token: "" }) // const response = await apiUnregisteredToken({ user: hasil, token: "" })
} // }
} catch (error) { } catch (error) {
console.error(error) console.error(error)
} finally { } finally {