diff --git a/frontend/pages/communication/chat.vue b/frontend/pages/communication/chat.vue
index 15af1ca9..80d77455 100644
--- a/frontend/pages/communication/chat.vue
+++ b/frontend/pages/communication/chat.vue
@@ -13,6 +13,7 @@ const activeRoomKey = ref(requestedRoom())
const loading = ref(true), roomLoading = ref(false), sending = ref(false), creating = ref(false)
const showRoomForm = ref(false), messagesViewport = ref(null)
const hiddenRoomKeys = ref([]), showHiddenRooms = ref(false), preferenceBusy = ref(''), preferenceError = ref('')
+const roomSearch = ref('')
const preferencesReady = ref(false)
const roomForm = reactive({ name: '', key: '', topic: '' })
const session = computed(() => `${auth.user?.id || auth.user?.user_id || ''}:${auth.activeTenant || ''}`)
@@ -42,8 +43,17 @@ const decoratedRooms = computed(() => [
])
const visibleRooms = computed(() => decoratedRooms.value.filter(room => !hiddenRoomKeys.value.includes(room.key)))
const hiddenRooms = computed(() => decoratedRooms.value.filter(room => hiddenRoomKeys.value.includes(room.key)))
+const normalizeRoomSearch = value => String(value || '').toLowerCase().normalize('NFKD').replace(/[\u0300-\u036f]/g, '').replace(/ß/g, 'ss')
+const roomSearchTerms = computed(() => normalizeRoomSearch(roomSearch.value).trim().split(/\s+/).filter(Boolean))
+function matchesRoomSearch(room) {
+ const text = normalizeRoomSearch([room.name, room.topic, room.projectNumber, room.email, room.ownerName].filter(value => value != null).join(' '))
+ return roomSearchTerms.value.every(term => text.includes(term))
+}
+// Filter only the sidebar; the open conversation and its draft keep their selection.
+const filteredRooms = computed(() => visibleRooms.value.filter(matchesRoomSearch))
+const filteredHiddenRooms = computed(() => hiddenRooms.value.filter(matchesRoomSearch))
const groupedRooms = computed(() => ['Räume', 'Projekte', 'Direktnachrichten', 'Zusammenarbeit']
- .map(label => ({ label, rooms: visibleRooms.value.filter(room => room.group === label) }))
+ .map(label => ({ label, rooms: filteredRooms.value.filter(room => room.group === label) }))
.filter(group => group.rooms.length))
const activeRoom = computed(() => visibleRooms.value.find(room => room.key === activeRoomKey.value) || null)
const isCollaboration = computed(() => activeRoom.value?.source === 'collaboration')
@@ -246,6 +256,7 @@ async function initialize() {
baseRooms.value = []; projectRooms.value = []; directRooms.value = []; collaborationRooms.value = []; invitations.value = []
unreadRooms.value = {}; invitationBusy.value = ''; collaborationError.value = ''; listError.value = ''; creating.value = false
hiddenRoomKeys.value = []; showHiddenRooms.value = false; preferenceBusy.value = ''; preferenceError.value = ''; preferencesReady.value = false
+ roomSearch.value = ''
showRoomForm.value = false; Object.assign(roomForm, { name: '', key: '', topic: '' })
activeRoomKey.value = requestedRoom(); loading.value = true
await Promise.all([refreshLists(), loadRoomPreferences(scope)])
@@ -291,6 +302,12 @@ onBeforeUnmount(() => {