updd: announcement

Deskripsi:
- edit pengumuman
- delete pengumuman

No Issues
This commit is contained in:
amel
2025-05-08 11:27:11 +08:00
parent 6cae53cbc7
commit e64f7c7e14
6 changed files with 263 additions and 45 deletions

View File

@@ -7,6 +7,7 @@ import { AntDesign, Entypo, MaterialIcons } from "@expo/vector-icons";
import { router, Stack, useLocalSearchParams } from "expo-router";
import { useEffect, useState } from "react";
import { SafeAreaView, ScrollView, Text, View } from "react-native";
import { useSelector } from "react-redux";
type Props = {
id: string
@@ -19,6 +20,8 @@ export default function DetailAnnouncement() {
const { token, decryptToken } = useAuthSession()
const [data, setData] = useState<Props>()
const [dataMember, setDataMember] = useState<any>({})
const update = useSelector((state: any) => state.announcementUpdate)
const entityUser = useSelector((state: any) => state.user)
async function handleLoad() {
try {
@@ -33,7 +36,7 @@ export default function DetailAnnouncement() {
useEffect(() => {
handleLoad()
}, [])
}, [update])
return (
<SafeAreaView>
@@ -42,7 +45,7 @@ export default function DetailAnnouncement() {
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
headerTitle: 'Pengumuman',
headerTitleAlign: 'center',
headerRight: () => <HeaderRightAnnouncementDetail id={id} />,
headerRight: () => entityUser.role != 'user' && entityUser.role != 'coadmin' ? <HeaderRightAnnouncementDetail id={id} /> : <></>,
}}
/>
<ScrollView>
@@ -66,7 +69,7 @@ export default function DetailAnnouncement() {
{
dataMember[v].map((item: any, x: any) => {
return (
<View style={[Styles.rowItemsCenter]}>
<View key={x} style={[Styles.rowItemsCenter]}>
<Entypo name="dot-single" size={24} color="black" />
<Text style={[Styles.textDefault]}>{item.division}</Text>
</View>

View File

@@ -138,11 +138,11 @@ export default function CreateAnnouncement() {
{
divisionMember.map((item: { name: any; Division: any }, index: any) => {
return (
<View>
<View key={index}>
<Text style={[Styles.textDefaultSemiBold]}>{item.name}</Text>
{
item.Division.map((division: any) => (
<View style={[Styles.rowItemsCenter, Styles.mv05]}>
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 File

@@ -1,46 +1,218 @@
import AlertKonfirmasi from "@/components/alertKonfirmasi"
import ButtonBackHeader from "@/components/buttonBackHeader"
import { ButtonForm } from "@/components/buttonForm"
import ButtonSaveHeader from "@/components/buttonSaveHeader"
import ButtonSelect from "@/components/buttonSelect"
import { InputForm } from "@/components/inputForm"
import Styles from "@/constants/Styles"
import { router, Stack } from "expo-router"
import { SafeAreaView, ScrollView, ToastAndroid, View } from "react-native"
import ButtonBackHeader from "@/components/buttonBackHeader";
import ButtonSaveHeader from "@/components/buttonSaveHeader";
import ButtonSelect from "@/components/buttonSelect";
import { InputForm } from "@/components/inputForm";
import ModalSelectMultiple from "@/components/modalSelectMultiple";
import Styles from "@/constants/Styles";
import { setUpdateAnnouncement } from "@/lib/announcementUpdate";
import { apiEditAnnouncement, apiGetAnnouncementOne } from "@/lib/api";
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() {
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 (
<SafeAreaView>
<Stack.Screen
options={{
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
headerTitle: 'Edit Pengumuman',
headerTitleAlign: 'center',
headerRight: () => <ButtonSaveHeader category="update" onPress={() => {
ToastAndroid.show('Berhasil mengubah data', ToastAndroid.SHORT)
router.push('/announcement')
}} />
headerLeft: () => (
<ButtonBackHeader
onPress={() => {
router.back();
}}
/>
),
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>
<View style={[Styles.p15, Styles.mb100]}>
<InputForm label="Judul" type="default" placeholder="Judul Pengumuman" required />
<InputForm label="Pengumuman" type="default" placeholder="Deskripsi Pengumuman" required />
<ButtonSelect value="Pilih divisi penerima pengumuman" />
{/* <ButtonForm
text="SIMPAN"
<InputForm
label="Judul"
type="default"
placeholder="Judul Pengumuman"
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={() => {
AlertKonfirmasi({
title: 'Konfirmasi',
desc: 'Apakah anda yakin ingin mengubah data?',
onPress: () => {
ToastAndroid.show('Berhasil mengubah data', ToastAndroid.SHORT)
router.push('/announcement')
}
})
}} /> */}
setModalDivisi(true)
}}
/>
{
dataMember.length > 0
&&
<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>
</ScrollView>
<ModalSelectMultiple
choose="dinas"
title="Pilih Divisi"
category="choose-division"
open={modalDivisi}
close={setModalDivisi}
onSelect={(val) => {
setDataMember(val)
setModalDivisi(false)
}}
value={dataMember}
/>
</SafeAreaView>
)
}
);
}

View File

@@ -1,18 +1,44 @@
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 { router } from "expo-router"
import { useState } from "react"
import { ToastAndroid, View } from "react-native"
import { useDispatch, useSelector } from "react-redux"
import AlertKonfirmasi from "../alertKonfirmasi"
import ButtonMenuHeader from "../buttonMenuHeader"
import DrawerBottom from "../drawerBottom"
import MenuItemRow from "../menuItemRow"
type Props = {
id: string | string[]
id: string
}
export default function HeaderRightAnnouncementDetail({ id }: Props) {
const { token, decryptToken } = useAuthSession()
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 (
<>
<ButtonMenuHeader onPress={() => { setVisible(true) }} />
@@ -34,9 +60,7 @@ export default function HeaderRightAnnouncementDetail({ id }: Props) {
title: 'Konfirmasi',
desc: 'Apakah anda yakin ingin menghapus pengumuman ini?',
onPress: () => {
setVisible(false)
ToastAndroid.show('Berhasil menghapus data', ToastAndroid.SHORT)
router.push('/announcement')
handleDelete()
}
})
}}

View File

@@ -14,6 +14,7 @@ type Props = {
category: 'share-division' | 'choose-division'
choose: string
onSelect: (value: any[]) => void
value?: any
}
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 { token, decryptToken } = useAuthSession()
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 response = await apiGetDivisionGroup({ user: hasil })
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) {
console.error(error)
}
@@ -112,7 +121,7 @@ export default function ModalSelectMultiple({ open, close, title, category, choo
<Text style={[Styles.textDefaultSemiBold]}>Sosial Kemasyarakatan</Text>
<AntDesign name="check" size={20} />
</Pressable>
<Pressable style={[Styles.itemSelectModal]}>
{/* <Pressable style={[Styles.itemSelectModal]}>
<Text>Kaur Pemerintahan</Text>
</Pressable>
<Pressable style={[Styles.itemSelectModal]}>
@@ -120,7 +129,7 @@ export default function ModalSelectMultiple({ open, close, title, category, choo
</Pressable>
<Pressable style={[Styles.itemSelectModal]}>
<Text>PKK</Text>
</Pressable>
</Pressable> */}
</>
:
data.map((item: any, index: number) => {

View File

@@ -222,3 +222,13 @@ export const apiGetAnnouncementOne = async ({ user, id }: { user: string, id: st
const response = await api.get(`mobile/announcement/${id}?user=${user}`);
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
};