- Documents page: Convert from text buttons to icon buttons (Eye for
View Details, Trash for Delete), add card hover shadow effect,
convert to MUI components for consistency
- Fuel Logs: Add row hover background effect on list items
- Maintenance Records: Add card hover shadow effect
- Maintenance Schedules: Add card hover shadow effect
All changes follow the VehicleCard pattern with:
- Light gray shadow/elevation on hover with 0.2s transition
- Consistent icon button styling with mobile-responsive touch targets
- Proper MUI component usage throughout
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
PostgreSQL DECIMAL columns return as strings from pg driver.
- Add Number() conversion for fuelUnits and costPerUnit in toEnhancedResponse()
- Add query invalidation for 'all' key to fix dynamic updates
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Enhanced repository methods were incorrectly calling mapRow() which
converts snake_case to camelCase, but the service's toEnhancedResponse()
expects raw database rows with snake_case properties. This caused
"Invalid time value" errors when calling new Date(row.created_at).
Fixed methods:
- createEnhanced
- findByVehicleIdEnhanced
- findByUserIdEnhanced
- findByIdEnhanced
- getPreviousLogByOdometer
- getLatestLogForVehicle
- updateEnhanced
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Replace polling-based auth detection with event-based subscription
- Remove unnecessary 100ms delay on desktop (keep 50ms for mobile)
- Unify dashboard data fetching to prevent duplicate API calls
- Use Promise.all for parallel maintenance schedule fetching
Reduces dashboard load time from ~1.5s to <500ms.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Rename "Open" button to "View Details" on desktop and mobile document lists
- Add hasDisplayableMetadata helper to check if document has metadata to display
- Conditionally render Details section only when metadata exists
- Prevents showing empty "Details" header for documents without metadata
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Create ExpirationBadge component with 30-day warning and expired states
- Create DocumentCardMetadata component for type-specific field display
- Update DocumentsPage to show metadata and expiration badges on cards
- Update DocumentsMobileScreen with metadata and badges (mobile variant)
- Redesign DocumentDetailPage with side-by-side layout (desktop) and
stacked layout (mobile) showing full metadata panel
- Add 33 unit tests for new components
- Fix jest.config.ts testMatch pattern for test discovery
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Add purchase price and purchase date display to vehicle detail page
- Fix form validation to handle NaN from empty number inputs using z.preprocess
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
The VIN Number field incorrectly showed license plate when VIN was empty.
Now displays "Not provided" for missing VIN values, matching mobile behavior.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Remove CostInterval type and TCOResponse interface from frontend types
- Remove insurance/registration cost fields from VehicleForm schema and UI
- Keep purchasePrice and purchaseDate fields on vehicle form
- Remove TCODisplay component from VehicleDetailPage
- Delete TCODisplay.tsx component file
- Remove getTCO method from vehicles API client
Legacy TCO fields moved to ownership-costs feature in #29.
Backend endpoint preserved for future reporting feature.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Replace raw HTML checkboxes with MUI Checkbox wrapped in FormControlLabel
for consistent styling and theme integration across:
- DocumentForm.tsx (shared vehicles + scan maintenance checkboxes)
- VehicleForm.tsx (TCO enabled checkbox)
- SignupForm.tsx (terms acceptance checkbox)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
The upload was hanging silently because breaking early from a
`for await` loop on a Node.js stream corrupts the stream's internal
state. The remaining stream could not be used afterward.
Changes:
- Collect ALL chunks from the file stream before processing
- Use subarray() for file type detection header (first 4100 bytes)
- Create single readable stream from complete buffer for storage
- Remove broken headerStream + remainingStream piping logic
This fixes the root cause where uploads would hang after logging
"Document upload requested" without ever completing or erroring.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Document uploads were failing with "timeout of 10000ms exceeded" error
because the global axios client timeout (10s) was too short for
medium-sized files (1-5MB).
Added calculateUploadTimeout() function that calculates timeout based on
file size: 30s base + 10s per MB. This allows uploads to complete on
slower connections while still having reasonable timeout limits.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Created DeleteDocumentConfirmDialog with context-aware messaging:
- Primary vehicle with no shares: Full delete
- Shared vehicle: Remove association only
- Primary vehicle with shares: Full delete (affects all)
- Integrated documents display in VehicleDetailPage records table
- Added delete button per document with 44px touch target
- Document deletion uses appropriate backend calls based on context
- Mobile-friendly dialog with responsive design
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Implemented comprehensive document editing capabilities:
1. Created EditDocumentDialog component:
- Responsive MUI Dialog with fullScreen on mobile
- Wraps DocumentForm in edit mode
- Proper close handlers with refetch
2. Enhanced DocumentForm to support edit mode:
- Added mode prop ('create' | 'edit')
- Pre-populate all fields from initialValues
- Use useUpdateDocument hook when in edit mode
- Multi-select for shared vehicles (insurance only)
- Vehicle and document type disabled in edit mode
- Optional file upload in edit mode
- Dynamic button text (Create/Save Changes)
3. Updated DocumentDetailPage:
- Added Edit button with proper touch targets
- Integrated EditDocumentDialog
- Refetch document on successful edit
Mobile-first implementation:
- All touch targets >= 44px
- Dialog goes fullScreen on mobile
- Form fields stack on mobile
- Shared vehicle checkboxes have min-h-[44px]
- Buttons use flex-wrap for mobile overflow
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Created shared utility getVehicleLabel() for consistent vehicle display
- Updated DocumentsPage to show vehicle names with clickable links
- Added "Shared with X vehicles" indicator for multi-vehicle docs
- Updated DocumentDetailPage with vehicle name and shared vehicle list
- Updated DocumentsMobileScreen with vehicle names and "Shared" indicator
- All vehicle names link to vehicle detail pages
- Mobile-first with 44px touch targets on all links
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Update DocumentRecord interface to include sharedVehicleIds array
- Add optional sharedVehicleIds to Create/UpdateDocumentRequest types
- Add documentsApi.listByVehicle() method for fetching by vehicle
- Add documentsApi.addSharedVehicle() for linking vehicles
- Add documentsApi.removeVehicleFromDocument() for unlinking
- Add useDocumentsByVehicle() query hook with vehicle filter
- Add useAddSharedVehicle() mutation with optimistic updates
- Add useRemoveVehicleFromDocument() mutation with optimistic updates
- Ensure query invalidation includes both documents and documents-by-vehicle keys
- Update test mocks to include sharedVehicleIds field
- Fix optimistic update in useCreateDocument to include new fields
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Updates documents backend service and API to support multi-vehicle insurance documents:
- Service: createDocument/updateDocument validate and handle sharedVehicleIds for insurance docs
- Service: addVehicleToDocument validates ownership and adds vehicles to shared array
- Service: removeVehicleFromDocument with context-aware delete logic:
- Shared vehicle only: remove from array
- Primary with no shared: soft delete document
- Primary with shared: promote first shared to primary
- Service: getDocumentsByVehicle returns all docs for a vehicle (primary or shared)
- Controller: Added handlers for listByVehicle, addVehicle, removeVehicle with proper error handling
- Routes: Added POST/DELETE /documents/:id/vehicles/:vehicleId and GET /documents/by-vehicle/:vehicleId
- Validation: Added DocumentVehicleParamsSchema for vehicle management routes
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Add migration 004_add_shared_vehicle_ids.sql with UUID array column and GIN index
- Update DocumentRecord interface to include sharedVehicleIds field
- Add sharedVehicleIds to CreateDocumentBody and UpdateDocumentBody schemas
- Update repository mapDocumentRecord() to map shared_vehicle_ids from database
- Update insert() and batchInsert() to handle sharedVehicleIds
- Update updateMetadata() to support sharedVehicleIds updates
- Add addSharedVehicle() method using atomic array_append()
- Add removeSharedVehicle() method using atomic array_remove()
- Add listByVehicle() method to query by primary or shared vehicle
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
The ownership_costs table was created with an outdated schema that had
different column names (start_date/end_date vs period_start/period_end)
and was missing the notes column. This migration aligns the database
schema with the current code expectations.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Milestone 6: Change empty interface to type alias to fix
@typescript-eslint/no-empty-object-type error
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Milestone 4: Complete frontend with:
- Types aligned with backend schema
- API client for CRUD operations
- React Query hooks with optimistic updates
- OwnershipCostForm with all 6 cost types
- OwnershipCostsList with edit/delete actions
- Mobile-friendly (44px touch targets)
- Full dark mode support
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Milestone 2: Auto-create ownership_cost when insurance/registration
document is created with cost data (premium or cost field).
- Add OwnershipCostsService integration
- Auto-create cost on document create when amount > 0
- Sync cost changes on document update
- mapDocumentTypeToCostType() validation
- extractCostAmount() for premium/cost field extraction
- CASCADE delete handled by FK constraint
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Milestone 1: Complete backend feature with:
- Migration with CHECK (amount > 0) constraint
- Repository with mapRow() for snake_case -> camelCase
- Service with CRUD and vehicle authorization
- Controller with HTTP handlers
- Routes registered at /api/ownership-costs
- Validation with Zod schemas
- README with endpoint documentation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Add 'features/ownership-costs' to MIGRATION_ORDER in run-all.ts
- Improve OwnershipCostsList error display to not block the page
- Show friendly message when feature needs migration
- Add OwnershipCostsList to desktop VehicleDetailPage
- Add OwnershipCostsList to mobile VehicleDetailMobile
- Users can now view, add, edit, and delete recurring costs directly
from the vehicle detail view
- Create ownership_costs table for recurring vehicle costs
- Add backend feature capsule with types, repository, service, routes
- Update TCO calculation to use ownership_costs (with fallback to legacy vehicle fields)
- Add taxCosts and otherCosts to TCO response
- Create frontend ownership-costs feature with form, list, API, hooks
- Update TCODisplay to show all cost types
This implements a more flexible approach to tracking recurring ownership costs
(insurance, registration, tax, other) with explicit date ranges and optional
document association.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Quality Review Fixes:
- Add comprehensive unit tests for getTCO() method (12 test cases)
- Add tests for normalizeRecurringCost() via getTCO integration
- Add future date validation guard in calculateMonthsOwned()
- Fix pre-existing unused React import in VehicleLimitDialog.test.tsx
- Fix pre-existing test parameter types in vehicles.service.test.ts
Test Coverage:
- Vehicle not found / unauthorized access
- Missing optional TCO fields handling
- Zero odometer (costPerDistance = 0)
- Monthly/semi-annual/annual cost normalization
- Division by zero guard (new purchase)
- Future purchase date handling
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Create TCODisplay component showing lifetime cost and cost per distance
- Display cost breakdown (purchase, insurance, registration, fuel, maintenance)
- Integrate into VehicleDetailPage right-justified next to vehicle details
- Responsive layout: stacks vertically on mobile, side-by-side on desktop
- Only shows when tcoEnabled is true
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Add GET /api/vehicles/:id/tco route
- Add getTCO controller method with error handling
- Returns 200 with TCO data, 404 for not found, 403 for unauthorized
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Add TCOResponse interface
- Add getTCO() method aggregating all cost sources
- Add normalizeRecurringCost() with division-by-zero guard
- Integrate FuelLogsService and MaintenanceService for cost data
- Respect user preferences for distance unit and currency
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Add MaintenanceCostStats interface
- Add getVehicleMaintenanceCosts() method to maintenance service
- Validates numeric cost values and throws on invalid data
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Add CostInterval type and PAYMENTS_PER_YEAR constant
- Add 7 TCO fields to Vehicle, CreateVehicleRequest, UpdateVehicleRequest
- Update VehicleResponse and Body types
- Update mapRow() with snake_case to camelCase mapping
- Update create(), update(), batchInsert() for new fields
- Add Zod validation for TCO fields with interval enum
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Add database columns for Total Cost of Ownership:
- purchase_price, purchase_date
- insurance_cost, insurance_interval
- registration_cost, registration_interval
- tco_enabled toggle
Includes CHECK constraints for interval values and non-negative costs.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Critical fix for merge mode vehicle matching logic.
Problem:
- Vehicles with same license plate but no VIN were matched to the same existing vehicle
- Example: 2 vehicles with license plate "TEST-123" both updated the same vehicle
- Result: "Updated: 2" but only 1 vehicle in database, second vehicle overwrites first
Root Cause:
- Matching order was: VIN → license plate
- Both vehicles had no VIN and same license plate
- Both matched the same existing vehicle by license plate
Solution:
- New matching order: ID → VIN → license plate
- Preserves vehicle identity across export/import cycles
- Vehicles exported with IDs will update the same vehicle on re-import
- New vehicles (no matching ID) will be created as new records
- Security check: Verify ID belongs to same user before matching
Benefits:
- Export-modify-import workflow now works correctly
- Vehicles maintain identity across imports
- Users can safely import data with duplicate license plates
- Prevents unintended overwrites
Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Added detailed logging to diagnose import merge issues:
- Log vehicle count at merge start
- Log each vehicle being processed with VIN/make/model/year
- Log when existing vehicles are found (by VIN or license plate)
- Log successful vehicle creation with new vehicle ID
- Log errors with full context (userId, VIN, make, model, error message)
- Log merge completion with summary statistics
This will help diagnose why vehicles show as "successfully imported" but don't appear in the UI.
Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Desktop changes:
- Replace ImportButton component with MUI Button matching Export style
- Use hidden file input with validation
- Dark red/maroon button with consistent styling
Mobile changes:
- Update both Import and Export buttons to use primary-500 style
- Consistent dark primary button appearance
- Maintains 44px touch target requirement
Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Implement archive service to extract and validate user data import archives. Validates manifest structure, data files, and ensures archive format compatibility with export feature.
- user-import.types.ts: Type definitions for import feature
- user-import-archive.service.ts: Archive extraction and validation
- Validates manifest version (1.0.0) and required fields
- Validates all data files exist and contain valid JSON
- Temp directory pattern mirrors export (/tmp/user-import-work)
- Cleanup method for archive directories
Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Add batchInsert methods to vehicles, fuel-logs, maintenance, and documents repositories. Multi-value INSERT syntax provides 10-100x performance improvement over individual operations for bulk data import.
- vehicles.repository: batchInsert for vehicles
- fuel-logs.repository: batchInsert for fuel logs
- maintenance.repository: batchInsertRecords and batchInsertSchedules
- documents.repository: batchInsert for documents
- All methods support empty array (immediate return) and optional transaction client
- Fix lint error: replace require() with ES6 import in test mock
Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
PostgreSQL error 0A000 (feature_not_supported) occurs when using
FOR UPDATE with aggregate functions like COUNT(*). Row-level locking
requires actual rows to lock.
Changes:
- Select id column instead of COUNT(*) aggregate
- Count rows in application using .length
- Maintains transaction isolation and race condition prevention
Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Backend: Enhanced matchField function with prefix and contains matching
so NHTSA values like "Sierra" match dropdown options like "Sierra 1500".
Matching hierarchy:
1. Exact match (case-insensitive) -> high confidence
2. Normalized match (remove special chars) -> medium confidence
3. Prefix match (option starts with value) -> medium confidence (NEW)
4. Contains match (option contains value) -> medium confidence (NEW)
Frontend: Fixed VIN decode form population by loading dropdown options
before setting form values, preventing cascade useEffects from clearing
decoded values.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
VIN decode was setting year/make/model/trim values, but the cascading
dropdown useEffects would immediately clear dependent fields because
they detected a value change. Added isVinDecoding ref flag (mirroring
the existing isInitializing pattern for edit mode) to skip cascade
clearing during VIN decode and properly load dropdown options.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Add NHTSA client for VIN decoding with caching and validation
- Add POST /api/vehicles/decode-vin endpoint with tier gating
- Add dropdown matching service with confidence levels
- Add decode button to VehicleForm with tier check
- Responsive layout: stacks on mobile, inline on desktop
- Only populate empty fields (preserve user input)
Backend:
- NHTSAClient with 5s timeout, VIN validation, vin_cache table
- Tier gating with 'vehicle.vinDecode' feature key (Pro+)
- Tiered matching: high (exact), medium (normalized), none
Frontend:
- Decode button with loading state and error handling
- UpgradeRequiredDialog for free tier users
- Mobile-first responsive layout
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Add userEmail field to AuditLogEntry type in backend and frontend
- Update audit-log repository to LEFT JOIN with user_profiles table
- Update AdminLogsPage to show email with fallback to truncated userId
- Update AdminLogsMobileScreen with same display logic
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Backend:
- Add login event logging to getUserStatus() controller method
- Create POST /auth/track-logout endpoint for logout tracking
Frontend:
- Create useLogout hook that wraps Auth0 logout with audit tracking
- Update all logout locations to use the new hook (SettingsPage,
Layout, MobileSettingsScreen, useDeletion)
Login events are logged when the frontend calls /auth/user-status after
Auth0 callback. Logout events are logged via fire-and-forget call to
/auth/track-logout before Auth0 logout.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
The audit_logs table migration was not being executed because the
audit-log feature was missing from MIGRATION_ORDER in run-all.ts,
causing 500 errors when accessing the audit logs API.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
The routes and screen components for AdminLogsPage were implemented but
the navigation links to access them were missing from both desktop and
mobile Settings pages.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
The old /api/admin/audit-logs route in admin.routes.ts conflicted with the
new centralized audit-log feature. Removed the old route since we're now
using the unified audit logging system.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Add audit_logs table with categories, severities, and indexes
- Create AuditLogService and AuditLogRepository
- Add REST API endpoints for viewing and exporting logs
- Wire audit logging into auth, vehicles, admin, and backup features
- Add desktop AdminLogsPage with filters and CSV export
- Add mobile AdminLogsMobileScreen with card layout
- Implement 90-day retention cleanup job
- Remove old AuditLogPanel from AdminCatalogPage
Security fixes:
- Escape LIKE special characters to prevent pattern injection
- Limit CSV export to 5000 records to prevent memory exhaustion
- Add truncation warning headers for large exports
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Replace per-schedule count-based retention with unified tiered classification.
Backups are now classified by timestamp into categories (hourly/daily/weekly/monthly)
and are only deleted when they exceed ALL applicable category quotas.
Changes:
- Add backup-classification.service.ts for timestamp-based classification
- Rewrite backup-retention.service.ts with tiered logic
- Add categories and expires_at columns to backup_history
- Add Expires column to desktop and mobile backup UI
- Add unit tests for classification logic (22 tests)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
File inputs are replaced elements that ignore CSS centering properties.
The only reliable solution is to wrap the input in a flex container
with items-center.
Changes:
- Added wrapper div with `flex items-center h-11`
- Moved border/background/focus styles to the wrapper
- Input now uses flex-1 to fill available space
- Used focus-within for focus ring on wrapper
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Use leading-[44px] to match the h-11 height, which should vertically
center the file input content. Removed padding that was conflicting.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
The "Choose File" button and "No file chosen" text were not vertically
centered within the file input box.
Fixed by:
- Using py-2.5 for input padding (10px top/bottom)
- Adding file:my-auto to center the button vertically
- Adjusting file:py-1.5 for button internal padding
Note: flex/items-center don't work on <input> elements as they are
replaced elements. Using padding and margin-auto instead.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
The "Choose File" button and "No file chosen" text were not vertically
centered within the file input. This was caused by:
1. Browser default `align-items: baseline` for file inputs
2. Conflicting `py-2` padding on the input container
Fixed by:
- Removing `py-2` (conflicting vertical padding)
- Adding `flex items-center` (explicit vertical centering)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Add GET /api/admin/stats endpoint for Total Vehicles widget
- Add GET /api/admin/users/:auth0Sub/vehicles endpoint for user vehicle list
- Update AdminUsersPage with Total Vehicles stat and expandable vehicle rows
- Add My Vehicles section to SettingsPage (desktop) and MobileSettingsScreen
- Update AdminUsersMobileScreen with stats header and vehicle expansion
- Add defense-in-depth admin checks and error handling
- Update admin README documentation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
The mobile FAB 'Maintenance' option was navigating to the Vehicles screen
instead of the Maintenance screen. Updated handleQuickAction to navigate
to 'Maintenance' which displays MaintenanceMobileScreen.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Add terms_agreements table for legal audit trail
- Create terms-agreement feature capsule with repository
- Modify signup to create terms agreement atomically
- Add checkbox with PDF link to SignupForm
- Capture IP, User-Agent, terms version, content hash
- Update CLAUDE.md documentation index
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Add Vehicle now navigates to Vehicles screen and opens add form
- Add Maintenance mobile screen with records/schedules tabs
- Add 'Maintenance' to MobileScreen type
- Wire up onViewMaintenance callback to navigate to Maintenance screen
refs #2🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Add onAddVehicle prop to DashboardScreen
- Mobile: triggers setShowAddVehicle(true) in App.tsx
- Desktop: navigates to /garage/vehicles with showAddForm state
- VehiclesPage auto-opens form when receiving showAddForm state
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Add onViewMaintenance prop to DashboardScreen
- Desktop: navigates to /garage/maintenance
- Mobile: falls back to Vehicles (no dedicated mobile maintenance screen)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Changed from borderRadius 3 (24px) to 1.5 (12px) for more rectangular look
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Visual consistency fixes:
- Replace all emojis with MUI Rounded icons
- Use theme colors (primary.main, warning.main, success.main, error.main)
- Use MUI Box with sx prop for consistent styling
- Use shared Button component instead of custom styled buttons
- Use theme tokens for dark mode (avus, titanio, canna)
Components updated:
- SummaryCards: DirectionsCarRoundedIcon, BuildRoundedIcon, LocalGasStationRoundedIcon
- QuickActions: MUI icons with primary.main color
- VehicleAttention: ErrorRoundedIcon, WarningAmberRoundedIcon, ScheduleRoundedIcon
- DashboardScreen: Proper icons for error/empty states, shared Button component
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Adds Visual Integration section to prevent design inconsistencies:
- Icons: Must use MUI Rounded icons only, no emoji in UI
- Colors: Theme colors only, no hardcoded hex, dark mode support
- Components: Use existing shared components (GlassCard, Button, etc.)
- Typography & Spacing: MUI variants, consistent spacing multiples
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Adds Gitea issue templates to prevent missed integration points:
- feature.yaml: Includes Integration Criteria section for navigation,
routing, and state management requirements
- bug.yaml: Structured bug reporting with platform selection
- chore.yaml: Technical debt and maintenance tasks
The Integration Criteria section ensures features specify:
- Desktop sidebar / mobile nav placement
- Route paths and default landing page
- Mobile screen type in navigation store
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Add Dashboard to desktop sidebar navigation (first item)
- Add /garage/dashboard route for desktop
- Change default redirect from /garage/vehicles to /garage/dashboard
- Change mobile default screen from Vehicles to Dashboard
- Create DashboardPage wrapper for desktop route
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>