Compare commits

...

5 Commits

Author SHA1 Message Date
c230e0b18b upd: custom header
Deskripsi:
- update custom button header

- yg blm : fitur divisi dan yg ada di divisi

No Issues
2026-01-27 17:39:54 +08:00
013589b9f7 upd: modal img
Deskripsi:
- view foto profile
- view foto detail member
- view image banner

No Issues
2026-01-23 17:18:08 +08:00
b99476a593 upd: tampilan detail pengumuman
Deskripisi :
- align item pada judul pengumuman

NO Issues
2026-01-23 14:13:07 +08:00
e1b2cd3790 fix input nomer
Deskripsi:
- pada ios item left input terlalu keatas

No Issues
2026-01-23 12:13:42 +08:00
03d0836111 Merge pull request 'amalia/19-jan-26' (#9) from amalia/19-jan-26 into join
Reviewed-on: http://wibugit.wibudev.com/wibu/mobile-darmasaba/pulls/9
2026-01-19 17:27:16 +08:00
39 changed files with 851 additions and 343 deletions

View File

@@ -1,5 +1,5 @@
import HeaderRightAnnouncementList from "@/components/announcement/headerAnnouncementList";
import ButtonBackHeader from "@/components/buttonBackHeader";
import AppHeader from "@/components/AppHeader";
import HeaderDiscussionGeneral from "@/components/discussion_general/headerDiscussionGeneral";
import HeaderRightDivisionList from "@/components/division/headerDivisionList";
import HeaderRightGroupList from "@/components/group/headerGroupList";
@@ -97,54 +97,100 @@ export default function RootLayout() {
<Stack.Screen name="search" options={{ title: 'Pencarian' }} />
<Stack.Screen name="notification" options={{
title: 'Notifikasi',
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
// headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
headerTitle: 'Notifikasi',
headerTitleAlign: 'center'
headerTitleAlign: 'center',
header: () => (
<AppHeader title="Notifikasi" showBack={true} onPressLeft={() => router.back()} />
)
}} />
<Stack.Screen name="profile" options={{ title: 'Profile' }} />
<Stack.Screen name="member/index" options={{
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
// headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
title: 'Anggota',
headerTitleAlign: 'center',
headerRight: () => <HeaderMemberList />
// headerRight: () => <HeaderMemberList />
header: () => (
<AppHeader title="Anggota"
showBack={true}
onPressLeft={() => router.back()}
right={<HeaderMemberList />}
/>
)
}} />
<Stack.Screen name="discussion/index" options={{
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
// headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
title: 'Diskusi Umum',
headerTitleAlign: 'center',
headerRight: () => <HeaderDiscussionGeneral />
// headerRight: () => <HeaderDiscussionGeneral />
header: () => (
<AppHeader
title="Diskusi Umum"
showBack={true}
onPressLeft={() => router.back()}
right={<HeaderDiscussionGeneral />}
/>
)
}} />
<Stack.Screen name="project/index" options={{
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
// headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
title: 'Kegiatan',
headerTitleAlign: 'center',
headerRight: () => <HeaderRightProjectList />
// headerRight: () => <HeaderRightProjectList />
header: () => (
<AppHeader title="Kegiatan"
showBack={true}
onPressLeft={() => router.back()}
right={<HeaderRightProjectList />}
/>
)
}} />
<Stack.Screen name="division/index" options={{
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
// headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
title: 'Divisi',
headerTitleAlign: 'center',
headerRight: () => <HeaderRightDivisionList />
}} />
<Stack.Screen name="division/[id]/(fitur-division)" options={{ headerShown: false }} />
<Stack.Screen name="group/index" options={{
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
// headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
headerTitle: 'Lembaga Desa',
headerTitleAlign: 'center',
headerRight: () => <HeaderRightGroupList />
// headerRight: () => <HeaderRightGroupList />
header: () => (
<AppHeader title="Lembaga Desa"
showBack={true}
onPressLeft={() => router.back()}
right={<HeaderRightGroupList />}
/>
)
}} />
<Stack.Screen name="position/index" options={{
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
// headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
headerTitle: 'Jabatan',
headerTitleAlign: 'center',
headerRight: () => <HeaderRightPositionList />
// headerRight: () => <HeaderRightPositionList />
header: () => (
<AppHeader title="Jabatan"
showBack={true}
onPressLeft={() => router.back()}
right={<HeaderRightPositionList />}
/>
)
}} />
<Stack.Screen name="announcement/index"
options={{
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
// headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
headerTitle: 'Pengumuman',
headerTitleAlign: 'center',
headerRight: () => <HeaderRightAnnouncementList />
// headerRight: () => <HeaderRightAnnouncementList />
header: () => (
<AppHeader title="Pengumuman"
showBack={true}
onPressLeft={() => router.back()}
right={<HeaderRightAnnouncementList />}
/>
)
}}
/>
</Stack>

View File

@@ -1,4 +1,5 @@
import HeaderRightAnnouncementDetail from "@/components/announcement/headerAnnouncementDetail";
import AppHeader from "@/components/AppHeader";
import BorderBottomItem from "@/components/borderBottomItem";
import ButtonBackHeader from "@/components/buttonBackHeader";
import Skeleton from "@/components/skeleton";
@@ -30,7 +31,7 @@ export default function DetailAnnouncement() {
const { token, decryptToken } = useAuthSession()
const [data, setData] = useState<Props>({ id: '', title: '', desc: '' })
const [dataMember, setDataMember] = useState<any>({})
const [dataFile, setDataFile] = useState<{ id:string; idStorage: string; name: string; extension: string }[]>([])
const [dataFile, setDataFile] = useState<{ id: string; idStorage: string; name: string; extension: string }[]>([])
const update = useSelector((state: any) => state.announcementUpdate)
const entityUser = useSelector((state: any) => state.user)
const contentWidth = Dimensions.get('window').width
@@ -115,10 +116,17 @@ export default function DetailAnnouncement() {
<SafeAreaView>
<Stack.Screen
options={{
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
// headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
headerTitle: 'Pengumuman',
headerTitleAlign: 'center',
headerRight: () => entityUser.role != 'user' && entityUser.role != 'coadmin' ? <HeaderRightAnnouncementDetail id={id} /> : <></>,
// headerRight: () => entityUser.role != 'user' && entityUser.role != 'coadmin' ? <HeaderRightAnnouncementDetail id={id} /> : <></>,
header: () => (
<AppHeader title="Pengumuman"
showBack={true}
onPressLeft={() => router.back()}
right={entityUser.role != 'user' && entityUser.role != 'coadmin' ? <HeaderRightAnnouncementDetail id={id} /> : <></>}
/>
)
}}
/>
<ScrollView
@@ -149,8 +157,8 @@ export default function DetailAnnouncement() {
:
<>
<View style={[Styles.rowItemsCenter, { alignItems: 'flex-start' }]}>
<MaterialIcons name="campaign" size={30} color="black" style={Styles.mr05} />
<Text style={[Styles.textDefaultSemiBold, Styles.w90]}>{data?.title}</Text>
<MaterialIcons name="campaign" size={25} color="black" style={[Styles.mr05]} />
<Text style={[Styles.textDefaultSemiBold, Styles.w90, Styles.mt02]}>{data?.title}</Text>
</View>
<View style={[Styles.mt10]}>
{

View File

@@ -1,5 +1,5 @@
import AppHeader from "@/components/AppHeader";
import BorderBottomItem from "@/components/borderBottomItem";
import ButtonBackHeader from "@/components/buttonBackHeader";
import ButtonSaveHeader from "@/components/buttonSaveHeader";
import ButtonSelect from "@/components/buttonSelect";
import DrawerBottom from "@/components/drawerBottom";
@@ -15,7 +15,7 @@ import { useAuthSession } from "@/providers/AuthProvider";
import { Entypo, Ionicons, MaterialCommunityIcons } from "@expo/vector-icons";
import * as DocumentPicker from "expo-document-picker";
import { router, Stack } from "expo-router";
import { useEffect, useState } from "react";
import React, { useEffect, useState } from "react";
import { SafeAreaView, ScrollView, StyleSheet, View } from "react-native";
import Toast from "react-native-toast-message";
import { useDispatch, useSelector } from "react-redux";
@@ -132,26 +132,44 @@ export default function CreateAnnouncement() {
<SafeAreaView>
<Stack.Screen
options={{
headerLeft: () => (
<ButtonBackHeader
onPress={() => {
router.back();
}}
/>
),
// headerLeft: () => (
// <ButtonBackHeader
// onPress={() => {
// router.back();
// }}
// />
// ),
headerTitle: "Tambah Pengumuman",
headerTitleAlign: "center",
headerRight: () => (
<ButtonSaveHeader
disable={disableBtn || divisionMember.length == 0 || loading ? true : false}
category="create"
onPress={() => {
divisionMember.length == 0
? Toast.show({ type: 'small', text1: "Anda belum memilih divisi", })
: handleCreate();
}}
// headerRight: () => (
// <ButtonSaveHeader
// disable={disableBtn || divisionMember.length == 0 || loading ? true : false}
// category="create"
// onPress={() => {
// divisionMember.length == 0
// ? Toast.show({ type: 'small', text1: "Anda belum memilih divisi", })
// : handleCreate();
// }}
// />
// ),
header: () => (
<AppHeader
title="Tambah Pengumuman"
showBack={true}
onPressLeft={() => router.back()}
right={
<ButtonSaveHeader
disable={disableBtn || divisionMember.length == 0 || loading ? true : false}
category="create"
onPress={() => {
divisionMember.length == 0
? Toast.show({ type: 'small', text1: "Anda belum memilih divisi", })
: handleCreate();
}}
/>
}
/>
),
)
}}
/>
<LoadingOverlay visible={loading} />

View File

@@ -1,5 +1,5 @@
import AppHeader from "@/components/AppHeader";
import BorderBottomItem from "@/components/borderBottomItem";
import ButtonBackHeader from "@/components/buttonBackHeader";
import ButtonSaveHeader from "@/components/buttonSaveHeader";
import ButtonSelect from "@/components/buttonSelect";
import DrawerBottom from "@/components/drawerBottom";
@@ -183,26 +183,44 @@ export default function EditAnnouncement() {
<SafeAreaView>
<Stack.Screen
options={{
headerLeft: () => (
<ButtonBackHeader
onPress={() => {
router.back();
}}
/>
),
// headerLeft: () => (
// <ButtonBackHeader
// onPress={() => {
// router.back();
// }}
// />
// ),
headerTitle: "Edit Pengumuman",
headerTitleAlign: "center",
headerRight: () => (
<ButtonSaveHeader
disable={disableBtn || loading ? true : false}
category="update"
onPress={() => {
dataMember.length == 0
? Toast.show({ type: 'small', text1: "Anda belum memilih divisi", })
: handleEdit();
}}
// headerRight: () => (
// <ButtonSaveHeader
// disable={disableBtn || loading ? true : false}
// category="update"
// onPress={() => {
// dataMember.length == 0
// ? Toast.show({ type: 'small', text1: "Anda belum memilih divisi", })
// : handleEdit();
// }}
// />
// ),
header: () => (
<AppHeader
title="Edit Pengumuman"
showBack={true}
onPressLeft={() => router.back()}
right={
<ButtonSaveHeader
disable={disableBtn || loading ? true : false}
category="update"
onPress={() => {
dataMember.length == 0
? Toast.show({ type: 'small', text1: "Anda belum memilih divisi", })
: handleEdit();
}}
/>
}
/>
),
)
}}
/>
<LoadingOverlay visible={loading} />

View File

@@ -1,4 +1,4 @@
import ButtonBackHeader from "@/components/buttonBackHeader";
import AppHeader from "@/components/AppHeader";
import ButtonSaveHeader from "@/components/buttonSaveHeader";
import { InputForm } from "@/components/inputForm";
import Text from "@/components/Text";
@@ -115,19 +115,32 @@ export default function EditBanner() {
<SafeAreaView>
<Stack.Screen
options={{
headerLeft: () => (
<ButtonBackHeader
onPress={() => {
router.back();
}}
/>
),
// headerLeft: () => (
// <ButtonBackHeader
// onPress={() => {
// router.back();
// }}
// />
// ),
headerTitle: "Edit Banner",
headerTitleAlign: "center",
headerRight: () => <ButtonSaveHeader
disable={title == "" || error || loading ? true : false}
onPress={() => { handleUpdateEntity() }}
category="update" />,
// headerRight: () => <ButtonSaveHeader
// disable={title == "" || error || loading ? true : false}
// onPress={() => { handleUpdateEntity() }}
// category="update" />,
header: () => (
<AppHeader
title="Edit Banner"
showBack={true}
onPressLeft={() => router.back()}
right={
<ButtonSaveHeader
disable={title == "" || error || loading ? true : false}
onPress={() => { handleUpdateEntity() }}
category="update" />
}
/>
)
}}
/>
<ScrollView showsVerticalScrollIndicator={false} style={[Styles.h100]}>

View File

@@ -1,4 +1,4 @@
import ButtonBackHeader from "@/components/buttonBackHeader";
import AppHeader from "@/components/AppHeader";
import ButtonSaveHeader from "@/components/buttonSaveHeader";
import { InputForm } from "@/components/inputForm";
import Text from "@/components/Text";
@@ -97,24 +97,40 @@ export default function CreateBanner() {
<SafeAreaView>
<Stack.Screen
options={{
headerLeft: () => (
<ButtonBackHeader
onPress={() => {
router.back();
}}
/>
),
// headerLeft: () => (
// <ButtonBackHeader
// onPress={() => {
// router.back();
// }}
// />
// ),
headerTitle: "Tambah Banner",
headerTitleAlign: "center",
headerRight: () => (
<ButtonSaveHeader
disable={title == "" || selectedImage == undefined || error || loading ? true : false}
category="create"
onPress={() => {
handleCreateEntity();
}}
// headerRight: () => (
// <ButtonSaveHeader
// disable={title == "" || selectedImage == undefined || error || loading ? true : false}
// category="create"
// onPress={() => {
// handleCreateEntity();
// }}
// />
// ),
header: () => (
<AppHeader
title="Fitur"
showBack={true}
onPressLeft={() => router.back()}
right={
<ButtonSaveHeader
disable={title == "" || selectedImage == undefined || error || loading ? true : false}
category="create"
onPress={() => {
handleCreateEntity();
}}
/>
}
/>
),
)
}}
/>
<ScrollView showsVerticalScrollIndicator={false} style={[Styles.h100]}>

View File

@@ -1,7 +1,7 @@
import AlertKonfirmasi from "@/components/alertKonfirmasi"
import AppHeader from "@/components/AppHeader"
import HeaderRightBannerList from "@/components/banner/headerBannerList"
import BorderBottomItem from "@/components/borderBottomItem"
import ButtonBackHeader from "@/components/buttonBackHeader"
import DrawerBottom from "@/components/drawerBottom"
import MenuItemRow from "@/components/menuItemRow"
import ModalLoading from "@/components/modalLoading"
@@ -18,6 +18,7 @@ import { router, Stack } from "expo-router"
import * as Sharing from 'expo-sharing'
import { useState } from "react"
import { Alert, Image, Platform, RefreshControl, SafeAreaView, ScrollView, View } from "react-native"
import ImageViewing from 'react-native-image-viewing'
import * as mime from 'react-native-mime-types'
import Toast from "react-native-toast-message"
import { useDispatch, useSelector } from "react-redux"
@@ -38,12 +39,13 @@ export default function BannerList() {
const dispatch = useDispatch()
const [refreshing, setRefreshing] = useState(false)
const [loadingOpen, setLoadingOpen] = useState(false)
const [viewImg, setViewImg] = useState(false)
const handleDeleteEntity = async () => {
try {
const hasil = await decryptToken(String(token?.current));
const deletedEntity = await apiDeleteBanner({ user: hasil }, dataId);
if (deletedEntity.success ) {
if (deletedEntity.success) {
Toast.show({ type: 'small', text1: 'Berhasil menghapus data', })
apiGetBanner({ user: hasil }).then((data) =>
dispatch(setEntities(data.data))
@@ -106,10 +108,20 @@ export default function BannerList() {
<SafeAreaView>
<Stack.Screen
options={{
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
// headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
headerTitle: 'Banner',
headerTitleAlign: 'center',
headerRight: () => <HeaderRightBannerList />
// headerRight: () => <HeaderRightBannerList />
header: () => (
<AppHeader
title="Banner"
showBack={true}
onPressLeft={() => router.back()}
right={
<HeaderRightBannerList />
}
/>
)
}}
/>
<ModalLoading isVisible={loadingOpen} setVisible={setLoadingOpen} />
@@ -167,8 +179,14 @@ export default function BannerList() {
/>
<MenuItemRow
icon={<MaterialCommunityIcons name="file-eye" color="black" size={25} />}
title="Lihat / Share"
onPress={() => { openFile() }}
title="Lihat"
onPress={() => {
setModal(false)
setTimeout(() => {
setViewImg(true);
}, 1000);
// openFile()
}}
/>
<MenuItemRow
icon={<Ionicons name="trash" color="black" size={25} />}
@@ -184,6 +202,14 @@ export default function BannerList() {
/>
</View>
</DrawerBottom>
<ImageViewing
images={[{ uri: `${ConstEnv.url_storage}/files/${selectFile?.image}` }]}
imageIndex={0}
visible={viewImg}
onRequestClose={() => setViewImg(false)}
doubleTapToZoomEnabled
/>
</SafeAreaView>
)
}

View File

@@ -1,7 +1,7 @@
import AlertKonfirmasi from "@/components/alertKonfirmasi";
import AppHeader from "@/components/AppHeader";
import BorderBottomItem from "@/components/borderBottomItem";
import BorderBottomItem2 from "@/components/borderBottomItem2";
import ButtonBackHeader from "@/components/buttonBackHeader";
import HeaderRightDiscussionGeneralDetail from "@/components/discussion_general/headerDiscussionDetail";
import DrawerBottom from "@/components/drawerBottom";
import ImageUser from "@/components/imageNew";
@@ -22,7 +22,7 @@ import { Feather, Ionicons, MaterialCommunityIcons, MaterialIcons } from "@expo/
import { ref } from '@react-native-firebase/database';
import { useHeaderHeight } from '@react-navigation/elements';
import { router, Stack, useLocalSearchParams } from "expo-router";
import { useEffect, useState } from "react";
import React, { useEffect, useState } from "react";
import { KeyboardAvoidingView, Platform, Pressable, RefreshControl, ScrollView, View } from "react-native";
import Toast from "react-native-toast-message";
import { useSelector } from "react-redux";
@@ -225,10 +225,18 @@ export default function DetailDiscussionGeneral() {
<>
<Stack.Screen
options={{
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
// headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
headerTitle: 'Diskusi',
headerTitleAlign: 'center',
headerRight: () => <HeaderRightDiscussionGeneralDetail id={id} active={data?.isActive !== undefined ? data.isActive : false} status={data?.status !== undefined ? data.status : 0} />,
// headerRight: () => <HeaderRightDiscussionGeneralDetail id={id} active={data?.isActive !== undefined ? data.isActive : false} status={data?.status !== undefined ? data.status : 0} />,
header: () => (
<AppHeader
title="Diskusi"
showBack={true}
onPressLeft={() => router.back()}
right={<HeaderRightDiscussionGeneralDetail id={id} active={data?.isActive !== undefined ? data.isActive : false} status={data?.status !== undefined ? data.status : 0} />}
/>
)
}}
/>
<View style={{ flex: 1 }}>

View File

@@ -1,4 +1,4 @@
import ButtonBackHeader from "@/components/buttonBackHeader";
import AppHeader from "@/components/AppHeader";
import ButtonSaveHeader from "@/components/buttonSaveHeader";
import ImageUser from "@/components/imageNew";
import ImageWithLabel from "@/components/imageWithLabel";
@@ -95,16 +95,32 @@ export default function AddMemberDiscussionDetail() {
<SafeAreaView>
<Stack.Screen
options={{
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
// headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
headerTitle: 'Tambah Anggota Diskusi',
headerTitleAlign: 'center',
headerRight: () => (
<ButtonSaveHeader
category="update"
disable={selectMember.length == 0 || loading ? true : false}
onPress={() => {
handleAddMember()
}}
// headerRight: () => (
// <ButtonSaveHeader
// category="update"
// disable={selectMember.length == 0 || loading ? true : false}
// onPress={() => {
// handleAddMember()
// }}
// />
// )
header: () => (
<AppHeader
title="Tambah Anggota Diskusi"
showBack={true}
onPressLeft={() => router.back()}
right={
<ButtonSaveHeader
category="update"
disable={selectMember.length == 0 || loading ? true : false}
onPress={() => {
handleAddMember()
}}
/>
}
/>
)
}}

View File

@@ -1,5 +1,5 @@
import AppHeader from "@/components/AppHeader";
import BorderBottomItem from "@/components/borderBottomItem";
import ButtonBackHeader from "@/components/buttonBackHeader";
import ButtonSaveHeader from "@/components/buttonSaveHeader";
import ButtonSelect from "@/components/buttonSelect";
import DrawerBottom from "@/components/drawerBottom";
@@ -166,24 +166,42 @@ export default function CreateDiscussionGeneral() {
<SafeAreaView>
<Stack.Screen
options={{
headerLeft: () => (
<ButtonBackHeader
onPress={() => { handleBack() }}
/>
),
// headerLeft: () => (
// <ButtonBackHeader
// onPress={() => { handleBack() }}
// />
// ),
headerTitle: "Tambah Diskusi",
headerTitleAlign: "center",
headerRight: () => (
<ButtonSaveHeader
category="create"
disable={disableBtn || loading ? true : false}
onPress={() => {
entitiesMember.length == 0
? Toast.show({ type: 'small', text1: 'Anda belum memilih anggota', })
: handleCreate()
}}
// headerRight: () => (
// <ButtonSaveHeader
// category="create"
// disable={disableBtn || loading ? true : false}
// onPress={() => {
// entitiesMember.length == 0
// ? Toast.show({ type: 'small', text1: 'Anda belum memilih anggota', })
// : handleCreate()
// }}
// />
// ),
header: () => (
<AppHeader
title="Tambah Diskusi"
showBack={true}
onPressLeft={() => router.back()}
right={
<ButtonSaveHeader
category="create"
disable={disableBtn || loading ? true : false}
onPress={() => {
entitiesMember.length == 0
? Toast.show({ type: 'small', text1: 'Anda belum memilih anggota', })
: handleCreate()
}}
/>
}
/>
),
)
}}
/>
<LoadingOverlay visible={loading} />

View File

@@ -1,6 +1,6 @@
import AppHeader from "@/components/AppHeader";
import Text from "@/components/Text";
import BorderBottomItem from "@/components/borderBottomItem";
import ButtonBackHeader from "@/components/buttonBackHeader";
import ButtonSaveHeader from "@/components/buttonSaveHeader";
import ButtonSelect from "@/components/buttonSelect";
import DrawerBottom from "@/components/drawerBottom";
@@ -165,22 +165,36 @@ export default function EditDiscussionGeneral() {
<SafeAreaView>
<Stack.Screen
options={{
headerLeft: () => (
<ButtonBackHeader
onPress={() => {
router.back();
}}
/>
),
// headerLeft: () => (
// <ButtonBackHeader
// onPress={() => {
// router.back();
// }}
// />
// ),
headerTitle: "Edit Diskusi",
headerTitleAlign: "center",
headerRight: () => (
<ButtonSaveHeader
disable={disableBtn || loading ? true : false}
category="update"
onPress={() => { handleEdit() }}
// headerRight: () => (
// <ButtonSaveHeader
// disable={disableBtn || loading ? true : false}
// category="update"
// onPress={() => { handleEdit() }}
// />
// ),
header: () => (
<AppHeader
title="Edit Diskusi"
showBack={true}
onPressLeft={() => router.back()}
right={
<ButtonSaveHeader
disable={disableBtn || loading ? true : false}
category="update"
onPress={() => { handleEdit() }}
/>
}
/>
),
)
}}
/>
<LoadingOverlay visible={loading} />

View File

@@ -1,6 +1,6 @@
import AlertKonfirmasi from "@/components/alertKonfirmasi";
import AppHeader from "@/components/AppHeader";
import BorderBottomItem from "@/components/borderBottomItem";
import ButtonBackHeader from "@/components/buttonBackHeader";
import DrawerBottom from "@/components/drawerBottom";
import ImageUser from "@/components/imageNew";
import MenuItemRow from "@/components/menuItemRow";
@@ -74,9 +74,16 @@ export default function MemberDiscussionDetail() {
<SafeAreaView>
<Stack.Screen
options={{
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
// headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
headerTitle: 'Anggota Diskusi',
headerTitleAlign: 'center',
header: () => (
<AppHeader
title="Anggota Diskusi"
showBack={true}
onPressLeft={() => router.back()}
/>
)
}}
/>
<ScrollView>

View File

@@ -328,7 +328,7 @@ export default function EditProfile() {
type="numeric"
placeholder="8XX-XXX-XXX"
required
itemLeft={<Text>+62</Text>}
itemLeft={<Text style={[Platform.OS === 'ios' && Styles.mt02]}>+62</Text>}
value={data?.phone}
error={error.phone}
errorText="Nomor Telepon tidak valid"

View File

@@ -1,4 +1,4 @@
import ButtonBackHeader from "@/components/buttonBackHeader";
import AppHeader from "@/components/AppHeader";
import { ButtonFiturMenu } from "@/components/buttonFiturMenu";
import Styles from "@/constants/Styles";
import { AntDesign, Entypo, Ionicons, MaterialCommunityIcons, MaterialIcons } from "@expo/vector-icons";
@@ -13,9 +13,11 @@ export default function Feature() {
<SafeAreaView>
<Stack.Screen
options={{
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
headerTitle: 'Fitur',
headerTitleAlign: 'center'
headerTitleAlign: 'center',
header: () => (
<AppHeader title="Fitur" showBack={true} onPressLeft={() => router.back()} />
)
}}
/>
<View style={[Styles.p15]}>

View File

@@ -1,17 +1,19 @@
import ButtonBackHeader from "@/components/buttonBackHeader";
import AppHeader from "@/components/AppHeader";
import ImageUser from "@/components/imageNew";
import ItemDetailMember from "@/components/itemDetailMember";
import LabelStatus from "@/components/labelStatus";
import HeaderRightMemberDetail from "@/components/member/headerMemberDetail";
import Skeleton from "@/components/skeleton";
import Text from "@/components/Text";
import { assetUserImage } from "@/constants/AssetsError";
import { ConstEnv } from "@/constants/ConstEnv";
import { valueRoleUser } from "@/constants/RoleUser";
import Styles from "@/constants/Styles";
import { apiGetProfile } from "@/lib/api";
import { router, Stack, useLocalSearchParams } from "expo-router";
import { useEffect, useState } from "react";
import { RefreshControl, SafeAreaView, ScrollView, View } from "react-native";
import React, { useEffect, useState } from "react";
import { Pressable, RefreshControl, SafeAreaView, ScrollView, View } from "react-native";
import ImageViewing from 'react-native-image-viewing';
import Toast from "react-native-toast-message";
import { useSelector } from "react-redux";
@@ -32,12 +34,13 @@ type Props = {
export default function MemberDetail() {
const { id } = useLocalSearchParams<{ id: string }>();
const [data, setData] = useState<Props>()
const [error, setError] = useState(false)
const [errorImg, setErrorImg] = useState(false)
const entityUser = useSelector((state: any) => state.user)
const [isEdit, setEdit] = useState(true)
const arrSkeleton = Array.from({ length: 5 }, (_, index) => index)
const [loading, setLoading] = useState(true)
const [refreshing, setRefreshing] = useState(false)
const [preview, setPreview] = useState(false)
async function handleLoad(loading: boolean) {
try {
@@ -74,11 +77,19 @@ export default function MemberDetail() {
<SafeAreaView>
<Stack.Screen
options={{
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
// headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
headerTitle: 'Anggota',
headerTitleAlign: 'center',
headerRight: () => (entityUser.role != "user") && isEdit ? <HeaderRightMemberDetail active={data?.isActive} id={id} /> : <></>,
headerShadowVisible: false
// headerRight: () => (entityUser.role != "user") && isEdit ? <HeaderRightMemberDetail active={data?.isActive} id={id} /> : <></>,
header: () => (
<AppHeader title="Anggota"
showBack={true}
onPressLeft={() => router.back()}
right={
(entityUser.role != "user") && isEdit ? <HeaderRightMemberDetail active={data?.isActive} id={id} /> : <></>
}
/>
)
}}
/>
<ScrollView
@@ -100,7 +111,9 @@ export default function MemberDetail() {
</>
:
<>
<ImageUser src={`${ConstEnv.url_storage}/files/${data?.img}`} size="lg" />
<Pressable onPress={() => setPreview(true)}>
<ImageUser src={`${ConstEnv.url_storage}/files/${data?.img}`} size="lg" onError={setErrorImg} />
</Pressable>
<Text style={[Styles.textSubtitle, Styles.cWhite, Styles.mt10, { textAlign: 'center' }]}>{data?.name}</Text>
<Text style={[Styles.textMediumNormal, Styles.cWhite]}>{data?.role}</Text>
</>
@@ -136,6 +149,14 @@ export default function MemberDetail() {
</View>
</ScrollView>
<ImageViewing
images={[{ uri: errorImg ? assetUserImage.uri : `${ConstEnv.url_storage}/files/${data?.img}` }]}
imageIndex={0}
visible={preview}
onRequestClose={() => setPreview(false)}
doubleTapToZoomEnabled
/>
</SafeAreaView>
)
}

View File

@@ -1,4 +1,4 @@
import ButtonBackHeader from "@/components/buttonBackHeader";
import AppHeader from "@/components/AppHeader";
import ButtonSaveHeader from "@/components/buttonSaveHeader";
import { InputForm } from "@/components/inputForm";
import ModalSelect from "@/components/modalSelect";
@@ -209,22 +209,35 @@ export default function CreateMember() {
<SafeAreaView>
<Stack.Screen
options={{
headerLeft: () => (
<ButtonBackHeader
onPress={() => {
router.back();
}}
/>
),
// headerLeft: () => (
// <ButtonBackHeader
// onPress={() => {
// router.back();
// }}
// />
// ),
headerTitle: "Tambah Anggota",
headerTitleAlign: "center",
headerRight: () => (
<ButtonSaveHeader
disable={disableBtn || loading}
category="create"
onPress={() => { handleCreate() }}
// headerRight: () => (
// <ButtonSaveHeader
// disable={disableBtn || loading}
// category="create"
// onPress={() => { handleCreate() }}
// />
// ),
header: () => (
<AppHeader title="Anggota"
showBack={true}
onPressLeft={() => router.back()}
right={
<ButtonSaveHeader
disable={disableBtn || loading}
category="create"
onPress={() => { handleCreate() }}
/>
}
/>
),
)
}}
/>
<KeyboardAvoidingView
@@ -331,7 +344,7 @@ export default function CreateMember() {
type="numeric"
placeholder="8XX-XXX-XXX"
required
itemLeft={<Text>+62</Text>}
itemLeft={<Text style={[Platform.OS === 'ios' && Styles.mt02]}>+62</Text>}
error={error.phone}
errorText="Nomor Telepon tidak valid"
onChange={val => {

View File

@@ -1,4 +1,4 @@
import ButtonBackHeader from "@/components/buttonBackHeader";
import AppHeader from "@/components/AppHeader";
import ButtonSaveHeader from "@/components/buttonSaveHeader";
import { InputForm } from "@/components/inputForm";
import ModalSelect from "@/components/modalSelect";
@@ -239,24 +239,40 @@ export default function EditMember() {
<SafeAreaView>
<Stack.Screen
options={{
headerLeft: () => (
<ButtonBackHeader
onPress={() => {
router.back();
}}
/>
),
// headerLeft: () => (
// <ButtonBackHeader
// onPress={() => {
// router.back();
// }}
// />
// ),
headerTitle: "Edit Anggota",
headerTitleAlign: "center",
headerRight: () => (
<ButtonSaveHeader
disable={disableBtn || loading}
category="update"
onPress={() => {
handleEdit()
}}
// headerRight: () => (
// <ButtonSaveHeader
// disable={disableBtn || loading}
// category="update"
// onPress={() => {
// handleEdit()
// }}
// />
// ),
header: () => (
<AppHeader
title="Edit Anggota"
showBack={true}
onPressLeft={() => router.back()}
right={
<ButtonSaveHeader
disable={disableBtn || loading}
category="update"
onPress={() => {
handleEdit()
}}
/>
}
/>
),
)
}}
/>
@@ -371,7 +387,7 @@ export default function EditMember() {
type="numeric"
placeholder="8XX-XXX-XXX"
required
itemLeft={<Text>+62</Text>}
itemLeft={<Text style={[Platform.OS === 'ios' && Styles.mt02]}>+62</Text>}
value={data?.phone}
error={error.phone}
errorText="Nomor Telepon tidak valid"

View File

@@ -1,51 +1,73 @@
import AlertKonfirmasi from "@/components/alertKonfirmasi";
import ButtonBackHeader from "@/components/buttonBackHeader";
import AppHeader from "@/components/AppHeader";
import { ButtonHeader } from "@/components/buttonHeader";
import ItemDetailMember from "@/components/itemDetailMember";
import Text from "@/components/Text";
import { assetUserImage } from "@/constants/AssetsError";
import { ConstEnv } from "@/constants/ConstEnv";
import Styles from "@/constants/Styles";
import { useAuthSession } from "@/providers/AuthProvider";
import { AntDesign } from "@expo/vector-icons";
import { router, Stack } from "expo-router";
import { useState } from "react";
import { Image, SafeAreaView, ScrollView, View } from "react-native";
import { Image, Pressable, SafeAreaView, ScrollView, View } from "react-native";
import ImageViewing from 'react-native-image-viewing';
import { useSelector } from 'react-redux';
export default function Profile() {
const { signOut } = useAuthSession()
const entities = useSelector((state: any) => state.entities)
const [error, setError] = useState(false)
const [preview, setPreview] = useState(false)
return (
<SafeAreaView>
<Stack.Screen
options={{
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
headerTitle: 'Profile',
headerTitleAlign: 'center',
headerShadowVisible: false,
headerRight: () => <ButtonHeader
item={<AntDesign name="logout" size={20} color="white" />}
onPress={() => {
AlertKonfirmasi({
title: 'Keluar',
desc: 'Apakah anda yakin ingin keluar?',
onPress: () => { signOut() }
})
}}
/>
header: () => (
<AppHeader
title="Profile"
showBack={true}
onPressLeft={() => router.back()}
right={
<ButtonHeader
item={<AntDesign name="logout" size={20} color="white" />}
onPress={() => {
AlertKonfirmasi({
title: 'Keluar',
desc: 'Apakah anda yakin ingin keluar?',
onPress: () => { signOut() }
})
}}
/>
}
/>
)
// headerRight: () => <ButtonHeader
// item={<AntDesign name="logout" size={20} color="white" />}
// onPress={() => {
// AlertKonfirmasi({
// title: 'Keluar',
// desc: 'Apakah anda yakin ingin keluar?',
// onPress: () => { signOut() }
// })
// }}
// />
}}
/>
<ScrollView style={[Styles.h100]}>
<View style={{ flexDirection: 'column' }}>
<View style={[Styles.wrapHeadViewMember]}>
<Image
source={error ? require("../../assets/images/user.jpg") : { uri: `${ConstEnv.url_storage}/files/${entities.img}` }}
onError={() => { setError(true) }}
style={[Styles.userProfileBig]}
/>
<Pressable onPress={() => setPreview(true)}>
<Image
source={error ? require("../../assets/images/user.jpg") : { uri: `${ConstEnv.url_storage}/files/${entities.img}` }}
onError={() => { setError(true) }}
style={[Styles.userProfileBig]}
/>
</Pressable>
<Text style={[Styles.textSubtitle, Styles.cWhite, Styles.mt10]}>{entities.name}</Text>
<Text style={[Styles.textMediumNormal, Styles.cWhite]}>{entities.role}</Text>
</View>
@@ -65,6 +87,13 @@ export default function Profile() {
</View>
</View>
</ScrollView>
<ImageViewing
images={[{ uri: error ? assetUserImage.uri : `${ConstEnv.url_storage}/files/${entities.img}` }]}
imageIndex={0}
visible={preview}
onRequestClose={() => setPreview(false)}
doubleTapToZoomEnabled
/>
</SafeAreaView>
)
}

View File

@@ -1,5 +1,5 @@
import AppHeader from "@/components/AppHeader"
import BorderBottomItem from "@/components/borderBottomItem"
import ButtonBackHeader from "@/components/buttonBackHeader"
import ButtonSaveHeader from "@/components/buttonSaveHeader"
import ButtonSelect from "@/components/buttonSelect"
import DrawerBottom from "@/components/drawerBottom"
@@ -130,13 +130,27 @@ export default function ProjectAddFile() {
<SafeAreaView>
<Stack.Screen
options={{
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
// headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
headerTitle: 'Tambah File',
headerTitleAlign: 'center',
headerRight: () => <ButtonSaveHeader
disable={fileForm.length == 0 || loading ? true : false}
category="create"
onPress={() => { handleAddFile() }} />
// headerRight: () => <ButtonSaveHeader
// disable={fileForm.length == 0 || loading ? true : false}
// category="create"
// onPress={() => { handleAddFile() }} />
header: () => (
<AppHeader
title="Tambah File"
showBack={true}
onPressLeft={() => router.back()}
right={
<ButtonSaveHeader
disable={fileForm.length == 0 || loading ? true : false}
category="create"
onPress={() => { handleAddFile() }}
/>
}
/>
)
}}
/>
<ScrollView>

View File

@@ -1,4 +1,4 @@
import ButtonBackHeader from "@/components/buttonBackHeader";
import AppHeader from "@/components/AppHeader";
import ButtonSaveHeader from "@/components/buttonSaveHeader";
import ImageUser from "@/components/imageNew";
import ImageWithLabel from "@/components/imageWithLabel";
@@ -97,16 +97,32 @@ export default function AddMemberProject() {
<>
<Stack.Screen
options={{
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
// headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
headerTitle: 'Tambah Anggota Kegiatan',
headerTitleAlign: 'center',
headerRight: () => (
<ButtonSaveHeader
category="update"
disable={selectMember.length == 0 || loading ? true : false}
onPress={() => {
handleAddMember()
}}
// headerRight: () => (
// <ButtonSaveHeader
// category="update"
// disable={selectMember.length == 0 || loading ? true : false}
// onPress={() => {
// handleAddMember()
// }}
// />
// )
header: () => (
<AppHeader
title="Tambah Anggota Kegiatan"
showBack={true}
onPressLeft={() => router.back()}
right={
<ButtonSaveHeader
category="update"
disable={selectMember.length == 0 || loading ? true : false}
onPress={() => {
handleAddMember()
}}
/>
}
/>
)
}}

View File

@@ -1,4 +1,4 @@
import ButtonBackHeader from "@/components/buttonBackHeader";
import AppHeader from "@/components/AppHeader";
import ButtonSaveHeader from "@/components/buttonSaveHeader";
import { InputForm } from "@/components/inputForm";
import ModalAddDetailTugasProject from "@/components/project/modalAddDetailTugasProject";
@@ -136,22 +136,36 @@ export default function ProjectAddTask() {
<SafeAreaView>
<Stack.Screen
options={{
headerLeft: () => (
<ButtonBackHeader
onPress={() => {
router.back();
}}
/>
),
// headerLeft: () => (
// <ButtonBackHeader
// onPress={() => {
// router.back();
// }}
// />
// ),
headerTitle: "Tambah Tugas",
headerTitleAlign: "center",
headerRight: () => (
<ButtonSaveHeader
disable={disable || loading}
category="create"
onPress={() => { handleCreate() }}
// headerRight: () => (
// <ButtonSaveHeader
// disable={disable || loading}
// category="create"
// onPress={() => { handleCreate() }}
// />
// ),
header: () => (
<AppHeader
title="Tambah Tugas"
showBack={true}
onPressLeft={() => router.back()}
right={
<ButtonSaveHeader
disable={disable || loading}
category="create"
onPress={() => { handleCreate() }}
/>
}
/>
),
)
}}
/>
<KeyboardAvoidingView

View File

@@ -1,4 +1,4 @@
import ButtonBackHeader from "@/components/buttonBackHeader";
import AppHeader from "@/components/AppHeader";
import ButtonSaveHeader from "@/components/buttonSaveHeader";
import { InputForm } from "@/components/inputForm";
import Styles from "@/constants/Styles";
@@ -6,7 +6,7 @@ import { apiCancelProject } from "@/lib/api";
import { setUpdateProject } from "@/lib/projectUpdate";
import { useAuthSession } from "@/providers/AuthProvider";
import { router, Stack, useLocalSearchParams } from "expo-router";
import { useEffect, useState } from "react";
import React, { useEffect, useState } from "react";
import { SafeAreaView, ScrollView, View } from "react-native";
import Toast from "react-native-toast-message";
import { useDispatch, useSelector } from "react-redux";
@@ -68,24 +68,40 @@ export default function ProjectCancel() {
<SafeAreaView>
<Stack.Screen
options={{
headerLeft: () => (
<ButtonBackHeader
onPress={() => {
router.back();
}}
/>
),
// headerLeft: () => (
// <ButtonBackHeader
// onPress={() => {
// router.back();
// }}
// />
// ),
headerTitle: "Pembatalan Kegiatan",
headerTitleAlign: "center",
headerRight: () => (
<ButtonSaveHeader
disable={disable || loading}
category="cancel"
onPress={() => {
handleCancel();
}}
// headerRight: () => (
// <ButtonSaveHeader
// disable={disable || loading}
// category="cancel"
// onPress={() => {
// handleCancel();
// }}
// />
// ),
header: () => (
<AppHeader
title="Pembatalan Kegiatan"
showBack={true}
onPressLeft={() => router.back()}
right={
<ButtonSaveHeader
disable={disable || loading}
category="cancel"
onPress={() => {
handleCancel();
}}
/>
}
/>
),
)
}}
/>
<ScrollView

View File

@@ -1,4 +1,4 @@
import ButtonBackHeader from "@/components/buttonBackHeader";
import AppHeader from "@/components/AppHeader";
import ButtonSaveHeader from "@/components/buttonSaveHeader";
import { InputForm } from "@/components/inputForm";
import Styles from "@/constants/Styles";
@@ -43,7 +43,7 @@ export default function EditProject() {
setJudul(val)
if (val == "" || val == "null") {
setError(true)
}else{
} else {
setError(false)
}
}
@@ -89,22 +89,36 @@ export default function EditProject() {
<SafeAreaView>
<Stack.Screen
options={{
headerLeft: () => (
<ButtonBackHeader
onPress={() => {
router.back();
}}
/>
),
// headerLeft: () => (
// <ButtonBackHeader
// onPress={() => {
// router.back();
// }}
// />
// ),
headerTitle: "Edit Judul Kegiatan",
headerTitleAlign: "center",
headerRight: () => (
<ButtonSaveHeader
disable={disable || loading}
category="update"
onPress={() => { handleUpdate() }}
// headerRight: () => (
// <ButtonSaveHeader
// disable={disable || loading}
// category="update"
// onPress={() => { handleUpdate() }}
// />
// ),
header: () => (
<AppHeader
title="Edit Judul Kegiatan"
showBack={true}
onPressLeft={() => router.back()}
right={
<ButtonSaveHeader
disable={disable || loading}
category="update"
onPress={() => { handleUpdate() }}
/>
}
/>
),
)
}}
/>
<ScrollView>

View File

@@ -1,4 +1,4 @@
import ButtonBackHeader from "@/components/buttonBackHeader";
import AppHeader from "@/components/AppHeader";
import HeaderRightProjectDetail from "@/components/project/headerProjectDetail";
import SectionFile from "@/components/project/sectionFile";
import SectionLink from "@/components/project/sectionLink";
@@ -11,7 +11,7 @@ import Styles from "@/constants/Styles";
import { apiGetProjectOne } from "@/lib/api";
import { useAuthSession } from "@/providers/AuthProvider";
import { router, Stack, useLocalSearchParams } from "expo-router";
import { useEffect, useState } from "react";
import React, { useEffect, useState } from "react";
import { RefreshControl, SafeAreaView, ScrollView, View } from "react-native";
import { useSelector } from "react-redux";
@@ -94,10 +94,20 @@ export default function DetailProject() {
<SafeAreaView>
<Stack.Screen
options={{
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
// headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
headerTitle: loading ? 'Loading... ' : data?.title,
headerTitleAlign: 'center',
headerRight: () => (entityUser.role == "user" || entityUser.role == "coadmin") && !isMember ? null : <HeaderRightProjectDetail id={id} status={data?.status} />,
// headerRight: () => (entityUser.role == "user" || entityUser.role == "coadmin") && !isMember ? null : <HeaderRightProjectDetail id={id} status={data?.status} />,
header: () => (
<AppHeader
title={loading ? 'Loading...' : data && data?.title || ''}
showBack={true}
onPressLeft={() => router.back()}
right={
(entityUser.role == "user" || entityUser.role == "coadmin") && !isMember ? null : <HeaderRightProjectDetail id={id} status={data?.status} />
}
/>
)
}}
/>
<ScrollView

View File

@@ -1,4 +1,4 @@
import ButtonBackHeader from "@/components/buttonBackHeader";
import AppHeader from "@/components/AppHeader";
import ButtonSaveHeader from "@/components/buttonSaveHeader";
import { InputForm } from "@/components/inputForm";
import Styles from "@/constants/Styles";
@@ -89,22 +89,36 @@ export default function ReportProject() {
<SafeAreaView>
<Stack.Screen
options={{
headerLeft: () => (
<ButtonBackHeader
onPress={() => {
router.back();
}}
/>
),
// headerLeft: () => (
// <ButtonBackHeader
// onPress={() => {
// router.back();
// }}
// />
// ),
headerTitle: "Laporan Kegiatan",
headerTitleAlign: "center",
headerRight: () => (
<ButtonSaveHeader
disable={disable || loading}
category="update"
onPress={() => { handleUpdate() }}
// headerRight: () => (
// <ButtonSaveHeader
// disable={disable || loading}
// category="update"
// onPress={() => { handleUpdate() }}
// />
// ),
header: () => (
<AppHeader
title="Laporan Kegiatan"
showBack={true}
onPressLeft={() => router.back()}
right={
<ButtonSaveHeader
disable={disable || loading}
category="update"
onPress={() => { handleUpdate() }}
/>
}
/>
),
)
}}
/>
<ScrollView

View File

@@ -1,5 +1,5 @@
import AppHeader from "@/components/AppHeader";
import BorderBottomItem from "@/components/borderBottomItem";
import ButtonBackHeader from "@/components/buttonBackHeader";
import ButtonSaveHeader from "@/components/buttonSaveHeader";
import ButtonSelect from "@/components/buttonSelect";
import DrawerBottom from "@/components/drawerBottom";
@@ -193,24 +193,39 @@ export default function CreateProject() {
<SafeAreaView>
<Stack.Screen
options={{
headerLeft: () => (
<ButtonBackHeader
onPress={() => {
handleBack();
}}
/>
),
// headerLeft: () => (
// <ButtonBackHeader
// onPress={() => {
// handleBack();
// }}
// />
// ),
headerTitle: "Tambah Kegiatan",
headerTitleAlign: "center",
headerRight: () => (
<ButtonSaveHeader
disable={disableBtn || loading}
category="create"
onPress={() => {
handleCreate()
}}
// headerRight: () => (
// <ButtonSaveHeader
// disable={disableBtn || loading}
// category="create"
// onPress={() => {
// handleCreate()
// }}
// />
// ),
header: () => (
<AppHeader title="Tambah Kegiatan"
showBack={true}
onPressLeft={() => router.back()}
right={
<ButtonSaveHeader
disable={disableBtn || loading}
category="create"
onPress={() => {
handleCreate()
}}
/>
}
/>
),
)
}}
/>
<ScrollView

View File

@@ -1,4 +1,4 @@
import ButtonBackHeader from "@/components/buttonBackHeader";
import AppHeader from "@/components/AppHeader";
import ButtonSaveHeader from "@/components/buttonSaveHeader";
import ImageUser from "@/components/imageNew";
import ImageWithLabel from "@/components/imageWithLabel";
@@ -11,8 +11,8 @@ import { setMemberChoose } from "@/lib/memberChoose";
import { useAuthSession } from "@/providers/AuthProvider";
import { AntDesign } from "@expo/vector-icons";
import { router, Stack } from "expo-router";
import { useEffect, useState } from "react";
import { Pressable, SafeAreaView, ScrollView, View } from "react-native";
import React, { useEffect, useState } from "react";
import { Pressable, ScrollView, View } from "react-native";
import Toast from "react-native-toast-message";
import { useDispatch, useSelector } from "react-redux";
@@ -74,16 +74,31 @@ export default function AddMemberCreateProject() {
<>
<Stack.Screen
options={{
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
// headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
headerTitle: 'Pilih Anggota',
headerTitleAlign: 'center',
headerRight: () => (
<ButtonSaveHeader
category="create"
disable={selectMember.length > 0 ? false : true}
onPress={() => {
handleAddMember()
}}
// headerRight: () => (
// <ButtonSaveHeader
// category="create"
// disable={selectMember.length > 0 ? false : true}
// onPress={() => {
// handleAddMember()
// }}
// />
// )
header: () => (
<AppHeader title="Pilih Anggota"
showBack={true}
onPressLeft={() => router.back()}
right={
<ButtonSaveHeader
category="create"
disable={selectMember.length > 0 ? false : true}
onPress={() => {
handleAddMember()
}}
/>
}
/>
)
}}

View File

@@ -1,4 +1,4 @@
import ButtonBackHeader from "@/components/buttonBackHeader";
import AppHeader from "@/components/AppHeader";
import ButtonSaveHeader from "@/components/buttonSaveHeader";
import { InputForm } from "@/components/inputForm";
import ModalAddDetailTugasProject from "@/components/project/modalAddDetailTugasProject";
@@ -12,7 +12,7 @@ import { router, Stack } from "expo-router";
import 'intl';
import 'intl/locale-data/jsonp/id';
import moment from "moment";
import { useEffect, useState } from "react";
import React, { useEffect, useState } from "react";
import {
KeyboardAvoidingView,
Platform,
@@ -122,22 +122,36 @@ export default function CreateProjectAddTask() {
<SafeAreaView>
<Stack.Screen
options={{
headerLeft: () => (
<ButtonBackHeader
onPress={() => {
router.back();
}}
/>
),
// headerLeft: () => (
// <ButtonBackHeader
// onPress={() => {
// router.back();
// }}
// />
// ),
headerTitle: "Tambah Tugas",
headerTitleAlign: "center",
headerRight: () => (
<ButtonSaveHeader
disable={disable}
category="create"
onPress={() => { handleCreate() }}
// headerRight: () => (
// <ButtonSaveHeader
// disable={disable}
// category="create"
// onPress={() => { handleCreate() }}
// />
// ),
header: () => (
<AppHeader
title="Tambah Tugas"
showBack={true}
onPressLeft={() => router.back()}
right={
<ButtonSaveHeader
disable={disable}
category="create"
onPress={() => { handleCreate() }}
/>
}
/>
),
)
}}
/>
<KeyboardAvoidingView

View File

@@ -1,4 +1,4 @@
import ButtonBackHeader from "@/components/buttonBackHeader";
import AppHeader from "@/components/AppHeader";
import ButtonSaveHeader from "@/components/buttonSaveHeader";
import { InputForm } from "@/components/inputForm";
import ModalAddDetailTugasProject from "@/components/project/modalAddDetailTugasProject";
@@ -14,7 +14,7 @@ import { router, Stack, useLocalSearchParams } from "expo-router";
import 'intl';
import 'intl/locale-data/jsonp/id';
import moment from "moment";
import { useEffect, useState } from "react";
import React, { useEffect, useState } from "react";
import { KeyboardAvoidingView, Platform, Pressable, SafeAreaView, ScrollView, View } from "react-native";
import Toast from "react-native-toast-message";
import DateTimePicker, { DateType } from "react-native-ui-datepicker";
@@ -172,14 +172,28 @@ export default function UpdateProjectTask() {
<SafeAreaView>
<Stack.Screen
options={{
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
// headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
headerTitle: 'Edit Tanggal dan Tugas',
headerTitleAlign: 'center',
headerRight: () => <ButtonSaveHeader
disable={disableBtn || loadingSubmit}
category="update"
onPress={() => { handleEdit() }}
/>
// headerRight: () => <ButtonSaveHeader
// disable={disableBtn || loadingSubmit}
// category="update"
// onPress={() => { handleEdit() }}
// />
header: () => (
<AppHeader
title="Edit Tanggal dan Tugas"
showBack={true}
onPressLeft={() => router.back()}
right={
<ButtonSaveHeader
disable={disableBtn || loadingSubmit}
category="update"
onPress={() => { handleEdit() }}
/>
}
/>
)
}}
/>
<KeyboardAvoidingView

View File

@@ -1,5 +1,5 @@
import AppHeader from "@/components/AppHeader";
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';
@@ -82,9 +82,11 @@ export default function Search() {
<SafeAreaView>
<Stack.Screen
options={{
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
headerTitle: 'Pencarian',
headerTitleAlign: 'center'
headerTitleAlign: 'center',
header: () => (
<AppHeader title="Pencarian" showBack={true} onPressLeft={() => router.back()} />
)
}}
/>
<View style={[Styles.p15]}>

BIN
bun.lockb

Binary file not shown.

33
components/AppHeader.tsx Normal file
View File

@@ -0,0 +1,33 @@
import { useRouter } from 'expo-router';
import { StyleSheet, Text, View } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import ButtonBackHeader from './buttonBackHeader';
import Styles from '@/constants/Styles';
type Props = {
title: string;
right?: React.ReactNode;
showBack?: boolean;
onPressLeft?: () => void
};
export default function AppHeader({ title, right, showBack = true, onPressLeft }: Props) {
const insets = useSafeAreaInsets();
const router = useRouter();
return (
<View style={[Styles.headerContainer, { paddingTop: insets.top }]}>
<View style={Styles.headerApp}>
{showBack ? (
<ButtonBackHeader onPress={onPressLeft} />
) : (
<View style={Styles.headerSide} />
)}
<Text style={Styles.headerTitle}>{title}</Text>
<View style={Styles.headerSide}>{right}</View>
</View>
</View>
);
}

View File

@@ -39,10 +39,10 @@ export default function ViewLogin({ onValidate }: Props) {
}
}
} else {
return Toast.show({ type: 'small', text1: response.message, position: 'top' })
return Toast.show({ type: 'small', text1: response.message, position: 'bottom' })
}
} catch (error) {
return Toast.show({ type: 'small', text1: `Terjadi kesalahan, coba lagi`, position: 'top' })
return Toast.show({ type: 'small', text1: `Terjadi kesalahan, coba lagi`, position: 'bottom' })
} finally {
setLoadingLogin(false)
}
@@ -70,7 +70,7 @@ export default function ViewLogin({ onValidate }: Props) {
type="numeric"
placeholder="XXX-XXX-XXXX"
round
itemLeft={<Text>+62</Text>}
itemLeft={<Text style={[Platform.OS === 'ios' && Styles.mt02]}>+62</Text>}
info="Kami akan mengirim kode verifikasi melalui WhatsApp, guna mengonfirmasikan nomor Anda." />
<ButtonForm
text="MASUK"

View File

@@ -28,7 +28,7 @@ export default function ViewVerification({ phone, otp }: Props) {
const encrypted = await encryptToken(valueUser);
signIn(encrypted);
} else {
return Toast.show({ type: 'small', text1: 'Terjadi kesalahan', position: 'top' })
return Toast.show({ type: 'small', text1: 'Terjadi kesalahan', position: 'bottom' })
}
}
@@ -36,7 +36,7 @@ export default function ViewVerification({ phone, otp }: Props) {
if (value === otpFix.toString()) {
login()
} else {
return Toast.show({ type: 'small', text1: 'Kode OTP tidak sesuai', position: 'top' });
return Toast.show({ type: 'small', text1: 'Kode OTP tidak sesuai', position: 'bottom' });
}
}

View File

@@ -6,17 +6,19 @@ type Props = {
src: string,
size?: 'sm' | 'xs' | 'lg'
border?: boolean
onError?: (val:boolean) => void
}
export default function ImageUser({ src, size }: Props) {
export default function ImageUser({ src, size, onError }: Props) {
const [error, setError] = useState(false)
return (
<Image
source={error ? require('../assets/images/user.jpg') : { uri: src }}
style={[size == 'xs' ? Styles.userProfileExtraSmall : size == 'lg' ? Styles.userProfileBig : Styles.userProfileSmall, Styles.borderAll]}
onError={() =>
onError={() => {
setError(true)
}
onError?.(true)
}}
/>
)
}

5
constants/AssetsError.ts Normal file
View File

@@ -0,0 +1,5 @@
import { Image } from "react-native";
export const assetUserImage = Image.resolveAssetSource(
require('@/assets/images/user.jpg')
);

View File

@@ -631,7 +631,27 @@ const Styles = StyleSheet.create({
position: 'absolute',
opacity: 0,
zIndex: -1,
}
},
headerContainer: {
backgroundColor: '#19345E',
},
headerApp: {
// height: 40,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingHorizontal: 16,
paddingVertical: 3
},
headerTitle: {
color: '#fff',
fontSize: 16,
fontWeight: '600',
},
headerSide: {
width: 40,
alignItems: 'center',
},
})
export default Styles;

View File

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

View File

@@ -75,6 +75,7 @@
"react-native-gesture-handler": "~2.24.0",
"react-native-gifted-charts": "^1.4.57",
"react-native-image-picker": "^8.2.1",
"react-native-image-viewing": "^0.2.2",
"react-native-mime-types": "^2.5.0",
"react-native-modal": "^14.0.0-rc.1",
"react-native-modal-datetime-picker": "^18.0.0",