# Solution Design Document

## Validation Checklist

- [x] All required sections are complete
- [x] No [NEEDS CLARIFICATION] markers remain
- [x] All context sources are listed with relevance ratings
- [x] Project commands are discovered from actual project files
- [x] Constraints → Strategy → Design → Implementation path is logical
- [x] Architecture pattern is clearly stated with rationale
- [x] Every component in diagram has directory mapping
- [x] Every interface has specification
- [x] Error handling covers all error types
- [x] Quality requirements are specific and measurable
- [x] Every quality requirement has test coverage
- [x] **All architecture decisions confirmed by user**
- [x] Component names consistent across diagrams
- [x] A developer could implement from this design

---

## Constraints

CON-1 **Technology Stack**
- PHP 8.x with Slim 2.6.2 framework
- Twig 1.44.8 templating engine
- Chart.js for data visualization
- DataTables jQuery plugin for table functionality
- Must work in Chrome 90+, Safari 14+, Firefox 88+, Edge 90+

CON-2 **Coding Standards**
- Follow existing PSR-4 autoloading structure under `BuyerKiosk\` namespace
- CSS must be scoped to avoid conflicts with existing styles
- JavaScript must integrate with existing jQuery patterns
- Follow backstock-home.css design patterns

CON-3 **Data Requirements**
- No database schema changes allowed
- Must use existing survey API endpoints
- Must preserve all existing functionality

## Implementation Context

**IMPORTANT**: You MUST read and analyze ALL listed context sources to understand constraints, patterns, and existing architecture.

### Required Context Sources

```yaml
# Internal documentation and patterns
- doc: docs/guides/style-guide.md
  relevance: HIGH
  why: "Brand design system with colors, typography, spacing"

- doc: docs/features/backstock.md
  relevance: MEDIUM
  why: "Reference implementation for modern admin page design"

# CSS Files - Design System Reference
- file: public_html/css/backstock-home.css
  relevance: CRITICAL
  sections: [stat-card, action-toolbar, backstock-table-wrapper, tips-card]
  why: "Primary design pattern source - must match this styling"

# Existing Survey Implementation
- file: userfrosting/templates/themes/default/survey/results.html
  relevance: CRITICAL
  why: "Current template to be redesigned - understand existing structure"

- file: userfrosting/routes/api.php
  relevance: HIGH
  sections: [survey API endpoints]
  why: "Existing API endpoints that provide survey data"

# Component References
- file: userfrosting/templates/themes/default/components/head.html
  relevance: MEDIUM
  why: "Shared component structure to follow"

- file: userfrosting/templates/themes/default/components/nav-account.html
  relevance: MEDIUM
  why: "Navigation component integration point"
```

### Implementation Boundaries

- **Must Preserve**:
  - Survey data loading via AJAX
  - Date range picker functionality
  - AI Analysis API integration
  - Chart.js chart rendering
  - DataTables functionality
  - All existing JavaScript function signatures

- **Can Modify**:
  - HTML template structure
  - CSS styling (add new stylesheet)
  - JavaScript for UI enhancements
  - Chart colors and options
  - DataTable column configuration

- **Must Not Touch**:
  - Database schema
  - API endpoint contracts
  - Survey submission process
  - Authentication/authorization logic

### External Interfaces

#### System Context Diagram

```mermaid
graph TB
    User[Store Manager] --> SurveyResults[Survey Results Page]

    SurveyResults --> SurveyAPI[Survey Results API]
    SurveyResults --> AIAnalysisAPI[AI Analysis API]

    SurveyAPI --> Database[(MySQL Database)]
    AIAnalysisAPI --> OpenAI[OpenAI API]
```

#### Interface Specifications

```yaml
# Inbound Interfaces (what calls this system)
inbound:
  - name: "Survey Results Page"
    type: HTTP/HTTPS
    format: HTML
    authentication: Session-based
    route: GET /admin/:typeNum/survey/results
    data_flow: "User requests survey results view"

# Outbound Interfaces (what this system calls)
outbound:
  - name: "Survey Results API"
    type: HTTPS
    format: JSON
    authentication: Session cookie
    endpoint: POST /api/:typeNum/survey/results/getByDateRange
    data_flow: "Fetch survey data for date range"
    criticality: HIGH

  - name: "AI Analysis API"
    type: HTTPS
    format: JSON
    authentication: Session cookie
    endpoint: POST /api/:typeNum/survey/analysis
    data_flow: "Generate AI insights from survey data"
    criticality: MEDIUM

