@meeovi/layer-lists 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/components/features/archived.vue +64 -0
- package/app/components/features/bookmarks.vue +64 -0
- package/app/components/features/lists.vue +61 -0
- package/app/components/features/starred.vue +64 -0
- package/app/components/lists/ListItemCard.vue +190 -0
- package/app/components/lists/add-bookmark.vue +52 -0
- package/app/components/lists/add-list-item.vue +88 -0
- package/app/components/lists/add-list.vue +57 -0
- package/app/components/lists/lists.vue +6 -0
- package/app/components/lists/listsettings.vue +145 -0
- package/app/components/lists/update-bookmark.vue +267 -0
- package/app/components/lists/update-list.vue +192 -0
- package/app/components/media/MediaPlayer.vue +302 -0
- package/app/components/partials/addtolist.vue +233 -0
- package/app/components/partials/createListBtn.vue +95 -0
- package/app/components/partials/listBtn.vue +35 -0
- package/app/components/related/list.vue +33 -0
- package/app/components/related/relatedlists.vue +43 -0
- package/app/components/tasks/TaskItem.vue +204 -0
- package/app/composables/bookmarks/createBookmark.js +30 -0
- package/app/composables/bookmarks/deleteBookmark.js +15 -0
- package/app/composables/bookmarks/updateBookmark.js +15 -0
- package/app/composables/config.ts +17 -0
- package/app/composables/content/uploadFiles.js +41 -0
- package/app/composables/globals/useDirectusForm.ts +1 -0
- package/app/composables/lists/createList.js +25 -0
- package/app/composables/lists/deleteList.js +14 -0
- package/app/composables/lists/updateList.js +20 -0
- package/app/composables/lists/useBookmarks.js +69 -0
- package/app/composables/lists/useLists.js +120 -0
- package/app/composables/lists/usePlaylist.js +64 -0
- package/app/composables/lists/useSaved.js +29 -0
- package/app/composables/lists/useTasks.js +86 -0
- package/app/composables/lists/useWishlist.js +51 -0
- package/app/composables/providers/atproto.ts +156 -0
- package/app/composables/providers/directus.ts +49 -0
- package/app/composables/providers/memory.ts +88 -0
- package/app/composables/registry.ts +13 -0
- package/app/composables/types.ts +35 -0
- package/app/composables/useLists.ts +20 -0
- package/app/composables/utils/transforms.ts +42 -0
- package/app/composables/utils/validation.ts +21 -0
- package/app/pages/lists/bookmark/[id].vue +76 -0
- package/app/pages/lists/index.vue +152 -0
- package/app/pages/lists/list/[...slug].vue +233 -0
- package/nuxt.config.ts +11 -0
- package/package.json +26 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<v-card elevation="0">
|
|
4
|
+
<v-toolbar title="Update A List"></v-toolbar>
|
|
5
|
+
<v-form @submit.prevent="createList">
|
|
6
|
+
<v-container>
|
|
7
|
+
<v-row>
|
|
8
|
+
<v-col cols="6">
|
|
9
|
+
<v-text-field v-model="title" label="List Name" required></v-text-field>
|
|
10
|
+
</v-col>
|
|
11
|
+
<v-col cols="6">
|
|
12
|
+
<v-combobox v-model="type" label="Type" :items="['List', 'Registry', 'Playlist', 'Todo']"></v-combobox>
|
|
13
|
+
</v-col>
|
|
14
|
+
<v-col cols="12">
|
|
15
|
+
<v-file-input clearable label="List Image"></v-file-input>
|
|
16
|
+
</v-col>
|
|
17
|
+
<v-col cols="12">
|
|
18
|
+
<v-textarea v-model="description" label="List Description"></v-textarea>
|
|
19
|
+
</v-col>
|
|
20
|
+
<v-col cols="12">
|
|
21
|
+
<v-card title="Choose a Product for your List">
|
|
22
|
+
<v-card-text>
|
|
23
|
+
<v-text-field density="compact" variant="solo" label="Search Meeovi for products"
|
|
24
|
+
append-inner-icon="fas:fa fa-search" single-line hide-details
|
|
25
|
+
@click:append-inner="onClick"></v-text-field>
|
|
26
|
+
<v-spacer></v-spacer>
|
|
27
|
+
<div class="d-flex pa-4">
|
|
28
|
+
<v-checkbox-btn v-model="includeFiles" class="pe-2" color="orange">
|
|
29
|
+
</v-checkbox-btn>
|
|
30
|
+
<!--<NuxtLink :to="`/product/${products.id}`">
|
|
31
|
+
<v-card class="ma-4" height="580" width="250" @click="toggle">
|
|
32
|
+
<NuxtImg loading="lazy" class="align-end text-white" height="280"
|
|
33
|
+
:src="`${products.featuredAsset.preview}`" :alt="products.name" cover />
|
|
34
|
+
|
|
35
|
+
<v-card-title class="pt-4">
|
|
36
|
+
{{ products.name }}
|
|
37
|
+
</v-card-title>
|
|
38
|
+
|
|
39
|
+
<v-card-text>
|
|
40
|
+
<div>Sku: {{ products.variants.sku }}</div>
|
|
41
|
+
</v-card-text>
|
|
42
|
+
|
|
43
|
+
<v-card-actions>
|
|
44
|
+
<v-card-title>$ {{ products.variants.price }}
|
|
45
|
+
</v-card-title>
|
|
46
|
+
</v-card-actions>
|
|
47
|
+
<div class="d-flex fill-height align-center justify-center">
|
|
48
|
+
<v-scale-transition>
|
|
49
|
+
<v-icon v-if="isSelected" color="white" size="48"
|
|
50
|
+
icon="mdi-close-circle-outline"></v-icon>
|
|
51
|
+
</v-scale-transition>
|
|
52
|
+
</div>
|
|
53
|
+
</v-card>
|
|
54
|
+
</NuxtLink>-->
|
|
55
|
+
</div>
|
|
56
|
+
</v-card-text>
|
|
57
|
+
</v-card>
|
|
58
|
+
</v-col>
|
|
59
|
+
</v-row>
|
|
60
|
+
</v-container>
|
|
61
|
+
|
|
62
|
+
<v-divider class="mt-12"></v-divider>
|
|
63
|
+
<v-card-actions>
|
|
64
|
+
<v-btn color="blue-darken-1" variant="text" type="submit" @click="reset = false">
|
|
65
|
+
Delete
|
|
66
|
+
</v-btn>
|
|
67
|
+
<v-spacer></v-spacer>
|
|
68
|
+
<v-btn color="blue-darken-1" variant="text" type="submit">
|
|
69
|
+
Update
|
|
70
|
+
</v-btn>
|
|
71
|
+
</v-card-actions>
|
|
72
|
+
</v-form>
|
|
73
|
+
</v-card>
|
|
74
|
+
</div>
|
|
75
|
+
</template>
|
|
76
|
+
|
|
77
|
+
<script setup>
|
|
78
|
+
import {
|
|
79
|
+
ref
|
|
80
|
+
} from 'vue'
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
const config = useRuntimeConfig();
|
|
84
|
+
const dialog = ref(false);
|
|
85
|
+
const includeFiles = ref(true);
|
|
86
|
+
const enabled = ref(false);
|
|
87
|
+
const title = ref('');
|
|
88
|
+
const acf = ref('');
|
|
89
|
+
const ispublic = ref('');
|
|
90
|
+
const description = ref('');
|
|
91
|
+
const type = ref('');
|
|
92
|
+
const products = ref('');
|
|
93
|
+
const owner = ref('');
|
|
94
|
+
const image = ref('');
|
|
95
|
+
const errorMessage = ref('');
|
|
96
|
+
const successMessage = ref('');
|
|
97
|
+
|
|
98
|
+
const updatelist = async () => {
|
|
99
|
+
try {
|
|
100
|
+
const response = await $fetch(`${config.apiUrl}/wp-json/wp/v2/list`, {
|
|
101
|
+
method: 'PUT',
|
|
102
|
+
headers: {
|
|
103
|
+
'Content-Type': 'application/json',
|
|
104
|
+
'Authorization': `Bearer ${config.wordpressToken}`
|
|
105
|
+
},
|
|
106
|
+
body: JSON.stringify({
|
|
107
|
+
title: title.value,
|
|
108
|
+
ispublic: ispublic.value,
|
|
109
|
+
description: description.value,
|
|
110
|
+
image: image.value,
|
|
111
|
+
type: type.value,
|
|
112
|
+
products: products.value,
|
|
113
|
+
owner: owner.value,
|
|
114
|
+
status: 'publish',
|
|
115
|
+
})
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
console.log(response);
|
|
119
|
+
|
|
120
|
+
if (response.id) {
|
|
121
|
+
successMessage.value = 'List updated successfully!'
|
|
122
|
+
errorMessage.value = ''
|
|
123
|
+
} else {
|
|
124
|
+
throw new Error('Failed to update list')
|
|
125
|
+
}
|
|
126
|
+
} catch (error) {
|
|
127
|
+
console.error('Error updating list:', error);
|
|
128
|
+
if (error.response) {
|
|
129
|
+
console.error('Error response:', error.response);
|
|
130
|
+
if (error.response.status === 403) {
|
|
131
|
+
errorMessage.value = 'You do not have permission to update a list.'
|
|
132
|
+
} else {
|
|
133
|
+
errorMessage.value = `Error: ${error.response.status} ${error.response.statusText}`
|
|
134
|
+
}
|
|
135
|
+
} else {
|
|
136
|
+
errorMessage.value = error.message
|
|
137
|
+
}
|
|
138
|
+
successMessage.value = ''
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
useHead({
|
|
143
|
+
title: 'Update List',
|
|
144
|
+
})
|
|
145
|
+
</script>
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<v-row justify="center">
|
|
4
|
+
<v-dialog v-model="dialog" :scrim="false" transition="dialog-bottom-transition" @show="fetchBookmarkData">
|
|
5
|
+
<template v-slot:activator="{ props }">
|
|
6
|
+
<v-btn v-bind="props">
|
|
7
|
+
<v-icon start icon="fas:fa fa-plus"></v-icon>Update Address
|
|
8
|
+
</v-btn>
|
|
9
|
+
</template>
|
|
10
|
+
<v-card>
|
|
11
|
+
<form @submit.prevent="handleSubmit">
|
|
12
|
+
<v-card>
|
|
13
|
+
<v-card-text>
|
|
14
|
+
<v-row>
|
|
15
|
+
<v-col cols="6"><v-text-field v-model="bookmarkData.name" id="bookmarkName"
|
|
16
|
+
label="Bookmark Name*" required /></v-col>
|
|
17
|
+
<v-col cols="6"><v-text-field v-model="bookmarkData.url" id="bookmarkUrl"
|
|
18
|
+
label="Bookmark Url*" required /></v-col>
|
|
19
|
+
<v-col cols="6">
|
|
20
|
+
<v-select v-model="bookmarkData.type" label="What type of bookmark is this?"
|
|
21
|
+
:items="['Website', 'Password']" />
|
|
22
|
+
</v-col>
|
|
23
|
+
<v-col cols="6">
|
|
24
|
+
<v-select v-model="bookmarkData.status"
|
|
25
|
+
label="Is this bookmark public or private?"
|
|
26
|
+
:items="['Public', 'Private']" />
|
|
27
|
+
</v-col>
|
|
28
|
+
<v-col cols="12">
|
|
29
|
+
<v-file-input @change="handleImageUpload" clearable density="compact"
|
|
30
|
+
prepend-icon="fas:fa fa-image" accept="image/*" label="Image"
|
|
31
|
+
variant="solo-inverted" />
|
|
32
|
+
</v-col>
|
|
33
|
+
<v-col cols="12"><v-textarea v-model="bookmarkData.note" label="Note"
|
|
34
|
+
variant="outlined"></v-textarea></v-col>
|
|
35
|
+
</v-row>
|
|
36
|
+
</v-card-text>
|
|
37
|
+
<v-divider class="mt-12"></v-divider>
|
|
38
|
+
<v-card-actions>
|
|
39
|
+
<v-btn color="blue-darken-1" variant="text" @click="isActive.value = false">
|
|
40
|
+
Close
|
|
41
|
+
</v-btn>
|
|
42
|
+
<v-spacer></v-spacer>
|
|
43
|
+
<v-btn color="blue-darken-1" variant="text" type="submit" @click="confirmDelete"
|
|
44
|
+
:loading="deleteLoading">
|
|
45
|
+
Delete Bookmark
|
|
46
|
+
</v-btn>
|
|
47
|
+
<v-btn color="blue-darken-1" variant="text" type="submit">
|
|
48
|
+
Update Bookmark
|
|
49
|
+
</v-btn>
|
|
50
|
+
</v-card-actions>
|
|
51
|
+
</v-card>
|
|
52
|
+
</form>
|
|
53
|
+
|
|
54
|
+
<!-- Delete Confirmation Dialog -->
|
|
55
|
+
<v-dialog v-model="deleteDialog" max-width="500px">
|
|
56
|
+
<v-card>
|
|
57
|
+
<v-card-title class="text-h5">Delete Bookmark</v-card-title>
|
|
58
|
+
<v-card-text>
|
|
59
|
+
Are you sure you want to delete this bookmark? This action cannot be undone.
|
|
60
|
+
</v-card-text>
|
|
61
|
+
<v-card-actions>
|
|
62
|
+
<v-spacer></v-spacer>
|
|
63
|
+
<v-btn color="blue-darken-1" variant="text" @click="deleteDialog = false">
|
|
64
|
+
Cancel
|
|
65
|
+
</v-btn>
|
|
66
|
+
<v-btn color="error" variant="text" @click="deleteBookmark" :loading="deleteLoading">
|
|
67
|
+
Delete
|
|
68
|
+
</v-btn>
|
|
69
|
+
</v-card-actions>
|
|
70
|
+
</v-card>
|
|
71
|
+
</v-dialog>
|
|
72
|
+
</v-card>
|
|
73
|
+
</v-dialog>
|
|
74
|
+
</v-row>
|
|
75
|
+
</div>
|
|
76
|
+
</template>
|
|
77
|
+
|
|
78
|
+
<script>
|
|
79
|
+
export default {
|
|
80
|
+
methods: {
|
|
81
|
+
reset() {
|
|
82
|
+
this.$refs.form.reset()
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
}
|
|
86
|
+
</script>
|
|
87
|
+
|
|
88
|
+
<script setup>
|
|
89
|
+
import {
|
|
90
|
+
ref
|
|
91
|
+
} from 'vue';
|
|
92
|
+
import {
|
|
93
|
+
useRoute,
|
|
94
|
+
useRouter
|
|
95
|
+
} from 'vue-router';
|
|
96
|
+
import uploadFiles from '~/app/composables/content/uploadFiles';
|
|
97
|
+
import updateBookmark from '~/app/composables/bookmarks/updateBookmark';
|
|
98
|
+
import {
|
|
99
|
+
updateItem,
|
|
100
|
+
deleteItem
|
|
101
|
+
} from '@meeovi/directus-client';
|
|
102
|
+
import {
|
|
103
|
+
useUserStore
|
|
104
|
+
} from '#auth/app/stores/user'
|
|
105
|
+
|
|
106
|
+
const userStore = useUserStore()
|
|
107
|
+
|
|
108
|
+
const userDisplayName = computed(() => {
|
|
109
|
+
return userStore.user?.name || userStore.user?.username || 'User'
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
const route = useRoute();
|
|
113
|
+
|
|
114
|
+
const id = route.params.id;
|
|
115
|
+
|
|
116
|
+
// Add these new refs for delete functionality
|
|
117
|
+
const deleteDialog = ref(false);
|
|
118
|
+
const deleteLoading = ref(false);
|
|
119
|
+
|
|
120
|
+
const bookmarkData = ref({
|
|
121
|
+
name: '',
|
|
122
|
+
url: '',
|
|
123
|
+
type: '',
|
|
124
|
+
status: '',
|
|
125
|
+
note: '',
|
|
126
|
+
image: null,
|
|
127
|
+
username: userDisplayName,
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
const dialog = ref(false);
|
|
131
|
+
const location = ref('bottom');
|
|
132
|
+
|
|
133
|
+
const imageFile = ref(null);
|
|
134
|
+
const loading = ref(false);
|
|
135
|
+
|
|
136
|
+
// Function to fetch existing bookmark data
|
|
137
|
+
const fetchBookmarkData = async () => {
|
|
138
|
+
try {
|
|
139
|
+
const {
|
|
140
|
+
$directus,
|
|
141
|
+
$readItem
|
|
142
|
+
} = useNuxtApp();
|
|
143
|
+
const bookmarkId = route.params.id;
|
|
144
|
+
|
|
145
|
+
if (!bookmarkId) return;
|
|
146
|
+
|
|
147
|
+
const response = await $directus.request($readItem('websites', bookmarkId));
|
|
148
|
+
|
|
149
|
+
if (response) {
|
|
150
|
+
bookmarkData.value = {
|
|
151
|
+
id: response.id,
|
|
152
|
+
name: response.name || '',
|
|
153
|
+
type: response.type || '',
|
|
154
|
+
status: response.status || '',
|
|
155
|
+
note: response.note || '',
|
|
156
|
+
image: response.image || '',
|
|
157
|
+
url: response.url || '',
|
|
158
|
+
username: response.username || userDisplayName
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
} catch (error) {
|
|
162
|
+
console.error('Error fetching bookmark:', error);
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
// Load existing data when component mounts
|
|
167
|
+
onMounted(() => {
|
|
168
|
+
if (route.params.id) {
|
|
169
|
+
fetchBookmarkData();
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
// Emit event for parent component updates
|
|
173
|
+
const emit = defineEmits(['bookmark-updated']);
|
|
174
|
+
|
|
175
|
+
const handleImageUpload = (event) => {
|
|
176
|
+
imageFile.value = event.target.files[0];
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const handleSubmit = async () => {
|
|
180
|
+
try {
|
|
181
|
+
loading.value = true;
|
|
182
|
+
|
|
183
|
+
const {
|
|
184
|
+
$directus
|
|
185
|
+
} = useNuxtApp();
|
|
186
|
+
|
|
187
|
+
// Prepare update data
|
|
188
|
+
const updateData = {
|
|
189
|
+
id: bookmarkData.value.id,
|
|
190
|
+
name: bookmarkData.value.name,
|
|
191
|
+
type: bookmarkData.value.type,
|
|
192
|
+
status: bookmarkData.value.status,
|
|
193
|
+
note: bookmarkData.value.note,
|
|
194
|
+
image: bookmarkData.value.image,
|
|
195
|
+
url: bookmarkData.value.url,
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
// Handle image upload if there's a new image
|
|
199
|
+
if (imageFile.value) {
|
|
200
|
+
const uploadedFiles = await uploadFiles({
|
|
201
|
+
imageFile: imageFile.value,
|
|
202
|
+
});
|
|
203
|
+
updateData.image = uploadedFiles.imageId;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Update the bookmark using Directus updateItem
|
|
207
|
+
const updatedBookmark = await $directus.request(
|
|
208
|
+
updateItem('websites', route.params.id, updateData)
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
if (updatedBookmark) {
|
|
212
|
+
// Refresh the bookmark data
|
|
213
|
+
await fetchBookmarkData();
|
|
214
|
+
|
|
215
|
+
// Show success message
|
|
216
|
+
alert('Bookmark updated successfully');
|
|
217
|
+
} else {
|
|
218
|
+
throw new Error('Failed to update bookmark');
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
} catch (error) {
|
|
222
|
+
console.error('Error updating bookmark:', error);
|
|
223
|
+
alert('Error updating bookmark: ' + error.message);
|
|
224
|
+
} finally {
|
|
225
|
+
loading.value = false;
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
// Remove the onMounted hook since we'll use the dialog @show event instead
|
|
230
|
+
// Instead, watch for dialog changes
|
|
231
|
+
watch(dialog, (newValue) => {
|
|
232
|
+
if (newValue && route.params.id) {
|
|
233
|
+
fetchBookmarkData();
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
// Add these new functions for delete functionality
|
|
238
|
+
const confirmDelete = () => {
|
|
239
|
+
deleteDialog.value = true;
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
const deleteBookmark = async () => {
|
|
243
|
+
try {
|
|
244
|
+
deleteLoading.value = true;
|
|
245
|
+
const {
|
|
246
|
+
$directus
|
|
247
|
+
} = useNuxtApp();
|
|
248
|
+
|
|
249
|
+
// Delete the bookmark using the imported deleteItem function
|
|
250
|
+
await $directus.request(deleteItem('websites', route.params.id));
|
|
251
|
+
|
|
252
|
+
// Close the delete dialog
|
|
253
|
+
deleteDialog.value = false;
|
|
254
|
+
|
|
255
|
+
// Show success message
|
|
256
|
+
alert('Bookmark deleted successfully');
|
|
257
|
+
|
|
258
|
+
// Redirect to bookmarks page
|
|
259
|
+
navigateTo('/commerce/lists');
|
|
260
|
+
} catch (error) {
|
|
261
|
+
console.error('Error deleting bookmark:', error);
|
|
262
|
+
alert('Error deleting bookmark: ' + error.message);
|
|
263
|
+
} finally {
|
|
264
|
+
deleteLoading.value = false;
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
</script>
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<v-row justify="center">
|
|
4
|
+
<v-card>
|
|
5
|
+
<form @submit.prevent="handleSubmit">
|
|
6
|
+
<v-toolbar dark color="primary">
|
|
7
|
+
<v-btn icon dark @click="dialog = false">
|
|
8
|
+
<v-icon icon="fas:fa fa-circle-xmark"></v-icon>
|
|
9
|
+
</v-btn>
|
|
10
|
+
<v-card-title>
|
|
11
|
+
<span class="text-h6">Create a new Space</span>
|
|
12
|
+
</v-card-title>
|
|
13
|
+
</v-toolbar>
|
|
14
|
+
<v-card-text>
|
|
15
|
+
<v-container>
|
|
16
|
+
<v-row>
|
|
17
|
+
<v-col cols="12">
|
|
18
|
+
<v-text-field v-model="listData.name" label="List Name" required></v-text-field>
|
|
19
|
+
</v-col>
|
|
20
|
+
<v-col cols="6">
|
|
21
|
+
<v-select v-model="listData.type" label="Type"
|
|
22
|
+
:items="['List', 'Registry', 'Playlist', 'Todo']"></v-select>
|
|
23
|
+
</v-col>
|
|
24
|
+
<v-col cols="6">
|
|
25
|
+
<v-select v-model="listData.status" label="Status"
|
|
26
|
+
:items="['Public', 'Private']"></v-select>
|
|
27
|
+
</v-col>
|
|
28
|
+
<v-col cols="12">
|
|
29
|
+
<v-file-input @change="handleImageUpload" clearable
|
|
30
|
+
density="compact" prepend-icon="fas:fa fa-image" accept="image/*"
|
|
31
|
+
label="Image for List" variant="solo-inverted" />
|
|
32
|
+
</v-col>
|
|
33
|
+
<v-col cols="12">
|
|
34
|
+
<v-textarea v-model="listData.description" label="List Description"></v-textarea>
|
|
35
|
+
</v-col>
|
|
36
|
+
<v-col cols="12">
|
|
37
|
+
<v-card title="Choose a Product for your List">
|
|
38
|
+
<v-card-text>
|
|
39
|
+
<v-text-field density="compact" variant="solo"
|
|
40
|
+
label="Search Meeovi for products" append-inner-icon="fas:fa fa-search"
|
|
41
|
+
single-line hide-details></v-text-field>
|
|
42
|
+
<div class="d-flex pa-4">
|
|
43
|
+
<v-checkbox-btn v-model="includeFiles" class="pe-2" color="orange">
|
|
44
|
+
</v-checkbox-btn>
|
|
45
|
+
<!--<NuxtLink :to="`/product/${products.id}`">
|
|
46
|
+
<v-card class="ma-4" height="580" width="250" @click="toggle">
|
|
47
|
+
<NuxtImg loading="lazy" class="align-end text-white" height="280"
|
|
48
|
+
:src="`${products.featuredAsset.preview}`" :alt="products.name" cover />
|
|
49
|
+
|
|
50
|
+
<v-card-title class="pt-4">
|
|
51
|
+
{{ products.name }}
|
|
52
|
+
</v-card-title>
|
|
53
|
+
|
|
54
|
+
<v-card-text>
|
|
55
|
+
<div>Sku: {{ products.variants.sku }}</div>
|
|
56
|
+
</v-card-text>
|
|
57
|
+
|
|
58
|
+
<v-card-actions>
|
|
59
|
+
<v-card-title>$ {{ products.variants.price }}
|
|
60
|
+
</v-card-title>
|
|
61
|
+
</v-card-actions>
|
|
62
|
+
<div class="d-flex fill-height align-center justify-center">
|
|
63
|
+
<v-scale-transition>
|
|
64
|
+
<v-icon v-if="isSelected" color="white" size="48"
|
|
65
|
+
icon="mdi-close-circle-outline"></v-icon>
|
|
66
|
+
</v-scale-transition>
|
|
67
|
+
</div>
|
|
68
|
+
</v-card>
|
|
69
|
+
</NuxtLink>-->
|
|
70
|
+
</div>
|
|
71
|
+
</v-card-text>
|
|
72
|
+
</v-card>
|
|
73
|
+
</v-col>
|
|
74
|
+
</v-row>
|
|
75
|
+
</v-container>
|
|
76
|
+
<small>*indicates required field</small>
|
|
77
|
+
</v-card-text>
|
|
78
|
+
<v-divider class="mt-12"></v-divider>
|
|
79
|
+
<v-card-actions>
|
|
80
|
+
<v-btn color="blue-darken-1" variant="text" type="submit" @click="resetForm = false">
|
|
81
|
+
Reset
|
|
82
|
+
</v-btn>
|
|
83
|
+
<v-btn color="blue-darken-1" variant="text" type="submit">
|
|
84
|
+
Update
|
|
85
|
+
</v-btn>
|
|
86
|
+
</v-card-actions>
|
|
87
|
+
</form>
|
|
88
|
+
</v-card>
|
|
89
|
+
</v-row>
|
|
90
|
+
</div>
|
|
91
|
+
</template>
|
|
92
|
+
|
|
93
|
+
<script setup>
|
|
94
|
+
import { ref, onMounted } from 'vue';
|
|
95
|
+
import { useRoute, useRouter } from 'vue-router';
|
|
96
|
+
import uploadFiles from '~//composables/uploadFiles';
|
|
97
|
+
import updateList from '~/app/composables/lists/updateList';
|
|
98
|
+
|
|
99
|
+
const route = useRoute();
|
|
100
|
+
const router = useRouter();
|
|
101
|
+
|
|
102
|
+
const listData = ref({
|
|
103
|
+
id: '', // Add this to store the list ID
|
|
104
|
+
name: '',
|
|
105
|
+
type: '',
|
|
106
|
+
status: '',
|
|
107
|
+
description: '',
|
|
108
|
+
image: null,
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const dialog = ref(false);
|
|
112
|
+
const includeFiles = ref(true);
|
|
113
|
+
const imageFile = ref(null);
|
|
114
|
+
const loading = ref(false);
|
|
115
|
+
|
|
116
|
+
// Function to fetch existing list data
|
|
117
|
+
const fetchListData = async () => {
|
|
118
|
+
try {
|
|
119
|
+
const { $directus, $readItem } = useNuxtApp();
|
|
120
|
+
const listId = route.params.id; // Assuming you're passing the ID in the route
|
|
121
|
+
const response = await $directus.request(readItem('lists', listId));
|
|
122
|
+
|
|
123
|
+
// Populate the form with existing data
|
|
124
|
+
listData.value = {
|
|
125
|
+
id: response.id,
|
|
126
|
+
name: response.name,
|
|
127
|
+
type: response.type,
|
|
128
|
+
status: response.status,
|
|
129
|
+
description: response.description,
|
|
130
|
+
image: response.image
|
|
131
|
+
};
|
|
132
|
+
} catch (error) {
|
|
133
|
+
console.error('Error fetching list:', error);
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
// Load existing data when component mounts
|
|
138
|
+
onMounted(() => {
|
|
139
|
+
if (route.params.id) {
|
|
140
|
+
fetchListData();
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
const handleImageUpload = (event) => {
|
|
145
|
+
imageFile.value = event.target.files[0];
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
const resetForm = () => {
|
|
149
|
+
listData.value = {
|
|
150
|
+
name: '',
|
|
151
|
+
type: '',
|
|
152
|
+
status: '',
|
|
153
|
+
description: '',
|
|
154
|
+
image: null,
|
|
155
|
+
};
|
|
156
|
+
imageFile.value = null;
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const handleSubmit = async () => {
|
|
160
|
+
try {
|
|
161
|
+
loading.value = true;
|
|
162
|
+
|
|
163
|
+
// Handle image upload if there's a new image
|
|
164
|
+
if (imageFile.value) {
|
|
165
|
+
const uploadedFiles = await uploadFiles({
|
|
166
|
+
imageFile: imageFile.value,
|
|
167
|
+
});
|
|
168
|
+
listData.value.image = uploadedFiles.imageId;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Update the list
|
|
172
|
+
const updatedList = await updateList(route.params.id, {
|
|
173
|
+
name: listData.value.name,
|
|
174
|
+
type: listData.value.type,
|
|
175
|
+
status: listData.value.status,
|
|
176
|
+
description: listData.value.description,
|
|
177
|
+
image: listData.value.image,
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
console.log('List updated successfully:', updatedList);
|
|
181
|
+
|
|
182
|
+
// Show success message (you can implement your preferred notification system)
|
|
183
|
+
alert('List updated successfully');
|
|
184
|
+
|
|
185
|
+
} catch (error) {
|
|
186
|
+
console.error('Error updating list:', error);
|
|
187
|
+
alert('Error updating list: ' + error.message);
|
|
188
|
+
} finally {
|
|
189
|
+
loading.value = false;
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
</script>
|