From 1e63cb2ff2bfd7ffc73ba58660b94f3434c46422 Mon Sep 17 00:00:00 2001 From: Chris Veleris Date: Fri, 4 Jul 2025 14:19:11 +0300 Subject: [PATCH] Add project name not empty validation and error --- frontend/components/Project/ProjectModal.tsx | 25 ++++++++++++++++++-- public/locales/de/translation.json | 4 +++- public/locales/el/translation.json | 4 +++- public/locales/en/translation.json | 4 +++- public/locales/es/translation.json | 4 +++- public/locales/jp/translation.json | 4 +++- public/locales/ua/translation.json | 4 +++- 7 files changed, 41 insertions(+), 8 deletions(-) diff --git a/frontend/components/Project/ProjectModal.tsx b/frontend/components/Project/ProjectModal.tsx index a8264f0..a21f3f4 100644 --- a/frontend/components/Project/ProjectModal.tsx +++ b/frontend/components/Project/ProjectModal.tsx @@ -54,8 +54,9 @@ const ProjectModal: React.FC = ({ const fileInputRef = useRef(null); const [isClosing, setIsClosing] = useState(false); const [showConfirmDialog, setShowConfirmDialog] = useState(false); + const [error, setError] = useState(null); - const { showSuccessToast } = useToast(); + const { showSuccessToast, showErrorToast } = useToast(); const { t } = useTranslation(); useEffect(() => { @@ -83,6 +84,7 @@ const ProjectModal: React.FC = ({ setImagePreview(""); } setImageFile(null); + setError(null); }, [project]); useEffect(() => { @@ -125,6 +127,11 @@ const ProjectModal: React.FC = ({ const target = e.target; const { name, type, value } = target; + // Clear error when user starts typing in the name field + if (name === 'name' && error) { + setError(null); + } + if (type === "checkbox") { if (target instanceof HTMLInputElement) { const checked = target.checked; @@ -204,6 +211,12 @@ const ProjectModal: React.FC = ({ }; const handleSubmit = async () => { + // Validate required fields + if (!formData.name.trim()) { + setError(t('errors.projectNameRequired', 'Project name is required')); + return; + } + try { let imageUrl = formData.image_url; @@ -233,6 +246,7 @@ const ProjectModal: React.FC = ({ handleClose(); } catch (error) { console.error('Error saving project:', error); + setError(t('errors.projectSaveFailed', 'Failed to save project')); } }; @@ -295,9 +309,16 @@ const ProjectModal: React.FC = ({ value={formData.name} onChange={handleChange} required - className="block w-full text-xl font-semibold dark:bg-gray-800 text-black dark:text-white border-b-2 border-gray-200 dark:border-gray-900 focus:outline-none shadow-sm py-2" + className={`block w-full text-xl font-semibold dark:bg-gray-800 text-black dark:text-white border-b-2 ${ + error ? 'border-red-500' : 'border-gray-200 dark:border-gray-900' + } focus:outline-none shadow-sm py-2`} placeholder={t('project.name', 'Enter project name')} /> + {error && ( +
+ {error} +
+ )}
diff --git a/public/locales/de/translation.json b/public/locales/de/translation.json index f0ead73..671ccc9 100644 --- a/public/locales/de/translation.json +++ b/public/locales/de/translation.json @@ -126,7 +126,9 @@ "noteTitleRequired": "Notiz-Titel ist erforderlich.", "failedToLoadTags": "Fehler beim Laden der verfügbaren Tags.", "failedToSaveNote": "Fehler beim Speichern der Notiz.", - "projectCreationFailed": "Projekt konnte nicht erstellt werden." + "projectCreationFailed": "Projekt konnte nicht erstellt werden.", + "projectNameRequired": "Projektname ist erforderlich.", + "projectSaveFailed": "Projekt konnte nicht gespeichert werden." }, "success": { "noteUpdated": "Notiz erfolgreich aktualisiert!", diff --git a/public/locales/el/translation.json b/public/locales/el/translation.json index 58a0e69..42744e0 100644 --- a/public/locales/el/translation.json +++ b/public/locales/el/translation.json @@ -197,7 +197,9 @@ "failedToSaveTag": "Αποτυχία αποθήκευσης ετικέτας.", "areaNameRequired": "Το όνομα περιοχής είναι υποχρεωτικό.", "failedToSaveArea": "Αποτυχία αποθήκευσης περιοχής.", - "projectCreationFailed": "Αποτυχία δημιουργίας έργου." + "projectCreationFailed": "Αποτυχία δημιουργίας έργου.", + "projectNameRequired": "Το όνομα έργου είναι υποχρεωτικό.", + "projectSaveFailed": "Αποτυχία αποθήκευσης έργου." }, "dropdown": { "createNew": "Δημιουργία Νέου", diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 995d95f..05a08d0 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -444,7 +444,9 @@ "areaNameRequired": "Area name is required.", "failedToSaveArea": "Failed to save area.", "tagNameRequired": "Tag name is required.", - "failedToSaveTag": "Failed to save tag." + "failedToSaveTag": "Failed to save tag.", + "projectNameRequired": "Project name is required.", + "projectSaveFailed": "Failed to save project." }, "inbox": { "title": "Inbox", diff --git a/public/locales/es/translation.json b/public/locales/es/translation.json index 23f9a4e..fbc23f7 100644 --- a/public/locales/es/translation.json +++ b/public/locales/es/translation.json @@ -158,7 +158,9 @@ "noteTitleRequired": "El título de la nota es obligatorio.", "failedToLoadTags": "Error al cargar las etiquetas disponibles.", "failedToSaveNote": "Error al guardar la nota.", - "projectCreationFailed": "Error al crear el proyecto." + "projectCreationFailed": "Error al crear el proyecto.", + "projectNameRequired": "El nombre del proyecto es obligatorio.", + "projectSaveFailed": "Error al guardar el proyecto." }, "dropdown": { "createNew": "Crear Nuevo", diff --git a/public/locales/jp/translation.json b/public/locales/jp/translation.json index 137b687..10757e6 100644 --- a/public/locales/jp/translation.json +++ b/public/locales/jp/translation.json @@ -227,7 +227,9 @@ "noteTitleRequired": "ノートのタイトルは必須です。", "failedToLoadTags": "利用可能なタグの読み込みに失敗しました。", "failedToSaveNote": "ノートの保存に失敗しました。", - "projectCreationFailed": "プロジェクトの作成に失敗しました。" + "projectCreationFailed": "プロジェクトの作成に失敗しました。", + "projectNameRequired": "プロジェクト名は必須です。", + "projectSaveFailed": "プロジェクトの保存に失敗しました。" }, "success": { "noteUpdated": "ノートが正常に更新されました!", diff --git a/public/locales/ua/translation.json b/public/locales/ua/translation.json index 69f3eaa..5c292ea 100644 --- a/public/locales/ua/translation.json +++ b/public/locales/ua/translation.json @@ -173,7 +173,9 @@ "noteTitleRequired": "Заголовок нотатки обов'язковий.", "failedToLoadTags": "Не вдалося завантажити доступні теги.", "failedToSaveNote": "Не вдалося зберегти нотатку.", - "projectCreationFailed": "Не вдалося створити проект." + "projectCreationFailed": "Не вдалося створити проект.", + "projectNameRequired": "Назва проекту обов'язкова.", + "projectSaveFailed": "Не вдалося зберегти проект." }, "success": {