87 lines
2.9 KiB
Vue
87 lines
2.9 KiB
Vue
<script setup lang="ts">
|
|
import { toTypedSchema } from "@vee-validate/zod";
|
|
import { useForm } from "vee-validate";
|
|
import * as z from "zod";
|
|
|
|
import { useQueryClient } from "@tanstack/vue-query";
|
|
import { toast } from "vue-sonner";
|
|
import { getPlaylistsQueryKey, useCreatePlaylist } from "~/composeables/api/playlist-controller/playlist-controller";
|
|
import { FormField } from "@/components/ui/form";
|
|
|
|
const formSchema = toTypedSchema(z.object({
|
|
playlistName: z.string().min(2).max(50).default(''),
|
|
}))
|
|
|
|
const { isFieldDirty, handleSubmit, resetForm } = useForm({
|
|
validationSchema: formSchema,
|
|
})
|
|
|
|
const queryClient = useQueryClient();
|
|
const { mutate: createPlaylistMutation } = useCreatePlaylist({
|
|
mutation: {
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: getPlaylistsQueryKey() });
|
|
toast('Successfully created playlist', {
|
|
description: `Playlist created successfully`,
|
|
});
|
|
},
|
|
onError: () => {
|
|
toast.error('Cannot create playlist', {
|
|
description: 'Error occurred during playlist creation, please try again later.',
|
|
});
|
|
},
|
|
},
|
|
});
|
|
|
|
const onSubmit = handleSubmit(async (values) => {
|
|
const playlistName = values['playlistName'];
|
|
open.value = false;
|
|
createPlaylistMutation({
|
|
data: {
|
|
title: playlistName,
|
|
},
|
|
});
|
|
})
|
|
|
|
const open = ref(false)
|
|
</script>
|
|
|
|
<template>
|
|
<Dialog v-model:open="open">
|
|
<DialogTrigger as-child>
|
|
<slot name="trigger">
|
|
Create playlist
|
|
</slot>
|
|
</DialogTrigger>
|
|
<DialogContent class="sm:max-w-[425px]">
|
|
<form @submit.prevent="onSubmit">
|
|
<DialogHeader>
|
|
<DialogTitle>Edit profile</DialogTitle>
|
|
<DialogDescription>
|
|
Create name for your playlist.
|
|
</DialogDescription>
|
|
</DialogHeader>
|
|
<div class="py-4">
|
|
<FormField v-slot="{ componentField }" name="playlistName" :validate-on-blur="!isFieldDirty">
|
|
<FormItem>
|
|
<FormLabel>Name</FormLabel>
|
|
<FormControl>
|
|
<Input type="text" placeholder="shadcn" v-bind="componentField" />
|
|
</FormControl>
|
|
<FormDescription>
|
|
This is your public display name.
|
|
</FormDescription>
|
|
<FormMessage />
|
|
</FormItem>
|
|
</FormField>
|
|
</div>
|
|
<DialogFooter>
|
|
<Button type="submit">
|
|
Create
|
|
</Button>
|
|
</DialogFooter>
|
|
</form>
|
|
</DialogContent>
|
|
</Dialog>
|
|
</template>
|