diff --git a/CHANGELOG.md b/CHANGELOG.md index b0f83ae..547dc0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.41.0] - 2026-05-01 + +### Added +- **Birthday badge**: the birthdays nav item now shows a badge when any family member has a birthday within the next 3 days. +- **Recent filter chips**: the task filter bar now shows up to three recently used filters as quick-access chips, persisted in `localStorage`. +- **Calendar icon search**: the event icon picker now includes a live search field to quickly find icons by keyword, with results grouped by category. +- **Calendar icon categories**: event icons are now organised into labelled category groups (transport, sports, health, nature, leisure, social, work, home, food, other). +- **Repeat indicator on calendar events**: events with a recurrence rule now display a small repeat icon in both month and week views. +- **3-day week view on mobile**: the calendar week view automatically switches to a 3-day window on screens narrower than 640 px for better readability. +- **Widget size presets**: the dashboard widget size selector uses named presets (Tiny, Narrow, Standard, Large, Full) instead of raw grid dimension values. + +### Changed +- **Required-field markers**: title fields in the task, event, and budget modals now show a required-field asterisk via the `.required-marker` CSS class. +- **Modal drag handle touch target**: the bottom-sheet drag handle has a 44 px tall invisible hit area so it can be grabbed comfortably. +- **Swipe affordance**: list rows with swipe actions show a subtle chevron hint to signal the gesture. +- **Budget tab height**: budget tab buttons have a minimum height of 40 px to meet touch-target requirements. + ## [0.40.1] - 2026-05-01 ### Changed diff --git a/package-lock.json b/package-lock.json index 687f85f..29af6bb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "oikos", - "version": "0.40.1", + "version": "0.41.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "oikos", - "version": "0.40.1", + "version": "0.41.0", "license": "MIT", "dependencies": { "bcrypt": "^6.0.0", diff --git a/package.json b/package.json index add1ae5..62efd59 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "oikos", - "version": "0.40.1", + "version": "0.41.0", "description": "Self-hosted family planner - calendar, tasks, shopping, meal planning, budget and more. Private, open-source, no subscription.", "main": "server/index.js", "type": "module", diff --git a/public/locales/ar.json b/public/locales/ar.json index ff71833..fd472ae 100644 --- a/public/locales/ar.json +++ b/public/locales/ar.json @@ -118,7 +118,12 @@ "customizeDrag": "اسحب الأداة", "customizeSize": "الحجم", "customizeSizeFor": "حجم {{widget}}", - "customizeHide": "إخفاء {{widget}}" + "customizeHide": "إخفاء {{widget}}", + "widgetSizeTiny": "صغير (1×1)", + "widgetSizeNarrow": "ضيق (2×1)", + "widgetSizeStandard": "قياسي (2×2)", + "widgetSizeLarge": "كبير (3×2)", + "widgetSizeFull": "كامل (4×2)" }, "tasks": { "title": "المهام", @@ -374,6 +379,91 @@ "resetToast": "تم إعادة تعيين التغييرات." }, "iconLabel": "Icon", + "iconSearchPlaceholder": "البحث عن أيقونة...", + "iconSearchEmpty": "لم يتم العثور على أيقونة.", + "iconCategoryGeneral": "عام", + "iconCategoryHealth": "الصحة والرياضة", + "iconCategoryTransport": "التنقل والسفر", + "iconCategoryWork": "العمل والتعليم", + "iconCategoryFood": "الطعام والشراب", + "iconCategoryShopping": "التسوق والمالية", + "iconCategoryLeisure": "الترفيه والتسلية", + "iconCategoryFamily": "العائلة والحيوانات الأليفة", + "iconCategoryHome": "المنزل والأسرة", + "iconCategoryNature": "الطبيعة وغير ذلك", + "iconCalendar": "التقويم", + "iconAlarm": "المنبّه", + "iconClock": "الساعة", + "iconBell": "تذكير", + "iconLocation": "الموقع", + "iconStar": "المفضلة", + "iconFlag": "علم", + "iconTarget": "هدف", + "iconFlame": "مهم", + "iconTooth": "طبيب الأسنان", + "iconHospital": "المستشفى", + "iconDoctor": "طبيب", + "iconVaccine": "تطعيم", + "iconMedicine": "دواء", + "iconBandage": "ضمادة", + "iconHealth": "صحة", + "iconActivity": "نشاط", + "iconHaircut": "صالون الحلاقة", + "iconSports": "رياضة", + "iconTrophy": "مسابقة", + "iconCar": "سيارة", + "iconBus": "حافلة", + "iconTrain": "قطار", + "iconPlane": "سفر", + "iconFlight": "رحلة جوية", + "iconFuel": "تزوّد بالوقود", + "iconNavigation": "ملاحة", + "iconWork": "عمل", + "iconLaptop": "حاسوب محمول", + "iconPresentation": "عرض تقديمي", + "iconSchool": "مدرسة", + "iconEducation": "تعليم", + "iconReading": "قراءة", + "iconStudy": "دراسة", + "iconCalculator": "آلة حاسبة", + "iconMeal": "وجبة", + "iconCooking": "طبخ", + "iconCoffee": "قهوة", + "iconCake": "عيد الميلاد", + "iconPizza": "بيتزا", + "iconWine": "نبيذ", + "iconBeer": "بار", + "iconShopping": "تسوق", + "iconGroceries": "بقالة", + "iconGift": "هدية", + "iconCard": "بطاقة", + "iconWallet": "محفظة", + "iconSavings": "ادخار", + "iconBank": "بنك", + "iconMusic": "موسيقى", + "iconMovie": "فيلم", + "iconTicket": "تذكرة", + "iconGame": "لعبة", + "iconPhoto": "صورة", + "iconParty": "حفلة", + "iconFamily": "عائلة", + "iconBaby": "طفل رضيع", + "iconDog": "كلب", + "iconCat": "قطة", + "iconPet": "حيوان أليف", + "iconHome": "منزل", + "iconBuilding": "مبنى", + "iconRepair": "إصلاح", + "iconMaintenance": "صيانة", + "iconDecoration": "ديكور", + "iconFurniture": "أثاث", + "iconLaundry": "غسيل", + "iconLeaf": "طبيعة", + "iconTree": "شجرة", + "iconFlower": "زهرة", + "iconSun": "نهار", + "iconMoon": "ليل", + "iconWeather": "طقس", "invalidDate": "Use a valid date in the selected date format.", "attachmentLabel": "Attachment", "attachmentHint": "Attach a local image, PDF, or document. Images will be shown in the event popup.", diff --git a/public/locales/de.json b/public/locales/de.json index 661f0c0..f16b1b1 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -124,7 +124,12 @@ "customizeDrag": "Widget ziehen", "customizeSize": "Größe", "customizeSizeFor": "Größe für {{widget}}", - "customizeHide": "{{widget}} ausblenden" + "customizeHide": "{{widget}} ausblenden", + "widgetSizeTiny": "Klein (1×1)", + "widgetSizeNarrow": "Schmal (2×1)", + "widgetSizeStandard": "Standard (2×2)", + "widgetSizeLarge": "Groß (3×2)", + "widgetSizeFull": "Voll (4×2)" }, "tasks": { "title": "Aufgaben", @@ -390,6 +395,91 @@ "resetToast": "Änderungen zurückgesetzt." }, "iconLabel": "Icon", + "iconSearchPlaceholder": "Icon suchen...", + "iconSearchEmpty": "Kein Icon gefunden.", + "iconCategoryGeneral": "Allgemein", + "iconCategoryHealth": "Gesundheit & Sport", + "iconCategoryTransport": "Mobilität & Reise", + "iconCategoryWork": "Arbeit & Bildung", + "iconCategoryFood": "Essen & Trinken", + "iconCategoryShopping": "Einkaufen & Finanzen", + "iconCategoryLeisure": "Freizeit & Unterhaltung", + "iconCategoryFamily": "Familie & Haustiere", + "iconCategoryHome": "Zuhause & Haushalt", + "iconCategoryNature": "Natur & Sonstiges", + "iconCalendar": "Kalender", + "iconAlarm": "Alarm", + "iconClock": "Uhr", + "iconBell": "Erinnerung", + "iconLocation": "Ort", + "iconStar": "Favorit", + "iconFlag": "Flagge", + "iconTarget": "Ziel", + "iconFlame": "Wichtig", + "iconTooth": "Zahnarzt", + "iconHospital": "Krankenhaus", + "iconDoctor": "Arzt", + "iconVaccine": "Impfung", + "iconMedicine": "Medikament", + "iconBandage": "Verband", + "iconHealth": "Gesundheit", + "iconActivity": "Aktivität", + "iconHaircut": "Friseur", + "iconSports": "Sport", + "iconTrophy": "Wettbewerb", + "iconCar": "Auto", + "iconBus": "Bus", + "iconTrain": "Zug", + "iconPlane": "Reise", + "iconFlight": "Flug", + "iconFuel": "Tanken", + "iconNavigation": "Navigation", + "iconWork": "Arbeit", + "iconLaptop": "Laptop", + "iconPresentation": "Präsentation", + "iconSchool": "Schule", + "iconEducation": "Bildung", + "iconReading": "Lesen", + "iconStudy": "Lernen", + "iconCalculator": "Rechner", + "iconMeal": "Mahlzeit", + "iconCooking": "Kochen", + "iconCoffee": "Kaffee", + "iconCake": "Geburtstag", + "iconPizza": "Pizza", + "iconWine": "Wein", + "iconBeer": "Bar", + "iconShopping": "Einkaufen", + "iconGroceries": "Lebensmittel", + "iconGift": "Geschenk", + "iconCard": "Karte", + "iconWallet": "Geldbörse", + "iconSavings": "Sparen", + "iconBank": "Bank", + "iconMusic": "Musik", + "iconMovie": "Film", + "iconTicket": "Ticket", + "iconGame": "Spiel", + "iconPhoto": "Foto", + "iconParty": "Party", + "iconFamily": "Familie", + "iconBaby": "Baby", + "iconDog": "Hund", + "iconCat": "Katze", + "iconPet": "Haustier", + "iconHome": "Zuhause", + "iconBuilding": "Gebäude", + "iconRepair": "Reparatur", + "iconMaintenance": "Wartung", + "iconDecoration": "Dekoration", + "iconFurniture": "Möbel", + "iconLaundry": "Wäsche", + "iconLeaf": "Natur", + "iconTree": "Baum", + "iconFlower": "Blume", + "iconSun": "Tag", + "iconMoon": "Nacht", + "iconWeather": "Wetter", "invalidDate": "Bitte ein gültiges Datum im ausgewählten Format verwenden.", "attachmentLabel": "Anhang", "attachmentHint": "Lokales Bild, PDF oder Dokument anhängen. Bilder werden im Ereignis-Popup angezeigt.", diff --git a/public/locales/el.json b/public/locales/el.json index a6a3ad4..84b67a6 100644 --- a/public/locales/el.json +++ b/public/locales/el.json @@ -118,7 +118,12 @@ "customizeDrag": "Σύρετε widget", "customizeSize": "Μέγεθος", "customizeSizeFor": "Μέγεθος για {{widget}}", - "customizeHide": "Απόκρυψη {{widget}}" + "customizeHide": "Απόκρυψη {{widget}}", + "widgetSizeTiny": "Μικρό (1×1)", + "widgetSizeNarrow": "Στενό (2×1)", + "widgetSizeStandard": "Τυπικό (2×2)", + "widgetSizeLarge": "Μεγάλο (3×2)", + "widgetSizeFull": "Πλήρες (4×2)" }, "tasks": { "title": "Εργασίες", @@ -374,6 +379,91 @@ "resetToast": "Οι αλλαγές επαναφέρθηκαν." }, "iconLabel": "Icon", + "iconSearchPlaceholder": "Αναζήτηση εικονιδίου...", + "iconSearchEmpty": "Δεν βρέθηκε εικονίδιο.", + "iconCategoryGeneral": "Γενικά", + "iconCategoryHealth": "Υγεία & Αθλητισμός", + "iconCategoryTransport": "Μετακίνηση & Ταξίδι", + "iconCategoryWork": "Εργασία & Εκπαίδευση", + "iconCategoryFood": "Φαγητό & Ποτό", + "iconCategoryShopping": "Αγορές & Οικονομικά", + "iconCategoryLeisure": "Αναψυχή & Ψυχαγωγία", + "iconCategoryFamily": "Οικογένεια & Κατοικίδια", + "iconCategoryHome": "Σπίτι & Νοικοκυριό", + "iconCategoryNature": "Φύση & Διάφορα", + "iconCalendar": "Ημερολόγιο", + "iconAlarm": "Ξυπνητήρι", + "iconClock": "Ρολόι", + "iconBell": "Υπενθύμιση", + "iconLocation": "Τοποθεσία", + "iconStar": "Αγαπημένο", + "iconFlag": "Σημαία", + "iconTarget": "Στόχος", + "iconFlame": "Σημαντικό", + "iconTooth": "Οδοντίατρος", + "iconHospital": "Νοσοκομείο", + "iconDoctor": "Γιατρός", + "iconVaccine": "Εμβόλιο", + "iconMedicine": "Φάρμακο", + "iconBandage": "Επίδεσμος", + "iconHealth": "Υγεία", + "iconActivity": "Δραστηριότητα", + "iconHaircut": "Κομμωτήριο", + "iconSports": "Αθλητισμός", + "iconTrophy": "Διαγωνισμός", + "iconCar": "Αυτοκίνητο", + "iconBus": "Λεωφορείο", + "iconTrain": "Τρένο", + "iconPlane": "Ταξίδι", + "iconFlight": "Πτήση", + "iconFuel": "Ανεφοδιασμός", + "iconNavigation": "Πλοήγηση", + "iconWork": "Εργασία", + "iconLaptop": "Φορητός υπολογιστής", + "iconPresentation": "Παρουσίαση", + "iconSchool": "Σχολείο", + "iconEducation": "Εκπαίδευση", + "iconReading": "Ανάγνωση", + "iconStudy": "Μελέτη", + "iconCalculator": "Αριθμομηχανή", + "iconMeal": "Γεύμα", + "iconCooking": "Μαγείρεμα", + "iconCoffee": "Καφές", + "iconCake": "Γενέθλια", + "iconPizza": "Πίτσα", + "iconWine": "Κρασί", + "iconBeer": "Μπαρ", + "iconShopping": "Αγορές", + "iconGroceries": "Τρόφιμα", + "iconGift": "Δώρο", + "iconCard": "Κάρτα", + "iconWallet": "Πορτοφόλι", + "iconSavings": "Αποταμίευση", + "iconBank": "Τράπεζα", + "iconMusic": "Μουσική", + "iconMovie": "Ταινία", + "iconTicket": "Εισιτήριο", + "iconGame": "Παιχνίδι", + "iconPhoto": "Φωτογραφία", + "iconParty": "Πάρτι", + "iconFamily": "Οικογένεια", + "iconBaby": "Μωρό", + "iconDog": "Σκύλος", + "iconCat": "Γάτα", + "iconPet": "Κατοικίδιο", + "iconHome": "Σπίτι", + "iconBuilding": "Κτίριο", + "iconRepair": "Επισκευή", + "iconMaintenance": "Συντήρηση", + "iconDecoration": "Διακόσμηση", + "iconFurniture": "Έπιπλα", + "iconLaundry": "Πλυντήριο", + "iconLeaf": "Φύση", + "iconTree": "Δέντρο", + "iconFlower": "Λουλούδι", + "iconSun": "Μέρα", + "iconMoon": "Νύχτα", + "iconWeather": "Καιρός", "invalidDate": "Use a valid date in the selected date format.", "attachmentLabel": "Attachment", "attachmentHint": "Attach a local image, PDF, or document. Images will be shown in the event popup.", diff --git a/public/locales/en.json b/public/locales/en.json index 764229c..ffff38e 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -118,7 +118,12 @@ "customizeDrag": "Drag widget", "customizeSize": "Size", "customizeSizeFor": "Size for {{widget}}", - "customizeHide": "Hide {{widget}}" + "customizeHide": "Hide {{widget}}", + "widgetSizeTiny": "Small (1×1)", + "widgetSizeNarrow": "Narrow (2×1)", + "widgetSizeStandard": "Standard (2×2)", + "widgetSizeLarge": "Large (3×2)", + "widgetSizeFull": "Full (4×2)" }, "tasks": { "title": "Tasks", @@ -374,6 +379,91 @@ "resetToast": "Changes reset." }, "iconLabel": "Icon", + "iconSearchPlaceholder": "Search icon...", + "iconSearchEmpty": "No icon found.", + "iconCategoryGeneral": "General", + "iconCategoryHealth": "Health & Sports", + "iconCategoryTransport": "Mobility & Travel", + "iconCategoryWork": "Work & Education", + "iconCategoryFood": "Food & Drinks", + "iconCategoryShopping": "Shopping & Finance", + "iconCategoryLeisure": "Leisure & Entertainment", + "iconCategoryFamily": "Family & Pets", + "iconCategoryHome": "Home & Household", + "iconCategoryNature": "Nature & Miscellaneous", + "iconCalendar": "Calendar", + "iconAlarm": "Alarm", + "iconClock": "Clock", + "iconBell": "Reminder", + "iconLocation": "Location", + "iconStar": "Favorite", + "iconFlag": "Flag", + "iconTarget": "Goal", + "iconFlame": "Important", + "iconTooth": "Dentist", + "iconHospital": "Hospital", + "iconDoctor": "Doctor", + "iconVaccine": "Vaccination", + "iconMedicine": "Medicine", + "iconBandage": "Bandage", + "iconHealth": "Health", + "iconActivity": "Activity", + "iconHaircut": "Hairdresser", + "iconSports": "Sports", + "iconTrophy": "Competition", + "iconCar": "Car", + "iconBus": "Bus", + "iconTrain": "Train", + "iconPlane": "Travel", + "iconFlight": "Flight", + "iconFuel": "Refuel", + "iconNavigation": "Navigation", + "iconWork": "Work", + "iconLaptop": "Laptop", + "iconPresentation": "Presentation", + "iconSchool": "School", + "iconEducation": "Education", + "iconReading": "Reading", + "iconStudy": "Study", + "iconCalculator": "Calculator", + "iconMeal": "Meal", + "iconCooking": "Cooking", + "iconCoffee": "Coffee", + "iconCake": "Birthday", + "iconPizza": "Pizza", + "iconWine": "Wine", + "iconBeer": "Bar", + "iconShopping": "Shopping", + "iconGroceries": "Groceries", + "iconGift": "Gift", + "iconCard": "Card", + "iconWallet": "Wallet", + "iconSavings": "Savings", + "iconBank": "Bank", + "iconMusic": "Music", + "iconMovie": "Movie", + "iconTicket": "Ticket", + "iconGame": "Game", + "iconPhoto": "Photo", + "iconParty": "Party", + "iconFamily": "Family", + "iconBaby": "Baby", + "iconDog": "Dog", + "iconCat": "Cat", + "iconPet": "Pet", + "iconHome": "Home", + "iconBuilding": "Building", + "iconRepair": "Repair", + "iconMaintenance": "Maintenance", + "iconDecoration": "Decoration", + "iconFurniture": "Furniture", + "iconLaundry": "Laundry", + "iconLeaf": "Nature", + "iconTree": "Tree", + "iconFlower": "Flower", + "iconSun": "Day", + "iconMoon": "Night", + "iconWeather": "Weather", "invalidDate": "Use a valid date in the selected date format.", "attachmentLabel": "Attachment", "attachmentHint": "Attach a local image, PDF, or document. Images will be shown in the event popup.", diff --git a/public/locales/es.json b/public/locales/es.json index 126c08a..30fee5a 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -118,7 +118,12 @@ "customizeDrag": "Arrastrar widget", "customizeSize": "Tamaño", "customizeSizeFor": "Tamaño de {{widget}}", - "customizeHide": "Ocultar {{widget}}" + "customizeHide": "Ocultar {{widget}}", + "widgetSizeTiny": "Pequeño (1×1)", + "widgetSizeNarrow": "Estrecho (2×1)", + "widgetSizeStandard": "Estándar (2×2)", + "widgetSizeLarge": "Grande (3×2)", + "widgetSizeFull": "Completo (4×2)" }, "tasks": { "title": "Tareas", @@ -374,6 +379,91 @@ "resetToast": "Cambios restablecidos." }, "iconLabel": "Icon", + "iconSearchPlaceholder": "Buscar icono...", + "iconSearchEmpty": "No se encontró ningún icono.", + "iconCategoryGeneral": "General", + "iconCategoryHealth": "Salud y Deporte", + "iconCategoryTransport": "Movilidad y Viaje", + "iconCategoryWork": "Trabajo y Educación", + "iconCategoryFood": "Comida y Bebida", + "iconCategoryShopping": "Compras y Finanzas", + "iconCategoryLeisure": "Ocio y Entretenimiento", + "iconCategoryFamily": "Familia y Mascotas", + "iconCategoryHome": "Hogar y Casa", + "iconCategoryNature": "Naturaleza y Otros", + "iconCalendar": "Calendario", + "iconAlarm": "Alarma", + "iconClock": "Reloj", + "iconBell": "Recordatorio", + "iconLocation": "Ubicación", + "iconStar": "Favorito", + "iconFlag": "Bandera", + "iconTarget": "Meta", + "iconFlame": "Importante", + "iconTooth": "Dentista", + "iconHospital": "Hospital", + "iconDoctor": "Médico", + "iconVaccine": "Vacuna", + "iconMedicine": "Medicamento", + "iconBandage": "Vendaje", + "iconHealth": "Salud", + "iconActivity": "Actividad", + "iconHaircut": "Peluquería", + "iconSports": "Deporte", + "iconTrophy": "Competición", + "iconCar": "Coche", + "iconBus": "Autobús", + "iconTrain": "Tren", + "iconPlane": "Viaje", + "iconFlight": "Vuelo", + "iconFuel": "Repostar", + "iconNavigation": "Navegación", + "iconWork": "Trabajo", + "iconLaptop": "Portátil", + "iconPresentation": "Presentación", + "iconSchool": "Escuela", + "iconEducation": "Educación", + "iconReading": "Lectura", + "iconStudy": "Estudio", + "iconCalculator": "Calculadora", + "iconMeal": "Comida", + "iconCooking": "Cocinar", + "iconCoffee": "Café", + "iconCake": "Cumpleaños", + "iconPizza": "Pizza", + "iconWine": "Vino", + "iconBeer": "Bar", + "iconShopping": "Compras", + "iconGroceries": "Supermercado", + "iconGift": "Regalo", + "iconCard": "Tarjeta", + "iconWallet": "Cartera", + "iconSavings": "Ahorro", + "iconBank": "Banco", + "iconMusic": "Música", + "iconMovie": "Película", + "iconTicket": "Entrada", + "iconGame": "Juego", + "iconPhoto": "Foto", + "iconParty": "Fiesta", + "iconFamily": "Familia", + "iconBaby": "Bebé", + "iconDog": "Perro", + "iconCat": "Gato", + "iconPet": "Mascota", + "iconHome": "Hogar", + "iconBuilding": "Edificio", + "iconRepair": "Reparación", + "iconMaintenance": "Mantenimiento", + "iconDecoration": "Decoración", + "iconFurniture": "Muebles", + "iconLaundry": "Lavandería", + "iconLeaf": "Naturaleza", + "iconTree": "Árbol", + "iconFlower": "Flor", + "iconSun": "Día", + "iconMoon": "Noche", + "iconWeather": "Clima", "invalidDate": "Use a valid date in the selected date format.", "attachmentLabel": "Attachment", "attachmentHint": "Attach a local image, PDF, or document. Images will be shown in the event popup.", diff --git a/public/locales/fr.json b/public/locales/fr.json index fb5764f..435314a 100644 --- a/public/locales/fr.json +++ b/public/locales/fr.json @@ -118,7 +118,12 @@ "customizeDrag": "Faire glisser le widget", "customizeSize": "Taille", "customizeSizeFor": "Taille de {{widget}}", - "customizeHide": "Masquer {{widget}}" + "customizeHide": "Masquer {{widget}}", + "widgetSizeTiny": "Petit (1×1)", + "widgetSizeNarrow": "Étroit (2×1)", + "widgetSizeStandard": "Standard (2×2)", + "widgetSizeLarge": "Grand (3×2)", + "widgetSizeFull": "Plein (4×2)" }, "tasks": { "title": "Tâches", @@ -374,6 +379,91 @@ "resetToast": "Modifications annulées." }, "iconLabel": "Icon", + "iconSearchPlaceholder": "Rechercher une icône...", + "iconSearchEmpty": "Aucune icône trouvée.", + "iconCategoryGeneral": "Général", + "iconCategoryHealth": "Santé & Sport", + "iconCategoryTransport": "Mobilité & Voyage", + "iconCategoryWork": "Travail & Éducation", + "iconCategoryFood": "Alimentation & Boissons", + "iconCategoryShopping": "Courses & Finances", + "iconCategoryLeisure": "Loisirs & Divertissement", + "iconCategoryFamily": "Famille & Animaux", + "iconCategoryHome": "Maison & Foyer", + "iconCategoryNature": "Nature & Divers", + "iconCalendar": "Calendrier", + "iconAlarm": "Alarme", + "iconClock": "Horloge", + "iconBell": "Rappel", + "iconLocation": "Lieu", + "iconStar": "Favori", + "iconFlag": "Drapeau", + "iconTarget": "Objectif", + "iconFlame": "Important", + "iconTooth": "Dentiste", + "iconHospital": "Hôpital", + "iconDoctor": "Médecin", + "iconVaccine": "Vaccination", + "iconMedicine": "Médicament", + "iconBandage": "Pansement", + "iconHealth": "Santé", + "iconActivity": "Activité", + "iconHaircut": "Coiffeur", + "iconSports": "Sport", + "iconTrophy": "Compétition", + "iconCar": "Voiture", + "iconBus": "Bus", + "iconTrain": "Train", + "iconPlane": "Voyage", + "iconFlight": "Vol", + "iconFuel": "Carburant", + "iconNavigation": "Navigation", + "iconWork": "Travail", + "iconLaptop": "Ordinateur portable", + "iconPresentation": "Présentation", + "iconSchool": "École", + "iconEducation": "Éducation", + "iconReading": "Lecture", + "iconStudy": "Étude", + "iconCalculator": "Calculatrice", + "iconMeal": "Repas", + "iconCooking": "Cuisine", + "iconCoffee": "Café", + "iconCake": "Anniversaire", + "iconPizza": "Pizza", + "iconWine": "Vin", + "iconBeer": "Bar", + "iconShopping": "Courses", + "iconGroceries": "Épicerie", + "iconGift": "Cadeau", + "iconCard": "Carte", + "iconWallet": "Portefeuille", + "iconSavings": "Épargne", + "iconBank": "Banque", + "iconMusic": "Musique", + "iconMovie": "Film", + "iconTicket": "Billet", + "iconGame": "Jeu", + "iconPhoto": "Photo", + "iconParty": "Fête", + "iconFamily": "Famille", + "iconBaby": "Bébé", + "iconDog": "Chien", + "iconCat": "Chat", + "iconPet": "Animal de compagnie", + "iconHome": "Maison", + "iconBuilding": "Bâtiment", + "iconRepair": "Réparation", + "iconMaintenance": "Entretien", + "iconDecoration": "Décoration", + "iconFurniture": "Meubles", + "iconLaundry": "Linge", + "iconLeaf": "Nature", + "iconTree": "Arbre", + "iconFlower": "Fleur", + "iconSun": "Jour", + "iconMoon": "Nuit", + "iconWeather": "Météo", "invalidDate": "Use a valid date in the selected date format.", "attachmentLabel": "Attachment", "attachmentHint": "Attach a local image, PDF, or document. Images will be shown in the event popup.", diff --git a/public/locales/hi.json b/public/locales/hi.json index 2530042..dec8486 100644 --- a/public/locales/hi.json +++ b/public/locales/hi.json @@ -118,7 +118,12 @@ "customizeDrag": "विजेट खींचें", "customizeSize": "आकार", "customizeSizeFor": "{{widget}} का आकार", - "customizeHide": "{{widget}} छिपाएँ" + "customizeHide": "{{widget}} छिपाएँ", + "widgetSizeTiny": "छोटा (1×1)", + "widgetSizeNarrow": "संकरा (2×1)", + "widgetSizeStandard": "मानक (2×2)", + "widgetSizeLarge": "बड़ा (3×2)", + "widgetSizeFull": "पूर्ण (4×2)" }, "tasks": { "title": "कार्य", @@ -374,6 +379,91 @@ "resetToast": "परिवर्तन रीसेट हो गए।" }, "iconLabel": "Icon", + "iconSearchPlaceholder": "आइकन खोजें...", + "iconSearchEmpty": "कोई आइकन नहीं मिला।", + "iconCategoryGeneral": "सामान्य", + "iconCategoryHealth": "स्वास्थ्य और खेल", + "iconCategoryTransport": "परिवहन और यात्रा", + "iconCategoryWork": "काम और शिक्षा", + "iconCategoryFood": "खाना और पेय", + "iconCategoryShopping": "खरीदारी और वित्त", + "iconCategoryLeisure": "मनोरंजन और फुर्सत", + "iconCategoryFamily": "परिवार और पालतू जानवर", + "iconCategoryHome": "घर और गृहस्थी", + "iconCategoryNature": "प्रकृति और अन्य", + "iconCalendar": "कैलेंडर", + "iconAlarm": "अलार्म", + "iconClock": "घड़ी", + "iconBell": "अनुस्मारक", + "iconLocation": "स्थान", + "iconStar": "पसंदीदा", + "iconFlag": "झंडा", + "iconTarget": "लक्ष्य", + "iconFlame": "महत्वपूर्ण", + "iconTooth": "दंत चिकित्सक", + "iconHospital": "अस्पताल", + "iconDoctor": "डॉक्टर", + "iconVaccine": "टीकाकरण", + "iconMedicine": "दवा", + "iconBandage": "पट्टी", + "iconHealth": "स्वास्थ्य", + "iconActivity": "गतिविधि", + "iconHaircut": "नाई की दुकान", + "iconSports": "खेल", + "iconTrophy": "प्रतियोगिता", + "iconCar": "कार", + "iconBus": "बस", + "iconTrain": "ट्रेन", + "iconPlane": "यात्रा", + "iconFlight": "उड़ान", + "iconFuel": "ईंधन भरना", + "iconNavigation": "नेविगेशन", + "iconWork": "काम", + "iconLaptop": "लैपटॉप", + "iconPresentation": "प्रस्तुति", + "iconSchool": "स्कूल", + "iconEducation": "शिक्षा", + "iconReading": "पठन", + "iconStudy": "अध्ययन", + "iconCalculator": "कैलकुलेटर", + "iconMeal": "भोजन", + "iconCooking": "खाना बनाना", + "iconCoffee": "कॉफी", + "iconCake": "जन्मदिन", + "iconPizza": "पिज्जा", + "iconWine": "वाइन", + "iconBeer": "बार", + "iconShopping": "खरीदारी", + "iconGroceries": "किराना", + "iconGift": "उपहार", + "iconCard": "कार्ड", + "iconWallet": "बटुआ", + "iconSavings": "बचत", + "iconBank": "बैंक", + "iconMusic": "संगीत", + "iconMovie": "फिल्म", + "iconTicket": "टिकट", + "iconGame": "खेल", + "iconPhoto": "फोटो", + "iconParty": "पार्टी", + "iconFamily": "परिवार", + "iconBaby": "शिशु", + "iconDog": "कुत्ता", + "iconCat": "बिल्ली", + "iconPet": "पालतू जानवर", + "iconHome": "घर", + "iconBuilding": "इमारत", + "iconRepair": "मरम्मत", + "iconMaintenance": "रखरखाव", + "iconDecoration": "सजावट", + "iconFurniture": "फर्नीचर", + "iconLaundry": "कपड़े धोना", + "iconLeaf": "प्रकृति", + "iconTree": "पेड़", + "iconFlower": "फूल", + "iconSun": "दिन", + "iconMoon": "रात", + "iconWeather": "मौसम", "invalidDate": "Use a valid date in the selected date format.", "attachmentLabel": "Attachment", "attachmentHint": "Attach a local image, PDF, or document. Images will be shown in the event popup.", diff --git a/public/locales/it.json b/public/locales/it.json index 8b42816..a24fde4 100644 --- a/public/locales/it.json +++ b/public/locales/it.json @@ -118,7 +118,12 @@ "customizeDrag": "Trascina widget", "customizeSize": "Dimensione", "customizeSizeFor": "Dimensione di {{widget}}", - "customizeHide": "Nascondi {{widget}}" + "customizeHide": "Nascondi {{widget}}", + "widgetSizeTiny": "Piccolo (1×1)", + "widgetSizeNarrow": "Stretto (2×1)", + "widgetSizeStandard": "Standard (2×2)", + "widgetSizeLarge": "Grande (3×2)", + "widgetSizeFull": "Pieno (4×2)" }, "tasks": { "title": "Compiti", @@ -374,6 +379,91 @@ "resetToast": "Modifiche ripristinate." }, "iconLabel": "Icon", + "iconSearchPlaceholder": "Cerca icona...", + "iconSearchEmpty": "Nessuna icona trovata.", + "iconCategoryGeneral": "Generale", + "iconCategoryHealth": "Salute & Sport", + "iconCategoryTransport": "Mobilità & Viaggi", + "iconCategoryWork": "Lavoro & Istruzione", + "iconCategoryFood": "Cibo & Bevande", + "iconCategoryShopping": "Acquisti & Finanze", + "iconCategoryLeisure": "Tempo libero & Intrattenimento", + "iconCategoryFamily": "Famiglia & Animali", + "iconCategoryHome": "Casa & Abitazione", + "iconCategoryNature": "Natura & Altro", + "iconCalendar": "Calendario", + "iconAlarm": "Sveglia", + "iconClock": "Orologio", + "iconBell": "Promemoria", + "iconLocation": "Luogo", + "iconStar": "Preferito", + "iconFlag": "Bandiera", + "iconTarget": "Obiettivo", + "iconFlame": "Importante", + "iconTooth": "Dentista", + "iconHospital": "Ospedale", + "iconDoctor": "Medico", + "iconVaccine": "Vaccinazione", + "iconMedicine": "Medicina", + "iconBandage": "Benda", + "iconHealth": "Salute", + "iconActivity": "Attività", + "iconHaircut": "Parrucchiere", + "iconSports": "Sport", + "iconTrophy": "Competizione", + "iconCar": "Auto", + "iconBus": "Autobus", + "iconTrain": "Treno", + "iconPlane": "Viaggio", + "iconFlight": "Volo", + "iconFuel": "Carburante", + "iconNavigation": "Navigazione", + "iconWork": "Lavoro", + "iconLaptop": "Laptop", + "iconPresentation": "Presentazione", + "iconSchool": "Scuola", + "iconEducation": "Istruzione", + "iconReading": "Lettura", + "iconStudy": "Studio", + "iconCalculator": "Calcolatrice", + "iconMeal": "Pasto", + "iconCooking": "Cucinare", + "iconCoffee": "Caffè", + "iconCake": "Compleanno", + "iconPizza": "Pizza", + "iconWine": "Vino", + "iconBeer": "Bar", + "iconShopping": "Acquisti", + "iconGroceries": "Alimentari", + "iconGift": "Regalo", + "iconCard": "Carta", + "iconWallet": "Portafoglio", + "iconSavings": "Risparmio", + "iconBank": "Banca", + "iconMusic": "Musica", + "iconMovie": "Film", + "iconTicket": "Biglietto", + "iconGame": "Gioco", + "iconPhoto": "Foto", + "iconParty": "Festa", + "iconFamily": "Famiglia", + "iconBaby": "Neonato", + "iconDog": "Cane", + "iconCat": "Gatto", + "iconPet": "Animale domestico", + "iconHome": "Casa", + "iconBuilding": "Edificio", + "iconRepair": "Riparazione", + "iconMaintenance": "Manutenzione", + "iconDecoration": "Decorazione", + "iconFurniture": "Mobili", + "iconLaundry": "Bucato", + "iconLeaf": "Natura", + "iconTree": "Albero", + "iconFlower": "Fiore", + "iconSun": "Giorno", + "iconMoon": "Notte", + "iconWeather": "Meteo", "invalidDate": "Use a valid date in the selected date format.", "attachmentLabel": "Attachment", "attachmentHint": "Attach a local image, PDF, or document. Images will be shown in the event popup.", diff --git a/public/locales/ja.json b/public/locales/ja.json index 87df852..b7cff32 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -118,7 +118,12 @@ "customizeDrag": "ウィジェットをドラッグ", "customizeSize": "サイズ", "customizeSizeFor": "{{widget}} のサイズ", - "customizeHide": "{{widget}} を非表示" + "customizeHide": "{{widget}} を非表示", + "widgetSizeTiny": "小 (1×1)", + "widgetSizeNarrow": "縦長 (2×1)", + "widgetSizeStandard": "標準 (2×2)", + "widgetSizeLarge": "大 (3×2)", + "widgetSizeFull": "全幅 (4×2)" }, "tasks": { "title": "タスク", @@ -374,6 +379,91 @@ "resetToast": "変更がリセットされました。" }, "iconLabel": "Icon", + "iconSearchPlaceholder": "アイコンを検索...", + "iconSearchEmpty": "アイコンが見つかりません。", + "iconCategoryGeneral": "一般", + "iconCategoryHealth": "健康とスポーツ", + "iconCategoryTransport": "移動と旅行", + "iconCategoryWork": "仕事と教育", + "iconCategoryFood": "食べ物と飲み物", + "iconCategoryShopping": "ショッピングと財務", + "iconCategoryLeisure": "レジャーとエンターテインメント", + "iconCategoryFamily": "家族とペット", + "iconCategoryHome": "家と家事", + "iconCategoryNature": "自然とその他", + "iconCalendar": "カレンダー", + "iconAlarm": "アラーム", + "iconClock": "時計", + "iconBell": "リマインダー", + "iconLocation": "場所", + "iconStar": "お気に入り", + "iconFlag": "フラグ", + "iconTarget": "目標", + "iconFlame": "重要", + "iconTooth": "歯医者", + "iconHospital": "病院", + "iconDoctor": "医者", + "iconVaccine": "ワクチン", + "iconMedicine": "薬", + "iconBandage": "包帯", + "iconHealth": "健康", + "iconActivity": "アクティビティ", + "iconHaircut": "美容院", + "iconSports": "スポーツ", + "iconTrophy": "大会", + "iconCar": "車", + "iconBus": "バス", + "iconTrain": "電車", + "iconPlane": "旅行", + "iconFlight": "フライト", + "iconFuel": "給油", + "iconNavigation": "ナビゲーション", + "iconWork": "仕事", + "iconLaptop": "ノートパソコン", + "iconPresentation": "プレゼンテーション", + "iconSchool": "学校", + "iconEducation": "教育", + "iconReading": "読書", + "iconStudy": "勉強", + "iconCalculator": "電卓", + "iconMeal": "食事", + "iconCooking": "料理", + "iconCoffee": "コーヒー", + "iconCake": "誕生日", + "iconPizza": "ピザ", + "iconWine": "ワイン", + "iconBeer": "バー", + "iconShopping": "ショッピング", + "iconGroceries": "食料品", + "iconGift": "プレゼント", + "iconCard": "カード", + "iconWallet": "財布", + "iconSavings": "貯金", + "iconBank": "銀行", + "iconMusic": "音楽", + "iconMovie": "映画", + "iconTicket": "チケット", + "iconGame": "ゲーム", + "iconPhoto": "写真", + "iconParty": "パーティー", + "iconFamily": "家族", + "iconBaby": "赤ちゃん", + "iconDog": "犬", + "iconCat": "猫", + "iconPet": "ペット", + "iconHome": "家", + "iconBuilding": "建物", + "iconRepair": "修理", + "iconMaintenance": "メンテナンス", + "iconDecoration": "装飾", + "iconFurniture": "家具", + "iconLaundry": "洗濯", + "iconLeaf": "自然", + "iconTree": "木", + "iconFlower": "花", + "iconSun": "昼", + "iconMoon": "夜", + "iconWeather": "天気", "invalidDate": "Use a valid date in the selected date format.", "attachmentLabel": "Attachment", "attachmentHint": "Attach a local image, PDF, or document. Images will be shown in the event popup.", diff --git a/public/locales/pt.json b/public/locales/pt.json index 845b74f..8ee1974 100644 --- a/public/locales/pt.json +++ b/public/locales/pt.json @@ -118,7 +118,12 @@ "customizeDrag": "Arrastar widget", "customizeSize": "Tamanho", "customizeSizeFor": "Tamanho de {{widget}}", - "customizeHide": "Ocultar {{widget}}" + "customizeHide": "Ocultar {{widget}}", + "widgetSizeTiny": "Pequeno (1×1)", + "widgetSizeNarrow": "Estreito (2×1)", + "widgetSizeStandard": "Padrão (2×2)", + "widgetSizeLarge": "Grande (3×2)", + "widgetSizeFull": "Completo (4×2)" }, "tasks": { "title": "Tarefas", @@ -374,6 +379,91 @@ "resetToast": "Alterações restauradas." }, "iconLabel": "Ícone", + "iconSearchPlaceholder": "Pesquisar ícone...", + "iconSearchEmpty": "Nenhum ícone encontrado.", + "iconCategoryGeneral": "Geral", + "iconCategoryHealth": "Saúde & Desporto", + "iconCategoryTransport": "Mobilidade & Viagem", + "iconCategoryWork": "Trabalho & Educação", + "iconCategoryFood": "Comida & Bebida", + "iconCategoryShopping": "Compras & Finanças", + "iconCategoryLeisure": "Lazer & Entretenimento", + "iconCategoryFamily": "Família & Animais", + "iconCategoryHome": "Casa & Lar", + "iconCategoryNature": "Natureza & Outros", + "iconCalendar": "Calendário", + "iconAlarm": "Alarme", + "iconClock": "Relógio", + "iconBell": "Lembrete", + "iconLocation": "Local", + "iconStar": "Favorito", + "iconFlag": "Bandeira", + "iconTarget": "Meta", + "iconFlame": "Importante", + "iconTooth": "Dentista", + "iconHospital": "Hospital", + "iconDoctor": "Médico", + "iconVaccine": "Vacina", + "iconMedicine": "Medicamento", + "iconBandage": "Curativo", + "iconHealth": "Saúde", + "iconActivity": "Atividade", + "iconHaircut": "Cabeleireiro", + "iconSports": "Desporto", + "iconTrophy": "Competição", + "iconCar": "Carro", + "iconBus": "Autocarro", + "iconTrain": "Comboio", + "iconPlane": "Viagem", + "iconFlight": "Voo", + "iconFuel": "Abastecimento", + "iconNavigation": "Navegação", + "iconWork": "Trabalho", + "iconLaptop": "Portátil", + "iconPresentation": "Apresentação", + "iconSchool": "Escola", + "iconEducation": "Educação", + "iconReading": "Leitura", + "iconStudy": "Estudo", + "iconCalculator": "Calculadora", + "iconMeal": "Refeição", + "iconCooking": "Cozinhar", + "iconCoffee": "Café", + "iconCake": "Aniversário", + "iconPizza": "Pizza", + "iconWine": "Vinho", + "iconBeer": "Bar", + "iconShopping": "Compras", + "iconGroceries": "Mercearia", + "iconGift": "Presente", + "iconCard": "Cartão", + "iconWallet": "Carteira", + "iconSavings": "Poupança", + "iconBank": "Banco", + "iconMusic": "Música", + "iconMovie": "Filme", + "iconTicket": "Bilhete", + "iconGame": "Jogo", + "iconPhoto": "Foto", + "iconParty": "Festa", + "iconFamily": "Família", + "iconBaby": "Bebé", + "iconDog": "Cão", + "iconCat": "Gato", + "iconPet": "Animal de estimação", + "iconHome": "Casa", + "iconBuilding": "Edifício", + "iconRepair": "Reparação", + "iconMaintenance": "Manutenção", + "iconDecoration": "Decoração", + "iconFurniture": "Mobília", + "iconLaundry": "Roupa", + "iconLeaf": "Natureza", + "iconTree": "Árvore", + "iconFlower": "Flor", + "iconSun": "Dia", + "iconMoon": "Noite", + "iconWeather": "Tempo", "invalidDate": "Use uma data válida no formato selecionado.", "attachmentLabel": "Anexo", "attachmentHint": "Anexe uma imagem, PDF ou documento local. Imagens aparecem no pop-up do evento.", diff --git a/public/locales/ru.json b/public/locales/ru.json index bdeb66c..08ba17e 100644 --- a/public/locales/ru.json +++ b/public/locales/ru.json @@ -118,7 +118,12 @@ "customizeDrag": "Перетащить виджет", "customizeSize": "Размер", "customizeSizeFor": "Размер для {{widget}}", - "customizeHide": "Скрыть {{widget}}" + "customizeHide": "Скрыть {{widget}}", + "widgetSizeTiny": "Маленький (1×1)", + "widgetSizeNarrow": "Узкий (2×1)", + "widgetSizeStandard": "Стандартный (2×2)", + "widgetSizeLarge": "Большой (3×2)", + "widgetSizeFull": "Полный (4×2)" }, "tasks": { "title": "Задачи", @@ -374,6 +379,91 @@ "resetToast": "Изменения сброшены." }, "iconLabel": "Icon", + "iconSearchPlaceholder": "Поиск иконки...", + "iconSearchEmpty": "Иконка не найдена.", + "iconCategoryGeneral": "Общее", + "iconCategoryHealth": "Здоровье и спорт", + "iconCategoryTransport": "Транспорт и путешествия", + "iconCategoryWork": "Работа и образование", + "iconCategoryFood": "Еда и напитки", + "iconCategoryShopping": "Покупки и финансы", + "iconCategoryLeisure": "Досуг и развлечения", + "iconCategoryFamily": "Семья и питомцы", + "iconCategoryHome": "Дом и хозяйство", + "iconCategoryNature": "Природа и прочее", + "iconCalendar": "Календарь", + "iconAlarm": "Будильник", + "iconClock": "Часы", + "iconBell": "Напоминание", + "iconLocation": "Место", + "iconStar": "Избранное", + "iconFlag": "Флаг", + "iconTarget": "Цель", + "iconFlame": "Важно", + "iconTooth": "Стоматолог", + "iconHospital": "Больница", + "iconDoctor": "Врач", + "iconVaccine": "Прививка", + "iconMedicine": "Лекарство", + "iconBandage": "Перевязка", + "iconHealth": "Здоровье", + "iconActivity": "Активность", + "iconHaircut": "Парикмахерская", + "iconSports": "Спорт", + "iconTrophy": "Соревнование", + "iconCar": "Автомобиль", + "iconBus": "Автобус", + "iconTrain": "Поезд", + "iconPlane": "Путешествие", + "iconFlight": "Рейс", + "iconFuel": "Заправка", + "iconNavigation": "Навигация", + "iconWork": "Работа", + "iconLaptop": "Ноутбук", + "iconPresentation": "Презентация", + "iconSchool": "Школа", + "iconEducation": "Образование", + "iconReading": "Чтение", + "iconStudy": "Учёба", + "iconCalculator": "Калькулятор", + "iconMeal": "Приём пищи", + "iconCooking": "Готовка", + "iconCoffee": "Кофе", + "iconCake": "День рождения", + "iconPizza": "Пицца", + "iconWine": "Вино", + "iconBeer": "Бар", + "iconShopping": "Покупки", + "iconGroceries": "Продукты", + "iconGift": "Подарок", + "iconCard": "Карта", + "iconWallet": "Кошелёк", + "iconSavings": "Сбережения", + "iconBank": "Банк", + "iconMusic": "Музыка", + "iconMovie": "Фильм", + "iconTicket": "Билет", + "iconGame": "Игра", + "iconPhoto": "Фото", + "iconParty": "Вечеринка", + "iconFamily": "Семья", + "iconBaby": "Ребёнок", + "iconDog": "Собака", + "iconCat": "Кошка", + "iconPet": "Питомец", + "iconHome": "Дом", + "iconBuilding": "Здание", + "iconRepair": "Ремонт", + "iconMaintenance": "Обслуживание", + "iconDecoration": "Декор", + "iconFurniture": "Мебель", + "iconLaundry": "Стирка", + "iconLeaf": "Природа", + "iconTree": "Дерево", + "iconFlower": "Цветок", + "iconSun": "День", + "iconMoon": "Ночь", + "iconWeather": "Погода", "invalidDate": "Use a valid date in the selected date format.", "attachmentLabel": "Attachment", "attachmentHint": "Attach a local image, PDF, or document. Images will be shown in the event popup.", diff --git a/public/locales/sv.json b/public/locales/sv.json index 54e94cc..4a030b4 100644 --- a/public/locales/sv.json +++ b/public/locales/sv.json @@ -118,7 +118,12 @@ "customizeDrag": "Dra widget", "customizeSize": "Storlek", "customizeSizeFor": "Storlek för {{widget}}", - "customizeHide": "Dölj {{widget}}" + "customizeHide": "Dölj {{widget}}", + "widgetSizeTiny": "Liten (1×1)", + "widgetSizeNarrow": "Smal (2×1)", + "widgetSizeStandard": "Standard (2×2)", + "widgetSizeLarge": "Stor (3×2)", + "widgetSizeFull": "Hel (4×2)" }, "tasks": { "title": "Uppgifter", @@ -374,6 +379,91 @@ "resetToast": "Ändringar återställda." }, "iconLabel": "Ikon", + "iconSearchPlaceholder": "Sök ikon...", + "iconSearchEmpty": "Ingen ikon hittades.", + "iconCategoryGeneral": "Allmänt", + "iconCategoryHealth": "Hälsa & Sport", + "iconCategoryTransport": "Rörlighet & Resa", + "iconCategoryWork": "Arbete & Utbildning", + "iconCategoryFood": "Mat & Dryck", + "iconCategoryShopping": "Shopping & Ekonomi", + "iconCategoryLeisure": "Fritid & Underhållning", + "iconCategoryFamily": "Familj & Husdjur", + "iconCategoryHome": "Hem & Hushåll", + "iconCategoryNature": "Natur & Övrigt", + "iconCalendar": "Kalender", + "iconAlarm": "Alarm", + "iconClock": "Klocka", + "iconBell": "Påminnelse", + "iconLocation": "Plats", + "iconStar": "Favorit", + "iconFlag": "Flagga", + "iconTarget": "Mål", + "iconFlame": "Viktigt", + "iconTooth": "Tandläkare", + "iconHospital": "Sjukhus", + "iconDoctor": "Läkare", + "iconVaccine": "Vaccination", + "iconMedicine": "Medicin", + "iconBandage": "Förband", + "iconHealth": "Hälsa", + "iconActivity": "Aktivitet", + "iconHaircut": "Frisör", + "iconSports": "Sport", + "iconTrophy": "Tävling", + "iconCar": "Bil", + "iconBus": "Buss", + "iconTrain": "Tåg", + "iconPlane": "Resa", + "iconFlight": "Flyg", + "iconFuel": "Tanka", + "iconNavigation": "Navigation", + "iconWork": "Arbete", + "iconLaptop": "Laptop", + "iconPresentation": "Presentation", + "iconSchool": "Skola", + "iconEducation": "Utbildning", + "iconReading": "Läsning", + "iconStudy": "Studera", + "iconCalculator": "Räknare", + "iconMeal": "Måltid", + "iconCooking": "Matlagning", + "iconCoffee": "Kaffe", + "iconCake": "Födelsedag", + "iconPizza": "Pizza", + "iconWine": "Vin", + "iconBeer": "Bar", + "iconShopping": "Shopping", + "iconGroceries": "Livsmedel", + "iconGift": "Present", + "iconCard": "Kort", + "iconWallet": "Plånbok", + "iconSavings": "Sparande", + "iconBank": "Bank", + "iconMusic": "Musik", + "iconMovie": "Film", + "iconTicket": "Biljett", + "iconGame": "Spel", + "iconPhoto": "Foto", + "iconParty": "Fest", + "iconFamily": "Familj", + "iconBaby": "Baby", + "iconDog": "Hund", + "iconCat": "Katt", + "iconPet": "Husdjur", + "iconHome": "Hem", + "iconBuilding": "Byggnad", + "iconRepair": "Reparation", + "iconMaintenance": "Underhåll", + "iconDecoration": "Dekoration", + "iconFurniture": "Möbler", + "iconLaundry": "Tvätt", + "iconLeaf": "Natur", + "iconTree": "Träd", + "iconFlower": "Blomma", + "iconSun": "Dag", + "iconMoon": "Natt", + "iconWeather": "Väder", "invalidDate": "Använd ett giltigt datum i det valda datumformatet.", "attachmentLabel": "Fastsättning", "attachmentHint": "Bifoga en lokal bild, PDF eller dokument. Bilder kommer att visas i evenemangets popup.", diff --git a/public/locales/tr.json b/public/locales/tr.json index b76bd3d..5581555 100644 --- a/public/locales/tr.json +++ b/public/locales/tr.json @@ -118,7 +118,12 @@ "customizeDrag": "Widgetı sürükle", "customizeSize": "Boyut", "customizeSizeFor": "{{widget}} boyutu", - "customizeHide": "{{widget}} gizle" + "customizeHide": "{{widget}} gizle", + "widgetSizeTiny": "Küçük (1×1)", + "widgetSizeNarrow": "Dar (2×1)", + "widgetSizeStandard": "Standart (2×2)", + "widgetSizeLarge": "Büyük (3×2)", + "widgetSizeFull": "Tam (4×2)" }, "tasks": { "title": "Görevler", @@ -374,6 +379,91 @@ "resetToast": "Değişiklikler sıfırlandı." }, "iconLabel": "Icon", + "iconSearchPlaceholder": "Simge ara...", + "iconSearchEmpty": "Simge bulunamadı.", + "iconCategoryGeneral": "Genel", + "iconCategoryHealth": "Sağlık & Spor", + "iconCategoryTransport": "Ulaşım & Seyahat", + "iconCategoryWork": "İş & Eğitim", + "iconCategoryFood": "Yiyecek & İçecek", + "iconCategoryShopping": "Alışveriş & Finans", + "iconCategoryLeisure": "Boş Zaman & Eğlence", + "iconCategoryFamily": "Aile & Evcil Hayvanlar", + "iconCategoryHome": "Ev & Hane", + "iconCategoryNature": "Doğa & Diğer", + "iconCalendar": "Takvim", + "iconAlarm": "Alarm", + "iconClock": "Saat", + "iconBell": "Hatırlatıcı", + "iconLocation": "Konum", + "iconStar": "Favori", + "iconFlag": "Bayrak", + "iconTarget": "Hedef", + "iconFlame": "Önemli", + "iconTooth": "Diş hekimi", + "iconHospital": "Hastane", + "iconDoctor": "Doktor", + "iconVaccine": "Aşı", + "iconMedicine": "İlaç", + "iconBandage": "Sargı", + "iconHealth": "Sağlık", + "iconActivity": "Aktivite", + "iconHaircut": "Kuaför", + "iconSports": "Spor", + "iconTrophy": "Yarışma", + "iconCar": "Araba", + "iconBus": "Otobüs", + "iconTrain": "Tren", + "iconPlane": "Seyahat", + "iconFlight": "Uçuş", + "iconFuel": "Yakıt", + "iconNavigation": "Navigasyon", + "iconWork": "İş", + "iconLaptop": "Dizüstü bilgisayar", + "iconPresentation": "Sunum", + "iconSchool": "Okul", + "iconEducation": "Eğitim", + "iconReading": "Okuma", + "iconStudy": "Çalışma", + "iconCalculator": "Hesap makinesi", + "iconMeal": "Öğün", + "iconCooking": "Yemek pişirme", + "iconCoffee": "Kahve", + "iconCake": "Doğum günü", + "iconPizza": "Pizza", + "iconWine": "Şarap", + "iconBeer": "Bar", + "iconShopping": "Alışveriş", + "iconGroceries": "Market", + "iconGift": "Hediye", + "iconCard": "Kart", + "iconWallet": "Cüzdan", + "iconSavings": "Tasarruf", + "iconBank": "Banka", + "iconMusic": "Müzik", + "iconMovie": "Film", + "iconTicket": "Bilet", + "iconGame": "Oyun", + "iconPhoto": "Fotoğraf", + "iconParty": "Parti", + "iconFamily": "Aile", + "iconBaby": "Bebek", + "iconDog": "Köpek", + "iconCat": "Kedi", + "iconPet": "Evcil hayvan", + "iconHome": "Ev", + "iconBuilding": "Bina", + "iconRepair": "Tamir", + "iconMaintenance": "Bakım", + "iconDecoration": "Dekorasyon", + "iconFurniture": "Mobilya", + "iconLaundry": "Çamaşır", + "iconLeaf": "Doğa", + "iconTree": "Ağaç", + "iconFlower": "Çiçek", + "iconSun": "Gün", + "iconMoon": "Gece", + "iconWeather": "Hava durumu", "invalidDate": "Use a valid date in the selected date format.", "attachmentLabel": "Attachment", "attachmentHint": "Attach a local image, PDF, or document. Images will be shown in the event popup.", diff --git a/public/locales/uk.json b/public/locales/uk.json index 88f277e..c6a3fd7 100644 --- a/public/locales/uk.json +++ b/public/locales/uk.json @@ -118,7 +118,12 @@ "customizeDrag": "Перетягнути віджет", "customizeSize": "Розмір", "customizeSizeFor": "Розмір для {{widget}}", - "customizeHide": "Приховати {{widget}}" + "customizeHide": "Приховати {{widget}}", + "widgetSizeTiny": "Маленький (1×1)", + "widgetSizeNarrow": "Вузький (2×1)", + "widgetSizeStandard": "Стандартний (2×2)", + "widgetSizeLarge": "Великий (3×2)", + "widgetSizeFull": "Повний (4×2)" }, "tasks": { "title": "Завдання", @@ -374,6 +379,91 @@ "resetToast": "Зміни скинуто." }, "iconLabel": "Icon", + "iconSearchPlaceholder": "Пошук іконки...", + "iconSearchEmpty": "Іконку не знайдено.", + "iconCategoryGeneral": "Загальне", + "iconCategoryHealth": "Здоров'я та спорт", + "iconCategoryTransport": "Транспорт та подорожі", + "iconCategoryWork": "Робота та освіта", + "iconCategoryFood": "Їжа та напої", + "iconCategoryShopping": "Покупки та фінанси", + "iconCategoryLeisure": "Дозвілля та розваги", + "iconCategoryFamily": "Сім'я та домашні тварини", + "iconCategoryHome": "Будинок та господарство", + "iconCategoryNature": "Природа та інше", + "iconCalendar": "Календар", + "iconAlarm": "Будильник", + "iconClock": "Годинник", + "iconBell": "Нагадування", + "iconLocation": "Місце", + "iconStar": "Обране", + "iconFlag": "Прапор", + "iconTarget": "Ціль", + "iconFlame": "Важливо", + "iconTooth": "Стоматолог", + "iconHospital": "Лікарня", + "iconDoctor": "Лікар", + "iconVaccine": "Щеплення", + "iconMedicine": "Ліки", + "iconBandage": "Перев'язка", + "iconHealth": "Здоров'я", + "iconActivity": "Активність", + "iconHaircut": "Перукарня", + "iconSports": "Спорт", + "iconTrophy": "Змагання", + "iconCar": "Автомобіль", + "iconBus": "Автобус", + "iconTrain": "Поїзд", + "iconPlane": "Подорож", + "iconFlight": "Рейс", + "iconFuel": "Заправка", + "iconNavigation": "Навігація", + "iconWork": "Робота", + "iconLaptop": "Ноутбук", + "iconPresentation": "Презентація", + "iconSchool": "Школа", + "iconEducation": "Освіта", + "iconReading": "Читання", + "iconStudy": "Навчання", + "iconCalculator": "Калькулятор", + "iconMeal": "Прийом їжі", + "iconCooking": "Готування", + "iconCoffee": "Кава", + "iconCake": "День народження", + "iconPizza": "Піца", + "iconWine": "Вино", + "iconBeer": "Бар", + "iconShopping": "Покупки", + "iconGroceries": "Продукти", + "iconGift": "Подарунок", + "iconCard": "Картка", + "iconWallet": "Гаманець", + "iconSavings": "Заощадження", + "iconBank": "Банк", + "iconMusic": "Музика", + "iconMovie": "Фільм", + "iconTicket": "Квиток", + "iconGame": "Гра", + "iconPhoto": "Фото", + "iconParty": "Вечірка", + "iconFamily": "Сім'я", + "iconBaby": "Немовля", + "iconDog": "Собака", + "iconCat": "Кіт", + "iconPet": "Домашня тварина", + "iconHome": "Будинок", + "iconBuilding": "Будівля", + "iconRepair": "Ремонт", + "iconMaintenance": "Обслуговування", + "iconDecoration": "Декор", + "iconFurniture": "Меблі", + "iconLaundry": "Прання", + "iconLeaf": "Природа", + "iconTree": "Дерево", + "iconFlower": "Квітка", + "iconSun": "День", + "iconMoon": "Ніч", + "iconWeather": "Погода", "invalidDate": "Use a valid date in the selected date format.", "attachmentLabel": "Attachment", "attachmentHint": "Attach a local image, PDF, or document. Images will be shown in the event popup.", diff --git a/public/locales/zh.json b/public/locales/zh.json index 0220a8b..42ba68c 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -118,7 +118,12 @@ "customizeDrag": "拖动小组件", "customizeSize": "大小", "customizeSizeFor": "{{widget}} 的大小", - "customizeHide": "隐藏 {{widget}}" + "customizeHide": "隐藏 {{widget}}", + "widgetSizeTiny": "小 (1×1)", + "widgetSizeNarrow": "窄 (2×1)", + "widgetSizeStandard": "标准 (2×2)", + "widgetSizeLarge": "大 (3×2)", + "widgetSizeFull": "全宽 (4×2)" }, "tasks": { "title": "任务", @@ -374,6 +379,91 @@ "resetToast": "更改已重置。" }, "iconLabel": "Icon", + "iconSearchPlaceholder": "搜索图标...", + "iconSearchEmpty": "未找到图标。", + "iconCategoryGeneral": "通用", + "iconCategoryHealth": "健康与运动", + "iconCategoryTransport": "出行与旅行", + "iconCategoryWork": "工作与教育", + "iconCategoryFood": "饮食", + "iconCategoryShopping": "购物与财务", + "iconCategoryLeisure": "休闲与娱乐", + "iconCategoryFamily": "家庭与宠物", + "iconCategoryHome": "家居与家务", + "iconCategoryNature": "自然与其他", + "iconCalendar": "日历", + "iconAlarm": "闹钟", + "iconClock": "时钟", + "iconBell": "提醒", + "iconLocation": "地点", + "iconStar": "收藏", + "iconFlag": "旗帜", + "iconTarget": "目标", + "iconFlame": "重要", + "iconTooth": "牙医", + "iconHospital": "医院", + "iconDoctor": "医生", + "iconVaccine": "疫苗", + "iconMedicine": "药物", + "iconBandage": "绷带", + "iconHealth": "健康", + "iconActivity": "活动", + "iconHaircut": "理发店", + "iconSports": "运动", + "iconTrophy": "比赛", + "iconCar": "汽车", + "iconBus": "公交车", + "iconTrain": "火车", + "iconPlane": "旅行", + "iconFlight": "航班", + "iconFuel": "加油", + "iconNavigation": "导航", + "iconWork": "工作", + "iconLaptop": "笔记本电脑", + "iconPresentation": "演示", + "iconSchool": "学校", + "iconEducation": "教育", + "iconReading": "阅读", + "iconStudy": "学习", + "iconCalculator": "计算器", + "iconMeal": "餐食", + "iconCooking": "烹饪", + "iconCoffee": "咖啡", + "iconCake": "生日", + "iconPizza": "披萨", + "iconWine": "葡萄酒", + "iconBeer": "酒吧", + "iconShopping": "购物", + "iconGroceries": "杂货", + "iconGift": "礼物", + "iconCard": "卡片", + "iconWallet": "钱包", + "iconSavings": "储蓄", + "iconBank": "银行", + "iconMusic": "音乐", + "iconMovie": "电影", + "iconTicket": "票", + "iconGame": "游戏", + "iconPhoto": "照片", + "iconParty": "聚会", + "iconFamily": "家庭", + "iconBaby": "婴儿", + "iconDog": "狗", + "iconCat": "猫", + "iconPet": "宠物", + "iconHome": "家", + "iconBuilding": "建筑", + "iconRepair": "维修", + "iconMaintenance": "维护", + "iconDecoration": "装饰", + "iconFurniture": "家具", + "iconLaundry": "洗衣", + "iconLeaf": "自然", + "iconTree": "树", + "iconFlower": "花", + "iconSun": "白天", + "iconMoon": "夜晚", + "iconWeather": "天气", "invalidDate": "Use a valid date in the selected date format.", "attachmentLabel": "Attachment", "attachmentHint": "Attach a local image, PDF, or document. Images will be shown in the event popup.", diff --git a/public/pages/birthdays.js b/public/pages/birthdays.js index 468ce68..2d39140 100644 --- a/public/pages/birthdays.js +++ b/public/pages/birthdays.js @@ -57,6 +57,28 @@ async function loadData() { ]); state.birthdays = allRes.data ?? []; state.upcoming = upcomingRes.data ?? []; + updateBirthdayBadge(); +} + +function updateBirthdayBadge() { + const soon = state.upcoming.filter((b) => b.days_until <= 3).length; + document.querySelectorAll('[data-route="/birthdays"] .nav-badge').forEach((el) => el.remove()); + if (!soon) return; + document.querySelectorAll('[data-route="/birthdays"]').forEach((navItem) => { + let anchor = navItem.querySelector('.nav-item__icon-wrap'); + if (!anchor) { + const icon = navItem.querySelector('.nav-item__icon'); + anchor = document.createElement('span'); + anchor.className = 'nav-item__icon-wrap'; + if (icon) { icon.replaceWith(anchor); anchor.appendChild(icon); } + else navItem.prepend(anchor); + } + const badge = document.createElement('span'); + badge.className = 'nav-badge'; + badge.setAttribute('aria-hidden', 'true'); + badge.textContent = String(soon); + anchor.appendChild(badge); + }); } function renderSuggestions() { diff --git a/public/pages/budget.js b/public/pages/budget.js index c076aa3..068b0de 100644 --- a/public/pages/budget.js +++ b/public/pages/budget.js @@ -826,13 +826,13 @@ function openBudgetModal({ mode, entry = null, initialType = '' }) {
- +
- + diff --git a/public/pages/calendar.js b/public/pages/calendar.js index d5cb96a..5611262 100644 --- a/public/pages/calendar.js +++ b/public/pages/calendar.js @@ -63,111 +63,145 @@ const EVENT_ICON_ALIASES = { drill: 'tooth', }; -const EVENT_ICONS = [ - { value: 'calendar', label: 'Calendar' }, - { value: 'tooth', label: 'Dentist' }, - { value: 'alarm-clock', label: 'Alarm' }, - { value: 'clock', label: 'Time' }, - { value: 'bell', label: 'Reminder' }, - { value: 'map-pin', label: 'Location' }, - { value: 'home', label: 'Home' }, - { value: 'house', label: 'House' }, - { value: 'building', label: 'Building' }, - { value: 'hospital', label: 'Hospital' }, - { value: 'stethoscope', label: 'Doctor' }, - { value: 'syringe', label: 'Vaccine' }, - { value: 'pill', label: 'Medicine' }, - { value: 'tablets', label: 'Tablets' }, - { value: 'bandage', label: 'Bandage' }, - { value: 'ambulance', label: 'Ambulance' }, - { value: 'heart-pulse', label: 'Health' }, - { value: 'activity', label: 'Activity' }, - { value: 'cross', label: 'Care' }, - { value: 'scissors', label: 'Haircut' }, - { value: 'shower-head', label: 'Personal care' }, - { value: 'dumbbell', label: 'Sports' }, - { value: 'trophy', label: 'Competition' }, - { value: 'car', label: 'Car' }, - { value: 'bus', label: 'Bus' }, - { value: 'train', label: 'Train' }, - { value: 'tram-front', label: 'Transit' }, - { value: 'fuel', label: 'Fuel' }, - { value: 'parking-meter', label: 'Parking' }, - { value: 'traffic-cone', label: 'Traffic' }, - { value: 'navigation', label: 'Navigation' }, - { value: 'route', label: 'Route' }, - { value: 'briefcase', label: 'Work' }, - { value: 'laptop', label: 'Laptop' }, - { value: 'monitor', label: 'Computer' }, - { value: 'presentation', label: 'Presentation' }, - { value: 'plane', label: 'Travel' }, - { value: 'plane-takeoff', label: 'Flight' }, - { value: 'school', label: 'School' }, - { value: 'graduation-cap', label: 'Education' }, - { value: 'book-open', label: 'Reading' }, - { value: 'library', label: 'Library' }, - { value: 'pencil', label: 'Study' }, - { value: 'notebook-pen', label: 'Notes' }, - { value: 'calculator', label: 'Calculator' }, - { value: 'utensils', label: 'Meal' }, - { value: 'cooking-pot', label: 'Cooking' }, - { value: 'coffee', label: 'Coffee' }, - { value: 'cake', label: 'Birthday' }, - { value: 'croissant', label: 'Bakery' }, - { value: 'pizza', label: 'Pizza' }, - { value: 'ice-cream', label: 'Dessert' }, - { value: 'beer', label: 'Bar' }, - { value: 'wine', label: 'Wine' }, - { value: 'popcorn', label: 'Cinema' }, - { value: 'sandwich', label: 'Snack' }, - { value: 'salad', label: 'Salad' }, - { value: 'shopping-bag', label: 'Shopping' }, - { value: 'shopping-cart', label: 'Groceries' }, - { value: 'gift', label: 'Gift' }, - { value: 'package', label: 'Package' }, - { value: 'shirt', label: 'Clothing' }, - { value: 'tag', label: 'Tag' }, - { value: 'credit-card', label: 'Card' }, - { value: 'wallet', label: 'Wallet' }, - { value: 'banknote', label: 'Cash' }, - { value: 'coins', label: 'Coins' }, - { value: 'piggy-bank', label: 'Savings' }, - { value: 'receipt', label: 'Receipt' }, - { value: 'landmark', label: 'Bank' }, - { value: 'music', label: 'Music' }, - { value: 'guitar', label: 'Guitar' }, - { value: 'film', label: 'Movie' }, - { value: 'theater', label: 'Theater' }, - { value: 'ticket', label: 'Ticket' }, - { value: 'gamepad-2', label: 'Game' }, - { value: 'camera', label: 'Photo' }, - { value: 'party-popper', label: 'Party' }, - { value: 'users', label: 'Family' }, - { value: 'baby', label: 'Baby' }, - { value: 'dog', label: 'Dog' }, - { value: 'cat', label: 'Cat' }, - { value: 'paw-print', label: 'Pet' }, - { value: 'wrench', label: 'Repair' }, - { value: 'hammer', label: 'Maintenance' }, - { value: 'paintbrush', label: 'Decoration' }, - { value: 'lightbulb', label: 'Idea' }, - { value: 'sofa', label: 'Furniture' }, - { value: 'bed', label: 'Bed' }, - { value: 'bath', label: 'Bath' }, - { value: 'washing-machine', label: 'Laundry' }, - { value: 'refrigerator', label: 'Fridge' }, - { value: 'star', label: 'Favorite' }, - { value: 'flag', label: 'Flag' }, - { value: 'target', label: 'Goal' }, - { value: 'flame', label: 'Important' }, - { value: 'leaf', label: 'Nature' }, - { value: 'tree-pine', label: 'Outdoors' }, - { value: 'flower', label: 'Flower' }, - { value: 'sun', label: 'Day' }, - { value: 'moon', label: 'Night' }, - { value: 'cloud-sun', label: 'Weather' }, +const EVENT_ICON_CATEGORIES = () => [ + { + key: 'general', + label: t('calendar.iconCategoryGeneral'), + icons: [ + { value: 'calendar', label: t('calendar.iconCalendar') }, + { value: 'alarm-clock', label: t('calendar.iconAlarm') }, + { value: 'clock', label: t('calendar.iconClock') }, + { value: 'bell', label: t('calendar.iconBell') }, + { value: 'map-pin', label: t('calendar.iconLocation') }, + { value: 'star', label: t('calendar.iconStar') }, + { value: 'flag', label: t('calendar.iconFlag') }, + { value: 'target', label: t('calendar.iconTarget') }, + { value: 'flame', label: t('calendar.iconFlame') }, + ], + }, + { + key: 'health', + label: t('calendar.iconCategoryHealth'), + icons: [ + { value: 'tooth', label: t('calendar.iconTooth') }, + { value: 'hospital', label: t('calendar.iconHospital') }, + { value: 'stethoscope', label: t('calendar.iconDoctor') }, + { value: 'syringe', label: t('calendar.iconVaccine') }, + { value: 'pill', label: t('calendar.iconMedicine') }, + { value: 'bandage', label: t('calendar.iconBandage') }, + { value: 'heart-pulse', label: t('calendar.iconHealth') }, + { value: 'activity', label: t('calendar.iconActivity') }, + { value: 'scissors', label: t('calendar.iconHaircut') }, + { value: 'dumbbell', label: t('calendar.iconSports') }, + { value: 'trophy', label: t('calendar.iconTrophy') }, + ], + }, + { + key: 'transport', + label: t('calendar.iconCategoryTransport'), + icons: [ + { value: 'car', label: t('calendar.iconCar') }, + { value: 'bus', label: t('calendar.iconBus') }, + { value: 'train', label: t('calendar.iconTrain') }, + { value: 'plane', label: t('calendar.iconPlane') }, + { value: 'plane-takeoff', label: t('calendar.iconFlight') }, + { value: 'fuel', label: t('calendar.iconFuel') }, + { value: 'navigation', label: t('calendar.iconNavigation') }, + ], + }, + { + key: 'work', + label: t('calendar.iconCategoryWork'), + icons: [ + { value: 'briefcase', label: t('calendar.iconWork') }, + { value: 'laptop', label: t('calendar.iconLaptop') }, + { value: 'presentation', label: t('calendar.iconPresentation') }, + { value: 'school', label: t('calendar.iconSchool') }, + { value: 'graduation-cap', label: t('calendar.iconEducation') }, + { value: 'book-open', label: t('calendar.iconReading') }, + { value: 'pencil', label: t('calendar.iconStudy') }, + { value: 'calculator', label: t('calendar.iconCalculator') }, + ], + }, + { + key: 'food', + label: t('calendar.iconCategoryFood'), + icons: [ + { value: 'utensils', label: t('calendar.iconMeal') }, + { value: 'cooking-pot', label: t('calendar.iconCooking') }, + { value: 'coffee', label: t('calendar.iconCoffee') }, + { value: 'cake', label: t('calendar.iconCake') }, + { value: 'pizza', label: t('calendar.iconPizza') }, + { value: 'wine', label: t('calendar.iconWine') }, + { value: 'beer', label: t('calendar.iconBeer') }, + ], + }, + { + key: 'shopping', + label: t('calendar.iconCategoryShopping'), + icons: [ + { value: 'shopping-bag', label: t('calendar.iconShopping') }, + { value: 'shopping-cart', label: t('calendar.iconGroceries') }, + { value: 'gift', label: t('calendar.iconGift') }, + { value: 'credit-card', label: t('calendar.iconCard') }, + { value: 'wallet', label: t('calendar.iconWallet') }, + { value: 'piggy-bank', label: t('calendar.iconSavings') }, + { value: 'landmark', label: t('calendar.iconBank') }, + ], + }, + { + key: 'leisure', + label: t('calendar.iconCategoryLeisure'), + icons: [ + { value: 'music', label: t('calendar.iconMusic') }, + { value: 'film', label: t('calendar.iconMovie') }, + { value: 'ticket', label: t('calendar.iconTicket') }, + { value: 'gamepad-2', label: t('calendar.iconGame') }, + { value: 'camera', label: t('calendar.iconPhoto') }, + { value: 'party-popper', label: t('calendar.iconParty') }, + ], + }, + { + key: 'family', + label: t('calendar.iconCategoryFamily'), + icons: [ + { value: 'users', label: t('calendar.iconFamily') }, + { value: 'baby', label: t('calendar.iconBaby') }, + { value: 'dog', label: t('calendar.iconDog') }, + { value: 'cat', label: t('calendar.iconCat') }, + { value: 'paw-print', label: t('calendar.iconPet') }, + ], + }, + { + key: 'home', + label: t('calendar.iconCategoryHome'), + icons: [ + { value: 'home', label: t('calendar.iconHome') }, + { value: 'building', label: t('calendar.iconBuilding') }, + { value: 'wrench', label: t('calendar.iconRepair') }, + { value: 'hammer', label: t('calendar.iconMaintenance') }, + { value: 'paintbrush', label: t('calendar.iconDecoration') }, + { value: 'sofa', label: t('calendar.iconFurniture') }, + { value: 'washing-machine', label: t('calendar.iconLaundry') }, + ], + }, + { + key: 'nature', + label: t('calendar.iconCategoryNature'), + icons: [ + { value: 'leaf', label: t('calendar.iconLeaf') }, + { value: 'tree-pine', label: t('calendar.iconTree') }, + { value: 'flower', label: t('calendar.iconFlower') }, + { value: 'sun', label: t('calendar.iconSun') }, + { value: 'moon', label: t('calendar.iconMoon') }, + { value: 'cloud-sun', label: t('calendar.iconWeather') }, + ], + }, ]; +// Flache Liste aller Icons für Kompatibilität (z.B. eventIconName-Validierung) +const EVENT_ICONS = EVENT_ICON_CATEGORIES().flatMap((cat) => cat.icons); + const CUSTOM_EVENT_ICONS = new Set(['tooth']); const MAX_ATTACHMENT_BYTES = 5 * 1024 * 1024; const ATTACHMENT_IMAGE_MIME = new Set(['image/png', 'image/jpeg', 'image/webp', 'image/gif']); @@ -556,7 +590,8 @@ async function navigate(dir) { if (state.view === 'month') { state.cursor = addMonths(state.cursor, dir); } else if (state.view === 'week') { - state.cursor = addDays(state.cursor, dir * 7); + const isMobile = window.matchMedia('(max-width: 639px)').matches; + state.cursor = addDays(state.cursor, dir * (isMobile ? 3 : 7)); } else if (state.view === 'day') { state.cursor = addDays(state.cursor, dir); } else if (state.view === 'agenda') { @@ -674,7 +709,7 @@ function renderMonthDay(date, inMonth) { data-id="${ev.id}" style="background-color:${esc(bg)};${fg ? `color:${fg};` : ''}" title="${esc(ev.title)}${ev.cal_name ? ' · ' + ev.cal_name : ''}" - >${eventIconHtml(ev.icon, 'event-icon event-icon--compact')}${esc(ev.title)}
+ >${eventIconHtml(ev.icon, 'event-icon event-icon--compact')}${esc(ev.title)}${(ev.recurrence_rule || ev.is_recurring_instance) ? '' : ''} `; }).join(''); @@ -692,8 +727,15 @@ function renderMonthDay(date, inMonth) { // -------------------------------------------------------- function renderWeekView(container) { - const monday = getMondayOf(state.cursor); - const days = Array.from({ length: 7 }, (_, i) => addDays(monday, i)); + const isMobile = window.matchMedia('(max-width: 639px)').matches; + // Auf Mobile: 3-Tage-Fenster zentriert um state.cursor statt vollem Mo–So + const days = isMobile + ? Array.from({ length: 3 }, (_, i) => addDays(state.cursor, i - 1)) + : (() => { + const monday = getMondayOf(state.cursor); + return Array.from({ length: 7 }, (_, i) => addDays(monday, i)); + })(); + const colCount = days.length; const alldayEvs = days.map((d) => eventsOnDay(d).filter((e) => e.all_day || !e.start_datetime.includes('T')) @@ -706,7 +748,7 @@ function renderWeekView(container) { container.innerHTML = `
+ style="display:grid;grid-template-columns:48px repeat(${colCount},1fr);">
${days.map((d) => { const dt = new Date(d + 'T00:00:00'); @@ -717,7 +759,7 @@ function renderWeekView(container) { }).join('')}
-
+
${t('calendar.allDayShort')}
${days.map((d, i) => `
@@ -739,7 +781,7 @@ function renderWeekView(container) { `).join('')}
+ style="display:grid;grid-template-columns:repeat(${colCount},1fr);"> ${days.map((d, i) => `
${Array.from({ length: 24 }, (_, h) => ` @@ -795,7 +837,7 @@ function renderWeekEvent(ev, layout = null) { return `
-
${eventIconHtml(ev.icon, 'event-icon event-icon--compact')}${esc(ev.title)}
+
${eventIconHtml(ev.icon, 'event-icon event-icon--compact')}${esc(ev.title)}${(ev.recurrence_rule || ev.is_recurring_instance) ? '' : ''}
${formatTime(ev.start_datetime)}${ev.end_datetime ? '–' + formatTime(ev.end_datetime) : ''}
`; @@ -1305,6 +1347,50 @@ function openEventModal({ mode, event = null, date = null, reminder = null }) { iconTrigger?.setAttribute('aria-expanded', 'false'); iconTrigger?.focus(); }); + + const iconSearch = iconGrid?.querySelector('#modal-icon-search'); + iconSearch?.addEventListener('input', () => { + const q = iconSearch.value.trim().toLowerCase(); + const resultsEl = iconGrid?.querySelector('#modal-icon-results'); + if (!resultsEl) return; + if (!q) { + resultsEl.replaceChildren(); + resultsEl.insertAdjacentHTML('afterbegin', EVENT_ICON_CATEGORIES().map((cat) => ` +
+
${esc(cat.label)}
+
+ ${cat.icons.map((icon) => ` + `).join('')} +
+
`).join('')); + if (window.lucide) lucide.createIcons({ el: resultsEl }); + return; + } + const allIcons = EVENT_ICON_CATEGORIES().flatMap((c) => c.icons); + const filtered = allIcons.filter((i) => i.label.toLowerCase().includes(q) || i.value.includes(q)); + resultsEl.replaceChildren(); + if (filtered.length === 0) { + resultsEl.insertAdjacentHTML('afterbegin', `
${esc(t('calendar.iconSearchEmpty'))}
`); + return; + } + resultsEl.insertAdjacentHTML('afterbegin', ` +
+ ${filtered.map((icon) => ` + `).join('')} +
`); + if (window.lucide) lucide.createIcons({ el: resultsEl }); + }); + document.addEventListener('click', function closeIconPicker(e) { if (!panel.isConnected) { document.removeEventListener('click', closeIconPicker); @@ -1403,17 +1489,23 @@ function buildEventModalContent({ mode, event, date, reminder = null }) { const endTime = isEdit && event.end_datetime && event.end_datetime.length > 10 ? localTime(event.end_datetime) : '10:00'; const selectedIcon = eventIconName(isEdit ? event.icon : 'calendar'); - const iconButtons = EVENT_ICONS.map((icon) => - `` - ).join(''); + const iconCats = EVENT_ICON_CATEGORIES(); + const iconCategoryButtons = iconCats.map((cat) => ` +
+
${esc(cat.label)}
+
+ ${cat.icons.map((icon) => ` + `).join('')} +
+
`).join(''); const userOpts = [ ``, @@ -1438,13 +1530,17 @@ function buildEventModalContent({ mode, event, date, reminder = null }) {
- +
diff --git a/public/pages/dashboard.js b/public/pages/dashboard.js index 38049e2..53b22fc 100644 --- a/public/pages/dashboard.js +++ b/public/pages/dashboard.js @@ -113,10 +113,23 @@ function showOnboarding(appContainer) { // NEU — primäre Inhalte (tasks, calendar) ganz oben const WIDGET_IDS = ['tasks', 'calendar', 'weather', 'meals', 'shopping', 'birthdays', 'budget', 'family', 'notes']; -const WIDGET_SIZE_OPTIONS = ['1x1', '1x2', '1x3', '1x4', '2x1', '2x2', '2x3', '2x4', '3x1', '3x2', '3x3', '3x4', '4x1', '4x2', '4x3', '4x4']; +const WIDGET_SIZE_PRESETS = [ + { value: '1x1', labelKey: 'dashboard.widgetSizeTiny' }, + { value: '2x1', labelKey: 'dashboard.widgetSizeNarrow' }, + { value: '2x2', labelKey: 'dashboard.widgetSizeStandard' }, + { value: '3x2', labelKey: 'dashboard.widgetSizeLarge' }, + { value: '4x2', labelKey: 'dashboard.widgetSizeFull' }, +]; + +// Alle bekannten Größen inkl. Legacy-Werte — für normalizeDashboardConfig-Validierung +const WIDGET_SIZE_OPTIONS = [...new Set([ + ...WIDGET_SIZE_PRESETS.map((p) => p.value), + '1x2', '1x3', '1x4', '2x3', '2x4', '3x1', '3x3', '3x4', '4x1', '4x3', '4x4', +])]; function widgetSizeLabel(size) { - return size; + const preset = WIDGET_SIZE_PRESETS.find((p) => p.value === size); + return preset ? t(preset.labelKey) : size; } function defaultWidgetSize(id) { @@ -621,7 +634,7 @@ function renderSizeMiniGridCells(size) { } function renderWidgetCustomizeControls(w) { - const sizeOptions = WIDGET_SIZE_OPTIONS.map((size) => ` + const sizeOptions = WIDGET_SIZE_PRESETS.map(({ value: size }) => ` `).join(''); diff --git a/public/pages/tasks.js b/public/pages/tasks.js index 9b2cc06..4e17e1b 100644 --- a/public/pages/tasks.js +++ b/public/pages/tasks.js @@ -317,7 +317,7 @@ function renderModalContent({ task = null, users = [], reminder = null } = {}) {
- + @@ -1128,6 +1128,27 @@ function renderFilters(container) { } bar.appendChild(toggleBtn); + + // ---- Zuletzt verwendete Filter als Quick-Chips ---- + const statusLabelsMap = STATUS_LABELS(); + const priorityLabelsMap = PRIORITY_LABELS(); + const recent = getRecentFilters(); + recent.forEach((f) => { + const parts = []; + if (f.status) parts.push(statusLabelsMap[f.status] ?? f.status); + if (f.priority) parts.push(priorityLabelsMap[f.priority] ?? f.priority); + if (f.assigned_to) { + const u = state.users.find((u) => u.id === Number(f.assigned_to)); + if (u) parts.push(u.display_name); + } + if (!parts.length) return; + const chip = document.createElement('span'); + chip.className = 'filter-chip filter-chip--recent'; + chip.dataset.recentFilter = JSON.stringify(f); + chip.textContent = parts.join(' · '); + bar.appendChild(chip); + }); + if (window.lucide) window.lucide.createIcons({ el: bar }); // ---- Filter-Panel: Gruppen mit allen Optionen ---- @@ -1245,8 +1266,24 @@ const SWIPE_THRESHOLD = 80; // px - Mindestweg für Aktion const SWIPE_MAX_VERT = 12; // px - vertikaler Bewegungs-Toleranzbereich (darunter: kein Scroll-Abbruch) const SWIPE_LOCK_VERT = 30; // px - ab diesem Weg gilt es als Scroll (Swipe abgebrochen) -const SWIPE_HINT_KEY = 'oikos:swipeHintSeen'; -const SWIPE_HINT_MAX = 3; +const SWIPE_HINT_KEY = 'oikos:swipeHintSeen'; +const SWIPE_HINT_MAX = 3; +const RECENT_FILTERS_KEY = 'oikos:recentTaskFilters'; +const RECENT_FILTERS_MAX = 3; + +function getRecentFilters() { + try { return JSON.parse(localStorage.getItem(RECENT_FILTERS_KEY) ?? '[]'); } catch { return []; } +} + +function saveRecentFilter(filters) { + if (!filters.status && !filters.priority && !filters.assigned_to) return; + const key = [filters.status, filters.priority, filters.assigned_to].join('|'); + const recent = getRecentFilters().filter((f) => + [f.status, f.priority, f.assigned_to].join('|') !== key + ); + recent.unshift({ ...filters }); + try { localStorage.setItem(RECENT_FILTERS_KEY, JSON.stringify(recent.slice(0, RECENT_FILTERS_MAX))); } catch {} +} function wireSwipeGestures(container) { const listEl = container.querySelector('#task-list'); @@ -1435,11 +1472,24 @@ function wireFilterChips(container) { state.filters[filter] = ''; } else { state.filters[filter] = chip.dataset.value; + saveRecentFilter(state.filters); } renderFilters(container); await loadTasks(container); }); }); + + // Recent-Filter-Chips anwenden + container.querySelectorAll('[data-recent-filter]').forEach((chip) => { + chip.addEventListener('click', async () => { + try { + const f = JSON.parse(chip.dataset.recentFilter); + state.filters = { status: f.status || '', priority: f.priority || '', assigned_to: f.assigned_to || '' }; + } catch { return; } + renderFilters(container); + await loadTasks(container); + }); + }); } function wireViewToggle(container) { diff --git a/public/styles/budget.css b/public/styles/budget.css index bffb69d..1d2135e 100644 --- a/public/styles/budget.css +++ b/public/styles/budget.css @@ -84,7 +84,7 @@ } .budget-tab { - min-height: 30px; + min-height: 40px; padding: 0 var(--space-2); border: 0; border-radius: var(--radius-xs); diff --git a/public/styles/calendar.css b/public/styles/calendar.css index eab690d..7130526 100644 --- a/public/styles/calendar.css +++ b/public/styles/calendar.css @@ -679,14 +679,43 @@ } .event-icon-picker__grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(44px, 1fr)); - gap: var(--space-2); + display: flex; + flex-direction: column; + gap: var(--space-3); margin: calc(var(--space-2) * -1) 0 var(--space-4) 0; padding: var(--space-3); border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface-2); + max-height: 320px; + overflow-y: auto; +} + +.event-icon-picker__search { + margin-bottom: var(--space-1); + background: var(--color-surface); +} + +.event-icon-picker__category-label { + font-size: var(--text-xs); + font-weight: var(--font-weight-semibold); + color: var(--color-text-tertiary); + text-transform: uppercase; + letter-spacing: 0.05em; + margin-bottom: var(--space-1); +} + +.event-icon-picker__category-icons { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(44px, 1fr)); + gap: var(--space-2); +} + +.event-icon-picker__no-results { + font-size: var(--text-sm); + color: var(--color-text-tertiary); + text-align: center; + padding: var(--space-4) 0; } .event-icon-picker__grid[hidden] { diff --git a/public/styles/layout.css b/public/styles/layout.css index 3368ebe..a1440dd 100755 --- a/public/styles/layout.css +++ b/public/styles/layout.css @@ -1174,12 +1174,20 @@ html.fab-anim-done .page-fab { .modal-panel::before { content: ''; position: absolute; - top: var(--space-3); + top: 0; left: 50%; transform: translateX(-50%); + /* Visuelle Linie bleibt klein, Hit-Area ist 44px hoch */ width: 36px; - height: var(--space-1); - background: var(--color-border); + height: 44px; + background-color: transparent; + background-image: linear-gradient( + to bottom, + transparent calc(50% - 2px), + var(--color-border) calc(50% - 2px), + var(--color-border) calc(50% + 2px), + transparent calc(50% + 2px) + ); border-radius: var(--radius-full); } @@ -1355,6 +1363,14 @@ html.fab-anim-done .page-fab { margin-bottom: var(--space-1); } +.required-marker { + color: var(--color-danger); + margin-left: var(--space-0h); + font-size: var(--text-xs); + font-weight: var(--font-weight-bold); + line-height: 1; +} + .form-group { display: flex; flex-direction: column; @@ -2089,6 +2105,33 @@ html.fab-anim-done .page-fab { animation: swipe-nudge 0.8s var(--ease-out) 1.2s both; } +/* Swipe-Affordanz: permanente Chevron-Hints an den Kartenrändern */ +.swipe-row::after { + content: ''; + position: absolute; + right: var(--space-2); + top: 50%; + transform: translateY(-50%); + width: 12px; + height: 20px; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 20' fill='none' stroke='%23888' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='3,4 9,10 3,16'/%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-size: contain; + opacity: 0.3; + pointer-events: none; + z-index: 1; + transition: opacity var(--transition-fast); +} + +.swipe-row:hover::after, +.swipe-row:focus-within::after { + opacity: 0.55; +} + +@media (prefers-reduced-motion: reduce) { + .swipe-row::after { display: none; } +} + /* Gemeinsam: Erledigt / Abhaken (Swipe nach links) */ .swipe-reveal--done { right: 0; diff --git a/public/styles/tasks.css b/public/styles/tasks.css index 9b1c76a..bf7f3e5 100644 --- a/public/styles/tasks.css +++ b/public/styles/tasks.css @@ -148,6 +148,18 @@ } } +.filter-chip--recent { + border-style: dashed; + opacity: 0.8; + cursor: pointer; +} + +.filter-chip--recent:hover { + opacity: 1; + border-color: var(--color-accent); + color: var(--color-accent); +} + .filter-chip__remove { width: 16px; height: 16px;