# shiftops-frontend-qa Full Instructions

## QA Checklist (ShiftOps-Specific)

### Essential Mode Flow

- [ ] Google Places autocomplete works correctly
- [ ] Search submits to `/v2/api/shiftops.php` with `mode='essential'`
- [ ] Essential data stored in `shiftops_report_data` localStorage key
- [ ] Redirect to `/shiftops-report` works
- [ ] Loading screen displays with preliminary score
- [ ] Rotating messages display correctly
- [ ] Background fetch enhanced data works

### Enhanced Mode Flow

- [ ] Enhanced data fetched after essential mode redirect
- [ ] Enhanced data stored in `shiftops_enhanced_data` localStorage key
- [ ] UI updates with enhanced data when available
- [ ] Enhanced score displays correctly
- [ ] Competitive positioning displays correctly
- [ ] Detailed recommendations display correctly

### Gated Content

- [ ] Email form overlay appears when content locked
- [ ] Values blurred until email submitted
- [ ] Email validation works (client-side and server-side)
- [ ] Unlock API call works (`action='unlock'`)
- [ ] Unlock status stored in localStorage
- [ ] Overlay removed after unlock
- [ ] Full report content visible after unlock

### localStorage Management

- [ ] All keys set correctly
- [ ] Data persists across page reloads
- [ ] Old keys migrated correctly (if applicable)
- [ ] Keys cleared when starting new search

### Team Size Display

- [ ] Team size consistent throughout report
- [ ] Team size matches HubSpot submission
- [ ] Team size used correctly in cost calculations
- [ ] Fallback value (10) used when no data available

### NPS Survey

- [ ] Survey displays after unlock
- [ ] Survey doesn't display if already submitted/dismissed
- [ ] NPS score submission works
- [ ] Feedback text submission works
- [ ] localStorage keys set correctly
- [ ] Survey doesn't reappear after dismissal

### PDF Export

- [ ] PDF download button works
- [ ] PDF includes full report content
- [ ] PDF includes Ordio branding
- [ ] PDF file size reasonable (< 5MB)

### Responsive Design

- [ ] Mobile layout works correctly
- [ ] Desktop layout works correctly
- [ ] Touch targets minimum 44px
- [ ] Font sizes readable on all devices
- [ ] Overlays work correctly on mobile

### Error Handling

- [ ] API errors handled gracefully
- [ ] User-friendly error messages displayed
- [ ] No console errors
- [ ] Fallback states work correctly

---

## Common ShiftOps Frontend Pitfalls

### localStorage Data Loss

❌ **BAD:** Not checking if localStorage data exists before using

```javascript
const data = JSON.parse(localStorage.getItem("shiftops_report_data"));
const score = data.total_score; // Error if data is null
```

✅ **GOOD:** Always check and provide fallback

```javascript
const data = JSON.parse(localStorage.getItem("shiftops_report_data") || "{}");
const score = data.total_score || 0;
```

### Race Conditions

❌ **BAD:** Not waiting for enhanced data before updating UI

```javascript
fetchEnhancedData();
updateUI(); // May run before fetch completes
```

✅ **GOOD:** Use async/await or promises

```javascript
const enhancedData = await fetchEnhancedData();
updateUI(enhancedData);
```

### Missing Error Handling

❌ **BAD:** No error handling for API calls

```javascript
fetch("/v2/api/shiftops.php", { method: "POST", body: data })
  .then((response) => response.json())
  .then((data) => updateUI(data));
```

✅ **GOOD:** Handle errors gracefully

```javascript
fetch("/v2/api/shiftops.php", { method: "POST", body: data })
  .then((response) => {
    if (!response.ok) throw new Error("API error");
    return response.json();
  })
  .then((data) => updateUI(data))
  .catch((error) => {
    console.error("ShiftOps API error:", error);
    showError("Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.");
  });
```

### Inconsistent Team Size

❌ **BAD:** Different team size values in different parts of report

```javascript
const teamSize1 = reportData.team_size;
const teamSize2 = userInput.team_size;
// May be different!
```

✅ **GOOD:** Use single source of truth

```javascript
const teamSize = getUserTeamSize(reportData, userInput); // Priority order
// Use same value everywhere
```

### Missing localStorage Cleanup

❌ **BAD:** Never clearing old keys

```javascript
// Old keys accumulate over time
```

✅ **GOOD:** Clear keys when starting new search

```javascript
function startNewSearch() {
  Object.keys(localStorage).forEach((key) => {
    if (key.startsWith("shiftops_")) {
      localStorage.removeItem(key);
    }
  });
}
```

---

## Performance Optimization Patterns

### Lazy Loading

**Load enhanced data in background:**

```javascript
// Don't block UI while fetching enhanced data
setTimeout(() => {
  fetchEnhancedData().then((data) => {
    updateUIWithEnhancedData(data);
  });
}, 100);
```

### Debouncing

**Debounce search input:**

```javascript
let searchTimeout;
function handleSearchInput(value) {
  clearTimeout(searchTimeout);
  searchTimeout = setTimeout(() => {
    performSearch(value);
  }, 300);
}
```

### Caching

**Cache API responses:**

