import { useState, useCallback } from 'react' import { useDropzone } from 'react-dropzone' import { useMutation } from '@tanstack/react-query' import api from '../utils/api' function UploadZone({ title, description, accept, endpoint, icon }) { const [tasks, setTasks] = useState([]) const upload = useMutation({ mutationFn: async (file) => { const form = new FormData() form.append('file', file) const { data } = await api.post(endpoint, form, { headers: { 'Content-Type': 'multipart/form-data' }, }) return { file: file.name, ...data } }, onSuccess: (data) => { setTasks(t => [...t, { ...data, status: 'queued' }]) }, }) const onDrop = useCallback((accepted) => { accepted.forEach(file => upload.mutate(file)) }, [upload]) const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop, accept, multiple: true, }) return (
{icon}

{title}

{description}

{isDragActive ? (

Drop files here…

) : (

Drag & drop files here, or click to browse

{Object.values(accept).flat().join(', ')}

)}
{upload.isPending && (

Uploading…

)} {tasks.length > 0 && (
{tasks.map((task, i) => (
{task.file} {task.activity_tasks !== undefined && ( {task.activity_tasks} activities queued )} βœ“ Queued
))}
)}
) } export default function UploadPage() { return (

Import Data

Import activities from Garmin or Strava. Large exports are processed in the background.

{/* How to export guides */}

πŸ“₯ How to export from Garmin Connect

  1. Go to Garmin Connect β†’ Profile β†’ Account
  2. Scroll to Data Management β†’ Export Your Data
  3. Request export and wait for the email
  4. Download and upload the ZIP file below

πŸ“₯ How to export from Strava

  1. Go to strava.com β†’ Settings β†’ My Account
  2. Scroll to Download or Delete Your Account
  3. Click "Request Your Archive"
  4. Download and upload the ZIP file below
{/* Single FIT/GPX */} {/* Garmin full export */} {/* Strava export */} {/* Ongoing FIT files */}
πŸ”„

Ongoing sync

Automatically import new Garmin watch files

After each activity, sync your Garmin watch via USB or Garmin Express. New FIT files appear in:

GARMIN/Activity/*.fit

Upload individual FIT files above using the "Single activity" uploader, or set up a folder-watch script:

{`# Example: auto-upload new FIT files inotifywait -m ~/Garmin/Activity/ -e create \\ --format '%f' | while read file; do curl -X POST /api/upload/activity \\ -H "Authorization: Bearer TOKEN" \\ -F "file=@$file" done`}
) }