Skip to content

Dashboard

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

Overview

The Dashboard feature is a comprehensive interface that combines event scheduling and contact management. It serves as the main hub for users to manage scheduled events, interact with recent contacts, and initiate communication sessions within the HVC Web platform.

In cases where a user lacks specific permissions, certain views within the feature or view will be hidden from their access. This ensures that users only see the relevant and permissible information and actions based on their assigned privileges. The feature dynamically adapts its display, tailoring the views and functionalities according to each user's authorized access level. This approach helps maintain security and data privacy while providing a customized and appropriate experience for different users within the system.

Core Features

1. Event Management

  • View scheduled events
  • Create and edit events
  • Start immediate or scheduled events
  • Join active events
  • Event details viewing and modification

2. Contact Management

  • Display recent contacts
  • Real-time contact search
  • Favorite contact management
  • Contact details viewing
  • Initiate calls or messages

Module Functions

1. Contact Management

svelte
async function readRecentContacts(term = null): Promise<{
  success: boolean;
  data?: IContact[];
  message?: string;
}>;

async function setFavourite(
  contactId: number,
  isFavourite: boolean
): Promise<{
  success: boolean;
  message: string;
}>;

2. Event Management

svelte
async function readUpcomingEvents(
  minutesBefore: number = 60
): Promise<{
  success: boolean;
  data?: any[];
  message?: string;
}>;

async function createEvent(payload: any): Promise<{
  success: boolean;
  message?: string;
  data?: any;
}>;

async function updateEvent(payload: any): Promise<{
  success: boolean;
  message?: string;
  data?: any;
}>;

State Management

Component State

svelte
// UI State
let showSearch = false;
let searchValue: string;
let showNewEventForm = false;
let showDetailsModal = false;
let processing = false;
let edit = false;

// Data State
let events: ICardInfo[] = [];
let contacts: IContact[] = [];
let selectedContacts: IContact[] = [];
let activeContact: IContact;
let activeContacts: IContact[] = [];
let activeEvent: any;

// Loading State
let contactsBusy = false;
let eventsBusy = false;

Reactive Statements

svelte
// Search Debouncing
const dSearch = debounce(delay, loadContacts);
$: dSearch(searchValue, sort);

UI Structure

1, Main Layout

svelte
<div class="grid grid-cols-1 sm:grid-cols-2 py-3 px-4">
  <!-- Events Section -->
  <div class="px-2 flex flex-col border-r-2">
    <CardHolder>
      <!-- Events List -->
    </CardHolder>
  </div>

  <!-- Contacts Section -->
  <div class="px-2 flex flex-col">
    <CardHolder>
      <!-- Contacts List -->
    </CardHolder>
  </div>
</div>

2. Event Creation and update Modal

svelte

<Modal
  title={`${edit ? "Update Event" : "New Event"}`}
  buttons={newEventButtons}
>
  <EventForm
    contacts={[]}
    initialContacts={activeContacts}
    startNow={edit ? false : true}
    on:change={onEventFormChange}
  />
</Modal>

3. Event detail Modal

svelte
{#if showDetailsModal && activeEvent}
  <Modal
    title={activeEvent.title}
    bind:open={showDetailsModal}
    on:close={(_) => {
      showDetailsModal = false;
      activeEvent = null;
    }}
    showCloseButton={true}
    buttons={detailsButtons}
    dangerous
    showIcon={false}
    closeOnOutsideClick
  >
    <EventDetails
      activeEventId={activeEvent.id}
      activeEvent={null}
      on:editEvent={editEvent}
      on:deleted={() => {
        showDetailsModal = false;
        activeEvent = null;
        loadUpcomingEvents();
      }}
    />
  </Modal>
{/if}

4. Contact Details Modal

svelte
{#if activeContact}
  <Modal
    on:close={(_) => (activeContact = null)}
    showIcon={false}
    grayBg
    padded={false}
  >
    <ContactDetails
      contact={activeContact}
      on:message={onMessage}
      on:call={onCall}
    />
  </Modal>
{/if}

Event Handlers

1. Contact Actions

svelte
async function addFavourite({ detail: contact }) {
  const ret = await setFavourite(contact.id, true);
  if (ret.success) {
    contacts = contacts.map(x => ({
      ...x,
      favourite: x.id === contact.id ? true : x.favourite
    }));
  }
}

// Remove from Favorites
async function removeFavourate({ detail: contact }) {
  const ret = await setFavourite(contact.id, false);
  if (ret.success) {
    contacts = contacts.map(x => ({
      ...x,
      favourite: x.id === contact.id ? false : x.favourite
    }));
  }
}

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

2. Event Actions

svelte
async function startEvent({ detail: contact }) {
  const initRet = await initEvent(contact.id, false);
  if (initRet.success) {
    window.open(`/private/events/${contact.id}`);
  }
}

async function onEventFormChange({ detail: event }) {
  eventData = event;
  updateButtonLabels(event.startNow);
}

Data Loading

1. Contact Loading

svelte
async function loadContacts(term, sort) {
  contactsBusy = true;
  try {
    const ret = await readRecentContacts(term);
    if (ret.success) {
      contacts = ret.data;
    }
  } finally {
    contactsBusy = false;
  }
}

2. Event Loading

svelte
async function loadUpcomingEvents() {
  eventsBusy = true;
  try {
    const ret = await readUpcomingEvents(60);
    if (ret.success) {
      events = ret.data;
    }
  } finally {
    eventsBusy = false;
  }
}

Permission Management

svelte

// Permission Checks
const canViewRecentContacts = hasPermission(Permissions.viewRecentCalls);
const canManageEvents = hasPermission(Permissions.manageEvents);

// Conditional Rendering
<div class:hidden={!hasPermission(Permissions.manageEvents)}>
  <!-- Protected Content -->
</div>

Error Handling

svelte
try {
  const ret = await operation();
  if (!ret.success) {
    showError(ret.message);
    return;
  }
} catch (e) {
  showError(e?.message || e);
}

Dependant Components

Released under the MIT License.