Introduce LocalShippingOverride type and Deno KV storage. Add patchOrderShipping utility that applies local overrides to fetched BLOrder objects. Create PUT /api/orders/{orderId}/shipping-method endpoint for persisting overrides. Update ShipList island: shipping method is now an editable select backed by cached BL methods. Patch order shipping on retrieval in ship-list, print-labels, pick-list, order detail, drive-thru, and the orders API endpoint. Show a 'local' badge on the order detail page when an override is active. Drive-thru template rules now evaluate against the locally overridden method.
Snapshot the original item values when entering edit mode via originalItem signal. Add hasChanges() helper comparing current form state against the snapshot. Gate both Delete Item and Delete + Next actions through confirmDeleteIfNeeded(). Show a confirmation modal when unsaved changes exist; delete immediately otherwise. Clear the snapshot on cancelEdit to avoid stale state.
When editing a pending item, the Delete Item and Update Item buttons now have join-item 'Next' counterparts that perform the same action and automatically move to the next pending item. This speeds up bulk editing of imported items. Extract buildPendingItem() to share item construction between add and update paths. Add getNextPendingItem(), deleteAndNext(), and updateAndNext() helpers. Wrap action buttons in DaisyUI join groups for a compact unified look. Disable 'Next' buttons when there is no subsequent pending item. Add row refs and a useEffect so the active pending row scrolls into view automatically when navigating with the Next buttons.
Add shared MARKETPLACE_PAGE_SIZE constant in utils/format.ts. Update marketplace API route to use constant and return pageSize in JSON. Update Inventory island to read dynamic pageSize from API for pagination.
No additional details.
Introduce TemplateRule and RuleCondition types. Persist rules and default template ID in Deno KV. Add evaluateTemplateRules engine with eq/ne/gt/gte/lt/lte/contains operators. Create /drive-thru/rules management UI with condition builder and reordering. Pre-select templates on send page based on order/customer criteria. Add Drive Thru Rules to sidebar navigation.
Replaces hardcoded AJAX_HEADERS with bricklinkAjaxHeaders(itemType, itemNo) so the Referer matches the requested catalog page. Adds bricklinkCatalogUrl() to utils/format.ts for reuse across the app. Updates Inventory, OrderItemsTable, PickList, and PartImageDialog to use the shared utility, fixing hardcoded P= prefixes in OrderItemsTable and PickList.
No additional details.
No additional details.
No additional details.
Adds getSenderAddress/saveSenderAddress KV helpers, a new /configuration page with a form to edit the sender address, and a /api/configuration endpoint. The print-labels module now reads from KV instead of SENDER_ADDRESS. Adds a Configuration link to the sidebar under Settings and updates the environment page to reference it.
Also updates Import button styling to match other primary actions.
Resizes labels and page setup from 105x148mm to 4x6 inches. Forces all text and borders to solid black under @media print for thermal printer clarity (grays do not render well). Increases recipient name to text-2xl and address lines to text-lg for better readability on printed labels.
Adds realistic Chrome 135 User-Agent and Origin headers to AJAX requests. Fixes referer casing and varies sec-fetch-site per endpoint. Introduces fetchWithRetry that pauses 2s and retries once on 403. Adds KV caching for marketplace listings (5 min TTL) and store items (10 min TTL) to reduce repeated scraping traffic and lower temporary ban risk.
BrickLink returns item names with inline numeric character references (e.g. ( for parentheses). Adds a decodeHtmlEntities helper that uses a temporary textarea to decode these, and applies it wherever catalogItem.name is rendered: the overview link text, both image alt attributes, and the zoom dialog caption.
No additional details.
Look up imported item colors in the KV cache so the pending items table displays color names instead of raw numeric IDs.
No additional details.
No additional details.
No additional details.
No additional details.
Adds an Import button that opens a modal dialog for selecting a BrickLink XML inventory file. Parsing is handled server-side via a new /api/xml/import endpoint. Imported items are appended to the pending list with a warning row tint that turns to success once edited. The pending items table is now scrollable with a max-h-128 cap and sticky headers.
Pending items now have an edit (pencil) button that populates the form for in-place editing, with the active row highlighted and the panel switching to Edit Item mode. A Delete Item button appears in the form footer during editing. The description field gains an inline copy icon that writes the current value to the clipboard with a brief check confirmation.
No additional details.
No additional details.
No additional details.
No additional details.
No additional details.
No additional details.
Adds a badge-check icon button in the Ship To header that verifies all exportable addresses in parallel, auto-saving matched results to KV and showing per-row status indicators (verified, unmatched, error).
No additional details.
No additional details.
Replaces the CANCELLED exclusion with an allowlist of SHIPPED, RECEIVED, COMPLETED, and PURGED — so in-progress and other non-final statuses are also excluded from order counts and totals.
routes/partials/index.tsx mapped to /partials (the directory root) which Fresh could not reliably serve as a partial endpoint, causing the sidebar Home link to update the URL but silently fail to swap the content region. Renaming to home.tsx gives a clean /partials/home URL matching the pattern used by all other flat partials.
Fresh's f-client-nav marks all anchors sharing a pathname as aria-current="page", causing DaisyUI to render both tabs as active. Fixed with a CSS override. Also corrected the Filed tab's f-partial URL to include query params so the handler receives the correct filter, and replaced a one-time useSignal initialisation in OrdersTable with a plain derived value so partial swaps render fresh rows.
Fetches the Customer record from KV and displays total order count and total value per currency in the Buyer card. Also links the buyer name to the customer page with f-partial.
Adds a partial route for customers/[username] so in-app navigation swaps only the content region. Buyer cells in OrdersTable now link to that page with f-partial and show the customer's historical order count from KV.
Replaces the redirect with a proper landing page showing the app logo, title, and three navigation cards for Orders, Inventory, and Customers. The Orders card shows live unfiled order count; Customers shows total count from the buyer index.
No additional details.
No additional details.
No additional details.
Forwards rpp=10 and pi to the upstream catalog API; accepts page and list_only params on the API route so page navigation skips the store and image fetches entirely. Adds prev/next controls with page N of M display. Splits marketplaceLoading from storeLoading so Store Items stays live while only the Marketplace Items section shows a loading state. Keeps existing items visible behind an absolute overlay spinner during page turns instead of clearing the container and collapsing its height.
No additional details.
No additional details.
No additional details.
No additional details.
On initial lookup, fetches the BrickLink catalog item (name, year, obsolete flag, image) and displays it in an overview card above Store Items. Selecting a color calls GET /items/{type}/{no}/images/{colorId} to fetch a color-specific thumbnail, swapping the image immediately; reverting to All restores the original catalog image.
Fetches known colors for an item via the BrickLink API on initial lookup, enriching names from the KV color cache. Color select enables when the item has real colors; selecting a color re-fetches marketplace listings filtered by that color without repeating the color API call. COLOR is included in pending items and the XML output; COLOR_NAME is display-only and stripped before submission.
Adds BLColor and ColorsMeta types, KV helpers for color storage, and BricklinkClient.getColors() via GET /colors. A refreshColors() utility stores each color individually in KV. New POST /api/colors/refresh endpoint returns updated colors and meta. The Colors island shows swatches, IDs, names, and types with a Refresh button. The /colors page follows the standard route/partial pattern, appears in the Settings sidebar with a palette icon, and a Deno cron runs automatic refresh at 01:00 daily.
Adds a two-step BrickLink API proxy: resolve user-facing item ID to internal ID via the catalog search API (cached in KV on success), then fetch AU marketplace listings. Adds POST /api/xml for JSON-to-XML conversion using @libs/xml and GET /api/marketplace. The Inventory island shows a marketplace table with store feedback score, quantity, price, condition, and description.
Adds POST /api/xml endpoint using @libs/xml to convert JSON to XML. Adds the Inventory island with item entry form, pending items table with Copy XML and Reset actions, and stub sections for store and marketplace. Two-column layout on wide screens with form fields split across four rows.
Remove wrapper div with p-6 from InventoryContent — AppFrame already provides page padding, matching the pattern used by other content components.
Adds shell Inventory route/partial, inserts it between Orders and Customers in the sidebar (renamed from "Processing" to "Workflow"), and registers the warehouse icon in @source inline.
Reduced the icon pragma from 35 entries to 9 — only the icons passed dynamically via the Sidebar MenuItem icon prop. Statically referenced icons are detected automatically by Tailwind's scanner. Also removed 9 icons that were unused entirely.
Adds /admin/changelog route displaying a collapsible list of changes sourced from data/changelog.json. Each entry uses a DaisyUI details/summary collapse with the commit subject as the title and optional body as detail. The changelog data is maintained separately in JSON so new entries can be prepended without touching the route code.
The BrickLink API returns HTTP 204 (no content) on a successful order status update. Previously this caused a JSON parse failure or a spurious API error; now it returns early as a success.
Weight is now entered in grams and converted to kg on export. Extra cover steps in multiples of 100 with no decimal places.
No additional details.
Falls back to buyerName if shippingName is absent.
Clicking a thumbnail opens a modal showing the full-size image, part number, name, lot description, color, and a link to the BrickLink catalog entry. Extracted the order items table into OrderItemsTable island so it can hold interactive state.
No additional details.
No additional details.
Allows f-client-nav to intercept all navigation in OrdersTable and OrdersFilterTabs instead of triggering full page reloads.
Adds /admin/logs route using listLogRecords() from logtape-kv-sink, rendering entries in a paginated table with cursor-based navigation. Includes sidebar Admin section with Logs link and scroll icon.
Sidebar links now swap only the main content region without reloading the page shell. Deep linking still works via full-page SSR. Fixes stopPropagation on order table links so partial nav is not blocked.
No additional details.
Fetches BrickLink order message counts and displays a chat bubble icon with count next to each order that has messages. Results are cached in Deno KV with a 60-second TTL to avoid hammering the API on every page load.
Adds a text input with live suggestions fetched from /api/crm/buyers?q=, backed by a KV buyer index built during CRM refresh. Selecting a buyer filters to that customer via server-side lookup. Pagination is hidden while a filter is active.
Adds /customers/{username} detail page showing the BrickLink member rating (PRAISE/NEUTRAL/COMPLAINT with percentages) and a full order history table drawn from the local order cache. Rating fetch failures are shown as a warning rather than a hard error.
Introduces BLMemberRating type matching the actual API wire format. Adds getMemberRating() to BricklinkClient and listCachedOrdersByBuyer() to kv.ts. Converts routes/customers.tsx to routes/customers/index.tsx to support nested routing, and links buyer names in the customers table to the detail page.
Adds POST /api/crm/import which accepts a multipart CSV file and maps rows (order_id, buyer_name, date_ordered, value) into BLOrderSummary records in the order cache. Returns a summary of imported/skipped/error counts with per-row error details.
Adds an Import CSV button to the Customers page that opens a dialog with a file picker and displays the import result summary inline.
Introduces BLOrderSummary to accurately represent the smaller payload returned by the orders list endpoint, distinct from the full BLOrder shape returned by the detail endpoint. getOrders() now returns BLOrderSummary[], the order cache stores summaries, and crm.ts aggregates from them.
Opens Deno KV at most once per process via a module-level singleton. Write functions now return Promise<Deno.KvCommitResult> by returning the KV promise directly rather than awaiting it, removing the redundant suspend point.
Introduces a local order cache in Deno KV. The CRM refresh is now two phases: first sync live API orders into the cache (skipping PURGED entries to protect the last known-good data), then aggregate customer records from the full cache so history beyond BrickLink's 6-month window is retained.
Fetches messages from BrickLink API and displays them as chat bubbles in a tabbed layout alongside Order Items. Buyer messages are chat-start (primary), seller messages are chat-end (secondary), sorted ascending by date. Messages tab only appears when messages exist.
Aggregates all inbound BrickLink orders by buyer_name (excluding cancelled) into a Deno KV-backed CRM. Tracks order count, first/last order date, and spend totals per currency. Customers page at /customers supports KV cursor-based pagination with Prev/Next navigation. An Update button triggers a manual refresh; a Deno cron job runs the same refresh automatically at midnight daily.
No additional details.
No additional details.
No additional details.
No additional details.
No additional details.
No additional details.
No additional details.
No additional details.
No additional details.
No additional details.
No additional details.
No additional details.
No additional details.
No additional details.
No additional details.
No additional details.
No additional details.
No additional details.
No additional details.
No additional details.
No additional details.
No additional details.
No additional details.
No additional details.
No additional details.