diff --git a/src/views/ContactEditView.vue b/src/views/ContactEditView.vue index 1111396..cc73e1e 100644 --- a/src/views/ContactEditView.vue +++ b/src/views/ContactEditView.vue @@ -142,6 +142,37 @@ import { AppString, NotificationIface } from "../constants/app"; import { db } from "../db/index"; import { Contact, ContactMethod } from "../db/tables/contacts"; +/** + * Contact Edit View Component + * @author Matthew Raymer + * + * This component provides a full-featured contact editing interface with support for: + * - Basic contact information (name, notes) + * - Multiple contact methods with type selection + * - Data validation and persistence + * + * Workflow: + * 1. Component loads with DID from route params + * 2. Fetches existing contact data from IndexedDB + * 3. Presents editable form with current values + * 4. Validates and saves updates back to database + * + * Contact Method Types: + * - CELL: Mobile phone numbers + * - EMAIL: Email addresses + * - WHATSAPP: WhatsApp contact info + * + * State Management: + * - Maintains separate state for form fields to prevent direct mutation + * - Handles array cloning for contact methods to prevent reference issues + * - Manages dropdown state for method type selection + * + * Navigation: + * - Back button returns to previous view + * - Save redirects to contact detail view + * - Cancel returns to previous view + * - Invalid DID redirects to contacts list + */ @Component({ components: { QuickNav, @@ -149,22 +180,44 @@ import { Contact, ContactMethod } from "../db/tables/contacts"; }, }) export default class ContactEditView extends Vue { + /** Notification function injected by Vue */ $notify!: (notification: NotificationIface, timeout?: number) => void; + /** Current route instance */ $route!: RouteLocationNormalizedLoaded; + /** Router instance for navigation */ $router!: Router; + /** Current contact data */ contact: Contact = { did: "", name: "", notes: "", }; + /** Editable contact name field */ contactName = ""; + /** Editable contact notes field */ contactNotes = ""; + /** Array of editable contact methods */ contactMethods: Array = []; + /** Currently open dropdown index, null if none open */ dropdownIndex: number | null = null; + /** App string constants */ AppString = AppString; + /** + * Component lifecycle hook that initializes the contact edit form + * + * Workflow: + * 1. Extracts DID from route parameters + * 2. Queries database for existing contact + * 3. Populates form fields with contact data + * 4. Handles missing contact error case + * + * @throws Will not throw but redirects on error + * @emits Notification on contact not found + * @emits Router navigation on error + */ async created() { const contactDid = this.$route.params.did; const contact = await db.contacts.get(contactDid || ""); @@ -185,29 +238,75 @@ export default class ContactEditView extends Vue { } } + /** + * Adds a new empty contact method to the methods array + * + * Creates a new method object with empty fields for: + * - label: Custom label for the method + * - type: Communication type (CELL, EMAIL, WHATSAPP) + * - value: The contact information value + */ addContactMethod() { this.contactMethods.push({ label: "", type: "", value: "" }); } + /** + * Removes a contact method at the specified index + * + * @param index The array index of the method to remove + */ removeContactMethod(index: number) { 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 + * + * Workflow: + * 1. Clones contact methods array to prevent reference issues + * 2. Normalizes method types to uppercase + * 3. Checks for changes in method types + * 4. Updates database with new values + * 5. Notifies user of success + * 6. Redirects to contact detail view + * + * @throws Will not throw but notifies on validation errors + * @emits Notification on type changes or success + * @emits Router navigation on success + */ async saveEdit() { // without this conversion, "Failed to execute 'put' on 'IDBObjectStore': [object Array] could not be cloned." const contactMethodsObj = JSON.parse(JSON.stringify(this.contactMethods)); + + // Normalize method types to uppercase const contactMethods = contactMethodsObj.map((method: ContactMethod) => R.set(R.lensProp("type"), method.type.toUpperCase(), method), ); + + // Check for type changes if (!R.equals(contactMethodsObj, contactMethods)) { this.contactMethods = contactMethods; this.$notify( @@ -221,11 +320,15 @@ export default class ContactEditView extends Vue { ); return; } + + // Save to database await db.contacts.update(this.contact.did, { name: this.contactName, notes: this.contactNotes, contactMethods: contactMethods, }); + + // Notify success and redirect this.$notify({ group: "alert", type: "success", diff --git a/src/views/ContactImportView.vue b/src/views/ContactImportView.vue index 12fd3d0..e817618 100644 --- a/src/views/ContactImportView.vue +++ b/src/views/ContactImportView.vue @@ -3,10 +3,7 @@
-

+

@@ -20,43 +17,28 @@
- + Make my activity visible to these contacts.
- One contact is the same as an existing contact - {{ sameCount }} contacts are the same as existing contacts + One contact is the same as an existing contact + {{ sameCount }} contacts are the same as existing contacts
-
    +
    • -
      +

      {{ contact.name || AppString.NO_CONTACT_NAME }} - - Existing + Existing New

      @@ -69,13 +51,9 @@
      Old Value
      New Value
      -
      +
      {{ capitalizeAndInsertSpacesBeforeCaps(contactField) }}
      @@ -88,8 +66,7 @@
    @@ -101,18 +78,10 @@ get the full text and paste it. (Note that iOS cuts off data in text messages.) Ask the person to send the data a different way, eg. email.
    -