diff --git a/app/javascript/dashboard/components-next/CustomAttributes/DateAttribute.vue b/app/javascript/dashboard/components-next/CustomAttributes/DateAttribute.vue
index 364e193c5..4ef63cf28 100644
--- a/app/javascript/dashboard/components-next/CustomAttributes/DateAttribute.vue
+++ b/app/javascript/dashboard/components-next/CustomAttributes/DateAttribute.vue
@@ -3,6 +3,8 @@
import { ref, computed } from 'vue';
import { parseISO } from 'date-fns';
import { useI18n } from 'vue-i18n';
+import { useVuelidate } from '@vuelidate/core';
+import { required } from '@vuelidate/validators';
import Input from 'dashboard/components-next/input/Input.vue';
import Button from 'dashboard/components-next/button/Button.vue';
@@ -24,16 +26,14 @@ const { t } = useI18n();
const isEditingValue = ref(false);
const editedValue = ref(props.attribute.value || '');
-const defaultDateValue = computed({
- get() {
- const existingDate = editedValue.value ?? props.attribute.value;
- if (existingDate) return new Date(existingDate).toISOString().slice(0, 10);
- return isEditingValue.value ? new Date().toISOString().slice(0, 10) : '';
+const rules = {
+ editedValue: {
+ required,
+ isDate: value => new Date(value).toISOString(),
},
- set(value) {
- editedValue.value = value ? new Date(value).toISOString() : value;
- },
-});
+};
+
+const v$ = useVuelidate(rules, { editedValue });
const formattedDate = computed(() => {
return props.attribute.value
@@ -41,16 +41,35 @@ const formattedDate = computed(() => {
: t('CONTACTS_LAYOUT.SIDEBAR.ATTRIBUTES.TRIGGER.INPUT');
});
+const hasError = computed(() => v$.value.$errors.length > 0);
+
+const defaultDateValue = computed({
+ get() {
+ const existingDate = editedValue.value ?? props.attribute.value;
+ if (existingDate) return new Date(existingDate).toISOString().slice(0, 10);
+ return isEditingValue.value && !hasError.value
+ ? new Date().toISOString().slice(0, 10)
+ : '';
+ },
+ set(value) {
+ editedValue.value = value ? new Date(value).toISOString() : value;
+ },
+});
+
const toggleEditValue = value => {
isEditingValue.value =
typeof value === 'boolean' ? value : !isEditingValue.value;
if (isEditingValue.value && !editedValue.value) {
+ v$.value.$reset();
editedValue.value = new Date().toISOString();
}
};
const handleInputUpdate = async () => {
+ const isValid = await v$.value.$validate();
+ if (!isValid) return;
+
emit('update', parseISO(editedValue.value));
isEditingValue.value = false;
};
@@ -107,16 +126,21 @@ const handleInputUpdate = async () => {
diff --git a/app/javascript/dashboard/components-next/CustomAttributes/OtherAttribute.vue b/app/javascript/dashboard/components-next/CustomAttributes/OtherAttribute.vue
index d5ba437ea..31f463493 100644
--- a/app/javascript/dashboard/components-next/CustomAttributes/OtherAttribute.vue
+++ b/app/javascript/dashboard/components-next/CustomAttributes/OtherAttribute.vue
@@ -171,14 +171,14 @@ const handleInputUpdate = async () => {
autofocus
:message="attributeErrorMessage"
:message-type="hasError ? 'error' : 'info'"
- custom-input-class="h-8 rounded-r-none !border-n-brand"
+ custom-input-class="h-8 ltr:rounded-r-none rtl:rounded-l-none"
@keyup.enter="handleInputUpdate"
/>
diff --git a/app/javascript/dashboard/i18n/locale/en/contact.json b/app/javascript/dashboard/i18n/locale/en/contact.json
index 682093e30..2d9d72132 100644
--- a/app/javascript/dashboard/i18n/locale/en/contact.json
+++ b/app/javascript/dashboard/i18n/locale/en/contact.json
@@ -568,7 +568,8 @@
"INVALID_NUMBER": "Invalid number",
"REQUIRED": "Valid value is required",
"INVALID_INPUT": "Invalid input",
- "INVALID_URL": "Invalid URL"
+ "INVALID_URL": "Invalid URL",
+ "INVALID_DATE": "Invalid date"
},
"NO_ATTRIBUTES": "No attributes found",
"EMPTY_STATE": "No unused attributes found",