diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/KaffeekasseModule.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/KaffeekasseModule.kt
index 7d7d88c85947a26a4868eff9ea324dfb6295e77d..02a2317e6753bbe1823a24a51e1371036df570fa 100644
--- a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/KaffeekasseModule.kt
+++ b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/KaffeekasseModule.kt
@@ -16,7 +16,6 @@ import net.novagamestudios.kaffeekasse.model.kaffeekasse.MutableCart
 import net.novagamestudios.kaffeekasse.model.kaffeekasse.isNotEmpty
 import net.novagamestudios.kaffeekasse.model.session.Session
 import net.novagamestudios.kaffeekasse.repositories.RepositoryProvider
-import net.novagamestudios.kaffeekasse.ui.AppModuleSelection
 import net.novagamestudios.kaffeekasse.ui.kaffeekasse.ManualBillScreenModel.Companion.backNavigationHandler
 import net.novagamestudios.kaffeekasse.ui.navigation.AppSubpageTitle
 import net.novagamestudios.kaffeekasse.ui.navigation.KaffeekasseNavigation
@@ -34,7 +33,6 @@ class KaffeekasseModuleScreenModel private constructor(
         else -> null
     }
 
-
     companion object : ScreenModelFactory<KaffeekasseNavigation.Tab, KaffeekasseModuleScreenModel> {
         context (RepositoryProvider)
         override fun create(screen: KaffeekasseNavigation.Tab) = KaffeekasseModuleScreenModel(
@@ -52,12 +50,8 @@ fun KaffeekasseTopBarTitle(
     model: KaffeekasseModuleScreenModel,
     navigator: Navigator
 ) {
-    when (navigator.lastItem) {
-        is KaffeekasseNavigation.ManualBillScreen -> {
-            val name = model.accountName
-            if (name != null) AppSubpageTitle("$name")
-            else AppModuleSelection()
-        }
+    when (val screen = navigator.lastItem) {
+        is KaffeekasseNavigation.ManualBillScreen -> ManualBillTopBarTitle(screen.model, navigator)
         is KaffeekasseNavigation.AccountScreen -> AppSubpageTitle("Konto")
         is KaffeekasseNavigation.TransactionsScreen -> AppSubpageTitle("Übersicht")
     }
diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/ManualBill.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/ManualBill.kt
index b4acc8670a0414091e09021a6fa30e5fee105c81..1da6dceb34ba87c3b49c0bb17adc98c81629a30b 100644
--- a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/ManualBill.kt
+++ b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/ManualBill.kt
@@ -14,6 +14,7 @@ import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Favorite
 import androidx.compose.material.icons.filled.Person
 import androidx.compose.material.icons.filled.Receipt
+import androidx.compose.material.icons.filled.Search
 import androidx.compose.material3.HorizontalDivider
 import androidx.compose.material3.Icon
 import androidx.compose.material3.IconButton
@@ -42,19 +43,23 @@ import net.novagamestudios.common_utils.Logger
 import net.novagamestudios.common_utils.compose.components.CircularProgressIndicator
 import net.novagamestudios.common_utils.compose.tabIndicatorOffset
 import net.novagamestudios.kaffeekasse.KaffeekasseModule.Companion.kaffeekasseCartProvider
+import net.novagamestudios.kaffeekasse.model.kaffeekasse.Item
 import net.novagamestudios.kaffeekasse.model.kaffeekasse.MutableCart
 import net.novagamestudios.kaffeekasse.model.kaffeekasse.isEmpty
 import net.novagamestudios.kaffeekasse.model.session.Session
 import net.novagamestudios.kaffeekasse.model.session.deviceOrNull
 import net.novagamestudios.kaffeekasse.repositories.RepositoryProvider
 import net.novagamestudios.kaffeekasse.repositories.i11.KaffeekasseRepository
+import net.novagamestudios.kaffeekasse.ui.AppModuleSelection
 import net.novagamestudios.kaffeekasse.ui.kaffeekasse.components.CategorizedItems
 import net.novagamestudios.kaffeekasse.ui.kaffeekasse.components.CategorizedItemsState
 import net.novagamestudios.kaffeekasse.ui.kaffeekasse.components.Checkout
 import net.novagamestudios.kaffeekasse.ui.kaffeekasse.components.CheckoutState
 import net.novagamestudios.kaffeekasse.ui.kaffeekasse.components.CustomItems
 import net.novagamestudios.kaffeekasse.ui.kaffeekasse.components.CustomItemsState
+import net.novagamestudios.kaffeekasse.ui.kaffeekasse.components.ItemSearchField
 import net.novagamestudios.kaffeekasse.ui.login.LogoutTopBarAction
+import net.novagamestudios.kaffeekasse.ui.navigation.AppSubpageTitle
 import net.novagamestudios.kaffeekasse.ui.navigation.KaffeekasseNavigation
 import net.novagamestudios.kaffeekasse.ui.util.FailureRetryScreen
 import net.novagamestudios.kaffeekasse.ui.util.RichDataContent
@@ -70,13 +75,43 @@ class ManualBillScreenModel private constructor(
     private val kaffeekasse: KaffeekasseRepository,
     val cart: MutableCart
 ) : ScreenModel, Logger {
+    val accountName = when (session) {
+        is Session.WithDevice -> session.realUser.displayName ?: "Unknown User"
+        else -> null
+    }
+
+    private var _showSearch by mutableStateOf(false)
+    var showSearch
+        get() = _showSearch
+        set(value) {
+            _showSearch = value
+            if (!value) searchQuery = ""
+        }
+    var searchQuery by mutableStateOf("")
 
     val stock = kaffeekasse.stock.collectAsRichStateHere()
 
     val itemGroups get() = stock.dataOrNull?.itemGroups ?: emptyList()
 
+    fun Sequence<Item>.filtered(): Sequence<Item> {
+        val query = searchQuery.takeIf { showSearch }?.takeUnless { it.isBlank() }
+        return if (query != null) filter { item ->
+            item.cleanFullName.contains(query, ignoreCase = true)
+        } else this
+    }
+
+    val searchItems by derivedStateOf {
+        if (showSearch) CategorizedItemsState(
+            itemGroups
+                .asSequence()
+                .flatMap { it.items }
+                .filtered()
+                .toList()
+        ) else null
+    }
+
     val categorizedItemsByGroup by derivedStateOf {
-        itemGroups.map { CategorizedItemsState(it.items) }
+        itemGroups.map { group -> CategorizedItemsState(group.items.asSequence().filtered().toList()) }
     }
 
     val customItemsState by lazy {
@@ -127,10 +162,25 @@ class ManualBillScreenModel private constructor(
 
         @Composable
         fun ManualBillScreenModel.backNavigationHandler(navigator: Navigator): BackNavigationHandler {
-            val categorizedItems = categorizedItemsByGroup.getOrNull(currentGroupIndex)
+            val categorizedItems = if (currentPagerIndex == 0) {
+                searchItems
+            } else {
+                categorizedItemsByGroup.getOrNull(currentGroupIndex)
+            }
             return remember(categorizedItems, cart) {
-                categorizedItems?.backNavigation then CartBackNavigationHandler(cart)
+                categorizedItems?.backNavigation then SearchBackNavigationHandler() then CartBackNavigationHandler(cart)
+            }
+        }
+    }
+
+    private inner class SearchBackNavigationHandler : BackNavigationHandler {
+        override fun canNavigateBack() = showSearch
+        override fun onNavigateBack(): Boolean {
+            if (showSearch) {
+                showSearch = false
+                return true
             }
+            return false
         }
     }
 
@@ -242,27 +292,75 @@ private fun TabbedItemGroups(
         model.pagerState,
         beyondViewportPageCount = 4
     ) { index ->
-        if (index == 0) CustomItems(
-            state = model.customItemsState,
-            cart = model.cart,
-            Modifier
-                .weight(1f)
-                .fillMaxHeight()
-        ) else CategorizedItems(
-            state = model.categorizedItemsByGroup[index - 1],
-            cart = model.cart,
-            Modifier
-                .weight(1f)
-                .fillMaxHeight()
+        if (index == 0) CustomItemsTab(
+            model = model,
+            Modifier.fillMaxHeight()
+        ) else ItemGroupTab(
+            model = model,
+            groupIndex = index - 1,
+            Modifier.fillMaxHeight()
         )
     }
 }
 
 
+@Composable
+private fun CustomItemsTab(
+    model: ManualBillScreenModel,
+    modifier: Modifier = Modifier
+) {
+    val state = model.searchItems
+    if (state != null) {
+        CategorizedItems(
+            state = state,
+            cart = model.cart,
+            modifier
+        )
+    } else CustomItems(
+        state = model.customItemsState,
+        cart = model.cart,
+        modifier
+    )
+}
+
+@Composable
+private fun ItemGroupTab(
+    model: ManualBillScreenModel,
+    groupIndex: Int,
+    modifier: Modifier = Modifier
+) {
+    CategorizedItems(
+        state = model.categorizedItemsByGroup[groupIndex],
+        cart = model.cart,
+        modifier
+    )
+}
+
+
+@Composable
+fun ManualBillTopBarTitle(
+    model: ManualBillScreenModel,
+    navigator: Navigator
+) {
+    if (model.showSearch) {
+        ItemSearchField(
+            query = model.searchQuery,
+            onQueryChange = { model.searchQuery = it },
+        )
+    } else {
+        val name = model.accountName
+        if (name != null) AppSubpageTitle("$name")
+        else AppModuleSelection()
+    }
+}
+
 @Composable
 fun ManualBillTopBarActions(
     model: ManualBillScreenModel
 ) {
+    if (!model.showSearch) IconButton(onClick = { model.showSearch = !model.showSearch }) {
+        Icon(Icons.Default.Search, "Suchen")
+    }
     val navigator = LocalNavigator.currentOrThrow
     IconButton(onClick = {
         navigator.push(KaffeekasseNavigation.AccountScreen(model.session))
diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/components/Checkout.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/components/Checkout.kt
index 0820ff42793eeef8326f525a4f11cc3945b44602..887bd96743920b65e757905d5a149ca577b63052 100644
--- a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/components/Checkout.kt
+++ b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/components/Checkout.kt
@@ -77,7 +77,6 @@ import net.novagamestudios.kaffeekasse.util.richdata.RichDataState
 import net.novagamestudios.kaffeekasse.util.richdata.collectAsRichStateIn
 import net.novagamestudios.kaffeekasse.util.richdata.combineRich
 import net.novagamestudios.kaffeekasse.util.richdata.dataOrNull
-import net.novagamestudios.kaffeekasse.util.richdata.flatMapLatestRich
 import net.novagamestudios.kaffeekasse.util.richdata.mapRich
 import net.novagamestudios.kaffeekasse.util.richdata.stateIn
 import kotlin.time.Duration.Companion.seconds
@@ -229,9 +228,9 @@ private class APIPurchaseController(
     }.stateIn(coroutineScope, SharingStarted.Eagerly)
     private val selfId get() = selfUserBasic.value.dataOrNull?.id
 
-    private val selfUserExtended = selfUserBasic.flatMapLatestRich {
-        kaffeekasse.getExtendedUserInfo(it.id)
-    }
+//    private val selfUserExtended = selfUserBasic.flatMapLatestRich {
+//        kaffeekasse.getExtendedUserInfo(it.id)
+//    }
 
 //    override val purchaseAccounts: RichDataFlow<List<PurchaseAccount>> = combineRich(
 //        selfUserExtended,
diff --git a/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/components/ItemSearch.kt b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/components/ItemSearch.kt
new file mode 100644
index 0000000000000000000000000000000000000000..5f769bcaa359ca8d5932126a67079b75160d6022
--- /dev/null
+++ b/app/src/main/java/net/novagamestudios/kaffeekasse/ui/kaffeekasse/components/ItemSearch.kt
@@ -0,0 +1,42 @@
+package net.novagamestudios.kaffeekasse.ui.kaffeekasse.components
+
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Clear
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.material3.SearchBarDefaults
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.focus.FocusRequester
+import androidx.compose.ui.focus.focusRequester
+
+
+@Composable
+fun ItemSearchField(
+    query: String,
+    onQueryChange: (String) -> Unit,
+    modifier: Modifier = Modifier
+) {
+    val focusRequester = remember { FocusRequester() }
+    LaunchedEffect(Unit) {
+        focusRequester.requestFocus()
+    }
+    SearchBarDefaults.InputField(
+        query = query,
+        onQueryChange = onQueryChange,
+        onSearch = { },
+        expanded = false,
+        onExpandedChange = { },
+        modifier = modifier.focusRequester(focusRequester),
+        placeholder = { Text("Suchen") },
+        trailingIcon = {
+            if (query.isNotEmpty()) IconButton(onClick = { onQueryChange("") }) {
+                Icon(Icons.Default.Clear, "Clear")
+            }
+        },
+    )
+}
+