diff --git a/frontend/src/components/dialogs/tasks/TaskFormDialog.tsx b/frontend/src/components/dialogs/tasks/TaskFormDialog.tsx index 2be80a3296..8266e3cf23 100644 --- a/frontend/src/components/dialogs/tasks/TaskFormDialog.tsx +++ b/frontend/src/components/dialogs/tasks/TaskFormDialog.tsx @@ -207,7 +207,7 @@ const TaskFormDialogImpl = NiceModal.create((props) => { }; const validator = (value: TaskFormValues): string | undefined => { - if (!value.title.trim().length) return 'need title'; + // Title is validated in a field level validator if ( value.autoStart && !forceCreateOnlyRef.current && @@ -222,9 +222,6 @@ const TaskFormDialogImpl = NiceModal.create((props) => { defaultValues: defaultValues, onSubmit: handleSubmit, validators: { - // we use an onMount validator so that the primary action button can - // enable/disable itself based on `canSubmit` - onMount: ({ value }) => validator(value), onChange: ({ value }) => validator(value), }, }); @@ -320,11 +317,6 @@ const TaskFormDialogImpl = NiceModal.create((props) => { preventDefault: true, }); - const canSubmitAlt = useStore( - form.store, - (state) => state.values.title.trim().length > 0 && !state.isSubmitting - ); - const handleSubmitCreateOnly = useCallback(() => { forceCreateOnlyRef.current = true; const promise = form.handleSubmit(); @@ -334,7 +326,7 @@ const TaskFormDialogImpl = NiceModal.create((props) => { }, [form]); useKeySubmitTaskAlt(handleSubmitCreateOnly, { - enabled: modal.visible && canSubmitAlt && !showDiscardWarning, + enabled: shortcutsEnabled, scope: Scope.DIALOG, enableOnFormTags: ['input', 'INPUT', 'textarea', 'TEXTAREA'], preventDefault: true, @@ -408,17 +400,32 @@ const TaskFormDialogImpl = NiceModal.create((props) => { {/* Title */}
- + + !value.trim().length + ? t('taskFormDialog.errors.titleRequired') + : undefined, + }} + > {(field) => ( - field.handleChange(e.target.value)} - placeholder={t('taskFormDialog.titlePlaceholder')} - className="text-lg font-medium border-none shadow-none px-0 placeholder:text-muted-foreground/60 focus-visible:ring-0" - disabled={isSubmitting} - autoFocus - /> + <> + field.handleChange(e.target.value)} + placeholder={t('taskFormDialog.titlePlaceholder')} + className="text-xl font-medium border-none shadow-none px-0 placeholder:text-muted-foreground/60 focus-visible:ring-0" + disabled={isSubmitting} + autoFocus + /> + {!field.state.meta.isValid && ( + + {field.state.meta.errors.join(', ')} + + )} + )}
@@ -594,26 +601,23 @@ const TaskFormDialogImpl = NiceModal.create((props) => { {/* Create/Start/Update button*/} ({ - canSubmit: state.canSubmit, isSubmitting: state.isSubmitting, - values: state.values, + autoStart: state.values.autoStart, })} > - {({ canSubmit, isSubmitting, values }) => { + {({ isSubmitting, autoStart }) => { const buttonText = editMode ? isSubmitting ? t('taskFormDialog.updating') : t('taskFormDialog.updateTask') : isSubmitting - ? values.autoStart + ? autoStart ? t('taskFormDialog.starting') : t('taskFormDialog.creating') : t('taskFormDialog.create'); return ( - + ); }} diff --git a/frontend/src/i18n/locales/en/tasks.json b/frontend/src/i18n/locales/en/tasks.json index e9b2ce9473..ef385acfba 100644 --- a/frontend/src/i18n/locales/en/tasks.json +++ b/frontend/src/i18n/locales/en/tasks.json @@ -399,6 +399,9 @@ "starting": "Starting...", "creating": "Creating...", "create": "Create", + "errors": { + "titleRequired": "Title is required" + }, "discardDialog": { "title": "Discard unsaved changes?", "description": "You have unsaved changes. Are you sure you want to discard them?", diff --git a/frontend/src/i18n/locales/es/tasks.json b/frontend/src/i18n/locales/es/tasks.json index 35a0dcb4f0..bbfb240ac8 100644 --- a/frontend/src/i18n/locales/es/tasks.json +++ b/frontend/src/i18n/locales/es/tasks.json @@ -399,6 +399,9 @@ "starting": "Iniciando...", "creating": "Creando...", "create": "Crear", + "errors": { + "titleRequired": "El título es obligatorio" + }, "discardDialog": { "title": "¿Descartar cambios sin guardar?", "description": "Tienes cambios sin guardar. ¿Estás seguro de que deseas descartarlos?", diff --git a/frontend/src/i18n/locales/ja/tasks.json b/frontend/src/i18n/locales/ja/tasks.json index d6226e3839..05de7a9d29 100644 --- a/frontend/src/i18n/locales/ja/tasks.json +++ b/frontend/src/i18n/locales/ja/tasks.json @@ -399,6 +399,9 @@ "starting": "開始中...", "creating": "作成中...", "create": "作成", + "errors": { + "titleRequired": "タイトルは必須です" + }, "discardDialog": { "title": "未保存の変更を破棄しますか?", "description": "未保存の変更があります。本当に破棄してもよろしいですか?", diff --git a/frontend/src/i18n/locales/ko/tasks.json b/frontend/src/i18n/locales/ko/tasks.json index a77353320d..24af2ba14b 100644 --- a/frontend/src/i18n/locales/ko/tasks.json +++ b/frontend/src/i18n/locales/ko/tasks.json @@ -399,6 +399,9 @@ "starting": "시작 중...", "creating": "만드는 중...", "create": "만들기", + "errors": { + "titleRequired": "제목은 필수입니다" + }, "discardDialog": { "title": "저장하지 않은 변경사항을 버리시겠습니까?", "description": "저장하지 않은 변경사항이 있습니다. 정말 버리시겠습니까?",