diff --git a/app/(application)/group/_layout.tsx b/app/(application)/group/_layout.tsx index 73a46d1..abfc52f 100644 --- a/app/(application)/group/_layout.tsx +++ b/app/(application)/group/_layout.tsx @@ -6,19 +6,55 @@ import { InputForm } from "@/components/inputForm"; import MenuItemRow from "@/components/menuItemRow"; import { Headers } from "@/constants/Headers"; import Styles from "@/constants/Styles"; +import { apiCreateGroup } from "@/lib/api"; +import { setUpdateGroup } from "@/lib/groupSlice"; +import { useAuthSession } from "@/providers/AuthProvider"; import AntDesign from "@expo/vector-icons/AntDesign"; import { router, Stack } from "expo-router"; import React, { useState } from "react"; import { ToastAndroid, View } from "react-native"; +import { useDispatch, useSelector } from "react-redux"; export default function RootLayout() { + const dispatch = useDispatch() + const update = useSelector((state: any) => state.groupUpdate) + const { token, decryptToken } = useAuthSession() const [isVisible, setVisible] = useState(false) const [isVisibleTambah, setVisibleTambah] = useState(false) + const [title, setTitle] = useState('') + const [error, setError] = useState({ + title: false, + }); - function handleTambah() { - setVisibleTambah(false) - setVisible(false) - ToastAndroid.show('Berhasil menambahkan data', ToastAndroid.SHORT) + async function handleTambah() { + try { + const hasil = await decryptToken(String(token?.current)) + const response = await apiCreateGroup({ user: hasil, name: title }) + dispatch(setUpdateGroup(!update)) + } catch (error) { + console.error(error) + } finally { + setVisibleTambah(false) + setVisible(false) + ToastAndroid.show('Berhasil menambahkan data', ToastAndroid.SHORT) + } + } + + function onCheck() { + if (Object.values(error).some((v) => v == true)) + return false + handleTambah() + } + + function validationForm(val: any, cat: 'title') { + if (cat === 'title') { + setTitle(val) + if (val == "" || val.length < 3) { + setError({ ...error, title: true }) + } else { + setError({ ...error, title: false }) + } + } } return ( @@ -51,13 +87,20 @@ export default function RootLayout() { - - + + - + { validationForm(val, 'title') }} + /> - { handleTambah() }} /> + { onCheck() }} /> diff --git a/app/(application)/group/index.tsx b/app/(application)/group/index.tsx index 1f63106..2548309 100644 --- a/app/(application)/group/index.tsx +++ b/app/(application)/group/index.tsx @@ -8,22 +8,79 @@ import InputSearch from "@/components/inputSearch"; import MenuItemRow from "@/components/menuItemRow"; import { ColorsStatus } from "@/constants/ColorsStatus"; import Styles from "@/constants/Styles"; +import { apiDeleteGroup, apiEditGroup, apiGetGroup } from "@/lib/api"; +import { setUpdateGroup } from "@/lib/groupSlice"; +import { useAuthSession } from "@/providers/AuthProvider"; import { AntDesign, Feather, MaterialCommunityIcons } from "@expo/vector-icons"; import { router, useLocalSearchParams } from "expo-router"; -import { useState } from "react"; -import { SafeAreaView, ScrollView, ToastAndroid, View } from "react-native"; +import { useEffect, useState } from "react"; +import { SafeAreaView, ScrollView, Text, ToastAndroid, View } from "react-native"; +import { useDispatch, useSelector } from "react-redux"; + +type Props = { + id: string + name: string + isActive: boolean +} export default function Index() { + const { token, decryptToken } = useAuthSession() const { active } = useLocalSearchParams<{ active?: string }>() const [isModal, setModal] = useState(false) const [isVisibleEdit, setVisibleEdit] = useState(false) + const [data, setData] = useState([]) + const [search, setSearch] = useState('') + + const [idChoose, setIdChoose] = useState('') + const [activeChoose, setActiveChoose] = useState(true) + const [titleChoose, setTitleChoose] = useState('') + + const dispatch = useDispatch() + const update = useSelector((state: any) => state.groupUpdate) + + + async function handleEdit() { + try { + const hasil = await decryptToken(String(token?.current)) + const response = await apiEditGroup({ user: hasil, name: titleChoose }, idChoose) + dispatch(setUpdateGroup(!update)) + } catch (error) { + console.error(error) + } finally { + setVisibleEdit(false) + setModal(false) + ToastAndroid.show('Berhasil mengupdate data', ToastAndroid.SHORT) + } - function handleEdit() { - setVisibleEdit(false) - setModal(false) - ToastAndroid.show('Berhasil mengupdate data', ToastAndroid.SHORT) } + async function handleDelete() { + try { + const hasil = await decryptToken(String(token?.current)) + const response = await apiDeleteGroup({ user: hasil, isActive: activeChoose }, idChoose) + dispatch(setUpdateGroup(!update)) + } catch (error) { + console.error(error) + } finally { + setModal(false) + ToastAndroid.show('Berhasil mengupdate data', ToastAndroid.SHORT) + } + } + + async function handleLoad() { + try { + const hasil = await decryptToken(String(token?.current)) + const response = await apiGetGroup({ user: hasil, active: String(active), search: search }) + setData(response.data) + } catch (error) { + console.error(error) + } + } + + useEffect(() => { + handleLoad() + }, [active, search, update]) + return ( @@ -44,90 +101,65 @@ export default function Index() { icon={} n={2} /> - + - { setModal(true) }} - borderType="all" - icon={ - - - - } - title="Adat" - /> - { setModal(true) }} - borderType="all" - icon={ - - - - } - title="Dinas" - /> - { setModal(true) }} - borderType="all" - icon={ - - - - } - title="PKK" - /> - { setModal(true) }} - borderType="all" - icon={ - - - - } - title="Karang Taruna" - /> - { setModal(true) }} - borderType="all" - icon={ - - - - } - title="Koperasi" - /> + { + data.length > 0 ? + data.map((item, index) => { + return ( + { + setIdChoose(item.id) + setActiveChoose(item.isActive) + setTitleChoose(item.name) + setModal(true) + }} + borderType="all" + icon={ + + + + } + title={item.name} + /> + ) + }) + : + Tidak ada data + } - + } - title="Non Aktifkan" + title={activeChoose ? "Non Aktifkan" : "Aktifkan"} onPress={() => { AlertKonfirmasi({ title: 'Konfirmasi', - desc: 'Apakah anda yakin ingin menonaktifkan data?', - onPress: () => { handleEdit() } + desc: activeChoose ? 'Apakah anda yakin ingin menonaktifkan data?' : 'Apakah anda yakin ingin mengaktifkan data?', + onPress: () => { handleDelete() } }) }} /> } title="Edit" - onPress={() => { + onPress={() => { setModal(false) - setVisibleEdit(true) + setVisibleEdit(true) }} /> - - + + - + { handleEdit() }} /> diff --git a/components/drawerBottom.tsx b/components/drawerBottom.tsx index bfab50e..fc5dc9d 100644 --- a/components/drawerBottom.tsx +++ b/components/drawerBottom.tsx @@ -39,7 +39,7 @@ export default function DrawerBottom({ isVisible, setVisible, title, children, a onSwipeComplete={() => setVisible(false)} swipeDirection="down" hideModalContentWhileAnimating={true} - onBackdropPress={() => { setVisible(false) }} + // onBackdropPress={() => { setVisible(true) }} style={[{ justifyContent: 'flex-end', margin: 0 }]} > diff --git a/components/inputForm.tsx b/components/inputForm.tsx index c448d00..075f017 100644 --- a/components/inputForm.tsx +++ b/components/inputForm.tsx @@ -1,5 +1,5 @@ import Styles from "@/constants/Styles"; -import { View, TextInput, Text, Dimensions } from "react-native"; +import { Dimensions, Text, TextInput, View } from "react-native"; type Props = { label?: string; @@ -15,10 +15,11 @@ type Props = { round?: boolean width?: number bg?: 'white' | 'transparent' + value?: string }; -export function InputForm({ label, placeholder, onChange, info, error, errorText, required, itemLeft, itemRight, type, round, width, bg }: Props) { +export function InputForm({ label, value, placeholder, onChange, info, error, errorText, required, itemLeft, itemRight, type, round, width, bg }: Props) { const lebar = Dimensions.get("window").width; if (itemLeft != undefined || itemRight != undefined) { @@ -35,10 +36,11 @@ export function InputForm({ label, placeholder, onChange, info, error, errorText {itemRight != undefined ? itemRight : itemLeft} {error && ({errorText})} @@ -60,6 +62,7 @@ export function InputForm({ label, placeholder, onChange, info, error, errorText ) } { + const response = await api.get(`mobile/group?user=${user}&active=${active}&search=${search}`); + return response.data; +}; + +export const apiCreateGroup = async (data: { user: string, name: string }) => { + await api.post('mobile/group', data).then(response => { + return response.data; + }) + .catch(error => { + console.error('Error:', error); + }); +}; + +export const apiEditGroup = async (data: { user: string, name: string }, id: string) => { + await api.put(`mobile/group/${id}`, data).then(response => { + return response.data; + }) + .catch(error => { + console.error('Error:', error); + }); +}; + +export const apiDeleteGroup = async (data: { user: string, isActive: boolean }, id: string) => { + await api.delete(`mobile/group/${id}`, { data }).then(response => { + return response.data; + }) + .catch(error => { + console.error('Error:', error); + }); +}; + + // export const updateEntityById = async (id: any, updatedEntity: any) => { // const response = await api.put(`/entities/${id}`, updatedEntity); // return response.data; diff --git a/lib/groupSlice.ts b/lib/groupSlice.ts new file mode 100644 index 0000000..9baa1f6 --- /dev/null +++ b/lib/groupSlice.ts @@ -0,0 +1,14 @@ +import { createSlice } from '@reduxjs/toolkit'; + +const groupUpdate = createSlice({ + name: 'groupUpdate', + initialState: false, + reducers: { + setUpdateGroup: (state, action) => { + return action.payload; + }, + }, +}); + +export const { setUpdateGroup } = groupUpdate.actions; +export default groupUpdate.reducer; \ No newline at end of file diff --git a/lib/store.ts b/lib/store.ts index 3171abc..4314df1 100644 --- a/lib/store.ts +++ b/lib/store.ts @@ -1,6 +1,7 @@ import { configureStore } from '@reduxjs/toolkit'; import bannerReducer from './bannerSlice'; import entitiesReducer from './entitiesSlice'; +import groupUpdate from './groupSlice'; import userReducer from './userSlice'; @@ -8,7 +9,8 @@ const store = configureStore({ reducer: { entities: entitiesReducer, banner: bannerReducer, - user: userReducer + user: userReducer, + groupUpdate: groupUpdate } });