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
Color Scheme Store
Handles dynamic color scheme management and theme color updates
Chat Store
Manages chat conversations, messages, and real-time communication state
Contacts Store
Handles contact management, filtering, blocking, and contact operations
Calls Store
Manages call history, voice/video call state, and call filtering
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:
Import the Store
Import the store composable in your Vue component:
import { useSettingsStore } from '@/stores/settingsStore'
import { useChatStore } from '@/stores/modules/chat'
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>
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