Skip to content

Survey Results Recipe

Patterns for handling and processing survey results from Sibilance.

Overview

This recipe covers common patterns for handling survey results, including submission, storage, and processing.

Basic Result Handling

Access Results

typescript
const client = new SibilanceClient({
  surveyKey: 'sibilance_your_key_here'
}, {
  onComplete: (yaml) => {
    // yaml is an array of collected information
    console.log('Results:', yaml);
    
    // Example structure:
    // [
    //   { field: 'name', value: 'John Doe', sourceStep: 'introduction', timestamp: 1234567890 },
    //   { field: 'email', value: 'john@example.com', sourceStep: 'contact', timestamp: 1234567891 },
    //   { field: 'project_type', value: 'residential', sourceStep: 'project_details', timestamp: 1234567892 }
    // ]
  }
});

Get Results Programmatically

typescript
// Get results at any time
const surveyState = client.getSurveyState();
const results = surveyState.collectedInfo;

// Or get YAML format
const yaml = client.getYAML();

Result Submission

Submit to API

typescript
const client = new SibilanceClient({
  surveyKey: 'sibilance_your_key_here'
}, {
  onComplete: async (yaml) => {
    try {
      const response = await fetch('/api/survey-results', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          surveyId: 'your-survey-id',
          results: yaml,
          timestamp: new Date().toISOString(),
          userAgent: navigator.userAgent
        })
      });
      
      if (!response.ok) {
        throw new Error(`HTTP ${response.status}`);
      }
      
      const data = await response.json();
      console.log('Results submitted:', data);
    } catch (error) {
      console.error('Failed to submit:', error);
      // Retry or show error
    }
  }
});

Submit with Retry Logic

typescript
async function submitWithRetry(yaml: any[], maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const response = await fetch('/api/survey-results', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ results: yaml })
      });
      
      if (response.ok) {
        return await response.json();
      }
      
      throw new Error(`HTTP ${response.status}`);
    } catch (error) {
      if (i === maxRetries - 1) throw error;
      await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
    }
  }
}

const client = new SibilanceClient({
  surveyKey: 'sibilance_your_key_here'
}, {
  onComplete: async (yaml) => {
    try {
      await submitWithRetry(yaml);
      console.log('Results submitted successfully');
    } catch (error) {
      console.error('Failed after retries:', error);
    }
  }
});

Result Processing

Transform Results

typescript
function processResults(yaml: any[]) {
  // Transform to your data structure
  const processed = yaml.reduce((acc, item) => {
    acc[item.field] = {
      value: item.value,
      step: item.sourceStep,
      timestamp: new Date(item.timestamp)
    };
    return acc;
  }, {} as Record<string, any>);
  
  return processed;
}

const client = new SibilanceClient({
  surveyKey: 'sibilance_your_key_here'
}, {
  onComplete: (yaml) => {
    const processed = processResults(yaml);
    console.log('Processed results:', processed);
  }
});

Validate Results

typescript
function validateResults(yaml: any[]): { valid: boolean; errors: string[] } {
  const errors: string[] = [];
  
  // Check required fields
  const requiredFields = ['name', 'email'];
  for (const field of requiredFields) {
    if (!yaml.find(item => item.field === field)) {
      errors.push(`Missing required field: ${field}`);
    }
  }
  
  // Validate email format
  const emailItem = yaml.find(item => item.field === 'email');
  if (emailItem && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(emailItem.value)) {
    errors.push('Invalid email format');
  }
  
  return {
    valid: errors.length === 0,
    errors
  };
}

const client = new SibilanceClient({
  surveyKey: 'sibilance_your_key_here'
}, {
  onComplete: (yaml) => {
    const validation = validateResults(yaml);
    
    if (validation.valid) {
      submitResults(yaml);
    } else {
      console.error('Validation errors:', validation.errors);
      // Show errors to user
    }
  }
});

Result Storage

Local Storage

typescript
const client = new SibilanceClient({
  surveyKey: 'sibilance_your_key_here'
}, {
  onComplete: (yaml) => {
    // Store locally as backup
    const stored = {
      results: yaml,
      timestamp: new Date().toISOString(),
      surveyKey: 'sibilance_your_key_here'
    };
    
    const existing = JSON.parse(localStorage.getItem('survey-results') || '[]');
    existing.push(stored);
    localStorage.setItem('survey-results', JSON.stringify(existing));
  }
});

IndexedDB

typescript
async function storeInIndexedDB(yaml: any[]) {
  const db = await openDB('survey-results', 1, {
    upgrade(db) {
      db.createObjectStore('results', { keyPath: 'id', autoIncrement: true });
    }
  });
  
  await db.add('results', {
    results: yaml,
    timestamp: new Date().toISOString()
  });
}

const client = new SibilanceClient({
  surveyKey: 'sibilance_your_key_here'
}, {
  onComplete: async (yaml) => {
    await storeInIndexedDB(yaml);
  }
});

Result Display

Display Results in UI

tsx
function ResultsDisplay() {
  const [results, setResults] = useState<any[]>([]);
  
  const { surveyState } = useSibilance({
    surveyKey: 'sibilance_your_key_here'
  }, {
    onComplete: (yaml) => {
      setResults(yaml);
    }
  });

  return (
    <div className="results">
      <h3>Survey Results</h3>
      {results.map((item, i) => (
        <div key={i} className="result-item">
          <strong>{item.field}:</strong> {item.value}
          {item.sourceStep && (
            <small> (from {item.sourceStep})</small>
          )}
        </div>
      ))}
    </div>
  );
}

Export Results

typescript
function exportResults(yaml: any[], format: 'json' | 'csv' = 'json') {
  if (format === 'json') {
    const blob = new Blob([JSON.stringify(yaml, null, 2)], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `survey-results-${Date.now()}.json`;
    a.click();
  } else if (format === 'csv') {
    const headers = ['Field', 'Value', 'Step', 'Timestamp'];
    const rows = yaml.map(item => [
      item.field,
      item.value,
      item.sourceStep || '',
      new Date(item.timestamp).toISOString()
    ]);
    
    const csv = [headers, ...rows]
      .map(row => row.map(cell => `"${cell}"`).join(','))
      .join('\n');
    
    const blob = new Blob([csv], { type: 'text/csv' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `survey-results-${Date.now()}.csv`;
    a.click();
  }
}

const client = new SibilanceClient({
  surveyKey: 'sibilance_your_key_here'
}, {
  onComplete: (yaml) => {
    exportResults(yaml, 'json');
  }
});