diff --git a/app/(application)/_layout.tsx b/app/(application)/_layout.tsx
index 4a53b50..9c4529c 100644
--- a/app/(application)/_layout.tsx
+++ b/app/(application)/_layout.tsx
@@ -1,4 +1,5 @@
import ButtonBackHeader from "@/components/buttonBackHeader";
+import HeaderDiscussionGeneral from "@/components/discussion_general/headerDiscussionGeneral";
import HeaderMemberList from "@/components/member/headerMemberList";
import { Headers } from "@/constants/Headers";
import { router, Stack } from "expo-router";
@@ -21,7 +22,12 @@ export default function RootLayout() {
headerTitleAlign: 'center',
headerRight: () =>
}} />
-
+ { router.back() }} />,
+ title: 'Diskusi Umum',
+ headerTitleAlign: 'center',
+ headerRight: () =>
+ }} />
>
diff --git a/app/(application)/discussion/[id].tsx b/app/(application)/discussion/[id].tsx
new file mode 100644
index 0000000..bf302cb
--- /dev/null
+++ b/app/(application)/discussion/[id].tsx
@@ -0,0 +1,7 @@
+import { Text } from "react-native";
+
+export default function DetailDiscussionGeneral() {
+ return (
+ Detail diskusi general
+ )
+}
\ No newline at end of file
diff --git a/app/(application)/discussion/create.tsx b/app/(application)/discussion/create.tsx
new file mode 100644
index 0000000..bd3b99c
--- /dev/null
+++ b/app/(application)/discussion/create.tsx
@@ -0,0 +1,7 @@
+import { Text } from "react-native";
+
+export default function CreateDiscussionGeneral(){
+ return(
+ Tambah diskusi general
+ )
+}
\ No newline at end of file
diff --git a/app/(application)/discussion/index.tsx b/app/(application)/discussion/index.tsx
new file mode 100644
index 0000000..2b62923
--- /dev/null
+++ b/app/(application)/discussion/index.tsx
@@ -0,0 +1,66 @@
+import BorderBottomItem from "@/components/borderBottomItem";
+import ButtonTab from "@/components/buttonTab";
+import InputSearch from "@/components/inputSearch";
+import LabelStatus from "@/components/labelStatus";
+import { ColorsStatus } from "@/constants/ColorsStatus";
+import Styles from "@/constants/Styles";
+import { AntDesign, Feather, Ionicons, MaterialCommunityIcons, MaterialIcons } from "@expo/vector-icons";
+import { router, useLocalSearchParams } from "expo-router";
+import { SafeAreaView, ScrollView, Text, View } from "react-native";
+
+export default function Discussion() {
+ const { active } = useLocalSearchParams<{ active?: string }>()
+
+ return (
+
+
+
+
+ { router.push('/discussion?active=true') }}
+ label="Aktif"
+ icon={}
+ n={2} />
+ { router.push('/discussion?active=false') }}
+ label="Arsip"
+ icon={}
+ n={2} />
+
+
+
+ Filter : Dinas
+
+
+ { router.push('/discussion/1') }}
+ borderType="bottom"
+ icon={
+
+
+
+ }
+ title="Danantara"
+ subtitle={
+
+ }
+ rightTopInfo="3 Jan 2025"
+ desc="Bagaimana dampak yg dirasakan akibat efisiensi?"
+ leftBottomInfo={
+
+
+ Diskusikan
+
+ }
+ rightBottomInfo='15 Komentar'
+ />
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/app/(application)/feature.tsx b/app/(application)/feature.tsx
index db893b4..6e309fe 100644
--- a/app/(application)/feature.tsx
+++ b/app/(application)/feature.tsx
@@ -20,7 +20,7 @@ export default function Feature() {
} text="Divisi" />
} text="Kegiatan" />
} text="Pengumuman" />
- } text="Diskusi" />
+ } text="Diskusi" onPress={() => { router.push('/discussion?active=true') }}/>
} text="Anggota" onPress={() => { router.push('/member?active=true') }}/>
diff --git a/app/(application)/member/[id].tsx b/app/(application)/member/[id].tsx
new file mode 100644
index 0000000..5cb84b0
--- /dev/null
+++ b/app/(application)/member/[id].tsx
@@ -0,0 +1,47 @@
+import ButtonBackHeader from "@/components/buttonBackHeader";
+import ItemDetailMember from "@/components/itemDetailMember";
+import HeaderRightMemberDetail from "@/components/member/headerMemberDetail";
+import Styles from "@/constants/Styles";
+import { router, Stack, useLocalSearchParams } from "expo-router";
+import { Image, SafeAreaView, ScrollView, Text, View } from "react-native";
+
+export default function MemberDetail() {
+ const { id } = useLocalSearchParams();
+
+ return (
+
+ { router.back() }} />,
+ headerTitle: 'Anggota',
+ headerTitleAlign:'center',
+ headerRight: () => ,
+ headerShadowVisible: false
+ }}
+ />
+
+
+
+
+ Putri Ayu Dewi
+ Super Admin
+
+
+
+ Informasi
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/app/(application)/member/create.tsx b/app/(application)/member/create.tsx
index 24577e2..1422d6a 100644
--- a/app/(application)/member/create.tsx
+++ b/app/(application)/member/create.tsx
@@ -1,7 +1,80 @@
-import { Text } from "react-native";
+import AlertKonfirmasi from "@/components/alertKonfirmasi";
+import ButtonBackHeader from "@/components/buttonBackHeader";
+import { ButtonForm } from "@/components/buttonForm";
+import { InputForm } from "@/components/inputForm";
+import SelectForm from "@/components/selectForm";
+import { ColorsStatus } from "@/constants/ColorsStatus";
+import Styles from "@/constants/Styles";
+import { MaterialCommunityIcons } from "@expo/vector-icons";
+import * as ImagePicker from 'expo-image-picker';
+import { router, Stack } from "expo-router";
+import { useState } from "react";
+import { Image, Pressable, SafeAreaView, ScrollView, Text, ToastAndroid, View } from "react-native";
export default function CreateMember() {
+ const [chooseGroup, setChooseGroup] = useState({ val: '', label: '' })
+ const [selectedImage, setSelectedImage] = useState(undefined);
+
+ const pickImageAsync = async () => {
+ let result = await ImagePicker.launchImageLibraryAsync({
+ mediaTypes: ['images'],
+ allowsEditing: true,
+ quality: 1,
+ });
+
+ if (!result.canceled) {
+ setSelectedImage(result.assets[0].uri);
+ } else {
+ alert('Tidak ada gambar yang dipilih');
+ }
+ };
+
return (
- Tambah Member
+
+ { router.back() }} />,
+ headerTitle: 'Tambah Anggota',
+ headerTitleAlign: 'center',
+ }}
+ />
+
+
+
+ {
+ selectedImage != undefined ? (
+
+
+
+ ) : (
+
+
+
+ )
+ }
+
+ { }} />
+ { }} />
+ { }} />
+
+
+
+ +62} />
+ { }} />
+ {
+ AlertKonfirmasi({
+ title: 'Konfirmasi',
+ desc: 'Apakah anda yakin ingin menambahkan data?',
+ onPress: () => {
+ ToastAndroid.show('Berhasil menambahkan data', ToastAndroid.SHORT)
+ router.push('/member?active=true')
+ }
+ })
+ }} />
+
+
+
)
}
\ No newline at end of file
diff --git a/app/(application)/member/edit/[id].tsx b/app/(application)/member/edit/[id].tsx
new file mode 100644
index 0000000..4bb010f
--- /dev/null
+++ b/app/(application)/member/edit/[id].tsx
@@ -0,0 +1,79 @@
+import AlertKonfirmasi from "@/components/alertKonfirmasi"
+import ButtonBackHeader from "@/components/buttonBackHeader"
+import { ButtonForm } from "@/components/buttonForm"
+import { InputForm } from "@/components/inputForm"
+import SelectForm from "@/components/selectForm"
+import { ColorsStatus } from "@/constants/ColorsStatus"
+import Styles from "@/constants/Styles"
+import { MaterialCommunityIcons } from "@expo/vector-icons"
+import * as ImagePicker from 'expo-image-picker'
+import { router, Stack } from "expo-router"
+import { useState } from "react"
+import { Image, Pressable, SafeAreaView, ScrollView, Text, ToastAndroid, View } from "react-native"
+
+export default function EditMember() {
+ const [chooseGroup, setChooseGroup] = useState({ val: '', label: '' })
+ const [selectedImage, setSelectedImage] = useState(undefined);
+
+ const pickImageAsync = async () => {
+ let result = await ImagePicker.launchImageLibraryAsync({
+ mediaTypes: ['images'],
+ allowsEditing: true,
+ quality: 1,
+ });
+
+ if (!result.canceled) {
+ setSelectedImage(result.assets[0].uri);
+ } else {
+ alert('Tidak ada gambar yang dipilih');
+ }
+ };
+
+ return (
+
+ { router.back() }} />,
+ headerTitle: 'Edit Anggota',
+ headerTitleAlign: 'center',
+ }}
+ />
+
+
+
+ {
+ selectedImage != undefined ? (
+
+
+
+ ) : (
+
+
+
+ )
+ }
+
+ { }} />
+ { }} />
+
+
+
+ +62} />
+ { }} />
+ {
+ AlertKonfirmasi({
+ title: 'Konfirmasi',
+ desc: 'Apakah anda yakin ingin mengubah data?',
+ onPress: () => {
+ ToastAndroid.show('Berhasil mengubah data', ToastAndroid.SHORT)
+ router.back()
+ }
+ })
+ }} />
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/app/(application)/member/index.tsx b/app/(application)/member/index.tsx
index f764692..4664416 100644
--- a/app/(application)/member/index.tsx
+++ b/app/(application)/member/index.tsx
@@ -35,7 +35,7 @@ export default function Index() {
{ }}
+ onPress={() => {router.push('/member/1')}}
borderType="all"
icon={
{ }}
+ onPress={() => {router.push('/member/1')}}
borderType="all"
icon={
{ }}
+ onPress={() => {router.push('/member/1')}}
borderType="all"
icon={
{ }}
+ onPress={() => {router.push('/member/1')}}
borderType="all"
icon={
{ }}
+ onPress={() => {router.push('/member/1')}}
borderType="all"
icon={
{ }}
+ onPress={() => {router.push('/member/1')}}
borderType="all"
icon={
{ router.back() }} />,
headerTitle: 'Profile',
headerTitleAlign: 'center',
+ headerShadowVisible: false,
headerRight: () => }
onPress={() => {
@@ -41,55 +43,12 @@ export default function Profile() {
Informasi
Edit
-
-
-
- NIK
-
- 123456789
-
-
-
-
-
- Lembaga Desa
-
- Dinas
-
-
-
-
-
- Jabatan
-
- Bendahara
-
-
-
-
-
- No Telepon
-
- 09482903842
-
-
-
-
-
- Email
-
- ayu@gmail.com
-
-
-
-
-
-
- Jenis Kelamin
-
- Perempuan
-
-
+
+
+
+
+
+
diff --git a/bun.lockb b/bun.lockb
index 6b99dd7..41feab0 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/components/borderBottomItem.tsx b/components/borderBottomItem.tsx
index 8f82c8d..6483a8c 100644
--- a/components/borderBottomItem.tsx
+++ b/components/borderBottomItem.tsx
@@ -1,17 +1,24 @@
import Styles from "@/constants/Styles";
+import React from "react";
import { Pressable, Text, View } from "react-native";
+import LabelStatus from "./labelStatus";
+import { Feather } from "@expo/vector-icons";
type Props = {
title: string
- subtitle?: string
+ subtitle?: string | React.ReactNode
icon: React.ReactNode
desc?: string
rightTopInfo?: string
onPress?: () => void
borderType: 'all' | 'bottom'
+ leftBottomInfo?: React.ReactNode | string
+ rightBottomInfo?: React.ReactNode | string
}
-export default function BorderBottomItem({ title, subtitle, icon, desc, onPress, rightTopInfo, borderType }: Props) {
+export default function BorderBottomItem({ title, subtitle, icon, desc, onPress, rightTopInfo, borderType, leftBottomInfo, rightBottomInfo }: Props) {
+
+ console.log(typeof rightBottomInfo)
return (
@@ -19,7 +26,14 @@ export default function BorderBottomItem({ title, subtitle, icon, desc, onPress,
{title}
- {subtitle && {subtitle}}
+ {
+ subtitle &&
+ typeof subtitle == "string"
+ ? {subtitle}
+ :
+ {subtitle}
+
+ }
{
rightTopInfo && {rightTopInfo}
@@ -28,6 +42,25 @@ export default function BorderBottomItem({ title, subtitle, icon, desc, onPress,
{desc && {desc}}
+ {
+ leftBottomInfo && rightBottomInfo &&
+ (
+
+ {
+ typeof leftBottomInfo == 'string' ?
+ {leftBottomInfo}
+ :
+ leftBottomInfo
+ }
+ {
+ typeof rightBottomInfo == 'string' ?
+ {rightBottomInfo}
+ :
+ rightBottomInfo
+ }
+
+ )
+ }
)
}
\ No newline at end of file
diff --git a/components/discussion_general/headerDiscussionGeneral.tsx b/components/discussion_general/headerDiscussionGeneral.tsx
new file mode 100644
index 0000000..b89753a
--- /dev/null
+++ b/components/discussion_general/headerDiscussionGeneral.tsx
@@ -0,0 +1,40 @@
+import Styles from "@/constants/Styles"
+import { AntDesign } from "@expo/vector-icons"
+import { router } from "expo-router"
+import { useState } from "react"
+import { View } from "react-native"
+import ButtonMenuHeader from "../buttonMenuHeader"
+import DrawerBottom from "../drawerBottom"
+import MenuItemRow from "../menuItemRow"
+import ModalFilter from "../modalFilter"
+
+export default function HeaderDiscussionGeneral() {
+ const [isVisible, setVisible] = useState(false)
+ const [isFilter, setFilter] = useState(false)
+ return (
+ <>
+ { setVisible(true) }} />
+
+
+ }
+ title="Tambah Diskusi"
+ onPress={() => {
+ setVisible(false)
+ router.push('/discussion/create')
+ }}
+ />
+ }
+ title="Filter"
+ onPress={() => {
+ setVisible(false)
+ setFilter(true)
+ }}
+ />
+
+
+ { setFilter(false) }} open={isFilter} page="discussion" />
+ >
+ )
+}
\ No newline at end of file
diff --git a/components/inputForm.tsx b/components/inputForm.tsx
index a24f1c9..48e0151 100644
--- a/components/inputForm.tsx
+++ b/components/inputForm.tsx
@@ -49,7 +49,7 @@ export function InputForm({ label, placeholder, onChange, info, error, errorText
{
label != undefined && (
-
+
{label}
{required && (*)}
diff --git a/components/itemDetailMember.tsx b/components/itemDetailMember.tsx
new file mode 100644
index 0000000..cb1fece
--- /dev/null
+++ b/components/itemDetailMember.tsx
@@ -0,0 +1,49 @@
+import Styles from "@/constants/Styles";
+import { AntDesign, MaterialCommunityIcons, MaterialIcons } from "@expo/vector-icons";
+import { Text, View } from "react-native";
+
+type Props = {
+ category: 'nik' | 'group' | 'position' | 'phone' | 'email' | 'gender'
+ value: string
+}
+
+
+const data = {
+ nik: {
+ label: 'NIK',
+ icon:
+ },
+ group: {
+ label: 'Lembaga Desa',
+ icon:
+ },
+ position: {
+ label: 'Jabatan',
+ icon:
+ },
+ phone: {
+ label: 'No Telepon',
+ icon:
+ },
+ email: {
+ label: 'Email',
+ icon:
+ },
+ gender: {
+ label: 'Jenis Kelamin',
+ icon:
+ },
+}
+
+
+export default function ItemDetailMember({ category, value }: Props) {
+ return (
+
+
+ {data[category].icon}
+ {data[category].label}
+
+ {value}
+
+ )
+}
\ No newline at end of file
diff --git a/components/labelStatus.tsx b/components/labelStatus.tsx
new file mode 100644
index 0000000..51deb32
--- /dev/null
+++ b/components/labelStatus.tsx
@@ -0,0 +1,17 @@
+import { ColorsStatus } from "@/constants/ColorsStatus";
+import Styles from "@/constants/Styles";
+import { Text, View } from "react-native";
+
+
+type Props = {
+ category: 'error' | 'success' | 'warning' | 'primary'
+ text: string
+ size: 'small' | 'default'
+}
+export default function LabelStatus({ category, text, size }: Props) {
+ return (
+
+ {text}
+
+ )
+}
\ No newline at end of file
diff --git a/components/member/headerMemberDetail.tsx b/components/member/headerMemberDetail.tsx
new file mode 100644
index 0000000..42d20b0
--- /dev/null
+++ b/components/member/headerMemberDetail.tsx
@@ -0,0 +1,46 @@
+import Styles from "@/constants/Styles"
+import { MaterialCommunityIcons } from "@expo/vector-icons"
+import { useState } from "react"
+import { View } from "react-native"
+import AlertKonfirmasi from "../alertKonfirmasi"
+import ButtonMenuHeader from "../buttonMenuHeader"
+import DrawerBottom from "../drawerBottom"
+import MenuItemRow from "../menuItemRow"
+import { router } from "expo-router"
+
+type Props = {
+ id: string | string[]
+}
+
+export default function HeaderRightMemberDetail({ id }: Props) {
+ const [isVisible, setVisible] = useState(false)
+
+ return (
+ <>
+ { setVisible(true) }} />
+
+
+ }
+ title="Non Aktifkan"
+ onPress={() => {
+ AlertKonfirmasi({
+ title: 'Konfirmasi',
+ desc: 'Apakah anda yakin ingin menonaktifkan data?',
+ onPress: () => { }
+ })
+ }}
+ />
+ }
+ title="Edit"
+ onPress={() => {
+ setVisible(false)
+ router.push(`/member/edit/${id}`)
+ }}
+ />
+
+
+ >
+ )
+}
\ No newline at end of file
diff --git a/components/member/headerMemberList.tsx b/components/member/headerMemberList.tsx
index d7ce15a..5e613a2 100644
--- a/components/member/headerMemberList.tsx
+++ b/components/member/headerMemberList.tsx
@@ -1,15 +1,16 @@
-import { router, Stack } from "expo-router"
-import ButtonBackHeader from "../buttonBackHeader"
-import ButtonMenuHeader from "../buttonMenuHeader"
-import { useState } from "react"
-import DrawerBottom from "../drawerBottom"
-import { View } from "react-native"
import Styles from "@/constants/Styles"
-import MenuItemRow from "../menuItemRow"
import { AntDesign } from "@expo/vector-icons"
+import { router } from "expo-router"
+import { useState } from "react"
+import { View } from "react-native"
+import ButtonMenuHeader from "../buttonMenuHeader"
+import DrawerBottom from "../drawerBottom"
+import MenuItemRow from "../menuItemRow"
+import ModalFilter from "../modalFilter"
export default function HeaderMemberList() {
const [isVisible, setVisible] = useState(false)
+ const [isFilter, setFilter] = useState(false)
return (
<>
{ setVisible(true) }} />
@@ -18,15 +19,22 @@ export default function HeaderMemberList() {
}
title="Tambah Anggota"
- onPress={() => { }}
+ onPress={() => {
+ setVisible(false)
+ router.push('/member/create')
+ }}
/>
}
title="Filter"
- onPress={() => { }}
+ onPress={() => {
+ setVisible(false)
+ setFilter(true)
+ }}
/>
+ { setFilter(false) }} open={isFilter} page="member" />
>
)
}
\ No newline at end of file
diff --git a/components/menuItemRow.tsx b/components/menuItemRow.tsx
index 31668c0..a459a49 100644
--- a/components/menuItemRow.tsx
+++ b/components/menuItemRow.tsx
@@ -9,7 +9,7 @@ type Props = {
export default function MenuItemRow({ onPress, icon, title }: Props) {
return (
- { console.log('press'); onPress() }} style={[Styles.btnMenuRow]}>
+ { onPress() }} style={[Styles.btnMenuRow]}>
{icon}
{title}
diff --git a/components/modalFilter.tsx b/components/modalFilter.tsx
index 1462891..cc05fb8 100644
--- a/components/modalFilter.tsx
+++ b/components/modalFilter.tsx
@@ -9,7 +9,7 @@ import { router } from "expo-router"
type Props = {
open: boolean,
close: (value: boolean) => void
- page: 'position'
+ page: 'position' | 'member' | 'discussion'
}
export default function ModalFilter({ open, close, page }: Props) {
diff --git a/constants/ColorsStatus.ts b/constants/ColorsStatus.ts
index 9eeab6f..2424e26 100644
--- a/constants/ColorsStatus.ts
+++ b/constants/ColorsStatus.ts
@@ -3,7 +3,7 @@ export const ColorsStatus = {
backgroundColor: '#19345E'
},
success: {
- backgroundColor: 'green'
+ backgroundColor: '#40c057'
},
info: {
backgroundColor: 'blue'
@@ -22,5 +22,8 @@ export const ColorsStatus = {
},
lightGreen: {
backgroundColor: '#d2f0cb'
+ },
+ gray: {
+ backgroundColor: '#d9d9d9'
}
}
\ No newline at end of file
diff --git a/constants/Styles.ts b/constants/Styles.ts
index beb886a..11a3956 100644
--- a/constants/Styles.ts
+++ b/constants/Styles.ts
@@ -25,6 +25,10 @@ const Styles = StyleSheet.create({
lineHeight: 24,
fontWeight: '600',
},
+ textSmallSemiBold: {
+ fontSize: 10,
+ fontWeight: '600',
+ },
textTitle: {
fontSize: 32,
fontWeight: 'bold',
@@ -120,6 +124,10 @@ const Styles = StyleSheet.create({
paddingHorizontal: 15,
borderRadius: 10
},
+ labelStatusSmall: {
+ paddingHorizontal: 10,
+ borderRadius: 10
+ },
rowSpaceBetween: {
justifyContent: 'space-between',
flexDirection: 'row'
diff --git a/package.json b/package.json
index e99a627..8f5177b 100644
--- a/package.json
+++ b/package.json
@@ -21,10 +21,13 @@
"expo": "~52.0.37",
"expo-blur": "~14.0.3",
"expo-constants": "~17.0.7",
+ "expo-document-picker": "^13.0.3",
"expo-font": "~13.0.4",
"expo-haptics": "~14.0.1",
+ "expo-image-picker": "~16.0.6",
"expo-linear-gradient": "~14.0.2",
"expo-linking": "~7.0.5",
+ "expo-media-library": "~17.0.6",
"expo-router": "~4.0.17",
"expo-splash-screen": "~0.29.22",
"expo-status-bar": "~2.0.1",