upd: announcement
Deskripsi: - load all announcement - pencarian announcement - tambah announcement - get detail one announcement No Issues
This commit is contained in:
@@ -1,12 +1,40 @@
|
||||
import HeaderRightAnnouncementDetail from "@/components/announcement/headerAnnouncementDetail";
|
||||
import ButtonBackHeader from "@/components/buttonBackHeader";
|
||||
import Styles from "@/constants/Styles";
|
||||
import { AntDesign, MaterialIcons } from "@expo/vector-icons";
|
||||
import { apiGetAnnouncementOne } from "@/lib/api";
|
||||
import { useAuthSession } from "@/providers/AuthProvider";
|
||||
import { AntDesign, Entypo, MaterialIcons } from "@expo/vector-icons";
|
||||
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||
import { SafeAreaView, ScrollView, SectionList, Text, View } from "react-native";
|
||||
import { useEffect, useState } from "react";
|
||||
import { SafeAreaView, ScrollView, Text, View } from "react-native";
|
||||
|
||||
type Props = {
|
||||
id: string
|
||||
title: string
|
||||
desc: string
|
||||
}
|
||||
|
||||
export default function DetailAnnouncement() {
|
||||
const { id } = useLocalSearchParams()
|
||||
const { id } = useLocalSearchParams<{ id: string }>();
|
||||
const { token, decryptToken } = useAuthSession()
|
||||
const [data, setData] = useState<Props>()
|
||||
const [dataMember, setDataMember] = useState<any>({})
|
||||
|
||||
async function handleLoad() {
|
||||
try {
|
||||
const hasil = await decryptToken(String(token?.current))
|
||||
const response = await apiGetAnnouncementOne({ id: id, user: hasil })
|
||||
setData(response.data)
|
||||
setDataMember(response.member)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
handleLoad()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<SafeAreaView>
|
||||
<Stack.Screen
|
||||
@@ -17,39 +45,42 @@ export default function DetailAnnouncement() {
|
||||
headerRight: () => <HeaderRightAnnouncementDetail id={id} />,
|
||||
}}
|
||||
/>
|
||||
{/* <ScrollView> */}
|
||||
<View style={[Styles.p15]}>
|
||||
<View style={[Styles.wrapPaper]}>
|
||||
<View style={Styles.rowItemsCenter}>
|
||||
<MaterialIcons name="campaign" size={30} color="black" style={Styles.mr05} />
|
||||
<Text style={[Styles.textDefaultSemiBold]}>Libur Nyepi</Text>
|
||||
<ScrollView>
|
||||
<View style={[Styles.p15]}>
|
||||
<View style={[Styles.wrapPaper]}>
|
||||
<View style={Styles.rowItemsCenter}>
|
||||
<MaterialIcons name="campaign" size={30} color="black" style={Styles.mr05} />
|
||||
<Text style={[Styles.textDefaultSemiBold]}>{data?.title}</Text>
|
||||
</View>
|
||||
<View style={[Styles.rowItemsCenter, Styles.mt10]}>
|
||||
<AntDesign name="profile" size={30} color="black" style={Styles.mr05} />
|
||||
<Text style={[Styles.textDefault]}>{data?.desc}</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View style={[Styles.rowItemsCenter, Styles.mt10]}>
|
||||
<AntDesign name="profile" size={30} color="black" style={Styles.mr05} />
|
||||
<Text style={[Styles.textDefault]}>Pengumuman terkait libur nyepi</Text>
|
||||
<View style={[Styles.wrapPaper, Styles.mv15]}>
|
||||
{
|
||||
Object.keys(dataMember).map((v: any, i: any) => {
|
||||
return (
|
||||
<View key={i} style={[Styles.mb05]}>
|
||||
<Text style={[Styles.textDefaultSemiBold]}>{dataMember[v]?.[0].group}</Text>
|
||||
{
|
||||
dataMember[v].map((item: any, x: any) => {
|
||||
return (
|
||||
<View style={[Styles.rowItemsCenter]}>
|
||||
<Entypo name="dot-single" size={24} color="black" />
|
||||
<Text style={[Styles.textDefault]}>{item.division}</Text>
|
||||
</View>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
</View>
|
||||
)
|
||||
})
|
||||
}
|
||||
</View>
|
||||
</View>
|
||||
<View style={[Styles.wrapPaper, Styles.mv15, { paddingTop: 0, paddingBottom: 10 }]}>
|
||||
<SectionList
|
||||
sections={[
|
||||
{ title: 'Dinas', data: ['TU dan Umum', 'Kasi Pemerintahan', 'Pelaksana Kewilayahan'] },
|
||||
{
|
||||
title: 'Adat',
|
||||
data: [
|
||||
'PKK',
|
||||
'Karang Taruna',
|
||||
],
|
||||
},
|
||||
]}
|
||||
renderItem={({ item }) => <Text style={Styles.textDefault}>{item}</Text>}
|
||||
renderSectionHeader={({ section }) => (
|
||||
<Text style={[Styles.textDefaultSemiBold, Styles.mt10, { borderBottomWidth: 1, borderBottomColor: 'gray' }]}>{section.title}</Text>
|
||||
)}
|
||||
keyExtractor={item => `basicListEntry-${item}`}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
{/* </ScrollView> */}
|
||||
</ScrollView>
|
||||
</SafeAreaView>
|
||||
)
|
||||
}
|
||||
@@ -2,43 +2,172 @@ 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 { apiCreateAnnouncement } from "@/lib/api";
|
||||
import { useAuthSession } from "@/providers/AuthProvider";
|
||||
import { Entypo } from "@expo/vector-icons";
|
||||
import { router, Stack } from "expo-router";
|
||||
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";
|
||||
|
||||
export default function CreateAnnouncement() {
|
||||
const dispatch = useDispatch()
|
||||
const update = useSelector((state: any) => state.announcementUpdate)
|
||||
const { token, decryptToken } = useAuthSession()
|
||||
const [disableBtn, setDisableBtn] = useState(true);
|
||||
const [modalDivisi, setModalDivisi] = useState(false);
|
||||
const [divisionMember, setDivisionMember] = useState<any>([]);
|
||||
const [dataForm, setDataForm] = useState({
|
||||
title: "",
|
||||
desc: "",
|
||||
});
|
||||
const [error, setError] = useState({
|
||||
title: false,
|
||||
desc: false,
|
||||
});
|
||||
|
||||
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 handleCreate() {
|
||||
try {
|
||||
const hasil = await decryptToken(String(token?.current))
|
||||
const response = await apiCreateAnnouncement({
|
||||
data: { ...dataForm, user: hasil, groups: divisionMember },
|
||||
});
|
||||
if (response.success) {
|
||||
dispatch(setUpdateAnnouncement(!update))
|
||||
ToastAndroid.show("Berhasil menambahkan data", ToastAndroid.SHORT);
|
||||
router.back();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<SafeAreaView>
|
||||
<Stack.Screen
|
||||
options={{
|
||||
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
|
||||
headerTitle: 'Tambah Pengumuman',
|
||||
headerTitleAlign: 'center',
|
||||
headerRight: () => <ButtonSaveHeader category="create" onPress={() => {
|
||||
ToastAndroid.show('Berhasil menambah data', ToastAndroid.SHORT)
|
||||
router.push('/announcement')
|
||||
}} />
|
||||
headerLeft: () => (
|
||||
<ButtonBackHeader
|
||||
onPress={() => {
|
||||
router.back();
|
||||
}}
|
||||
/>
|
||||
),
|
||||
headerTitle: "Tambah Pengumuman",
|
||||
headerTitleAlign: "center",
|
||||
headerRight: () => (
|
||||
<ButtonSaveHeader
|
||||
disable={disableBtn}
|
||||
category="create"
|
||||
onPress={() => {
|
||||
divisionMember.length == 0
|
||||
? ToastAndroid.show("Anda belum memilih divisi", ToastAndroid.SHORT)
|
||||
: handleCreate();
|
||||
}}
|
||||
/>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<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)}
|
||||
/>
|
||||
<InputForm
|
||||
label="Pengumuman"
|
||||
type="default"
|
||||
placeholder="Deskripsi Pengumuman"
|
||||
required
|
||||
error={error.desc}
|
||||
errorText="Pengumuman harus diisi"
|
||||
onChange={(val) => validationForm("desc", val)}
|
||||
/>
|
||||
<ButtonSelect
|
||||
value="Pilih divisi penerima pengumuman"
|
||||
onPress={() => {
|
||||
AlertKonfirmasi({
|
||||
title: 'Konfirmasi',
|
||||
desc: 'Apakah anda yakin ingin menambahkan data?',
|
||||
onPress: () => {
|
||||
ToastAndroid.show('Berhasil menambahkan data', ToastAndroid.SHORT)
|
||||
router.push('/announcement')
|
||||
}
|
||||
})
|
||||
}} /> */}
|
||||
setModalDivisi(true)
|
||||
}}
|
||||
/>
|
||||
|
||||
{
|
||||
divisionMember.length > 0
|
||||
&&
|
||||
<View style={[Styles.borderAll, Styles.round10, Styles.p10]}>
|
||||
{
|
||||
divisionMember.map((item: { name: any; Division: any }, index: any) => {
|
||||
return (
|
||||
<View>
|
||||
<Text style={[Styles.textDefaultSemiBold]}>{item.name}</Text>
|
||||
{
|
||||
item.Division.map((division: any) => (
|
||||
<View 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) => {
|
||||
setDivisionMember(val)
|
||||
setModalDivisi(false)
|
||||
}}
|
||||
/>
|
||||
</SafeAreaView>
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,11 +4,43 @@ import ButtonBackHeader from "@/components/buttonBackHeader";
|
||||
import InputSearch from "@/components/inputSearch";
|
||||
import { ColorsStatus } from "@/constants/ColorsStatus";
|
||||
import Styles from "@/constants/Styles";
|
||||
import { apiGetAnnouncement } from "@/lib/api";
|
||||
import { useAuthSession } from "@/providers/AuthProvider";
|
||||
import { MaterialIcons } from "@expo/vector-icons";
|
||||
import { router, Stack } from "expo-router";
|
||||
import { SafeAreaView, ScrollView, View } from "react-native";
|
||||
import { useEffect, useState } from "react";
|
||||
import { SafeAreaView, ScrollView, Text, View } from "react-native";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
type Props = {
|
||||
id: string,
|
||||
title: string,
|
||||
desc: string,
|
||||
createdAt: string
|
||||
}
|
||||
|
||||
|
||||
export default function Announcement() {
|
||||
const { token, decryptToken } = useAuthSession()
|
||||
const [data, setData] = useState<Props[]>([])
|
||||
const [search, setSearch] = useState('')
|
||||
const entityUser = useSelector((state: any) => state.user)
|
||||
const update = useSelector((state: any) => state.announcementUpdate)
|
||||
|
||||
async function handleLoad() {
|
||||
try {
|
||||
const hasil = await decryptToken(String(token?.current))
|
||||
const response = await apiGetAnnouncement({ user: hasil, search: search })
|
||||
setData(response.data)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
handleLoad()
|
||||
}, [search, update])
|
||||
|
||||
return (
|
||||
<SafeAreaView>
|
||||
<Stack.Screen
|
||||
@@ -16,97 +48,36 @@ export default function Announcement() {
|
||||
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
|
||||
headerTitle: 'Pengumuman',
|
||||
headerTitleAlign: 'center',
|
||||
headerRight: () => <HeaderRightAnnouncementList />
|
||||
headerRight: () => entityUser.role != 'user' && entityUser.role != 'coadmin' ? <HeaderRightAnnouncementList /> : <></>
|
||||
}}
|
||||
/>
|
||||
|
||||
<ScrollView>
|
||||
<View style={[Styles.p15, Styles.mb100]}>
|
||||
<InputSearch />
|
||||
<BorderBottomItem
|
||||
onPress={() => {router.push('/announcement/7493')}}
|
||||
borderType="bottom"
|
||||
icon={
|
||||
<View style={[Styles.iconContent, ColorsStatus.lightGreen]}>
|
||||
<MaterialIcons name="campaign" size={25} color={'#384288'} />
|
||||
</View>
|
||||
}
|
||||
title="Libur Nyepi"
|
||||
desc="Pengumuman terkait libur nyepi"
|
||||
rightTopInfo="23 Mar 2025"
|
||||
/>
|
||||
<BorderBottomItem
|
||||
onPress={() => {router.push('/announcement/7493')}}
|
||||
borderType="bottom"
|
||||
icon={
|
||||
<View style={[Styles.iconContent, ColorsStatus.lightGreen]}>
|
||||
<MaterialIcons name="campaign" size={25} color={'#384288'} />
|
||||
</View>
|
||||
}
|
||||
title="Libur Nyepi"
|
||||
desc="Pengumuman terkait libur nyepi"
|
||||
rightTopInfo="23 Mar 2025"
|
||||
/>
|
||||
<BorderBottomItem
|
||||
onPress={() => {router.push('/announcement/7493')}}
|
||||
borderType="bottom"
|
||||
icon={
|
||||
<View style={[Styles.iconContent, ColorsStatus.lightGreen]}>
|
||||
<MaterialIcons name="campaign" size={25} color={'#384288'} />
|
||||
</View>
|
||||
}
|
||||
title="Libur Nyepi"
|
||||
desc="Pengumuman terkait libur nyepi"
|
||||
rightTopInfo="23 Mar 2025"
|
||||
/>
|
||||
<BorderBottomItem
|
||||
onPress={() => {router.push('/announcement/7493')}}
|
||||
borderType="bottom"
|
||||
icon={
|
||||
<View style={[Styles.iconContent, ColorsStatus.lightGreen]}>
|
||||
<MaterialIcons name="campaign" size={25} color={'#384288'} />
|
||||
</View>
|
||||
}
|
||||
title="Libur Nyepi"
|
||||
desc="Pengumuman terkait libur nyepi"
|
||||
rightTopInfo="23 Mar 2025"
|
||||
/>
|
||||
<BorderBottomItem
|
||||
onPress={() => {router.push('/announcement/7493')}}
|
||||
borderType="bottom"
|
||||
icon={
|
||||
<View style={[Styles.iconContent, ColorsStatus.lightGreen]}>
|
||||
<MaterialIcons name="campaign" size={25} color={'#384288'} />
|
||||
</View>
|
||||
}
|
||||
title="Libur Nyepi"
|
||||
desc="Pengumuman terkait libur nyepi"
|
||||
rightTopInfo="23 Mar 2025"
|
||||
/>
|
||||
<BorderBottomItem
|
||||
onPress={() => {router.push('/announcement/7493')}}
|
||||
borderType="bottom"
|
||||
icon={
|
||||
<View style={[Styles.iconContent, ColorsStatus.lightGreen]}>
|
||||
<MaterialIcons name="campaign" size={25} color={'#384288'} />
|
||||
</View>
|
||||
}
|
||||
title="Libur Nyepi"
|
||||
desc="Pengumuman terkait libur nyepi"
|
||||
rightTopInfo="23 Mar 2025"
|
||||
/>
|
||||
<BorderBottomItem
|
||||
onPress={() => {router.push('/announcement/7493')}}
|
||||
borderType="bottom"
|
||||
icon={
|
||||
<View style={[Styles.iconContent, ColorsStatus.lightGreen]}>
|
||||
<MaterialIcons name="campaign" size={25} color={'#384288'} />
|
||||
</View>
|
||||
}
|
||||
title="Libur Nyepi"
|
||||
desc="Pengumuman terkait libur nyepi"
|
||||
rightTopInfo="23 Mar 2025"
|
||||
/>
|
||||
<InputSearch onChange={setSearch} />
|
||||
{
|
||||
data.length > 0
|
||||
?
|
||||
data.map((item, index) => {
|
||||
return (
|
||||
<BorderBottomItem
|
||||
key={index}
|
||||
onPress={() => { router.push(`/announcement/${item.id}`) }}
|
||||
borderType="bottom"
|
||||
icon={
|
||||
<View style={[Styles.iconContent, ColorsStatus.lightGreen]}>
|
||||
<MaterialIcons name="campaign" size={25} color={'#384288'} />
|
||||
</View>
|
||||
}
|
||||
title={item.title}
|
||||
desc={item.desc}
|
||||
rightTopInfo={item.createdAt}
|
||||
/>
|
||||
)
|
||||
})
|
||||
:
|
||||
<Text style={[Styles.textDefault, Styles.cGray, { textAlign: 'center' }]}>Tidak ada pengumuman</Text>
|
||||
}
|
||||
</View>
|
||||
</ScrollView>
|
||||
</SafeAreaView>
|
||||
|
||||
Reference in New Issue
Block a user