# Data Interfaces
data:
  - name: "Survey Results Data"
    type: MySQL
    tables: [postBuySurveys, customers, buys, employees]
    data_flow: "Survey response persistence and retrieval"
```

### Project Commands

```bash
# Component: Survey Results Page
Location: userfrosting/templates/themes/default/survey/

## Environment Setup
Install Dependencies: cd userfrosting && composer install
Start Development: Local Apache/nginx with PHP

# Testing Commands
Manual Testing: Navigate to /admin/:typeNum/survey/results in browser
Visual Regression: Compare screenshots before/after

# Code Quality Commands
PHP Linting: (not configured)
CSS Validation: Validate against W3C standards

# Build & Compilation
No build step required - PHP/Twig renders server-side
CSS changes are immediate
JS changes are immediate

# Deployment
Deploy: ./deploy.sh (runs tests then deploys)
```

## Solution Strategy

- **Architecture Pattern**: Progressive Enhancement within existing MVC architecture
  - Server-side rendering with Twig templates
  - CSS-only styling changes (new stylesheet)
  - JavaScript enhancements for interactivity

- **Integration Approach**: Drop-in replacement
  - New CSS file loaded alongside existing styles
  - Same template file, restructured HTML
  - JavaScript functions maintained, UI code updated

- **Justification**: This approach minimizes risk by:
  - Not changing any backend code or APIs
  - Maintaining all existing functionality
  - Using proven design patterns from backstock pages
  - Allowing incremental testing and rollback

- **Key Decisions**:
  1. Create new CSS file `survey-results.css` to avoid conflicts
  2. Add `.survey-results-page` class to body for style scoping
  3. Reuse backstock CSS patterns wholesale where possible
  4. Keep Chart.js but update color palette

## Building Block View

### Components

```mermaid
graph TD
    subgraph "Survey Results Page"
        PageHeader[Page Header Component]
        StatsGrid[Stats Grid Component]
        ChartsSection[Charts Section]
        AIAnalysis[AI Analysis Section]
        DataTable[Survey Results Table]
    end

    subgraph "Shared Components"
        DatePicker[Date Range Picker]
        StatCard[Stat Card]
        ChartCard[Chart Card]
        ModernTable[Modern Table Wrapper]
    end

    PageHeader --> DatePicker
    StatsGrid --> StatCard
    ChartsSection --> ChartCard
    DataTable --> ModernTable
```

### Directory Map

**CSS Files:**
```
public_html/
├── css/
│   ├── backstock-home.css        # REFERENCE: Design patterns
│   └── survey-results.css        # NEW: Survey-specific styles
```

**Template Files:**
```
userfrosting/
├── templates/
│   └── themes/
│       └── default/
│           └── survey/
│               └── results.html  # MODIFY: Restructure HTML
```

**JavaScript:**
```
(Inline in results.html - MODIFY existing scripts)
```

### Interface Specifications

#### Data Storage Changes

```yaml
# No database changes required
# Existing tables used:
# - postBuySurveys
# - customers
# - buys
# - employees
```

#### Internal API Changes

```yaml
# No API changes required
# Using existing endpoints:

Endpoint: Get Survey Results by Date Range
  Method: POST
  Path: /api/:typeNum/survey/results/getByDateRange
  Request:
    payload: JSON string containing { startDate, endDate }
  Response:
    success:
      surveys: array of survey objects
      results:
        question1: array[3] counts
        question2: array[5] counts
        question3: array[5] counts
        question6: array[9] counts
        ratingAverage: float

Endpoint: Generate AI Analysis
  Method: POST
  Path: /api/:typeNum/survey/analysis
  Response:
    success:
      overallSummary: string
      step1Analysis: object
      step2Analysis: object
      step3Analysis: object
      step4Analysis: object
      recurringPositiveThemes: array
      recurringNegativeThemes: array
      recommendedActions: array
