Overview

Bimble Chat Vue uses Pinia 3.0.3 as the state management solution, providing a type-safe, intuitive, and lightweight store system. The application is organized into feature-specific stores using both Options API and Composition API patterns.

Why Pinia?

Pinia is the official state management library for Vue 3, offering better TypeScript support, a simpler API, and excellent DevTools integration compared to Vuex.

Store Architecture

The stores are organized in a logical structure with clear separation of concerns:

Settings Store

Manages global application settings, theme preferences, and user interface state

stores/settingsStore.ts
Color Scheme Store

Handles dynamic color scheme management and theme color updates

stores/colorSchemeStore.ts
Chat Store

Manages chat conversations, messages, and real-time communication state

stores/modules/chat.ts
Contacts Store

Handles contact management, filtering, blocking, and contact operations

stores/modules/contacts.ts
Calls Store

Manages call history, voice/video call state, and call filtering

stores/modules/calls.ts

Directory Structure

The stores are organized in a clear directory structure:

src/stores/
├── settingsStore.ts        # Global app settings
├── colorSchemeStore.ts     # Color scheme management
└── modules/                # Feature-specific stores
    ├── chat.ts            # Chat functionality
    ├── contacts.ts        # Contact management
    └── calls.ts           # Call history and management

Store Patterns

Bimble Chat Vue uses both Options API and Composition API patterns for different store types:

// Settings Store - Options API Pattern
import { defineStore } from "pinia";

export const useSettingsStore = defineStore("settingsStore", {
  state: () => ({
    activeTheme: 'LIGHT_THEME',
    isDarkMode: false,
    language: 'en',
  }),
  
  actions: { 
    SET_THEME(payload: string) {
      this.activeTheme = payload;
      this.isDarkMode = payload === 'DARK_THEME';
    },
    SET_LANGUAGE(payload: string) {
      this.language = payload;
    }
  },
});
// Chat Store - Composition API Pattern
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';

export const useChatStore = defineStore('chat', () => {
  // State
  const chats = ref<Chat[]>([]);
  const loading = ref(false);
  const error = ref<string | null>(null);
  
  // Computed/Getters
  const activeChats = computed(() => 
    chats.value.filter(chat => !chat.isArchived)
  );
  
  // Actions
  const fetchChats = async () => {
    loading.value = true;
    try {
      const response = await axios.get('/api/chats');
      chats.value = response.data;
    } catch (err) {
      error.value = 'Failed to fetch chats';
    } finally {
      loading.value = false;
    }
  };
  
  return {
    chats,
    loading,
    error,
    activeChats,
    fetchChats
  };
});

Basic Usage

Here's how to use Pinia stores in your Vue components:

1
Import the Store

Import the store composable in your Vue component:

import { useSettingsStore } from '@/stores/settingsStore'
import { useChatStore } from '@/stores/modules/chat'
2
Use in Component

Access state and actions in your component setup or script:

<script setup lang="ts">
import { useSettingsStore } from '@/stores/settingsStore'

// Initialize store
const settingsStore = useSettingsStore()

// Access state
const isDarkMode = computed(() => settingsStore.isDarkMode)
const currentLanguage = computed(() => settingsStore.language)

// Call actions
const toggleTheme = () => {
  settingsStore.SET_DARK_MODE(!settingsStore.isDarkMode)
}

const changeLanguage = (lang: string) => {
  settingsStore.SET_LANGUAGE(lang)
}
</script>
3
Reactive Template

Use store state directly in your template:

<template>
  <div>
    <h3>Current Theme: {{ settingsStore.activeTheme }}</h3>
    <button @click="toggleTheme">
      Switch to {{ isDarkMode ? 'Light' : 'Dark' }} Mode
    </button>
    
    <select @change="changeLanguage($event.target.value)">
      <option value="en">English</option>
      <option value="fr">French</option>
      <option value="es">Spanish</option>
    </select>
  </div>
</template>

Store Details

Detailed information about each store and their responsibilities:

Settings Store

Purpose: Manages global application settings and UI preferences

  • State: Theme mode, sidebar state, language, RTL layout
  • Actions: Theme switching, language changes, UI toggles
  • Pattern: Options API for simple state management
// Key Actions
SET_MINI_SIDEBAR(payload: boolean)
SET_THEME(payload: string)
SET_DARK_MODE(payload: boolean)
SET_LANGUAGE(payload: string)
Color Scheme Store

Purpose: Handles dynamic color scheme changes with predefined themes

  • State: Active color scheme, scheme definitions
  • Getters: Current color scheme object
  • Schemes: Blue, Aqua, Purple, Green, Cyan
// Available Color Schemes
const colorSchemes = [
  { name: 'blue', primary: '#2687e5' },
  { name: 'aqua', primary: '#0074BA' },
  { name: 'purple', primary: '#763EBD' },
  { name: 'green', primary: '#0A7EA4' },
  { name: 'cyan', primary: '#01C0C8' }
]
Chat Store

Purpose: Manages chat conversations and messaging functionality

  • State: Chat list, loading states, conversation status
  • Actions: Fetch chats, search, conversation management
  • Pattern: Composition API for complex reactive logic
// Key Actions
fetchChats()
searchChats(query: string)
setConversationActive(active: boolean)
Contacts Store

Purpose: Handles contact management and organization

  • State: Contact list, search query, active tab
  • Computed: Filtered contacts, contact counts
  • Features: Search, filtering, blocking, adding contacts
// Key Actions
fetchContacts()
addContact(newContact: NewContact)
blockContact(contactId: number)

TypeScript Integration

All stores are fully typed with TypeScript for better development experience and type safety:

// Type Definitions Example
export interface ColorScheme {
  name: string;
  displayName: string;
  primary: string;
  secondary: string;
  lightprimary: string;
  lightsecondary: string;
}

// Store with Types
export const useColorSchemeStore = defineStore("colorSchemeStore", {
  state: () => ({
    activeColorScheme: 'blue' as string,
  }),
  
  getters: {
    currentColorScheme: (state): ColorScheme => {
      return colorSchemes.find(scheme => scheme.name === state.activeColorScheme) || colorSchemes[0];
    }
  },
  
  actions: {
    setColorScheme(schemeName: string): void {
      this.activeColorScheme = schemeName;
    }
  }
});

Best Practices

Do
  • Use TypeScript for type safety
  • Keep stores focused on single responsibilities
  • Use computed properties for derived state
  • Handle async operations with proper error handling
  • Use Composition API for complex reactive logic
Avoid
  • Directly mutating state outside of actions
  • Storing large objects that don't need reactivity
  • Creating unnecessary nested store dependencies
  • Forgetting to handle loading and error states
  • Using stores for temporary component state

DevTools Integration

Pinia provides excellent DevTools support for debugging and monitoring store state:

DevTools Features
  • Real-time state inspection
  • Time-travel debugging
  • Action tracking and replay
  • State mutation monitoring
  • Performance profiling