Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/raceliciouss/YUSEN-LIMO-WAREHOUSE/llms.txt

Use this file to discover all available pages before exploring further.

The YUSEN LIMO scanner accepts two payload formats encoded in a QR code. The first is a JSON object containing one or more shipment fields, which triggers normalizeShipmentPayload() and auto-fills the active form. The second is a plain text string (any non-JSON value), which is treated as a HAWB or MAWB identifier and used as a search/filter term on the Inventory or Activity page. The app selects between the two formats by attempting JSON.parse() on the decoded text — if parsing throws, the value is handled as plain text.

JSON Payload Format

When the decoded QR text is valid JSON, handleScannedPayload() passes the parsed object to normalizeShipmentPayload(). This function accepts a wide range of alias keys for each logical field, making it tolerant of QR codes generated by different source systems or label-printing tools.

Supported Field Aliases

Canonical FieldAccepted Property Names
hawbhawb, HAWB, hawbNumber, shipmentId
mawbmawb, MAWB, mawbNumber
clientclient, Client, shipmentClient
invoiceinvoice, invoiceNumber, markings, marking
transactionTypetransactionType, transactionTypeName, transaction_type, transactionTypeLabel, transaction, type
plateNoplateNo, plate, plateNumber, vehiclePlate, vehiclePlateNo
datedate
timetime
Any property name not in the table above is silently ignored by normalizeShipmentPayload(). Unknown keys will not cause an error, but their values will not be written to the form.

Full JSON Example

{
  "hawb": "HAWB-20240601-001",
  "mawb": "MAWB-YL-2024-888",
  "client": "Acme Corporation",
  "invoice": "INV-2024-005",
  "transactionType": "Import",
  "plateNo": "ABC-1234",
  "date": "2024-06-01",
  "time": "09:30"
}

How normalizeShipmentPayload() Works

normalizeShipmentPayload(payload) accepts any object and returns a new object with a fixed set of canonical keys. Every key in the return value is always present — fields that have no matching alias in the source payload are returned as empty strings rather than undefined. This guarantees that populateShipmentForm() can iterate data-field elements without needing to guard against missing keys.
// Simplified internal logic — see assets/app.js for full source
const normalizeShipmentPayload = (payload) => {
  const source = payload && typeof payload === 'object' ? payload : {}
  return {
    client:          source.client          || source.Client          || source.shipmentClient      || '',
    hawb:            source.hawb            || source.HAWB            || source.hawbNumber          || source.shipmentId || '',
    mawb:            source.mawb            || source.MAWB            || source.mawbNumber          || '',
    invoice:         source.invoice         || source.invoiceNumber   || source.markings            || source.marking    || '',
    transactionType: source.transactionType || source.transactionTypeName || source.transaction_type || source.transactionTypeLabel || source.transaction || source.type || '',
    plateNo:         source.plateNo         || source.plate           || source.plateNumber         || source.vehiclePlate || source.vehiclePlateNo || '',
    date:            source.date            || '',
    time:            source.time            || ''
  }
}

How populateShipmentForm() Works

After normalization, populateShipmentForm(payload, context) resolves the active form context — either the explicitly provided context argument, the currently visible .tab-content.active element, or the document root as a fallback. It then:
  1. Queries every element with a data-field attribute inside that context.
  2. Looks up fieldValues[fieldName] from the normalized payload for each element.
  3. For <select> elements, delegates to applySelectValue(), which tries an exact match on option text/value first, then a substring match — both comparisons are case-insensitive and strip punctuation.
  4. For all other input types, sets .value directly and dispatches a synthetic input event so reactive UI listeners (e.g., auto-suggest, validation) are triggered.
  5. If a stored shipment in Local Storage has a HAWB or MAWB matching the scanned value, populateShipmentForm() additionally back-fills the location (text input) and unit (select) fields from that stored record — useful for outbound forms where the location was recorded at inbound time.

Date and Time Fallback

If the scanned payload omits date or time, populateShipmentForm() calls getPhilippineDateTime() and fills those fields with the current date and time in the Philippine Standard Time (UTC+8) timezone. This means forms are never submitted with blank date/time fields even when the QR code only carries identifiers.

Plain-Text Payload Format

If JSON.parse(text) throws — meaning the QR code contains a raw string rather than a JSON object — handleScannedPayload() routes the raw text to applyScannedPayloadToPage(). This function checks for the presence of #inventorySearchInput or #activitySearchInput in the current page:
  • If found, it sets the search input value to the decoded string and calls refreshInventory() or refreshActivity() to immediately re-filter the displayed rows.
  • If neither search input exists on the current page (for example, if the operator scans while on the Inbound/Outbound page), applyScannedPayloadToPage() returns false and the app shows an "Invalid QR Code" alert.
Plain-text payloads are best suited for barcodes or QR codes on shipping labels that contain only a HAWB or MAWB number, with no JSON wrapping. For example, a QR code containing the bare string:
HAWB-20240601-001
will populate #inventorySearchInput with HAWB-20240601-001 and trigger a live filter, without any JSON parsing at all.

Generating QR Codes

Any standard QR code generator (browser-based, command-line, or embedded in a label printer) can encode the JSON payload as a UTF-8 string. There are no proprietary extensions or checksums beyond the QR standard itself. For maximum scanner reliability, encode only the shipment identifier (HAWB or MAWB) and let the application look up the remaining fields from Local Storage or, in a future backend integration, from the database:
{ "hawb": "HAWB-20240601-001" }
When populateShipmentForm() receives a single-field payload like this, it will write the HAWB into the form, auto-fill date and time from the current Philippine time, and — if a matching inbound record is found in Local Storage — also restore location and unit from that stored shipment.
Embedding a full shipment payload (all fields, long client names, invoice numbers, etc.) in a single QR code increases the data density required and forces the encoder to use a smaller module size (the individual black/white squares). Smaller modules are harder for cameras to resolve, especially at a distance or under poor lighting. Payloads above roughly 300 characters may require QR version 10 or higher, which significantly reduces scan reliability on lower-resolution device cameras. Keep encoded payloads as short as possible.
The recommended long-term approach is to store only the HAWB or MAWB identifier in the QR code and fetch all other shipment details from a server-side database at scan time. This keeps every QR code small, allows shipment data to be updated without reprinting labels, and removes the risk of stale data being auto-filled from an outdated code. See Migration Path for a discussion of moving from Local Storage to a backend API.

Build docs developers (and LLMs) love