-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathDashboard.vue
162 lines (151 loc) · 6.63 KB
/
Dashboard.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
<template>
<AppLayout title="Dashboard">
<template #header>
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
Dashboard
</h2>
</template>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-xl sm:rounded-lg p-6">
<form @submit.prevent="submit">
<div>
<label class="block font-medium text-sm text-gray-700">
<span>Name</span>
</label>
<input
type="text"
name="name"
class="border-gray-300 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 rounded-md shadow-sm w-full"
v-model="form.name"
/>
<div v-if="form.errors.name" class="text-red-500">{{ form.errors.name }}</div>
</div>
<div class="mt-4">
<label class="block font-medium text-sm text-gray-700">
<span>Email</span>
</label>
<input
type="email"
name="email"
class="border-gray-300 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 rounded-md shadow-sm w-full"
v-model="form.email"
/>
<div v-if="form.errors.email" class="text-red-500">{{ form.errors.email }}</div>
</div>
<div class="mt-4">
<label class="block font-medium text-sm text-gray-700">
<span>Avatar</span>
</label>
<FilePond
name="avatar"
ref="filepondAvatarInput"
class-name="my-pond"
allow-multiple="false"
accepted-file-types="image/*"
@init="handleFilePondInit"
@processfile="handleFilePondAvatarProcess"
@removefile="handleFilePondAvatarRemoveFile"
/>
</div>
<div class="mt-4">
<label class="block font-medium text-sm text-gray-700">
<span>Gallery</span>
</label>
<FilePond
name="gallery"
ref="filepondGalleryInput"
class-name="my-pond"
allow-multiple="true"
accepted-file-types="image/*"
@init="handleFilePondInit"
@processfile="handleFilePondGalleryProcess"
@removefile="handleFilePondGalleryRemoveFile"
/>
<div v-if="form.errors">
<div v-for="(error, index) in form.errors" class="text-red-500">{{ error }}</div>
</div>
</div>
<button
type="submit"
class="inline-flex items-center justify-center mt-3 p-3 bg-gray-800 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-gray-700 active:bg-gray-900 focus:outline-none focus:border-gray-900 focus:ring focus:ring-gray-300 disabled:opacity-25 transition w-full"
:disabled="form.processing"
>
Submit
</button>
</form>
</div>
</div>
</div>
</AppLayout>
</template>
<script setup>
import AppLayout from "../Layouts/AppLayout";
import { useForm } from "@inertiajs/inertia-vue3";
import { ref } from "vue";
// Import filepond
import vueFilePond, { setOptions } from 'vue-filepond';
// Import filepond plugins
import FilePondPluginFileValidateType from 'filepond-plugin-file-validate-type/dist/filepond-plugin-file-validate-type.esm.js';
import FilePondPluginImagePreview from 'filepond-plugin-image-preview/dist/filepond-plugin-image-preview.esm.js';
// Import filepond styles
import 'filepond/dist/filepond.min.css';
import 'filepond-plugin-image-preview/dist/filepond-plugin-image-preview.min.css';
const props = defineProps({
user: Object,
csrf_token: String
});
const filepondAvatarInput = ref(null); // Reference the input to clear the files later
const filepondGalleryInput = ref(null); // Reference the input to clear the files later
const form = useForm({
name: props.user.name,
email: props.user.email,
avatar: null,
gallery: [],
});
const submit = () => {
form
.transform((data) => {
return {
...data,
gallery: data.gallery.map(item => item.serverId) // Pluck only the serverIds
}
})
.put(route('update-profile'), {
onSuccess: () => {
filepondAvatarInput.value.removeFiles();
filepondGalleryInput.value.removeFiles();
},
});
};
// Create FilePond component
const FilePond = vueFilePond(FilePondPluginFileValidateType, FilePondPluginImagePreview);
// Set global options on filepond init
const handleFilePondInit = () => {
setOptions({
credits: false,
server: {
url: '/filepond',
headers: {
'X-CSRF-TOKEN': props.csrf_token,
}
}
});
};
// Set the server id from response
const handleFilePondAvatarProcess = (error, file) => {
form.avatar = file.serverId;
};
// Remove the server id on file remove
const handleFilePondAvatarRemoveFile = (error, file) => {
form.avatar = null;
};
// Set the server id from response
const handleFilePondGalleryProcess = (error, file) => {
form.gallery.push({id: file.id, serverId: file.serverId});
};
// Remove the server id on file remove
const handleFilePondGalleryRemoveFile = (error, file) => {
form.gallery = form.gallery.filter(item => item.id !== file.id);
}
</script>