updd: announcement
Deskripsi: - edit pengumuman - delete pengumuman No Issues
This commit is contained in:
@@ -7,6 +7,7 @@ import { AntDesign, Entypo, MaterialIcons } from "@expo/vector-icons";
|
|||||||
import { router, Stack, useLocalSearchParams } from "expo-router";
|
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { SafeAreaView, ScrollView, Text, View } from "react-native";
|
import { SafeAreaView, ScrollView, Text, View } from "react-native";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
id: string
|
id: string
|
||||||
@@ -19,6 +20,8 @@ export default function DetailAnnouncement() {
|
|||||||
const { token, decryptToken } = useAuthSession()
|
const { token, decryptToken } = useAuthSession()
|
||||||
const [data, setData] = useState<Props>()
|
const [data, setData] = useState<Props>()
|
||||||
const [dataMember, setDataMember] = useState<any>({})
|
const [dataMember, setDataMember] = useState<any>({})
|
||||||
|
const update = useSelector((state: any) => state.announcementUpdate)
|
||||||
|
const entityUser = useSelector((state: any) => state.user)
|
||||||
|
|
||||||
async function handleLoad() {
|
async function handleLoad() {
|
||||||
try {
|
try {
|
||||||
@@ -33,7 +36,7 @@ export default function DetailAnnouncement() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
handleLoad()
|
handleLoad()
|
||||||
}, [])
|
}, [update])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SafeAreaView>
|
<SafeAreaView>
|
||||||
@@ -42,7 +45,7 @@ export default function DetailAnnouncement() {
|
|||||||
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
|
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
|
||||||
headerTitle: 'Pengumuman',
|
headerTitle: 'Pengumuman',
|
||||||
headerTitleAlign: 'center',
|
headerTitleAlign: 'center',
|
||||||
headerRight: () => <HeaderRightAnnouncementDetail id={id} />,
|
headerRight: () => entityUser.role != 'user' && entityUser.role != 'coadmin' ? <HeaderRightAnnouncementDetail id={id} /> : <></>,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<ScrollView>
|
<ScrollView>
|
||||||
@@ -66,7 +69,7 @@ export default function DetailAnnouncement() {
|
|||||||
{
|
{
|
||||||
dataMember[v].map((item: any, x: any) => {
|
dataMember[v].map((item: any, x: any) => {
|
||||||
return (
|
return (
|
||||||
<View style={[Styles.rowItemsCenter]}>
|
<View key={x} style={[Styles.rowItemsCenter]}>
|
||||||
<Entypo name="dot-single" size={24} color="black" />
|
<Entypo name="dot-single" size={24} color="black" />
|
||||||
<Text style={[Styles.textDefault]}>{item.division}</Text>
|
<Text style={[Styles.textDefault]}>{item.division}</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -138,11 +138,11 @@ export default function CreateAnnouncement() {
|
|||||||
{
|
{
|
||||||
divisionMember.map((item: { name: any; Division: any }, index: any) => {
|
divisionMember.map((item: { name: any; Division: any }, index: any) => {
|
||||||
return (
|
return (
|
||||||
<View>
|
<View key={index}>
|
||||||
<Text style={[Styles.textDefaultSemiBold]}>{item.name}</Text>
|
<Text style={[Styles.textDefaultSemiBold]}>{item.name}</Text>
|
||||||
{
|
{
|
||||||
item.Division.map((division: any) => (
|
item.Division.map((division: any, i: any) => (
|
||||||
<View style={[Styles.rowItemsCenter, Styles.mv05]}>
|
<View key={i} style={[Styles.rowItemsCenter, Styles.mv05]}>
|
||||||
<Entypo name="dot-single" size={24} color="black" />
|
<Entypo name="dot-single" size={24} color="black" />
|
||||||
<Text style={[Styles.textDefault]}>{division.name}</Text>
|
<Text style={[Styles.textDefault]}>{division.name}</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -1,46 +1,218 @@
|
|||||||
import AlertKonfirmasi from "@/components/alertKonfirmasi"
|
import ButtonBackHeader from "@/components/buttonBackHeader";
|
||||||
import ButtonBackHeader from "@/components/buttonBackHeader"
|
import ButtonSaveHeader from "@/components/buttonSaveHeader";
|
||||||
import { ButtonForm } from "@/components/buttonForm"
|
import ButtonSelect from "@/components/buttonSelect";
|
||||||
import ButtonSaveHeader from "@/components/buttonSaveHeader"
|
import { InputForm } from "@/components/inputForm";
|
||||||
import ButtonSelect from "@/components/buttonSelect"
|
import ModalSelectMultiple from "@/components/modalSelectMultiple";
|
||||||
import { InputForm } from "@/components/inputForm"
|
import Styles from "@/constants/Styles";
|
||||||
import Styles from "@/constants/Styles"
|
import { setUpdateAnnouncement } from "@/lib/announcementUpdate";
|
||||||
import { router, Stack } from "expo-router"
|
import { apiEditAnnouncement, apiGetAnnouncementOne } from "@/lib/api";
|
||||||
import { SafeAreaView, ScrollView, ToastAndroid, View } from "react-native"
|
import { useAuthSession } from "@/providers/AuthProvider";
|
||||||
|
import { Entypo } from "@expo/vector-icons";
|
||||||
|
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { SafeAreaView, ScrollView, Text, ToastAndroid, View } from "react-native";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
|
||||||
|
|
||||||
|
type GroupDivision = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
Division: {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
export default function EditAnnouncement() {
|
export default function EditAnnouncement() {
|
||||||
|
const { id } = useLocalSearchParams<{ id: string }>();
|
||||||
|
const dispatch = useDispatch()
|
||||||
|
const update = useSelector((state: any) => state.announcementUpdate)
|
||||||
|
const { token, decryptToken } = useAuthSession();
|
||||||
|
const [modalDivisi, setModalDivisi] = useState(false);
|
||||||
|
const [disableBtn, setDisableBtn] = useState(true);
|
||||||
|
const [dataMember, setDataMember] = useState<any>([]);
|
||||||
|
const [dataForm, setDataForm] = useState({
|
||||||
|
title: "",
|
||||||
|
desc: "",
|
||||||
|
});
|
||||||
|
const [error, setError] = useState({
|
||||||
|
title: false,
|
||||||
|
desc: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
async function handleLoad() {
|
||||||
|
try {
|
||||||
|
const hasil = await decryptToken(String(token?.current));
|
||||||
|
const response = await apiGetAnnouncementOne({ id: id, user: hasil });
|
||||||
|
setDataForm(response.data);
|
||||||
|
|
||||||
|
const arrNew: GroupDivision[] = []
|
||||||
|
const coba = Object.keys(response.member).map((v: any, i: any) => {
|
||||||
|
const newObject = {
|
||||||
|
"id": response.member[v][0].idGroup,
|
||||||
|
"name": v,
|
||||||
|
"Division": response.member[v]
|
||||||
|
}
|
||||||
|
|
||||||
|
response.member[v].map((v: any, i: any) => {
|
||||||
|
newObject["Division"][i] = {
|
||||||
|
"id": v.idDivision,
|
||||||
|
"name": v.division
|
||||||
|
}
|
||||||
|
})
|
||||||
|
arrNew.push(newObject)
|
||||||
|
})
|
||||||
|
setDataMember(arrNew);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
handleLoad();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
function validationForm(cat: string, val: any) {
|
||||||
|
if (cat == "title") {
|
||||||
|
setDataForm({ ...dataForm, title: val });
|
||||||
|
if (val == "" || val == "null") {
|
||||||
|
setError({ ...error, title: true });
|
||||||
|
} else {
|
||||||
|
setError({ ...error, title: false });
|
||||||
|
}
|
||||||
|
} else if (cat == "desc") {
|
||||||
|
setDataForm({ ...dataForm, desc: val });
|
||||||
|
if (val == "" || val == "null") {
|
||||||
|
setError({ ...error, desc: true });
|
||||||
|
} else {
|
||||||
|
setError({ ...error, desc: false });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkForm() {
|
||||||
|
if (
|
||||||
|
Object.values(error).some((v) => v == true) ||
|
||||||
|
Object.values(dataForm).some((v) => v == "")
|
||||||
|
) {
|
||||||
|
setDisableBtn(true);
|
||||||
|
} else {
|
||||||
|
setDisableBtn(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
checkForm();
|
||||||
|
}, [error, dataForm]);
|
||||||
|
|
||||||
|
async function handleEdit() {
|
||||||
|
try {
|
||||||
|
const hasil = await decryptToken(String(token?.current))
|
||||||
|
const response = await apiEditAnnouncement({
|
||||||
|
...dataForm, user: hasil, groups: dataMember,
|
||||||
|
}, id);
|
||||||
|
if (response.success) {
|
||||||
|
dispatch(setUpdateAnnouncement(!update))
|
||||||
|
ToastAndroid.show("Berhasil mengubah data", ToastAndroid.SHORT);
|
||||||
|
router.back();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SafeAreaView>
|
<SafeAreaView>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
options={{
|
options={{
|
||||||
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
|
headerLeft: () => (
|
||||||
headerTitle: 'Edit Pengumuman',
|
<ButtonBackHeader
|
||||||
headerTitleAlign: 'center',
|
onPress={() => {
|
||||||
headerRight: () => <ButtonSaveHeader category="update" onPress={() => {
|
router.back();
|
||||||
ToastAndroid.show('Berhasil mengubah data', ToastAndroid.SHORT)
|
}}
|
||||||
router.push('/announcement')
|
/>
|
||||||
}} />
|
),
|
||||||
|
headerTitle: "Edit Pengumuman",
|
||||||
|
headerTitleAlign: "center",
|
||||||
|
headerRight: () => (
|
||||||
|
<ButtonSaveHeader
|
||||||
|
disable={disableBtn}
|
||||||
|
category="update"
|
||||||
|
onPress={() => {
|
||||||
|
dataMember.length == 0
|
||||||
|
? ToastAndroid.show("Anda belum memilih divisi", ToastAndroid.SHORT)
|
||||||
|
: handleEdit();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<ScrollView>
|
<ScrollView>
|
||||||
<View style={[Styles.p15, Styles.mb100]}>
|
<View style={[Styles.p15, Styles.mb100]}>
|
||||||
<InputForm label="Judul" type="default" placeholder="Judul Pengumuman" required />
|
<InputForm
|
||||||
<InputForm label="Pengumuman" type="default" placeholder="Deskripsi Pengumuman" required />
|
label="Judul"
|
||||||
<ButtonSelect value="Pilih divisi penerima pengumuman" />
|
type="default"
|
||||||
{/* <ButtonForm
|
placeholder="Judul Pengumuman"
|
||||||
text="SIMPAN"
|
required
|
||||||
|
error={error.title}
|
||||||
|
errorText="Judul harus diisi"
|
||||||
|
onChange={(val) => validationForm("title", val)}
|
||||||
|
value={dataForm.title}
|
||||||
|
/>
|
||||||
|
<InputForm
|
||||||
|
label="Pengumuman"
|
||||||
|
type="default"
|
||||||
|
placeholder="Deskripsi Pengumuman"
|
||||||
|
required
|
||||||
|
error={error.desc}
|
||||||
|
errorText="Pengumuman harus diisi"
|
||||||
|
onChange={(val) => validationForm("desc", val)}
|
||||||
|
value={dataForm.desc}
|
||||||
|
/>
|
||||||
|
<ButtonSelect
|
||||||
|
value="Pilih divisi penerima pengumuman"
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
AlertKonfirmasi({
|
setModalDivisi(true)
|
||||||
title: 'Konfirmasi',
|
}}
|
||||||
desc: 'Apakah anda yakin ingin mengubah data?',
|
/>
|
||||||
onPress: () => {
|
{
|
||||||
ToastAndroid.show('Berhasil mengubah data', ToastAndroid.SHORT)
|
dataMember.length > 0
|
||||||
router.push('/announcement')
|
&&
|
||||||
}
|
<View style={[Styles.borderAll, Styles.round10, Styles.p10]}>
|
||||||
})
|
{
|
||||||
}} /> */}
|
dataMember.map((item: { name: any; Division: any }, index: any) => {
|
||||||
|
return (
|
||||||
|
<View key={index}>
|
||||||
|
<Text style={[Styles.textDefaultSemiBold]}>{item.name}</Text>
|
||||||
|
{
|
||||||
|
item.Division.map((division: any, i: any) => (
|
||||||
|
<View key={i} style={[Styles.rowItemsCenter, Styles.mv05]}>
|
||||||
|
<Entypo name="dot-single" size={24} color="black" />
|
||||||
|
<Text style={[Styles.textDefault]}>{division.name}</Text>
|
||||||
|
</View>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</View>
|
||||||
|
}
|
||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
|
<ModalSelectMultiple
|
||||||
|
choose="dinas"
|
||||||
|
title="Pilih Divisi"
|
||||||
|
category="choose-division"
|
||||||
|
open={modalDivisi}
|
||||||
|
close={setModalDivisi}
|
||||||
|
onSelect={(val) => {
|
||||||
|
setDataMember(val)
|
||||||
|
setModalDivisi(false)
|
||||||
|
}}
|
||||||
|
value={dataMember}
|
||||||
|
/>
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
@@ -1,18 +1,44 @@
|
|||||||
import Styles from "@/constants/Styles"
|
import Styles from "@/constants/Styles"
|
||||||
|
import { setUpdateAnnouncement } from "@/lib/announcementUpdate"
|
||||||
|
import { apiDeleteAnnouncement } from "@/lib/api"
|
||||||
|
import { useAuthSession } from "@/providers/AuthProvider"
|
||||||
import { Ionicons, MaterialCommunityIcons } from "@expo/vector-icons"
|
import { Ionicons, MaterialCommunityIcons } from "@expo/vector-icons"
|
||||||
import { router } from "expo-router"
|
import { router } from "expo-router"
|
||||||
import { useState } from "react"
|
import { useState } from "react"
|
||||||
import { ToastAndroid, View } from "react-native"
|
import { ToastAndroid, View } from "react-native"
|
||||||
|
import { useDispatch, useSelector } from "react-redux"
|
||||||
import AlertKonfirmasi from "../alertKonfirmasi"
|
import AlertKonfirmasi from "../alertKonfirmasi"
|
||||||
import ButtonMenuHeader from "../buttonMenuHeader"
|
import ButtonMenuHeader from "../buttonMenuHeader"
|
||||||
import DrawerBottom from "../drawerBottom"
|
import DrawerBottom from "../drawerBottom"
|
||||||
import MenuItemRow from "../menuItemRow"
|
import MenuItemRow from "../menuItemRow"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
id: string | string[]
|
id: string
|
||||||
}
|
}
|
||||||
export default function HeaderRightAnnouncementDetail({ id }: Props) {
|
export default function HeaderRightAnnouncementDetail({ id }: Props) {
|
||||||
|
const { token, decryptToken } = useAuthSession()
|
||||||
const [isVisible, setVisible] = useState(false)
|
const [isVisible, setVisible] = useState(false)
|
||||||
|
const update = useSelector((state: any) => state.announcementUpdate)
|
||||||
|
const dispatch = useDispatch()
|
||||||
|
|
||||||
|
|
||||||
|
async function handleDelete() {
|
||||||
|
try {
|
||||||
|
const hasil = await decryptToken(String(token?.current))
|
||||||
|
const response = await apiDeleteAnnouncement({ user: hasil }, id)
|
||||||
|
if (response.success) {
|
||||||
|
dispatch(setUpdateAnnouncement(!update))
|
||||||
|
setVisible(false)
|
||||||
|
ToastAndroid.show('Berhasil menghapus data', ToastAndroid.SHORT)
|
||||||
|
router.back()
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
} finally {
|
||||||
|
setVisible(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ButtonMenuHeader onPress={() => { setVisible(true) }} />
|
<ButtonMenuHeader onPress={() => { setVisible(true) }} />
|
||||||
@@ -34,9 +60,7 @@ export default function HeaderRightAnnouncementDetail({ id }: Props) {
|
|||||||
title: 'Konfirmasi',
|
title: 'Konfirmasi',
|
||||||
desc: 'Apakah anda yakin ingin menghapus pengumuman ini?',
|
desc: 'Apakah anda yakin ingin menghapus pengumuman ini?',
|
||||||
onPress: () => {
|
onPress: () => {
|
||||||
setVisible(false)
|
handleDelete()
|
||||||
ToastAndroid.show('Berhasil menghapus data', ToastAndroid.SHORT)
|
|
||||||
router.push('/announcement')
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ type Props = {
|
|||||||
category: 'share-division' | 'choose-division'
|
category: 'share-division' | 'choose-division'
|
||||||
choose: string
|
choose: string
|
||||||
onSelect: (value: any[]) => void
|
onSelect: (value: any[]) => void
|
||||||
|
value?: any
|
||||||
}
|
}
|
||||||
|
|
||||||
type CheckedState = {
|
type CheckedState = {
|
||||||
@@ -29,7 +30,7 @@ type GroupData = {
|
|||||||
}[];
|
}[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ModalSelectMultiple({ open, close, title, category, choose, onSelect }: Props) {
|
export default function ModalSelectMultiple({ open, close, title, category, choose, onSelect, value }: Props) {
|
||||||
const [isChoose, setChoose] = useState(choose)
|
const [isChoose, setChoose] = useState(choose)
|
||||||
const { token, decryptToken } = useAuthSession()
|
const { token, decryptToken } = useAuthSession()
|
||||||
const [data, setData] = useState<any>([])
|
const [data, setData] = useState<any>([])
|
||||||
@@ -40,6 +41,14 @@ export default function ModalSelectMultiple({ open, close, title, category, choo
|
|||||||
const hasil = await decryptToken(String(token?.current))
|
const hasil = await decryptToken(String(token?.current))
|
||||||
const response = await apiGetDivisionGroup({ user: hasil })
|
const response = await apiGetDivisionGroup({ user: hasil })
|
||||||
setData(response.data)
|
setData(response.data)
|
||||||
|
|
||||||
|
if (value.length > 0) {
|
||||||
|
const formatArray = value.reduce((result: any, obj: any) => {
|
||||||
|
result[obj.id] = obj.Division.map((item: any) => item.id);
|
||||||
|
return result;
|
||||||
|
}, {})
|
||||||
|
setChecked(formatArray)
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
}
|
}
|
||||||
@@ -112,7 +121,7 @@ export default function ModalSelectMultiple({ open, close, title, category, choo
|
|||||||
<Text style={[Styles.textDefaultSemiBold]}>Sosial Kemasyarakatan</Text>
|
<Text style={[Styles.textDefaultSemiBold]}>Sosial Kemasyarakatan</Text>
|
||||||
<AntDesign name="check" size={20} />
|
<AntDesign name="check" size={20} />
|
||||||
</Pressable>
|
</Pressable>
|
||||||
<Pressable style={[Styles.itemSelectModal]}>
|
{/* <Pressable style={[Styles.itemSelectModal]}>
|
||||||
<Text>Kaur Pemerintahan</Text>
|
<Text>Kaur Pemerintahan</Text>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
<Pressable style={[Styles.itemSelectModal]}>
|
<Pressable style={[Styles.itemSelectModal]}>
|
||||||
@@ -120,7 +129,7 @@ export default function ModalSelectMultiple({ open, close, title, category, choo
|
|||||||
</Pressable>
|
</Pressable>
|
||||||
<Pressable style={[Styles.itemSelectModal]}>
|
<Pressable style={[Styles.itemSelectModal]}>
|
||||||
<Text>PKK</Text>
|
<Text>PKK</Text>
|
||||||
</Pressable>
|
</Pressable> */}
|
||||||
</>
|
</>
|
||||||
:
|
:
|
||||||
data.map((item: any, index: number) => {
|
data.map((item: any, index: number) => {
|
||||||
|
|||||||
10
lib/api.ts
10
lib/api.ts
@@ -222,3 +222,13 @@ export const apiGetAnnouncementOne = async ({ user, id }: { user: string, id: st
|
|||||||
const response = await api.get(`mobile/announcement/${id}?user=${user}`);
|
const response = await api.get(`mobile/announcement/${id}?user=${user}`);
|
||||||
return response.data;
|
return response.data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const apiEditAnnouncement = async (data: { title: string, desc: string, user: string, groups: any[] }, id: string) => {
|
||||||
|
const response = await api.put(`/mobile/announcement/${id}`, data)
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const apiDeleteAnnouncement = async (data: { user: string }, id: string) => {
|
||||||
|
const response = await api.delete(`mobile/announcement/${id}`, { data })
|
||||||
|
return response.data
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user