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",