- Set up esbuild for fast TypeScript compilation of frontend code
- Create SharedHeader component with factories for main/admin/privacy pages
- Create SharedFooter component with standard and minimal variants
- Add frontend build scripts (build:frontend, watch:frontend, dev:full)
- Configure TypeScript for browser environment with DOM types
- Add example page demonstrating shared component usage
- Update .gitignore to exclude compiled frontend files
Benefits:
- Type-safe frontend components
- Consistent headers/footers across all pages
- Single source of truth for common UI elements
- Built-in i18n and theme toggle support
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove default text from i18n spans to prevent double snowflake on main page
- Add i18n support to admin page with language selector
- Make admin panel title translatable
This ensures the snowflake emoji only appears once as a clickable link,
and the translated app name appears separately without its own snowflake.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add data-i18n-placeholder support to i18n.js for dynamic placeholder translation
- Update form inputs with proper i18n attributes for placeholders and labels
- Make snowflake emoji (❄️) clickable on all pages to return to homepage
- Remove snowflake from translation strings since it's now a separate element
- Add i18n support to README features list
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit extends the existing i18n system to fully support server-side translations
for users who have JavaScript disabled or are using the /table route directly.
Changes:
- Complete server-side Spanish (es-MX) translation support for /table route
- Language selector dropdown in table view with form-based locale switching
- URL parameter support (?locale=es-MX) for direct language selection
- Updated POST form handler to persist locale selection across submissions
- Proper locale detection and fallback for server-rendered pages
- Fixed language selector initialization timing in client-side JS
- Removed unused dependencies (canvas, sharp) to clean up package.json
- Added snowflake emoji to app name in both English and Spanish translations
The /table route now provides a complete non-JavaScript experience in both English
and Spanish, ensuring accessibility for all users regardless of their browser
capabilities or JavaScript preferences.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
This major feature introduces complete internationalization architecture with Spanish (Mexico) as the first additional language:
## New Features:
- **I18n Architecture**: Complete client-side and server-side internationalization system
- **Spanish (Mexico) Support**: Full es-MX translations for all user-facing text
- **Language Selector**: Dynamic language switching UI component in header
- **API Endpoints**: RESTful endpoints for serving translations (/api/i18n)
- **Progressive Enhancement**: Language detection via Accept-Language header and cookies
## Technical Implementation:
- **Frontend**: Client-side i18n.js with automatic DOM translation and language selector
- **Backend**: Server-side i18n service with locale detection middleware
- **Build Process**: Automated copying of translation files to dist/ directory
- **Responsive Design**: Language selector integrated into header controls layout
## Files Added:
- public/i18n.js - Client-side internationalization library
- src/i18n/index.ts - Server-side i18n service
- src/i18n/locales/en.json - English translations
- src/i18n/locales/es-MX.json - Spanish (Mexico) translations
- src/routes/i18n.ts - API endpoints for translations
## Files Modified:
- package.json - Updated build process to include i18n files
- public/index.html - Added i18n attributes and language selector
- public/app.js - Integrated dynamic translation updates
- src/server.ts - Added locale detection middleware
- src/scss/pages/_index.scss - Language selector styling
This implementation supports easy addition of future languages and maintains backward compatibility while providing a seamless multilingual experience.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add web app manifest for home screen installation
- Implement service worker with offline caching strategy
- Create offline fallback page with auto-reconnect
- Generate PWA icons in multiple sizes (72px-512px)
- Add PWA meta tags and Apple Touch icons to all pages
- Register service worker with graceful degradation
- Update documentation with PWA installation instructions
- Add browserconfig.xml for Windows tile support
Features:
- Installable on mobile and desktop
- Offline functionality with cached resources
- App-like experience in standalone mode
- Automatic updates when online
- Works seamlessly with existing progressive enhancement
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Moved .nojs-notice styles to main SCSS to eliminate duplication.
The styles are already properly defined in src/scss/main.scss,
so inline styles in <noscript> tags are redundant.
This follows DRY principles and reduces code duplication.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Implement MapImageService using Mapbox Static Images API
- Add server-side /table route with HTML form submission
- Generate static map images with auto-fit positioning based on actual location coordinates
- Add progressive enhancement with noscript fallbacks and Basic View button
- Update map center coordinates to proper Grand Rapids location
- Add numbered pins with color coding (red for regular, orange for persistent reports)
- Remove server-side caching to ensure fresh map images
- Fix theme toggle icon centering in CSS mixins
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Accept main branch's superior inline theme detection approach
- Keep architecture improvements from feature branch
- Maintain all new models/services layer functionality
- Preserve frontend refactoring with MapBase class
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add inline script to apply theme immediately in head
- Prevents flash of light mode before auto/dark theme applies
- Script runs before DOM parsing to avoid visual flicker
- Applied to all pages: index, admin, and privacy
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Major architectural improvements:
- Created models/services layer for better separation of concerns
- Location model with async methods for database operations
- ProfanityWord model for content moderation
- DatabaseService for centralized database management
- ProfanityFilterService refactored to use models
- Refactored frontend map implementations to share common code
- MapBase class extracts 60-70% of duplicate functionality
- Refactored implementations extend MapBase for specific features
- Maintained unique geocoding capabilities per implementation
- Updated server.js to use new service architecture
- All routes now use async/await with models instead of raw queries
- Enhanced error handling and maintainability
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add immediate theme application in <head> section for all pages
- Prevents light mode flash when navigating in dark mode
- Script executes before body renders to apply saved theme
- Fixes flash when going from privacy policy back to home
- Maintains consistent theme experience across all pages
- Supports auto theme detection based on system preference
- Add missing #map CSS styles to fix map container display
- Fix auto theme detection by implementing proper system preference detection
- Update applyTheme function in all JS files to handle 'auto' theme correctly
- System theme changes are now properly detected and applied when in auto mode
- Remove public/style.css.map from git tracking with git rm --cached
- CSS source maps are generated artifacts like the CSS file itself
- Already excluded in .gitignore but was previously tracked
- Keeps local file for development debugging but excludes from repo
- Add :focus pseudo-class to button mixin with outline styling
- Improves keyboard navigation accessibility for all buttons
- Uses currentColor for outline to adapt to different button styles
- Meets WCAG accessibility standards for focus visibility
- Update CSS source map after rebuild
- Remove all !important declarations from table cell styles in _index.scss
- Increase selector specificity by changing .location-cell to td.location-cell
- Change .details-cell to td.details-cell, .time-cell to td.time-cell, etc.
- This eliminates the need for !important while maintaining proper cascade order
- Follows CSS best practices for maintainable and readable stylesheets
- Added public/style.css to .gitignore
- Removed style.css from git tracking (git rm --cached)
- Enhanced package.json scripts for better CSS workflow:
- postinstall: Auto-builds CSS on npm install
- build-css:dev: Development build with source maps
- start: Now builds CSS before starting server
- dev: Builds CSS before development mode
- Updated README with CSS development documentation
- Explains SCSS organization and build process
- Documents all CSS-related npm scripts
Benefits:
✅ Cleaner repository (no generated files)
✅ Prevents merge conflicts in generated CSS
✅ Automatic CSS generation on new machine setup
✅ Source of truth is SCSS files only
✅ Consistent build process across environments
- Created src/scss/pages/_privacy.scss with all privacy page styles
- Moved all inline styles from privacy.html to proper CSS classes
- Replaced inline style attributes with semantic CSS classes:
- privacy-header__title-wrapper for header positioning
- privacy-header__title-content for centered title content
- privacy-header__theme-toggle for theme toggle button
- Maintained all existing functionality and styling
- Improved maintainability and consistency with SCSS architecture
- All styles now use CSS variables for theme compatibility
- Resolved conflicts in admin.html to keep CSS optimization changes
- Regenerated package-lock.json after merge
- All features from both branches are now integrated
- Add async initialize() method for reliable initialization waiting
- Add static create() factory method for easy async creation
- Add initialization state tracking with isInitialized flag
- Add warning system for methods called before full initialization
- Update server.js to use proper async initialization pattern
- Maintain backward compatibility with constructor-only usage
- Add accessibility improvement for reduced motion preferences in CSS
Fixes the race condition issue where consumers relied on arbitrary
timeouts instead of properly waiting for async initialization to complete.
- Create public/utils.js with shared frontend utility functions
- Extract parseUTCDate, getTimeAgo, getTimeRemaining, getRemainingClass to utils.js
- Remove duplicate functions from admin.js, app-mapbox.js, app-google.js, and app.js
- Add utils.js script import to index.html and admin.html
- Add comprehensive JSDoc documentation for all utility functions
- Ensure consistent UTC timestamp parsing across all frontend scripts
This addresses Copilot AI feedback about function duplication across multiple frontend scripts.
Now all timestamp and time calculation logic is centralized in one maintainable module.
Benefits:
- Single source of truth for time-related utilities
- Easier maintenance and updates
- Consistent behavior across all frontend components
- Better code organization and documentation
- Reduced bundle size through deduplication
- Add parseUTCDate helper function to handle timestamp UTC parsing consistently
- Eliminates code duplication across getTimeAgo, getTimeRemaining, and expiry functions
- Applied to admin.js, app-mapbox.js, app-google.js, and app.js
- Ensures consistent UTC timezone handling throughout all frontend JavaScript
- Addresses Copilot AI feedback for better code maintainability and DRY principles
The parseUTCDate function handles the logic:
timestamp.includes('T') ? timestamp : timestamp + 'Z'
This ensures all timestamp parsing uses the same UTC interpretation logic.
- Use :not(.back-link) selector to exclude back button from general link styling
- Add more specific CSS selectors for back-link to increase specificity
- Use both .privacy-content .back-link and a.back-link selectors
- Ensure white text color overrides the blue link color from general rules
- Prevent general link styling from interfering with button appearance
- Remove conflicting .back-link CSS rule that used undefined variables
- Consolidate all back-link styling into single comprehensive rule
- Add all necessary properties with !important to override conflicts
- Include display, margin, padding, border-radius for proper button appearance
- Ensure white text color on blue background for proper contrast
- Add font-weight and transition for better visual presentation
- Change back-link text color from blue to white for readability
- Remove text-decoration underline for cleaner button appearance
- Ensure white text shows clearly on blue button background
- Maintain white text color on hover for consistency
- Improve accessibility with proper color contrast ratio
- Add explicit link styling with proper color variables for readability
- Use !important declarations to override any conflicting inline styles
- Style all links in privacy-content and contact-info sections
- Add font-weight: 500 for better link visibility
- Fix back-link button with proper primary color styling
- Add CSS variables for primary colors in both light and dark themes
- Ensure links maintain proper contrast in both theme modes
- Change flexbox layout to relative positioning for header container
- Position theme toggle as absolute overlay in top-right corner
- Keep title and subtitle centered without interference from theme button
- Effective date now properly aligns with centered title text
- Theme toggle no longer displaces header text horizontally
- Add proper flexbox styling for .header-content to space items correctly
- Style .header-text with flex: 1 to take available space on left
- Position theme toggle button on the right side of header row
- Add responsive mobile layout that stacks header vertically
- Center header text and theme toggle on mobile devices
- Maintain proper spacing and visual hierarchy at all screen sizes
- Increase all typography scale by 2px for improved accessibility
- xs: 10px → 12px, sm: 12px → 14px, md: 14px → 16px
- lg: 16px → 18px, xl: 18px → 20px, xxl: 24px → 28px
- Set base body font-size to medium (16px) for default text
- All form inputs, buttons, tables, and content now more readable
- Maintains responsive design but with larger, more accessible text
- Increase footer font size from small to medium for better readability
- Ensure all footer text is properly centered including disclaimer
- Add explicit text-align: center and display: block for disclaimer small text
- Maintain responsive design with smaller font on mobile but still readable
- Update mobile disclaimer font size to small instead of extra small
- Add card styling to map-section with proper spacing and visual hierarchy
- Add reports-header with flexbox layout for title and view toggle buttons
- Add styling for view-toggle buttons, map-info, and table-controls
- Create shared footer component with consistent styling across pages
- Add footer to admin.html and privacy.html for consistency
- Add missing CSS variables for links, secondary text, and font-size-xs
- Ensure footer uses proper theme colors for light/dark modes
- Restore visual box around Current Reports section on main page
## Critical CSS Fixes
- ✅ Added missing index page styles (_index.scss) for main application
- ✅ Restored original CSS variables and color scheme compatibility
- ✅ Added comprehensive reports-table styles with proper cell formatting
- ✅ Fixed theme variables to match original design (updated colors)
- ✅ Added missing form, button, and layout components
## Enhanced Styles
- ✅ Proper table cell styling (.location-cell, .details-cell, .time-cell, .remaining-cell)
- ✅ Status indicators for urgent/warning/normal time remaining
- ✅ Enhanced responsive design for mobile tables
- ✅ Form and input styling consistency
- ✅ Theme toggle and header components
- ✅ Error/success message styling
## Architecture Improvements
- ✅ Modular imports: admin styles + index styles + shared components
- ✅ Better CSS variable organization with light/dark theme support
- ✅ Maintained backward compatibility with existing classes
- ✅ Compressed CSS output for production performance
The application now has full styling coverage with the new SCSS architecture.
## Major CSS/SCSS Improvements
- ✅ Set up modular SCSS architecture with variables, mixins, and components
- ✅ Created organized directory structure: src/scss/ with variables, mixins, pages/
- ✅ Removed ~300+ lines of inline CSS from admin.html
- ✅ Added comprehensive design system with consistent spacing, colors, typography
- ✅ Created reusable mixins for buttons, cards, tables, forms, and layouts
- ✅ Implemented responsive breakpoint mixins for mobile/tablet/desktop
- ✅ Added utility classes for common layouts and spacing
## Build System
- ✅ Added sass and concurrently as dev dependencies
- ✅ Created npm scripts: build-css, watch-css, dev-with-css
- ✅ Automated SCSS compilation to compressed CSS
- ✅ Set up development workflow with CSS watching
## Admin Panel Enhancements
- ✅ Added complete tab navigation system (Location Reports + Profanity Filter)
- ✅ Integrated profanity management UI with forms and tables
- ✅ Consistent styling across all components using SCSS mixins
- ✅ Improved responsive design for mobile devices
## Benefits
- 🎯 Maintainable: All styles centralized in modular SCSS files
- 📱 Responsive: Better mobile experience with consistent breakpoints
- 🎨 Consistent: Design system ensures visual consistency
- ⚡ Efficient: Compressed CSS output, no inline styles
- 🔧 Developer-friendly: Easy to extend and modify styles
The application now has professional-grade CSS architecture that's easy to maintain and extend.
- Fixed getTimeAgo(), getTimeRemaining(), and getRemainingClass() functions
- Database stores UTC timestamps but frontend was treating them as local time
- Added logic to append 'Z' to timestamps without timezone info to force UTC interpretation
- Now properly shows 48-hour countdown instead of incorrect 52-hour or 28-hour values
- Affects both main app (app-mapbox.js) and admin panel (admin.js)
- Updated getTimeRemaining() function to use 48 hours instead of 24 hours
- Updated getRemainingClass() function to calculate remaining time based on 48 hours
- Frontend now matches backend 48-hour expiration policy
- Time remaining display will now show up to ~47h instead of ~23h for new reports
- Corrected API endpoint URLs from /api/admin/profanity/words to /api/admin/profanity-words
- Fixed profanity test endpoint from /api/admin/profanity/test to /api/admin/test-profanity
- Updated data handling to match actual API response format
- Fixed profanity test results display to match API analysis structure
- All CRUD operations for profanity words now working correctly
- Added tab-based admin interface with separate Profanity Filter tab
- Implemented custom word management (add/delete words with severity levels)
- Added profanity filter testing interface for real-time validation
- Integrated with profanity database API endpoints
- Added comprehensive CSS styling for new UI components
- Full admin interface for managing custom profanity words and categories
- Create dedicated ProfanityFilter class with isolated SQLite database
- Separate profanity.db from main application database to prevent SQLITE_MISUSE errors
- Add comprehensive custom word management (CRUD operations)
- Implement advanced profanity detection with leetspeak and pattern matching
- Add admin UI for managing custom profanity words
- Add extensive test suites for both profanity filter and API routes
- Update server.js to use isolated profanity filter
- Add proper database initialization and cleanup methods
- Support in-memory databases for testing
Breaking changes:
- Profanity filter now uses separate database file
- Updated admin API endpoints for profanity management
- Enhanced profanity detection capabilities
- Add dark mode overrides for table cell text colors to ensure visibility
- Remove Google Maps API key exposure from /api/config endpoint (security fix)
- Update privacy policy to clarify international server hosting
- Switch from CDN resources to local files for better control
- Add SCSS build system for future styling improvements
Applied the exact same selector pattern as admin table:
- .reports-table th, .reports-table td { color: var(--text-color); }
This ensures both header and data cells explicitly inherit the correct
text color variable, matching the admin table behavior exactly.
Should resolve the white text visibility issue in dark mode.
Updated reports table to use the same robust styling as admin table:
✅ Added:
- border-radius: 8px and overflow: hidden for rounded corners
- box-shadow: 0 2px 4px var(--shadow) for elevation
- color: var(--text-color) on table element for inheritance
- Consistent border styling with 1px borders
- font-weight: bold for headers (matching admin)
✅ Improved:
- Better dark mode support with proper color inheritance
- Consistent visual appearance between admin and public tables
- Removed duplicate box-shadow from table-container
- Simplified header borders (removed 2px, sticky positioning complexity)
Both tables now share the same visual design language and dark mode behavior.