Quick fixes to lang plus mmap realtime

This commit is contained in:
AlacrisDevs
2026-02-08 23:30:09 +02:00
parent f2384bceb8
commit ce80dc6d75
5 changed files with 438 additions and 242 deletions

View File

@@ -1,4 +1,4 @@
{ {
"$schema": "https://inlang.com/schema/inlang-message-format", "$schema": "https://inlang.com/schema/inlang-message-format",
"app_name": "Root", "app_name": "Root",
"nav_files": "Failid", "nav_files": "Failid",
@@ -7,28 +7,28 @@
"nav_kanban": "Kanban", "nav_kanban": "Kanban",
"user_menu_account_settings": "Konto seaded", "user_menu_account_settings": "Konto seaded",
"user_menu_switch_org": "Vaheta organisatsiooni", "user_menu_switch_org": "Vaheta organisatsiooni",
"user_menu_logout": "Logi vƤlja", "user_menu_logout": "Logi välja",
"btn_new": "Uus", "btn_new": "Uus",
"btn_create": "Loo", "btn_create": "Loo",
"btn_cancel": "Tühista", "btn_cancel": "Tühista",
"btn_save": "Salvesta", "btn_save": "Salvesta",
"btn_delete": "Kustuta", "btn_delete": "Kustuta",
"btn_edit": "Muuda", "btn_edit": "Muuda",
"btn_close": "Sulge", "btn_close": "Sulge",
"btn_upload": "Laadi üles", "btn_upload": "Laadi üles",
"btn_remove": "Eemalda", "btn_remove": "Eemalda",
"login_title": "Tere tulemast Rooti", "login_title": "Tere tulemast rooti",
"login_subtitle": "Sinu meeskonna tƶƶruum dokumentide, tahvlite ja kalendrite jaoks.", "login_subtitle": "Sinu meeskonna tööruum dokumentide, tahvlite ja kalendrite jaoks.",
"login_tab_login": "Logi sisse", "login_tab_login": "Logi sisse",
"login_tab_signup": "Registreeru", "login_tab_signup": "Registreeru",
"login_email_label": "E-post", "login_email_label": "E-post",
"login_email_placeholder": "sina@nƤide.ee", "login_email_placeholder": "sina@näide.ee",
"login_password_label": "Parool", "login_password_label": "Parool",
"login_password_placeholder": "••••••••", "login_password_placeholder": "••••••••",
"login_btn_login": "Logi sisse", "login_btn_login": "Logi sisse",
"login_btn_signup": "Registreeru", "login_btn_signup": "Registreeru",
"login_or_continue": "vƵi jƤtka", "login_or_continue": "või jätka",
"login_google": "JƤtka Google'iga", "login_google": "Jätka Google'iga",
"login_signup_prompt": "Pole kontot?", "login_signup_prompt": "Pole kontot?",
"login_login_prompt": "On juba konto?", "login_login_prompt": "On juba konto?",
"login_signup_success_title": "Kontrolli oma e-posti", "login_signup_success_title": "Kontrolli oma e-posti",
@@ -38,9 +38,9 @@
"org_selector_create_title": "Loo organisatsioon", "org_selector_create_title": "Loo organisatsioon",
"org_selector_name_label": "Organisatsiooni nimi", "org_selector_name_label": "Organisatsiooni nimi",
"org_selector_name_placeholder": "Minu meeskond", "org_selector_name_placeholder": "Minu meeskond",
"org_selector_slug_label": "URL-i lühend", "org_selector_slug_label": "URL-i lühend",
"org_selector_slug_placeholder": "minu-meeskond", "org_selector_slug_placeholder": "minu-meeskond",
"org_overview": "Organisatsiooni ülevaade", "org_overview": "Organisatsiooni ülevaade",
"files_title": "Failid", "files_title": "Failid",
"files_breadcrumb_home": "Avaleht", "files_breadcrumb_home": "Avaleht",
"files_create_title": "Loo uus", "files_create_title": "Loo uus",
@@ -51,8 +51,8 @@
"files_doc_placeholder": "Dokumendi nimi", "files_doc_placeholder": "Dokumendi nimi",
"files_folder_placeholder": "Kausta nimi", "files_folder_placeholder": "Kausta nimi",
"files_kanban_placeholder": "Kanban tahvli nimi", "files_kanban_placeholder": "Kanban tahvli nimi",
"files_rename_title": "Nimeta ümber", "files_rename_title": "Nimeta ümber",
"files_context_rename": "Nimeta ümber", "files_context_rename": "Nimeta ümber",
"files_context_move": "Teisalda...", "files_context_move": "Teisalda...",
"files_context_delete": "Kustuta", "files_context_delete": "Kustuta",
"files_context_open_tab": "Ava uuel vahelehel", "files_context_open_tab": "Ava uuel vahelehel",
@@ -63,36 +63,36 @@
"kanban_board_name_label": "Tahvli nimi", "kanban_board_name_label": "Tahvli nimi",
"kanban_board_name_placeholder": "nt Sprint 1", "kanban_board_name_placeholder": "nt Sprint 1",
"kanban_edit_board": "Muuda tahvlit", "kanban_edit_board": "Muuda tahvlit",
"kanban_rename_board": "Nimeta tahvel ümber", "kanban_rename_board": "Nimeta tahvel ümber",
"kanban_delete_board": "Kustuta tahvel", "kanban_delete_board": "Kustuta tahvel",
"kanban_add_column": "Lisa veerg", "kanban_add_column": "Lisa veerg",
"kanban_column_name_label": "Veeru nimi", "kanban_column_name_label": "Veeru nimi",
"kanban_column_name_placeholder": "nt Teha, Tƶƶs, Valmis", "kanban_column_name_placeholder": "nt Teha, Töös, Valmis",
"kanban_add_card": "Lisa kaart", "kanban_add_card": "Lisa kaart",
"kanban_card_details": "Kaardi üksikasjad", "kanban_card_details": "Kaardi üksikasjad",
"kanban_card_title_label": "Pealkiri", "kanban_card_title_label": "Pealkiri",
"kanban_card_title_placeholder": "Kaardi pealkiri", "kanban_card_title_placeholder": "Kaardi pealkiri",
"kanban_card_desc_label": "Kirjeldus", "kanban_card_desc_label": "Kirjeldus",
"kanban_card_desc_placeholder": "Lisa üksikasjalikum kirjeldus...", "kanban_card_desc_placeholder": "Lisa üksikasjalikum kirjeldus...",
"kanban_tags": "Sildid", "kanban_tags": "Sildid",
"kanban_tag_placeholder": "Sildi nimi", "kanban_tag_placeholder": "Sildi nimi",
"kanban_tag_add": "Lisa", "kanban_tag_add": "Lisa",
"kanban_empty": "Kanban tahvleid hallatakse nüüd Failides", "kanban_empty": "Kanban tahvleid hallatakse nüüd Failides",
"kanban_go_to_files": "Mine Failidesse", "kanban_go_to_files": "Mine Failidesse",
"kanban_select_board": "Vali tahvel ülalt", "kanban_select_board": "Vali tahvel ülalt",
"calendar_title": "Kalender", "calendar_title": "Kalender",
"calendar_subscribe": "Telli kalender", "calendar_subscribe": "Telli kalender",
"calendar_refresh": "VƤrskenda sündmusi", "calendar_refresh": "Värskenda sündmusi",
"calendar_settings": "Kalendri seaded", "calendar_settings": "Kalendri seaded",
"calendar_create_event": "Loo sündmus", "calendar_create_event": "Loo sündmus",
"calendar_edit_event": "Muuda sündmust", "calendar_edit_event": "Muuda sündmust",
"calendar_event_title": "Pealkiri", "calendar_event_title": "Pealkiri",
"calendar_event_title_placeholder": "Sündmuse pealkiri", "calendar_event_title_placeholder": "Sündmuse pealkiri",
"calendar_event_date": "KuupƤev", "calendar_event_date": "Kuupäev",
"calendar_event_time": "Kellaaeg", "calendar_event_time": "Kellaaeg",
"calendar_event_desc": "Kirjeldus", "calendar_event_desc": "Kirjeldus",
"settings_title": "Seaded", "settings_title": "Seaded",
"settings_tab_general": "Üldine", "settings_tab_general": "Üldine",
"settings_tab_members": "Liikmed", "settings_tab_members": "Liikmed",
"settings_tab_roles": "Rollid", "settings_tab_roles": "Rollid",
"settings_tab_tags": "Sildid", "settings_tab_tags": "Sildid",
@@ -101,12 +101,12 @@
"settings_general_avatar": "Avatar", "settings_general_avatar": "Avatar",
"settings_general_name": "Nimi", "settings_general_name": "Nimi",
"settings_general_name_placeholder": "Organisatsiooni nimi", "settings_general_name_placeholder": "Organisatsiooni nimi",
"settings_general_slug": "URL-i lühend (sait.ee/...)", "settings_general_slug": "URL-i lühend (sait.ee/...)",
"settings_general_slug_placeholder": "minu-org", "settings_general_slug_placeholder": "minu-org",
"settings_general_save": "Salvesta muudatused", "settings_general_save": "Salvesta muudatused",
"settings_general_danger_zone": "Ohutsoon", "settings_general_danger_zone": "Ohutsoon",
"settings_general_delete_org": "Kustuta organisatsioon", "settings_general_delete_org": "Kustuta organisatsioon",
"settings_general_delete_org_desc": "Kustuta see organisatsioon ja kƵik selle andmed jƤƤdavalt.", "settings_general_delete_org_desc": "Kustuta see organisatsioon ja kõik selle andmed jäädavalt.",
"settings_general_leave_org": "Lahku organisatsioonist", "settings_general_leave_org": "Lahku organisatsioonist",
"settings_general_leave_org_desc": "Lahku sellest organisatsioonist. Tagasi liitumiseks on vaja uut kutset.", "settings_general_leave_org_desc": "Lahku sellest organisatsioonist. Tagasi liitumiseks on vaja uut kutset.",
"settings_general_leave_btn": "Lahku {orgName}", "settings_general_leave_btn": "Lahku {orgName}",
@@ -134,7 +134,7 @@
"settings_social_twitch_placeholder": "https://twitch.tv/sinuorg", "settings_social_twitch_placeholder": "https://twitch.tv/sinuorg",
"settings_social_save": "Salvesta lingid", "settings_social_save": "Salvesta lingid",
"settings_tags_title": "Organisatsiooni sildid", "settings_tags_title": "Organisatsiooni sildid",
"settings_tags_desc": "Halda silte, mida saab kasutada kƵigil Kanban tahvlitel.", "settings_tags_desc": "Halda silte, mida saab kasutada kõigil Kanban tahvlitel.",
"settings_tags_create": "Loo silt", "settings_tags_create": "Loo silt",
"settings_tags_empty": "Silte pole veel. Loo oma esimene silt Kanban kaartide korraldamiseks.", "settings_tags_empty": "Silte pole veel. Loo oma esimene silt Kanban kaartide korraldamiseks.",
"settings_tags_name_placeholder": "Sildi nimi", "settings_tags_name_placeholder": "Sildi nimi",
@@ -149,7 +149,7 @@
"settings_members_remove": "Eemalda organisatsioonist", "settings_members_remove": "Eemalda organisatsioonist",
"settings_invite_title": "Kutsu liige", "settings_invite_title": "Kutsu liige",
"settings_invite_email": "E-posti aadress", "settings_invite_email": "E-posti aadress",
"settings_invite_email_placeholder": "kolleeg@nƤide.ee", "settings_invite_email_placeholder": "kolleeg@näide.ee",
"settings_invite_role": "Roll", "settings_invite_role": "Roll",
"settings_invite_send": "Saada kutse", "settings_invite_send": "Saada kutse",
"settings_invite_role_viewer": "Vaataja - Saab sisu vaadata", "settings_invite_role_viewer": "Vaataja - Saab sisu vaadata",
@@ -158,42 +158,42 @@
"settings_invite_role_admin": "Admin - Saab hallata liikmeid ja seadeid", "settings_invite_role_admin": "Admin - Saab hallata liikmeid ja seadeid",
"settings_edit_member": "Muuda liiget", "settings_edit_member": "Muuda liiget",
"settings_roles_title": "Rollid", "settings_roles_title": "Rollid",
"settings_roles_desc": "Loo kohandatud rolle kindlate Ƶigustega.", "settings_roles_desc": "Loo kohandatud rolle kindlate õigustega.",
"settings_roles_create": "Loo roll", "settings_roles_create": "Loo roll",
"settings_roles_edit": "Muuda rolli", "settings_roles_edit": "Muuda rolli",
"settings_roles_system": "Süsteemne", "settings_roles_system": "Süsteemne",
"settings_roles_default": "Vaikimisi", "settings_roles_default": "Vaikimisi",
"settings_roles_all_perms": "KƵik Ƶigused", "settings_roles_all_perms": "Kõik õigused",
"settings_roles_more": "+{count} veel", "settings_roles_more": "+{count} veel",
"settings_roles_name_label": "Nimi", "settings_roles_name_label": "Nimi",
"settings_roles_name_placeholder": "nt Moderaator", "settings_roles_name_placeholder": "nt Moderaator",
"settings_roles_color": "VƤrv", "settings_roles_color": "Värv",
"settings_roles_permissions": "Ć•igused", "settings_roles_permissions": "Õigused",
"settings_integrations_google_cal": "Google'i kalender", "settings_integrations_google_cal": "Google'i kalender",
"settings_integrations_google_cal_desc": "Jaga Google'i kalendrit kƵigi organisatsiooni liikmetega.", "settings_integrations_google_cal_desc": "Jaga Google'i kalendrit kõigi organisatsiooni liikmetega.",
"settings_integrations_connected": "Ühendatud", "settings_integrations_connected": "Ühendatud",
"settings_integrations_disconnect": "Katkesta ühendus", "settings_integrations_disconnect": "Katkesta ühendus",
"settings_integrations_connect": "Ühenda Google'i kalender", "settings_integrations_connect": "Ühenda Google'i kalender",
"settings_integrations_discord": "Discord", "settings_integrations_discord": "Discord",
"settings_integrations_discord_desc": "Saa teavitusi oma Discordi serveris.", "settings_integrations_discord_desc": "Saa teavitusi oma Discordi serveris.",
"settings_integrations_slack": "Slack", "settings_integrations_slack": "Slack",
"settings_integrations_slack_desc": "Saa teavitusi oma Slacki tƶƶruumis.", "settings_integrations_slack_desc": "Saa teavitusi oma Slacki tööruumis.",
"settings_integrations_coming_soon": "Tulekul", "settings_integrations_coming_soon": "Tulekul",
"settings_connect_cal_title": "Ühenda avalik Google'i kalender", "settings_connect_cal_title": "Ühenda avalik Google'i kalender",
"settings_connect_cal_desc": "Kleebi oma Google'i kalendri jagamislink vƵi kalendri ID. Kalender peab olema Google'i kalendri seadetes avalikuks seatud.", "settings_connect_cal_desc": "Kleebi oma Google'i kalendri jagamislink või kalendri ID. Kalender peab olema Google'i kalendri seadetes avalikuks seatud.",
"settings_connect_cal_how": "Kuidas saada kalendri linki:", "settings_connect_cal_how": "Kuidas saada kalendri linki:",
"settings_connect_cal_step1": "Ava Google'i kalender", "settings_connect_cal_step1": "Ava Google'i kalender",
"settings_connect_cal_step2": "Kliki kalendri kƵrval 3 punkti → Seaded", "settings_connect_cal_step2": "Kliki kalendri kõrval 3 punkti → Seaded",
"settings_connect_cal_step3": "\"JuurdepƤƤsuƵiguste\" all mƤrgi \"Tee avalikuks\"", "settings_connect_cal_step3": "\"Juurdepääsuõiguste\" all märgi \"Tee avalikuks\"",
"settings_connect_cal_step4": "Keri alla \"Kalendri integreerimine\" ja kopeeri kalendri ID vƵi avalik URL", "settings_connect_cal_step4": "Keri alla \"Kalendri integreerimine\" ja kopeeri kalendri ID või avalik URL",
"settings_connect_cal_input_label": "Kalendri URL vƵi ID", "settings_connect_cal_input_label": "Kalendri URL või ID",
"settings_connect_cal_input_placeholder": "Kleebi kalendri URL vƵi ID (nt abc123@group.calendar.google.com)", "settings_connect_cal_input_placeholder": "Kleebi kalendri URL või ID (nt abc123@group.calendar.google.com)",
"settings_connect_cal_btn": "Ühenda", "settings_connect_cal_btn": "Ühenda",
"account_title": "Konto seaded", "account_title": "Konto seaded",
"account_subtitle": "Halda oma isiklikku profiili ja eelistusi.", "account_subtitle": "Halda oma isiklikku profiili ja eelistusi.",
"account_profile": "Profiil", "account_profile": "Profiil",
"account_photo": "Foto", "account_photo": "Foto",
"account_sync_google": "Sünkrooni Google", "account_sync_google": "Sünkrooni Google",
"account_remove_photo": "Eemalda foto", "account_remove_photo": "Eemalda foto",
"account_display_name": "Kuvatav nimi", "account_display_name": "Kuvatav nimi",
"account_display_name_placeholder": "Sinu nimi", "account_display_name_placeholder": "Sinu nimi",
@@ -203,16 +203,16 @@
"account_discord": "Discord", "account_discord": "Discord",
"account_discord_placeholder": "kasutajanimi", "account_discord_placeholder": "kasutajanimi",
"account_contact_info": "Kontakt ja suurused", "account_contact_info": "Kontakt ja suurused",
"account_shirt_size": "SƤrgi suurus", "account_shirt_size": "Särgi suurus",
"account_hoodie_size": "Pusa suurus", "account_hoodie_size": "Pusa suurus",
"account_size_placeholder": "Vali suurus", "account_size_placeholder": "Vali suurus",
"account_save_profile": "Salvesta profiil", "account_save_profile": "Salvesta profiil",
"account_appearance": "VƤlimus", "account_appearance": "Välimus",
"account_theme": "Teema", "account_theme": "Teema",
"account_theme_dark": "Tume", "account_theme_dark": "Tume",
"account_theme_light": "Hele (tulekul)", "account_theme_light": "Hele (tulekul)",
"account_theme_system": "Süsteemne (tulekul)", "account_theme_system": "Süsteemne (tulekul)",
"account_accent_color": "AktsentvƤrv", "account_accent_color": "Aktsentvärv",
"account_use_org_theme": "Kasuta organisatsiooni teemat", "account_use_org_theme": "Kasuta organisatsiooni teemat",
"account_use_org_theme_desc": "Asenda oma isiklik teema organisatsiooni seadetega.", "account_use_org_theme_desc": "Asenda oma isiklik teema organisatsiooni seadetega.",
"account_language": "Keel", "account_language": "Keel",
@@ -220,11 +220,11 @@
"account_save_preferences": "Salvesta eelistused", "account_save_preferences": "Salvesta eelistused",
"account_security": "Turvalisus ja seansid", "account_security": "Turvalisus ja seansid",
"account_password": "Parool", "account_password": "Parool",
"account_password_desc": "Kui logisid sisse Google'iga, haldab sinu parooli Google. Muul juhul saad parooli e-posti teel lƤhtestada.", "account_password_desc": "Kui logisid sisse Google'iga, haldab sinu parooli Google. Muul juhul saad parooli e-posti teel lähtestada.",
"account_send_reset": "Saada lƤhtestamise e-kiri", "account_send_reset": "Saada lähtestamise e-kiri",
"account_active_sessions": "Aktiivsed seansid", "account_active_sessions": "Aktiivsed seansid",
"account_sessions_desc": "Logi vƤlja kƵigist teistest seanssidest, kui kahtlustad volitamata juurdepƤƤsu.", "account_sessions_desc": "Logi välja kõigist teistest seanssidest, kui kahtlustad volitamata juurdepääsu.",
"account_signout_others": "Logi teised seansid vƤlja", "account_signout_others": "Logi teised seansid välja",
"editor_save": "Salvesta", "editor_save": "Salvesta",
"editor_saving": "Salvestamine...", "editor_saving": "Salvestamine...",
"editor_saved": "Salvestatud", "editor_saved": "Salvestatud",
@@ -232,33 +232,33 @@
"editor_placeholder": "Alusta kirjutamist...", "editor_placeholder": "Alusta kirjutamist...",
"editor_bold": "Paks (Ctrl+B)", "editor_bold": "Paks (Ctrl+B)",
"editor_italic": "Kursiiv (Ctrl+I)", "editor_italic": "Kursiiv (Ctrl+I)",
"editor_strikethrough": "LƤbikriipsutus", "editor_strikethrough": "Läbikriipsutus",
"editor_bullet_list": "TƤpploend", "editor_bullet_list": "Täpploend",
"editor_numbered_list": "Nummerdatud loend", "editor_numbered_list": "Nummerdatud loend",
"editor_quote": "Tsitaat", "editor_quote": "Tsitaat",
"editor_code_block": "Koodiplokk", "editor_code_block": "Koodiplokk",
"toast_error_delete_org": "Organisatsiooni kustutamine ebaƵnnestus.", "toast_error_delete_org": "Organisatsiooni kustutamine ebaõnnestus.",
"toast_error_leave_org": "Organisatsioonist lahkumine ebaƵnnestus.", "toast_error_leave_org": "Organisatsioonist lahkumine ebaõnnestus.",
"toast_error_invite": "Kutse saatmine ebaƵnnestus: {error}", "toast_error_invite": "Kutse saatmine ebaõnnestus: {error}",
"toast_error_update_role": "Rolli uuendamine ebaƵnnestus.", "toast_error_update_role": "Rolli uuendamine ebaõnnestus.",
"toast_error_remove_member": "Liikme eemaldamine ebaƵnnestus.", "toast_error_remove_member": "Liikme eemaldamine ebaõnnestus.",
"toast_error_delete_role": "Rolli kustutamine ebaƵnnestus.", "toast_error_delete_role": "Rolli kustutamine ebaõnnestus.",
"toast_error_disconnect_cal": "Kalendri lahtiühendamine ebaƵnnestus.", "toast_error_disconnect_cal": "Kalendri lahtiühendamine ebaõnnestus.",
"toast_error_reset_email": "LƤhtestamise e-kirja saatmine ebaƵnnestus.", "toast_error_reset_email": "Lähtestamise e-kirja saatmine ebaõnnestus.",
"toast_success_reset_email": "Parooli lƤhtestamise e-kiri saadetud.", "toast_success_reset_email": "Parooli lähtestamise e-kiri saadetud.",
"toast_success_signout_others": "Teised seansid vƤlja logitud.", "toast_success_signout_others": "Teised seansid välja logitud.",
"confirm_delete_role": "Kustuta roll \"{name}\"? Selle rolliga liikmed tuleb ümber mƤƤrata.", "confirm_delete_role": "Kustuta roll \"{name}\"? Selle rolliga liikmed tuleb ümber määrata.",
"confirm_leave_org": "Kas oled kindel, et soovid lahkuda {orgName}?", "confirm_leave_org": "Kas oled kindel, et soovid lahkuda {orgName}?",
"confirm_delete_org": "Sisesta \"{orgName}\" kustutamise kinnitamiseks:", "confirm_delete_org": "Sisesta \"{orgName}\" kustutamise kinnitamiseks:",
"confirm_remove_member": "Eemalda {name} organisatsioonist?", "confirm_remove_member": "Eemalda {name} organisatsioonist?",
"confirm_disconnect_cal": "Katkesta Google'i kalendri ühendus?", "confirm_disconnect_cal": "Katkesta Google'i kalendri ühendus?",
"role_viewer": "Vaataja", "role_viewer": "Vaataja",
"role_commenter": "Kommenteerija", "role_commenter": "Kommenteerija",
"role_editor": "Toimetaja", "role_editor": "Toimetaja",
"role_admin": "Admin", "role_admin": "Admin",
"role_owner": "Omanik", "role_owner": "Omanik",
"error_owner_cant_leave": "Omanikud ei saa lahkuda. KƵigepealt anna omandiƵigus üle vƵi kustuta organisatsioon.", "error_owner_cant_leave": "Omanikud ei saa lahkuda. Kõigepealt anna omandiõigus üle või kustuta organisatsioon.",
"overview_title": "Organisatsiooni ülevaade", "overview_title": "Organisatsiooni ülevaade",
"overview_stat_members": "Liikmed", "overview_stat_members": "Liikmed",
"overview_stat_documents": "Dokumendid", "overview_stat_documents": "Dokumendid",
"overview_stat_folders": "Kaustad", "overview_stat_folders": "Kaustad",
@@ -266,11 +266,11 @@
"overview_quick_links": "Kiirlingid", "overview_quick_links": "Kiirlingid",
"activity_title": "Viimane tegevus", "activity_title": "Viimane tegevus",
"activity_empty": "Viimast tegevust pole veel.", "activity_empty": "Viimast tegevust pole veel.",
"activity_created": "{user} lƵi {entityType} \"{name}\"", "activity_created": "{user} lõi {entityType} \"{name}\"",
"activity_updated": "{user} uuendas {entityType} \"{name}\"", "activity_updated": "{user} uuendas {entityType} \"{name}\"",
"activity_deleted": "{user} kustutas {entityType} \"{name}\"", "activity_deleted": "{user} kustutas {entityType} \"{name}\"",
"activity_moved": "{user} teisaldas {entityType} \"{name}\"", "activity_moved": "{user} teisaldas {entityType} \"{name}\"",
"activity_renamed": "{user} nimetas ümber {entityType} \"{name}\"", "activity_renamed": "{user} nimetas ümber {entityType} \"{name}\"",
"activity_just_now": "Just praegu", "activity_just_now": "Just praegu",
"activity_minutes_ago": "{count} min tagasi", "activity_minutes_ago": "{count} min tagasi",
"activity_hours_ago": "{count}t tagasi", "activity_hours_ago": "{count}t tagasi",
@@ -283,88 +283,88 @@
"entity_member": "liikme", "entity_member": "liikme",
"entity_role": "rolli", "entity_role": "rolli",
"entity_invite": "kutse", "entity_invite": "kutse",
"entity_event": "ürituse", "entity_event": "ürituse",
"nav_events": "Üritused", "nav_events": "Üritused",
"nav_chat": "Vestlus", "nav_chat": "Vestlus",
"chat_title": "Vestlus", "chat_title": "Vestlus",
"chat_subtitle": "Meeskonna sƵnumid ja suhtlus", "chat_subtitle": "Meeskonna sõnumid ja suhtlus",
"events_title": "Üritused", "events_title": "Üritused",
"events_subtitle": "Korralda ja halda oma üritusi", "events_subtitle": "Korralda ja halda oma üritusi",
"events_new": "Uus üritus", "events_new": "Uus üritus",
"events_create": "Loo üritus", "events_create": "Loo üritus",
"events_empty_title": "Üritusi pole veel", "events_empty_title": "Üritusi pole veel",
"events_empty_desc": "Loo oma esimene üritus alustamiseks", "events_empty_desc": "Loo oma esimene üritus alustamiseks",
"events_no_dates": "KuupƤevad mƤƤramata", "events_no_dates": "Kuupäevad määramata",
"events_tab_all": "KƵik üritused", "events_tab_all": "Kõik üritused",
"events_tab_planning": "Planeerimisel", "events_tab_planning": "Planeerimisel",
"events_tab_active": "Aktiivne", "events_tab_active": "Aktiivne",
"events_tab_completed": "LƵpetatud", "events_tab_completed": "Lõpetatud",
"events_tab_archived": "Arhiveeritud", "events_tab_archived": "Arhiveeritud",
"events_status_planning": "Planeerimisel", "events_status_planning": "Planeerimisel",
"events_status_active": "Aktiivne", "events_status_active": "Aktiivne",
"events_status_completed": "LƵpetatud", "events_status_completed": "Lõpetatud",
"events_status_archived": "Arhiveeritud", "events_status_archived": "Arhiveeritud",
"events_form_name": "Ürituse nimi", "events_form_name": "Ürituse nimi",
"events_form_name_placeholder": "nt Suvekonverents 2026", "events_form_name_placeholder": "nt Suvekonverents 2026",
"events_form_description": "Kirjeldus", "events_form_description": "Kirjeldus",
"events_form_description_placeholder": "Ürituse lühikirjeldus...", "events_form_description_placeholder": "Ürituse lühikirjeldus...",
"events_form_start_date": "AlguskuupƤev", "events_form_start_date": "Alguskuupäev",
"events_form_end_date": "LƵppkuupƤev", "events_form_end_date": "Lõppkuupäev",
"events_form_venue": "Toimumiskoht", "events_form_venue": "Toimumiskoht",
"events_form_venue_placeholder": "nt Konverentsikeskus", "events_form_venue_placeholder": "nt Konverentsikeskus",
"events_form_venue_address_placeholder": "Toimumiskoha aadress", "events_form_venue_address_placeholder": "Toimumiskoha aadress",
"events_form_color": "VƤrv", "events_form_color": "Värv",
"events_form_select_color": "Vali vƤrv {color}", "events_form_select_color": "Vali värv {color}",
"events_creating": "Loomine...", "events_creating": "Loomine...",
"events_saving": "Salvestamine...", "events_saving": "Salvestamine...",
"events_deleting": "Kustutamine...", "events_deleting": "Kustutamine...",
"events_updated": "Üritus uuendatud", "events_updated": "Üritus uuendatud",
"events_created": "Üritus \"{name}\" loodud", "events_created": "Üritus \"{name}\" loodud",
"events_deleted": "Üritus kustutatud", "events_deleted": "Üritus kustutatud",
"events_delete_title": "Kustuta üritus?", "events_delete_title": "Kustuta üritus?",
"events_delete_desc": "See kustutab jƤƤdavalt ürituse {name} ja kƵik selle andmed. Seda toimingut ei saa tagasi vƵtta.", "events_delete_desc": "See kustutab jäädavalt ürituse {name} ja kõik selle andmed. Seda toimingut ei saa tagasi võtta.",
"events_delete_confirm": "Kustuta üritus", "events_delete_confirm": "Kustuta üritus",
"events_days_ago": "{count} pƤeva tagasi", "events_days_ago": "{count} päeva tagasi",
"events_today": "TƤna!", "events_today": "Täna!",
"events_tomorrow": "Homme", "events_tomorrow": "Homme",
"events_in_days": "{count} pƤeva pƤrast", "events_in_days": "{count} päeva pärast",
"events_overview": "Ülevaade", "events_overview": "Ülevaade",
"events_modules": "Moodulid", "events_modules": "Moodulid",
"events_details": "Ürituse andmed", "events_details": "Ürituse andmed",
"events_start_date": "AlguskuupƤev", "events_start_date": "Alguskuupäev",
"events_end_date": "LƵppkuupƤev", "events_end_date": "Lõppkuupäev",
"events_venue": "Toimumiskoht", "events_venue": "Toimumiskoht",
"events_not_set": "MƤƤramata", "events_not_set": "Määramata",
"events_all_events": "KƵik üritused", "events_all_events": "Kõik üritused",
"events_team": "Meeskond", "events_team": "Meeskond",
"events_team_count": "Meeskond ({count})", "events_team_count": "Meeskond ({count})",
"events_team_manage": "Halda", "events_team_manage": "Halda",
"events_team_empty": "Meeskonnaliikmeid pole veel mƤƤratud", "events_team_empty": "Meeskonnaliikmeid pole veel määratud",
"events_more_members": "+{count} veel", "events_more_members": "+{count} veel",
"events_mod_tasks": "Ülesanded", "events_mod_tasks": "Ülesanded",
"events_mod_tasks_desc": "Halda ülesandeid, verstaposte ja edenemist", "events_mod_tasks_desc": "Halda ülesandeid, verstaposte ja edenemist",
"events_mod_files": "Failid", "events_mod_files": "Failid",
"events_mod_files_desc": "Dokumendid, lepingud ja meedia", "events_mod_files_desc": "Dokumendid, lepingud ja meedia",
"events_mod_schedule": "Ajakava", "events_mod_schedule": "Ajakava",
"events_mod_schedule_desc": "Ürituse ajakava ja programm", "events_mod_schedule_desc": "Ürituse ajakava ja programm",
"events_mod_budget": "Eelarve", "events_mod_budget": "Eelarve",
"events_mod_budget_desc": "Tulud, kulud ja jƤlgimine", "events_mod_budget_desc": "Tulud, kulud ja jälgimine",
"events_mod_guests": "Külalised", "events_mod_guests": "Külalised",
"events_mod_guests_desc": "Külaliste nimekiri ja registreerimine", "events_mod_guests_desc": "Külaliste nimekiri ja registreerimine",
"events_mod_team": "Meeskond", "events_mod_team": "Meeskond",
"events_mod_team_desc": "Meeskonnaliikmed ja vahetuste planeerimine", "events_mod_team_desc": "Meeskonnaliikmed ja vahetuste planeerimine",
"events_mod_sponsors": "Sponsorid", "events_mod_sponsors": "Sponsorid",
"events_mod_sponsors_desc": "Sponsorid, partnerid ja kohustused", "events_mod_sponsors_desc": "Sponsorid, partnerid ja kohustused",
"module_coming_soon": "Tulekul", "module_coming_soon": "Tulekul",
"module_coming_soon_desc": "See moodul on arendamisel ja saab peagi kƤttesaadavaks.", "module_coming_soon_desc": "See moodul on arendamisel ja saab peagi kättesaadavaks.",
"team_title": "Ürituse meeskond", "team_title": "Ürituse meeskond",
"team_subtitle": "Halda meeskonnaliikmeid ja nende rolle selle ürituse jaoks.", "team_subtitle": "Halda meeskonnaliikmeid ja nende rolle selle ürituse jaoks.",
"team_add_member": "Lisa liige", "team_add_member": "Lisa liige",
"team_role_lead": "Juht", "team_role_lead": "Juht",
"team_role_manager": "Haldur", "team_role_manager": "Haldur",
"team_role_member": "Liige", "team_role_member": "Liige",
"team_empty": "Meeskonnaliikmeid pole veel mƤƤratud. Lisa liikmeid oma organisatsioonist.", "team_empty": "Meeskonnaliikmeid pole veel määratud. Lisa liikmeid oma organisatsioonist.",
"team_remove_confirm": "Eemalda {name} selle ürituse meeskonnast?", "team_remove_confirm": "Eemalda {name} selle ürituse meeskonnast?",
"team_remove_btn": "Eemalda", "team_remove_btn": "Eemalda",
"team_added": "{name} lisatud meeskonda", "team_added": "{name} lisatud meeskonda",
"team_removed": "{name} eemaldatud meeskonnast", "team_removed": "{name} eemaldatud meeskonnast",
@@ -374,8 +374,8 @@
"team_already_assigned": "Juba meeskonnas", "team_already_assigned": "Juba meeskonnas",
"team_departments": "Valdkonnad", "team_departments": "Valdkonnad",
"team_roles": "Rollid", "team_roles": "Rollid",
"team_all": "KƵik", "team_all": "Kõik",
"team_no_department": "MƤƤramata", "team_no_department": "Määramata",
"team_add_department": "Lisa valdkond", "team_add_department": "Lisa valdkond",
"team_add_role": "Lisa roll", "team_add_role": "Lisa roll",
"team_edit_department": "Muuda valdkonda", "team_edit_department": "Muuda valdkonda",
@@ -390,31 +390,31 @@
"team_role_deleted": "Roll kustutatud", "team_role_deleted": "Roll kustutatud",
"team_dept_delete_confirm": "Kustuta valdkond {name}? Liikmed eemaldatakse sellest.", "team_dept_delete_confirm": "Kustuta valdkond {name}? Liikmed eemaldatakse sellest.",
"team_role_delete_confirm": "Kustuta roll {name}? Liikmed kaotavad selle rolli.", "team_role_delete_confirm": "Kustuta roll {name}? Liikmed kaotavad selle rolli.",
"team_view_by_dept": "Valdkondade jƤrgi", "team_view_by_dept": "Valdkondade järgi",
"team_view_list": "Nimekirja vaade", "team_view_list": "Nimekirja vaade",
"team_member_count": "{count} liiget", "team_member_count": "{count} liiget",
"team_assign_dept": "MƤƤra valdkonnad", "team_assign_dept": "Määra valdkonnad",
"team_notes": "MƤrkmed", "team_notes": "Märkmed",
"team_notes_placeholder": "Valikulised mƤrkmed selle liikme kohta...", "team_notes_placeholder": "Valikulised märkmed selle liikme kohta...",
"overview_subtitle": "Tere tagasi. Siin on ülevaade toimuvast.", "overview_subtitle": "Tere tagasi. Siin on ülevaade toimuvast.",
"overview_stat_events": "Üritused", "overview_stat_events": "Üritused",
"overview_upcoming_events": "Tulevased üritused", "overview_upcoming_events": "Tulevased üritused",
"overview_upcoming_empty": "Tulevasi üritusi pole. Loo üks alustamiseks.", "overview_upcoming_empty": "Tulevasi üritusi pole. Loo üks alustamiseks.",
"overview_view_all_events": "Vaata kƵiki üritusi", "overview_view_all_events": "Vaata kõiki üritusi",
"overview_more_members": "+{count} veel", "overview_more_members": "+{count} veel",
"chat_join_title": "Liitu vestlusega", "chat_join_title": "Liitu vestlusega",
"chat_join_description": "Vestlus pƵhineb Matrixil - avatud standardil turvalise ja detsentraliseeritud suhtluse jaoks.", "chat_join_description": "Vestlus põhineb Matrixil - avatud standardil turvalise ja detsentraliseeritud suhtluse jaoks.",
"chat_join_consent": "Liitudes luuakse sulle Matrixi konto sinu praeguste profiiliandmete (nimi, e-post ja avatar) pƵhjal.", "chat_join_consent": "Liitudes luuakse sulle Matrixi konto sinu praeguste profiiliandmete (nimi, e-post ja avatar) põhjal.",
"chat_join_learn_more": "Loe Matrixi kohta lƤhemalt", "chat_join_learn_more": "Loe Matrixi kohta lähemalt",
"chat_join_button": "Liitu vestlusega", "chat_join_button": "Liitu vestlusega",
"chat_joining": "Konto seadistamine...", "chat_joining": "Konto seadistamine...",
"chat_join_success": "Vestluskonto loodud! Tere tulemast.", "chat_join_success": "Vestluskonto loodud! Tere tulemast.",
"chat_join_error": "Vestluse seadistamine ebaƵnnestus. Proovi uuesti.", "chat_join_error": "Vestluse seadistamine ebaõnnestus. Proovi uuesti.",
"chat_disconnect": "Katkesta vestlusühendus", "chat_disconnect": "Katkesta vestlusühendus",
"dept_dashboard_no_modules": "Mooduleid pole veel seadistatud", "dept_dashboard_no_modules": "Mooduleid pole veel seadistatud",
"dept_dashboard_add_first": "Lisa oma esimene moodul", "dept_dashboard_add_first": "Lisa oma esimene moodul",
"dept_dashboard_add_module": "Lisa moodul", "dept_dashboard_add_module": "Lisa moodul",
"dept_dashboard_all_added": "KƵik moodulid on juba lisatud", "dept_dashboard_all_added": "Kõik moodulid on juba lisatud",
"dept_dashboard_expand": "Laienda", "dept_dashboard_expand": "Laienda",
"dept_dashboard_remove_module": "Eemalda moodul", "dept_dashboard_remove_module": "Eemalda moodul",
"dept_dashboard_coming_soon": "Tulekul", "dept_dashboard_coming_soon": "Tulekul",
@@ -422,14 +422,14 @@
"dept_dashboard_departments": "Valdkonnad", "dept_dashboard_departments": "Valdkonnad",
"dept_checklist_no_items": "Kontrollnimekirju pole veel", "dept_checklist_no_items": "Kontrollnimekirju pole veel",
"dept_checklist_add": "Lisa kontrollnimekiri", "dept_checklist_add": "Lisa kontrollnimekiri",
"dept_checklist_add_item": "Lisa üksus...", "dept_checklist_add_item": "Lisa üksus...",
"dept_notes_no_notes": "MƤrkmeid pole veel", "dept_notes_no_notes": "Märkmeid pole veel",
"dept_notes_new": "Uus mƤrge", "dept_notes_new": "Uus märge",
"dept_notes_select": "Vali mƤrge", "dept_notes_select": "Vali märge",
"dept_notes_placeholder": "Alusta kirjutamist...", "dept_notes_placeholder": "Alusta kirjutamist...",
"dept_notes_title_placeholder": "MƤrkme pealkiri...", "dept_notes_title_placeholder": "Märkme pealkiri...",
"dept_kanban_open": "Ava ülesannete tahvel", "dept_kanban_open": "Ava ülesannete tahvel",
"dept_kanban_desc": "Selle valdkonna ülesannete tahvel", "dept_kanban_desc": "Selle valdkonna ülesannete tahvel",
"dept_files_open": "Ava failid", "dept_files_open": "Ava failid",
"dept_files_desc": "Valdkonna failid ja dokumendid", "dept_files_desc": "Valdkonna failid ja dokumendid",
"dept_quick_add": "Kiirvalik", "dept_quick_add": "Kiirvalik",
@@ -444,70 +444,70 @@
"dept_module_kanban": "Kanban", "dept_module_kanban": "Kanban",
"dept_module_files": "Failid", "dept_module_files": "Failid",
"dept_module_checklist": "Kontrollnimekiri", "dept_module_checklist": "Kontrollnimekiri",
"dept_module_notes": "MƤrkmed", "dept_module_notes": "Märkmed",
"dept_module_schedule": "Ajakava", "dept_module_schedule": "Ajakava",
"dept_module_contacts": "Kontaktid", "dept_module_contacts": "Kontaktid",
"dept_module_budget": "Eelarve", "dept_module_budget": "Eelarve",
"dept_module_sponsors": "Sponsorid", "dept_module_sponsors": "Sponsorid",
"dept_module_map": "Kaart", "dept_module_map": "Kaart",
"toast_error_update_layout": "Paigutuse uuendamine ebaƵnnestus", "toast_error_update_layout": "Paigutuse uuendamine ebaõnnestus",
"toast_error_add_module": "Mooduli lisamine ebaƵnnestus", "toast_error_add_module": "Mooduli lisamine ebaõnnestus",
"toast_error_remove_module": "Mooduli eemaldamine ebaƵnnestus", "toast_error_remove_module": "Mooduli eemaldamine ebaõnnestus",
"toast_error_reorder_modules": "Moodulite ümberjƤrjestamine ebaƵnnestus", "toast_error_reorder_modules": "Moodulite ümberjärjestamine ebaõnnestus",
"toast_error_add_item": "Üksuse lisamine ebaƵnnestus", "toast_error_add_item": "Üksuse lisamine ebaõnnestus",
"toast_error_update_item": "Üksuse uuendamine ebaƵnnestus", "toast_error_update_item": "Üksuse uuendamine ebaõnnestus",
"toast_error_delete_item": "Üksuse kustutamine ebaƵnnestus", "toast_error_delete_item": "Üksuse kustutamine ebaõnnestus",
"toast_error_create_checklist": "Kontrollnimekirja loomine ebaƵnnestus", "toast_error_create_checklist": "Kontrollnimekirja loomine ebaõnnestus",
"toast_error_delete_checklist": "Kontrollnimekirja kustutamine ebaƵnnestus", "toast_error_delete_checklist": "Kontrollnimekirja kustutamine ebaõnnestus",
"toast_error_rename_checklist": "Kontrollnimekirja ümbernimetamine ebaƵnnestus", "toast_error_rename_checklist": "Kontrollnimekirja ümbernimetamine ebaõnnestus",
"toast_error_create_note": "MƤrkme loomine ebaƵnnestus", "toast_error_create_note": "Märkme loomine ebaõnnestus",
"toast_error_update_note": "MƤrkme uuendamine ebaƵnnestus", "toast_error_update_note": "Märkme uuendamine ebaõnnestus",
"toast_error_delete_note": "MƤrkme kustutamine ebaƵnnestus", "toast_error_delete_note": "Märkme kustutamine ebaõnnestus",
"toast_error_create_stage": "Lava loomine ebaƵnnestus", "toast_error_create_stage": "Lava loomine ebaõnnestus",
"toast_error_delete_stage": "Lava kustutamine ebaƵnnestus", "toast_error_delete_stage": "Lava kustutamine ebaõnnestus",
"toast_error_create_block": "Ajakavaploki loomine ebaƵnnestus", "toast_error_create_block": "Ajakavaploki loomine ebaõnnestus",
"toast_error_update_block": "Ajakavaploki uuendamine ebaƵnnestus", "toast_error_update_block": "Ajakavaploki uuendamine ebaõnnestus",
"toast_error_delete_block": "Ajakavaploki kustutamine ebaƵnnestus", "toast_error_delete_block": "Ajakavaploki kustutamine ebaõnnestus",
"toast_error_create_contact": "Kontakti loomine ebaƵnnestus", "toast_error_create_contact": "Kontakti loomine ebaõnnestus",
"toast_error_update_contact": "Kontakti uuendamine ebaƵnnestus", "toast_error_update_contact": "Kontakti uuendamine ebaõnnestus",
"toast_error_delete_contact": "Kontakti kustutamine ebaƵnnestus", "toast_error_delete_contact": "Kontakti kustutamine ebaõnnestus",
"toast_error_create_category": "Kategooria loomine ebaƵnnestus", "toast_error_create_category": "Kategooria loomine ebaõnnestus",
"toast_error_delete_category": "Kategooria kustutamine ebaƵnnestus", "toast_error_delete_category": "Kategooria kustutamine ebaõnnestus",
"toast_error_create_budget_item": "Eelarveüksuse loomine ebaƵnnestus", "toast_error_create_budget_item": "Eelarveüksuse loomine ebaõnnestus",
"toast_error_update_budget_item": "Eelarveüksuse uuendamine ebaƵnnestus", "toast_error_update_budget_item": "Eelarveüksuse uuendamine ebaõnnestus",
"toast_error_delete_budget_item": "Eelarveüksuse kustutamine ebaƵnnestus", "toast_error_delete_budget_item": "Eelarveüksuse kustutamine ebaõnnestus",
"toast_error_upload_receipt": "Kviitungi üleslaadimine ebaƵnnestus", "toast_error_upload_receipt": "Kviitungi üleslaadimine ebaõnnestus",
"toast_success_receipt_attached": "Kviitung \"{name}\" lisatud", "toast_success_receipt_attached": "Kviitung \"{name}\" lisatud",
"toast_error_create_tier": "Taseme loomine ebaƵnnestus", "toast_error_create_tier": "Taseme loomine ebaõnnestus",
"toast_error_delete_tier": "Taseme kustutamine ebaƵnnestus", "toast_error_delete_tier": "Taseme kustutamine ebaõnnestus",
"toast_error_create_sponsor": "Sponsori loomine ebaƵnnestus", "toast_error_create_sponsor": "Sponsori loomine ebaõnnestus",
"toast_error_update_sponsor": "Sponsori uuendamine ebaƵnnestus", "toast_error_update_sponsor": "Sponsori uuendamine ebaõnnestus",
"toast_error_delete_sponsor": "Sponsori kustutamine ebaƵnnestus", "toast_error_delete_sponsor": "Sponsori kustutamine ebaõnnestus",
"toast_error_create_deliverable": "Kohustuse loomine ebaƵnnestus", "toast_error_create_deliverable": "Kohustuse loomine ebaõnnestus",
"toast_error_update_deliverable": "Kohustuse uuendamine ebaƵnnestus", "toast_error_update_deliverable": "Kohustuse uuendamine ebaõnnestus",
"toast_error_delete_deliverable": "Kohustuse kustutamine ebaƵnnestus", "toast_error_delete_deliverable": "Kohustuse kustutamine ebaõnnestus",
"checklist_rename": "Nimeta ümber", "checklist_rename": "Nimeta ümber",
"checklist_delete": "Kustuta nimekiri", "checklist_delete": "Kustuta nimekiri",
"checklist_add_item_placeholder": "Lisa üksus...", "checklist_add_item_placeholder": "Lisa üksus...",
"checklist_name_placeholder": "Nimekirja nimi...", "checklist_name_placeholder": "Nimekirja nimi...",
"checklist_no_items": "Kontrollnimekirju pole veel", "checklist_no_items": "Kontrollnimekirju pole veel",
"checklist_add": "Lisa kontrollnimekiri", "checklist_add": "Lisa kontrollnimekiri",
"notes_new": "Uus mƤrge", "notes_new": "Uus märge",
"notes_title_placeholder": "MƤrkme pealkiri...", "notes_title_placeholder": "Märkme pealkiri...",
"notes_placeholder": "Alusta kirjutamist...", "notes_placeholder": "Alusta kirjutamist...",
"notes_no_notes": "MƤrkmeid pole veel", "notes_no_notes": "Märkmeid pole veel",
"notes_select": "Vali mƤrge", "notes_select": "Vali märge",
"notes_export_document": "Ekspordi dokumendina", "notes_export_document": "Ekspordi dokumendina",
"notes_delete": "Kustuta mƤrge", "notes_delete": "Kustuta märge",
"notes_exported": "Eksporditud \"{title}\" dokumendina", "notes_exported": "Eksporditud \"{title}\" dokumendina",
"notes_export_error": "MƤrkme eksportimine ebaƵnnestus", "notes_export_error": "Märkme eksportimine ebaõnnestus",
"schedule_timeline": "Ajajoon", "schedule_timeline": "Ajajoon",
"schedule_list": "Nimekiri", "schedule_list": "Nimekiri",
"schedule_add_block": "Lisa plokk", "schedule_add_block": "Lisa plokk",
"schedule_manage_stages": "Halda lavasid", "schedule_manage_stages": "Halda lavasid",
"schedule_no_blocks": "Ajakavaplokke pole veel", "schedule_no_blocks": "Ajakavaplokke pole veel",
"schedule_add_first": "Lisa oma esimene plokk ajakava koostamise alustamiseks.", "schedule_add_first": "Lisa oma esimene plokk ajakava koostamise alustamiseks.",
"schedule_all_day": "Terve pƤev", "schedule_all_day": "Terve päev",
"schedule_no_stage": "Lava puudub", "schedule_no_stage": "Lava puudub",
"schedule_add_stage_title": "Lisa lava / ruum", "schedule_add_stage_title": "Lisa lava / ruum",
"schedule_stage_name_placeholder": "nt Peamine lava", "schedule_stage_name_placeholder": "nt Peamine lava",
@@ -521,19 +521,19 @@
"schedule_block_speaker_label": "Esineja / Juht", "schedule_block_speaker_label": "Esineja / Juht",
"schedule_block_speaker_placeholder": "nt Jaan Tamm", "schedule_block_speaker_placeholder": "nt Jaan Tamm",
"schedule_block_start_label": "Algusaeg", "schedule_block_start_label": "Algusaeg",
"schedule_block_end_label": "LƵpuaeg", "schedule_block_end_label": "Lõpuaeg",
"schedule_block_stage_label": "Lava / Ruum", "schedule_block_stage_label": "Lava / Ruum",
"schedule_block_no_stage": "Lava puudub", "schedule_block_no_stage": "Lava puudub",
"schedule_block_description_label": "Kirjeldus", "schedule_block_description_label": "Kirjeldus",
"schedule_block_description_placeholder": "Valikuline kirjeldus...", "schedule_block_description_placeholder": "Valikuline kirjeldus...",
"schedule_block_color_label": "VƤrv", "schedule_block_color_label": "Värv",
"schedule_block_delete": "Kustuta plokk", "schedule_block_delete": "Kustuta plokk",
"contacts_search_placeholder": "Otsi kontakte...", "contacts_search_placeholder": "Otsi kontakte...",
"contacts_add": "Lisa kontakt", "contacts_add": "Lisa kontakt",
"contacts_no_contacts": "Kontakte pole veel", "contacts_no_contacts": "Kontakte pole veel",
"contacts_add_first": "Lisa oma esimene kontakt kataloogi loomiseks.", "contacts_add_first": "Lisa oma esimene kontakt kataloogi loomiseks.",
"contacts_no_results": "Otsingutulemusi ei leitud", "contacts_no_results": "Otsingutulemusi ei leitud",
"contacts_category_all": "KƵik", "contacts_category_all": "Kõik",
"contacts_category_venue": "Toimumiskoht", "contacts_category_venue": "Toimumiskoht",
"contacts_category_catering": "Toitlustus", "contacts_category_catering": "Toitlustus",
"contacts_category_av": "AV / Tehnika", "contacts_category_av": "AV / Tehnika",
@@ -548,31 +548,31 @@
"contacts_name_label": "Nimi", "contacts_name_label": "Nimi",
"contacts_name_placeholder": "Kontakti nimi", "contacts_name_placeholder": "Kontakti nimi",
"contacts_role_label": "Roll / Ametinimetus", "contacts_role_label": "Roll / Ametinimetus",
"contacts_role_placeholder": "nt Ürituse juht", "contacts_role_placeholder": "nt Ürituse juht",
"contacts_company_label": "EttevƵte", "contacts_company_label": "Ettevõte",
"contacts_company_placeholder": "EttevƵtte nimi", "contacts_company_placeholder": "Ettevõtte nimi",
"contacts_email_label": "E-post", "contacts_email_label": "E-post",
"contacts_email_placeholder": "email@nƤide.ee", "contacts_email_placeholder": "email@näide.ee",
"contacts_phone_label": "Telefon", "contacts_phone_label": "Telefon",
"contacts_phone_placeholder": "+372 ...", "contacts_phone_placeholder": "+372 ...",
"contacts_website_label": "Veebileht", "contacts_website_label": "Veebileht",
"contacts_website_placeholder": "https://...", "contacts_website_placeholder": "https://...",
"contacts_category_label": "Kategooria", "contacts_category_label": "Kategooria",
"contacts_notes_label": "MƤrkmed", "contacts_notes_label": "Märkmed",
"contacts_notes_placeholder": "Valikulised mƤrkmed...", "contacts_notes_placeholder": "Valikulised märkmed...",
"contacts_delete_confirm": "Kustuta see kontakt?", "contacts_delete_confirm": "Kustuta see kontakt?",
"budget_income": "Tulud", "budget_income": "Tulud",
"budget_expenses": "Kulud", "budget_expenses": "Kulud",
"budget_planned": "Planeeritud: {amount}", "budget_planned": "Planeeritud: {amount}",
"budget_planned_balance": "Planeeritud saldo", "budget_planned_balance": "Planeeritud saldo",
"budget_actual_balance": "Tegelik saldo", "budget_actual_balance": "Tegelik saldo",
"budget_view_all": "KƵik", "budget_view_all": "Kõik",
"budget_view_income": "Tulud", "budget_view_income": "Tulud",
"budget_view_expenses": "Kulud", "budget_view_expenses": "Kulud",
"budget_add_category": "Kategooria", "budget_add_category": "Kategooria",
"budget_add_item": "Lisa üksus", "budget_add_item": "Lisa üksus",
"budget_no_items": "Eelarveüksusi pole veel", "budget_no_items": "Eelarveüksusi pole veel",
"budget_col_type": "Tüüp", "budget_col_type": "Tüüp",
"budget_col_description": "Kirjeldus", "budget_col_description": "Kirjeldus",
"budget_col_category": "Kategooria", "budget_col_category": "Kategooria",
"budget_col_planned": "Planeeritud", "budget_col_planned": "Planeeritud",
@@ -581,35 +581,35 @@
"budget_col_receipt": "Kviitung", "budget_col_receipt": "Kviitung",
"budget_uncategorized": "Kategoriseerimata", "budget_uncategorized": "Kategoriseerimata",
"budget_total": "Kokku", "budget_total": "Kokku",
"budget_missing_receipt": "Arve/kviitung puudub - kliki üleslaadimiseks", "budget_missing_receipt": "Arve/kviitung puudub - kliki üleslaadimiseks",
"budget_missing_receipt_short": "Arve/kviitung puudub", "budget_missing_receipt_short": "Arve/kviitung puudub",
"budget_receipt_attached": "Kviitung lisatud", "budget_receipt_attached": "Kviitung lisatud",
"budget_add_item_title": "Lisa eelarveüksus", "budget_add_item_title": "Lisa eelarveüksus",
"budget_edit_item_title": "Muuda eelarveüksust", "budget_edit_item_title": "Muuda eelarveüksust",
"budget_description_label": "Kirjeldus", "budget_description_label": "Kirjeldus",
"budget_description_placeholder": "nt Ruumi rent", "budget_description_placeholder": "nt Ruumi rent",
"budget_type_label": "Tüüp", "budget_type_label": "Tüüp",
"budget_type_expense": "Kulu", "budget_type_expense": "Kulu",
"budget_type_income": "Tulu", "budget_type_income": "Tulu",
"budget_category_label": "Kategooria", "budget_category_label": "Kategooria",
"budget_planned_amount_label": "Planeeritud summa", "budget_planned_amount_label": "Planeeritud summa",
"budget_actual_amount_label": "Tegelik summa", "budget_actual_amount_label": "Tegelik summa",
"budget_notes_label": "MƤrkmed", "budget_notes_label": "Märkmed",
"budget_notes_placeholder": "Valikulised mƤrkmed...", "budget_notes_placeholder": "Valikulised märkmed...",
"budget_add_category_title": "Lisa kategooria", "budget_add_category_title": "Lisa kategooria",
"budget_category_name_label": "Nimi", "budget_category_name_label": "Nimi",
"budget_category_name_placeholder": "nt Toimumiskoht", "budget_category_name_placeholder": "nt Toimumiskoht",
"budget_category_color_label": "VƤrv", "budget_category_color_label": "Värv",
"budget_select_color": "Vali vƤrv {color}", "budget_select_color": "Vali värv {color}",
"budget_existing_categories": "Olemasolevad kategooriad", "budget_existing_categories": "Olemasolevad kategooriad",
"sponsors_search_placeholder": "Otsi sponsoreid...", "sponsors_search_placeholder": "Otsi sponsoreid...",
"sponsors_add_tier": "Lisa tase", "sponsors_add_tier": "Lisa tase",
"sponsors_add_sponsor": "Lisa sponsor", "sponsors_add_sponsor": "Lisa sponsor",
"sponsors_no_sponsors": "Sponsoreid pole veel", "sponsors_no_sponsors": "Sponsoreid pole veel",
"sponsors_add_first": "Lisa sponsoritasemed ja alusta sponsorite jƤlgimist.", "sponsors_add_first": "Lisa sponsoritasemed ja alusta sponsorite jälgimist.",
"sponsors_no_results": "Filtritele vastavaid sponsoreid ei leitud", "sponsors_no_results": "Filtritele vastavaid sponsoreid ei leitud",
"sponsors_filter_all_statuses": "KƵik staatused", "sponsors_filter_all_statuses": "Kõik staatused",
"sponsors_filter_all_tiers": "KƵik tasemed", "sponsors_filter_all_tiers": "Kõik tasemed",
"sponsors_status_prospect": "Potentsiaalne", "sponsors_status_prospect": "Potentsiaalne",
"sponsors_status_contacted": "Kontakteeritud", "sponsors_status_contacted": "Kontakteeritud",
"sponsors_status_confirmed": "Kinnitatud", "sponsors_status_confirmed": "Kinnitatud",
@@ -620,18 +620,18 @@
"sponsors_deliverables_label": "Kohustused", "sponsors_deliverables_label": "Kohustused",
"sponsors_deliverable_placeholder": "Lisa kohustus...", "sponsors_deliverable_placeholder": "Lisa kohustus...",
"sponsors_no_deliverables": "Kohustusi pole veel", "sponsors_no_deliverables": "Kohustusi pole veel",
"sponsors_notes_label": "MƤrkmed", "sponsors_notes_label": "Märkmed",
"sponsors_add_tier_title": "Lisa sponsoritase", "sponsors_add_tier_title": "Lisa sponsoritase",
"sponsors_tier_name_label": "Taseme nimi", "sponsors_tier_name_label": "Taseme nimi",
"sponsors_tier_name_placeholder": "nt Kuld", "sponsors_tier_name_placeholder": "nt Kuld",
"sponsors_tier_amount_label": "Minimaalne summa", "sponsors_tier_amount_label": "Minimaalne summa",
"sponsors_tier_color_label": "VƤrv", "sponsors_tier_color_label": "Värv",
"sponsors_existing_tiers": "Olemasolevad tasemed", "sponsors_existing_tiers": "Olemasolevad tasemed",
"sponsors_no_tiers": "Tasemeid pole veel", "sponsors_no_tiers": "Tasemeid pole veel",
"sponsors_add_sponsor_title": "Lisa sponsor", "sponsors_add_sponsor_title": "Lisa sponsor",
"sponsors_edit_sponsor_title": "Muuda sponsorit", "sponsors_edit_sponsor_title": "Muuda sponsorit",
"sponsors_name_label": "Sponsori nimi", "sponsors_name_label": "Sponsori nimi",
"sponsors_name_placeholder": "EttevƵtte nimi", "sponsors_name_placeholder": "Ettevõtte nimi",
"sponsors_tier_label": "Tase", "sponsors_tier_label": "Tase",
"sponsors_no_tier": "Tase puudub", "sponsors_no_tier": "Tase puudub",
"sponsors_status_label": "Staatus", "sponsors_status_label": "Staatus",
@@ -640,18 +640,18 @@
"sponsors_contact_name_label": "Kontaktisiku nimi", "sponsors_contact_name_label": "Kontaktisiku nimi",
"sponsors_contact_name_placeholder": "Kontaktisik", "sponsors_contact_name_placeholder": "Kontaktisik",
"sponsors_contact_email_label": "Kontakti e-post", "sponsors_contact_email_label": "Kontakti e-post",
"sponsors_contact_email_placeholder": "email@nƤide.ee", "sponsors_contact_email_placeholder": "email@näide.ee",
"sponsors_contact_phone_label": "Kontakti telefon", "sponsors_contact_phone_label": "Kontakti telefon",
"sponsors_contact_phone_placeholder": "+372 ...", "sponsors_contact_phone_placeholder": "+372 ...",
"sponsors_website_label": "Veebileht", "sponsors_website_label": "Veebileht",
"sponsors_website_placeholder": "https://...", "sponsors_website_placeholder": "https://...",
"sponsors_notes_placeholder": "Valikulised mƤrkmed...", "sponsors_notes_placeholder": "Valikulised märkmed...",
"sponsors_delete_confirm": "Kustuta see sponsor?", "sponsors_delete_confirm": "Kustuta see sponsor?",
"sponsors_select_color": "Vali vƤrv {color}", "sponsors_select_color": "Vali värv {color}",
"files_widget_loading": "Failide laadimine...", "files_widget_loading": "Failide laadimine...",
"files_widget_no_folder": "Valdkonna kausta pole veel loodud", "files_widget_no_folder": "Valdkonna kausta pole veel loodud",
"files_widget_empty": "Faile pole veel", "files_widget_empty": "Faile pole veel",
"files_widget_full_view": "TƤisvaade", "files_widget_full_view": "Täisvaade",
"files_widget_create_title": "Loo uus", "files_widget_create_title": "Loo uus",
"files_widget_type_document": "Dokument", "files_widget_type_document": "Dokument",
"files_widget_type_folder": "Kaust", "files_widget_type_folder": "Kaust",
@@ -660,30 +660,30 @@
"files_widget_doc_placeholder": "Dokumendi nimi", "files_widget_doc_placeholder": "Dokumendi nimi",
"files_widget_folder_placeholder": "Kausta nimi", "files_widget_folder_placeholder": "Kausta nimi",
"files_widget_kanban_placeholder": "Tahvli nimi", "files_widget_kanban_placeholder": "Tahvli nimi",
"files_widget_drop_files": "Lohista failid üleslaadimiseks", "files_widget_drop_files": "Lohista failid üleslaadimiseks",
"files_widget_uploading": "Üleslaadimine {name}...", "files_widget_uploading": "Üleslaadimine {name}...",
"kanban_widget_loading": "Tahvlite laadimine...", "kanban_widget_loading": "Tahvlite laadimine...",
"kanban_widget_no_folder": "Valdkonna kausta pole veel loodud", "kanban_widget_no_folder": "Valdkonna kausta pole veel loodud",
"kanban_widget_no_boards": "Kanban tahvleid pole veel", "kanban_widget_no_boards": "Kanban tahvleid pole veel",
"kanban_widget_create": "Loo tahvel", "kanban_widget_create": "Loo tahvel",
"kanban_widget_create_title": "Loo Kanban tahvel", "kanban_widget_create_title": "Loo Kanban tahvel",
"kanban_widget_name_label": "Tahvli nimi", "kanban_widget_name_label": "Tahvli nimi",
"kanban_widget_name_placeholder": "nt Ülesannete jƤlgija", "kanban_widget_name_placeholder": "nt Ülesannete jälgija",
"finances_title": "Ürituse rahandus", "finances_title": "Ürituse rahandus",
"finances_subtitle": "Eelarve ülevaade kƵigi valdkondade lƵikes", "finances_subtitle": "Eelarve ülevaade kõigi valdkondade lõikes",
"finances_total_income": "Tulud kokku", "finances_total_income": "Tulud kokku",
"finances_total_expenses": "Kulud kokku", "finances_total_expenses": "Kulud kokku",
"finances_net_balance": "Netosaldo", "finances_net_balance": "Netosaldo",
"finances_missing_receipts": "Puuduvad kviitungid", "finances_missing_receipts": "Puuduvad kviitungid",
"finances_items_without_receipts": "{count} üksust ilma kviitungita", "finances_items_without_receipts": "{count} üksust ilma kviitungita",
"finances_planned": "planeeritud", "finances_planned": "planeeritud",
"finances_view_by_dept": "Valdkondade jƤrgi", "finances_view_by_dept": "Valdkondade järgi",
"finances_view_by_category": "Kategooriate jƤrgi", "finances_view_by_category": "Kategooriate järgi",
"finances_filter_all": "KƵik", "finances_filter_all": "Kõik",
"finances_filter_income": "Tulud", "finances_filter_income": "Tulud",
"finances_filter_expenses": "Kulud", "finances_filter_expenses": "Kulud",
"finances_no_items": "Eelarveüksusi pole veel", "finances_no_items": "Eelarveüksusi pole veel",
"finances_no_items_desc": "Eelarveüksused ilmuvad siia, kui valdkonnad neid lisavad.", "finances_no_items_desc": "Eelarveüksused ilmuvad siia, kui valdkonnad neid lisavad.",
"finances_col_description": "Kirjeldus", "finances_col_description": "Kirjeldus",
"finances_col_department": "Valdkond", "finances_col_department": "Valdkond",
"finances_col_category": "Kategooria", "finances_col_category": "Kategooria",

View File

@@ -250,3 +250,50 @@ export async function deleteMapShape(supabase: SupabaseClient, shapeId: string):
if (error) throw error; if (error) throw error;
} }
// ── Realtime ──
export interface RealtimeMapPayload<T> {
event: 'INSERT' | 'UPDATE' | 'DELETE';
new: T;
old: Partial<T>;
}
export function subscribeToMapLayers(
supabase: SupabaseClient,
layerIds: string[],
onPinChange: (payload: RealtimeMapPayload<MapPin>) => void,
onShapeChange: (payload: RealtimeMapPayload<MapShape>) => void,
) {
const layerIdSet = new Set(layerIds);
const channel = supabase.channel(`map:${layerIds.join(',')}`);
channel
.on('postgres_changes', { event: '*', schema: 'public', table: 'map_pins' },
(payload) => {
const pin = (payload.new ?? payload.old) as Partial<MapPin>;
const lid = pin.layer_id ?? (payload.old as Partial<MapPin>)?.layer_id;
if (lid && !layerIdSet.has(lid)) return;
onPinChange({
event: payload.eventType as 'INSERT' | 'UPDATE' | 'DELETE',
new: payload.new as MapPin,
old: payload.old as Partial<MapPin>,
});
}
)
.on('postgres_changes', { event: '*', schema: 'public', table: 'map_shapes' },
(payload) => {
const shape = (payload.new ?? payload.old) as Partial<MapShape>;
const lid = shape.layer_id ?? (payload.old as Partial<MapShape>)?.layer_id;
if (lid && !layerIdSet.has(lid)) return;
onShapeChange({
event: payload.eventType as 'INSERT' | 'UPDATE' | 'DELETE',
new: payload.new as MapShape,
old: payload.old as Partial<MapShape>,
});
}
)
.subscribe();
return channel;
}

