- Click chevron or checklist title to expand/collapse
- Completed checklists (100%) auto-collapse on page load
- Completed title shown in green with checkmark icon
- Progress bar and count always visible when collapsed
- Items and add-item form hidden when collapsed
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New reusable components:
- ImageUpload.svelte: drag-and-drop / click / paste zone with file
icon, preview of selected filename, caption field, 50MB limit
- DocumentUpload.svelte: same pattern for documents with description
field instead of caption
Applied to both device and component detail pages, replacing the old
inline file input forms. Cleaner look matching modern upload UIs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Shows number of non-done todos (todo + in_progress) next to the
Todos nav item. Hides when count is zero.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Image upload/delete on component detail page (same pattern as devices)
- Images section with grid, hover-to-delete, 50MB client-side limit
- Sidebar component count now excludes disabled components by joining
componentInstances with components and filtering disabled=false
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- disabled boolean on components table (default false)
- Component list filters out disabled components
- Component detail returns 404 for disabled
- Delete button with confirmation on component detail page
- Installation form filters out instances of disabled components
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Components are now split into two concepts:
- Component (type definition): title, componentType, brand, partNumber,
specs, notes, default condition/firmware/location
- Component Instance (individual physical unit): serialNumber, condition,
firmwareVersion, notes, currentDeviceId, locationId
Key changes:
- New component_instances table with per-unit tracking
- Component list shows cards with total/installed/available counts
- Component detail page shows all instances with inline edit
- Add instances: bulk (quantity) or one at a time
- Each instance has install/remove/edit/delete actions
- Installation log now references instances, not components
- Device detail shows installed instances with instance numbers
- Dashboard and sidebar counts use instance totals
- Location pages show instances, not component types
- Labels show component type info (serial is per-instance)
IMPORTANT: Run db:push on the server after deploy to create the new
tables and columns. Existing component data will need manual migration.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Added BODY_SIZE_LIMIT=52428800 (50MB) to .env.example
- handleError in hooks catches body size exceeded and returns friendly message
- Client-side file size check on image upload input (alerts before submit)
- adapter-node uses BODY_SIZE_LIMIT env var (default was 512KB)
To fix: add BODY_SIZE_LIMIT=52428800 to .env on the server and restart.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
In production with adapter-node, the relative path 'static/uploads'
doesn't resolve correctly. Now uses UPLOAD_DIR env variable (absolute
path) for both saving and serving uploaded files.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replaced all 'B4L Repair' references with 'My Collection'
- Added favicon.png next to the title in the sidebar
- Added favicon.png on the login page above the title
- Updated all page <title> tags
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- /checklists now shows templates in a responsive grid (cards with
title, description, item count, last updated)
- Clicking a card opens /checklists/[id] dedicated edit page
- "New Template" creates and redirects to the edit page
- Edit page has: rename title/description, add/edit/delete/reorder
items, delete template (redirects back to grid)
- Breadcrumb navigation back to grid
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Templates page (/checklists):
- Edit template name/description inline (pencil icon)
- Edit item text and unit inline (pencil icon on hover)
- Move items up/down with arrow buttons
- Reorder swaps sort order values in the database
Device checklists:
- Rename checklist title inline (pencil icon)
- Edit item text and unit inline (pencil icon on hover)
- Move items up/down with arrow buttons
- All item types (checkbox and input) support editing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
adapter-node only serves pre-built static assets, not files uploaded
at runtime. Added /uploads/[...path] catch-all route that reads from
static/uploads/ with proper MIME types and cache headers.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Added HEIF, GIF, AVIF, BMP, TIFF to allowed image types
- All uploads converted to JPEG via sharp (fixes HEIC/HEIF from iPhones)
- Upload action wrapped in try/catch, errors shown in UI
- Error banner displayed above image section on failure
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- /locations/[id] shows all devices and stored components at a location
- Breadcrumb navigation with parent location
- Sub-location chips for navigating to children
- Location names are clickable links everywhere: location list page,
device detail sidebar, component detail current location
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Device/component detail pages show "Parent › Child" for locations
- Device list cards show full location path
- Location edit form now includes a Parent selector to move locations
between parents or make them top-level
- Prevents setting a location as its own parent
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
LocationPicker component shows parent locations first. Once a parent
is selected, a second dropdown appears with its children. If the
parent has no children, it's selected directly. Used in device
create/edit, component create/edit, and installation log forms.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pencil icon on each location opens inline form to edit name and
description. Saves via rename action, cancel to discard.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Settings page shows account info and a change password form.
Validates current password, minimum 8 chars, confirmation match.
Added Settings link in sidebar.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Two SSH keys needed:
- DEPLOY_KEY: CI runner → LXC server (SSH access)
- REPO_DEPLOY_KEY: LXC server → Gitea repo (git pull access)
Workflow writes the repo deploy key to ~/.ssh on the server and
configures SSH to use it for git.b4l.co.th. Handles first deploy
(clone) and subsequent deploys (pull) automatically.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- component_documents table matching device_documents structure
- Upload/delete actions on component detail page
- Documents section in sidebar with file icon, filename, delete on hover
- Devices already had document support; components now match
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Edit buttons were missing type="button" so they could trigger parent
form submissions. Kanban edit now switches to list view where the
inline edit form is rendered.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- todos table with title, description, status (todo/in_progress/done),
priority (urgent/high/medium/low), optional device link, due date
- List view: sorted by priority, inline edit, click-to-advance status
circle (empty → blue dot → green check), edit/delete actions
- Kanban board view: three columns, move buttons between statuses,
priority badges, device links, due dates
- Toggle between List and Board views via URL param
- Optional link to a device for repair-related todos
- Sidebar nav item added
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Sidebar navItems uses $derived() so badge counts stay reactive
- const destructures (c, d, cd) use $derived() to track prop changes
- Added aria-label to hamburger and add-item buttons
- Filter state_referenced_locally warnings in svelte.config.js — these
are intentional one-shot initializers for mutable form inputs
Result: 0 errors, 0 warnings, 0 files with problems.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Removed page-break-after: always and reset html/body height to auto
so the print renderer doesn't generate a trailing empty page.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The (app) layout's flex h-screen + overflow-hidden container was
clipping label content in the print renderer. Print routes now use
a dedicated (print) layout group with no sidebar/header/flex shell,
just the raw label HTML. Routes changed to /print/device/[id] and
/print/component/[id].
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Moved all label styling to inline styles with explicit color: black and
background: white so dark mode and Tailwind resets can't hide content.
Print styles use :global() scoped selectors.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Label width/height was inside @media screen so print had no dimensions.
Moved to base CSS so labels render in both screen preview and print.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
QR code on the left, text and barcode on the right. Fits the pre-cut
DK-1201 address label format.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Print page formatted for Brother DK-22210 (29mm continuous tape)
- Each label has: title, brand/model, serial, QR code, Code 128 barcode
- CSS @page sized to 29mm width with minimal margins
- Print button opens popup that auto-triggers print dialog
- Copies selector to print multiple labels at once
- Barcode encodes short ID (first 8 chars) scannable by the lookup endpoint
- Available on both device and component detail pages
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Multiple voltages are stored as comma-separated string (e.g. "110V, 220V").
Edit form pre-selects existing values by parsing the stored string.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- All items use a consistent grid layout (checkbox/indicator, content, delete)
- Input items show a green check indicator when a value is filled
- Saving a value auto-sets checked=true (clearing it sets checked=false)
- Progress bar and count now include input items with values as completed
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Checklist items can now be either 'checkbox' (tick/untick) or 'input'
(text value with optional unit). Useful for recording measurements
like RPM, wow & flutter, torque, voltage, dB levels, etc.
- itemType and unit fields on template_items and checklist_items
- Template page shows type selector and unit field when adding items
- Device checklist renders input items as labeled text fields with unit
- Save button persists measured values
- Import copies item types and units from templates
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The bind:value + onsubmit pattern caused the input to be empty when
enhance submitted the form. Replaced with post-submission DOM reset
so the value is intact during submission.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- checklist_templates and template_items tables for reusable checklists
- /checklists page: create/edit/delete templates with ordered items
- "Import" button on device detail imports a template as a new checklist
with all items copied (unchecked)
- Sidebar nav item for Checklists between Locations and Gallery
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Checklists feature:
- device_checklists and checklist_items tables
- Create multiple named checklists per device
- Add/toggle/delete items with progress bar
- Checkbox UI with green check, strikethrough for completed items
- Delete checklist button with item count display
Also adds the classic Mac happy face as favicon.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Users and sessions tables (Argon2 password hashing, SHA-256 session tokens)
- Server hooks validate session cookie on every request
- (app) routes redirect to /login if not authenticated
- Login page with email/password, styled matching budget app
- Logout via POST form action (invalidates session)
- User display name and sign out button in header
- create-user CLI script: npm run create-user <email> <password> [name]
- 30-day sessions with auto-refresh after 15 days
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Upgrade to nodejs_22 (22.22.2) for better Vite 6 compatibility
- Fix wrapper script shebang broken by heredoc indentation
- Add preBuild step for svelte-kit sync
- Default databaseUrl to "" so environmentFile-only configs don't fail eval
- Add assertion ensuring either databaseUrl or environmentFile is set
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Includes nix develop shell (node, pg, vips), buildNpmPackage derivation,
and a NixOS module for deploying as a systemd service with hardening,
dedicated user, and configurable secrets via environmentFile.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
SvelteKit + PostgreSQL app for tracking vintage computers, audio equipment,
components, and installation history. Features device/component CRUD, operation
logs, QR code labels, global search, image uploads, and dark mode.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>