```

#### Application Data Models

```pseudocode
# Survey Response (existing model, for reference)
ENTITY: SurveyResponse
  FIELDS:
    dateSubmitted: datetime
    customerID: int
    firstName: string
    lastName: string
    buyID: int
    ptStep1: string (greeting response)
    ptStep2: string (process explanation response)
    ptStep3: string (passes explanation response)
    step4: int (satisfaction rating 1-5)
    ptStep6: string (marketing source)
    step6Comments: string (additional source details)
    comments: string
    buyerID: int
    buyerFirstName: string
    buyerLastName: string
    sorterID: int
    sorterFirstName: string
    sorterLastName: string
```

### Implementation Examples

#### Example: Stats Grid Calculation

**Why this example**: Shows how to calculate KPI values from survey data for stat cards

```javascript
// Example: Calculate KPI stats from survey response array
function calculateStats(surveys) {
  const totalResponses = surveys.length;

  // Average satisfaction
  const avgSatisfaction = surveys
    .filter(s => s.step4 && s.step4 !== 'NR')
    .reduce((sum, s) => sum + parseInt(s.step4), 0) / totalResponses;

  // Greeted immediately percentage
  const greetedImmediately = surveys
    .filter(s => s.ptStep1 === 'Yes, immediately').length;
  const greetedPct = (greetedImmediately / totalResponses * 100).toFixed(0);

  // Process explained clearly percentage
  const processExplained = surveys
    .filter(s => s.ptStep2 === 'Yes, clearly').length;
  const processPct = (processExplained / totalResponses * 100).toFixed(0);

  // Top marketing source
  const sourceCounts = {};
  surveys.forEach(s => {
    const source = s.ptStep6 || 'Unknown';
    sourceCounts[source] = (sourceCounts[source] || 0) + 1;
  });
  const topSource = Object.entries(sourceCounts)
    .sort((a, b) => b[1] - a[1])[0];

  return {
    totalResponses,
    avgSatisfaction: avgSatisfaction.toFixed(1),
    greetedPct,
    processPct,
    topSource: topSource ? topSource[0] : 'N/A'
  };
}
```

#### Example: Stat Card Color Logic

**Why this example**: Demonstrates semantic color assignment based on metric thresholds

```javascript
// Example: Determine stat card color variant based on value
function getStatCardVariant(metricType, value) {
  switch (metricType) {
    case 'satisfaction':
      if (value >= 4.0) return 'success';
      if (value >= 3.5) return 'warning';
      return 'danger';

    case 'percentage':
      if (value >= 80) return 'success';
      if (value >= 60) return 'warning';
      return 'danger';

    default:
      return 'primary';
  }
}
```

## Runtime View

### Primary Flow

#### Primary Flow: Page Load and Data Display
1. User navigates to Survey Results page
2. Page renders with empty stat cards showing loading state
3. JavaScript fetches survey data for default date range (last 90 days)
4. System calculates KPIs from response data
5. Stat cards populate with values and appropriate colors
6. Charts render with updated data
7. DataTable populates with survey responses

```mermaid
sequenceDiagram
    actor User
    participant Browser
    participant SurveyPage
    participant SurveyAPI
    participant Database

    User->>Browser: Navigate to Survey Results
    Browser->>SurveyPage: GET /admin/:typeNum/survey/results
    SurveyPage-->>Browser: HTML (empty placeholders)
    Browser->>Browser: Initialize stat cards, charts, table
    Browser->>SurveyAPI: POST /api/:typeNum/survey/results/getByDateRange
    SurveyAPI->>Database: Query surveys
    Database-->>SurveyAPI: Survey data
    SurveyAPI-->>Browser: JSON response
    Browser->>Browser: Calculate KPIs
    Browser->>Browser: Update stat cards
    Browser->>Browser: Render charts
    Browser->>Browser: Populate DataTable
