upd: calendar division

Deskripsi:
- load list data event
- indicator kalender
- detail data event kalender
- mengeluarkan anggota
- menambahkan anggota
- menghapus event kalender
- riwayat event kalender
- nb : tambah dan edit kalender blm selesai karena input tgl susahh

No Issues
This commit is contained in:
amel
2025-05-23 17:35:07 +08:00
parent 3f67f65ae5
commit ee87cab5b8
12 changed files with 657 additions and 156 deletions

View File

@@ -0,0 +1,172 @@
import ButtonBackHeader from "@/components/buttonBackHeader";
import ButtonSaveHeader from "@/components/buttonSaveHeader";
import ImageUser from "@/components/imageNew";
import ImageWithLabel from "@/components/imageWithLabel";
import InputSearch from "@/components/inputSearch";
import Styles from "@/constants/Styles";
import { apiAddMemberCalendar, apiGetCalendarOne, apiGetDivisionMember } from "@/lib/api";
import { setUpdateCalendar } from "@/lib/calendarUpdate";
import { useAuthSession } from "@/providers/AuthProvider";
import { AntDesign } from "@expo/vector-icons";
import { router, Stack, useLocalSearchParams } from "expo-router";
import { useEffect, useState } from "react";
import { Pressable, SafeAreaView, ScrollView, Text, ToastAndroid, View } from "react-native";
import { useDispatch, useSelector } from "react-redux";
type Props = {
idUser: string,
name: string,
img: string
}
export default function AddMemberCalendarEvent() {
const dispatch = useDispatch()
const update = useSelector((state: any) => state.calendarUpdate)
const { token, decryptToken } = useAuthSession()
const { id, detail } = useLocalSearchParams<{ id: string, detail: string }>()
const [dataOld, setDataOld] = useState<Props[]>([])
const [data, setData] = useState<Props[]>([])
const [selectMember, setSelectMember] = useState<any[]>([])
const [search, setSearch] = useState('')
const [idCalendar, setIdCalendar] = useState('')
async function handleLoadOldMember() {
try {
const hasil = await decryptToken(String(token?.current));
const response = await apiGetCalendarOne({
user: hasil,
id: detail,
cat: 'member',
});
setDataOld(response.data)
const responseData = await apiGetCalendarOne({
user: hasil,
id: detail,
cat: 'data',
});
setIdCalendar(responseData.data.idCalendar)
} catch (error) {
console.error(error)
}
}
async function handleLoadMemberDivision() {
const hasil = await decryptToken(String(token?.current))
const responMemberDivision = await apiGetDivisionMember({ id: id, user: hasil, search: search })
setData(responMemberDivision.data)
}
useEffect(() => {
handleLoadOldMember()
}, []);
useEffect(() => {
handleLoadMemberDivision()
}, [search]);
function onChoose(val: string, label: string, img?: string) {
if (selectMember.some((i: any) => i.idUser == val)) {
setSelectMember(selectMember.filter((i: any) => i.idUser != val))
} else {
setSelectMember([...selectMember, { idUser: val, name: label, img }])
}
}
async function handleAddMember() {
try {
const hasil = await decryptToken(String(token?.current))
const response = await apiAddMemberCalendar({ id: idCalendar, data: { user: hasil, member: selectMember } })
if (response.success) {
ToastAndroid.show('Berhasil menambahkan anggota', ToastAndroid.SHORT)
dispatch(setUpdateCalendar({ ...update, member: !update.member }))
router.back()
} else {
ToastAndroid.show(response.message, ToastAndroid.SHORT)
}
} catch (error) {
console.error(error)
ToastAndroid.show('Terjadi kesalahan', ToastAndroid.SHORT)
}
}
return (
<SafeAreaView>
<Stack.Screen
options={{
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
headerTitle: 'Tambah Anggota',
headerTitleAlign: 'center',
headerRight: () => (
<ButtonSaveHeader
category="update"
disable={selectMember.length > 0 ? false : true}
onPress={() => {
handleAddMember()
}}
/>
)
}}
/>
<View style={[Styles.p15]}>
<InputSearch onChange={(val) => setSearch(val)} value={search} />
{
selectMember.length > 0
?
<View>
<ScrollView horizontal style={[Styles.mb10, Styles.pv10]}>
{
selectMember.map((item: any, index: any) => (
<ImageWithLabel
key={index}
label={item.name}
src={`https://wibu-storage.wibudev.com/api/files/${item.img}`}
onClick={() => onChoose(item.idUser, item.name, item.img)}
/>
))
}
</ScrollView>
</View>
:
<Text style={[Styles.textDefault, Styles.cGray, Styles.pv05, { textAlign: 'center' }]}>Tidak ada member yang dipilih</Text>
}
<ScrollView>
{
data.length > 0 ?
data.map((item: any, index: any) => {
const found = dataOld.some((i: any) => i.idUser == item.idUser)
return (
<Pressable
key={index}
style={[Styles.itemSelectModal]}
onPress={() => {
!found && onChoose(item.idUser, item.name, item.img)
}}
>
<View style={[Styles.rowItemsCenter]}>
<ImageUser src={`https://wibu-storage.wibudev.com/api/files/${item.img}`} border />
<View style={[Styles.ml10, { width: '80%' }]}>
<Text numberOfLines={1} ellipsizeMode="tail" style={[Styles.textDefault]}>{item.name}</Text>
{
found && <Text style={[Styles.textInformation, Styles.cGray]}>sudah menjadi anggota</Text>
}
</View>
</View>
{
selectMember.some((i: any) => i.idUser == item.id) && <AntDesign name="check" size={20} />
}
</Pressable>
)
}
)
:
<Text style={[Styles.textDefault, { textAlign: 'center' }]}>Tidak ada data</Text>
}
</ScrollView>
</View>
</SafeAreaView>
)
}

