feat: make the contact methods more presentable, and clarify exact types
This commit is contained in:
@@ -43,6 +43,7 @@ import {
|
|||||||
faDownload,
|
faDownload,
|
||||||
faEllipsis,
|
faEllipsis,
|
||||||
faEllipsisVertical,
|
faEllipsisVertical,
|
||||||
|
faEnvelope,
|
||||||
faEnvelopeOpenText,
|
faEnvelopeOpenText,
|
||||||
faEraser,
|
faEraser,
|
||||||
faEye,
|
faEye,
|
||||||
@@ -101,6 +102,9 @@ import {
|
|||||||
// these are referenced differently, eg. ":icon='['far', 'star']'" as in ProjectViewView.vue
|
// these are referenced differently, eg. ":icon='['far', 'star']'" as in ProjectViewView.vue
|
||||||
import { faStar as faStarRegular } from "@fortawesome/free-regular-svg-icons";
|
import { faStar as faStarRegular } from "@fortawesome/free-regular-svg-icons";
|
||||||
|
|
||||||
|
// Brand icons
|
||||||
|
import { faWhatsapp } from "@fortawesome/free-brands-svg-icons";
|
||||||
|
|
||||||
// Initialize Font Awesome library with all required icons
|
// Initialize Font Awesome library with all required icons
|
||||||
library.add(
|
library.add(
|
||||||
faArrowDown,
|
faArrowDown,
|
||||||
@@ -140,6 +144,7 @@ library.add(
|
|||||||
faDownload,
|
faDownload,
|
||||||
faEllipsis,
|
faEllipsis,
|
||||||
faEllipsisVertical,
|
faEllipsisVertical,
|
||||||
|
faEnvelope,
|
||||||
faEnvelopeOpenText,
|
faEnvelopeOpenText,
|
||||||
faEraser,
|
faEraser,
|
||||||
faEye,
|
faEye,
|
||||||
@@ -193,6 +198,7 @@ library.add(
|
|||||||
faTriangleExclamation,
|
faTriangleExclamation,
|
||||||
faUser,
|
faUser,
|
||||||
faUsers,
|
faUsers,
|
||||||
|
faWhatsapp,
|
||||||
faXmark,
|
faXmark,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -55,56 +55,70 @@
|
|||||||
|
|
||||||
<!-- Contact Methods -->
|
<!-- Contact Methods -->
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<h2 class="text-lg font-medium text-gray-700">Contact Methods</h2>
|
<div v-for="(method, index) in contactMethods" :key="index" class="mt-4">
|
||||||
<div
|
<!-- Type and Value Row -->
|
||||||
v-for="(method, index) in contactMethods"
|
<div class="flex gap-2">
|
||||||
:key="index"
|
<div class="flex-none w-32">
|
||||||
class="flex mt-2"
|
<label class="block text-xs font-medium text-gray-700 mb-1">
|
||||||
>
|
Type
|
||||||
<input
|
</label>
|
||||||
v-model="method.label"
|
<select
|
||||||
type="text"
|
v-model="method.type"
|
||||||
class="block w-1/4 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500"
|
class="block w-full border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500"
|
||||||
placeholder="Label"
|
|
||||||
/>
|
|
||||||
<input
|
|
||||||
v-model="method.type"
|
|
||||||
type="text"
|
|
||||||
class="block ml-2 w-1/4 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500"
|
|
||||||
placeholder="Type"
|
|
||||||
/>
|
|
||||||
<div class="relative">
|
|
||||||
<button
|
|
||||||
class="px-2 py-1 bg-gray-200 rounded-md"
|
|
||||||
@click="toggleDropdown(index)"
|
|
||||||
>
|
|
||||||
<font-awesome icon="caret-down" class="fa-fw" />
|
|
||||||
</button>
|
|
||||||
<div
|
|
||||||
v-if="dropdownIndex === index"
|
|
||||||
class="absolute bg-white border border-gray-300 rounded-md mt-1"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
v-for="methodType in contactMethodTypes"
|
|
||||||
:key="methodType.value"
|
|
||||||
class="px-4 py-2 hover:bg-gray-100 cursor-pointer"
|
|
||||||
@click="setMethodType(index, methodType.value)"
|
|
||||||
>
|
>
|
||||||
{{ methodType.label }}
|
<option value="">—</option>
|
||||||
</div>
|
<option
|
||||||
|
v-for="methodType in contactMethodTypes"
|
||||||
|
:key="methodType.value"
|
||||||
|
:value="methodType.value"
|
||||||
|
>
|
||||||
|
{{ methodType.label }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex-1">
|
||||||
|
<label class="block text-xs font-medium text-gray-700 mb-1">
|
||||||
|
Value
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
v-model="method.value"
|
||||||
|
type="text"
|
||||||
|
class="block w-full border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500"
|
||||||
|
placeholder="Number, email, etc."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
class="self-end pb-0.5 text-red-500"
|
||||||
|
@click="removeContactMethod(index)"
|
||||||
|
>
|
||||||
|
<font-awesome icon="trash-can" class="fa-fw" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- WhatsApp Help Text -->
|
||||||
|
<div
|
||||||
|
v-if="method.type === 'WHATSAPP'"
|
||||||
|
class="mt-1 ml-[calc(8rem+0.5rem)] text-xs text-gray-600 italic"
|
||||||
|
>
|
||||||
|
Must include country code and only numbers (e.g., 12225551234)
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Label Row -->
|
||||||
|
<div class="mt-2 flex justify-end">
|
||||||
|
<div class="flex-1 ml-[calc(8rem+0.5rem)]">
|
||||||
|
<label class="block text-xs font-medium text-gray-700 mb-1">
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
v-model="method.label"
|
||||||
|
type="text"
|
||||||
|
class="block w-full border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500"
|
||||||
|
placeholder="Label / Note"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="w-[2.5rem]"></div>
|
||||||
</div>
|
</div>
|
||||||
<input
|
|
||||||
v-model="method.value"
|
|
||||||
type="text"
|
|
||||||
class="block ml-2 w-1/2 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500"
|
|
||||||
placeholder="Number, email, etc."
|
|
||||||
/>
|
|
||||||
<button class="ml-2 text-red-500" @click="removeContactMethod(index)">
|
|
||||||
<font-awesome icon="trash-can" class="fa-fw" />
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
<button class="mt-2" @click="addContactMethod">
|
<button class="mt-4" @click="addContactMethod">
|
||||||
<font-awesome
|
<font-awesome
|
||||||
icon="plus"
|
icon="plus"
|
||||||
class="fa-fw px-2 py-2.5 bg-green-500 text-green-100 rounded-full"
|
class="fa-fw px-2 py-2.5 bg-green-500 text-green-100 rounded-full"
|
||||||
@@ -210,12 +224,10 @@ export default class ContactEditView extends Vue {
|
|||||||
contactNotes = "";
|
contactNotes = "";
|
||||||
/** Array of editable contact methods */
|
/** Array of editable contact methods */
|
||||||
contactMethods: Array<ContactMethod> = [];
|
contactMethods: Array<ContactMethod> = [];
|
||||||
/** Currently open dropdown index, null if none open */
|
|
||||||
dropdownIndex: number | null = null;
|
|
||||||
|
|
||||||
/** App string constants */
|
/** App string constants */
|
||||||
AppString = AppString;
|
AppString = AppString;
|
||||||
/** Contact method types for dropdown */
|
/** Contact method types for datalist suggestions */
|
||||||
contactMethodTypes = CONTACT_METHOD_TYPES;
|
contactMethodTypes = CONTACT_METHOD_TYPES;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -273,29 +285,6 @@ export default class ContactEditView extends Vue {
|
|||||||
this.contactMethods.splice(index, 1);
|
this.contactMethods.splice(index, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Toggles the type selection dropdown for a contact method
|
|
||||||
*
|
|
||||||
* If the clicked dropdown is already open, closes it.
|
|
||||||
* If another dropdown is open, closes it and opens the clicked one.
|
|
||||||
*
|
|
||||||
* @param index The array index of the method whose dropdown to toggle
|
|
||||||
*/
|
|
||||||
toggleDropdown(index: number) {
|
|
||||||
this.dropdownIndex = this.dropdownIndex === index ? null : index;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the type for a contact method and closes the dropdown
|
|
||||||
*
|
|
||||||
* @param index The array index of the method to update
|
|
||||||
* @param type The new type value (CELL, EMAIL, WHATSAPP)
|
|
||||||
*/
|
|
||||||
setMethodType(index: number, type: string) {
|
|
||||||
this.contactMethods[index].type = type;
|
|
||||||
this.dropdownIndex = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the edited contact information to the database
|
* Saves the edited contact information to the database
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -52,14 +52,16 @@
|
|||||||
|
|
||||||
<!-- Contact Methods -->
|
<!-- Contact Methods -->
|
||||||
<div v-if="contactFromDid.contactMethods?.length" class="mt-3">
|
<div v-if="contactFromDid.contactMethods?.length" class="mt-3">
|
||||||
<div class="flex flex-wrap gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<div
|
<div
|
||||||
v-for="(method, index) in contactFromDid.contactMethods"
|
v-for="(method, index) in contactFromDid.contactMethods"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="inline-flex items-center gap-2 text-sm"
|
class="flex items-center gap-2 text-sm"
|
||||||
>
|
>
|
||||||
<span class="font-semibold text-slate-600"
|
<span class="font-semibold text-slate-600"
|
||||||
>{{ getContactMethodLabel(method.type) }}:</span
|
>{{
|
||||||
|
getContactMethodLabel(method.type) || "(unspecified)"
|
||||||
|
}}:</span
|
||||||
>
|
>
|
||||||
<span class="text-slate-700">{{ method.label }}</span>
|
<span class="text-slate-700">{{ method.label }}</span>
|
||||||
<span class="text-slate-600">{{ method.value }}</span>
|
<span class="text-slate-600">{{ method.value }}</span>
|
||||||
@@ -71,6 +73,23 @@
|
|||||||
>
|
>
|
||||||
<font-awesome icon="message" class="text-base" />
|
<font-awesome icon="message" class="text-base" />
|
||||||
</a>
|
</a>
|
||||||
|
<a
|
||||||
|
v-if="method.type === 'EMAIL'"
|
||||||
|
:href="`mailto:${method.value}`"
|
||||||
|
class="ml-2 text-blue-500 hover:text-blue-700"
|
||||||
|
title="Send email"
|
||||||
|
>
|
||||||
|
<font-awesome icon="envelope" class="text-base" />
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
v-if="method.type === 'WHATSAPP'"
|
||||||
|
:href="`https://wa.me/${method.value.replace(/\D/g, '')}`"
|
||||||
|
target="_blank"
|
||||||
|
class="ml-2 text-blue-700"
|
||||||
|
title="Send WhatsApp message"
|
||||||
|
>
|
||||||
|
<font-awesome :icon="['fab', 'whatsapp']" class="text-base" />
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user