upd: task division
> > Deskripsi: > - list task divisi > - pencarian task divisi > - detail task divisi > - update status tugas task divisi > - detail tugas task divisi > - edit tugas task divisi > - hapus tugas task divisi > - hapus file task divisi > - hapus member > - tambah tugas task divisi > - check file task divisi > - tambah file task divisi > - edit task divisi > - cancel task divisi > - tambah member task divisi > > No Issues
This commit is contained in:
@@ -2,60 +2,184 @@ import BorderBottomItem from "@/components/borderBottomItem";
|
|||||||
import ButtonBackHeader from "@/components/buttonBackHeader";
|
import ButtonBackHeader from "@/components/buttonBackHeader";
|
||||||
import ButtonSaveHeader from "@/components/buttonSaveHeader";
|
import ButtonSaveHeader from "@/components/buttonSaveHeader";
|
||||||
import ButtonSelect from "@/components/buttonSelect";
|
import ButtonSelect from "@/components/buttonSelect";
|
||||||
|
import DrawerBottom from "@/components/drawerBottom";
|
||||||
|
import MenuItemRow from "@/components/menuItemRow";
|
||||||
import Styles from "@/constants/Styles";
|
import Styles from "@/constants/Styles";
|
||||||
import { MaterialCommunityIcons } from "@expo/vector-icons";
|
import { apiAddFileTask, apiCheckFileTask } from "@/lib/api";
|
||||||
|
import { setUpdateTask } from "@/lib/taskUpdate";
|
||||||
|
import { useAuthSession } from "@/providers/AuthProvider";
|
||||||
|
import { Ionicons, MaterialCommunityIcons } from "@expo/vector-icons";
|
||||||
|
import * as DocumentPicker from "expo-document-picker";
|
||||||
import { router, Stack, useLocalSearchParams } from "expo-router";
|
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||||
import { SafeAreaView, ScrollView, Text, ToastAndroid, View } from "react-native";
|
import { useState } from "react";
|
||||||
|
import {
|
||||||
|
ActivityIndicator,
|
||||||
|
SafeAreaView,
|
||||||
|
ScrollView,
|
||||||
|
Text,
|
||||||
|
ToastAndroid,
|
||||||
|
View,
|
||||||
|
} from "react-native";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
|
||||||
export default function TaskDivisionAddFile() {
|
export default function TaskDivisionAddFile() {
|
||||||
const { id, detail } = useLocalSearchParams()
|
const { id, detail } = useLocalSearchParams<{ id: string; detail: string }>();
|
||||||
|
const [fileForm, setFileForm] = useState<any[]>([]);
|
||||||
|
const [listFile, setListFile] = useState<any[]>([]);
|
||||||
|
const [indexDelFile, setIndexDelFile] = useState<number>(0);
|
||||||
|
const [isModal, setModal] = useState(false);
|
||||||
|
const { token, decryptToken } = useAuthSession();
|
||||||
|
const [loadingCheck, setLoadingCheck] = useState(false);
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const update = useSelector((state: any) => state.taskUpdate);
|
||||||
|
|
||||||
|
const pickDocumentAsync = async () => {
|
||||||
|
let result = await DocumentPicker.getDocumentAsync({
|
||||||
|
type: ["*/*"],
|
||||||
|
multiple: false,
|
||||||
|
});
|
||||||
|
if (!result.canceled) {
|
||||||
|
if (result.assets?.[0].uri) {
|
||||||
|
const check = await handleCheckFile(result.assets?.[0]);
|
||||||
|
if (check) {
|
||||||
|
setFileForm([...fileForm, result.assets?.[0]]);
|
||||||
|
setListFile([...listFile, result.assets?.[0].name]);
|
||||||
|
} else {
|
||||||
|
ToastAndroid.show("File sudah ada", ToastAndroid.SHORT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function deleteFile(index: number) {
|
||||||
|
setListFile([...listFile.filter((val, i) => i !== index)]);
|
||||||
|
setFileForm([...fileForm.filter((val, i) => i !== index)]);
|
||||||
|
setModal(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleCheckFile(val: any) {
|
||||||
|
try {
|
||||||
|
setLoadingCheck(true);
|
||||||
|
const hasil = await decryptToken(String(token?.current));
|
||||||
|
const fd = new FormData();
|
||||||
|
|
||||||
|
fd.append("file", {
|
||||||
|
uri: val.uri,
|
||||||
|
type: "application/octet-stream",
|
||||||
|
name: val.name,
|
||||||
|
} as any);
|
||||||
|
|
||||||
|
fd.append(
|
||||||
|
"data",
|
||||||
|
JSON.stringify({
|
||||||
|
user: hasil,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const response = await apiCheckFileTask({ data: fd, id: detail });
|
||||||
|
return response.success;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
setLoadingCheck(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleAddFile() {
|
||||||
|
try {
|
||||||
|
const hasil = await decryptToken(String(token?.current));
|
||||||
|
const fd = new FormData();
|
||||||
|
|
||||||
|
for (let i = 0; i < fileForm.length; i++) {
|
||||||
|
fd.append(`file${i}`, {
|
||||||
|
uri: fileForm[i].uri,
|
||||||
|
type: "application/octet-stream",
|
||||||
|
name: fileForm[i].name,
|
||||||
|
} as any);
|
||||||
|
}
|
||||||
|
|
||||||
|
fd.append(
|
||||||
|
"data",
|
||||||
|
JSON.stringify({
|
||||||
|
user: hasil,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const response = await apiAddFileTask({ data: fd, id: detail });
|
||||||
|
if (response.success) {
|
||||||
|
ToastAndroid.show("Berhasil menambahkan file", ToastAndroid.SHORT);
|
||||||
|
dispatch(setUpdateTask({ ...update, file: !update.file }));
|
||||||
|
router.back();
|
||||||
|
} else {
|
||||||
|
ToastAndroid.show(response.message, ToastAndroid.SHORT);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
ToastAndroid.show("Terjadi kesalahan", ToastAndroid.SHORT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SafeAreaView>
|
<SafeAreaView>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
options={{
|
options={{
|
||||||
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
|
headerLeft: () => (
|
||||||
headerTitle: 'Tambah File',
|
<ButtonBackHeader
|
||||||
headerTitleAlign: 'center',
|
onPress={() => {
|
||||||
headerRight: () => <ButtonSaveHeader category="create" onPress={() => {
|
router.back();
|
||||||
ToastAndroid.show('Berhasil menambah data', ToastAndroid.SHORT)
|
}}
|
||||||
router.push('./')
|
/>
|
||||||
}} />
|
),
|
||||||
|
headerTitle: "Tambah File",
|
||||||
|
headerTitleAlign: "center",
|
||||||
|
headerRight: () => (
|
||||||
|
<ButtonSaveHeader
|
||||||
|
category="create"
|
||||||
|
disable={fileForm.length == 0 ? true : false}
|
||||||
|
onPress={() => { handleAddFile() }}
|
||||||
|
/>
|
||||||
|
),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<ScrollView>
|
<ScrollView>
|
||||||
<View style={[Styles.p15, Styles.mb100]}>
|
<View style={[Styles.p15, Styles.mb100]}>
|
||||||
<ButtonSelect value="Upload File" />
|
<ButtonSelect value="Upload File" onPress={pickDocumentAsync} />
|
||||||
<View style={[Styles.mb15]}>
|
{
|
||||||
<Text style={[Styles.textDefaultSemiBold, Styles.mv05]}>File</Text>
|
listFile.length > 0 && (
|
||||||
<View style={[Styles.wrapPaper]}>
|
<View style={[Styles.mb15]}>
|
||||||
<BorderBottomItem
|
<Text style={[Styles.textDefaultSemiBold, Styles.mv05]}>File</Text>
|
||||||
borderType="all"
|
<View style={[Styles.wrapPaper]}>
|
||||||
icon={<MaterialCommunityIcons name="file-outline" size={25} color="black" />}
|
{
|
||||||
title="image_pertama.jpg"
|
listFile.map((item, index) => (
|
||||||
titleWeight="normal"
|
<BorderBottomItem
|
||||||
/>
|
key={index}
|
||||||
<BorderBottomItem
|
borderType="all"
|
||||||
borderType="all"
|
icon={<MaterialCommunityIcons name="file-outline" size={25} color="black" />}
|
||||||
icon={<MaterialCommunityIcons name="file-outline" size={25} color="black" />}
|
title={item}
|
||||||
title="file_kedua.pdf"
|
titleWeight="normal"
|
||||||
titleWeight="normal"
|
onPress={() => { setIndexDelFile(index); setModal(true) }}
|
||||||
/>
|
/>
|
||||||
</View>
|
))
|
||||||
</View>
|
}
|
||||||
{/* <ButtonForm
|
</View>
|
||||||
text="SIMPAN"
|
</View>
|
||||||
onPress={() => {
|
)
|
||||||
AlertKonfirmasi({
|
}
|
||||||
title: 'Konfirmasi',
|
{
|
||||||
desc: 'Apakah anda yakin ingin menambahkan data?',
|
loadingCheck && <ActivityIndicator size="small" />
|
||||||
onPress: () => {
|
}
|
||||||
ToastAndroid.show('Berhasil menambahkan data', ToastAndroid.SHORT)
|
|
||||||
router.push('./')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}} /> */}
|
|
||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
<DrawerBottom animation="slide" isVisible={isModal} setVisible={setModal} title="Menu">
|
||||||
|
<View style={Styles.rowItemsCenter}>
|
||||||
|
<MenuItemRow
|
||||||
|
icon={<Ionicons name="trash" color="black" size={25} />}
|
||||||
|
title="Hapus"
|
||||||
|
onPress={() => { deleteFile(indexDelFile) }}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</DrawerBottom>
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,168 @@
|
|||||||
|
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 { apiAddMemberTask, apiGetDivisionMember, apiGetTaskOne } from "@/lib/api";
|
||||||
|
import { setUpdateTask } from "@/lib/taskUpdate";
|
||||||
|
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 AddMemberTask() {
|
||||||
|
const dispatch = useDispatch()
|
||||||
|
const update = useSelector((state: any) => state.projectUpdate)
|
||||||
|
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('')
|
||||||
|
|
||||||
|
async function handleLoadOldMember() {
|
||||||
|
try {
|
||||||
|
const hasil = await decryptToken(String(token?.current));
|
||||||
|
const response = await apiGetTaskOne({
|
||||||
|
user: hasil,
|
||||||
|
id: detail,
|
||||||
|
cat: 'member',
|
||||||
|
});
|
||||||
|
setDataOld(response.data)
|
||||||
|
} 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 apiAddMemberTask({ id: detail, data: { user: hasil, member: selectMember, idDivision: id } })
|
||||||
|
if (response.success) {
|
||||||
|
ToastAndroid.show('Berhasil menambahkan anggota', ToastAndroid.SHORT)
|
||||||
|
dispatch(setUpdateTask({ ...update, member: !update.member }))
|
||||||
|
router.back()
|
||||||
|
} else {
|
||||||
|
ToastAndroid.show(response.message, ToastAndroid.SHORT)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
ToastAndroid.show('Gagal menambahkan anggota', ToastAndroid.SHORT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SafeAreaView>
|
||||||
|
<Stack.Screen
|
||||||
|
options={{
|
||||||
|
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
|
||||||
|
headerTitle: 'Tambah Anggota Kegiatan',
|
||||||
|
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]}>
|
||||||
|
<Text 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.idUser) && <AntDesign name="check" size={20} />
|
||||||
|
}
|
||||||
|
</Pressable>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
:
|
||||||
|
<Text style={[Styles.textDefault, { textAlign: 'center' }]}>Tidak ada data</Text>
|
||||||
|
}
|
||||||
|
</ScrollView>
|
||||||
|
</View>
|
||||||
|
</SafeAreaView>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -2,34 +2,123 @@ import ButtonBackHeader from "@/components/buttonBackHeader";
|
|||||||
import ButtonSaveHeader from "@/components/buttonSaveHeader";
|
import ButtonSaveHeader from "@/components/buttonSaveHeader";
|
||||||
import { InputForm } from "@/components/inputForm";
|
import { InputForm } from "@/components/inputForm";
|
||||||
import Styles from "@/constants/Styles";
|
import Styles from "@/constants/Styles";
|
||||||
|
import { apiCreateTaskTugas } from "@/lib/api";
|
||||||
|
import { setUpdateTask } from "@/lib/taskUpdate";
|
||||||
|
import { useAuthSession } from "@/providers/AuthProvider";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { router, Stack, useLocalSearchParams } from "expo-router";
|
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||||
import { useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { SafeAreaView, ScrollView, Text, ToastAndroid, View } from "react-native";
|
import {
|
||||||
import DateTimePicker, { DateType, getDefaultStyles } from "react-native-ui-datepicker";
|
SafeAreaView,
|
||||||
|
ScrollView,
|
||||||
|
Text,
|
||||||
|
ToastAndroid,
|
||||||
|
View,
|
||||||
|
} from "react-native";
|
||||||
|
import DateTimePicker, { DateType } from "react-native-ui-datepicker";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
|
||||||
export default function TaskDivisionAddTask() {
|
export default function TaskDivisionAddTask() {
|
||||||
const { id, detail } = useLocalSearchParams()
|
const { token, decryptToken } = useAuthSession();
|
||||||
const [range, setRange] = useState<{ startDate: DateType; endDate: DateType; }>({ startDate: undefined, endDate: undefined });
|
const dispatch = useDispatch();
|
||||||
const defaultStyles = getDefaultStyles()
|
const update = useSelector((state: any) => state.taskUpdate);
|
||||||
|
const { id, detail } = useLocalSearchParams<{ id: string; detail: string }>();
|
||||||
|
const [disable, setDisable] = useState(true);
|
||||||
|
const [range, setRange] = useState<{
|
||||||
|
startDate: DateType;
|
||||||
|
endDate: DateType;
|
||||||
|
}>({ startDate: undefined, endDate: undefined });
|
||||||
|
const [error, setError] = useState({
|
||||||
|
startDate: false,
|
||||||
|
endDate: false,
|
||||||
|
title: false,
|
||||||
|
});
|
||||||
|
const [title, setTitle] = useState("");
|
||||||
|
|
||||||
const from = range.startDate
|
const from = range.startDate
|
||||||
? dayjs(range.startDate).format('MMM DD, YYYY')
|
? dayjs(range.startDate).format("DD-MM-YYYY")
|
||||||
: '';
|
: "";
|
||||||
const to = range.endDate ? dayjs(range.endDate).format('MMM DD, YYYY') : '';
|
const to = range.endDate ? dayjs(range.endDate).format("DD-MM-YYYY") : "";
|
||||||
|
|
||||||
|
function checkAll() {
|
||||||
|
if (
|
||||||
|
from == "" ||
|
||||||
|
to == "" ||
|
||||||
|
title == "" ||
|
||||||
|
title == "null" ||
|
||||||
|
error.startDate ||
|
||||||
|
error.endDate ||
|
||||||
|
error.title
|
||||||
|
) {
|
||||||
|
setDisable(true);
|
||||||
|
} else {
|
||||||
|
setDisable(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onValidation(cat: string, val: string) {
|
||||||
|
if (cat == "title") {
|
||||||
|
setTitle(val);
|
||||||
|
if (val == "" || val == "null") {
|
||||||
|
setError((error) => ({ ...error, title: true }));
|
||||||
|
} else {
|
||||||
|
setError((error) => ({ ...error, title: false }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
checkAll();
|
||||||
|
}, [from, to, title, error]);
|
||||||
|
|
||||||
|
async function handleCreate() {
|
||||||
|
try {
|
||||||
|
const hasil = await decryptToken(String(token?.current));
|
||||||
|
const response = await apiCreateTaskTugas({
|
||||||
|
data: {
|
||||||
|
title,
|
||||||
|
dateStart: dayjs(range.startDate).format("YYYY-MM-DD"),
|
||||||
|
dateEnd: dayjs(range.endDate).format("YYYY-MM-DD"),
|
||||||
|
user: hasil,
|
||||||
|
idDivision: id,
|
||||||
|
},
|
||||||
|
id: detail,
|
||||||
|
});
|
||||||
|
if (response.success) {
|
||||||
|
dispatch(setUpdateTask({ ...update, task: !update.task, progress: !update.progress }));
|
||||||
|
ToastAndroid.show("Berhasil menambah data", ToastAndroid.SHORT);
|
||||||
|
router.back();
|
||||||
|
} else {
|
||||||
|
ToastAndroid.show(response.message, ToastAndroid.SHORT);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
ToastAndroid.show("Gagal menambah data", ToastAndroid.SHORT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SafeAreaView>
|
<SafeAreaView>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
options={{
|
options={{
|
||||||
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
|
headerLeft: () => (
|
||||||
headerTitle: 'Tambah Tugas',
|
<ButtonBackHeader
|
||||||
headerTitleAlign: 'center',
|
onPress={() => {
|
||||||
headerRight: () => <ButtonSaveHeader category="create" onPress={() => {
|
router.back();
|
||||||
ToastAndroid.show('Berhasil menambah data', ToastAndroid.SHORT)
|
}}
|
||||||
router.push('./')
|
/>
|
||||||
}} />
|
),
|
||||||
|
headerTitle: "Tambah Tugas",
|
||||||
|
headerTitleAlign: "center",
|
||||||
|
headerRight: () => (
|
||||||
|
<ButtonSaveHeader
|
||||||
|
category="create"
|
||||||
|
disable={disable}
|
||||||
|
onPress={() => {
|
||||||
|
handleCreate();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<ScrollView>
|
<ScrollView>
|
||||||
@@ -40,43 +129,51 @@ export default function TaskDivisionAddTask() {
|
|||||||
startDate={range.startDate}
|
startDate={range.startDate}
|
||||||
endDate={range.endDate}
|
endDate={range.endDate}
|
||||||
onChange={(param) => setRange(param)}
|
onChange={(param) => setRange(param)}
|
||||||
// styles={defaultStyles}
|
|
||||||
styles={{
|
styles={{
|
||||||
selected: Styles.selectedDate,
|
selected: Styles.selectedDate,
|
||||||
selected_label:Styles.cWhite,
|
selected_label: Styles.cWhite,
|
||||||
range_fill: Styles.selectRangeDate,
|
range_fill: Styles.selectRangeDate,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
<View style={[Styles.rowSpaceBetween, Styles.mv10]}>
|
<View style={[Styles.mv10]}>
|
||||||
<View style={[{ width: '48%' }]}>
|
<View style={[Styles.rowSpaceBetween]}>
|
||||||
<Text style={[Styles.mb05]}>Tanggal Mulai <Text style={Styles.cError}>*</Text></Text>
|
<View style={[{ width: "48%" }]}>
|
||||||
<View style={[Styles.wrapPaper, Styles.p10]}>
|
<Text style={[Styles.mb05]}>
|
||||||
<Text style={{ textAlign: 'center' }}>{from}</Text>
|
Tanggal Mulai <Text style={Styles.cError}>*</Text>
|
||||||
</View>
|
</Text>
|
||||||
</View>
|
<View style={[Styles.wrapPaper, Styles.p10]}>
|
||||||
<View style={[{ width: '48%' }]}>
|
<Text style={{ textAlign: "center" }}>{from}</Text>
|
||||||
<Text style={[Styles.mb05]}>Tanggal Berakhir <Text style={Styles.cError}>*</Text></Text>
|
</View>
|
||||||
<View style={[Styles.wrapPaper, Styles.p10]}>
|
</View>
|
||||||
<Text style={{ textAlign: 'center' }}>{to}</Text>
|
<View style={[{ width: "48%" }]}>
|
||||||
|
<Text style={[Styles.mb05]}>
|
||||||
|
Tanggal Berakhir <Text style={Styles.cError}>*</Text>
|
||||||
|
</Text>
|
||||||
|
<View style={[Styles.wrapPaper, Styles.p10]}>
|
||||||
|
<Text style={{ textAlign: "center" }}>{to}</Text>
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
{
|
||||||
|
(error.endDate || error.startDate) && <Text style={[Styles.textInformation, Styles.cError, Styles.mt05]}>Tanggal tidak boleh kosong</Text>
|
||||||
|
}
|
||||||
</View>
|
</View>
|
||||||
<InputForm label="Judul Tugas" type="default" placeholder="Judul Tugas" required bg="white" />
|
<InputForm
|
||||||
{/* <ButtonForm
|
label="Judul Tugas"
|
||||||
text="SIMPAN"
|
type="default"
|
||||||
onPress={() => {
|
placeholder="Judul Tugas"
|
||||||
AlertKonfirmasi({
|
required
|
||||||
title: 'Konfirmasi',
|
bg="white"
|
||||||
desc: 'Apakah anda yakin ingin menambahkan data?',
|
value={title}
|
||||||
onPress: () => {
|
error={error.title}
|
||||||
ToastAndroid.show('Berhasil menambahkan data', ToastAndroid.SHORT)
|
errorText="Judul tidak boleh kosong"
|
||||||
router.push('./')
|
onChange={(e) => {
|
||||||
}
|
onValidation("title", e)
|
||||||
})
|
}}
|
||||||
}} /> */}
|
/>
|
||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,42 +1,106 @@
|
|||||||
import ButtonBackHeader from "@/components/buttonBackHeader"
|
import ButtonBackHeader from "@/components/buttonBackHeader";
|
||||||
import ButtonSaveHeader from "@/components/buttonSaveHeader"
|
import ButtonSaveHeader from "@/components/buttonSaveHeader";
|
||||||
import { InputForm } from "@/components/inputForm"
|
import { InputForm } from "@/components/inputForm";
|
||||||
import Styles from "@/constants/Styles"
|
import Styles from "@/constants/Styles";
|
||||||
import { router, Stack, useLocalSearchParams } from "expo-router"
|
import { apiCancelTask } from "@/lib/api";
|
||||||
import { SafeAreaView, ScrollView, ToastAndroid, View } from "react-native"
|
import { setUpdateTask } from "@/lib/taskUpdate";
|
||||||
|
import { useAuthSession } from "@/providers/AuthProvider";
|
||||||
|
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { SafeAreaView, ScrollView, ToastAndroid, View } from "react-native";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
|
||||||
export default function TaskDivisionCancel() {
|
export default function TaskDivisionCancel() {
|
||||||
const { id, detail } = useLocalSearchParams()
|
const { id, detail } = useLocalSearchParams<{ id: string; detail: string }>();
|
||||||
|
const { token, decryptToken } = useAuthSession();
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const update = useSelector((state: any) => state.projectUpdate);
|
||||||
|
const [reason, setReason] = useState("");
|
||||||
|
const [error, setError] = useState(false);
|
||||||
|
const [disable, setDisable] = useState(false);
|
||||||
|
|
||||||
|
function onValidation(val: string) {
|
||||||
|
setReason(val);
|
||||||
|
if (val == "" || val == "null") {
|
||||||
|
setError(true);
|
||||||
|
} else {
|
||||||
|
setError(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkAll() {
|
||||||
|
if (reason == "" || reason == "null" || error) {
|
||||||
|
setDisable(true);
|
||||||
|
} else {
|
||||||
|
setDisable(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
checkAll();
|
||||||
|
}, [reason, error]);
|
||||||
|
|
||||||
|
async function handleCancel() {
|
||||||
|
try {
|
||||||
|
const hasil = await decryptToken(String(token?.current));
|
||||||
|
const response = await apiCancelTask(
|
||||||
|
{
|
||||||
|
reason: reason,
|
||||||
|
user: hasil,
|
||||||
|
},
|
||||||
|
detail
|
||||||
|
);
|
||||||
|
if (response.success) {
|
||||||
|
dispatch(setUpdateTask({ ...update, data: !update.data }));
|
||||||
|
ToastAndroid.show("Berhasil membatalkan kegiatan", ToastAndroid.SHORT);
|
||||||
|
router.back();
|
||||||
|
} else {
|
||||||
|
ToastAndroid.show(response.message, ToastAndroid.SHORT);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
ToastAndroid.show("Gagal membatalkan kegiatan", ToastAndroid.SHORT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SafeAreaView>
|
<SafeAreaView>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
options={{
|
options={{
|
||||||
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
|
headerLeft: () => (
|
||||||
headerTitle: 'Pembatalan Tugas',
|
<ButtonBackHeader
|
||||||
headerTitleAlign: 'center',
|
onPress={() => {
|
||||||
headerRight: () => <ButtonSaveHeader category="cancel" onPress={() => {
|
router.back();
|
||||||
ToastAndroid.show('Berhasil mengubah data', ToastAndroid.SHORT)
|
}}
|
||||||
router.push('./')
|
/>
|
||||||
}} />
|
),
|
||||||
|
headerTitle: "Pembatalan Tugas",
|
||||||
|
headerTitleAlign: "center",
|
||||||
|
headerRight: () => (
|
||||||
|
<ButtonSaveHeader
|
||||||
|
disable={disable}
|
||||||
|
category="cancel"
|
||||||
|
onPress={() => {
|
||||||
|
handleCancel();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<ScrollView>
|
<ScrollView>
|
||||||
<View style={[Styles.p15, Styles.mb100]}>
|
<View style={[Styles.p15, Styles.mb100]}>
|
||||||
<InputForm label="Alasan Pembatalan" type="default" placeholder="Alasan Pembatalan" required bg="white" />
|
<InputForm
|
||||||
{/* <ButtonForm
|
label="Alasan Pembatalan"
|
||||||
text="SIMPAN"
|
type="default"
|
||||||
onPress={() => {
|
placeholder="Alasan Pembatalan"
|
||||||
AlertKonfirmasi({
|
required
|
||||||
title: 'Konfirmasi',
|
bg="white"
|
||||||
desc: 'Apakah anda yakin ingin membatalkan tugas? Pembatalan bersifat permanen',
|
error={error}
|
||||||
onPress: () => {
|
errorText="Alasan pembatalan harus diisi"
|
||||||
ToastAndroid.show('Berhasil mengubah data', ToastAndroid.SHORT)
|
onChange={(val) => onValidation(val)}
|
||||||
router.push('./')
|
/>
|
||||||
}
|
|
||||||
})
|
|
||||||
}} /> */}
|
|
||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,41 +2,122 @@ import ButtonBackHeader from "@/components/buttonBackHeader";
|
|||||||
import ButtonSaveHeader from "@/components/buttonSaveHeader";
|
import ButtonSaveHeader from "@/components/buttonSaveHeader";
|
||||||
import { InputForm } from "@/components/inputForm";
|
import { InputForm } from "@/components/inputForm";
|
||||||
import Styles from "@/constants/Styles";
|
import Styles from "@/constants/Styles";
|
||||||
|
import { apiEditTask, apiGetTaskOne } from "@/lib/api";
|
||||||
|
import { setUpdateTask } from "@/lib/taskUpdate";
|
||||||
|
import { useAuthSession } from "@/providers/AuthProvider";
|
||||||
import { router, Stack, useLocalSearchParams } from "expo-router";
|
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
import { SafeAreaView, ScrollView, ToastAndroid, View } from "react-native";
|
import { SafeAreaView, ScrollView, ToastAndroid, View } from "react-native";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
|
||||||
export default function TaskDivisionEdit() {
|
export default function TaskDivisionEdit() {
|
||||||
const { id, detail } = useLocalSearchParams()
|
const { id, detail } = useLocalSearchParams<{ id: string; detail: string }>();
|
||||||
|
const { token, decryptToken } = useAuthSession();
|
||||||
|
const [judul, setJudul] = useState("");
|
||||||
|
const [error, setError] = useState(false);
|
||||||
|
const [disable, setDisable] = useState(false);
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const update = useSelector((state: any) => state.taskUpdate);
|
||||||
|
|
||||||
|
async function handleLoad() {
|
||||||
|
try {
|
||||||
|
const hasil = await decryptToken(String(token?.current));
|
||||||
|
const response = await apiGetTaskOne({
|
||||||
|
user: hasil,
|
||||||
|
cat: "data",
|
||||||
|
id: detail,
|
||||||
|
});
|
||||||
|
setJudul(response.data.title);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
handleLoad();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
function onValidation(val: string) {
|
||||||
|
setJudul(val);
|
||||||
|
if (val == "" || val == "null") {
|
||||||
|
setError(true);
|
||||||
|
}else{
|
||||||
|
setError(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkAll() {
|
||||||
|
if (judul == "" || judul == "null" || error) {
|
||||||
|
setDisable(true);
|
||||||
|
} else {
|
||||||
|
setDisable(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
checkAll();
|
||||||
|
}, [judul, error]);
|
||||||
|
|
||||||
|
async function handleUpdate() {
|
||||||
|
try {
|
||||||
|
const hasil = await decryptToken(String(token?.current));
|
||||||
|
const response = await apiEditTask(
|
||||||
|
{
|
||||||
|
title: judul,
|
||||||
|
user: hasil,
|
||||||
|
},
|
||||||
|
detail
|
||||||
|
);
|
||||||
|
if (response.success) {
|
||||||
|
dispatch(setUpdateTask({ ...update, data: !update.data }));
|
||||||
|
ToastAndroid.show("Berhasil mengubah data", ToastAndroid.SHORT);
|
||||||
|
router.back();
|
||||||
|
} else {
|
||||||
|
ToastAndroid.show(response.message, ToastAndroid.SHORT);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
ToastAndroid.show("Terjadi kesalahan", ToastAndroid.SHORT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SafeAreaView>
|
<SafeAreaView>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
options={{
|
options={{
|
||||||
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
|
headerLeft: () => (
|
||||||
headerTitle: 'Edit Judul Tugas',
|
<ButtonBackHeader
|
||||||
headerTitleAlign: 'center',
|
onPress={() => {
|
||||||
headerRight: () => <ButtonSaveHeader category="update" onPress={() => {
|
router.back();
|
||||||
ToastAndroid.show('Berhasil mengubah data', ToastAndroid.SHORT)
|
}}
|
||||||
router.push('./')
|
/>
|
||||||
}} />
|
),
|
||||||
|
headerTitle: "Edit Judul",
|
||||||
|
headerTitleAlign: "center",
|
||||||
|
headerRight: () => (
|
||||||
|
<ButtonSaveHeader
|
||||||
|
category="update"
|
||||||
|
disable={disable}
|
||||||
|
onPress={() => { handleUpdate() }}
|
||||||
|
/>
|
||||||
|
),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<ScrollView>
|
<ScrollView>
|
||||||
<View style={[Styles.p15, Styles.mb100]}>
|
<View style={[Styles.p15, Styles.mb100]}>
|
||||||
<InputForm label="Judul Kegiatan" type="default" placeholder="Judul Kegiatan" required bg="white" />
|
<InputForm
|
||||||
{/* <ButtonForm
|
label="Judul Kegiatan"
|
||||||
text="SIMPAN"
|
type="default"
|
||||||
onPress={() => {
|
placeholder="Judul Kegiatan"
|
||||||
AlertKonfirmasi({
|
required
|
||||||
title: 'Konfirmasi',
|
bg="white"
|
||||||
desc: 'Apakah anda yakin ingin mengubah data?',
|
value={judul}
|
||||||
onPress: () => {
|
onChange={(val) => { onValidation(val) }}
|
||||||
ToastAndroid.show('Berhasil mengubah data', ToastAndroid.SHORT)
|
error={error}
|
||||||
router.push('./')
|
errorText="Judul Kegiatan harus diisi"
|
||||||
}
|
/>
|
||||||
})
|
|
||||||
}} /> */}
|
|
||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,54 @@
|
|||||||
import ButtonBackHeader from "@/components/buttonBackHeader";
|
import ButtonBackHeader from "@/components/buttonBackHeader";
|
||||||
|
import SectionCancel from "@/components/sectionCancel";
|
||||||
import SectionProgress from "@/components/sectionProgress";
|
import SectionProgress from "@/components/sectionProgress";
|
||||||
import HeaderRightTaskDetail from "@/components/task/headerTaskDetail";
|
import HeaderRightTaskDetail from "@/components/task/headerTaskDetail";
|
||||||
import SectionFileTask from "@/components/task/sectionFileTask";
|
import SectionFileTask from "@/components/task/sectionFileTask";
|
||||||
import SectionMemberTask from "@/components/task/sectionMemberTask";
|
import SectionMemberTask from "@/components/task/sectionMemberTask";
|
||||||
import SectionTanggalTugasTask from "@/components/task/sectionTanggalTugasTask";
|
import SectionTanggalTugasTask from "@/components/task/sectionTanggalTugasTask";
|
||||||
import Styles from "@/constants/Styles";
|
import Styles from "@/constants/Styles";
|
||||||
|
import { apiGetTaskOne } from "@/lib/api";
|
||||||
|
import { useAuthSession } from "@/providers/AuthProvider";
|
||||||
import { router, Stack, useLocalSearchParams } from "expo-router";
|
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
import { SafeAreaView, ScrollView, View } from "react-native";
|
import { SafeAreaView, ScrollView, View } from "react-native";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
id: string
|
||||||
|
title: string
|
||||||
|
desc: string
|
||||||
|
reason: string
|
||||||
|
status: number
|
||||||
|
isActive: boolean
|
||||||
|
}
|
||||||
|
|
||||||
export default function DetailTaskDivision() {
|
export default function DetailTaskDivision() {
|
||||||
const { id, detail } = useLocalSearchParams()
|
const { id, detail } = useLocalSearchParams<{ id: string, detail: string }>();
|
||||||
|
const { token, decryptToken } = useAuthSession()
|
||||||
|
const [data, setData] = useState<Props>()
|
||||||
|
const [loading, setLoading] = useState(true)
|
||||||
|
const [progress, setProgress] = useState(0)
|
||||||
|
const update = useSelector((state: any) => state.taskUpdate)
|
||||||
|
|
||||||
|
|
||||||
|
async function handleLoad() {
|
||||||
|
try {
|
||||||
|
setLoading(true)
|
||||||
|
const hasil = await decryptToken(String(token?.current))
|
||||||
|
const response = await apiGetTaskOne({ id: detail, user: hasil, cat: 'data' })
|
||||||
|
setData(response.data)
|
||||||
|
const responseProgress = await apiGetTaskOne({ id: detail, user: hasil, cat: 'progress' })
|
||||||
|
setProgress(responseProgress.data.progress)
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
} finally {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
handleLoad()
|
||||||
|
}, [update.progress, update.data])
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -17,14 +56,17 @@ export default function DetailTaskDivision() {
|
|||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
options={{
|
options={{
|
||||||
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
|
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
|
||||||
headerTitle: 'Judul Tugas Divisi',
|
headerTitle: loading ? 'Loading...' : data?.title,
|
||||||
headerTitleAlign: 'center',
|
headerTitleAlign: 'center',
|
||||||
headerRight: () => <HeaderRightTaskDetail id={detail} />,
|
headerRight: () => <HeaderRightTaskDetail id={detail} />,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<ScrollView>
|
<ScrollView>
|
||||||
<View style={[Styles.p15, Styles.mb100]}>
|
<View style={[Styles.p15, Styles.mb100]}>
|
||||||
<SectionProgress text="Kemajuan Kegiatan 50%" progress={50} />
|
{
|
||||||
|
data?.reason != null && data?.reason != "" && <SectionCancel text={data?.reason} />
|
||||||
|
}
|
||||||
|
<SectionProgress text={`Kemajuan Kegiatan ${progress}%`} progress={progress} />
|
||||||
<SectionTanggalTugasTask />
|
<SectionTanggalTugasTask />
|
||||||
<SectionFileTask />
|
<SectionFileTask />
|
||||||
<SectionMemberTask />
|
<SectionMemberTask />
|
||||||
|
|||||||
@@ -6,14 +6,51 @@ import PaperGridContent from "@/components/paperGridContent";
|
|||||||
import ProgressBar from "@/components/progressBar";
|
import ProgressBar from "@/components/progressBar";
|
||||||
import { ColorsStatus } from "@/constants/ColorsStatus";
|
import { ColorsStatus } from "@/constants/ColorsStatus";
|
||||||
import Styles from "@/constants/Styles";
|
import Styles from "@/constants/Styles";
|
||||||
import { AntDesign, Ionicons, MaterialCommunityIcons } from "@expo/vector-icons";
|
import { apiGetTask } from "@/lib/api";
|
||||||
|
import { useAuthSession } from "@/providers/AuthProvider";
|
||||||
|
import {
|
||||||
|
AntDesign,
|
||||||
|
Ionicons,
|
||||||
|
MaterialCommunityIcons,
|
||||||
|
} from "@expo/vector-icons";
|
||||||
import { router, useLocalSearchParams } from "expo-router";
|
import { router, useLocalSearchParams } from "expo-router";
|
||||||
import { useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Pressable, SafeAreaView, ScrollView, Text, View } from "react-native";
|
import { Pressable, SafeAreaView, ScrollView, Text, View } from "react-native";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
desc: string;
|
||||||
|
status: number;
|
||||||
|
progress: number;
|
||||||
|
member: number;
|
||||||
|
};
|
||||||
|
|
||||||
export default function ListTask() {
|
export default function ListTask() {
|
||||||
const { status } = useLocalSearchParams<{ status: string }>()
|
const { id, status } = useLocalSearchParams<{ id: string; status: string }>();
|
||||||
const [isList, setList] = useState(false)
|
const [isList, setList] = useState(false);
|
||||||
|
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 apiGetTask({
|
||||||
|
user: hasil,
|
||||||
|
division: id,
|
||||||
|
status,
|
||||||
|
search,
|
||||||
|
});
|
||||||
|
setData(response.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
handleLoad();
|
||||||
|
}, [status, search]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SafeAreaView>
|
<SafeAreaView>
|
||||||
@@ -23,112 +60,152 @@ export default function ListTask() {
|
|||||||
<ButtonTab
|
<ButtonTab
|
||||||
active={status}
|
active={status}
|
||||||
value="0"
|
value="0"
|
||||||
onPress={() => { router.push('./task?status=0') }}
|
onPress={() => {
|
||||||
|
router.replace("./task?status=0");
|
||||||
|
}}
|
||||||
label="Segera"
|
label="Segera"
|
||||||
icon={<MaterialCommunityIcons name="clock-alert-outline" color={status == "0" ? 'white' : 'black'} size={20} />}
|
icon={
|
||||||
n={4} />
|
<MaterialCommunityIcons
|
||||||
|
name="clock-alert-outline"
|
||||||
|
color={status == "0" ? "white" : "black"}
|
||||||
|
size={20}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
n={4}
|
||||||
|
/>
|
||||||
<ButtonTab
|
<ButtonTab
|
||||||
active={status}
|
active={status}
|
||||||
value="1"
|
value="1"
|
||||||
onPress={() => { router.push('./task?status=1') }}
|
onPress={() => {
|
||||||
|
router.replace("./task?status=1");
|
||||||
|
}}
|
||||||
label="Dikerjakan"
|
label="Dikerjakan"
|
||||||
icon={<MaterialCommunityIcons name="progress-check" color={status == "1" ? 'white' : 'black'} size={20} />}
|
icon={
|
||||||
n={4} />
|
<MaterialCommunityIcons
|
||||||
|
name="progress-check"
|
||||||
|
color={status == "1" ? "white" : "black"}
|
||||||
|
size={20}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
n={4}
|
||||||
|
/>
|
||||||
<ButtonTab
|
<ButtonTab
|
||||||
active={status}
|
active={status}
|
||||||
value="2"
|
value="2"
|
||||||
onPress={() => { router.push('./task?status=2') }}
|
onPress={() => {
|
||||||
|
router.replace("./task?status=2");
|
||||||
|
}}
|
||||||
label="Selesai"
|
label="Selesai"
|
||||||
icon={<Ionicons name="checkmark-done-circle-outline" color={status == "2" ? 'white' : 'black'} size={20} />}
|
icon={
|
||||||
n={4} />
|
<Ionicons
|
||||||
|
name="checkmark-done-circle-outline"
|
||||||
|
color={status == "2" ? "white" : "black"}
|
||||||
|
size={20}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
n={4}
|
||||||
|
/>
|
||||||
<ButtonTab
|
<ButtonTab
|
||||||
active={status}
|
active={status}
|
||||||
value="3"
|
value="3"
|
||||||
onPress={() => { router.push('./task?status=3') }}
|
onPress={() => {
|
||||||
|
router.replace("./task?status=3");
|
||||||
|
}}
|
||||||
label="Batal"
|
label="Batal"
|
||||||
icon={<AntDesign name="closecircleo" color={status == "3" ? 'white' : 'black'} size={20} />}
|
icon={
|
||||||
n={4} />
|
<AntDesign
|
||||||
|
name="closecircleo"
|
||||||
|
color={status == "3" ? "white" : "black"}
|
||||||
|
size={20}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
n={4}
|
||||||
|
/>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
<View style={[Styles.rowSpaceBetween]}>
|
<View style={[Styles.rowSpaceBetween]}>
|
||||||
<InputSearch width={68} />
|
<InputSearch width={68} onChange={setSearch} />
|
||||||
<Pressable onPress={() => { setList(!isList) }}>
|
<Pressable
|
||||||
<MaterialCommunityIcons name={isList ? 'format-list-bulleted' : 'view-grid'} color={"black"} size={30} />
|
onPress={() => {
|
||||||
|
setList(!isList);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<MaterialCommunityIcons
|
||||||
|
name={isList ? "format-list-bulleted" : "view-grid"}
|
||||||
|
color={"black"}
|
||||||
|
size={30}
|
||||||
|
/>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
</View>
|
</View>
|
||||||
{
|
{data.length > 0 ? (
|
||||||
isList
|
<></>
|
||||||
?
|
) : (
|
||||||
<View>
|
<Text
|
||||||
|
style={[
|
||||||
|
Styles.textDefault,
|
||||||
|
Styles.cGray,
|
||||||
|
{ textAlign: "center" },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
Tidak ada data
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
{isList ? (
|
||||||
|
<View>
|
||||||
|
{data.map((item, index) => (
|
||||||
<BorderBottomItem
|
<BorderBottomItem
|
||||||
onPress={() => { }}
|
key={index}
|
||||||
|
onPress={() => {
|
||||||
|
router.push(`./task/${item.id}`);
|
||||||
|
}}
|
||||||
borderType="bottom"
|
borderType="bottom"
|
||||||
icon={
|
icon={
|
||||||
<View style={[Styles.iconContent, ColorsStatus.lightGreen]}>
|
<View style={[Styles.iconContent, ColorsStatus.lightGreen]}>
|
||||||
<AntDesign name="areachart" size={25} color={'#384288'} />
|
<AntDesign name="areachart" size={25} color={"#384288"} />
|
||||||
</View>
|
</View>
|
||||||
}
|
}
|
||||||
title="Pembangunan Jembatan"
|
title={item.title}
|
||||||
/>
|
/>
|
||||||
<BorderBottomItem
|
))}
|
||||||
onPress={() => { }}
|
</View>
|
||||||
borderType="bottom"
|
) : (
|
||||||
icon={
|
<View>
|
||||||
<View style={[Styles.iconContent, ColorsStatus.lightGreen]}>
|
{data.map((item, index) => (
|
||||||
<AntDesign name="areachart" size={25} color={'#384288'} />
|
<PaperGridContent
|
||||||
</View>
|
key={index}
|
||||||
}
|
onPress={() => {
|
||||||
title="Pembangunan Jembatan"
|
router.push(`./task/${item.id}`);
|
||||||
/>
|
}}
|
||||||
<BorderBottomItem
|
content="page"
|
||||||
onPress={() => { }}
|
title={item.title}
|
||||||
borderType="bottom"
|
headerColor="primary"
|
||||||
icon={
|
>
|
||||||
<View style={[Styles.iconContent, ColorsStatus.lightGreen]}>
|
<ProgressBar category="page" value={item.progress} />
|
||||||
<AntDesign name="areachart" size={25} color={'#384288'} />
|
|
||||||
</View>
|
|
||||||
}
|
|
||||||
title="Pembangunan Jembatan"
|
|
||||||
/>
|
|
||||||
<BorderBottomItem
|
|
||||||
onPress={() => { }}
|
|
||||||
borderType="bottom"
|
|
||||||
icon={
|
|
||||||
<View style={[Styles.iconContent, ColorsStatus.lightGreen]}>
|
|
||||||
<AntDesign name="areachart" size={25} color={'#384288'} />
|
|
||||||
</View>
|
|
||||||
}
|
|
||||||
title="Pembangunan Jembatan"
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
:
|
|
||||||
|
|
||||||
<View>
|
|
||||||
<PaperGridContent onPress={() => { router.push('./task/321') }} content="page" title="Pembangunan Jembatan" headerColor="primary">
|
|
||||||
<ProgressBar category="page" value={0}/>
|
|
||||||
<View style={[Styles.rowSpaceBetween]}>
|
<View style={[Styles.rowSpaceBetween]}>
|
||||||
<Text style={[Styles.textDefault, Styles.cGray]}>13 Februari 2025</Text>
|
<Text></Text>
|
||||||
<LabelStatus size="default" category="primary" text="SEGERA" />
|
<LabelStatus
|
||||||
|
size="default"
|
||||||
|
category={
|
||||||
|
item.status === 0 ? 'primary' :
|
||||||
|
item.status === 1 ? 'warning' :
|
||||||
|
item.status === 2 ? 'success' :
|
||||||
|
item.status === 3 ? 'error' :
|
||||||
|
'primary'
|
||||||
|
}
|
||||||
|
text={
|
||||||
|
item.status === 0 ? 'SEGERA' :
|
||||||
|
item.status === 1 ? 'DIKERJAKAN' :
|
||||||
|
item.status === 2 ? 'SELESAI' :
|
||||||
|
item.status === 3 ? 'DIBATALKAN' :
|
||||||
|
'SEGERA'
|
||||||
|
}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
</PaperGridContent>
|
</PaperGridContent>
|
||||||
<PaperGridContent content="page" title="Pembangunan Jembatan" headerColor="primary">
|
))}
|
||||||
<ProgressBar category="page" value={0}/>
|
</View>
|
||||||
<View style={[Styles.rowSpaceBetween]}>
|
)}
|
||||||
<Text style={[Styles.textDefault, Styles.cGray]}>13 Februari 2025</Text>
|
|
||||||
<LabelStatus size="default" category="primary" text="SEGERA" />
|
|
||||||
</View>
|
|
||||||
</PaperGridContent>
|
|
||||||
<PaperGridContent content="page" title="Pembangunan Jembatan" headerColor="primary">
|
|
||||||
<ProgressBar category="page" value={0}/>
|
|
||||||
<View style={[Styles.rowSpaceBetween]}>
|
|
||||||
<Text style={[Styles.textDefault, Styles.cGray]}>13 Februari 2025</Text>
|
|
||||||
<LabelStatus size="default" category="primary" text="SEGERA" />
|
|
||||||
</View>
|
|
||||||
</PaperGridContent>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
}
|
|
||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,207 @@
|
|||||||
|
import ButtonBackHeader from "@/components/buttonBackHeader";
|
||||||
|
import ButtonSaveHeader from "@/components/buttonSaveHeader";
|
||||||
|
import { InputForm } from "@/components/inputForm";
|
||||||
|
import Styles from "@/constants/Styles";
|
||||||
|
import { apiEditTaskTugas, apiGetTaskTugas } from "@/lib/api";
|
||||||
|
import { setUpdateTask } from "@/lib/taskUpdate";
|
||||||
|
import { useAuthSession } from "@/providers/AuthProvider";
|
||||||
|
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 } from "react-native-ui-datepicker";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
|
||||||
|
export default function UpdateProjectTaskDivision() {
|
||||||
|
const { detail } = useLocalSearchParams<{ detail: string }>();
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const update = useSelector((state: any) => state.taskUpdate);
|
||||||
|
const { token, decryptToken } = useAuthSession();
|
||||||
|
const [range, setRange] = useState<{
|
||||||
|
startDate: DateType;
|
||||||
|
endDate: DateType;
|
||||||
|
}>({ startDate: undefined, endDate: undefined });
|
||||||
|
const [month, setMonth] = useState<any>();
|
||||||
|
const [year, setYear] = useState<any>();
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [disableBtn, setDisableBtn] = useState(false);
|
||||||
|
const [title, setTitle] = useState("");
|
||||||
|
const [error, setError] = useState({
|
||||||
|
startDate: false,
|
||||||
|
endDate: false,
|
||||||
|
title: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const from = range.startDate
|
||||||
|
? dayjs(range.startDate).format("MMM DD, YYYY")
|
||||||
|
: "";
|
||||||
|
const to = range.endDate ? dayjs(range.endDate).format("MMM DD, YYYY") : "";
|
||||||
|
|
||||||
|
async function handleLoad() {
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
const hasil = await decryptToken(String(token?.current));
|
||||||
|
const response = await apiGetTaskTugas({
|
||||||
|
user: hasil,
|
||||||
|
id: detail,
|
||||||
|
});
|
||||||
|
setTitle(response.data.title);
|
||||||
|
setRange({
|
||||||
|
startDate: new Date(response.data.dateStart),
|
||||||
|
endDate: new Date(response.data.dateEnd),
|
||||||
|
});
|
||||||
|
setMonth(new Date(response.data.dateStart).getMonth());
|
||||||
|
setYear(new Date(response.data.dateStart).getFullYear());
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
handleLoad();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
async function handleEdit() {
|
||||||
|
try {
|
||||||
|
const hasil = await decryptToken(String(token?.current));
|
||||||
|
const response = await apiEditTaskTugas({ data: { title, dateStart: dayjs(range.startDate).format("YYYY-MM-DD"), dateEnd: dayjs(range.endDate).format("YYYY-MM-DD"), user: hasil }, id: detail });
|
||||||
|
if (response.success) {
|
||||||
|
dispatch(setUpdateTask({ ...update, task: !update.task }))
|
||||||
|
ToastAndroid.show("Berhasil mengubah data", ToastAndroid.SHORT);
|
||||||
|
router.back();
|
||||||
|
} else {
|
||||||
|
ToastAndroid.show(response.message, ToastAndroid.SHORT);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
ToastAndroid.show("Gagal mengubah data", ToastAndroid.SHORT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkAll() {
|
||||||
|
if (
|
||||||
|
from == "" ||
|
||||||
|
to == "" ||
|
||||||
|
title == "" ||
|
||||||
|
title == "null" ||
|
||||||
|
error.startDate ||
|
||||||
|
error.endDate ||
|
||||||
|
error.title
|
||||||
|
) {
|
||||||
|
setDisableBtn(true);
|
||||||
|
} else {
|
||||||
|
setDisableBtn(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onValidation(cat: string, val: string) {
|
||||||
|
if (cat == "title") {
|
||||||
|
setTitle(val);
|
||||||
|
if (val == "" || val == "null") {
|
||||||
|
setError((error) => ({ ...error, title: true }));
|
||||||
|
} else {
|
||||||
|
setError((error) => ({ ...error, title: false }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
checkAll();
|
||||||
|
}, [from, to, title, error]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SafeAreaView>
|
||||||
|
<Stack.Screen
|
||||||
|
options={{
|
||||||
|
headerLeft: () => (
|
||||||
|
<ButtonBackHeader
|
||||||
|
onPress={() => {
|
||||||
|
router.back();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
headerTitle: "Edit Tanggal dan Tugas",
|
||||||
|
headerTitleAlign: "center",
|
||||||
|
headerRight: () => (
|
||||||
|
<ButtonSaveHeader
|
||||||
|
disable={disableBtn}
|
||||||
|
category="update"
|
||||||
|
onPress={() => {
|
||||||
|
handleEdit()
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ScrollView>
|
||||||
|
<View style={[Styles.p15, Styles.mb100]}>
|
||||||
|
<View style={[Styles.wrapPaper, Styles.p10]}>
|
||||||
|
{!loading && (
|
||||||
|
<DateTimePicker
|
||||||
|
mode="range"
|
||||||
|
startDate={range.startDate}
|
||||||
|
endDate={range.endDate}
|
||||||
|
onChange={(param) => setRange(param)}
|
||||||
|
month={month}
|
||||||
|
year={year}
|
||||||
|
styles={{
|
||||||
|
selected: Styles.selectedDate,
|
||||||
|
selected_label: Styles.cWhite,
|
||||||
|
range_fill: Styles.selectRangeDate,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
<View style={[Styles.mv10]}>
|
||||||
|
<View style={[Styles.rowSpaceBetween]}>
|
||||||
|
<View style={[{ width: "48%" }]}>
|
||||||
|
<Text style={[Styles.mb05]}>
|
||||||
|
Tanggal Mulai <Text style={Styles.cError}>*</Text>
|
||||||
|
</Text>
|
||||||
|
<View style={[Styles.wrapPaper, Styles.p10]}>
|
||||||
|
<Text style={{ textAlign: "center" }}>{from}</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
<View style={[{ width: "48%" }]}>
|
||||||
|
<Text style={[Styles.mb05]}>
|
||||||
|
Tanggal Berakhir <Text style={Styles.cError}>*</Text>
|
||||||
|
</Text>
|
||||||
|
<View style={[Styles.wrapPaper, Styles.p10]}>
|
||||||
|
<Text style={{ textAlign: "center" }}>{to}</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
{(error.endDate || error.startDate) && (
|
||||||
|
<Text
|
||||||
|
style={[Styles.textInformation, Styles.cError, Styles.mt05]}
|
||||||
|
>
|
||||||
|
Tanggal tidak boleh kosong
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
<InputForm
|
||||||
|
label="Judul Tugas"
|
||||||
|
type="default"
|
||||||
|
placeholder="Judul Tugas"
|
||||||
|
required
|
||||||
|
bg="white"
|
||||||
|
value={title}
|
||||||
|
error={error.title}
|
||||||
|
errorText="Judul tidak boleh kosong"
|
||||||
|
onChange={(e) => {
|
||||||
|
onValidation("title", e)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</ScrollView>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
import ButtonBackHeader from "@/components/buttonBackHeader";
|
|
||||||
import ButtonSaveHeader from "@/components/buttonSaveHeader";
|
|
||||||
import { InputForm } from "@/components/inputForm";
|
|
||||||
import Styles from "@/constants/Styles";
|
|
||||||
import dayjs from "dayjs";
|
|
||||||
import { router, Stack, useLocalSearchParams } from "expo-router";
|
|
||||||
import { useState } from "react";
|
|
||||||
import { SafeAreaView, ScrollView, Text, ToastAndroid, View } from "react-native";
|
|
||||||
import DateTimePicker, { DateType, getDefaultStyles } from "react-native-ui-datepicker";
|
|
||||||
|
|
||||||
export default function UpdateProjectTaskDivision() {
|
|
||||||
const { id } = useLocalSearchParams()
|
|
||||||
const [range, setRange] = useState<{ startDate: DateType; endDate: DateType; }>({ startDate: undefined, endDate: undefined });
|
|
||||||
const defaultStyles = getDefaultStyles()
|
|
||||||
|
|
||||||
const from = range.startDate
|
|
||||||
? dayjs(range.startDate).format('MMM DD, YYYY')
|
|
||||||
: '';
|
|
||||||
const to = range.endDate ? dayjs(range.endDate).format('MMM DD, YYYY') : '';
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
|
||||||
<SafeAreaView>
|
|
||||||
<Stack.Screen
|
|
||||||
options={{
|
|
||||||
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
|
|
||||||
headerTitle: 'Edit Tanggal dan Tugas Divisi',
|
|
||||||
headerTitleAlign: 'center',
|
|
||||||
headerRight: () => <ButtonSaveHeader category="update" onPress={() => {
|
|
||||||
ToastAndroid.show('Berhasil mengubah data', ToastAndroid.SHORT)
|
|
||||||
router.push('../4324')
|
|
||||||
}} />
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<ScrollView>
|
|
||||||
<View style={[Styles.p15, Styles.mb100]}>
|
|
||||||
<View style={[Styles.wrapPaper, Styles.p10]}>
|
|
||||||
<DateTimePicker
|
|
||||||
mode="range"
|
|
||||||
startDate={range.startDate}
|
|
||||||
endDate={range.endDate}
|
|
||||||
onChange={(param) => setRange(param)}
|
|
||||||
// styles={defaultStyles}
|
|
||||||
styles={{
|
|
||||||
selected: Styles.selectedDate,
|
|
||||||
selected_label: Styles.cWhite,
|
|
||||||
range_fill: Styles.selectRangeDate,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
<View style={[Styles.rowSpaceBetween, Styles.mv10]}>
|
|
||||||
<View style={[{ width: '48%' }]}>
|
|
||||||
<Text style={[Styles.mb05]}>Tanggal Mulai <Text style={Styles.cError}>*</Text></Text>
|
|
||||||
<View style={[Styles.wrapPaper, Styles.p10]}>
|
|
||||||
<Text style={{ textAlign: 'center' }}>{from}</Text>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
<View style={[{ width: '48%' }]}>
|
|
||||||
<Text style={[Styles.mb05]}>Tanggal Berakhir <Text style={Styles.cError}>*</Text></Text>
|
|
||||||
<View style={[Styles.wrapPaper, Styles.p10]}>
|
|
||||||
<Text style={{ textAlign: 'center' }}>{to}</Text>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
<InputForm label="Judul Tugas" type="default" placeholder="Judul Tugas" required bg="white" />
|
|
||||||
</View>
|
|
||||||
</ScrollView>
|
|
||||||
</SafeAreaView>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
import Styles from "@/constants/Styles"
|
import Styles from "@/constants/Styles"
|
||||||
import { AntDesign, MaterialCommunityIcons, MaterialIcons } from "@expo/vector-icons"
|
import { AntDesign, MaterialCommunityIcons, MaterialIcons } from "@expo/vector-icons"
|
||||||
|
import { router } from "expo-router"
|
||||||
import { useState } from "react"
|
import { useState } from "react"
|
||||||
import { View } from "react-native"
|
import { View } from "react-native"
|
||||||
import ButtonMenuHeader from "../buttonMenuHeader"
|
import ButtonMenuHeader from "../buttonMenuHeader"
|
||||||
import DrawerBottom from "../drawerBottom"
|
import DrawerBottom from "../drawerBottom"
|
||||||
import MenuItemRow from "../menuItemRow"
|
import MenuItemRow from "../menuItemRow"
|
||||||
import { router } from "expo-router"
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
id: string | string[]
|
id: string | string[]
|
||||||
@@ -40,8 +40,8 @@ export default function HeaderRightTaskDetail({ id }: Props) {
|
|||||||
icon={<MaterialIcons name="groups" color="black" size={25} />}
|
icon={<MaterialIcons name="groups" color="black" size={25} />}
|
||||||
title="Tambah Anggota"
|
title="Tambah Anggota"
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
// setVisible(false)
|
setVisible(false)
|
||||||
|
router.push(`./${id}/add-member`)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -1,34 +1,87 @@
|
|||||||
import Styles from "@/constants/Styles";
|
import Styles from "@/constants/Styles";
|
||||||
|
import { apiDeleteFileTask, apiGetTaskOne } from "@/lib/api";
|
||||||
|
import { setUpdateTask } from "@/lib/taskUpdate";
|
||||||
|
import { useAuthSession } from "@/providers/AuthProvider";
|
||||||
import { Ionicons, MaterialCommunityIcons } from "@expo/vector-icons";
|
import { Ionicons, MaterialCommunityIcons } from "@expo/vector-icons";
|
||||||
import { useState } from "react";
|
import { useLocalSearchParams } from "expo-router";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
import { Text, ToastAndroid, View } from "react-native";
|
import { Text, ToastAndroid, View } from "react-native";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import AlertKonfirmasi from "../alertKonfirmasi";
|
import AlertKonfirmasi from "../alertKonfirmasi";
|
||||||
import BorderBottomItem from "../borderBottomItem";
|
import BorderBottomItem from "../borderBottomItem";
|
||||||
import DrawerBottom from "../drawerBottom";
|
import DrawerBottom from "../drawerBottom";
|
||||||
import MenuItemRow from "../menuItemRow";
|
import MenuItemRow from "../menuItemRow";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
extension: string
|
||||||
|
idStorage: string
|
||||||
|
}
|
||||||
|
|
||||||
export default function SectionFileTask() {
|
export default function SectionFileTask() {
|
||||||
const [isModal, setModal] = useState(false)
|
const [isModal, setModal] = useState(false)
|
||||||
|
const { token, decryptToken } = useAuthSession()
|
||||||
|
const { detail } = useLocalSearchParams<{ detail: string }>();
|
||||||
|
const [data, setData] = useState<Props[]>([])
|
||||||
|
const [idSelect, setIdSelect] = useState('')
|
||||||
|
const update = useSelector((state: any) => state.taskUpdate)
|
||||||
|
const dispatch = useDispatch()
|
||||||
|
|
||||||
|
async function handleLoad() {
|
||||||
|
try {
|
||||||
|
const hasil = await decryptToken(String(token?.current))
|
||||||
|
const response = await apiGetTaskOne({ id: detail, user: hasil, cat: 'file' })
|
||||||
|
setData(response.data)
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
handleLoad()
|
||||||
|
}, [update.file])
|
||||||
|
|
||||||
|
async function handleDelete() {
|
||||||
|
try {
|
||||||
|
const hasil = await decryptToken(String(token?.current));
|
||||||
|
const response = await apiDeleteFileTask({ user: hasil }, idSelect);
|
||||||
|
if (response.success) {
|
||||||
|
ToastAndroid.show('Berhasil menghapus file', ToastAndroid.SHORT)
|
||||||
|
dispatch(setUpdateTask({ ...update, file: !update.file }))
|
||||||
|
} else {
|
||||||
|
ToastAndroid.show(response.message, ToastAndroid.SHORT)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
ToastAndroid.show('Terjadi kesalahan', ToastAndroid.SHORT)
|
||||||
|
} finally {
|
||||||
|
setModal(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<View style={[Styles.mb15]}>
|
<View style={[Styles.mb15]}>
|
||||||
<Text style={[Styles.textDefaultSemiBold, Styles.mv05]}>File</Text>
|
<Text style={[Styles.textDefaultSemiBold, Styles.mv05]}>File</Text>
|
||||||
<View style={[Styles.wrapPaper]}>
|
<View style={[Styles.wrapPaper]}>
|
||||||
<BorderBottomItem
|
{
|
||||||
borderType="all"
|
data.length > 0 ?
|
||||||
icon={<MaterialCommunityIcons name="file-outline" size={25} color="black" />}
|
data.map((item, index) => {
|
||||||
title="image_pertama.jpg"
|
return (
|
||||||
titleWeight="normal"
|
<BorderBottomItem
|
||||||
onPress={() => { setModal(true) }}
|
key={index}
|
||||||
/>
|
borderType="all"
|
||||||
<BorderBottomItem
|
icon={<MaterialCommunityIcons name="file-outline" size={25} color="black" />}
|
||||||
borderType="all"
|
title={item.name + '.' + item.extension}
|
||||||
icon={<MaterialCommunityIcons name="file-outline" size={25} color="black" />}
|
titleWeight="normal"
|
||||||
title="file_kedua.pdf"
|
onPress={() => { setIdSelect(item.id); setModal(true) }}
|
||||||
titleWeight="normal"
|
/>
|
||||||
onPress={() => { setModal(true) }}
|
)
|
||||||
/>
|
})
|
||||||
|
:
|
||||||
|
<Text style={[Styles.textDefault, Styles.cGray, { textAlign: 'center' }]}>Tidak ada file</Text>
|
||||||
|
}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
@@ -57,8 +110,7 @@ export default function SectionFileTask() {
|
|||||||
title: 'Konfirmasi',
|
title: 'Konfirmasi',
|
||||||
desc: 'Apakah Anda yakin ingin menghapus file ini? File yang dihapus tidak dapat dikembalikan',
|
desc: 'Apakah Anda yakin ingin menghapus file ini? File yang dihapus tidak dapat dikembalikan',
|
||||||
onPress: () => {
|
onPress: () => {
|
||||||
setModal(false)
|
handleDelete()
|
||||||
ToastAndroid.show('Berhasil menghapus data', ToastAndroid.SHORT)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,67 +1,165 @@
|
|||||||
import Styles from "@/constants/Styles"
|
import Styles from "@/constants/Styles";
|
||||||
import { MaterialCommunityIcons } from "@expo/vector-icons"
|
import { apiDeleteTaskMember, apiGetTaskOne } from "@/lib/api";
|
||||||
import { router } from "expo-router"
|
import { setUpdateTask } from "@/lib/taskUpdate";
|
||||||
import { useState } from "react"
|
import { useAuthSession } from "@/providers/AuthProvider";
|
||||||
import { Image, Text, ToastAndroid, View } from "react-native"
|
import { MaterialCommunityIcons } from "@expo/vector-icons";
|
||||||
import AlertKonfirmasi from "../alertKonfirmasi"
|
import { router, useLocalSearchParams } from "expo-router";
|
||||||
import BorderBottomItem from "../borderBottomItem"
|
import { useEffect, useState } from "react";
|
||||||
import DrawerBottom from "../drawerBottom"
|
import { Text, ToastAndroid, View } from "react-native";
|
||||||
import MenuItemRow from "../menuItemRow"
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
import AlertKonfirmasi from "../alertKonfirmasi";
|
||||||
|
import BorderBottomItem from "../borderBottomItem";
|
||||||
|
import DrawerBottom from "../drawerBottom";
|
||||||
|
import ImageUser from "../imageNew";
|
||||||
|
import MenuItemRow from "../menuItemRow";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
id: string;
|
||||||
|
idUser: string;
|
||||||
|
name: string;
|
||||||
|
email: string;
|
||||||
|
img: string;
|
||||||
|
position: string;
|
||||||
|
};
|
||||||
|
|
||||||
export default function SectionMemberTask() {
|
export default function SectionMemberTask() {
|
||||||
const [isModal, setModal] = useState(false)
|
const [isModal, setModal] = useState(false);
|
||||||
|
const { token, decryptToken } = useAuthSession();
|
||||||
|
const { id, detail } = useLocalSearchParams<{ id: string; detail: string }>();
|
||||||
|
const [data, setData] = useState<Props[]>([]);
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const update = useSelector((state: any) => state.taskUpdate);
|
||||||
|
const [memberChoose, setMemberChoose] = useState({
|
||||||
|
id: "",
|
||||||
|
name: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
async function handleLoad() {
|
||||||
|
try {
|
||||||
|
const hasil = await decryptToken(String(token?.current));
|
||||||
|
const response = await apiGetTaskOne({
|
||||||
|
id: detail,
|
||||||
|
user: hasil,
|
||||||
|
cat: "member",
|
||||||
|
});
|
||||||
|
setData(response.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
handleLoad();
|
||||||
|
}, [update.member]);
|
||||||
|
|
||||||
|
|
||||||
|
async function handleDeleteMember() {
|
||||||
|
try {
|
||||||
|
const hasil = await decryptToken(String(token?.current));
|
||||||
|
const response = await apiDeleteTaskMember({
|
||||||
|
user: hasil,
|
||||||
|
idUser: memberChoose.id,
|
||||||
|
}, detail)
|
||||||
|
if (response.success) {
|
||||||
|
ToastAndroid.show("Berhasil menghapus anggota", ToastAndroid.SHORT);
|
||||||
|
dispatch(setUpdateTask({ ...update, member: !update.progress }))
|
||||||
|
} else {
|
||||||
|
ToastAndroid.show(response.message, ToastAndroid.SHORT);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
ToastAndroid.show("Gagal menghapus anggota", ToastAndroid.SHORT);
|
||||||
|
} finally {
|
||||||
|
setModal(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<View style={[Styles.mb15]}>
|
<View style={[Styles.mb15]}>
|
||||||
<View style={[Styles.rowSpaceBetween, Styles.mv05]}>
|
<View style={[Styles.rowSpaceBetween, Styles.mv05]}>
|
||||||
<Text style={[Styles.textDefaultSemiBold]}>Anggota</Text>
|
<Text style={[Styles.textDefaultSemiBold]}>Anggota</Text>
|
||||||
<Text style={[Styles.textDefault]}>Total 5 Anggota</Text>
|
<Text style={[Styles.textDefault]}>Total {data.length} Anggota</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={[Styles.wrapPaper]}>
|
<View style={[Styles.wrapPaper]}>
|
||||||
<BorderBottomItem
|
{data.length > 0 ? (
|
||||||
borderType="bottom"
|
data.map((item, index) => {
|
||||||
icon={
|
return (
|
||||||
<></>
|
<BorderBottomItem
|
||||||
}
|
key={index}
|
||||||
title="Amalia Dwi"
|
borderType="bottom"
|
||||||
subtitle="Dinas - Bendahara"
|
icon={
|
||||||
rightTopInfo="Anggota"
|
<ImageUser
|
||||||
onPress={() => { setModal(true) }}
|
src={`https://wibu-storage.wibudev.com/api/files/${item.img}`}
|
||||||
/>
|
/>
|
||||||
|
}
|
||||||
|
title={item.name}
|
||||||
|
onPress={() => {
|
||||||
|
setMemberChoose({
|
||||||
|
id: item.idUser,
|
||||||
|
name: item.name,
|
||||||
|
});
|
||||||
|
setModal(true);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
) : (
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
Styles.textDefault,
|
||||||
|
Styles.cGray,
|
||||||
|
{ textAlign: "center" },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
Tidak ada anggota
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<DrawerBottom animation="slide" isVisible={isModal} setVisible={setModal} title="Menu">
|
<DrawerBottom
|
||||||
|
animation="slide"
|
||||||
|
isVisible={isModal}
|
||||||
|
setVisible={setModal}
|
||||||
|
title={memberChoose.name}
|
||||||
|
>
|
||||||
<View style={Styles.rowItemsCenter}>
|
<View style={Styles.rowItemsCenter}>
|
||||||
<MenuItemRow
|
<MenuItemRow
|
||||||
icon={<MaterialCommunityIcons name="account-eye" color="black" size={25} />}
|
icon={
|
||||||
|
<MaterialCommunityIcons
|
||||||
|
name="account-eye"
|
||||||
|
color="black"
|
||||||
|
size={25}
|
||||||
|
/>
|
||||||
|
}
|
||||||
title="Lihat Profil"
|
title="Lihat Profil"
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
setModal(false)
|
setModal(false);
|
||||||
router.push('/member/123')
|
router.push(`/member/${memberChoose.id}`);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<MenuItemRow
|
<MenuItemRow
|
||||||
icon={<MaterialCommunityIcons name="account-remove" color="black" size={25} />}
|
icon={
|
||||||
|
<MaterialCommunityIcons
|
||||||
|
name="account-remove"
|
||||||
|
color="black"
|
||||||
|
size={25}
|
||||||
|
/>
|
||||||
|
}
|
||||||
title="Keluarkan"
|
title="Keluarkan"
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
AlertKonfirmasi({
|
AlertKonfirmasi({
|
||||||
title: 'Konfirmasi',
|
title: "Konfirmasi",
|
||||||
desc: 'Apakah Anda yakin ingin mengeluarkan anggota?',
|
desc: "Apakah Anda yakin ingin mengeluarkan anggota?",
|
||||||
onPress: () => {
|
onPress: () => { handleDeleteMember() },
|
||||||
setModal(false)
|
});
|
||||||
ToastAndroid.show('Berhasil mengeluarkan anggota', ToastAndroid.SHORT)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</DrawerBottom>
|
</DrawerBottom>
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,128 @@
|
|||||||
import Styles from "@/constants/Styles";
|
import Styles from "@/constants/Styles";
|
||||||
|
import { apiDeleteTaskTugas, apiGetTaskOne, apiUpdateStatusTaskDivision } from "@/lib/api";
|
||||||
|
import { setUpdateTask } from "@/lib/taskUpdate";
|
||||||
|
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, useLocalSearchParams } from "expo-router";
|
||||||
import { useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Text, ToastAndroid, View } from "react-native";
|
import { Text, ToastAndroid, View } from "react-native";
|
||||||
import ItemSectionTanggalTugas from "../itemSectionTanggalTugas";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import DrawerBottom from "../drawerBottom";
|
|
||||||
import MenuItemRow from "../menuItemRow";
|
|
||||||
import AlertKonfirmasi from "../alertKonfirmasi";
|
import AlertKonfirmasi from "../alertKonfirmasi";
|
||||||
|
import DrawerBottom from "../drawerBottom";
|
||||||
|
import ItemSectionTanggalTugas from "../itemSectionTanggalTugas";
|
||||||
|
import MenuItemRow from "../menuItemRow";
|
||||||
import ModalSelect from "../modalSelect";
|
import ModalSelect from "../modalSelect";
|
||||||
|
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
status: number;
|
||||||
|
dateStart: string;
|
||||||
|
dateEnd: string;
|
||||||
|
}
|
||||||
|
|
||||||
export default function SectionTanggalTugasTask() {
|
export default function SectionTanggalTugasTask() {
|
||||||
|
const dispatch = useDispatch()
|
||||||
|
const update = useSelector((state: any) => state.taskUpdate)
|
||||||
const [isModal, setModal] = useState(false)
|
const [isModal, setModal] = useState(false)
|
||||||
const [isSelect, setSelect] = useState(false)
|
const [isSelect, setSelect] = useState(false)
|
||||||
const [choose, setChoose] = useState({ val: '', label: '' })
|
const { token, decryptToken } = useAuthSession()
|
||||||
|
const { id, detail } = useLocalSearchParams<{ id: string, detail: string }>();
|
||||||
|
const [data, setData] = useState<Props[]>([])
|
||||||
|
const [tugas, setTugas] = useState({
|
||||||
|
id: '',
|
||||||
|
status: 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
async function handleLoad() {
|
||||||
|
try {
|
||||||
|
const hasil = await decryptToken(String(token?.current))
|
||||||
|
const response = await apiGetTaskOne({ id: detail, user: hasil, cat: 'task' })
|
||||||
|
setData(response.data)
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleUpdate(status: number) {
|
||||||
|
try {
|
||||||
|
const hasil = await decryptToken(String(token?.current));
|
||||||
|
const response = await apiUpdateStatusTaskDivision({
|
||||||
|
user: hasil,
|
||||||
|
idProject: detail,
|
||||||
|
status: status,
|
||||||
|
}, tugas.id);
|
||||||
|
if (response.success) {
|
||||||
|
dispatch(setUpdateTask({ ...update, progress: !update.progress, task: !update.task }))
|
||||||
|
ToastAndroid.show("Berhasil mengubah data", ToastAndroid.SHORT);
|
||||||
|
} else {
|
||||||
|
ToastAndroid.show(response.message, ToastAndroid.SHORT);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
ToastAndroid.show("Gagal mengubah data", ToastAndroid.SHORT);
|
||||||
|
} finally {
|
||||||
|
setSelect(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
handleLoad()
|
||||||
|
}, [update.task])
|
||||||
|
|
||||||
|
|
||||||
|
async function handleDelete() {
|
||||||
|
try {
|
||||||
|
const hasil = await decryptToken(String(token?.current));
|
||||||
|
const response = await apiDeleteTaskTugas({
|
||||||
|
user: hasil,
|
||||||
|
idProject: detail,
|
||||||
|
}, tugas.id);
|
||||||
|
if (response.success) {
|
||||||
|
dispatch(setUpdateTask({ ...update, progress: !update.progress, task: !update.task }))
|
||||||
|
ToastAndroid.show("Berhasil menghapus data", ToastAndroid.SHORT);
|
||||||
|
} else {
|
||||||
|
ToastAndroid.show(response.message, ToastAndroid.SHORT);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
ToastAndroid.show("Gagal menghapus data", ToastAndroid.SHORT);
|
||||||
|
} finally {
|
||||||
|
setModal(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<View style={[Styles.mb15, Styles.mt10]}>
|
<View style={[Styles.mb15, Styles.mt10]}>
|
||||||
<Text style={[Styles.textDefaultSemiBold, Styles.mv05]}>Tanggal & Tugas</Text>
|
<Text style={[Styles.textDefaultSemiBold, Styles.mv05]}>Tanggal & Tugas</Text>
|
||||||
<View style={[Styles.wrapPaper]}>
|
<View style={[Styles.wrapPaper]}>
|
||||||
<ItemSectionTanggalTugas done={false} title="Pertama" dateStart="12-03-2023" dateEnd="15-03-2023" onPress={() => { setModal(true) }} />
|
{
|
||||||
<ItemSectionTanggalTugas done={true} title="Kedua" dateStart="15-03-2023" dateEnd="20-03-2023" onPress={() => { setModal(true) }} />
|
data.length > 0
|
||||||
|
?
|
||||||
|
data.map((item, index) => {
|
||||||
|
return (
|
||||||
|
<ItemSectionTanggalTugas
|
||||||
|
key={index}
|
||||||
|
done={item.status === 1}
|
||||||
|
title={item.title}
|
||||||
|
dateStart={item.dateStart}
|
||||||
|
dateEnd={item.dateEnd}
|
||||||
|
onPress={() => {
|
||||||
|
setTugas({
|
||||||
|
id: item.id,
|
||||||
|
status: item.status
|
||||||
|
})
|
||||||
|
setModal(true)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
:
|
||||||
|
<Text style={[Styles.textDefault, Styles.cGray, { textAlign: 'center' }]}>Tidak ada tugas</Text>
|
||||||
|
}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
@@ -40,7 +141,7 @@ export default function SectionTanggalTugasTask() {
|
|||||||
title="Edit Tugas"
|
title="Edit Tugas"
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
setModal(false)
|
setModal(false)
|
||||||
router.push(`./update/124`)
|
router.push(`./update/${tugas.id}`)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -52,8 +153,7 @@ export default function SectionTanggalTugasTask() {
|
|||||||
title: 'Konfirmasi',
|
title: 'Konfirmasi',
|
||||||
desc: 'Apakah anda yakin ingin menghapus data ini?',
|
desc: 'Apakah anda yakin ingin menghapus data ini?',
|
||||||
onPress: () => {
|
onPress: () => {
|
||||||
setModal(false)
|
handleDelete()
|
||||||
ToastAndroid.show('Berhasil menghapus data', ToastAndroid.SHORT)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -66,12 +166,11 @@ export default function SectionTanggalTugasTask() {
|
|||||||
category="status-task"
|
category="status-task"
|
||||||
close={setSelect}
|
close={setSelect}
|
||||||
onSelect={(value) => {
|
onSelect={(value) => {
|
||||||
setChoose(value)
|
handleUpdate(Number(value.val))
|
||||||
setSelect(false)
|
|
||||||
ToastAndroid.show('Berhasil mengubah data', ToastAndroid.SHORT)
|
|
||||||
}}
|
}}
|
||||||
title="Status"
|
title="Status"
|
||||||
open={isSelect}
|
open={isSelect}
|
||||||
|
valChoose={String(tugas.status)}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
82
lib/api.ts
82
lib/api.ts
@@ -468,3 +468,85 @@ export const apiGetCalendarHistory = async ({ user, search, division }: { user:
|
|||||||
const response = await api.get(`mobile/calendar/history?user=${user}&search=${search}&division=${division}`);
|
const response = await api.get(`mobile/calendar/history?user=${user}&search=${search}&division=${division}`);
|
||||||
return response.data;
|
return response.data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const apiGetTask = async ({ user, status, search, division }: { user: string, status: string, search: string, division: string }) => {
|
||||||
|
const response = await api.get(`mobile/task?user=${user}&status=${status}&division=${division}&search=${search}`);
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const apiGetTaskOne = async ({ user, cat, id }: { user: string, cat: 'data' | 'progress' | 'task' | 'file' | 'member', id: string }) => {
|
||||||
|
const response = await api.get(`mobile/task/${id}?user=${user}&cat=${cat}`);
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const apiUpdateStatusTaskDivision = async (data: { user: string, status: number, idProject: string }, id: string) => {
|
||||||
|
const response = await api.put(`mobile/task/detail/${id}`, data)
|
||||||
|
return response.data
|
||||||
|
};
|
||||||
|
|
||||||
|
export const apiGetTaskTugas = async ({ user, id }: { user: string, id: string }) => {
|
||||||
|
const response = await api.get(`mobile/task/detail/${id}?user=${user}`);
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const apiEditTaskTugas = async ({ data, id }: { data: { title: string, dateStart: string, user: string, dateEnd: string }, id: string }) => {
|
||||||
|
const response = await api.post(`/mobile/task/detail/${id}`, data)
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const apiDeleteTaskTugas = async (data: { user: string, idProject: string }, id: string) => {
|
||||||
|
const response = await api.delete(`mobile/task/detail/${id}`, { data })
|
||||||
|
return response.data
|
||||||
|
};
|
||||||
|
|
||||||
|
export const apiDeleteFileTask = async (data: { user: string }, id: string) => {
|
||||||
|
const response = await api.delete(`/mobile/task/file/${id}`, { data })
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const apiDeleteTaskMember = async (data: { user: string, idUser: string }, id: string) => {
|
||||||
|
const response = await api.delete(`mobile/task/${id}/member`, { data })
|
||||||
|
return response.data
|
||||||
|
};
|
||||||
|
|
||||||
|
export const apiCreateTaskTugas = async ({ data, id }: { data: { title: string, dateStart: string, user: string, dateEnd: string, idDivision: string }, id: string }) => {
|
||||||
|
const response = await api.post(`/mobile/task/${id}`, data)
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const apiCheckFileTask = async ({ data, id }: { data: FormData, id: string }) => {
|
||||||
|
const response = await api.put(`/mobile/task/file/${id}`, data,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const apiAddFileTask = async ({ data, id }: { data: FormData, id: string }) => {
|
||||||
|
const response = await api.post(`/mobile/task/file/${id}`, data,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const apiEditTask = async (data: { title: string, user: string }, id: string) => {
|
||||||
|
const response = await api.put(`/mobile/task/${id}`, data)
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const apiCancelTask = async (data: { user: string, reason: string }, id: string) => {
|
||||||
|
const response = await api.delete(`mobile/task/${id}`, { data })
|
||||||
|
return response.data
|
||||||
|
};
|
||||||
|
|
||||||
|
export const apiAddMemberTask = async ({ data, id }: { data: { user: string, member: any[], idDivision: string }, id: string }) => {
|
||||||
|
const response = await api.post(`/mobile/task/${id}/member`, data)
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
@@ -13,6 +13,7 @@ import memberUpdate from './memberSlice';
|
|||||||
import positionUpdate from './positionSlice';
|
import positionUpdate from './positionSlice';
|
||||||
import projectUpdate from './projectUpdate';
|
import projectUpdate from './projectUpdate';
|
||||||
import taskCreate from './taskCreate';
|
import taskCreate from './taskCreate';
|
||||||
|
import taskUpdate from './taskUpdate';
|
||||||
import userReducer from './userSlice';
|
import userReducer from './userSlice';
|
||||||
|
|
||||||
const store = configureStore({
|
const store = configureStore({
|
||||||
@@ -32,6 +33,7 @@ const store = configureStore({
|
|||||||
divisionUpdate: divisionUpdate,
|
divisionUpdate: divisionUpdate,
|
||||||
discussionUpdate: discussionUpdate,
|
discussionUpdate: discussionUpdate,
|
||||||
calendarUpdate: calendarUpdate,
|
calendarUpdate: calendarUpdate,
|
||||||
|
taskUpdate: taskUpdate,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
20
lib/taskUpdate.ts
Normal file
20
lib/taskUpdate.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { createSlice } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
|
const taskUpdate = createSlice({
|
||||||
|
name: 'taskUpdate',
|
||||||
|
initialState: {
|
||||||
|
data: false,
|
||||||
|
progress: false,
|
||||||
|
task: false,
|
||||||
|
file: false,
|
||||||
|
member: false
|
||||||
|
},
|
||||||
|
reducers: {
|
||||||
|
setUpdateTask: (state, action) => {
|
||||||
|
return action.payload;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const { setUpdateTask } = taskUpdate.actions;
|
||||||
|
export default taskUpdate.reducer;
|
||||||
Reference in New Issue
Block a user