Add singles from admin
This commit is contained in:
1 parent
3255a97339
commit
3402178932
2 files changed
+72
-1
No files matched your search
@@ -4,6 +4,7 @@ import { type Option } from "~/ui/SearchSelect.vue"
|
|||||||
interface BaseField<T> {
|
interface BaseField<T> {
|
||||||
key: keyof T
|
key: keyof T
|
||||||
label?: string
|
label?: string
|
||||||
|
visibleWhen?: (value: any) => boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TextField<T> extends BaseField<T> {
|
interface TextField<T> extends BaseField<T> {
|
||||||
@@ -114,7 +115,12 @@ watch(
|
|||||||
<p v-if="props.title" class="title">{{ props.title }}</p>
|
<p v-if="props.title" class="title">{{ props.title }}</p>
|
||||||
|
|
||||||
<form class="form" @submit.prevent="save">
|
<form class="form" @submit.prevent="save">
|
||||||
<template v-for="field in props.fields">
|
<template
|
||||||
|
v-for="field in props.fields.filter(
|
||||||
|
(field) =>
|
||||||
|
!field.visibleWhen || field.visibleWhen(localItem),
|
||||||
|
)"
|
||||||
|
>
|
||||||
<SearchSelect
|
<SearchSelect
|
||||||
v-if="
|
v-if="
|
||||||
field.type == 'search-select' ||
|
field.type == 'search-select' ||
|
||||||
|
|||||||
@@ -48,6 +48,14 @@ const albumFetchOptions = async (q?: string): Promise<Option[]> => {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { data: genreData } = useApiFetch<Genre[]>("/all/genres")
|
||||||
|
const genreFetchOptions = async (): Promise<Option[]> => {
|
||||||
|
return genreData.value.map<Option>((genre) => ({
|
||||||
|
label: genre.name,
|
||||||
|
value: genre._id,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
const modalFields: Field[] = [
|
const modalFields: Field[] = [
|
||||||
{ key: "name", label: "Name" },
|
{ key: "name", label: "Name" },
|
||||||
{ key: "file", label: "Audio file", type: "file" },
|
{ key: "file", label: "Audio file", type: "file" },
|
||||||
@@ -57,11 +65,31 @@ const modalFields: Field[] = [
|
|||||||
type: "search-select-array",
|
type: "search-select-array",
|
||||||
fetchOptions: artistFetchOptions,
|
fetchOptions: artistFetchOptions,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: "createSingle",
|
||||||
|
label: "Create a single album automatically",
|
||||||
|
type: "checkbox",
|
||||||
|
visibleWhen: (value) => !value._id,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: "album",
|
key: "album",
|
||||||
label: "Album",
|
label: "Album",
|
||||||
type: "search-select",
|
type: "search-select",
|
||||||
fetchOptions: albumFetchOptions,
|
fetchOptions: albumFetchOptions,
|
||||||
|
visibleWhen: (value) => !value.createSingle,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "cover",
|
||||||
|
label: "Single cover",
|
||||||
|
type: "file",
|
||||||
|
visibleWhen: (value) => !value._id && value.createSingle,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "genre",
|
||||||
|
label: "Genre",
|
||||||
|
type: "search-select",
|
||||||
|
fetchOptions: genreFetchOptions,
|
||||||
|
visibleWhen: (value) => !value._id && value.createSingle,
|
||||||
},
|
},
|
||||||
{ key: "lyrics.text", label: "Lyrics", type: "textarea", rows: 6 },
|
{ key: "lyrics.text", label: "Lyrics", type: "textarea", rows: 6 },
|
||||||
{ key: "lyrics.synced", label: "Synced lyrics", type: "checkbox" },
|
{ key: "lyrics.synced", label: "Synced lyrics", type: "checkbox" },
|
||||||
@@ -96,10 +124,47 @@ const save = async (value: any) => {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
|
if (!value.name || !value.file || !value.artists?.length) {
|
||||||
|
toast.show(
|
||||||
|
"Name, audio file, and at least one artist are required",
|
||||||
|
"error",
|
||||||
|
)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.createSingle) {
|
||||||
|
if (!value.cover || !value.genre) {
|
||||||
|
toast.show(
|
||||||
|
"A cover image and genre are required for a single",
|
||||||
|
"error",
|
||||||
|
)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const albumResponse = await cfetch("/admin/album", {
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
name: `${value.name} - Single`,
|
||||||
|
artists: value.artists.map((artist: Option) => artist.value),
|
||||||
|
genres: value.genre.value,
|
||||||
|
file: value.cover,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
value.album = albumResponse.data._id
|
||||||
|
} else if (!value.album) {
|
||||||
|
toast.show(
|
||||||
|
"Choose an album or create a single album",
|
||||||
|
"error",
|
||||||
|
)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
await cfetch("/admin/track", {
|
await cfetch("/admin/track", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
data: {
|
data: {
|
||||||
...value,
|
...value,
|
||||||
|
album: value.album?.value ?? value.album,
|
||||||
|
artists: value.artists.map((artist: Option) => artist.value),
|
||||||
lyrics: serializeLyrics(value.lyrics),
|
lyrics: serializeLyrics(value.lyrics),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in new issue
Block a user