diff --git a/app/javascript/dashboard/components-next/Contacts/ContactLabels/ContactLabels.vue b/app/javascript/dashboard/components-next/Contacts/ContactLabels/ContactLabels.vue new file mode 100644 index 000000000..818b3beb1 --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactLabels/ContactLabels.vue @@ -0,0 +1,74 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsCard/ContactsCard.vue b/app/javascript/dashboard/components-next/Contacts/ContactsCard/ContactsCard.vue index 6b4b3dec2..bd1f46efc 100644 --- a/app/javascript/dashboard/components-next/Contacts/ContactsCard/ContactsCard.vue +++ b/app/javascript/dashboard/components-next/Contacts/ContactsCard/ContactsCard.vue @@ -1,6 +1,7 @@ diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsForm/ContactsForm.vue b/app/javascript/dashboard/components-next/Contacts/ContactsForm/ContactsForm.vue index d8b4a25bf..9ddc1de5b 100644 --- a/app/javascript/dashboard/components-next/Contacts/ContactsForm/ContactsForm.vue +++ b/app/javascript/dashboard/components-next/Contacts/ContactsForm/ContactsForm.vue @@ -11,6 +11,10 @@ const props = defineProps({ type: Object, required: true, }, + isDetailsView: { + type: Boolean, + default: false, + }, }); const emit = defineEmits(['update']); @@ -18,8 +22,8 @@ const emit = defineEmits(['update']); const { t } = useI18n(); const FORM_CONFIG = { - FIRST_NAME: { field: 'name' }, - LAST_NAME: { field: 'name' }, + FIRST_NAME: { field: 'firstName' }, + LAST_NAME: { field: 'lastName' }, EMAIL_ADDRESS: { field: 'email' }, PHONE_NUMBER: { field: 'phone_number' }, CITY: { field: 'additional_attributes.city' }, @@ -40,6 +44,8 @@ const defaultState = { id: 0, name: '', email: '', + firstName: '', + lastName: '', phone_number: '', additional_attributes: { description: '', @@ -60,9 +66,14 @@ const defaultState = { const state = reactive({ ...defaultState }); const updateState = () => { + const [firstName = '', lastName = ''] = (props.contactData.name || '').split( + ' ' + ); Object.assign(state, { id: props.contactData.id, name: props.contactData.name, + firstName, + lastName, email: props.contactData.email, phone_number: props.contactData.phoneNumber, additional_attributes: { @@ -109,6 +120,9 @@ const getFormBinding = key => { // Example 1 (nested): field = 'contact.name' returns state.contact.name = "John Doe" // Example 2 (root): field = 'email' returns state.email = "john@example.com" get: () => { + if (field === 'firstName' || field === 'lastName') { + return state[field]; + } const [base, nested] = field.split('.'); return nested ? state[base][nested] : state[base]; }, @@ -117,11 +131,17 @@ const getFormBinding = key => { // Example 1 (nested): field = 'contact.name', value = "Jane Doe" → state.contact.name = "Jane Doe" // Example 2 (root): field = 'email', value = "jane@example.com" → state.email = "jane@example.com" set: value => { - const [base, nested] = field.split('.'); - if (nested) { - state[base][nested] = value; + if (field === 'firstName' || field === 'lastName') { + state[field] = value; + // Combine first and last name into the name field + state.name = `${state.firstName} ${state.lastName}`.trim(); } else { - state[base] = value; + const [base, nested] = field.split('.'); + if (nested) { + state[base][nested] = value; + } else { + state[base] = value; + } } emit('update', state); }, @@ -132,8 +152,8 @@ watch(() => props.contactData, updateState, { immediate: true, deep: true }); -
+
{{ t('CONTACTS_LAYOUT.CARD.SOCIAL_MEDIA.TITLE') }} diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsLayout.vue b/app/javascript/dashboard/components-next/Contacts/ContactsLayout.vue index e17799acb..db9da2155 100644 --- a/app/javascript/dashboard/components-next/Contacts/ContactsLayout.vue +++ b/app/javascript/dashboard/components-next/Contacts/ContactsLayout.vue @@ -1,10 +1,14 @@ + + diff --git a/app/javascript/dashboard/components-next/breadcrumb/Breadcrumb.vue b/app/javascript/dashboard/components-next/breadcrumb/Breadcrumb.vue index e87728d1e..bb848c62b 100644 --- a/app/javascript/dashboard/components-next/breadcrumb/Breadcrumb.vue +++ b/app/javascript/dashboard/components-next/breadcrumb/Breadcrumb.vue @@ -8,14 +8,6 @@ defineProps({ items: { type: Array, required: true, - validator: value => { - return value.every( - item => - typeof item.label === 'string' && - (item.link === undefined || typeof item.link === 'string') && - (item.count === undefined || typeof item.count === 'number') - ); - }, }, }); diff --git a/app/javascript/dashboard/i18n/locale/en/contact.json b/app/javascript/dashboard/i18n/locale/en/contact.json index 243f9622e..2ccaef9b4 100644 --- a/app/javascript/dashboard/i18n/locale/en/contact.json +++ b/app/javascript/dashboard/i18n/locale/en/contact.json @@ -391,7 +391,10 @@ "HEADER": { "TITLE": "Contacts", "SEARCH_PLACEHOLDER": "Search...", - "MESSAGE_BUTTON": "Message" + "MESSAGE_BUTTON": "Message", + "BREADCRUMB": { + "CONTACTS": "Contacts" + } }, "CARD": { "OF": "of", @@ -445,6 +448,20 @@ } } } + }, + "DETAILS": { + "TAG_BUTTON": "tag", + "MERGE_CONTACT": "Merge contact", + "DELETE_CONTACT": "Delete contact", + "DELETE_DIALOG": { + "TITLE": "Confirm Deletion", + "DESCRIPTION": "Are you sure you want to delete this {contactName} contact?", + "CONFIRM": "Yes, Delete", + "API": { + "SUCCESS_MESSAGE": "Contact deleted successfully", + "ERROR_MESSAGE": "Could not delete contact. Please try again later." + } + } } } } diff --git a/app/javascript/dashboard/routes/dashboard/contact/contact.routes.js b/app/javascript/dashboard/routes/dashboard/contact/contact.routes.js index 71f6a008b..42f689092 100644 --- a/app/javascript/dashboard/routes/dashboard/contact/contact.routes.js +++ b/app/javascript/dashboard/routes/dashboard/contact/contact.routes.js @@ -1,21 +1,25 @@ import { frontendURL } from 'dashboard/helper/URLHelper.js'; import ContactsPageRouteView from './pages/ContactsPageRouteView.vue'; +import EditContactsPageRouteView from './pages/EditContactsPageRouteView.vue'; const contactsRoutes = { routes: [ { path: frontendURL('accounts/:accountId/contacts-new'), component: ContactsPageRouteView, - children: [ - { - path: 'ongoing', - name: 'contacts_dashboard_index', - meta: { - permissions: ['administrator', 'agent', 'contact_manage'], - }, - }, - ], + name: 'contacts_dashboard_index', + meta: { + permissions: ['administrator', 'agent', 'contact_manage'], + }, + }, + { + path: frontendURL('accounts/:accountId/contacts-new/:contactId'), + component: EditContactsPageRouteView, + name: 'contacts_dashboard_edit_index', + meta: { + permissions: ['administrator', 'agent', 'contact_manage'], + }, }, ], }; diff --git a/app/javascript/dashboard/routes/dashboard/contact/pages/ContactsPageRouteView.vue b/app/javascript/dashboard/routes/dashboard/contact/pages/ContactsPageRouteView.vue index 635542a48..1af5b5e4c 100644 --- a/app/javascript/dashboard/routes/dashboard/contact/pages/ContactsPageRouteView.vue +++ b/app/javascript/dashboard/routes/dashboard/contact/pages/ContactsPageRouteView.vue @@ -4,6 +4,7 @@ import { useStore, useMapGetter } from 'dashboard/composables/store'; import ContactsLayout from 'dashboard/components-next/Contacts/ContactsLayout.vue'; import ContactsList from 'dashboard/components-next/Contacts/Pages/ContactsList.vue'; +import Spinner from 'dashboard/components-next/spinner/Spinner.vue'; const store = useStore(); @@ -11,6 +12,8 @@ const contacts = useMapGetter('contacts/getContacts'); const uiFlags = useMapGetter('contacts/getUIFlags'); const meta = useMapGetter('contacts/getMeta'); +const isFetchingList = computed(() => uiFlags.value.isFetching); + const currentPage = computed(() => Number(meta.value?.currentPage)); const totalItems = computed(() => meta.value?.count); @@ -38,7 +41,13 @@ const updateCurrentPage = page => { :total-items="totalItems" @update:current-page="updateCurrentPage" > - +
+ +
+
diff --git a/app/javascript/dashboard/routes/dashboard/contact/pages/EditContactsPageRouteView.vue b/app/javascript/dashboard/routes/dashboard/contact/pages/EditContactsPageRouteView.vue new file mode 100644 index 000000000..559c088a9 --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/contact/pages/EditContactsPageRouteView.vue @@ -0,0 +1,62 @@ + + +