Skip to content

Contacts Page

  • File: src/pages/private/contacts/index.svelte

Overview

The Contacts page provides a comprehensive interface for managing contacts, groups, and initiating communications. It features contact searching, filtering, sorting, group management, and event creation capabilities. These diverse views provide users with different perspectives and functionalities, offering a comprehensive and versatile user experience. Users can switch between these views to access specific features, manage contacts, and interact with groups effortlessly.

Core Features

1. Contact Management

  • View and search contacts
  • Sort contacts alphabetically or by recent activity
  • Filter contacts by alphabet
  • Add/remove favorites
  • View contact details
  • Group management

2. Communication Features

  • Start chat sessions
  • Initiate calls
  • Create events
  • Manage group communications

UI Structure

1. Main Layout

svelte
<div class="flex-grow grid grid-cols-1 overflow-y-hidden">
  <!-- Contact Selection Bar -->
  <ContactSelection/>

  <!-- Contact List -->
  <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3">
    <!-- Individual Contacts -->
    <ContactBox/>

    <!-- Group Contacts -->
    <GroupContactBox/>
  </div>

  <!-- Alphabet Scroll -->
  <AlphabetScroll/>
</div>

Contact Selection Bar

The ContactSelection bar or component serves as the initial section on the contact page, remaining hidden until a contact is checked. When triggered, it displays an avatar of the selected contacts on the far left, accompanied by three action buttons on the right side. These action buttons offer the following functionalities:

  • Start Event button: Initiates the EventForm component, pre-populating it with the selected contacts as initial participants.

  • Chat button: Creates a group chat with the selected contacts, triggering the chat view for easy communication.

  • Search icon button: Activates an input field, enabling users to conduct quick and efficient searches within the contact selection area.

svelte
<ContactSelection
  contacts={selectedContacts}
  on:close={clearSelection}
  on:call={onCall}
  on:message={onMessage}
  bind:searchValue
/>

Control Section

After the contact selection bar, the second segment of the contact page is the control action area. This section remains constantly visible, except when the contact selection bar is active. The control action view comprises the page header positioned on the far left and various control elements on the right, which include:

  • Dropdown Menu: This menu enables users to sort the contacts either alphabetically or based on recent interactions.

  • Search Icon Button: Users can activate this button to reveal an input field, facilitating quick and efficient searches within the contact selection area.

  • New Group Button: This button triggers the NewGroup component or form, empowering users to create new contact groups conveniently.

  • Person Icon Button: The person icon button facilitates navigation within the AlphabetScroll component. When clicked, it allows users to scroll to specific contacts whose initials match the selected alphabetical character.

The control action area offers essential tools and functionalities for managing contacts efficiently, while the constant visibility ensures quick access to these features throughout the contact page.

Contacts and Groups Grid

The section is divided into two parts: the contacts section, which occupies three-fourths of the space, and the groups section, which occupies one-fourth.

  • Contact Section: This shows grid layout of all contacts, seamlessly presented through the use of the contact box component. This component offers various functionalities, allowing users to access and interact with their contacts efficiently. The component presents essential contact details and provides quick access to actions like initiating calls, sending messages, and marking favorites.
svelte
<ContactBox
  {contact}
  on:checked={onContactChecked}
  on:addFavourite={addFavourite}
  on:removeFavourate={removeFavourate}
  on:viewDetails={onViewDetails}
  on:call={onCall}
  on:message={onMessage}
/>
  • Group Section: Similar to the contact section, the group section make use of the group contact box tailored specifically for groups. This component elegantly displays essential details about each group, showcases recent interactions, and provides quick access to key action for group management.
svelte
<GroupContactBox
  {contact}
  on:checked={onContactChecked}
  on:viewDetails={openGroupManager}
  on:call={onCall}
  on:message={onMessage}
  on:openManager={openGroupManager}
/>

1. Contact Details Modal

A modal show casing the details of a selected contact

svelte
<Modal on:close={() => (activeContact = null)}>
  <ContactDetails
    contact={activeContact}
    on:call={onCall}
    on:message={onMessage}
  />
</Modal>

2. New Event Modal

A modal to create a new event

svelte
<Modal title="New Event" buttons={newEventButtons}>
  <EventForm
    {contacts}
    initialContacts={activeContacts}
    {startNow}
    on:change={onEventFormChange}
  />
</Modal>

3. Group Management Modal

A modal show casing managing tools and actions for groups

svelte
<Modal title={`${edit ? "Edit Group" : "New Group"}`}>
  <NewGroup
    on:change={onGroupFormChange}
    groupId={activeGroupId}
  />
</Modal>

State Management

1. Contact State

svelte
let contacts: IContact[] = [];
let selectedContacts: IContact[] = [];
let activeContact: IContact | null;
let busy = false;

2. Search State

svelte
let showSearch = false;
let searchValue: string;
let sort = "name";
let activeLetter: string;
let activeCharacters: string[] = [];

3. Group State

svelte

let groupId: number | null;
let groupData: any;
let showNewGroupForm = false;
let edit = false;

Key Functions

1. Contact Operations

svelte
// Load Contacts
async function search(term, alphabet, sort) {
  busy = true;
  try {
    const ret = await readContacts(term, alphabet, sort);
    contacts = ret.success ? ret.data : [];
    activeCharacters = ret.contactAlphabets;
  } finally {
    busy = false;
  }
}

// Favorite Management
async function addFavourite({ detail: contact }) {
  const ret = await setFavourite(contact.id, true);
  if (ret.success) {
    await dSearch(searchValue, activeLetter, sort);
  }
}

2. Communication Functions

svelte

// Start Chat
async function onMessage({ detail: contact }) {
  const selected = contact ? [contact] : selectedContacts;
  $activeChat = { targets: selected };

  const ret = await sendMessage({
    content: "",
    contacts: selected.map(x => x.id)
  });

  if (ret.success && ret.data?.groupId) {
    activateChatGroup(+ret.data.groupId);
  }
}

// Initiate Call/Event
function onCall({ detail: contact }) {
  activeContacts = contact ? [contact] : selectedContacts;
  startNow = true;
  showNewEventForm = true;
}

3. Group Management

svelte
// Create Group
async function createGroup(command) {
  const ret = await createGroup({
    name: groupData.groupName,
    description: groupData.description,
    participants: known,
    unknownParticipants: unknown
  });

  if (ret.success) {
    showInfo("Group created successfully");
    await dSearch(searchValue, activeLetter, sort);
  }
}

Event Handlers

1. Contact Selection

svelte
function onContactChecked({ detail }) {
  const { contact, checked } = detail;
  if (!checked) {
    selectedContacts = selectedContacts.filter(x => x.id !== contact.id);
  } else {
    selectedContacts = [...selectedContacts, contact];
  }
}

2. Real-time Status Updates

svelte
function onUserStatusChanged(status) {
  contacts = contacts.map(x => {
    if (x.username == status.username) {
      x.online = status.online;
    }
    return x;
  });
}

Permissions

svelte
// View Access
if (!hasPermission(Permissions.viewContacts)) {
  $goto("/private/dashboard");
  return;
}

// Group Management
{#if hasPermission(Permissions.manageGroups)}
  <button on:click={() => showNewGroupForm = true}>
    New group
  </button>
{/if}

Lifecycle Management

svelte

onMount(async () => {
  // Check permissions
  if (!hasPermission(Permissions.viewContacts)) {
    $goto("/private/dashboard");
    return;
  }

  // Initial data load
  await dSearch(searchValue, activeLetter, sort);
});

onDestroy(() => {
  unsubscribe("userStatus", onUserStatusChanged);
});

Released under the MIT License.