State Management

TeBiMa uses a combination of Vue 3's Composition API, Nuxt 3's built-in state management capabilities, and the @sidebase/nuxt-auth module for authentication state.

Authentication State

The @sidebase/nuxt-auth module provides authentication state management:

components/AuthStatus.vue
<script setup>
import { useAuth } from '@sidebase/nuxt-auth'

const { status, data, signOut } = useAuth()

// Access user data
const username = computed(() => data.value?.username || 'Guest')
const userRole = computed(() => data.value?.role || '')

// Check authentication status
const isLoggedIn = computed(() => status.value === 'authenticated')

// Perform logout
const handleLogout = async () => {
  try {
    await signOut({ callbackUrl: '/login' })
  } catch (error) {
    console.error('Logout failed:', error)
  }
}
</script>

API State Management

API calls are managed using a custom $api composable:

composables/api.js
export const useApi = () => {
  const $api = async (endpoint, options = {}) => {
    // Implementation details...
  }

  return {
    $api
  }
}
components/DataFetcher.vue
<script setup>
const { $api } = useApi()

const fetchData = async () => {
  const response = await $api('/endpoint', { method: 'GET' })
  // Handle response...
}
</script>

Form State

Form state is typically managed within individual components using ref and reactive. For form validation, a custom useFormValidation composable is used:

composables/formValidation.js
export const useFormValidation = () => {
  // Implementation details...
}
components/CreateMatchForm.vue
<script setup>
const { errors, validateField, validateForm, clearErrors } = useFormValidation()

const validateCreateMatch = () => {
  const rules = {
    game_id: [{ required: true, message: 'Game is required' }],
    round_number: [
      { required: true, message: 'Round number is required' },
      { custom: value => value > 0, message: 'Round number must be positive' }
    ],
    participating_teams: [
      { required: true, message: 'At least one team must be selected' },
      { custom: value => value.length >= 2, message: 'At least two teams must be selected' }
    ]
  }

  return validateForm(newMatch.value, rules)
}
</script>

Shared State

For state that needs to be shared between components, TeBiMa uses Vue's provide/inject API:

layouts/default.vue
<script setup>
provide('layout', {
  isFullscreen,
  toggleFullscreen,
  isSidebarCollapsed,
  toggleSidebar
})
</script>
components/ChildComponent.vue
<script setup>
const { isFullscreen, toggleFullscreen } = inject('layout')
</script>

Best Practices

  1. Use useAuth for all authentication-related state and actions.
  2. Leverage the $api composable for consistent API state management across the application.
  3. Keep form state local to components where possible, using useFormValidation for validation.
  4. Use provide/inject for sharing state between related components.
  5. Use computed properties to derive state where possible, rather than storing derived state.

By following these practices and leveraging Vue 3 and Nuxt 3's built-in capabilities, TeBiMa maintains a simple yet effective state management system.