```javascript
const cacheKey = `shiftops_${placeId}`;
const cached = sessionStorage.getItem(cacheKey);
if (cached) {
  return JSON.parse(cached);
}
// Fetch and cache
const data = await fetchData();
sessionStorage.setItem(cacheKey, JSON.stringify(data));
```

### Image Optimization

**Lazy load images:**

```html
<img src="placeholder.jpg" data-src="actual-image.jpg" loading="lazy" />
```

**Use WebP format:**

```html
<picture>
  <source srcset="image.webp" type="image/webp" />
  <img src="image.jpg" alt="Description" />
</picture>
```

---

## Mention Verification Steps in Task Handoff

When completing ShiftOps frontend tasks, always mention:

1. **localStorage verification:** Check that all keys are set correctly
2. **API integration:** Verify API calls work correctly
3. **Error handling:** Test error scenarios
4. **Responsive design:** Test on mobile and desktop
5. **Performance:** Check page load times and API response times

---

## Scoring Display Requirements

### Score Format

- **Total Score:** Display as integer (0-100) with "/100" suffix
- **Pillar Scores:** Display as integers (0-20) with "/20" suffix
- **Grade:** Display letter grade (A+, A, A-, B+, B, B-, C+, C, C-, D+, D, D-, F)

### Score Metadata Display

- Display data completeness percentage
- Show calculation method (full, partial, fallback)
- Indicate if customer boost was applied
- Display estimation confidence level

### Score Validation

- Verify scores are within valid ranges (0-100 total, 0-20 per pillar)
- Verify pillar scores sum to total score
- Verify grade matches total score range
- Handle missing score data gracefully (show fallback or loading state)

**For complete scoring documentation, see `docs/systems/shiftops/SHIFTOPS_SCORING_SYSTEM.md`**

---

## Tracking Implementation

### Tracking Pixels

ShiftOps pages include the following tracking pixels (located before closing `</body>` tag):

1. **Google Tag Manager (GTM)**

   - ID: `GTM-5DWSFND`
   - Initialized in head section
   - DataLayer events pushed throughout user journey

2. **Facebook Pixel**

   - ID: `446906457117125`
   - Duplicate prevention via `window.fbqInitialized` check
   - Events: PageView, ViewContent, Search, InitiateCheckout, CompleteRegistration, Lead, Rate

3. **LinkedIn Insight Tag**

   - Conversion ID: `6554434`
   - Async loading with error handling
   - Tracks conversions automatically

4. **TikTok Pixel**

   - SDK ID: `CMF6TN3C77U483AS1HB0`
   - Events: PageView, ViewContent
   - Async loading with error handling

5. **HubSpot Tracking**
   - Script ID: `145133546.js`
   - Already implemented, loads async/defer

### Event Tracking

**shiftops.php Events:**

- `shiftops_search_initiated` - User focuses on search input
- `shiftops_analysis_started` - Analysis begins (business selected)
- `shiftops_analysis_completed` - Analysis finishes
- `shiftops_redirect_to_report` - User redirected to report page

**shiftops-report.php Events:**

- `shiftops_report_viewed` - Report page loads
- `shiftops_report_unlocked` - User unlocks report via form
- `shiftops_form_submitted` - Email unlock form submitted
- `shiftops_pdf_downloaded` - PDF export completed
- `shiftops_nps_shown` - NPS survey displayed
- `shiftops_nps_score_selected` - User selects NPS score
- `shiftops_nps_submitted` - NPS survey submitted

### Tracking Implementation Pattern

All events are tracked via three methods:

1. **Custom trackEvent()** - Database tracking via `/v2/base/tracking.php`
2. **Facebook Pixel** - `fbq('track', eventName, params)` if available
3. **GTM dataLayer** - `window.dataLayer.push({event: 'event_name', ...})` if available

All tracking includes error handling (try-catch blocks) and silent failure patterns to prevent page breakage.

### Code Organization

Tracking scripts are grouped together before closing `</body>` tag with clear section comments:

```html
<!-- ============================================
     TRACKING SCRIPTS
     ============================================
     All tracking pixels and scripts are grouped here
     for easy maintenance and consistent loading order.
     ============================================ -->
```

## Reference Documentation

For detailed ShiftOps workflows:

- `docs/systems/shiftops/SHIFTOPS_ARCHITECTURE.md` – System architecture (updated with current file sizes, detailed data flow)
- `docs/systems/shiftops/SHIFTOPS_API_DOCUMENTATION.md` – API documentation
- `docs/systems/shiftops/SHIFTOPS_DATA_STRUCTURES.md` – Complete data structures reference (NEW)
- `docs/systems/shiftops/SHIFTOPS_COMPONENTS.md` – All classes and methods documentation (NEW)
- `docs/systems/shiftops/SHIFTOPS_QUICK_REFERENCE.md` – Quick reference guide
- `docs/systems/shiftops/SHIFTOPS_TROUBLESHOOTING.md` – Troubleshooting guide
- `docs/systems/shiftops/SHIFTOPS_SCORING_SYSTEM.md` – Complete scoring system documentation (NEW)
## Related Documentation

See [docs/ai/RULE_TO_DOC_MAPPING.md](../../docs/ai/RULE_TO_DOC_MAPPING.md) for complete mapping.

