Skip to content

useSupportApi Composable ​

File Information ​

  • Path: app/composables/api/useSupportApi.ts
  • Purpose: Support and feedback API operations
  • Category: API Composable

Overview ​

The useSupportApi composable provides API operations for sending feedback and support requests to the system administrators.

Functions ​

sendFeedback ​

Sends feedback or support request to the system.

Signature:

typescript
sendFeedback(body: any): Promise<any>

Parameters:

  • body: any - Feedback data (can be FormData for file uploads or plain object)

Returns:

  • Promise<any> - Response data

Features:

  • Supports both FormData (for file attachments) and plain objects
  • Handles file uploads in feedback

Usage:

typescript
const { sendFeedback } = useSupportApi()

// Send text feedback
await sendFeedback({
  subject: 'Bug Report',
  message: 'Found an issue with the search feature',
  category: 'bug',
  email: '[email protected]'
})

// Send feedback with file attachment
const formData = new FormData()
formData.append('subject', 'Feature Request')
formData.append('message', 'Please add dark mode')
formData.append('file', fileBlob, 'screenshot.png')

await sendFeedback(formData)

API Endpoint: POST /digital/feedback

Request Body Formats ​

Text Feedback ​

typescript
{
  subject: string           // Feedback subject
  message: string          // Feedback message
  category?: string        // Feedback category (bug, feature, etc.)
  email?: string          // User email (optional)
  name?: string           // User name (optional)
}

Feedback with File Attachment ​

typescript
FormData {
  subject: string
  message: string
  category?: string
  file: File              // Attached file
  email?: string
  name?: string
}

Complete Usage Example ​

typescript
const { sendFeedback } = useSupportApi()
const snackbar = useSnackbar()

// Text feedback
const submitTextFeedback = async () => {
  try {
    await sendFeedback({
      subject: 'Bug Report',
      message: 'The search filter is not working correctly',
      category: 'bug'
    })
    snackbar.showSuccess('Feedback submitted successfully')
  } catch (error) {
    snackbar.showError('Failed to submit feedback')
  }
}

// Feedback with screenshot
const submitFeedbackWithScreenshot = async (file: File) => {
  try {
    const formData = new FormData()
    formData.append('subject', 'UI Issue')
    formData.append('message', 'The button alignment looks off')
    formData.append('category', 'ui')
    formData.append('file', file)
    
    await sendFeedback(formData)
    snackbar.showSuccess('Feedback with screenshot submitted')
  } catch (error) {
    snackbar.showError('Failed to submit feedback')
  }
}

Integration with Feedback Form ​

vue
<script setup lang="ts">
const { sendFeedback } = useSupportApi()
const snackbar = useSnackbar()

const form = ref({
  subject: '',
  message: '',
  category: 'general',
  file: null as File | null
})

const loading = ref(false)

const submitFeedback = async () => {
  if (!form.value.subject || !form.value.message) {
    snackbar.showError('Please fill in all required fields')
    return
  }
  
  loading.value = true
  try {
    if (form.value.file) {
      // With file attachment
      const formData = new FormData()
      formData.append('subject', form.value.subject)
      formData.append('message', form.value.message)
      formData.append('category', form.value.category)
      formData.append('file', form.value.file)
      
      await sendFeedback(formData)
    } else {
      // Text only
      await sendFeedback({
        subject: form.value.subject,
        message: form.value.message,
        category: form.value.category
      })
    }
    
    snackbar.showSuccess('Thank you for your feedback!')
    // Reset form
    form.value = { subject: '', message: '', category: 'general', file: null }
  } catch (error) {
    snackbar.showError('Failed to submit feedback. Please try again.')
  } finally {
    loading.value = false
  }
}

const handleFileSelect = (event: Event) => {
  const input = event.target as HTMLInputElement
  if (input.files && input.files[0]) {
    form.value.file = input.files[0]
  }
}
</script>

<template>
  <v-form @submit.prevent="submitFeedback">
    <v-text-field
      v-model="form.subject"
      label="Subject"
      required
    />
    <v-textarea
      v-model="form.message"
      label="Message"
      required
    />
    <v-select
      v-model="form.category"
      :items="['bug', 'feature', 'ui', 'general']"
      label="Category"
    />
    <v-file-input
      label="Attachment (optional)"
      @change="handleFileSelect"
    />
    <v-btn
      type="submit"
      :loading="loading"
      color="primary"
    >
      Submit Feedback
    </v-btn>
  </v-form>
</template>

Error Handling ​

The composable includes error handling with logging:

typescript
catch (error: any) {
  console.error('[SupportAPI] sendFeedback - Error:', error)
  throw error
}

Use Cases ​

Bug Report ​

typescript
const { sendFeedback } = useSupportApi()

const reportBug = async (description: string, screenshot?: File) => {
  const body: any = {
    subject: 'Bug Report',
    message: description,
    category: 'bug'
  }
  
  if (screenshot) {
    const formData = new FormData()
    Object.keys(body).forEach(key => formData.append(key, body[key]))
    formData.append('file', screenshot)
    await sendFeedback(formData)
  } else {
    await sendFeedback(body)
  }
}

Feature Request ​

typescript
const { sendFeedback } = useSupportApi()

const requestFeature = async (feature: string, description: string) => {
  await sendFeedback({
    subject: `Feature Request: ${feature}`,
    message: description,
    category: 'feature'
  })
}