laravel-vue-file-share/resources/js/Layouts/AuthenticatedLayout.vue
2023-10-17 22:45:04 -07:00

121 lines
4.1 KiB
Vue

<script setup>
import Navigation from "@/Components/custom/Navigation.vue";
import SearchForm from "@/Components/custom/SearchForm.vue";
import UserDropdown from "@/Components/custom/UserDropdown.vue";
import FileUploadErrorModal from "@/Components/custom/FileUploadErrorModal.vue";
import { emitter } from "@/emitter.js";
import { ref, onMounted } from "vue";
import { useForm, usePage } from "@inertiajs/vue3";
// get current page for file uploading
const page = usePage();
// make refs
const dragging = ref(false);
const fileUploadError = ref(false);
const draggable = ref(false);
// add Mitt event listener on component load
onMounted(() => {
emitter.on("FILE_UPLOAD_STARTED", uploadFiles);
// determines whether this page is draggable
const regex = new RegExp("/files.*", "gi");
if (regex.test(page.url)) draggable.value = true;
});
// file drop function
const onDrop = (event) => {
dragging.value = false;
// get dragged files
const files = event.dataTransfer.files;
// check if files exist, then upload
// note that folders can be falsy here
if (files.length) {
uploadFiles(files);
}
};
// create form input for file upload
const fileUpload = useForm({
files: [],
paths: [],
parent_id: null,
});
// upload files function
const uploadFiles = (files) => {
// fill out form
fileUpload.files = files;
fileUpload.parent_id = page.props.folder.id;
fileUpload.paths = Array.from(files).map((file) => file.webkitRelativePath);
// send form to backend for processing
fileUpload.post(route("file.upload"), {
onError: (errors) => {
if (Object.keys(errors).length > 0) {
message = errors[Object.keys(errors)[0]];
fileUploadError.value = message;
} else {
message =
"Errors encountered while uploading file. Please try again.";
}
},
});
};
</script>
<template>
<div class="h-screen w-full bg-zinc-900 text-gray-100 flex gap-4">
<Navigation />
<main
v-if="draggable"
@drop.prevent="onDrop"
@dragover.prevent="dragging = true"
@dragleave.prevent="dragging = false"
class="flex flex-col flex-1 px-4 overflow-hidden"
>
<template v-if="dragging">
<div
class="text-lg w-full h-full flex flex-col items-center justify-center border-2 border-dashed border-gray-700"
>
<div
class="w-40 h-40 border-2 rounded-lg border-gray-700 text-gray-300 text-6xl flex items-center justify-center"
>
<div class="arrow">+</div>
</div>
</div>
</template>
<template v-else>
<div class="flex items-center justify-between w-full">
<SearchForm />
<UserDropdown />
</div>
<div class="flex-1 flex flex-col overflow-hidden">
<div class="h-4 bg-zinc-900" v-if="fileUpload.progress">
<div
class="h-full bg-sky-600 transition-all"
:style="{ width: `${form.progress.percentage}%` }"
></div>
</div>
<slot />
</div>
</template>
</main>
<main v-else class="flex flex-col flex-1 px-4 overflow-hidden">
<div class="flex items-center justify-between w-full">
<SearchForm />
<UserDropdown />
</div>
<div class="flex-1 flex flex-col overflow-hidden">
<slot />
</div>
</main>
</div>
<FileUploadErrorModal v-if="fileUploadError" :message="fileUploadError">
<button
@click="fileUploadError = false"
class="border border-sky-600 px-5 py-3 rounded hover:bg-sky-600"
>
OK
</button>
</FileUploadErrorModal>
</template>