View File

@@ -3,12 +3,50 @@ import ButtonSaveHeader from "@/components/buttonSaveHeader"
import { InputForm } from "@/components/inputForm"
import SelectForm from "@/components/selectForm"
import Styles from "@/constants/Styles"
import { Stack, router } from "expo-router"
import { useState } from "react"
import { apiGetCalendarOne } from "@/lib/api"
import { useAuthSession } from "@/providers/AuthProvider"
import { Stack, router, useLocalSearchParams } from "expo-router"
import { useEffect, useState } from "react"
import { SafeAreaView, ScrollView, Text, ToastAndroid, View } from "react-native"
export default function EditEventCalendar() {
const { token, decryptToken } = useAuthSession();
const [chooseGroup, setChooseGroup] = useState({ val: '', label: '' })
const { id, detail } = useLocalSearchParams<{ id: string, detail: string }>();
const [data, setData] = useState({
id: '',
timeStart: '',
timeEnd: '',
dateStart: '',
dateEnd: '',
idCalendar: '',
status: 0,
title: '',
desc: '',
linkMeet: '',
repeatEventTyper: '',
repeatValue: 0,
})
async function handleLoad() {
try {
const hasil = await decryptToken(String(token?.current));
const response = await apiGetCalendarOne({
user: hasil,
id: detail,
cat: 'data',
});
setData(response.data);
} catch (error) {
console.error(error);
}
}
useEffect(() => {
handleLoad();
}, []);
return (
<SafeAreaView>
@@ -45,18 +83,6 @@ export default function EditEventCalendar() {
<SelectForm bg="white" label="Ulangi Acara" placeholder="Ulangi Acara" value={chooseGroup.label} required onPress={() => { }} />
<InputForm label="Jumlah Pengulangan" type="numeric" placeholder="Jumlah Pengulangan" required bg="white" />
<InputForm label="Deskripsi" type="default" placeholder="Deskripsi" bg="white" />
{/* <ButtonForm
text="SIMPAN"
onPress={() => {
AlertKonfirmasi({
title: 'Konfirmasi',
desc: 'Apakah anda yakin ingin menambahkan data?',
onPress: () => {
ToastAndroid.show('Berhasil menambahkan data', ToastAndroid.SHORT)
router.back()
}
})
}} /> */}
</View>
</ScrollView>
</SafeAreaView>

View File

@@ -1,13 +1,110 @@
import AlertKonfirmasi from "@/components/alertKonfirmasi"
import BorderBottomItem from "@/components/borderBottomItem"
import ButtonBackHeader from "@/components/buttonBackHeader"
import HeaderRightCalendarDetail from "@/components/calendar/headerCalendarDetail"
import DrawerBottom from "@/components/drawerBottom"
import ImageUser from "@/components/imageNew"
import MenuItemRow from "@/components/menuItemRow"
import Styles from "@/constants/Styles"
import { apiDeleteCalendarMember, apiGetCalendarOne } from "@/lib/api"
import { setUpdateCalendar } from "@/lib/calendarUpdate"
import { useAuthSession } from "@/providers/AuthProvider"
import { MaterialCommunityIcons } from "@expo/vector-icons"
import { router, Stack, useLocalSearchParams } from "expo-router"
import { Image, SafeAreaView, ScrollView, Text, 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;
timeStart: string;
timeEnd: string;
dateStart: string;
dateEnd: string;
idCalendar: string;
status: number;
title: string;
desc: string;
linkMeet: string;
repeatEventTyper: string;
repeatValue: number;
}
type PropsMember = {
id: string;
idUser: string;
name: string;
img: string;
email: string
}
export default function DetailEventCalendar() {
const { id, detail } = useLocalSearchParams()
const { id, detail } = useLocalSearchParams<{ id: string, detail: string }>();
const [data, setData] = useState<Props>()
const [member, setMember] = useState<PropsMember[]>([])
const { token, decryptToken } = useAuthSession();
const [memberChoose, setMemberChoose] = useState({ id: '', name: '' })
const [isModalMember, setModalMember] = useState(false)
const update = useSelector((state: any) => state.calendarUpdate)
const dispatch = useDispatch()
async function handleLoad() {
try {
const hasil = await decryptToken(String(token?.current));
const response = await apiGetCalendarOne({
user: hasil,
id: detail,
cat: 'data',
});
setData(response.data);
} catch (error) {
console.error(error);
}
}
async function handleLoadMember() {
try {
const hasil = await decryptToken(String(token?.current));
const response = await apiGetCalendarOne({
user: hasil,
id: detail,
cat: 'member',
});
setMember(response.data);
} catch (error) {
console.error(error);
}
}
useEffect(() => {
handleLoad();
}, []);
useEffect(() => {
handleLoadMember();
}, [update.member]);
async function handleDeleteUser() {
try {
const hasil = await decryptToken(String(token?.current));
const response = await apiDeleteCalendarMember({
user: hasil,
idUser: memberChoose.id,
}, String(data?.idCalendar));
if (response.success) {
dispatch(setUpdateCalendar({ ...update, member: !update.member }));
ToastAndroid.show(response.message, ToastAndroid.SHORT);
} else {
ToastAndroid.show(response.message, ToastAndroid.SHORT);
}
} catch (error) {
console.error(error);
ToastAndroid.show('Terjadi kesalahan', ToastAndroid.SHORT);
} finally {
setModalMember(false)
}
}
return (
<SafeAreaView>
@@ -16,7 +113,7 @@ export default function DetailEventCalendar() {
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
headerTitle: 'Detail Acara',
headerTitleAlign: 'center',
headerRight: () => <HeaderRightCalendarDetail id={detail} />
headerRight: () => <HeaderRightCalendarDetail id={String(data?.idCalendar)} />
}}
/>
<ScrollView>
@@ -24,65 +121,94 @@ export default function DetailEventCalendar() {
<View style={[Styles.wrapPaper, Styles.mb15]}>
<View style={Styles.rowItemsCenter}>
<MaterialCommunityIcons name="calendar-text" size={30} color="black" style={Styles.mr10} />
<Text style={[Styles.textDefault]}>Rapat Libur Lebaran</Text>
<Text style={[Styles.textDefault]}>{data?.title}</Text>
</View>
<View style={[Styles.rowItemsCenter, Styles.mt10]}>
<MaterialCommunityIcons name="calendar-month-outline" size={30} color="black" style={Styles.mr10} />
<Text style={[Styles.textDefault]}>10 Maret 2025</Text>
<Text style={[Styles.textDefault]}>{data?.dateStart}</Text>
</View>
<View style={[Styles.rowItemsCenter, Styles.mt10]}>
<MaterialCommunityIcons name="clock-outline" size={30} color="black" style={Styles.mr10} />
<Text style={[Styles.textDefault]}>07:30 | 09:45</Text>
<Text style={[Styles.textDefault]}>{data?.timeStart} | {data?.timeEnd}</Text>
</View>
<View style={[Styles.rowItemsCenter, Styles.mt10]}>
<MaterialCommunityIcons name="repeat" size={30} color="black" style={Styles.mr10} />
<Text style={[Styles.textDefault]}>Acara 1 Kali</Text>
<Text style={[Styles.textDefault]}>
{
data?.repeatEventTyper.toString() === 'once' ? 'Acara 1 Kali' :
data?.repeatEventTyper.toString() === 'daily' ? 'Setiap Hari' :
data?.repeatEventTyper.toString() === 'weekly' ? 'Mingguan' :
data?.repeatEventTyper.toString() === 'monthly' ? 'Bulanan' :
data?.repeatEventTyper.toString() === 'yearly' ? 'Tahunan' :
''
}
</Text>
</View>
<View style={[Styles.rowItemsCenter, Styles.mt10]}>
<MaterialCommunityIcons name="link-variant" size={30} color="black" style={Styles.mr10} />
<Text style={[Styles.textDefault]}>meet.com</Text>
<Text style={[Styles.textDefault]}>{data?.linkMeet ? data.linkMeet : '-'}</Text>
</View>
<View style={[Styles.rowItemsCenter, Styles.mt10]}>
<MaterialCommunityIcons name="card-text-outline" size={30} color="black" style={Styles.mr10} />
<Text style={[Styles.textDefault]}>Rapat persiapan libur panjang lebaran</Text>
<Text style={[Styles.textDefault]}>{data?.desc}</Text>
</View>
</View>
<View style={[Styles.mb15]}>
<View style={[Styles.rowSpaceBetween, Styles.mv05]}>
<Text style={[Styles.textDefaultSemiBold]}>Anggota</Text>
<Text style={[Styles.textDefault]}>Total 4 Anggota</Text>
<Text style={[Styles.textDefault]}>Total {member.length} Anggota</Text>
</View>
<View style={[Styles.wrapPaper]}>
<BorderBottomItem
borderType="bottom"
icon={<Image source={require("../../../../../../../assets/images/user.jpeg")} style={[Styles.userProfileSmall]} />}
title="Amalia Dwi"
subtitle="Dinas - Bendahara"
/>
<BorderBottomItem
borderType="bottom"
icon={<Image source={require("../../../../../../../assets/images/user.jpeg")} style={[Styles.userProfileSmall]} />}
title="Amalia Dwi"
subtitle="Dinas - Bendahara"
/>
<BorderBottomItem
borderType="bottom"
icon={<Image source={require("../../../../../../../assets/images/user.jpeg")} style={[Styles.userProfileSmall]} />}
title="Amalia Dwi"
subtitle="Dinas - Bendahara"
/>
<BorderBottomItem
borderType="bottom"
icon={<Image source={require("../../../../../../../assets/images/user.jpeg")} style={[Styles.userProfileSmall]} />}
title="Amalia Dwi"
subtitle="Dinas - Bendahara"
/>
{
member.map((item, index) => (
<BorderBottomItem
key={index}
borderType="bottom"
icon={<ImageUser src={`https://wibu-storage.wibudev.com/api/files/${item.img}`} />}
title={item.name}
subtitle={item.email}
onPress={() => {
setMemberChoose({ id: item.idUser, name: item.name })
setModalMember(true)
}}
/>
))
}
</View>
</View>
</View>
</ScrollView>
<DrawerBottom animation="slide" isVisible={isModalMember} setVisible={setModalMember} title={memberChoose.name}>
<View style={Styles.rowItemsCenter}>
<MenuItemRow
icon={<MaterialCommunityIcons name="account-eye" color="black" size={25} />}
title="Lihat Profil"
onPress={() => {
setModalMember(false)
router.push(`/member/${memberChoose.id}`)
}}
/>
<MenuItemRow
icon={<MaterialCommunityIcons name="account-remove" color="black" size={25} />}
title="Keluarkan"
onPress={() => {
AlertKonfirmasi({
title: 'Konfirmasi',
desc: 'Apakah Anda yakin ingin mengeluarkan anggota?',
onPress: () => {
handleDeleteUser()
}
})
}}
/>
</View>
</DrawerBottom>
</SafeAreaView>
)
}

View File

@@ -2,11 +2,38 @@ import ButtonBackHeader from "@/components/buttonBackHeader";
import ItemHistoryEvent from "@/components/calendar/itemHistoryEvent";
import InputSearch from "@/components/inputSearch";
import Styles from "@/constants/Styles";
import { router, Stack } from "expo-router";
import { SafeAreaView, ScrollView, Text, View } from "react-native";
import { apiGetCalendarHistory } from "@/lib/api";
import { useAuthSession } from "@/providers/AuthProvider";
import { router, Stack, useLocalSearchParams } from "expo-router";
import { useEffect, useState } from "react";
import { SafeAreaView, ScrollView, View } from "react-native";
export default function CalendarHistory(){
return(
type Props = {
dateStart: Date
year:string
data: []
}
export default function CalendarHistory() {
const { id } = useLocalSearchParams<{ id: string }>();
const { token, decryptToken } = useAuthSession();
const [data, setData] = useState<Props[]>([])
const [search, setSearch] = useState('')
async function handleLoad() {
try {
const hasil = await decryptToken(String(token?.current));
const response = await apiGetCalendarHistory({ user: hasil, search: '', division: id });
setData(response.data);
} catch (error) {
console.error(error);
}
}
useEffect(() => {
handleLoad()
}, [search])
return (
<SafeAreaView>
<Stack.Screen
options={{
@@ -17,8 +44,8 @@ export default function CalendarHistory(){
/>
<ScrollView>
<View style={[Styles.p15]}>
<InputSearch />
<ItemHistoryEvent/>
<InputSearch onChange={(val) => setSearch(val)} />
<ItemHistoryEvent data={data} />
</View>
</ScrollView>
</SafeAreaView>

View File

@@ -1,63 +1,159 @@
import ButtonBackHeader from "@/components/buttonBackHeader"
import HeaderRightCalendarList from "@/components/calendar/headerCalendarList"
import ItemDateCalendar from "@/components/calendar/itemDateCalendar"
import EventItem from "@/components/eventItem"
import Styles from "@/constants/Styles"
import { router, Stack } from "expo-router"
import moment from 'moment'
import { useState } from "react"
import { SafeAreaView, ScrollView, Text, View } from "react-native"
import DateTimePicker, { CalendarComponents, CalendarDay, DateType, getDefaultStyles } from "react-native-ui-datepicker"
import ButtonBackHeader from "@/components/buttonBackHeader";
import HeaderRightCalendarList from "@/components/calendar/headerCalendarList";
import ItemDateCalendar from "@/components/calendar/itemDateCalendar";
import EventItem from "@/components/eventItem";
import Styles from "@/constants/Styles";
import { apiGetCalendarByDateDivision, apiGetIndicatorCalendar } from "@/lib/api";
import { useAuthSession } from "@/providers/AuthProvider";
import { Feather } from "@expo/vector-icons";
import dayjs from "dayjs";
import { router, Stack, useLocalSearchParams } from "expo-router";
import moment from "moment";
import { useEffect, useState } from "react";
import { Pressable, SafeAreaView, ScrollView, Text, View } from "react-native";
import Datepicker, {
CalendarComponents,
CalendarDay
} from "react-native-ui-datepicker";
import { useDispatch, useSelector } from "react-redux";
type Props = {
id: string;
idCalendar: string;
timeStart: string;
timeEnd: string;
dateStart: string;
dateEnd: string;
status: number;
title: string;
desc: string;
user_name: string;
};
export default function CalendarDivision() {
const defaultStyles = getDefaultStyles()
const [selected, setSelected] = useState<DateType>(new Date());
const listDate = ['2025-03-19', '2025-03-22']
const [selected, setSelected] = useState<any>(new Date());
const [data, setData] = useState<Props[]>([]);
const { token, decryptToken } = useAuthSession();
const { id } = useLocalSearchParams<{ id: string }>();
const [dataIndicator, setDataIndicator] = useState<any>([]);
const [month, setMonth] = useState<number>(new Date().getMonth());
const update = useSelector((state: any) => state.calendarUpdate)
async function handleLoad() {
try {
const hasil = await decryptToken(String(token?.current));
const response = await apiGetCalendarByDateDivision({
user: hasil,
date: dayjs(selected).format("YYYY-MM-DD"),
division: id,
});
setData(response.data);
} catch (error) {
console.error(error);
}
}
async function handleLoadIndicator() {
try {
const newDate = new Date(selected?.getFullYear(), month, 1);
const hasil = await decryptToken(String(token?.current));
const response = await apiGetIndicatorCalendar({
user: hasil,
date: dayjs(newDate).format("YYYY-MM-DD"),
division: id,
});
setDataIndicator(response.data);
} catch (error) {
console.error(error);
}
}
useEffect(() => {
handleLoad();
}, [selected, update.data]);
useEffect(() => {
handleLoadIndicator();
}, [month, update.data]);
const components: CalendarComponents = {
Day: (day: CalendarDay) => {
const now = String(day.date)
const today = moment(now).format('YYYY-MM-DD');
const sign = listDate.includes(today)
const now = String(day.date);
const today = moment(now).format("YYYY-MM-DD");
const sign = dataIndicator.includes(today);
return (
<ItemDateCalendar text={day.text} isSelected={day.isSelected} isSign={sign} />
)
<ItemDateCalendar
text={day.text}
isSelected={day.isSelected}
isSign={sign}
/>
);
},
IconNext: <Pressable onPress={() => setMonth(month + 1)}>
<Feather name="chevron-right" size={20} />
</Pressable>,
IconPrev: <Pressable onPress={() => setMonth(month - 1)}>
<Feather name="chevron-left" size={20} />
</Pressable>,
};
return (
<SafeAreaView>
<Stack.Screen
options={{
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
headerTitle: 'Kalender',
headerTitleAlign: 'center',
headerRight: () => <HeaderRightCalendarList />
headerLeft: () => (
<ButtonBackHeader
onPress={() => {
router.back();
}}
/>
),
headerTitle: "Kalender",
headerTitleAlign: "center",
headerRight: () => <HeaderRightCalendarList />,
}}
/>
<ScrollView>
<View style={[Styles.p15]}>
<View style={[Styles.wrapPaper, Styles.p10]}>
<DateTimePicker
<Datepicker
components={components}
mode="single"
date={selected}
month={month}
onChange={({ date }) => setSelected(date)}
styles={{
selected: Styles.selectedDate,
}}
/>
</View>
<View style={[Styles.mb15, Styles.mt15]}>
<Text style={[Styles.textDefaultSemiBold, Styles.mb05]}>Acara</Text>
<View style={[Styles.wrapPaper]}>
<EventItem category="purple" title="Meeting Pertama" user="Amalia" jamAwal="10.00" jamAkhir="11.00" onPress={() => { router.push('./calendar/321') }} />
<EventItem category="orange" title="Meeting Pertama" user="Amalia" jamAwal="10.00" jamAkhir="11.00" onPress={() => { router.push('./calendar/321') }} />
{data.length > 0 ? (
data.map((item, index) => (
<EventItem
key={index}
category={index % 2 == 0 ? 'purple' : 'orange'}
title={item.title}
user={item.user_name}
jamAwal={item.timeStart}
jamAkhir={item.timeEnd}
onPress={() => {
router.push(`./calendar/${item.id}`);
}}
/>
))
) : (
<Text style={[Styles.textDefault, Styles.cGray, { textAlign: 'center' }]}>Tidak ada acara</Text>
)}
</View>
</View>
</View>
</ScrollView>
</SafeAreaView>
)
}
);
}

View File

@@ -9,7 +9,7 @@ import dayjs from "dayjs";
import { router, Stack, useLocalSearchParams } from "expo-router";
import { useEffect, useState } from "react";
import { SafeAreaView, ScrollView, Text, ToastAndroid, View } from "react-native";
import DateTimePicker, { DateType, getDefaultStyles } from "react-native-ui-datepicker";
import DateTimePicker, { DateType } from "react-native-ui-datepicker";
import { useDispatch, useSelector } from "react-redux";
export default function UpdateProjectTask() {
@@ -18,7 +18,6 @@ export default function UpdateProjectTask() {
const { token, decryptToken } = useAuthSession();
const { detail } = useLocalSearchParams<{ detail: string }>();
const [range, setRange] = useState<{ startDate: DateType; endDate: DateType; }>({ startDate: undefined, endDate: undefined });
const defaultStyles = getDefaultStyles()
const [month, setMonth] = useState<any>()
const [year, setYear] = useState<any>()
const [loading, setLoading] = useState(true)

View File

@@ -1,8 +1,12 @@
import Styles from "@/constants/Styles"
import { apiDeleteCalendar } from "@/lib/api"
import { setUpdateCalendar } from "@/lib/calendarUpdate"
import { useAuthSession } from "@/providers/AuthProvider"
import { Ionicons, MaterialCommunityIcons, MaterialIcons } 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"
@@ -14,6 +18,28 @@ type Props = {
export default function HeaderRightCalendarDetail({ id }: Props) {
const [isVisible, setVisible] = useState(false)
const { token, decryptToken } = useAuthSession()
const update = useSelector((state: any) => state.calendarUpdate)
const dispatch = useDispatch()
async function handleDeleteCalendar() {
try {
const hasil = await decryptToken(String(token?.current));
const response = await apiDeleteCalendar({ user: hasil }, String(id));
if (response.success) {
dispatch(setUpdateCalendar({ ...update, data: !update.data }));
ToastAndroid.show(response.message, ToastAndroid.SHORT);
router.back()
} else {
ToastAndroid.show(response.message, ToastAndroid.SHORT);
}
} catch (error) {
console.error(error);
ToastAndroid.show('Terjadi kesalahan', ToastAndroid.SHORT);
} finally {
setVisible(false)
}
}
return (
<>
@@ -25,7 +51,7 @@ export default function HeaderRightCalendarDetail({ id }: Props) {
title="Tambah Anggota"
onPress={() => {
setVisible(false)
router.push(`./${id}/add-member`)
}}
/>
<MenuItemRow
@@ -42,11 +68,9 @@ export default function HeaderRightCalendarDetail({ id }: Props) {
onPress={() => {
AlertKonfirmasi({
title: 'Konfirmasi',
desc: 'Apakah anda yakin ingin menghapus data?',
desc: 'Apakah anda yakin ingin menghapus data ini? Data ini akan mempengaruhi semua data yang terkait',
onPress: () => {
setVisible(false)
ToastAndroid.show('Berhasil menghapus data', ToastAndroid.SHORT)
router.back()
handleDeleteCalendar()
}
})
}}

View File

@@ -2,73 +2,45 @@ import { ColorsStatus } from "@/constants/ColorsStatus";
import Styles from "@/constants/Styles";
import { Text, View } from "react-native";
export default function ItemHistoryEvent() {
type Props = {
dateStart: Date
year: string
data: {
title: string
timeStart: string
timeEnd: string
}[]
}[]
export default function ItemHistoryEvent({ data }: { data: Props }) {
return (
<>
<View style={[{ flexDirection: 'row' }, Styles.mv05, ColorsStatus.lightGreen, Styles.p10, Styles.round10]}>
<View style={[Styles.mr10, Styles.ph05]}>
<Text style={[Styles.textSubtitle]}>22 Jan</Text>
<Text style={[Styles.textDefault, { textAlign: 'center' }]}>Kamis</Text>
</View>
<View>
<View style={[Styles.mb05]}>
<Text style={[Styles.textDefaultSemiBold]}>Acara 1</Text>
<Text style={[Styles.textDefault]}>07:00 | 08:00</Text>
{
data.length > 0 ? (
data.map((item, index) => (
<View key={index} style={[{ flexDirection: 'row' }, Styles.mv05, ColorsStatus.lightGreen, Styles.p10, Styles.round10]}>
<View style={[Styles.mr10, Styles.ph05]}>
<Text style={[Styles.textSubtitle]}>{String(item.dateStart)}</Text>
<Text style={[Styles.textDefault, { textAlign: 'center' }]}>{item.year}</Text>
</View>
<View style={[{ flex: 1 }]}>
{
item.data.map((item2, index2) => (
<View key={index2} style={[Styles.mb05, Styles.w80]}>
<Text style={[Styles.textDefaultSemiBold]} numberOfLines={1} ellipsizeMode="tail">{item2.title}</Text>
<Text style={[Styles.textDefault]}>{item2.timeStart} | {item2.timeEnd}</Text>
</View>
))
}
</View>
</View>
))
) : (
<View style={[Styles.p15]}>
<Text style={[Styles.textDefault]}>Tidak ada data</Text>
</View>
<View style={[Styles.mb05]}>
<Text style={[Styles.textDefaultSemiBold]}>Acara 2</Text>
<Text style={[Styles.textDefault]}>10:30 | 12:00</Text>
</View>
</View>
</View>
<View style={[{ flexDirection: 'row' }, Styles.mv05, ColorsStatus.lightGreen, Styles.p10, Styles.round10]}>
<View style={[Styles.mr10, Styles.ph05]}>
<Text style={[Styles.textSubtitle]}>15 Feb</Text>
<Text style={[Styles.textDefault, { textAlign: 'center' }]}>Senin</Text>
</View>
<View>
<View style={[Styles.mb05]}>
<Text style={[Styles.textDefaultSemiBold]}>Acara 1</Text>
<Text style={[Styles.textDefault]}>07:00 | 08:00</Text>
</View>
</View>
</View>
<View style={[{ flexDirection: 'row' }, Styles.mv05, ColorsStatus.lightGreen, Styles.p10, Styles.round10]}>
<View style={[Styles.mr10, Styles.ph05]}>
<Text style={[Styles.textSubtitle]}>15 Feb</Text>
<Text style={[Styles.textDefault, { textAlign: 'center' }]}>Senin</Text>
</View>
<View>
<View style={[Styles.mb05]}>
<Text style={[Styles.textDefaultSemiBold]}>Acara 1</Text>
<Text style={[Styles.textDefault]}>07:00 | 08:00</Text>
</View>
</View>
</View>
<View style={[{ flexDirection: 'row' }, Styles.mv05, ColorsStatus.lightGreen, Styles.p10, Styles.round10]}>
<View style={[Styles.mr10, Styles.ph05]}>
<Text style={[Styles.textSubtitle]}>15 Feb</Text>
<Text style={[Styles.textDefault, { textAlign: 'center' }]}>Senin</Text>
</View>
<View>
<View style={[Styles.mb05]}>
<Text style={[Styles.textDefaultSemiBold]}>Acara 1</Text>
<Text style={[Styles.textDefault]}>07:00 | 08:00</Text>
</View>
</View>
</View>
<View style={[{ flexDirection: 'row' }, Styles.mv05, ColorsStatus.lightGreen, Styles.p10, Styles.round10]}>
<View style={[Styles.mr10, Styles.ph05]}>
<Text style={[Styles.textSubtitle]}>15 Feb</Text>
<Text style={[Styles.textDefault, { textAlign: 'center' }]}>Senin</Text>
</View>
<View>
<View style={[Styles.mb05]}>
<Text style={[Styles.textDefaultSemiBold]}>Acara 1</Text>
<Text style={[Styles.textDefault]}>07:00 | 08:00</Text>
</View>
</View>
</View>
)
}
</>
)
}

View File

@@ -10,9 +10,9 @@ type Props = {
export default function ImageWithLabel({ src, label, onClick }: Props) {
return (
<TouchableOpacity style={[Styles.contentItemCenter, Styles.mh05]} onPress={onClick}>
<TouchableOpacity style={[Styles.contentItemCenter, Styles.mh05, { width: 70 }]} onPress={onClick}>
<ImageUser src={src} border />
<Text numberOfLines={1} ellipsizeMode="tail">{label}</Text>
<Text numberOfLines={1} ellipsizeMode="tail" style={[{ textAlign: 'center' }]}>{label}</Text>
</TouchableOpacity>
)
}

View File

@@ -394,6 +394,11 @@ export const apiUpdateStatusDivision = async ({ data, id }: { data: { user: stri
return response.data;
};
export const apiGetDivisionMember = async ({ user, id, search }: { user: string, id: string, search: string }) => {
const response = await api.get(`mobile/division/${id}/member?user=${user}&search=${search}`);
return response.data;
};
export const apiGetDiscussion = async ({ user, search, division, active }: { user: string, search: string, division: string, active?: string }) => {
const response = await api.get(`mobile/discussion?user=${user}&active=${active}&search=${search}&division=${division}`);
return response.data;
@@ -427,4 +432,39 @@ export const apiOpenCloseDiscussion = async (data: { user: string, status: numbe
export const apiCreateDiscussion = async ({ data }: { data: { user: string, desc: string, idDivision: string } }) => {
const response = await api.post(`/mobile/discussion`, data)
return response.data;
};
};
export const apiGetCalendarByDateDivision = async ({ user, date, division }: { user: string, date: string, division: string, }) => {
const response = await api.get(`mobile/calendar?user=${user}&date=${date}&division=${division}`);
return response.data;
};
export const apiGetIndicatorCalendar = async ({ user, date, division }: { user: string, date: string, division: string, }) => {
const response = await api.get(`mobile/calendar/indicator?user=${user}&date=${date}&division=${division}`);
return response.data;
};
export const apiGetCalendarOne = async ({ user, id, cat }: { user: string, id: string, cat: 'data' | 'member' }) => {
const response = await api.get(`mobile/calendar/${id}?user=${user}&cat=${cat}`);
return response.data;
};
export const apiDeleteCalendarMember = async (data: { user: string, idUser: string }, id: string) => {
const response = await api.delete(`/mobile/calendar/${id}/member`, { data })
return response.data
};
export const apiAddMemberCalendar = async ({ data, id }: { data: { user: string, member: any[] }, id: string }) => {
const response = await api.post(`/mobile/calendar/${id}/member`, data)
return response.data;
};
export const apiDeleteCalendar = async (data: { user: string }, id: string) => {
const response = await api.delete(`/mobile/calendar/${id}`, { data })
return response.data
};
export const apiGetCalendarHistory = async ({ user, search, division }: { user: string, search: string, division: string, }) => {
const response = await api.get(`mobile/calendar/history?user=${user}&search=${search}&division=${division}`);
return response.data;
};

17
lib/calendarUpdate.ts Normal file
View File

@@ -0,0 +1,17 @@
import { createSlice } from '@reduxjs/toolkit';
const calendarUpdate = createSlice({
name: 'calendarUpdate',
initialState: {
data: false,
member: false,
},
reducers: {
setUpdateCalendar: (state, action) => {
return action.payload;
},
},
});
export const { setUpdateCalendar } = calendarUpdate.actions;
export default calendarUpdate.reducer;

View File

@@ -1,6 +1,7 @@
import { configureStore } from '@reduxjs/toolkit';
import announcementUpdate from './announcementUpdate';
import bannerReducer from './bannerSlice';
import calendarUpdate from './calendarUpdate';
import discussionGeneralDetailUpdate from './discussionGeneralDetail';
import discussionUpdate from './discussionUpdate';
import divisionUpdate from './divisionUpdate';
@@ -30,6 +31,7 @@ const store = configureStore({
taskCreate: taskCreate,
divisionUpdate: divisionUpdate,
discussionUpdate: discussionUpdate,
calendarUpdate: calendarUpdate,
}
});