> ## Documentation Index
> Fetch the complete documentation index at: https://docs.appliedaifoundation.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Data upload

> Drag-drop Excel consumption logs with preview, validation, and duplicate detection.

The Upload page is how data gets into the system. Drag an Excel file in; the platform parses it, shows you a preview, flags duplicates, and inserts only what's new.

<Frame caption="Upload page — empty state.">
  <img src="https://mintcdn.com/metaweaveconsultant/ZChQsW2FZuO2wFx2/images/upload/empty.png?fit=max&auto=format&n=ZChQsW2FZuO2wFx2&q=85&s=f1933a281c3e802f8c681c0450a84d8a" alt="Upload empty state" width="2880" height="1800" data-path="images/upload/empty.png" />
</Frame>

## How it works

<Steps>
  <Step title="Pick a vessel">
    <Frame caption="Two modes — pick an existing vessel or onboard a new one.">
      <img src="https://mintcdn.com/metaweaveconsultant/ZChQsW2FZuO2wFx2/images/upload/vessel-mode.png?fit=max&auto=format&n=ZChQsW2FZuO2wFx2&q=85&s=f4824fc4d1d9db33090f9c6a424226ec" alt="Vessel selector with two modes" width="2880" height="1800" data-path="images/upload/vessel-mode.png" />
    </Frame>

    Two modes:

    * **Existing vessel** — pick from the fleet dropdown. The dropdown shows vessel type and DWT for confirmation.
    * **New vessel** — enter IMO (7 digits), name, DWT. The vessel is registered before the upload runs.

    See [Vessel onboarding](/data/vessel-onboarding) for the full new-vessel flow.
  </Step>

  <Step title="Drop the file">
    <Frame caption="Drag-drop zone — accepts .xlsx and .xls up to 50 MB.">
      <img src="https://mintcdn.com/metaweaveconsultant/ZChQsW2FZuO2wFx2/images/upload/dropzone.png?fit=max&auto=format&n=ZChQsW2FZuO2wFx2&q=85&s=064ad315ae5060105219a54dc3e6d831" alt="File drop zone" width="2880" height="1800" data-path="images/upload/dropzone.png" />
    </Frame>

    Either drag an `.xlsx` or `.xls` file onto the dashed zone or click to open a file picker. The platform reads the filename and size; nothing is uploaded yet.
  </Step>

  <Step title="Parse & preview">
    <Frame caption="Preview shows column count, total rows, date range, valid rows.">
      <img src="https://mintcdn.com/metaweaveconsultant/ZChQsW2FZuO2wFx2/images/upload/preview.png?fit=max&auto=format&n=ZChQsW2FZuO2wFx2&q=85&s=6d9dfd67f705d66fcfe177deda37af5b" alt="Upload preview" width="2880" height="1800" data-path="images/upload/preview.png" />
    </Frame>

    Click **Parse File**. The platform sends the file to `/api/upload/consumption?action=preview` and shows you:

    * Column count and total rows
    * Date range covered (start → end)
    * Valid rows ready to insert
    * **Duplicate detection** — rows that already exist (by IMO + timestamp) and will be skipped
    * The first 10 rows of data, so you can sanity-check column mapping

    See [Excel upload format](/data/excel-upload-format) for the expected columns.
  </Step>

  <Step title="Confirm">
    Once the preview looks right, click **Upload N Rows**. The platform inserts the new rows into Postgres, leaving duplicates alone.
  </Step>

  <Step title="Result">
    <Frame caption="Success banner with insert/skip counts and a debug panel.">
      <img src="https://mintcdn.com/metaweaveconsultant/ZChQsW2FZuO2wFx2/images/upload/success.png?fit=max&auto=format&n=ZChQsW2FZuO2wFx2&q=85&s=7db0855dea138ddc63349baa43e51c08" alt="Upload success state" width="2880" height="1800" data-path="images/upload/success.png" />
    </Frame>

    A green banner reports rows inserted vs. duplicates skipped. A collapsible debug panel exposes deeper info — total rows processed, valid timestamps, invalid timestamps, etc. — useful when something looks off.

    Click **Upload Another File** to reset and continue.
  </Step>
</Steps>

## Validation rules

The parser enforces:

* File must be `.xlsx` or `.xls` and under 50 MB
* A `timestampUtc` column is required (no row without a valid timestamp is inserted)
* Timestamps are parsed as **UTC** — Excel local-time serials are converted
* Duplicate detection key: `imo` + `timestampUtc`

If anything fails, the preview surfaces the exact reason — bad date format, missing column, etc.

## Source

UI in `src/app/upload/`. Server-side parsing in `src/lib/utils/excelParser.ts`. API route at `src/app/api/upload/consumption/route.ts`.
