Appearance
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);
}