diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..6313b56c --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/changelogs/1.3.0.md b/changelogs/1.3.0.md new file mode 100644 index 00000000..1bdb9aa6 --- /dev/null +++ b/changelogs/1.3.0.md @@ -0,0 +1,115 @@ +# Release Notes – v1.3.0 (2026-03-19) + +## Overview + +v1.3.0 focuses on the settings experience, notification delivery controls, clearer overview charts, and a broad cleanup of shared helpers and notification flows. It also improves demo seed data so mileage and cost trends look more realistic over time. + +## Major Features + +### Settings UX Improvements + +- Expanded all settings accordions by default for quicker access +- Made settings forms more responsive with two- and three-column layouts where space allows +- Added a compact switch-based style for feature flags +- Updated notification provider forms to default new providers to enabled +- Simplified channel subscription controls in the provider dialog +- Extracted reusable settings sections, field helpers, and display blocks +- Reused shared tab shell and form composition patterns in settings + +### Notification Delivery Controls + +- Added a toggle to enable or disable scheduled notification delivery +- Kept the delivery schedule tied to the notification settings state +- Disabled schedule inputs automatically when scheduling is turned off +- Added webhook and Gotify providers alongside email +- Improved provider toggling, cron scheduling, and notification send templates +- Allowed editing providers without exposing keys/tokens + +### Overview Charts + +- Added an average reference line to mileage and cost graphs +- Displayed the average as a top-right label with unit-aware formatting +- Formatted tooltip values with the correct units for mileage and currency +- Added a unit-aware average formatter for chart tooltips and labels +- Improved the chart presentation with clearer dashed average lines + +### Demo Seed Data + +- Updated seeded mileage values to progress more naturally over time +- Added small mileage deviations and realistic fuel cost variation +- Made the overall seed data better reflect real-world usage patterns +- Refined seeded notifications and maintenance history for more natural trends + +## Configuration Changes + +- Added `notificationProcessingEnabled` to control scheduled notification delivery +- Kept `notificationProcessingSchedule` as the cron expression for delivery timing +- Added default config values for LPG and CNG fuel units +- Preserved mileage unit format settings for distance-per-fuel and fuel-per-distance +- Expanded settings schema and defaults for feature flags and notification delivery +- Updated chart formatting helpers to support unit-aware mileage and currency display +- Added shared config handling and merge helpers for notification provider settings +- Seeded the new config entries automatically for demo setups + +## Environment/Runtime Changes + +- Demo seeding now generates more realistic mileage and cost trends +- Notification scheduler respects the new enabled/disabled config state +- Overview charts now format tooltip and average values using app units +- The app now keeps chart and settings formatting aligned with the active locale/config + +## UI/UX Improvements + +- Compact provider channel subscriptions in the add/edit provider dialog +- Better chart labeling and readability in the overview section +- More consistent settings layout across personalization, units, and feature flags +- Better mobile behavior and tighter spacing across settings and dialogs +- Improved loading skeletons and shared record card layouts across the UI + +## Architecture & Shared Helpers + +- Consolidated route error helpers and standardized backend service responses +- Added typed payload helpers for domain and service layers +- Reduced shared store and form `any` usage +- Extracted reusable table, skeleton, and formatter helpers +- Reused shared resource state and feature card layouts across the UI +- Improved notification provider config merge and service date helpers +- Added helper reuse across vehicle, fuel, maintenance, insurance, and reminders + +## Localization & Messaging + +- Continued moving hardcoded UI text into i18n message functions +- Added or refined translated messages for settings, notifications, and charts +- Improved localized labels across dashboard, forms, and notifications + +## Developer Experience + +- Added MCP support for the repo's Svelte workflow +- Upgraded dependencies and fixed follow-up lint/check issues +- Cleaned up formatting, typing, and shared abstractions across the codebase + +## Bug Fixes & Improvements + +- Fixed reactive binding issues in settings forms so inputs update correctly +- Fixed notification delivery scheduling state so it no longer re-enables unexpectedly after save +- Improved unit display for mileage and cost values in chart tooltips and labels +- Fixed settings accordions to stay expanded by default +- Fixed provider add/edit flow to keep new providers enabled by default +- Fixed fuel and maintenance sorting when records share dates +- Fixed NaN-prone calculations and lint issues carried over from refactors + +## Migration Notes + +- No breaking changes were introduced +- Existing settings and data remain compatible + +## Environment Variables + +- No new environment variables were required for this release +- Existing runtime behavior continues to use the current app configuration and demo flags + +## Known Issues + +- None reported at release time + +For detailed commit history, see the [compare view](https://github.com/javedh-dev/tracktor/compare/v1.2.0...v1.3.0). diff --git a/messages/en.json b/messages/en.json index 6c4e825c..c7536046 100644 --- a/messages/en.json +++ b/messages/en.json @@ -45,6 +45,7 @@ "settings_desc_mileage_format": "Choose how fuel efficiency is displayed", "settings_mileage_format_distance_per_fuel": "Distance per Fuel (e.g., km/L, mpg)", "settings_mileage_format_fuel_per_distance": "Fuel per Distance (e.g., L/100km)", + "settings_mileage_format_uk_mpg": "UK MPG (miles per imperial gallon)", "settings_desc_theme": "Choose your preferred theme", "settings_desc_custom_css": "CSS Styles for customizing the interface", "settings_select_language": "Select language", diff --git a/messages/fi.json b/messages/fi.json index 375c6b46..5333a127 100644 --- a/messages/fi.json +++ b/messages/fi.json @@ -3,6 +3,7 @@ "hello_world": "Hei, {name} fi:stä!", "app_name": "Tracktor", "app_title": "Autotallisi", + "app_new_update_available": "Uusi päivitys saatavilla. Ladataan uudelleen..!", "app_add_vehicle": "Lisää ajoneuvo", "app_empty_select_message": "Valitse ajoneuvo nähdäksesi sen yksityiskohdat", "app_empty_select_hint": "Valitse ajoneuvo nähdäksesi sen kojelaudan", @@ -79,7 +80,6 @@ "nav_insurance": "Vakuutus", "nav_pollution": "Päästöt", "nav_reminders": "Muistutukset", - "nav_settings": "Asetukset", "tools_export_data": "Vie data", "tools_import_data": "Tuo data", "vehicle_form_make_label": "Valmistaja", @@ -163,7 +163,7 @@ "fuel_add_title": "Lisää tankkaus", "col_date": "Päivämäärä", "col_odometer": "Matkamittari", - "col_filled": "Täytetty", + "col_filled": "Täysi tankki", "col_missed_last": "Edellinen ohitettu", "col_fuel_amount": "Polttoainemäärä", "col_cost": "Kustannus", @@ -204,6 +204,8 @@ "notifications_section_alerts": "Hälytykset", "notifications_mark_done_title": "Merkitse muistutus valmiiksi", "notifications_mark_done_aria": "Merkitse {type} muistutus valmiiksi", + "notifications_mark_all_read_title": "Merkitse kaikki luetuiksi", + "notifications_mark_all_read_aria": "Merkitse kaikki ilmoitukset luetuiksi", "notifications_overdue_days": "{days} päivää myöhässä", "notifications_due_today": "Määräaika tänään", "notifications_due_tomorrow": "Määräaika huomenna", @@ -449,5 +451,104 @@ "pollution_recurrence_type_fixed": "Kiinteä päättymispäivä", "pollution_recurrence_type_yearly": "Uusiutuu vuosittain", "pollution_recurrence_type_monthly": "Uusiutuu kuukausittain", - "pollution_recurrence_type_no_end": "Ei päättymispäivämäärää" + "pollution_recurrence_type_no_end": "Ei päättymispäivämäärää", + "file_drop_existing_note": "Liitetiedosto (Napauta nähdäksesi)", + "fuel_import_step_1_title": "Vaihe 1 : Lataa CSV tiedosto", + "fuel_import_step_1_desc": "Valitse erotinmerkkiä käyttävä tekstitiedosto, joka sisältää polttoaineen kulutustietosi, aloittaaksesi tuontiprosessin", + "fuel_import_drop_placeholder": "Liitä erotinmerkillinen teksti tai napauta selataksesi", + "fuel_import_headers_checkbox": "Ensimmäinen rivi sisältää otsikot", + "fuel_import_delimiter_title": "Erotin", + "fuel_import_delimiter_desc": "Valitse merkki, joka erottaa kentät", + "fuel_import_date_format_title": "Päivämäärän muoto", + "fuel_import_date_format_desc": "Määritä CSV-tiedostosi päivämäärille käytettävä muoto.", + "fuel_import_error_no_headers": "Otsikoita ei havaittu. Päivitä csv.helper.ts palauttaaksesi otsikot.", + "fuel_import_step_2_title": "Vaihe 2 : CSV-sarakkeiden kartoitus", + "fuel_import_step_2_desc": "Määritä CSV-tiedostosi sarakkeet vastaaviin polttoainelokin kenttiin. Pakolliset kentät on merkitty merkinnällä *.", + "fuel_import_step_3_title": "Vaihe 3 : Esikatsele ja tuo", + "fuel_import_step_3_desc": "Tarkista tuotavat tiedot esikatselusta.", + "fuel_import_no_preview": "Ei esikatseltavaa tietoa vielä. Toteuta jäsentely csv.helper.ts-tiedostossa rivien täyttämiseksi.", + "fuel_import_success": "Tuotu onnistuneesti {count} polttoainelokia.", + "fuel_import_failed_count": "Tuotu {imported}, epäonnistui {failed}", + "fuel_import_error_generic": "Polttoainelokin tuonti epäonnistui.", + "fuel_import_vehicle_label": "Ajoneuvo:", + "fuel_import_delimiter_comma": "Pilkku ( , )", + "fuel_import_delimiter_semicolon": "Puolipiste ( ; )", + "fuel_import_delimiter_tab": "Sarkain ( \\t )", + "fuel_import_delimiter_pipe": "Pystyviiva ( | )", + "fuel_import_delimiter_custom": "Muokattu", + "fuel_import_date_error": "Jotkin rivit sisältävät virheellisesti muotoiltuja päivämääriä \"{format}\"", + "fuel_import_date_format_placeholder": "esim., MM/DD/YYYY", + "fuel_import_date_invalid": "Virheellinen päivämäärä", + "fuel_import_no_vehicle": "Ajoneuvoa ei valittu", + "fuel_import_col_date_hint": "Tankkauspäivämäärä", + "fuel_import_col_odometer_hint": "Mittarilukema tankkaushetkellä", + "fuel_import_col_fuel_hint": "Tankattu määrä tai energia", + "fuel_import_col_cost_hint": "Kokonaiskustannus", + "fuel_import_col_filled_hint": "Onko tämä täysi tankki/lataus?", + "fuel_import_col_missed_hint": "Jäikö edellinen merkintä väliin?", + "fuel_import_col_notes_hint": "Lisätietoja", + "autocomplete_placeholder": "Kirjoita tai valitse...", + "autocomplete_loading": "Ladataan ehdotuksia...", + "autocomplete_no_results": "Ehdotuksia ei löydy. Voit kirjoittaa uuden arvon.", + "input_date_placeholder": "Valitse päivämäärä", + "loading_default_message": "Ladataan...", + "dropzone_placeholder_image": "Napauta tai vedä kuva ladataksesi", + "dropzone_placeholder_attachment": "Pudota kuva tänne tai napauta valitaksesi", + "dropzone_placeholder_default": "Napauta tai vedä tiedostoja ladataksesi", + "dropzone_error_single_file": "Lataa vain yksi tiedosto.", + "dropzone_error_file_size": "Tiedoston koko ylittää sallitun enimmäiskoon {size}.", + "dropzone_unknown_file": "Tuntematon tiedosto", + "dropzone_uploading": "Ladataan...", + "dropzone_supports": "Tuettu: {types}", + "dropzone_max_size": "Enimmäiskoko: {size}", + "dropzone_error_file_type": "Tiedoston tyyppi ei ole tuettu", + "dropzone_hint_accept_limit": "{types} enintään {size}", + "vehicle_details_color_aria": "Väri", + "vehicle_details_close_aria": "Sulje", + "attachment_link_view_title": "Näytä liite", + "file_preview_not_available": "Esikatselu ei ole saatavilla", + "file_preview_download_hint": "Tätä tiedostotyyppiä ei voi esikatsella suoraan. Lataa tiedosto tarkastellaksesi sitä.", + "file_preview_download_button": "Lataa tiedosto", + "file_preview_aria_download": "Lataa", + "file_preview_aria_close": "Sulje", + "theme_toggle_label": "Vaihda teemaa", + "fuel_log_edit": "Muokkaa", + "fuel_log_delete": "Poista", + "fuel_log_menu_open": "Avaa valikko", + "fuel_log_delete_success": "Poistetut polttoainelokimerkinnät", + "fuel_log_menu_sheet_title": "Päivitä polttoainelokimerkintä", + "fuel_log_delete_error": "Polttoainelokimerkinnän poistamisessa tapahtui virhe", + "color_picker_label": "Valitse väri", + "reminder_type_maintenance": "Huolto", + "reminder_type_insurance": "Vakuutuksen uusiminen", + "reminder_type_pollution": "Päästömittaus / katsastus", + "reminder_type_registration": "Rekisteröinti / ajoneuvovero", + "reminder_type_inspection": "Katsastus", + "reminder_type_custom": "Custom", + "alert_type_insurance": "Vakuutus", + "alert_type_pucc": "Päästötodistus", + "alert_status_expired_ago": "{label} vanheni {days} päivää sitten", + "alert_status_expires_in": "{label} vanhenee {days} päivässä", + "alert_status_valid_for": "{label} voimassa {days} päivää", + "alert_insurance_active_no_end": "Vakuutus on voimassa toistaiseksi", + "alert_pucc_active_no_end": "Päästötodistus on voimassa toistaiseksi", + "alert_record_not_found": "{label}-tietoja ei löydy. Lisää tiedot pysyäksesi vaatimusten mukaisena.", + "settings_error_format_not_valid": "Virheellinen muoto", + "common_kilogram_unit": "Kilogrammaa (kg)", + "common_pound_unit": "Paunaa (lb)", + "settings_section_fuel_types": "Polttoaineen tyyppi", + "settings_section_fuel_types_desc": "Valitse mittayksikkö kullekin polttoaineelle.", + "fuel_type_petrol_diesel": "Bensiini/Diesel", + "theme_slate": "Liuskekivi", + "theme_stone": "Kivi", + "theme_red": "Punainen", + "theme_rose": "Ruusu", + "theme_blue": "Sininen", + "theme_green": "Vihreä", + "theme_purple": "Violetti", + "theme_orange": "Oranssi", + "theme_yellow": "Keltainen", + "theme_teal": "Sinivihreä", + "theme_indigo": "Indigo", + "theme_pink": "Vaaleanpunainen" } diff --git a/messages/hu.json b/messages/hu.json index 35bfd08e..ed2722cc 100644 --- a/messages/hu.json +++ b/messages/hu.json @@ -205,6 +205,8 @@ "notifications_section_alerts": "Riasztások", "notifications_mark_done_title": "Emlékeztető megjelölése készként", "notifications_mark_done_aria": "{type} emlékeztető megjelölése készként", + "notifications_mark_all_read_title": "Az összes megjelölése olvasottként", + "notifications_mark_all_read_aria": "Összes értesítés megjelölése olvasottként", "notifications_overdue_days": "{days} napja lejárt", "notifications_due_today": "Ma esedékes", "notifications_due_tomorrow": "Holnap esedékes", diff --git a/src/lib/components/feature/settings/SettingsModal.svelte b/src/lib/components/feature/settings/SettingsModal.svelte index 9cbd4ec1..7ca53d7f 100644 --- a/src/lib/components/feature/settings/SettingsModal.svelte +++ b/src/lib/components/feature/settings/SettingsModal.svelte @@ -50,7 +50,7 @@ unitOfLpg: z.enum(['liter', 'gallon', 'kilogram', 'pound']).default('liter'), unitOfCng: z.enum(['liter', 'gallon', 'kilogram', 'pound']).default('kilogram'), mileageUnitFormat: z - .enum(['distance-per-fuel', 'fuel-per-distance']) + .enum(['distance-per-fuel', 'fuel-per-distance', 'uk-mpg']) .default('distance-per-fuel'), theme: z.string().default('light'), customCss: z.string().optional(), @@ -177,6 +177,10 @@ { value: 'fuel-per-distance', label: m.settings_mileage_format_fuel_per_distance() + }, + { + value: 'uk-mpg', + label: m.settings_mileage_format_uk_mpg() } ]; diff --git a/src/lib/components/feature/settings/SettingsPersonalizationTab.svelte b/src/lib/components/feature/settings/SettingsPersonalizationTab.svelte index da4127e9..e7fe2ed5 100644 --- a/src/lib/components/feature/settings/SettingsPersonalizationTab.svelte +++ b/src/lib/components/feature/settings/SettingsPersonalizationTab.svelte @@ -105,7 +105,7 @@ />