Skip to content

Add data export/import/clear to prevent localStorage data loss#1

Open
Copilot wants to merge 4 commits intomainfrom
copilot/add-data-management-section
Open

Add data export/import/clear to prevent localStorage data loss#1
Copilot wants to merge 4 commits intomainfrom
copilot/add-data-management-section

Conversation

Copy link
Copy Markdown

Copilot AI commented Feb 16, 2026

All Apollo training data lives in localStorage with no backup mechanism. Users lose months of progress if localStorage clears (browser reset, device switch, bugs).

Changes

Service Layer (src/services/dataManager.ts)

New data management service with:

  • exportAllData() - Collects all apollo_* prefixed keys + credential keys (strava_*, garmin_*)
  • importAllData() - Validates backup structure before restore
  • clearAllData() - Removes all Apollo localStorage entries
  • downloadJson() - Browser download via Blob + object URL
  • generateBackupFilename() - Timestamped filenames (apollo-backup-YYYY-MM-DD-HHMMSS.json) prevent collisions

Backup format includes metadata wrapper:

{
  "metadata": {
    "exportDate": "2026-02-16T09:36:32.169Z",
    "appName": "Apollo Running",
    "version": "1.0",
    "keyCount": 4
  },
  "data": {
    "apollo_race_prediction": "{...}",
    "apollo_coaching_prefs": "{...}",
    "strava_tokens": "{...}"
  }
}

Settings UI (src/pages/Settings.tsx)

Added Data Management section with orange accent border:

  • Export - Downloads complete backup, shows item count in success message
  • Import - Hidden file input, validates backup, shows confirmation dialog with backup details before restore
  • Clear - Double confirmation with explicit warnings, destructive styling

All operations reload the page after completion to ensure fresh app state.

Screenshots

Data Management Section

Data Management section

Success Message

Export success message

Captured Data

Exports all training-related localStorage:

  • Training plans, progress, race predictions, adherence
  • Heart rate profiles and history
  • Strava/Garmin credentials and tokens
  • Coaching preferences, readiness scores, analytics
  • Activity data, sync metadata
Original prompt

Problem

All user data in Apollo Running is stored exclusively in localStorage. There is currently no way for users to export, back up, or restore their training data. If localStorage is cleared — by the browser, a bug, or the user switching devices — weeks or months of training progress, race predictions, coaching history, HR data, and plan modifications are permanently lost.

This is the highest-impact, lowest-effort improvement identified in a codebase review.

Requirements

Add a Data Management section to the Settings page (src/pages/Settings.tsx) with the following capabilities:

1. Export Data

  • Add an "Export All Data" button that collects all Apollo-related localStorage keys and downloads them as a single JSON file.
  • The exported file should be named something like apollo-backup-YYYY-MM-DD.json with the current date.
  • The export should include ALL Apollo-related localStorage keys. These are the known key prefixes/names used across the app:
    • strava_tokens, strava_credentials — from src/services/storage.ts
    • garmin_tokens, garmin_credentials — from src/services/storage.ts
    • apollo_race_prediction, apollo_adherence — from src/services/racePrediction.ts
    • apollo_active_plan, apollo_welcome_done, apollo_plan_progress_*, apollo_sync_meta_*, apollo_last_sync — from src/services/planProgress.ts
    • apollo_hr_profile, apollo_hr_history — from src/services/heartRate.ts
    • apollo_coaching_prefs — from src/services/coachingPreferences.ts
    • apollo_adaptive_prefs, apollo_adaptive_recs, apollo_adaptive_mods, apollo_adaptive_analytics, apollo_adaptive_last_analysis — from src/services/adaptiveTraining.ts
    • apollo_readiness_* — from src/services/weeklyReadiness.ts
    • apollo_daily_recap_* — from src/services/dailyRecap.ts
    • apollo_custom_plan — from src/data/plans.ts
    • apollo_analytics_activities — from src/services/analyticsService.ts
    • Any other apollo_* prefixed keys that may exist
  • The best approach is to iterate over all localStorage keys and include any that start with apollo_ or match the known credential keys (strava_tokens, strava_credentials, garmin_tokens, garmin_credentials).
  • The export should also include a metadata wrapper with the export date, app version or identifier, and the number of keys exported.

2. Import / Restore Data

  • Add an "Import Data" button that accepts a .json file (via a hidden file input).
  • On import, validate the file structure (check for the metadata wrapper and that keys are present).
  • Show a confirmation dialog/prompt before overwriting existing data, warning the user that this will replace their current data.
  • After a successful import, reload the page so the app picks up the restored data.
  • Handle errors gracefully — show a user-friendly error message if the file is invalid, corrupt, or not an Apollo backup.

3. Clear All Data

  • Add a "Clear All Data" button with a danger/destructive styling.
  • Require a confirmation before clearing (e.g., a window.confirm() dialog).
  • On confirmation, remove all Apollo-related localStorage keys and reload the page.

4. UI Design

  • Add these controls in a new card section in Settings, styled consistently with the existing cards (use the same className="card" pattern and existing design system variables).
  • Use a left border accent color to distinguish the section (similar to how Strava uses var(--strava) and coaching uses var(--apollo-teal)).
  • Include helpful descriptive text explaining what each action does.
  • The "Clear All Data" button should use destructive/error styling to indicate it's a dangerous action.

5. Service Layer

  • Create a new service file src/services/dataManager.ts (or similar) that contains the pure logic for:
    • exportAllData(): object — gathers all relevant localStorage data
    • importAllData(data: object): boolean — validates and restores data
    • clearAllData(): void — removes all Apollo-related localStorage keys
    • downloadJson(data: object, filename: string): void — triggers a browser download
  • This keeps the Settings component clean and the logic reusable/testable.

Technical Notes

  • The app uses localStorage heavily across many service files. Look at the key constants defined in each service to know what to include.
  • The download can be implemented by creating a Blob, generating an object URL, and programmatically clicking a temporary <a> element.
  • The file input for import can be a hidden <input type="file" accept=".json"> triggered by a button click.
  • After import or clear, call window.location.reload() to ensure the entire app re-reads from localStorage.

This pull request was created from Copilot chat.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.


Continue Tasks: ✅ 3 no changes — View all

Copilot AI and others added 3 commits February 16, 2026 09:30
Co-authored-by: LetsLearntocodeforfun <216424165+LetsLearntocodeforfun@users.noreply.github.com>
Co-authored-by: LetsLearntocodeforfun <216424165+LetsLearntocodeforfun@users.noreply.github.com>
Co-authored-by: LetsLearntocodeforfun <216424165+LetsLearntocodeforfun@users.noreply.github.com>
Copilot AI changed the title [WIP] Add data management section to settings page Add data export/import/clear to prevent localStorage data loss Feb 16, 2026
Copy link
Copy Markdown
Owner

@LetsLearntocodeforfun LetsLearntocodeforfun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

woking on a data export feature to save data locally across devices.

@LetsLearntocodeforfun LetsLearntocodeforfun marked this pull request as ready for review February 16, 2026 09:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants