# Workflow System

## Overview

Each workflow type (e.g. `foto-first-bulk-import`, `import-items`) is
implemented by **one** Vue file that contains **all of its steps** and
**its own metadata** (name, category, description, icons, duration, step
list, initial payload). There is no separate per-step component registry and
no parallel class hierarchy for metadata - a single flat catalog in
`@/workflows.js` ties everything together.

## Architecture

### 1. Workflow components (`/components/workflow/workflows/*.vue`)

Each file is fully self-contained:

- **Metadata**: a static `meta: { id, name, category, description, icons,
  estimatedDuration, stepDefinitions, getInitialPayload() }` option on the
  component's options object, right alongside `name`/`components`/`props`.
- **UI**: the same component implements every step internally, branching on
  the `step` prop (e.g. `v-if="step === '1'"`, `v-else-if="step === '2'"`, ...).

Currently implemented:
- **FotoFirstBulkImportWorkflow.vue** - all 4 steps of `foto-first-bulk-import`:
  photo capture (camera + upload), image processing/compression, per-item
  detail entry, and import completion.
- **BulkItemImportWorkflow.vue** - `import-items`' file upload (step 1) and
  item creation (step 6) with full UI; steps 2-5 and 7 render a generic
  placeholder using this same file's own `meta.stepDefinitions` (accessed via
  `this.$options.meta` inside the component) until their UI is built out.

### 2. The catalog (`@/workflows.js`)

A single flat array assembled from:
- `implementedWorkflows` - workflows with a real component, built by
  importing the component and reading its static `.meta` property:
  `{ ...Component.meta, component: Component }`
- `plannedWorkflows` - workflows that exist conceptually (so they show up in
  the catalog, can be started/tracked, and get a progress sidebar) but don't
  have a dedicated UI yet; these are plain metadata objects with
  `component: null`, defined directly in `workflows.js` since there's no
  component file to attach `meta` to

Exposed functions:
- `getAllWorkflows()` - the full catalog, used by the `Workflows.vue` list
- `getWorkflow(id)` - a single workflow definition by id
- `getWorkflowComponent(id)` - the Vue component for a workflow, or `null`
- `getWorkflowsByCategory(category)` / `getWorkflowCategories()`
- `buildWorkflowApiPayload(workflow)` - builds the request body used to start
  a new `WorkflowInstance`, merging the common `workflow_config` block with
  the workflow's own `getInitialPayload()`
- `serializeWorkflowPayload(workflow)` / `deserializeWorkflowPayload(workflow)`
  - JSON (de)serialization of `WorkflowInstance.payload`, also used by `store.js`

### 3. Usage in the views

`WorkflowDetail.vue`:
```javascript
import { getWorkflow, getWorkflowComponent } from '@/workflows.js';

workflowDefinition() {
    // `name` on the WorkflowInstance doubles as the workflow type identifier
    return getWorkflow(this.workflowInstance?.name);
},
workflowComponent() {
    return getWorkflowComponent(this.workflowInstance?.name);
}
```

The resolved component is rendered once via `<component :is="workflowComponent">`
and receives the `step` prop on every step change - there's no need to swap
components as the user navigates between steps of the same workflow.

`Workflows.vue` uses `getAllWorkflows()` for the catalog grid and
`buildWorkflowApiPayload(workflow)` when starting a new instance.

### 4. Component contract

Every workflow component receives props `workflowInstance`, `step`, `payload`
and emits `update`, `next`, `prev`, `complete`. `WorkflowDetail.vue` handles
persisting payload updates (`handleStepUpdate`) and step navigation
(`handleNextStep` / `handlePrevStep` / `completeWorkflow`), independent of
which workflow is active.

### 5. Workflow progress sidebar

Step metadata (name/description, total step count) comes from
`workflowDefinition.stepDefinitions` (the catalog entry, i.e. `Component.meta.stepDefinitions`),
used to render the progress sidebar and step list regardless of whether a
custom UI exists yet. `isStepCurrent(stepNumber)` / `isStepCompleted(stepNumber)` /
`getStepClass(stepNumber)` in `WorkflowDetail.vue` drive the sidebar styling.

## Extensibility

### Adding UI for a planned workflow
1. Create `/components/workflow/workflows/MyWorkflow.vue`:
   - Add a `meta: {...}` option to the exported component (copy the matching
     entry out of `plannedWorkflows` in `workflows.js` and delete it there)
   - Implement every step internally (`v-if="step === '1'"`, etc.)
2. In `workflows.js`, import the component and add
   `{ ...MyWorkflow.meta, component: MyWorkflow }` to `implementedWorkflows`

### Adding a brand new workflow type
1. Create the `.vue` file as above with a unique `id`
2. Add it to `implementedWorkflows` in `workflows.js` (if it has UI) or add a
   plain metadata object to `plannedWorkflows` (if it doesn't, yet)

### Adding steps to an existing workflow
1. Add another `v-else-if="step === 'N'"` branch to the workflow's `.vue` file
2. Add the step to that same file's `meta.stepDefinitions`
3. Add any step-specific data/methods to the same file - no other file needs
   to change

## Benefits

1. **Single source of truth**: metadata and UI for a workflow live in one file
2. **No indirection**: one array, no separate component registry to keep in sync
3. **Cohesion**: all state and logic for a workflow's steps lives together
4. **Extensibility**: new workflows are a single new file + one array entry
5. **Consistency**: standardized props (`workflowInstance`, `step`, `payload`)
   and events (`update`, `next`, `prev`, `complete`) across all workflow components

