# Order Persistence - Server-Side Storage

## Overview

Service order (drag-and-drop positioning) is now persisted server-side using SQLite database, with localStorage as a fallback/cache.

## Architecture

```
Browser (drag-drop) → localStorage (immediate)
                    → /api/order (async save to server)
                                   ↓
                            order-service (Flask)
                                   ↓
                            SQLite Database
                            (/data/services-order.db)
```

## Components

### Backend Service: `order-service.py`
- **Port:** 8082 (internal)
- **Database:** SQLite at `/data/services-order.db`
- **Volume:** `order-data` (persistent across container restarts)

### API Endpoints

#### GET `/api/order?user_id=default`
- Retrieves saved service order for a user
- Returns: JSON object mapping group names to ordered service IDs
- Example response:
  ```json
  {
    "Management": ["portainer", "uptime-kuma", "scrutiny"],
    "Media": ["jellyfin", "jellyseer", "transmission"]
  }
  ```

#### POST `/api/order`
- Saves service order for a user
- Request body:
  ```json
  {
    "user_id": "default",
    "order": {
      "Management": ["portainer", "uptime-kuma"],
      ...
    }
  }
  ```
- Response: `{"success": true, "message": "Order saved"}`

#### DELETE `/api/order?user_id=default`
- Resets order to default (deletes saved order)
- Response: `{"success": true, "message": "Order deleted"}`

## Database Schema

```sql
CREATE TABLE service_order (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    user_id TEXT NOT NULL DEFAULT 'default',
    order_data TEXT NOT NULL,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```

## Behavior

### On Page Load
1. JavaScript calls `/api/order?user_id=default`
2. If server has data, use it and cache in localStorage
3. If server returns empty, fall back to localStorage
4. If both empty, use default XML order

### On Drag-Drop
1. Save to localStorage immediately (instant response)
2. Async POST to `/api/order` in background
3. If server save fails, localStorage still works as fallback

### Benefits
- **Cross-device sync:** Order syncs across browsers/devices
- **Persistent:** Survives container restarts, browser clearing
- **Fallback:** localStorage works if server is down
- **Fast:** Instant UI update, async server save

## Data Location

- **Server:** Docker volume `services-homepage_order-data`
  - Inspect: `docker volume inspect services-homepage_order-data`
  - Location: `/var/lib/docker/volumes/services-homepage_order-data/_data/`
- **Client:** Browser localStorage key `services-order`

## Backup/Restore

### Backup Server Data
```bash
# Copy database from volume
docker run --rm -v services-homepage_order-data:/data -v $(pwd):/backup \
  alpine cp /data/services-order.db /backup/order-backup.db
```

### Restore Server Data
```bash
# Copy database to volume
docker run --rm -v services-homepage_order-data:/data -v $(pwd):/backup \
  alpine cp /backup/order-backup.db /data/services-order.db

# Restart service to load new data
docker restart services-homepage-order-service
```

### Reset All Orders
```bash
# Delete all saved orders
curl -X DELETE "http://192.168.2.180:8088/api/order?user_id=default"

# Or restart with fresh database
docker compose down
docker volume rm services-homepage_order-data
docker compose up -d
```

## Future Enhancements

- Multi-user support (authentication)
- Order history/versioning
- Export/import order via UI
- Sync status indicator in UI
- Conflict resolution for concurrent edits