View File

@@ -6,11 +6,13 @@
import * as m from "$lib/paraglide/messages"; import * as m from "$lib/paraglide/messages";
import type { SupabaseClient } from "@supabase/supabase-js"; import type { SupabaseClient } from "@supabase/supabase-js";
import type { Database } from "$lib/supabase/types"; import type { Database } from "$lib/supabase/types";
import type { RealtimeChannel } from "@supabase/supabase-js";
import { import {
type MapLayerWithPins, type MapLayerWithPins,
type MapLayer, type MapLayer,
type MapPin as MapPinType, type MapPin as MapPinType,
type MapShape, type MapShape,
type RealtimeMapPayload,
createMapLayer, createMapLayer,
updateMapLayer, updateMapLayer,
deleteMapLayer, deleteMapLayer,
@@ -20,6 +22,7 @@
createMapShape, createMapShape,
updateMapShape, updateMapShape,
deleteMapShape, deleteMapShape,
subscribeToMapLayers,
} from "$lib/api/map"; } from "$lib/api/map";
let L: any; let L: any;
@@ -51,6 +54,10 @@
let leafletShapes = new Map<string, any>(); let leafletShapes = new Map<string, any>();
let leafletBoundsRects = new Map<string, any>(); let leafletBoundsRects = new Map<string, any>();
// Realtime
let realtimeChannel: RealtimeChannel | null = null;
const optimisticIds = new Set<string>();
// svelte-ignore state_referenced_locally // svelte-ignore state_referenced_locally
let layers = $state<MapLayerWithPins[]>(initialLayers); let layers = $state<MapLayerWithPins[]>(initialLayers);
let activeLayerIdx = $state(0); let activeLayerIdx = $state(0);
@@ -415,6 +422,7 @@
(s) => s.id === shapeId, (s) => s.id === shapeId,
); );
if (shape) { if (shape) {
optimisticIds.add(shapeId);
try { try {
await updateMapShape(supabase, shapeId, { await updateMapShape(supabase, shapeId, {
vertices: shape.vertices, vertices: shape.vertices,
@@ -461,6 +469,7 @@
vertices, vertices,
sort_order: activeLayer.shapes?.length ?? 0, sort_order: activeLayer.shapes?.length ?? 0,
}); });
optimisticIds.add(shape.id);
layers = layers.map((l, i) => layers = layers.map((l, i) =>
i === activeLayerIdx i === activeLayerIdx
? { ...l, shapes: [...(l.shapes ?? []), shape] } ? { ...l, shapes: [...(l.shapes ?? []), shape] }
@@ -485,6 +494,7 @@
vertices: verts, vertices: verts,
sort_order: activeLayer.shapes?.length ?? 0, sort_order: activeLayer.shapes?.length ?? 0,
}); });
optimisticIds.add(shape.id);
layers = layers.map((l, i) => layers = layers.map((l, i) =>
i === activeLayerIdx i === activeLayerIdx
? { ...l, shapes: [...(l.shapes ?? []), shape] } ? { ...l, shapes: [...(l.shapes ?? []), shape] }
@@ -643,6 +653,7 @@
); );
showPinModal = false; showPinModal = false;
syncAllObjects(layers[activeLayerIdx]); syncAllObjects(layers[activeLayerIdx]);
optimisticIds.add(editingPin.id);
try { try {
await updateMapPin(supabase, editingPin.id, updated); await updateMapPin(supabase, editingPin.id, updated);
} catch { } catch {
@@ -658,6 +669,7 @@
lng: pendingLatLng.lng, lng: pendingLatLng.lng,
sort_order: activeLayer.pins.length, sort_order: activeLayer.pins.length,
}); });
optimisticIds.add(pin.id);
layers = layers.map((l, i) => layers = layers.map((l, i) =>
i === activeLayerIdx ? { ...l, pins: [...l.pins, pin] } : l, i === activeLayerIdx ? { ...l, pins: [...l.pins, pin] } : l,
); );
@@ -687,6 +699,7 @@
); );
if (selectedObjectId === pinId) deselectAll(); if (selectedObjectId === pinId) deselectAll();
syncAllObjects(layers[activeLayerIdx]); syncAllObjects(layers[activeLayerIdx]);
optimisticIds.add(pinId);
try { try {
await deleteMapPin(supabase, pinId); await deleteMapPin(supabase, pinId);
} catch { } catch {
@@ -720,6 +733,7 @@
); );
showShapeModal = false; showShapeModal = false;
syncAllObjects(layers[activeLayerIdx]); syncAllObjects(layers[activeLayerIdx]);
optimisticIds.add(editingShape.id);
try { try {
await updateMapShape(supabase, editingShape.id, updated); await updateMapShape(supabase, editingShape.id, updated);
} catch { } catch {
@@ -740,6 +754,7 @@
); );
if (selectedObjectId === shapeId) deselectAll(); if (selectedObjectId === shapeId) deselectAll();
syncAllObjects(layers[activeLayerIdx]); syncAllObjects(layers[activeLayerIdx]);
optimisticIds.add(shapeId);
try { try {
await deleteMapShape(supabase, shapeId); await deleteMapShape(supabase, shapeId);
} catch { } catch {
@@ -774,6 +789,7 @@
rotation: original.rotation, rotation: original.rotation,
sort_order: activeLayer.shapes?.length ?? 0, sort_order: activeLayer.shapes?.length ?? 0,
}); });
optimisticIds.add(shape.id);
layers = layers.map((l, i) => layers = layers.map((l, i) =>
i === activeLayerIdx i === activeLayerIdx
? { ...l, shapes: [...(l.shapes ?? []), shape] } ? { ...l, shapes: [...(l.shapes ?? []), shape] }
@@ -815,6 +831,7 @@
layers = [...layers, withData]; layers = [...layers, withData];
activeLayerIdx = layers.length - 1; activeLayerIdx = layers.length - 1;
showLayerOnMap(withData); showLayerOnMap(withData);
setupRealtime();
} catch { } catch {
toasts.error("Failed to create layer"); toasts.error("Failed to create layer");
} }
@@ -827,6 +844,7 @@
if (activeLayerIdx >= layers.length) if (activeLayerIdx >= layers.length)
activeLayerIdx = Math.max(0, layers.length - 1); activeLayerIdx = Math.max(0, layers.length - 1);
if (layers.length > 0) showLayerOnMap(layers[activeLayerIdx]); if (layers.length > 0) showLayerOnMap(layers[activeLayerIdx]);
setupRealtime();
try { try {
await deleteMapLayer(supabase, layerId); await deleteMapLayer(supabase, layerId);
} catch { } catch {
@@ -979,6 +997,120 @@
} }
} }
// ── Realtime handlers ──
function handlePinRealtime(payload: RealtimeMapPayload<MapPinType>) {
const id = payload.new?.id ?? payload.old?.id;
if (!id) return;
if (optimisticIds.has(id)) {
optimisticIds.delete(id);
return;
}
const layerId = payload.new?.layer_id ?? payload.old?.layer_id;
if (!layerId) return;
if (payload.event === "INSERT") {
layers = layers.map((l) =>
l.id === layerId
? {
...l,
pins: [
...l.pins.filter((p) => p.id !== id),
payload.new,
],
}
: l,
);
} else if (payload.event === "UPDATE") {
layers = layers.map((l) =>
l.id === layerId
? {
...l,
pins: l.pins.map((p) =>
p.id === id ? payload.new : p,
),
}
: l,
);
} else if (payload.event === "DELETE") {
layers = layers.map((l) =>
l.id === layerId
? { ...l, pins: l.pins.filter((p) => p.id !== id) }
: l,
);
if (selectedObjectId === id) deselectAll();
}
const layerIdx = layers.findIndex((l) => l.id === layerId);
if (layerIdx === activeLayerIdx) syncAllObjects(layers[layerIdx]);
}
function handleShapeRealtime(payload: RealtimeMapPayload<MapShape>) {
const id = payload.new?.id ?? payload.old?.id;
if (!id) return;
if (optimisticIds.has(id)) {
optimisticIds.delete(id);
return;
}
const layerId = payload.new?.layer_id ?? payload.old?.layer_id;
if (!layerId) return;
if (payload.event === "INSERT") {
layers = layers.map((l) =>
l.id === layerId
? {
...l,
shapes: [
...(l.shapes ?? []).filter((s) => s.id !== id),
payload.new,
],
}
: l,
);
} else if (payload.event === "UPDATE") {
layers = layers.map((l) =>
l.id === layerId
? {
...l,
shapes: (l.shapes ?? []).map((s) =>
s.id === id ? payload.new : s,
),
}
: l,
);
} else if (payload.event === "DELETE") {
layers = layers.map((l) =>
l.id === layerId
? {
...l,
shapes: (l.shapes ?? []).filter((s) => s.id !== id),
}
: l,
);
if (selectedObjectId === id) deselectAll();
}
const layerIdx = layers.findIndex((l) => l.id === layerId);
if (layerIdx === activeLayerIdx) syncAllObjects(layers[layerIdx]);
}
function setupRealtime() {
if (realtimeChannel) {
supabase.removeChannel(realtimeChannel);
realtimeChannel = null;
}
const layerIds = layers.map((l) => l.id).filter(Boolean);
if (layerIds.length === 0) return;
realtimeChannel = subscribeToMapLayers(
supabase,
layerIds,
handlePinRealtime,
handleShapeRealtime,
);
}
// ── Lifecycle ── // ── Lifecycle ──
onMount(async () => { onMount(async () => {
@@ -1003,9 +1135,15 @@
} else { } else {
showLayerOnMap(layers[activeLayerIdx]); showLayerOnMap(layers[activeLayerIdx]);
} }
setupRealtime();
}); });
onDestroy(() => { onDestroy(() => {
if (realtimeChannel) {
supabase.removeChannel(realtimeChannel);
realtimeChannel = null;
}
if (map) { if (map) {
map.remove(); map.remove();
map = null; map = null;

View File

@@ -59,6 +59,7 @@
let newEventStartDate = $state(""); let newEventStartDate = $state("");
let newEventEndDate = $state(""); let newEventEndDate = $state("");
let newEventVenue = $state(""); let newEventVenue = $state("");
let newEventVenueAddress = $state("");
let newEventColor = $state(data.org.default_event_color || "#00A3E0"); let newEventColor = $state(data.org.default_event_color || "#00A3E0");
let creating = $state(false); let creating = $state(false);
@@ -111,6 +112,7 @@
start_date: newEventStartDate || null, start_date: newEventStartDate || null,
end_date: newEventEndDate || null, end_date: newEventEndDate || null,
venue_name: newEventVenue.trim() || null, venue_name: newEventVenue.trim() || null,
venue_address: newEventVenueAddress.trim() || null,
color: newEventColor, color: newEventColor,
created_by: userId, created_by: userId,
}) })
@@ -154,6 +156,7 @@
newEventStartDate = ""; newEventStartDate = "";
newEventEndDate = ""; newEventEndDate = "";
newEventVenue = ""; newEventVenue = "";
newEventVenueAddress = "";
newEventColor = data.org.default_event_color || "#00A3E0"; newEventColor = data.org.default_event_color || "#00A3E0";
} }
@@ -331,12 +334,19 @@
</div> </div>
<!-- Venue --> <!-- Venue -->
<div class="flex flex-col gap-2">
<Input <Input
variant="compact" variant="compact"
label={m.events_form_venue()} label={m.events_form_venue()}
bind:value={newEventVenue} bind:value={newEventVenue}
placeholder={m.events_form_venue_placeholder()} placeholder={m.events_form_venue_placeholder()}
/> />
<Input
variant="compact"
bind:value={newEventVenueAddress}
placeholder={m.events_form_venue_address_placeholder()}
/>
</div>
<!-- Color --> <!-- Color -->
<div class="flex flex-col gap-1.5"> <div class="flex flex-col gap-1.5">

View File

@@ -1272,13 +1272,14 @@
</div> </div>
{:else} {:else}
<div <div
class="grid {layoutConfig.cols} gap-4 {currentLayout === 'grid' class="grid {layoutConfig.cols} gap-4"
? 'auto-rows-[calc(50vh-5rem)]' style={currentLayout === "grid"
: 'h-full'}" ? "grid-auto-rows: minmax(320px, calc(50vh - 5rem))"
: ""}
> >
{#each dashboard.panels as panel (panel.id)} {#each dashboard.panels as panel (panel.id)}
<div <div
class="bg-surface/50 rounded-2xl border border-light/5 flex flex-col overflow-hidden {currentLayout === class="bg-surface/50 rounded-2xl border border-light/5 flex flex-col overflow-hidden min-h-[320px] {currentLayout ===
'single' 'single'
? 'col-span-full' ? 'col-span-full'
: ''}" : ''}"