upd: dokumen divisi
Deskripsi: -get all dokumen - select dokumen - tambah folder - upload file - rename dokumen - hapus dokumen - informasi dokumen - move blm selsai NO Issues
This commit is contained in:
@@ -1,52 +1,453 @@
|
|||||||
import ButtonBackHeader from "@/components/buttonBackHeader"
|
import AlertKonfirmasi from "@/components/alertKonfirmasi";
|
||||||
import { ButtonHeader } from "@/components/buttonHeader"
|
import ButtonBackHeader from "@/components/buttonBackHeader";
|
||||||
import HeaderRightDocument from "@/components/document/headerDocument"
|
import { ButtonHeader } from "@/components/buttonHeader";
|
||||||
import ItemFile from "@/components/document/itemFile"
|
import HeaderRightDocument from "@/components/document/headerDocument";
|
||||||
import MenuBottomSelectDocument from "@/components/document/menuBottomSelectDocument"
|
import ItemFile from "@/components/document/itemFile";
|
||||||
import Styles from "@/constants/Styles"
|
import ModalMore from "@/components/document/modalMore";
|
||||||
import { AntDesign, MaterialIcons } from "@expo/vector-icons"
|
import DrawerBottom from "@/components/drawerBottom";
|
||||||
import { router, Stack, useLocalSearchParams } from "expo-router"
|
import { InputForm } from "@/components/inputForm";
|
||||||
import { useState } from "react"
|
import MenuItemRow from "@/components/menuItemRow";
|
||||||
import { SafeAreaView, ScrollView, Text, View } from "react-native"
|
import ModalFloat from "@/components/modalFloat";
|
||||||
|
import { ColorsStatus } from "@/constants/ColorsStatus";
|
||||||
|
import Styles from "@/constants/Styles";
|
||||||
|
import { apiDocumentDelete, apiDocumentRename, apiGetDocument } from "@/lib/api";
|
||||||
|
import { setUpdateDokumen } from "@/lib/dokumenUpdate";
|
||||||
|
import { useAuthSession } from "@/providers/AuthProvider";
|
||||||
|
import {
|
||||||
|
AntDesign,
|
||||||
|
MaterialCommunityIcons,
|
||||||
|
MaterialIcons,
|
||||||
|
} 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 = {
|
||||||
|
id: string;
|
||||||
|
category: string;
|
||||||
|
name: string;
|
||||||
|
extension: string;
|
||||||
|
idStorage: string;
|
||||||
|
path: string;
|
||||||
|
createdBy: string;
|
||||||
|
share: boolean;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type PropsPath = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
|
||||||
export default function DocumentDivision() {
|
export default function DocumentDivision() {
|
||||||
const { path } = useLocalSearchParams<{ path?: string }>()
|
const { token, decryptToken } = useAuthSession();
|
||||||
const [isChecked, setIsChecked] = useState(false)
|
const { id } = useLocalSearchParams<{ id: string }>();
|
||||||
|
const [path, setPath] = useState("home");
|
||||||
|
const [data, setData] = useState<Props[]>([]);
|
||||||
|
const [dataJalur, setDataJalur] = useState<PropsPath[]>([]);
|
||||||
|
const [dariSelectAll, setDariSelectAll] = useState(false);
|
||||||
|
const [selectedFiles, setSelectedFiles] = useState<any>([]);
|
||||||
|
const [selectAll, setSelectAll] = useState(false);
|
||||||
|
const [shareSelected, setShareSelected] = useState(false);
|
||||||
|
const [copyAllowed, setCopyAllowed] = useState(true);
|
||||||
|
const [modalMore, setModalMore] = useState(false);
|
||||||
|
const [isRename, setRename] = useState(false);
|
||||||
|
const dispatch = useDispatch()
|
||||||
|
const update = useSelector((state: any) => state.dokumenUpdate);
|
||||||
|
const [bodyRename, setBodyRename] = useState({
|
||||||
|
id: "",
|
||||||
|
name: "",
|
||||||
|
path: "",
|
||||||
|
idDivision: id,
|
||||||
|
extension: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
async function handleLoad() {
|
||||||
|
try {
|
||||||
|
const hasil = await decryptToken(String(token?.current));
|
||||||
|
const response = await apiGetDocument({
|
||||||
|
user: hasil,
|
||||||
|
path,
|
||||||
|
division: id,
|
||||||
|
category: "all",
|
||||||
|
});
|
||||||
|
setData(response.data);
|
||||||
|
setDataJalur(response.jalur);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
handleLoad();
|
||||||
|
}, [path, update]);
|
||||||
|
|
||||||
|
const handleCheckboxChange = (index: number) => {
|
||||||
|
setDariSelectAll(false);
|
||||||
|
if (selectedFiles.some((i: any) => i.id == data[index].id)) {
|
||||||
|
setSelectedFiles(
|
||||||
|
selectedFiles.filter((i: any) => i.id != data[index].id)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
setSelectedFiles([
|
||||||
|
...selectedFiles,
|
||||||
|
{
|
||||||
|
id: data[index].id,
|
||||||
|
name: data[index].name,
|
||||||
|
path: data[index].path,
|
||||||
|
extension: data[index].extension,
|
||||||
|
category: data[index].category,
|
||||||
|
share: data[index].share,
|
||||||
|
idStorage: data[index].idStorage,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function cek() {
|
||||||
|
if (selectedFiles.length == data.length) {
|
||||||
|
setSelectAll(true);
|
||||||
|
} else {
|
||||||
|
setSelectAll(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const shareSelected = selectedFiles.some((i: any) => i?.share == true);
|
||||||
|
if (shareSelected) {
|
||||||
|
setShareSelected(true);
|
||||||
|
} else {
|
||||||
|
setShareSelected(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const cek = selectedFiles.some((i: any) => i?.category == "FOLDER");
|
||||||
|
if (cek || selectedFiles.length > 1) {
|
||||||
|
setCopyAllowed(false);
|
||||||
|
} else {
|
||||||
|
setCopyAllowed(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
cek();
|
||||||
|
}, [selectedFiles]);
|
||||||
|
|
||||||
|
const handleSelectAll = () => {
|
||||||
|
if (!selectAll) {
|
||||||
|
setDariSelectAll(false);
|
||||||
|
for (let index = 0; index < data.length; index++) {
|
||||||
|
if (!selectedFiles.some((i: any) => i.id == data[index].id)) {
|
||||||
|
const newArr = {
|
||||||
|
id: data[index].id,
|
||||||
|
name: data[index].name,
|
||||||
|
path: data[index].path,
|
||||||
|
extension: data[index].extension,
|
||||||
|
category: data[index].category,
|
||||||
|
share: data[index].share,
|
||||||
|
idStorage: data[index].idStorage,
|
||||||
|
};
|
||||||
|
setSelectedFiles((selectedFiles: any) => [...selectedFiles, newArr]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setDariSelectAll(true);
|
||||||
|
setSelectedFiles([]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleBatal = () => {
|
||||||
|
setSelectedFiles([]);
|
||||||
|
setSelectAll(false);
|
||||||
|
setDariSelectAll(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
function onChooseRename() {
|
||||||
|
setBodyRename({
|
||||||
|
...bodyRename,
|
||||||
|
id: selectedFiles[0].id,
|
||||||
|
name: selectedFiles[0].name,
|
||||||
|
path: selectedFiles[0].path,
|
||||||
|
extension: selectedFiles[0].extension,
|
||||||
|
});
|
||||||
|
setRename(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleRename() {
|
||||||
|
try {
|
||||||
|
const hasil = await decryptToken(String(token?.current))
|
||||||
|
const response = await apiDocumentRename({ user: hasil, ...bodyRename })
|
||||||
|
if (response.success) {
|
||||||
|
ToastAndroid.show("Berhasil mengubah nama", ToastAndroid.SHORT)
|
||||||
|
dispatch(setUpdateDokumen(!update))
|
||||||
|
handleBatal()
|
||||||
|
} else {
|
||||||
|
ToastAndroid.show(response.message, ToastAndroid.SHORT)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
ToastAndroid.show("Terjadi kesalahan", ToastAndroid.SHORT)
|
||||||
|
} finally {
|
||||||
|
setRename(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleDelete() {
|
||||||
|
try {
|
||||||
|
const hasil = await decryptToken(String(token?.current))
|
||||||
|
const response = await apiDocumentDelete({ user: hasil, data: selectedFiles })
|
||||||
|
if (response.success) {
|
||||||
|
ToastAndroid.show("Berhasil menghapus", ToastAndroid.SHORT)
|
||||||
|
dispatch(setUpdateDokumen(!update))
|
||||||
|
handleBatal()
|
||||||
|
} 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: () =>
|
headerLeft: () =>
|
||||||
isChecked
|
selectedFiles.length > 0 || dariSelectAll ? (
|
||||||
? <ButtonHeader item={<MaterialIcons name="close" size={20} color="white" />} onPress={() => { setIsChecked(false) }} />
|
<ButtonHeader
|
||||||
: <ButtonBackHeader onPress={() => { router.back() }} />,
|
item={<MaterialIcons name="close" size={20} color="white" />}
|
||||||
headerTitle: isChecked ? '1 item terpilih' : 'Dokumen Divisi',
|
onPress={() => {
|
||||||
headerTitleAlign: 'center',
|
handleBatal();
|
||||||
headerRight: () =>
|
|
||||||
isChecked
|
|
||||||
? <ButtonHeader item={<MaterialIcons name="checklist-rtl" size={20} color="white" />} onPress={() => { }} />
|
|
||||||
: <HeaderRightDocument id={path} />
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<ScrollView style={{ height: '100%' }}>
|
) : (
|
||||||
|
<ButtonBackHeader
|
||||||
|
onPress={() => {
|
||||||
|
router.back();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
headerTitle:
|
||||||
|
selectedFiles.length > 0 || dariSelectAll
|
||||||
|
? `${selectedFiles.length} item terpilih`
|
||||||
|
: "Dokumen Divisi",
|
||||||
|
headerTitleAlign: "center",
|
||||||
|
headerRight: () =>
|
||||||
|
selectedFiles.length > 0 || dariSelectAll ? (
|
||||||
|
<ButtonHeader
|
||||||
|
item={
|
||||||
|
<MaterialIcons name="checklist-rtl" size={20} color="white" />
|
||||||
|
}
|
||||||
|
onPress={() => {
|
||||||
|
handleSelectAll();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<HeaderRightDocument path={path} />
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ScrollView style={{ height: "100%" }}>
|
||||||
<View style={[Styles.p15, Styles.mb100]}>
|
<View style={[Styles.p15, Styles.mb100]}>
|
||||||
<View style={[Styles.rowItemsCenter]}>
|
<View style={[Styles.rowItemsCenter]}>
|
||||||
<Text> home </Text>
|
{dataJalur.map((item, index) => (
|
||||||
|
<Pressable
|
||||||
|
key={index}
|
||||||
|
style={[Styles.rowItemsCenter]}
|
||||||
|
onPress={() => {
|
||||||
|
setPath(item.id);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{item.id != "home" && (
|
||||||
<AntDesign name="right" style={[Styles.mh05, Styles.mt02]} />
|
<AntDesign name="right" style={[Styles.mh05, Styles.mt02]} />
|
||||||
<Text> folder 1 </Text>
|
)}
|
||||||
|
<Text> {item.name} </Text>
|
||||||
|
</Pressable>
|
||||||
|
))}
|
||||||
</View>
|
</View>
|
||||||
<View>
|
<View>
|
||||||
<ItemFile category="folder" title="Folder Pertama" dateTime="05-02-2025 07:54" onChecked={() => { setIsChecked(!isChecked) }} checked={isChecked} />
|
{data.length > 0 ? (
|
||||||
<ItemFile category="file" title="Images.jpg" dateTime="05-11-2024 07:54" />
|
data.map((item, index) => {
|
||||||
<ItemFile category="folder-shared" title="Folder shared" dateTime="05-11-2024 07:54" />
|
const isSelected = selectedFiles.some(
|
||||||
<ItemFile category="file-shared" title="images-shared.pdf" dateTime="05-11-2024 07:54" />
|
(i: any) => i?.id == item.id
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<ItemFile
|
||||||
|
key={index}
|
||||||
|
category={
|
||||||
|
item.category == "FOLDER"
|
||||||
|
? item.share
|
||||||
|
? "folder-shared"
|
||||||
|
: "folder"
|
||||||
|
: item.share
|
||||||
|
? "file-shared"
|
||||||
|
: "file"
|
||||||
|
}
|
||||||
|
title={
|
||||||
|
item.category == "FOLDER"
|
||||||
|
? item.name
|
||||||
|
: `${item.name}.${item.extension}`
|
||||||
|
}
|
||||||
|
dateTime={item.createdAt}
|
||||||
|
onChecked={() => {
|
||||||
|
handleCheckboxChange(index);
|
||||||
|
}}
|
||||||
|
checked={isSelected}
|
||||||
|
onPress={() => {
|
||||||
|
setPath(item.id);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
) : (
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
Styles.textDefault,
|
||||||
|
Styles.cGray,
|
||||||
|
Styles.mt15,
|
||||||
|
{ textAlign: "center" },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
Tidak ada dokumen
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
{
|
{(selectedFiles.length > 0 || dariSelectAll) && (
|
||||||
isChecked && <MenuBottomSelectDocument onDone={() => { setIsChecked(false) }} />
|
<View style={[ColorsStatus.primary, Styles.bottomMenuSelectDocument]}>
|
||||||
|
<View style={[Styles.rowItemsCenter, { justifyContent: "center" }]}>
|
||||||
|
<MenuItemRow
|
||||||
|
icon={
|
||||||
|
<MaterialCommunityIcons
|
||||||
|
name="download-outline"
|
||||||
|
color="white"
|
||||||
|
size={25}
|
||||||
|
/>
|
||||||
}
|
}
|
||||||
|
title="Unduh"
|
||||||
|
onPress={() => { }}
|
||||||
|
column="many"
|
||||||
|
color="white"
|
||||||
|
disabled={selectedFiles.length == 0 || !copyAllowed}
|
||||||
|
/>
|
||||||
|
<MenuItemRow
|
||||||
|
icon={
|
||||||
|
<MaterialCommunityIcons
|
||||||
|
name="trash-can-outline"
|
||||||
|
color="white"
|
||||||
|
size={25}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
title="Hapus"
|
||||||
|
onPress={() => {
|
||||||
|
AlertKonfirmasi({
|
||||||
|
title: "Konfirmasi",
|
||||||
|
desc: "Apakah anda yakin ingin menghapus dokumen?",
|
||||||
|
onPress: () => {
|
||||||
|
handleDelete()
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
column="many"
|
||||||
|
color="white"
|
||||||
|
disabled={selectedFiles.length == 0 || shareSelected}
|
||||||
|
/>
|
||||||
|
<MenuItemRow
|
||||||
|
icon={
|
||||||
|
<MaterialCommunityIcons
|
||||||
|
name="pencil-outline"
|
||||||
|
color="white"
|
||||||
|
size={25}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
title="Ganti Nama"
|
||||||
|
onPress={() => {
|
||||||
|
onChooseRename();
|
||||||
|
}}
|
||||||
|
column="many"
|
||||||
|
color="white"
|
||||||
|
disabled={selectedFiles.length != 1 || shareSelected}
|
||||||
|
/>
|
||||||
|
<MenuItemRow
|
||||||
|
icon={
|
||||||
|
<MaterialCommunityIcons
|
||||||
|
name="share-variant-outline"
|
||||||
|
color="white"
|
||||||
|
size={25}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
title="Bagikan"
|
||||||
|
onPress={() => { }}
|
||||||
|
column="many"
|
||||||
|
color="white"
|
||||||
|
disabled={selectedFiles.length != 1 || shareSelected}
|
||||||
|
/>
|
||||||
|
<MenuItemRow
|
||||||
|
icon={
|
||||||
|
<MaterialCommunityIcons
|
||||||
|
name="dots-vertical"
|
||||||
|
color="white"
|
||||||
|
size={25}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
title="Lainnya"
|
||||||
|
onPress={() => {
|
||||||
|
setModalMore(true);
|
||||||
|
}}
|
||||||
|
column="many"
|
||||||
|
color="white"
|
||||||
|
disabled={
|
||||||
|
selectedFiles.length == 1 ||
|
||||||
|
(selectedFiles.length > 0 && !shareSelected)
|
||||||
|
? false
|
||||||
|
: true
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<DrawerBottom
|
||||||
|
animation="slide"
|
||||||
|
isVisible={modalMore}
|
||||||
|
setVisible={setModalMore}
|
||||||
|
title=""
|
||||||
|
>
|
||||||
|
<ModalMore
|
||||||
|
onClose={() => {
|
||||||
|
setModalMore(false);
|
||||||
|
}}
|
||||||
|
data={selectedFiles}
|
||||||
|
share={shareSelected}
|
||||||
|
/>
|
||||||
|
</DrawerBottom>
|
||||||
|
|
||||||
|
<ModalFloat
|
||||||
|
title="Ganti Nama"
|
||||||
|
isVisible={isRename}
|
||||||
|
setVisible={setRename}
|
||||||
|
onSubmit={() => { handleRename() }}
|
||||||
|
disableSubmit={bodyRename.name == ""}
|
||||||
|
>
|
||||||
|
<View>
|
||||||
|
<InputForm
|
||||||
|
type="default"
|
||||||
|
placeholder="Nama File"
|
||||||
|
value={bodyRename.name}
|
||||||
|
onChange={(text) => {
|
||||||
|
setBodyRename({ ...bodyRename, name: text });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</ModalFloat>
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
@@ -1,54 +1,150 @@
|
|||||||
import Styles from "@/constants/Styles"
|
import Styles from "@/constants/Styles";
|
||||||
import { MaterialCommunityIcons, MaterialIcons } from "@expo/vector-icons"
|
import { apiCreateFolderDocument, apiUploadFileDocument } from "@/lib/api";
|
||||||
import { useState } from "react"
|
import { setUpdateDokumen } from "@/lib/dokumenUpdate";
|
||||||
import { ToastAndroid, View } from "react-native"
|
import { useAuthSession } from "@/providers/AuthProvider";
|
||||||
import ButtonMenuHeader from "../buttonMenuHeader"
|
import { MaterialCommunityIcons, MaterialIcons } from "@expo/vector-icons";
|
||||||
import DrawerBottom from "../drawerBottom"
|
import * as DocumentPicker from "expo-document-picker";
|
||||||
import { InputForm } from "../inputForm"
|
import { useLocalSearchParams } from "expo-router";
|
||||||
import MenuItemRow from "../menuItemRow"
|
import { useState } from "react";
|
||||||
import ModalFloat from "../modalFloat"
|
import { ToastAndroid, View } from "react-native";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
import ButtonMenuHeader from "../buttonMenuHeader";
|
||||||
|
import DrawerBottom from "../drawerBottom";
|
||||||
|
import { InputForm } from "../inputForm";
|
||||||
|
import MenuItemRow from "../menuItemRow";
|
||||||
|
import ModalFloat from "../modalFloat";
|
||||||
|
|
||||||
type Props = {
|
export default function HeaderRightDocument({ path }: { path: string }) {
|
||||||
id: string | string[] | undefined | null
|
const [isVisible, setVisible] = useState(false);
|
||||||
}
|
const [newFolder, setNewFolder] = useState(false);
|
||||||
|
const { id } = useLocalSearchParams<{ id: string }>();
|
||||||
|
const [name, setName] = useState("");
|
||||||
|
const { token, decryptToken } = useAuthSession()
|
||||||
|
const dispatch = useDispatch()
|
||||||
|
const update = useSelector((state: any) => state.dokumenUpdate)
|
||||||
|
|
||||||
|
async function handleCreateFolder() {
|
||||||
|
try {
|
||||||
|
const hasil = await decryptToken(String(token?.current))
|
||||||
|
const response = await apiCreateFolderDocument({ user: hasil, name, path, idDivision: id })
|
||||||
|
if (response.success) {
|
||||||
|
ToastAndroid.show("Berhasil membuat folder baru", ToastAndroid.SHORT)
|
||||||
|
dispatch(setUpdateDokumen(!update))
|
||||||
|
} else {
|
||||||
|
ToastAndroid.show(response.message, ToastAndroid.SHORT)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
ToastAndroid.show("Terjadi kesalahan", ToastAndroid.SHORT)
|
||||||
|
} finally {
|
||||||
|
setNewFolder(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const pickDocumentAsync = async () => {
|
||||||
|
let result = await DocumentPicker.getDocumentAsync({
|
||||||
|
type: ["*/*"],
|
||||||
|
multiple: false,
|
||||||
|
});
|
||||||
|
if (!result.canceled) {
|
||||||
|
if (result.assets?.[0].uri) {
|
||||||
|
handleUploadFile(result.assets?.[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
async function handleUploadFile(file: any) {
|
||||||
|
try {
|
||||||
|
const hasil = await decryptToken(String(token?.current))
|
||||||
|
const fd = new FormData()
|
||||||
|
fd.append("file", {
|
||||||
|
uri: file.uri,
|
||||||
|
type: "application/octet-stream",
|
||||||
|
name: file.name,
|
||||||
|
} as any);
|
||||||
|
|
||||||
|
fd.append(
|
||||||
|
"data",
|
||||||
|
JSON.stringify({
|
||||||
|
idPath: path,
|
||||||
|
idDivision: id,
|
||||||
|
user: hasil,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const response = await apiUploadFileDocument({ data: fd })
|
||||||
|
if (response.success) {
|
||||||
|
ToastAndroid.show("Berhasil mengunggah file", ToastAndroid.SHORT)
|
||||||
|
dispatch(setUpdateDokumen(!update))
|
||||||
|
} else {
|
||||||
|
ToastAndroid.show(response.message, ToastAndroid.SHORT)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
ToastAndroid.show("Terjadi kesalahan", ToastAndroid.SHORT)
|
||||||
|
} finally {
|
||||||
|
setVisible(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default function HeaderRightDocument({ id }: Props) {
|
|
||||||
const [isVisible, setVisible] = useState(false)
|
|
||||||
const [newFolder, setNewFolder] = useState(false)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ButtonMenuHeader onPress={() => { setVisible(true) }} />
|
<ButtonMenuHeader
|
||||||
<DrawerBottom animation="slide" isVisible={isVisible} setVisible={setVisible} title="Menu">
|
onPress={() => {
|
||||||
|
setVisible(true);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<DrawerBottom
|
||||||
|
animation="slide"
|
||||||
|
isVisible={isVisible}
|
||||||
|
setVisible={setVisible}
|
||||||
|
title="Menu"
|
||||||
|
>
|
||||||
<View style={Styles.rowItemsCenter}>
|
<View style={Styles.rowItemsCenter}>
|
||||||
<MenuItemRow
|
<MenuItemRow
|
||||||
icon={<MaterialCommunityIcons name="folder-open" color="black" size={25} />}
|
icon={
|
||||||
|
<MaterialCommunityIcons
|
||||||
|
name="folder-open"
|
||||||
|
color="black"
|
||||||
|
size={25}
|
||||||
|
/>
|
||||||
|
}
|
||||||
title="Tambah Dokumen"
|
title="Tambah Dokumen"
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
setVisible(false)
|
setVisible(false);
|
||||||
setNewFolder(true)
|
setNewFolder(true);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<MenuItemRow
|
<MenuItemRow
|
||||||
icon={<MaterialIcons name="upload-file" color="black" size={25} />}
|
icon={<MaterialIcons name="upload-file" color="black" size={25} />}
|
||||||
title="Upload File"
|
title="Upload File"
|
||||||
onPress={() => {
|
onPress={pickDocumentAsync}
|
||||||
setVisible(false)
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</DrawerBottom>
|
</DrawerBottom>
|
||||||
<ModalFloat title="Buat Folder Baru" isVisible={newFolder} setVisible={setNewFolder}
|
<ModalFloat
|
||||||
|
title="Buat Folder Baru"
|
||||||
|
isVisible={newFolder}
|
||||||
|
setVisible={setNewFolder}
|
||||||
|
disableSubmit={name == ""}
|
||||||
onSubmit={() => {
|
onSubmit={() => {
|
||||||
setNewFolder(false)
|
handleCreateFolder()
|
||||||
ToastAndroid.show('Berhasil membuat folder baru', ToastAndroid.SHORT)
|
}}
|
||||||
}}>
|
>
|
||||||
<View>
|
<View>
|
||||||
<InputForm type="default" placeholder="Nama Folder" required label="Nama Folder" />
|
<InputForm
|
||||||
|
type="default"
|
||||||
|
placeholder="Nama Folder"
|
||||||
|
required
|
||||||
|
label="Nama Folder"
|
||||||
|
onChange={(value: string) => {
|
||||||
|
setName(value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
</ModalFloat>
|
</ModalFloat>
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -42,8 +42,8 @@ export default function ItemFile({ category, checked, dateTime, title, onChecked
|
|||||||
|
|
||||||
</Pressable>
|
</Pressable>
|
||||||
<View style={[Styles.rowSpaceBetween, { flex: 1, alignItems: 'center' }]}>
|
<View style={[Styles.rowSpaceBetween, { flex: 1, alignItems: 'center' }]}>
|
||||||
<Pressable style={[Styles.ml10]} onPress={onPress}>
|
<Pressable style={[Styles.ml10, {flex:1},]} onPress={onPress}>
|
||||||
<Text style={[Styles.textDefault]}>{title}</Text>
|
<Text style={[Styles.textDefault]} numberOfLines={1} ellipsizeMode="tail">{title}</Text>
|
||||||
<Text style={[Styles.textInformation]}>{dateTime}</Text>
|
<Text style={[Styles.textInformation]}>{dateTime}</Text>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
<Pressable onPress={onChecked}>
|
<Pressable onPress={onChecked}>
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ export default function MenuBottomSelectDocument({ onDone }: Props) {
|
|||||||
setShare(false)
|
setShare(false)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<ModalSalinMove open={isMoveCopy} close={setMoveCopy} category={valMoveCopy} />
|
<ModalSalinMove open={isMoveCopy} close={setMoveCopy} category={valMoveCopy} onConfirm={(value: string) => { }} />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
96
components/document/modalInformasi.tsx
Normal file
96
components/document/modalInformasi.tsx
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
import Styles from "@/constants/Styles";
|
||||||
|
import { apiGetDocumentInformasi } from "@/lib/api";
|
||||||
|
import { useAuthSession } from "@/providers/AuthProvider";
|
||||||
|
import { Ionicons, MaterialCommunityIcons } from "@expo/vector-icons";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { Pressable, ScrollView, Text, View } from "react-native";
|
||||||
|
import { useSharedValue } from "react-native-reanimated";
|
||||||
|
import ItemAccordion from "../itemAccordion";
|
||||||
|
import ItemDetailMember from "../itemDetailMember";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
category: string,
|
||||||
|
name: string,
|
||||||
|
extension: string,
|
||||||
|
createdAt: string,
|
||||||
|
path: string,
|
||||||
|
division: string,
|
||||||
|
createdBy: string
|
||||||
|
}
|
||||||
|
|
||||||
|
type PropsShare = {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ModalInformasi({ data }: { data: any }) {
|
||||||
|
const open = useSharedValue(false)
|
||||||
|
const [dataInformasi, setDataInformasi] = useState<Props>()
|
||||||
|
const { token, decryptToken } = useAuthSession()
|
||||||
|
const [dataShare, setDataShare] = useState<PropsShare[]>([])
|
||||||
|
|
||||||
|
async function handleInformasi() {
|
||||||
|
try {
|
||||||
|
const hasil = await decryptToken(String(token?.current))
|
||||||
|
const response = await apiGetDocumentInformasi({ user: hasil, item: data.id, cat: 'lainnya' })
|
||||||
|
setDataInformasi(response.data)
|
||||||
|
|
||||||
|
const responseShare = await apiGetDocumentInformasi({ user: hasil, item: data.id, cat: 'share' })
|
||||||
|
setDataShare(responseShare.data)
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
handleInformasi()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<View style={[Styles.contentItemCenter, Styles.mb10]}>
|
||||||
|
{
|
||||||
|
dataInformasi?.extension == 'folder'
|
||||||
|
?
|
||||||
|
<Ionicons name="folder-open-sharp" color={'#f9cc40'} size={80} />
|
||||||
|
:
|
||||||
|
<Ionicons name="document-text-sharp" color={'#9fcff8'} size={80} />
|
||||||
|
}
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View>
|
||||||
|
<ItemDetailMember category="dokumen" value={dataInformasi?.category == 'FOLDER' ? dataInformasi?.name : `${dataInformasi?.name}.${dataInformasi?.extension}`} border />
|
||||||
|
<ItemDetailMember category="type" value={dataInformasi?.category} border />
|
||||||
|
<ItemDetailMember category="location" value={dataInformasi?.path} border />
|
||||||
|
<ItemDetailMember category="owner" value={dataInformasi?.division} border />
|
||||||
|
<ItemDetailMember category="calendar" value={dataInformasi?.createdAt} border />
|
||||||
|
<Pressable style={[Styles.rowSpaceBetween, Styles.rowItemsCenter, Styles.wrapItemBorderBottom]} onPress={() => { open.value = !open.value; }}>
|
||||||
|
<View style={[Styles.rowItemsCenter]}>
|
||||||
|
<MaterialCommunityIcons name="share-variant-outline" size={22} color="black" style={[Styles.mr10]} />
|
||||||
|
<Text style={[Styles.textDefault]}>Telah dibagikan ke divisi</Text>
|
||||||
|
</View>
|
||||||
|
<MaterialCommunityIcons name="chevron-down" size={22} color="black" />
|
||||||
|
</Pressable>
|
||||||
|
<ItemAccordion isExpanded={open} viewKey="Accordion" duration={500}>
|
||||||
|
<ScrollView style={[Styles.w100, { height: 200 }]} >
|
||||||
|
{
|
||||||
|
dataShare.length > 0 ? (
|
||||||
|
dataShare.map((item, index) => (
|
||||||
|
<View key={index} style={[Styles.rowOnly, Styles.ml10, Styles.mt02]}>
|
||||||
|
<MaterialCommunityIcons name="account-group-outline" size={22} color="black" style={[Styles.mr10]} />
|
||||||
|
<Text style={[Styles.textDefault]}>{item.name}</Text>
|
||||||
|
</View>
|
||||||
|
))
|
||||||
|
)
|
||||||
|
: (
|
||||||
|
<View style={[Styles.ml10, Styles.mt02]}>
|
||||||
|
<Text style={[Styles.textDefault, Styles.cGray, { textAlign: 'center' }]}>Tidak ada data</Text>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ScrollView>
|
||||||
|
</ItemAccordion>
|
||||||
|
</View>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
111
components/document/modalMore.tsx
Normal file
111
components/document/modalMore.tsx
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
import Styles from "@/constants/Styles";
|
||||||
|
import { apiMoveDocument } from "@/lib/api";
|
||||||
|
import { setUpdateDokumen } from "@/lib/dokumenUpdate";
|
||||||
|
import { useAuthSession } from "@/providers/AuthProvider";
|
||||||
|
import { MaterialCommunityIcons } from "@expo/vector-icons";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { ToastAndroid, View } from "react-native";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
import DrawerBottom from "../drawerBottom";
|
||||||
|
import MenuItemRow from "../menuItemRow";
|
||||||
|
import ModalInformasi from "./modalInformasi";
|
||||||
|
import ModalSalinMove from "./modalSalinMove";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
idStorage: string;
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
extension: string;
|
||||||
|
category: string;
|
||||||
|
path: string;
|
||||||
|
share: boolean;
|
||||||
|
createdBy: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ModalMore({ onClose, data, share }: { onClose: () => void, data: Props[], share: boolean }) {
|
||||||
|
const [isInformasi, setInformasi] = useState(false)
|
||||||
|
const [isCut, setIsCut] = useState(false)
|
||||||
|
const [isCopy, setIsCopy] = useState(false)
|
||||||
|
const [forbidCopy, setForbidCopy] = useState(true)
|
||||||
|
const [nFileSelected, setNFileSelected] = useState(0)
|
||||||
|
const { token, decryptToken } = useAuthSession()
|
||||||
|
const dispatch = useDispatch()
|
||||||
|
const update = useSelector((state: any) => state.dokumenUpdate)
|
||||||
|
const [isMoveCopy, setMoveCopy] = useState(false)
|
||||||
|
|
||||||
|
function cekFileSelected() {
|
||||||
|
const cek = data.some((i: any) => i.category == "FOLDER")
|
||||||
|
setForbidCopy(cek)
|
||||||
|
setNFileSelected(data.length)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
cekFileSelected()
|
||||||
|
}, [data])
|
||||||
|
|
||||||
|
async function handleMove(path: string) {
|
||||||
|
try {
|
||||||
|
const hasil = await decryptToken(String(token?.current))
|
||||||
|
const response = await apiMoveDocument({ user: hasil, dataItem: data, path })
|
||||||
|
if (response.success) {
|
||||||
|
ToastAndroid.show("Berhasil memindahkan file", ToastAndroid.SHORT)
|
||||||
|
dispatch(setUpdateDokumen(!update))
|
||||||
|
} else {
|
||||||
|
ToastAndroid.show(response.message, ToastAndroid.SHORT)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
ToastAndroid.show("Terjadi kesalahan", ToastAndroid.SHORT)
|
||||||
|
} finally {
|
||||||
|
setMoveCopy(false)
|
||||||
|
onClose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<View style={Styles.rowItemsCenter}>
|
||||||
|
{
|
||||||
|
!share &&
|
||||||
|
<MenuItemRow
|
||||||
|
icon={<MaterialCommunityIcons name="folder-move-outline" color="black" size={25} />}
|
||||||
|
title="Pindah"
|
||||||
|
onPress={() => {
|
||||||
|
setMoveCopy(true)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
{
|
||||||
|
!forbidCopy &&
|
||||||
|
<MenuItemRow
|
||||||
|
icon={<MaterialCommunityIcons name="folder-multiple-outline" color="black" size={25} />}
|
||||||
|
title="Salin"
|
||||||
|
onPress={() => {
|
||||||
|
// handleMoveCopy('copy')
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
{
|
||||||
|
nFileSelected == 1 &&
|
||||||
|
<MenuItemRow
|
||||||
|
icon={<MaterialCommunityIcons name="information-variant" color="black" size={25} />}
|
||||||
|
title="Informasi"
|
||||||
|
onPress={() => {
|
||||||
|
// onClose()
|
||||||
|
setInformasi(true)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<DrawerBottom animation="slide" isVisible={isInformasi} setVisible={setInformasi} title="Informasi Dokumen" height={80}>
|
||||||
|
<ModalInformasi data={data[0]} />
|
||||||
|
</DrawerBottom>
|
||||||
|
|
||||||
|
<ModalSalinMove open={isMoveCopy} close={() => setMoveCopy(false)} category={'move'} onConfirm={(value: string) => handleMove(value)} />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
import Styles from "@/constants/Styles"
|
import Styles from "@/constants/Styles"
|
||||||
|
import { apiGetDocument } from "@/lib/api"
|
||||||
|
import { useAuthSession } from "@/providers/AuthProvider"
|
||||||
import { AntDesign, Ionicons } from "@expo/vector-icons"
|
import { AntDesign, Ionicons } from "@expo/vector-icons"
|
||||||
|
import { useLocalSearchParams } from "expo-router"
|
||||||
|
import { useEffect, useState } from "react"
|
||||||
import { Pressable, Text, View } from "react-native"
|
import { Pressable, Text, View } from "react-native"
|
||||||
import BorderBottomItem from "../borderBottomItem"
|
import BorderBottomItem from "../borderBottomItem"
|
||||||
import DrawerBottom from "../drawerBottom"
|
import DrawerBottom from "../drawerBottom"
|
||||||
@@ -8,41 +12,92 @@ type Props = {
|
|||||||
open: boolean
|
open: boolean
|
||||||
close: (value: boolean) => void
|
close: (value: boolean) => void
|
||||||
category: 'copy' | 'move'
|
category: 'copy' | 'move'
|
||||||
|
onConfirm: (value: string) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ModalSalinMove({ open, close, category, }: Props) {
|
type DataProps = {
|
||||||
|
id: string;
|
||||||
|
category: string;
|
||||||
|
name: string;
|
||||||
|
extension: string;
|
||||||
|
idStorage: string;
|
||||||
|
path: string;
|
||||||
|
createdBy: string;
|
||||||
|
share: boolean;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
type PropsPath = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function ModalSalinMove({ open, close, category, onConfirm }: Props) {
|
||||||
|
const [data, setData] = useState<DataProps[]>([])
|
||||||
|
const { token, decryptToken } = useAuthSession()
|
||||||
|
const [path, setPath] = useState('home')
|
||||||
|
const { id } = useLocalSearchParams<{ id: string }>();
|
||||||
|
const [dataJalur, setDataJalur] = useState<PropsPath[]>([])
|
||||||
|
|
||||||
|
async function getData() {
|
||||||
|
try {
|
||||||
|
const hasil = await decryptToken(String(token?.current))
|
||||||
|
const response = await apiGetDocument({ user: hasil, path, division: id, category: 'folder' })
|
||||||
|
if (response.success) {
|
||||||
|
setData(response.data)
|
||||||
|
setDataJalur(response.jalur)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getData()
|
||||||
|
}, [path])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DrawerBottom animation="slide" isVisible={open} setVisible={close} title={category == 'copy' ? 'Pilih Lokasi Salin' : 'Pilih Lokasi Pemindahan'} height={75}>
|
<DrawerBottom animation="slide" isVisible={open} setVisible={close} title={category == 'copy' ? 'Pilih Lokasi Salin' : 'Pilih Lokasi Pemindahan'} height={75}>
|
||||||
<View style={[Styles.rowItemsCenter, Styles.mv05]}>
|
<View style={[Styles.rowItemsCenter, Styles.mv05]}>
|
||||||
<Text> home </Text>
|
{
|
||||||
|
dataJalur.map((item, index) => (
|
||||||
|
<Pressable
|
||||||
|
key={index}
|
||||||
|
style={[Styles.rowItemsCenter]}
|
||||||
|
onPress={() => {
|
||||||
|
setPath(item.id);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{item.id != "home" && (
|
||||||
<AntDesign name="right" style={[Styles.mh05, Styles.mt02]} />
|
<AntDesign name="right" style={[Styles.mh05, Styles.mt02]} />
|
||||||
<Text> folder 1 </Text>
|
)}
|
||||||
|
<Text> {item.name} </Text>
|
||||||
|
</Pressable>
|
||||||
|
))
|
||||||
|
}
|
||||||
</View>
|
</View>
|
||||||
<View>
|
<View>
|
||||||
|
{
|
||||||
|
data.map((item, index) => (
|
||||||
<BorderBottomItem
|
<BorderBottomItem
|
||||||
|
key={index}
|
||||||
borderType="bottom"
|
borderType="bottom"
|
||||||
icon={<Ionicons name="folder-open-sharp" color={'#f9cc40'} size={30} />}
|
icon={<Ionicons name="folder-open-sharp" color={'#f9cc40'} size={30} />}
|
||||||
title="Folder 1"
|
title={item.name}
|
||||||
titleWeight="normal"
|
|
||||||
/>
|
|
||||||
<BorderBottomItem
|
|
||||||
borderType="bottom"
|
|
||||||
icon={<Ionicons name="folder-open-sharp" color={'#f9cc40'} size={30} />}
|
|
||||||
title="Folder 2"
|
|
||||||
titleWeight="normal"
|
|
||||||
/>
|
|
||||||
<BorderBottomItem
|
|
||||||
borderType="bottom"
|
|
||||||
icon={<Ionicons name="folder-open-sharp" color={'#f9cc40'} size={30} />}
|
|
||||||
title="Folder 3"
|
|
||||||
titleWeight="normal"
|
titleWeight="normal"
|
||||||
|
onPress={() => {
|
||||||
|
setPath(item.id);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
|
))
|
||||||
|
}
|
||||||
</View>
|
</View>
|
||||||
<View style={[Styles.rowOnly, Styles.mt15, Styles.absolute0]}>
|
<View style={[Styles.rowOnly, Styles.mt15, Styles.absolute0]}>
|
||||||
<Pressable style={[Styles.pv05, Styles.borderRight, { width: '50%' }]} onPress={() => { close }}>
|
<Pressable style={[Styles.pv05, Styles.borderRight, { width: '50%' }]} onPress={() => close(false)}>
|
||||||
<Text style={[Styles.textDefaultSemiBold, { textAlign: 'center' }]}>BATAL</Text>
|
<Text style={[Styles.textDefaultSemiBold, { textAlign: 'center' }]}>BATAL</Text>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
<Pressable style={[Styles.pv05, { width: '50%' }]} onPress={() => { }}>
|
<Pressable style={[Styles.pv05, { width: '50%' }]} onPress={() => onConfirm(path)}>
|
||||||
<Text style={[Styles.textDefaultSemiBold, { textAlign: 'center' }]}>{category == 'copy' ? 'SALIN' : 'PINDAH'}</Text>
|
<Text style={[Styles.textDefaultSemiBold, { textAlign: 'center' }]}>{category == 'copy' ? 'SALIN' : 'PINDAH'}</Text>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ const data = {
|
|||||||
icon: <MaterialCommunityIcons name="gender-male-female" size={22} color="black" style={[Styles.mr10]} />
|
icon: <MaterialCommunityIcons name="gender-male-female" size={22} color="black" style={[Styles.mr10]} />
|
||||||
},
|
},
|
||||||
dokumen: {
|
dokumen: {
|
||||||
label: 'Nama Dokumen',
|
label: 'Dokumen',
|
||||||
icon: <MaterialCommunityIcons name="file-document-outline" size={22} color="black" style={[Styles.mr10]} />
|
icon: <MaterialCommunityIcons name="file-document-outline" size={22} color="black" style={[Styles.mr10]} />
|
||||||
},
|
},
|
||||||
type: {
|
type: {
|
||||||
@@ -68,7 +68,7 @@ export default function ItemDetailMember({ category, value, border }: Props) {
|
|||||||
{data[category].icon}
|
{data[category].icon}
|
||||||
<Text style={[Styles.textDefault]}>{data[category].label}</Text>
|
<Text style={[Styles.textDefault]}>{data[category].label}</Text>
|
||||||
</View>
|
</View>
|
||||||
<Text style={[Styles.textDefault]}>{value}</Text>
|
<Text style={[Styles.textDefault, Styles.w60, { textAlign: 'right' }]} numberOfLines={1} ellipsizeMode="tail">{value}</Text>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -8,9 +8,10 @@ type Props = {
|
|||||||
title?: string
|
title?: string
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
onSubmit: () => void
|
onSubmit: () => void
|
||||||
|
disableSubmit?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ModalFloat({ isVisible, setVisible, title, children, onSubmit }: Props) {
|
export default function ModalFloat({ isVisible, setVisible, title, children, onSubmit, disableSubmit }: Props) {
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
animationIn={"fadeIn"}
|
animationIn={"fadeIn"}
|
||||||
@@ -30,8 +31,8 @@ export default function ModalFloat({ isVisible, setVisible, title, children, onS
|
|||||||
<Pressable style={[Styles.ph15, Styles.pv05, Styles.round10, Styles.mr10]} onPress={() => { setVisible(false) }}>
|
<Pressable style={[Styles.ph15, Styles.pv05, Styles.round10, Styles.mr10]} onPress={() => { setVisible(false) }}>
|
||||||
<Text style={[Styles.textDefault]}>Batal</Text>
|
<Text style={[Styles.textDefault]}>Batal</Text>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
<Pressable style={[Styles.ph15, Styles.pv05, Styles.round10]} onPress={onSubmit}>
|
<Pressable style={[Styles.ph15, Styles.pv05, Styles.round10]} onPress={onSubmit} disabled={disableSubmit}>
|
||||||
<Text style={[Styles.textDefault]}>Simpan</Text>
|
<Text style={[Styles.textDefault, disableSubmit && Styles.cGray]}>Simpan</Text>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
44
lib/api.ts
44
lib/api.ts
@@ -399,7 +399,7 @@ export const apiGetDivisionMember = async ({ user, id, search }: { user: string,
|
|||||||
return response.data;
|
return response.data;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const apiCreateDivision = async (data: { data: { idGroup: string, name: string, desc: string }, member: [], admin: string[], user:string }) => {
|
export const apiCreateDivision = async (data: { data: { idGroup: string, name: string, desc: string }, member: [], admin: string[], user: string }) => {
|
||||||
const response = await api.post(`/mobile/division`, data)
|
const response = await api.post(`/mobile/division`, data)
|
||||||
return response.data;
|
return response.data;
|
||||||
};
|
};
|
||||||
@@ -570,3 +570,45 @@ export const apiDeleteTask = async (data: { user: string }, id: string) => {
|
|||||||
const response = await api.delete(`/mobile/task/${id}/lainnya`, { data })
|
const response = await api.delete(`/mobile/task/${id}/lainnya`, { data })
|
||||||
return response.data;
|
return response.data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const apiGetDocument = async ({ user, path, division, category }: { user: string, path: string, division: string, category: 'all' | 'folder' }) => {
|
||||||
|
const response = await api.get(`mobile/document?user=${user}&path=${path}&division=${division}&category=${category}`);
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const apiGetDocumentInformasi = async ({ user, item, cat }: { user: string, item: string, cat: 'share' | 'lainnya' }) => {
|
||||||
|
const response = await api.get(`mobile/document/more?user=${user}&item=${item}&cat=${cat}`);
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const apiDocumentRename = async (data: { name: string, user: string, id: string, path: string, idDivision: string, extension: string }) => {
|
||||||
|
const response = await api.put(`/mobile/document/`, data)
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const apiDocumentDelete = async (data: { user: string, data: any[] }) => {
|
||||||
|
const response = await api.delete(`/mobile/document`, { data })
|
||||||
|
return response.data
|
||||||
|
};
|
||||||
|
|
||||||
|
export const apiCreateFolderDocument = async (data: { name: string, path: string, idDivision: string, user: string }) => {
|
||||||
|
const response = await api.post(`/mobile/document/`, data)
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const apiUploadFileDocument = async ({ data }: { data: FormData }) => {
|
||||||
|
console.log(data)
|
||||||
|
const response = await api.post(`/mobile/document/upload`, data,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const apiMoveDocument = async (data: { path: string, dataItem: any[], user: string }) => {
|
||||||
|
const response = await api.post(`/mobile/document/more`, data)
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|||||||
14
lib/dokumenUpdate.ts
Normal file
14
lib/dokumenUpdate.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { createSlice } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
|
const dokumenUpdate = createSlice({
|
||||||
|
name: 'dokumenUpdate',
|
||||||
|
initialState: false,
|
||||||
|
reducers: {
|
||||||
|
setUpdateDokumen: (state, action) => {
|
||||||
|
return action.payload;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const { setUpdateDokumen } = dokumenUpdate.actions;
|
||||||
|
export default dokumenUpdate.reducer;
|
||||||
@@ -6,6 +6,7 @@ import discussionGeneralDetailUpdate from './discussionGeneralDetail';
|
|||||||
import discussionUpdate from './discussionUpdate';
|
import discussionUpdate from './discussionUpdate';
|
||||||
import divisionCreate from './divisionCreate';
|
import divisionCreate from './divisionCreate';
|
||||||
import divisionUpdate from './divisionUpdate';
|
import divisionUpdate from './divisionUpdate';
|
||||||
|
import dokumenUpdate from './dokumenUpdate';
|
||||||
import entitiesReducer from './entitiesSlice';
|
import entitiesReducer from './entitiesSlice';
|
||||||
import filterSlice from './filterSlice';
|
import filterSlice from './filterSlice';
|
||||||
import groupUpdate from './groupSlice';
|
import groupUpdate from './groupSlice';
|
||||||
@@ -36,6 +37,7 @@ const store = configureStore({
|
|||||||
calendarUpdate: calendarUpdate,
|
calendarUpdate: calendarUpdate,
|
||||||
taskUpdate: taskUpdate,
|
taskUpdate: taskUpdate,
|
||||||
divisionCreate: divisionCreate,
|
divisionCreate: divisionCreate,
|
||||||
|
dokumenUpdate: dokumenUpdate,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user