```

#### Secondary Flow: Date Range Change
1. User clicks date range picker
2. User selects new date range
3. System shows loading state on all components
4. System fetches new data
5. All components update with new data

#### Secondary Flow: AI Analysis Generation
1. User clicks "Generate AI Analysis" button
2. Button shows loading state
3. System calls AI analysis API
4. Results tabs display analysis data
5. User can browse analysis tabs

### Error Handling

- **Empty Date Range**: Show "No survey data available for selected date range" message in each section
- **API Network Error**: Show retry button with "Unable to load survey data. Please try again."
- **AI Analysis Timeout**: Show "Analysis is taking longer than expected. Please try again later."
- **Invalid Survey Data**: Skip malformed records, log to console, display partial data

## Deployment View

### Single Application Deployment
- **Environment**: Server-side PHP with client-side JavaScript
- **Configuration**: No new configuration required
- **Dependencies**: Uses existing Chart.js, DataTables, Raty, Moment.js libraries
- **Performance**:
  - Initial page load < 2s
  - API response handling < 500ms
  - Chart rendering < 200ms

No changes to deployment process - CSS/JS changes deploy with standard deploy.sh

## Cross-Cutting Concepts

### Pattern Documentation

```yaml
# Existing patterns used in this feature
- pattern: backstock-home.css stat-card pattern
  relevance: CRITICAL
  why: "Primary UI component pattern for KPIs"

- pattern: backstock-home.css backstock-table-wrapper pattern
  relevance: CRITICAL
  why: "DataTable styling pattern to replicate"

- pattern: backstock-home.css action-toolbar pattern
  relevance: HIGH
  why: "Button and controls styling"
```

### System-Wide Patterns

- **Security**: Uses existing session-based authentication, no changes required
- **Error Handling**: Client-side error handling with user-friendly messages
- **Performance**: Lazy loading of charts after page render
- **Logging**: Console logging for debugging, no server-side logging changes

### Implementation Patterns

#### CSS Architecture Pattern

```css
/* All styles scoped under .survey-results-page to prevent conflicts */
.survey-results-page .component-name {
  /* Component styles */
}

/* Use existing backstock patterns wholesale */
/* Example: Stat card inherits from backstock-home.css */
.survey-results-page .stat-card {
  /* Same as backstock-home.css .backstock-home .stat-card */
}
```

#### Component Structure Pattern

```html
<!-- Page Header Pattern -->
<div class="page-header">
    <div class="row">
        <div class="col-sm-6">
            <h1><i class="fa fa-icon"></i> Page Title</h1>
            <p>Page subtitle description</p>
        </div>
        <div class="col-sm-6 text-right">
            <div class="page-actions">
                <!-- Action buttons -->
            </div>
        </div>
    </div>
</div>

<!-- Stats Grid Pattern -->
<div class="stats-grid">
    <div class="stat-card primary">
        <div class="stat-icon"><i class="fa fa-icon"></i></div>
        <div class="stat-value">123</div>
        <div class="stat-label">LABEL</div>
    </div>
    <!-- More stat cards -->
</div>

<!-- Chart Card Pattern -->
<div class="chart-card">
    <div class="chart-card-header">Chart Title</div>
    <div class="chart-card-body">
        <canvas id="chartId"></canvas>
    </div>
</div>

<!-- Modern Table Pattern -->
<div class="survey-table-wrapper">
    <table id="surveysTable" class="table table-striped">
        <!-- Table content -->
    </table>
