diff --git a/app/(application)/_layout.tsx b/app/(application)/_layout.tsx index 9c4529c..2650703 100644 --- a/app/(application)/_layout.tsx +++ b/app/(application)/_layout.tsx @@ -1,6 +1,7 @@ import ButtonBackHeader from "@/components/buttonBackHeader"; import HeaderDiscussionGeneral from "@/components/discussion_general/headerDiscussionGeneral"; import HeaderMemberList from "@/components/member/headerMemberList"; +import HeaderRightProjectList from "@/components/project/headerProjectList"; import { Headers } from "@/constants/Headers"; import { router, Stack } from "expo-router"; import { StatusBar } from 'expo-status-bar'; @@ -28,6 +29,12 @@ export default function RootLayout() { headerTitleAlign: 'center', headerRight: () => }} /> + { router.back() }} />, + title: 'Kegiatan', + headerTitleAlign: 'center', + headerRight: () => + }} /> diff --git a/app/(application)/banner/[id].tsx b/app/(application)/banner/[id].tsx new file mode 100644 index 0000000..5ef4ef7 --- /dev/null +++ b/app/(application)/banner/[id].tsx @@ -0,0 +1,73 @@ +import AlertKonfirmasi from "@/components/alertKonfirmasi" +import ButtonBackHeader from "@/components/buttonBackHeader" +import { ButtonForm } from "@/components/buttonForm" +import { InputForm } from "@/components/inputForm" +import Styles from "@/constants/Styles" +import { Entypo } 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 EditBanner() { + const [selectedImage, setSelectedImage] = useState(undefined) + + const pickImageAsync = async () => { + let result = await ImagePicker.launchImageLibraryAsync({ + mediaTypes: ['images'], + allowsEditing: false, + quality: 1, + }); + + if (!result.canceled) { + setSelectedImage(result.assets[0].uri); + } else { + alert('Tidak ada gambar yang dipilih'); + } + }; + + return ( + + { router.back() }} />, + headerTitle: 'Edit Banner', + headerTitleAlign: 'center', + }} + /> + + + + { + selectedImage != undefined ? ( + + + + ) : ( + + + + Mohon unggah gambar dalam resolusi 1535 x 450 piksel untuk memastikan + + + ) + } + + + { + AlertKonfirmasi({ + title: 'Konfirmasi', + desc: 'Apakah anda yakin ingin mengubah data?', + onPress: () => { + ToastAndroid.show('Berhasil mengubah data', ToastAndroid.SHORT) + router.push('/banner') + } + }) + }} /> + + + + ) +} \ No newline at end of file diff --git a/app/(application)/banner/create.tsx b/app/(application)/banner/create.tsx new file mode 100644 index 0000000..54c4293 --- /dev/null +++ b/app/(application)/banner/create.tsx @@ -0,0 +1,73 @@ +import AlertKonfirmasi from "@/components/alertKonfirmasi"; +import ButtonBackHeader from "@/components/buttonBackHeader"; +import { ButtonForm } from "@/components/buttonForm"; +import { InputForm } from "@/components/inputForm"; +import Styles from "@/constants/Styles"; +import { Entypo } 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 CreateBanner() { + const [selectedImage, setSelectedImage] = useState(undefined) + + const pickImageAsync = async () => { + let result = await ImagePicker.launchImageLibraryAsync({ + mediaTypes: ['images'], + allowsEditing: false, + quality: 1, + }); + + if (!result.canceled) { + setSelectedImage(result.assets[0].uri); + } else { + alert('Tidak ada gambar yang dipilih'); + } + }; + + return ( + + { router.back() }} />, + headerTitle: 'Tambah Banner', + headerTitleAlign: 'center', + }} + /> + + + + { + selectedImage != undefined ? ( + + + + ) : ( + + + + Mohon unggah gambar dalam resolusi 1535 x 450 piksel untuk memastikan + + + ) + } + + + { + AlertKonfirmasi({ + title: 'Konfirmasi', + desc: 'Apakah anda yakin ingin menambahkan data?', + onPress: () => { + ToastAndroid.show('Berhasil menambahkan data', ToastAndroid.SHORT) + router.push('/banner') + } + }) + }} /> + + + + ) +} \ No newline at end of file diff --git a/app/(application)/banner/index.tsx b/app/(application)/banner/index.tsx new file mode 100644 index 0000000..27bf918 --- /dev/null +++ b/app/(application)/banner/index.tsx @@ -0,0 +1,98 @@ +import AlertKonfirmasi from "@/components/alertKonfirmasi" +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 Styles from "@/constants/Styles" +import { Ionicons, MaterialCommunityIcons } from "@expo/vector-icons" +import { router, Stack } from "expo-router" +import { useState } from "react" +import { Image, SafeAreaView, ScrollView, ToastAndroid, View } from "react-native" + +export default function BannerList() { + const [isModal, setModal] = useState(false) + + return ( + + { router.back() }} />, + headerTitle: 'Banner', + headerTitleAlign: 'center', + headerRight: () => + }} + /> + + + + { setModal(true) }} + borderType="all" + icon={ + + } + title="Banner 1" + /> + { setModal(true) }} + borderType="all" + icon={ + + } + title="Banner 2" + /> + { setModal(true) }} + borderType="all" + icon={ + + } + title="Banner 3" + /> + + + + + + } + title="Edit" + onPress={() => { + setModal(false) + router.push('/banner/784') + }} + /> + } + title="Lihat File" + onPress={() => { }} + /> + } + title="Hapus" + onPress={() => { + AlertKonfirmasi({ + title: 'Konfirmasi', + desc: 'Apakah anda yakin ingin menghapus data?', + onPress: () => { + setModal(false) + ToastAndroid.show('Berhasil menghapus data', ToastAndroid.SHORT) + } + }) + }} + /> + + + + ) +} \ No newline at end of file diff --git a/app/(application)/feature.tsx b/app/(application)/feature.tsx index 234c193..0979781 100644 --- a/app/(application)/feature.tsx +++ b/app/(application)/feature.tsx @@ -18,7 +18,7 @@ export default function Feature() { } text="Divisi" /> - } text="Kegiatan" /> + } text="Kegiatan" onPress={() => { router.push('/project?status=0') }} /> } text="Pengumuman" onPress={() => { router.push('/announcement') }} /> } text="Diskusi" onPress={() => { router.push('/discussion?active=true') }} /> @@ -29,7 +29,7 @@ export default function Feature() { } text="Tema" onPress={() => { }} /> - } text="Banner" /> + } text="Banner" onPress={() => { router.push('/banner') }} /> diff --git a/app/(application)/project/[id]/index.tsx b/app/(application)/project/[id]/index.tsx new file mode 100644 index 0000000..480f22c --- /dev/null +++ b/app/(application)/project/[id]/index.tsx @@ -0,0 +1,29 @@ +import ButtonBackHeader from "@/components/buttonBackHeader"; +import HeaderRightProjectDetail from "@/components/project/headerProjectDetail"; +import SectionProgress from "@/components/sectionProgress"; +import SectionTanggalTugas from "@/components/sectionTanggalTugas"; +import Styles from "@/constants/Styles"; +import { router, Stack, useLocalSearchParams } from "expo-router"; +import { SafeAreaView, ScrollView, Text, View } from "react-native"; + +export default function DetailProject() { + const { id } = useLocalSearchParams() + return ( + + { router.back() }} />, + headerTitle: 'Judul Kegiatan', + headerTitleAlign: 'center', + headerRight: () => , + }} + /> + + + + + + + + ) +} \ No newline at end of file diff --git a/app/(application)/project/create.tsx b/app/(application)/project/create.tsx new file mode 100644 index 0000000..e3c6f91 --- /dev/null +++ b/app/(application)/project/create.tsx @@ -0,0 +1,47 @@ +import AlertKonfirmasi from "@/components/alertKonfirmasi"; +import ButtonBackHeader from "@/components/buttonBackHeader"; +import { ButtonForm } from "@/components/buttonForm"; +import ButtonSelect from "@/components/buttonSelect"; +import { InputForm } from "@/components/inputForm"; +import SelectForm from "@/components/selectForm"; +import Styles from "@/constants/Styles"; +import { router, Stack } from "expo-router"; +import { useState } from "react"; +import { SafeAreaView, ScrollView, Text, ToastAndroid, View } from "react-native"; + +export default function CreateProject() { + const [chooseGroup, setChooseGroup] = useState({ val: '', label: '' }) + + return ( + + { router.back() }} />, + headerTitle: 'Tambah Kegiatan', + headerTitleAlign: 'center', + }} + /> + + + { }} /> + + + + + { + AlertKonfirmasi({ + title: 'Konfirmasi', + desc: 'Apakah anda yakin ingin menambahkan data?', + onPress: () => { + ToastAndroid.show('Berhasil menambahkan data', ToastAndroid.SHORT) + router.push('/project?status=0') + } + }) + }} /> + + + + ) +} \ No newline at end of file diff --git a/app/(application)/project/index.tsx b/app/(application)/project/index.tsx new file mode 100644 index 0000000..96b0939 --- /dev/null +++ b/app/(application)/project/index.tsx @@ -0,0 +1,138 @@ +import BorderBottomItem from "@/components/borderBottomItem"; +import ButtonTab from "@/components/buttonTab"; +import InputSearch from "@/components/inputSearch"; +import LabelStatus from "@/components/labelStatus"; +import PaperGridContent from "@/components/paperGridContent"; +import ProgressBar from "@/components/progressBar"; +import { ColorsStatus } from "@/constants/ColorsStatus"; +import Styles from "@/constants/Styles"; +import { AntDesign, Ionicons, MaterialCommunityIcons } from "@expo/vector-icons"; +import { router, useLocalSearchParams } from "expo-router"; +import { useState } from "react"; +import { Pressable, SafeAreaView, ScrollView, Text, View } from "react-native"; + +export default function ListProject() { + const { status } = useLocalSearchParams<{ status: string }>() + const [isList, setList] = useState(false) + + return ( + + + + + { router.push('/project?status=0') }} + label="Segera" + icon={} + n={4} /> + { router.push('/project?status=1') }} + label="Dikerjakan" + icon={} + n={4} /> + { router.push('/project?status=2') }} + label="Selesai" + icon={} + n={4} /> + { router.push('/project?status=3') }} + label="Batal" + icon={} + n={4} /> + + + + { setList(!isList) }}> + + + + + Filter : Dinas + + { + isList + ? + + { }} + borderType="bottom" + icon={ + + + + } + title="Pembangunan Jembatan" + /> + { }} + borderType="bottom" + icon={ + + + + } + title="Pembangunan Jembatan" + /> + { }} + borderType="bottom" + icon={ + + + + } + title="Pembangunan Jembatan" + /> + { }} + borderType="bottom" + icon={ + + + + } + title="Pembangunan Jembatan" + /> + + : + + + { router.push('/project/234') }} content="page" title="Pembangunan Jembatan" headerColor="primary"> + + + 13 Februari 2025 + + + + + + + 13 Februari 2025 + + + + + + + 13 Februari 2025 + + + + + + } + + + + + ) +} \ No newline at end of file diff --git a/assets/images/bg.png b/assets/images/bg.png new file mode 100644 index 0000000..252f4ea Binary files /dev/null and b/assets/images/bg.png differ diff --git a/components/banner/headerBannerList.tsx b/components/banner/headerBannerList.tsx new file mode 100644 index 0000000..9035e50 --- /dev/null +++ b/components/banner/headerBannerList.tsx @@ -0,0 +1,29 @@ +import { useState } from "react"; +import ButtonMenuHeader from "../buttonMenuHeader"; +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"; + +export default function HeaderRightBannerList() { + const [isVisible, setVisible] = useState(false) + return ( + <> + { setVisible(true) }} /> + + + } + title="Tambah Banner" + onPress={() => { + setVisible(false) + router.push('/banner/create') + }} + /> + + + + ) +} \ No newline at end of file diff --git a/components/buttonTab.tsx b/components/buttonTab.tsx index 26dbf8e..1fa079c 100644 --- a/components/buttonTab.tsx +++ b/components/buttonTab.tsx @@ -15,7 +15,7 @@ type Props = { export default function ButtonTab({ active, value, onPress, label, n, icon }: Props) { return ( - { onPress() }}> + { onPress() }}> {icon} {label} diff --git a/components/home/fiturHome.tsx b/components/home/fiturHome.tsx index a2012d8..b64503a 100644 --- a/components/home/fiturHome.tsx +++ b/components/home/fiturHome.tsx @@ -11,7 +11,7 @@ export default function FiturHome() { Fitur } text="Divisi" /> - } text="Kegiatan" /> + } text="Kegiatan" onPress={() => { router.push('/project?status=0') }} /> } text="Pengumuman" onPress={() => { router.push('/announcement') }} /> } text="Semua" onPress={() => { router.push('/feature') }} /> diff --git a/components/inputForm.tsx b/components/inputForm.tsx index 48e0151..837b49f 100644 --- a/components/inputForm.tsx +++ b/components/inputForm.tsx @@ -1,5 +1,5 @@ import Styles from "@/constants/Styles"; -import { View, TextInput, Text } from "react-native"; +import { View, TextInput, Text, Dimensions } from "react-native"; type Props = { label?: string; @@ -13,10 +13,12 @@ type Props = { required?: boolean; type: 'default' | 'visible-password' | 'numeric' round?: boolean + width?: number }; -export function InputForm({ label, placeholder, onChange, info, error, errorText, required, itemLeft, itemRight, type, round }: Props) { +export function InputForm({ label, placeholder, onChange, info, error, errorText, required, itemLeft, itemRight, type, round, width }: Props) { + const lebar = Dimensions.get("window").width; if (itemLeft != undefined || itemRight != undefined) { return ( @@ -35,6 +37,7 @@ export function InputForm({ label, placeholder, onChange, info, error, errorText placeholder={placeholder} keyboardType={type} onChangeText={onChange} + style={{ width: width && lebar * width / 100 }} /> {error && ({errorText})} diff --git a/components/inputSearch.tsx b/components/inputSearch.tsx index da7872b..135cfbd 100644 --- a/components/inputSearch.tsx +++ b/components/inputSearch.tsx @@ -1,7 +1,7 @@ import { Feather } from "@expo/vector-icons"; import { InputForm } from "./inputForm"; -export default function InputSearch({ onChange }: { onChange?: (val: string) => void }) { +export default function InputSearch({ onChange, width }: { onChange?: (val: string) => void, width?: number }) { return ( round itemLeft={} onChange={onChange} + width={width} /> ) } \ No newline at end of file diff --git a/components/modalFilter.tsx b/components/modalFilter.tsx index cc05fb8..2c34e0b 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' | 'member' | 'discussion' + page: 'position' | 'member' | 'discussion' | 'project' } export default function ModalFilter({ open, close, page }: Props) { @@ -34,7 +34,10 @@ export default function ModalFilter({ open, close, page }: Props) { { close(false) - router.push(`/${page}?active=true`) + page == 'project' ? + router.push(`/${page}?status=0`) + : + router.push(`/${page}?active=true`) }} /> diff --git a/components/paperGridContent.tsx b/components/paperGridContent.tsx index 5f64490..d13d242 100644 --- a/components/paperGridContent.tsx +++ b/components/paperGridContent.tsx @@ -1,23 +1,26 @@ import { ColorsStatus } from "@/constants/ColorsStatus"; import Styles from "@/constants/Styles"; -import { Text, View } from "react-native"; -import ProgressBar from "./progressBar"; +import { Pressable, Text, View } from "react-native"; type Props = { content: 'carousel' | 'page'; children: React.ReactNode; title: string headerColor: 'primary' | 'warning' + onPress?: () => void }; -export default function PaperGridContent({ content, children, title, headerColor }: Props) { +export default function PaperGridContent({ content, children, title, headerColor, onPress }: Props) { return ( - - - {title} + + + + {title} + + + {children} + - - {children} - - + + ) } \ No newline at end of file diff --git a/components/progressBar.tsx b/components/progressBar.tsx index e8e1d42..de13dbb 100644 --- a/components/progressBar.tsx +++ b/components/progressBar.tsx @@ -2,7 +2,12 @@ import Styles from "@/constants/Styles"; import { useEffect, useState } from "react"; import { Animated, Text, View } from "react-native"; -export default function ProgressBar() { + +type Props = { + margin?: number +} + +export default function ProgressBar({ margin }: Props) { const [progress, setProgress] = useState(new Animated.Value(0)); @@ -16,7 +21,7 @@ export default function ProgressBar() { }, []); return ( - + ) diff --git a/components/project/headerProjectDetail.tsx b/components/project/headerProjectDetail.tsx new file mode 100644 index 0000000..816fdfe --- /dev/null +++ b/components/project/headerProjectDetail.tsx @@ -0,0 +1,66 @@ +import { useState } from "react" +import ButtonMenuHeader from "../buttonMenuHeader" +import DrawerBottom from "../drawerBottom" +import { View } from "react-native" +import Styles from "@/constants/Styles" +import MenuItemRow from "../menuItemRow" +import { AntDesign, MaterialCommunityIcons, MaterialIcons } from "@expo/vector-icons" + +type Props = { + id: string | string[] +} + +export default function HeaderRightProjectDetail({ id }: Props) { + const [isVisible, setVisible] = useState(false) + + return ( + <> + { setVisible(true) }} /> + + + } + title="Tambah Tugas" + onPress={() => { + + }} + /> + } + title="Tambah File" + onPress={() => { + + }} + /> + + } + title="Tambah Anggota" + onPress={() => { + setVisible(false) + // router.push(`/discussion/member/${id}`) + }} + /> + + + + } + title="Edit" + onPress={() => { + setVisible(false) + // router.push(`/discussion/edit/${id}`) + }} + /> + } + title="Batal" + onPress={() => { + + }} + /> + + + + ) +} \ No newline at end of file diff --git a/components/project/headerProjectList.tsx b/components/project/headerProjectList.tsx new file mode 100644 index 0000000..1bf7fc2 --- /dev/null +++ b/components/project/headerProjectList.tsx @@ -0,0 +1,40 @@ +import { useState } from "react" +import ButtonMenuHeader from "../buttonMenuHeader" +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 ModalFilter from "../modalFilter" + +export default function HeaderRightProjectList() { + const [isVisible, setVisible] = useState(false) + const [isFilter, setFilter] = useState(false) + return ( + <> + { setVisible(true) }} /> + + + } + title="Tambah Kegiatan" + onPress={() => { + setVisible(false) + router.push('/project/create') + }} + /> + } + title="Filter" + onPress={() => { + setVisible(false) + setFilter(true) + }} + /> + + + { setFilter(false) }} open={isFilter} page="project" /> + + ) +} \ No newline at end of file diff --git a/components/sectionProgress.tsx b/components/sectionProgress.tsx new file mode 100644 index 0000000..ed17cd2 --- /dev/null +++ b/components/sectionProgress.tsx @@ -0,0 +1,23 @@ +import { ColorsStatus } from "@/constants/ColorsStatus"; +import Styles from "@/constants/Styles"; +import { AntDesign } from "@expo/vector-icons"; +import { Text, View } from "react-native"; +import ProgressBar from "./progressBar"; + +type Props = { + text: string +} + +export default function SectionProgress({ text }: Props) { + return ( + + + + + + {text} + + + + ) +} \ No newline at end of file diff --git a/components/sectionTanggalTugas.tsx b/components/sectionTanggalTugas.tsx new file mode 100644 index 0000000..ec8de2f --- /dev/null +++ b/components/sectionTanggalTugas.tsx @@ -0,0 +1,13 @@ +import Styles from "@/constants/Styles"; +import { Text, View } from "react-native"; + +export default function SectionTanggalTugas() { + return ( + + Tanggal Dan Tugas + + + + + ) +} \ No newline at end of file diff --git a/constants/Styles.ts b/constants/Styles.ts index b7dc302..f89b03d 100644 --- a/constants/Styles.ts +++ b/constants/Styles.ts @@ -217,6 +217,7 @@ const Styles = StyleSheet.create({ shadowRadius: 3, elevation: 10, borderRadius: 15, + marginBottom:15 }, wrapGridCaraousel: { width: '80%', @@ -247,6 +248,7 @@ const Styles = StyleSheet.create({ backgroundColor: '#ccc', borderRadius: 10, margin: 10, + width:'90%' }, contentBar: { height: 20, @@ -312,6 +314,11 @@ const Styles = StyleSheet.create({ height: 100, borderRadius: 100 }, + imgListBanner: { + width: 100, + height: 50, + borderRadius: 5 + }, iconContent: { padding: 10, borderRadius: 100,