From 41d173c18da7daf7d3613041f2ffbb9249f5dc2f Mon Sep 17 00:00:00 2001 From: allen Date: Sun, 27 Oct 2024 23:57:25 +0800 Subject: [PATCH] feat: add song editor and validator --- app/components/editors/SongEditor.vue | 52 +++----------------- app/components/editors/SongForm.vue | 68 +++++++++++++++++++++++++++ app/composables/validator.ts | 57 ++++++++++++++++++++++ app/locales/en.json | 8 +++- app/locales/ja.json | 8 +++- app/locales/zh-Hans.json | 9 +++- app/locales/zh-Hant.json | 8 +++- 7 files changed, 161 insertions(+), 49 deletions(-) create mode 100644 app/components/editors/SongForm.vue create mode 100644 app/composables/validator.ts diff --git a/app/components/editors/SongEditor.vue b/app/components/editors/SongEditor.vue index c368cac7..e8d5f865 100644 --- a/app/components/editors/SongEditor.vue +++ b/app/components/editors/SongEditor.vue @@ -1,5 +1,6 @@ + + diff --git a/app/composables/validator.ts b/app/composables/validator.ts new file mode 100644 index 00000000..3bbb591f --- /dev/null +++ b/app/composables/validator.ts @@ -0,0 +1,57 @@ +import type { MaruSongDataParsed } from '@marure/schema' +import { useNuxtApp } from 'nuxt/app' +import { reactive } from 'vue' + +export interface ValidationErrors { + youtube: string + title: string + artists: string + tags: string + offset?: string + notes?: string +} + +export function useValidation(stateRef: MaruSongDataParsed) { + const errors = reactive({ + youtube: '', + title: '', + artists: '', + tags: '', + }) + const nuxtApp = useNuxtApp() + const { t } = nuxtApp.$i18n + + const validate = (): boolean => { + let isValid = true + + errors.youtube = '' + errors.title = '' + errors.artists = '' + errors.tags = '' + + if (!stateRef.youtube || !stateRef.youtube.trim()) { + errors.youtube = t('editor.validator.youtube') + isValid = false + } + + if (!stateRef.title || !stateRef.title.trim()) { + errors.title = t('editor.validator.title') + isValid = false + } + if (!stateRef.artists || stateRef.artists?.includes('')) { + errors.artists = t('editor.validator.artists') + isValid = false + } + + if (!stateRef.tags || stateRef.tags?.includes('')) { + errors.tags = t('editor.validator.tags') + isValid = false + } + return isValid + } + + return { + errors, + validate, + } +} diff --git a/app/locales/en.json b/app/locales/en.json index 42aee7ae..860c6321 100644 --- a/app/locales/en.json +++ b/app/locales/en.json @@ -48,7 +48,13 @@ "setCurrentTime": "Apply current playback time and go next", "setCurrentTimeOnly": "Apply current playback time" }, - "visualization": "Visualization" + "visualization": "Visualization", + "validator": { + "youtube": "YouTube ID is required.", + "title": "Title is required.", + "artists": "At least one artist is required.", + "tags": "At least one tag is required." + } }, "footer": { "fileFormat": "File Format", diff --git a/app/locales/ja.json b/app/locales/ja.json index 2bd7ecc0..3c5748a2 100644 --- a/app/locales/ja.json +++ b/app/locales/ja.json @@ -48,7 +48,13 @@ "setCurrentTime": "現在の再生時間に設定して次の行へ", "setCurrentTimeOnly": "現在の再生時間に設定" }, - "visualization": "可視化" + "visualization": "可視化", + "validator": { + "youtube": "YouTube IDは必須です。", + "title": "タイトルは必須です。", + "artists": "少なくとも1人のアーティストが必要です。", + "tags": "少なくとも1つのタグが必要です。" + } }, "footer": { "fileFormat": "ファイル形式", diff --git a/app/locales/zh-Hans.json b/app/locales/zh-Hans.json index db7370f3..65795da8 100644 --- a/app/locales/zh-Hans.json +++ b/app/locales/zh-Hans.json @@ -48,7 +48,14 @@ "setCurrentTime": "设为当前播放时间后跳行", "setCurrentTimeOnly": "设为当前播放时间" }, - "visualization": "可视化" + "visualization": "可视化", + "validator": { + "youtube": "YouTube ID 是必填的。", + "title": "标题是必填的。", + "artists": "至少需要一个歌手。", + "tags": "至少需要一个标签。" + } + }, "footer": { "fileFormat": "文件格式", diff --git a/app/locales/zh-Hant.json b/app/locales/zh-Hant.json index cf9036d9..0f6ea2e1 100644 --- a/app/locales/zh-Hant.json +++ b/app/locales/zh-Hant.json @@ -48,7 +48,13 @@ "setCurrentTime": "設為當前播放時間後跳行", "setCurrentTimeOnly": "設為當前播放時間" }, - "visualization": "可視化" + "visualization": "可視化", + "validator": { + "youtube": "YouTube ID 是必填的。", + "title": "標題是必填的。", + "artists": "至少需要一個歌手。", + "tags": "至少需要一個標籤。" + } }, "footer": { "fileFormat": "檔案格式",