</div>
```

### Integration Points

- **Connection Points**:
  - Existing navigation sidebar (unchanged)
  - Existing date range picker library
  - Existing Chart.js configuration
  - Existing DataTables initialization

- **Data Flow**:
  - Survey API → JavaScript → UI Components
  - Date picker → API request → Data refresh

- **Events**:
  - Date range change triggers data reload
  - Stat card click could trigger table filter (optional enhancement)

## Architecture Decisions

- [x] ADR-1 **Create New CSS File**: Create `survey-results.css` instead of modifying existing CSS
  - Rationale: Prevents conflicts, easier rollback, cleaner separation
  - Trade-offs: Additional HTTP request (negligible with caching)
  - User confirmed: Yes

- [x] ADR-2 **Scope All Styles**: Use `.survey-results-page` body class for style scoping
  - Rationale: Prevents accidental style leakage to other pages
  - Trade-offs: Slightly more verbose CSS selectors
  - User confirmed: Yes

- [x] ADR-3 **Inline JavaScript**: Keep JavaScript inline in template rather than separate file
  - Rationale: Matches existing pattern, easier to maintain in single file
  - Trade-offs: Template file is longer, but matches codebase convention
  - User confirmed: Yes

- [x] ADR-4 **Reuse Chart.js**: Keep existing Chart.js library, update styling only
  - Rationale: Proven to work, no learning curve, minimal changes
  - Trade-offs: Limited customization compared to newer libraries
  - User confirmed: Yes

## Quality Requirements

- **Performance**:
  - Page must load and display stat cards within 2 seconds on 3G connection
  - Charts must render within 500ms after data loads
  - Table must handle 1000+ rows without lag

- **Usability**:
  - All content readable on 320px width screen
  - Touch targets minimum 44px
  - Color contrast meets WCAG AA standards

- **Security**:
  - No new security requirements (uses existing auth)
  - XSS prevention via Twig autoescape

- **Reliability**:
  - Graceful degradation if JavaScript fails
  - Show meaningful error states for API failures

## Risks and Technical Debt

### Known Technical Issues

- Chart.js 2.x is outdated (version 2.1.3) - may have rendering quirks
- DataTables styling may conflict with new CSS patterns
- Date range picker styling may need overrides

### Technical Debt

- Existing inline JavaScript is lengthy and could benefit from modularization (not in scope)
- Survey API returns denormalized data which limits flexibility (not in scope)

### Implementation Gotchas

- **Raty Library**: Star ratings use Raty jQuery plugin - must preserve initialization timing
- **Handlebars Templates**: Template escaping uses `{% raw %}` blocks in Twig - be careful with template syntax
- **DataTables Callbacks**: `drawCallback` is used for star rating initialization - must preserve
- **Moment.js Deprecation**: Code uses deprecated moment methods - don't refactor these

## Test Specifications

### Critical Test Scenarios

**Scenario 1: Page Loads with Stats**
```gherkin
Given: User is logged in and has survey permission
And: Store has survey data in last 90 days
When: User navigates to Survey Results page
Then: Page header displays with "Post-Buy Survey Results"
And: 4-6 stat cards show with values
And: Charts render with data
And: DataTable populates with survey rows
```

**Scenario 2: Empty State**
```gherkin
Given: User navigates to Survey Results
And: Selected date range has no survey data
When: Page loads
Then: Stat cards show "N/A" or "0"
And: Charts show empty state message
And: DataTable shows "No data available"
```

**Scenario 3: Mobile Responsive**
```gherkin
Given: User views page on 375px width screen
When: Page renders
Then: Stat cards stack in 2-column grid
And: Charts resize to fit screen
And: Table is horizontally scrollable
And: All touch targets are minimum 44px
```

**Scenario 4: Date Range Change**
```gherkin
Given: Page is loaded with default date range
When: User selects "Last 30 Days" from date picker
Then: All stat cards show loading state
And: API is called with new date range
And: All components update with new data
```

### Test Coverage Requirements

- **Visual Testing**: Compare screenshots at desktop (1440px), tablet (768px), mobile (375px)
- **Functional Testing**: Verify all date range presets work
- **Interaction Testing**: Verify table sorting, pagination, search
- **Error Testing**: Verify error states display correctly
- **Accessibility Testing**: Verify keyboard navigation, screen reader compatibility

---

## Glossary

### Domain Terms

| Term | Definition | Context |
|------|------------|---------|
| Survey Response | Customer feedback collected after a buy transaction | Primary data displayed on this page |
| Post-Buy Survey | Survey sent to customers after completing a sale | The type of survey this page analyzes |
| Buy Transaction | A purchase made by a customer selling items | Referenced via buyID in survey data |
| Satisfaction Rating | 1-5 star rating given by customer | Displayed as stars, averaged for KPI |
| Marketing Source | How customer heard about the store | Analyzed in "Where did you hear about us?" chart |

### Technical Terms

| Term | Definition | Context |
|------|------------|---------|
| Stat Card | Visual component showing a single KPI metric | Used in stats grid at top of page |
| DataTables | jQuery plugin for enhanced HTML tables | Powers the survey results table |
| Chart.js | JavaScript charting library | Renders bar charts for survey questions |
| Raty | jQuery star rating plugin | Displays star ratings in table |
| typeNum | Store identifier pattern (e.g., pc00, ou00) | URL parameter for multi-store routing |

### API Terms

| Term | Definition | Context |
|------|------------|---------|
| getByDateRange | API endpoint for filtered survey data | Primary data fetch endpoint |
| ptStep1/2/3 | Prettified text responses for survey questions | Human-readable survey answers |
| step4 | Numeric satisfaction rating (1-5) | Star rating value |
| ptStep6 | Marketing source category | "Where did you hear about us?" answer |
