diff --git a/src/components/Navbar/SideWidgets/FilterSelect.vue b/src/components/Navbar/SideWidgets/FilterSelect.vue
index e6d29260..bab31873 100644
--- a/src/components/Navbar/SideWidgets/FilterSelect.vue
+++ b/src/components/Navbar/SideWidgets/FilterSelect.vue
@@ -1,90 +1,134 @@
-<script setup lang="ts">
-import { FilterState } from '@/constants/qbit'
-import { useDashboardStore } from '@/stores/dashboard'
+<script lang="ts" setup>
+import { TorrentState } from '@/constants/qbit'
 import { useMaindataStore } from '@/stores/maindata'
 import { useVueTorrentStore } from '@/stores/vuetorrent'
-import { computed } from 'vue'
+import { storeToRefs } from 'pinia'
+import { computed, toRefs } from 'vue'
 import { useI18n } from 'vue-i18n'
 
 const { t } = useI18n()
-const dashboardStore = useDashboardStore()
-const maindataStore = useMaindataStore()
+const { categories: _categories, tags: _tags, trackers: _trackers, filters } = storeToRefs(useMaindataStore())
+const { statusFilter, categoryFilter, tagFilter, trackerFilter } = toRefs(filters.value)
 const vueTorrentStore = useVueTorrentStore()
 
-const statusOptions = [
-  { title: t('navbar.side.filters.disabled'), value: FilterState.ALL },
-  { title: t('constants.filterStatus.downloading'), value: FilterState.DOWNLOADING },
-  { title: t('constants.filterStatus.seeding'), value: FilterState.SEEDING },
-  { title: t('constants.filterStatus.completed'), value: FilterState.COMPLETED },
-  { title: t('constants.filterStatus.resumed'), value: FilterState.RESUMED },
-  { title: t('constants.filterStatus.paused'), value: FilterState.PAUSED },
-  { title: t('constants.filterStatus.active'), value: FilterState.ACTIVE },
-  { title: t('constants.filterStatus.inactive'), value: FilterState.INACTIVE },
-  { title: t('constants.filterStatus.stalled'), value: FilterState.STALLED },
-  { title: t('constants.filterStatus.stalled_uploading'), value: FilterState.STALLED_UPLOADING },
-  { title: t('constants.filterStatus.stalled_downloading'), value: FilterState.STALLED_DOWNLOADING },
-  { title: t('constants.filterStatus.checking'), value: FilterState.CHECKING },
-  { title: t('constants.filterStatus.moving'), value: FilterState.MOVING },
-  { title: t('constants.filterStatus.errored'), value: FilterState.ERRORED }
-]
+const statuses = computed(() => Object.values(TorrentState).map(state => (
+  { title: t(`torrent.state.${ state }`), value: state }
+)))
+const categories = computed(() => [
+  { title: t('navbar.side.filters.uncategorized'), value: '' },
+  ..._categories.value.map(c => ({ title: c.name, value: c.name }))
+])
+const tags = computed(() => [
+  { title: t('navbar.side.filters.untagged'), value: null },
+  ..._tags.value.map(tag => ({ title: tag, value: tag }))
+])
+const trackers = computed(() => [
+  { title: t('navbar.side.filters.untracked'), value: '' },
+  ..._trackers.value.map(tracker => ({ title: tracker, value: tracker }))
+])
 
-const categories = computed(() => {
-  const categories = [
-    { title: t('navbar.side.filters.disabled'), value: null },
-    { title: t('navbar.side.filters.uncategorized'), value: '' }
-  ]
-  categories.push(...maindataStore.categories.map(c => ({ title: c.name, value: c.name })))
-  return categories
-})
-const tags = computed(() => {
-  const tags = [
-    { title: t('navbar.side.filters.disabled'), value: null },
-    { title: t('navbar.side.filters.untagged'), value: '' }
-  ]
-  tags.push(...maindataStore.tags.map(tag => ({ title: tag, value: tag })))
-  return tags
-})
-const trackers = computed(() => {
-  const trackers = [{ title: t('navbar.side.filters.disabled'), value: null as string | null }]
-  trackers.push(...maindataStore.trackers.map(tag => ({ title: tag, value: tag })))
-  return trackers
-})
+function selectAllStatuses() {
+  statusFilter.value = []
+}
+
+function selectAllCategories() {
+  categoryFilter.value = []
+}
+
+function selectAllTags() {
+  tagFilter.value = []
+}
+
+function selectAllTrackers() {
+  trackerFilter.value = []
+}
 </script>
 
 <template>
   <v-list class="pb-0">
     <v-list-item class="px-0 pb-3">
-      <v-list-item-title class="px-0 text-uppercase white--text ml-1 font-weight-normal text-caption">Status</v-list-item-title>
-      <v-select
-        v-model="dashboardStore.sortOptions.statusFilter"
-        :items="statusOptions"
-        class="text-accent pt-1"
-        hide-details
-        density="compact"
-        variant="solo"
-        bg-color="secondary" />
+      <v-list-item-title class="px-0 text-uppercase white--text ml-1 font-weight-normal text-caption">
+        {{ t('navbar.side.filters.state') }}
+      </v-list-item-title>
+      <v-select v-model="statusFilter" :items="statuses" bg-color="secondary"
+                :placeholder="t('navbar.side.filters.disabled')"
+                class="text-accent pt-1" density="compact" hide-details multiple variant="solo">
+        <template v-slot:prepend-item>
+          <v-list-item :title="$t('common.disable')" @click="selectAllStatuses" />
+          <v-divider />
+        </template>
+        <template v-slot:selection="{ item, index }">
+          <span v-if="index === 0 && statusFilter.length === 1"
+                class="text-accent">{{ t(`torrent.state.${ item.props.value }`) }}</span>
+          <span v-else-if="index === 0" class="text-accent">{{
+              t('navbar.side.filters.activeFilter', statusFilter.length)
+            }}</span>
+        </template>
+      </v-select>
     </v-list-item>
 
     <v-list-item class="px-0 pb-3">
-      <v-list-item-title class="px-0 text-uppercase white--text ml-1 font-weight-light text-subtitle-2">Category</v-list-item-title>
-      <v-select
-        v-model="dashboardStore.sortOptions.categoryFilter"
-        :items="categories"
-        class="text-accent pt-1"
-        hide-details
-        density="compact"
-        variant="solo"
-        bg-color="secondary" />
+      <v-list-item-title class="px-0 text-uppercase white--text ml-1 font-weight-light text-subtitle-2">
+        {{ t('navbar.side.filters.category') }}
+      </v-list-item-title>
+      <v-select v-model="categoryFilter" :items="categories" bg-color="secondary"
+                :placeholder="t('navbar.side.filters.disabled')"
+                class="text-accent pt-1" density="compact" hide-details multiple variant="solo">
+        <template v-slot:prepend-item>
+          <v-list-item :title="$t('common.disable')" @click="selectAllCategories" />
+          <v-divider />
+        </template>
+        <template v-slot:selection="{ item, index }">
+          <span v-if="index === 0 && categoryFilter.length === 1"
+                class="text-accent">{{ item.props.title }}</span>
+          <span v-else-if="index === 0" class="text-accent">{{
+              t('navbar.side.filters.activeFilter', categoryFilter.length)
+            }}</span>
+        </template>
+      </v-select>
     </v-list-item>
 
     <v-list-item class="px-0 pb-3">
-      <v-list-item-title class="px-0 text-uppercase white--text ml-1 font-weight-light text-subtitle-2">Tags</v-list-item-title>
-      <v-select v-model="dashboardStore.sortOptions.tagFilter" :items="tags" class="text-accent pt-1" hide-details density="compact" variant="solo" bg-color="secondary" />
+      <v-list-item-title class="px-0 text-uppercase white--text ml-1 font-weight-light text-subtitle-2">
+        {{ t('navbar.side.filters.tag') }}
+      </v-list-item-title>
+      <v-select v-model="tagFilter" :items="tags" bg-color="secondary"
+                :placeholder="t('navbar.side.filters.disabled')"
+                class="text-accent pt-1" density="compact" hide-details multiple variant="solo">
+        <template v-slot:prepend-item>
+          <v-list-item :title="$t('common.disable')" @click="selectAllTags" />
+          <v-divider />
+        </template>
+        <template v-slot:selection="{ item, index }">
+          <span v-if="index === 0 && tagFilter.length === 1"
+                class="text-accent">{{ item.props.title }}</span>
+          <span v-else-if="index === 0" class="text-accent">{{
+              t('navbar.side.filters.activeFilter', tagFilter.length)
+            }}</span>
+        </template>
+      </v-select>
     </v-list-item>
 
-    <v-list-item :class="{ 'px-0': true, 'pb-3': vueTorrentStore.showTrackerFilter }" v-if="vueTorrentStore.showTrackerFilter">
-      <v-list-item-title class="px-0 text-uppercase white--text ml-1 font-weight-light text-subtitle-2">Tracker</v-list-item-title>
-      <v-select v-model="dashboardStore.sortOptions.trackerFilter" :items="trackers" class="text-accent pt-1" hide-details density="compact" variant="solo" bg-color="secondary" />
+    <v-list-item v-if="vueTorrentStore.showTrackerFilter"
+                 :class="{ 'px-0': true, 'pb-3': vueTorrentStore.showTrackerFilter }">
+      <v-list-item-title class="px-0 text-uppercase white--text ml-1 font-weight-light text-subtitle-2">
+        {{ t('navbar.side.filters.tracker') }}
+      </v-list-item-title>
+      <v-select v-model="trackerFilter" :items="trackers" bg-color="secondary"
+                :placeholder="t('navbar.side.filters.disabled')"
+                class="text-accent pt-1" density="compact" hide-details multiple variant="solo">
+        <template v-slot:prepend-item>
+          <v-list-item :title="$t('common.disable')" @click="selectAllTrackers" />
+          <v-divider />
+        </template>
+        <template v-slot:selection="{ item, index }">
+          <span v-if="index === 0 && trackerFilter.length === 1"
+                class="text-accent">{{ item.props.title }}</span>
+          <span v-else-if="index === 0" class="text-accent">{{
+              t('navbar.side.filters.activeFilter', trackerFilter.length)
+            }}</span>
+        </template>
+      </v-select>
     </v-list-item>
   </v-list>
 </template>
diff --git a/src/components/Navbar/TopWidgets/ActiveFilters.vue b/src/components/Navbar/TopWidgets/ActiveFilters.vue
index 97b6ccbb..186d7a6f 100644
--- a/src/components/Navbar/TopWidgets/ActiveFilters.vue
+++ b/src/components/Navbar/TopWidgets/ActiveFilters.vue
@@ -1,17 +1,20 @@
 <script setup lang="ts">
-import { FilterState } from '@/constants/qbit'
 import { useDashboardStore } from '@/stores/dashboard'
-import { computed } from 'vue'
+import { useMaindataStore } from '@/stores/maindata.ts'
+import { storeToRefs } from 'pinia'
+import { computed, toRefs } from 'vue'
 import { useI18n } from 'vue-i18n'
 
 const { t } = useI18n()
 const dashboardStore = useDashboardStore()
+const { filters } = storeToRefs(useMaindataStore())
+const { statusFilter, categoryFilter, tagFilter, trackerFilter } = toRefs(filters.value)
 
 const isTextFilterActive = computed(() => dashboardStore.searchFilter?.length > 0)
-const isStatusFilterActive = computed(() => dashboardStore.sortOptions.statusFilter !== FilterState.ALL)
-const isCategoryFilterActive = computed(() => dashboardStore.sortOptions.categoryFilter !== null)
-const isTagFilterActive = computed(() => dashboardStore.sortOptions.tagFilter !== null)
-const isTrackerFilterActive = computed(() => dashboardStore.sortOptions.trackerFilter !== null)
+const isStatusFilterActive = computed(() => statusFilter.value.length > 0)
+const isCategoryFilterActive = computed(() => categoryFilter.value.length > 0)
+const isTagFilterActive = computed(() => tagFilter.value.length > 0)
+const isTrackerFilterActive = computed(() => trackerFilter.value.length > 0)
 
 const filterCount = computed(
   () =>
@@ -21,37 +24,73 @@ const filterCount = computed(
     Number(isTagFilterActive.value) +
     Number(isTrackerFilterActive.value)
 )
+
+// TODO
+function resetAllFilters() {
+  dashboardStore.searchFilter = ''
+  statusFilter.value = []
+  categoryFilter.value = []
+  tagFilter.value = []
+  trackerFilter.value = []
+}
+function resetTextFilter() {
+  dashboardStore.searchFilter = ''
+}
+function resetStatusFilter() {
+  statusFilter.value = []
+}
+function resetCategoryFilter() {
+  categoryFilter.value = []
+}
+function resetTagFilter() {
+  tagFilter.value = []
+}
+function resetTrackerFilter() {
+  trackerFilter.value = []
+}
 </script>
 
 <template>
-  <v-menu open-on-click open-on-hover open-delay="0" close-delay="0">
+  <v-menu close-delay="0" open-delay="0" open-on-click open-on-hover>
     <template v-slot:activator="{ props }">
       <v-slide-x-transition>
-        <v-chip v-if="filterCount > 0" v-bind="props" class="ml-6" color="primary" variant="elevated">
+        <v-chip v-if="filterCount > 0" v-bind="props" class="ml-6" color="primary" variant="elevated" closable @click:close="resetAllFilters()">
           {{ t('navbar.top.active_filters.menu_label', filterCount) }}
         </v-chip>
       </v-slide-x-transition>
     </template>
 
     <div class="d-flex flex-column gap mt-3">
-      <v-chip v-if="isTextFilterActive" variant="elevated" color="grey">
+      <v-chip v-if="isTextFilterActive" variant="elevated" color="grey" closable @click:close="resetTextFilter()">
         {{ t('navbar.top.active_filters.text', { value: dashboardStore.searchFilter }) }}
       </v-chip>
-      <v-chip v-if="isStatusFilterActive" variant="elevated" :color="'state-' + dashboardStore.sortOptions.statusFilter">
-        {{ t('navbar.top.active_filters.status', { value: t(`constants.filterStatus.${dashboardStore.sortOptions.statusFilter}`) }) }}
+
+      <v-chip v-if="isStatusFilterActive && statusFilter.length === 1" :color="'torrent-' + statusFilter[0]" variant="elevated" closable @click:close="resetStatusFilter()">
+        {{ t('navbar.top.active_filters.state', { value: t(`torrent.state.${statusFilter[0]}`) }) }}
       </v-chip>
-      <v-chip v-if="isCategoryFilterActive" variant="elevated" color="category">
-        {{
-          t('navbar.top.active_filters.category', {
-            value: dashboardStore.sortOptions.categoryFilter === '' ? t('navbar.side.filters.uncategorized') : dashboardStore.sortOptions.categoryFilter
-          })
-        }}
+      <v-chip v-else-if="isStatusFilterActive" variant="elevated" closable @click:close="resetStatusFilter()">
+        {{ t('navbar.top.active_filters.multiple_state', statusFilter.length) }}
       </v-chip>
-      <v-chip v-if="isTagFilterActive" variant="elevated" color="tag">
-        {{ t('navbar.top.active_filters.tag', { value: dashboardStore.sortOptions.tagFilter === '' ? t('navbar.side.filters.untagged') : dashboardStore.sortOptions.tagFilter }) }}
+
+      <v-chip v-if="isCategoryFilterActive && categoryFilter.length === 1" color="category" variant="elevated" closable @click:close="resetCategoryFilter()">
+        {{ t('navbar.top.active_filters.category', { value: categoryFilter[0] === '' ? t('navbar.side.filters.uncategorized') : categoryFilter[0] }) }}
       </v-chip>
-      <v-chip v-if="isTrackerFilterActive" variant="elevated" color="tracker">
-        {{ t('navbar.top.active_filters.tracker', { value: dashboardStore.sortOptions.trackerFilter }) }}
+      <v-chip v-else-if="isCategoryFilterActive" color="category" variant="elevated" closable @click:close="resetCategoryFilter()">
+        {{ t('navbar.top.active_filters.multiple_category', categoryFilter.length) }}
+      </v-chip>
+
+      <v-chip v-if="isTagFilterActive && tagFilter.length === 1" color="tag" variant="elevated" closable @click:close="resetTagFilter()">
+        {{ t('navbar.top.active_filters.tag', { value: tagFilter[0] === null ? t('navbar.side.filters.untagged') : tagFilter[0] }) }}
+      </v-chip>
+      <v-chip v-else-if="isTagFilterActive" color="tag" variant="elevated" closable @click:close="resetTagFilter()">
+        {{ t('navbar.top.active_filters.multiple_tag', tagFilter.length) }}
+      </v-chip>
+
+      <v-chip v-if="isTrackerFilterActive && trackerFilter.length === 1" color="tracker" variant="elevated" closable @click:close="resetTrackerFilter()">
+        {{ t('navbar.top.active_filters.tracker', { value: trackerFilter[0] === '' ? t('navbar.side.filters.untracked') : trackerFilter[0] }) }}
+      </v-chip>
+      <v-chip v-else-if="isTrackerFilterActive" color="tracker" variant="elevated" closable @click:close="resetTrackerFilter()">
+        {{ t('navbar.top.active_filters.multiple_tracker', trackerFilter.length) }}
       </v-chip>
     </div>
   </v-menu>
diff --git a/src/components/TorrentDetail/Overview.vue b/src/components/TorrentDetail/Overview.vue
index ecf3dd5d..722bdf36 100644
--- a/src/components/TorrentDetail/Overview.vue
+++ b/src/components/TorrentDetail/Overview.vue
@@ -77,12 +77,12 @@ async function renderTorrentPieceStates() {
   let rectWidth = 1
 
   for (let i = 0; i < pieces.length; ++i) {
-    const status = pieces[i]
+    const state = pieces[i]
     let newColor = ''
 
-    if (status === PieceState.DOWNLOADING) newColor = theme.current.value.colors['torrent-downloading']
-    else if (status === PieceState.DOWNLOADED) newColor = theme.current.value.colors['torrent-pausedUP']
-    else if (status === PieceState.MISSING) {
+    if (state === PieceState.DOWNLOADING) newColor = theme.current.value.colors['torrent-downloading']
+    else if (state === PieceState.DOWNLOADED) newColor = theme.current.value.colors['torrent-pausedUP']
+    else if (state === PieceState.MISSING) {
       const selected_piece_ranges = files.value.filter(file => file.priority !== FilePriority.DO_NOT_DOWNLOAD).map(file => file.piece_range)
       for (const [min_piece_range, max_piece_range] of selected_piece_ranges) {
         if (i > min_piece_range && i < max_piece_range) {
diff --git a/src/constants/qbit/FilterState.ts b/src/constants/qbit/FilterState.ts
index fc18d34e..d8248c4a 100644
--- a/src/constants/qbit/FilterState.ts
+++ b/src/constants/qbit/FilterState.ts
@@ -13,4 +13,4 @@ export enum FilterState {
   CHECKING = 'checking',
   MOVING = 'moving',
   ERRORED = 'errored'
-}
+}
\ No newline at end of file
diff --git a/src/constants/qbit/index.ts b/src/constants/qbit/index.ts
index ade2082a..e22b1c97 100644
--- a/src/constants/qbit/index.ts
+++ b/src/constants/qbit/index.ts
@@ -7,4 +7,4 @@ import { FilePriority } from './FilePriority'
 import { TorrentState } from './TorrentState'
 import { TrackerStatus } from './TrackerStatus'
 
-export { AppPreferences, ConnectionStatus, LogType, PieceState, FilePriority, TrackerStatus, TorrentState, FilterState }
+export { AppPreferences, ConnectionStatus, FilterState, LogType, PieceState, FilePriority, TrackerStatus, TorrentState }
diff --git a/src/locales/en.json b/src/locales/en.json
index 16d0ca7d..f7b4ded9 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -7,6 +7,7 @@
     "yes": "Yes",
     "no": "No",
     "save": "Save",
+    "disable": "Disable",
     "selectNone": "Select None",
     "selectAll": "Select All",
     "useGlobalSettings": "Use Global Settings",
@@ -374,10 +375,14 @@
       "active_filters": {
         "menu_label": "Active filter: {n} | Active filters: {n}",
         "text": "Text filter: {value}",
-        "status": "Status filter: {value}",
+        "state": "State filter: {value}",
+        "multiple_state": "State filter: {n} states",
         "category": "Category filter: {value}",
+        "multiple_category": "Category filter: {n} categories",
         "tag": "Tag filter: {value}",
-        "tracker": "Tracker filter: {value}"
+        "multiple_tag": "Tag filter: {n} tags",
+        "tracker": "Tracker filter: {value}",
+        "multiple_tracker": "Tracker filter: {n} trackers"
       }
     },
     "side": {
@@ -389,9 +394,14 @@
       },
       "filters": {
         "disabled": "(Disabled)",
+        "state": "Torrent State Filter",
+        "category": "Category Filter",
         "uncategorized": "(Uncategorized)",
+        "tag": "Tag Filter",
         "untagged": "(Untagged)",
-        "untracked": "(Untracked)"
+        "tracker": "Tracker Filter",
+        "untracked": "(Untracked)",
+        "activeFilter": "{n} filters active"
       },
       "bottom_actions": {
         "logout": "Logout",
@@ -1026,22 +1036,6 @@
       "always": "Always",
       "never": "Never"
     },
-    "filterStatus": {
-      "all": "All",
-      "downloading": "Downloading",
-      "seeding": "Seeding",
-      "completed": "Completed",
-      "resumed": "Resumed",
-      "paused": "Paused",
-      "active": "Active",
-      "inactive": "Inactive",
-      "stalled": "Stalled",
-      "stalled_uploading": "Stalled Uploading",
-      "stalled_downloading": "Stalled Downloading",
-      "checking": "Checking",
-      "moving": "Moving",
-      "errored": "Errored"
-    },
     "connectionStatus": {
       "connected": "Connected",
       "firewalled": "Firewalled",
diff --git a/src/pages/Logs.vue b/src/pages/Logs.vue
index c6e01cbb..942d7a53 100644
--- a/src/pages/Logs.vue
+++ b/src/pages/Logs.vue
@@ -51,7 +51,7 @@ const formatLogTimestamp = (log: Log) => {
   return dayjs(log.timestamp * 1000).format(vueTorrentStore.dateFormat)
 }
 const toggleSelectAll = () => {
-  if (logTypeFilter.value.length === logTypeOptions.value.length) {
+  if (allTypesSelected.value) {
     logTypeFilter.value = []
   } else {
     logTypeFilter.value = logTypeOptions.value.map(option => option.value)
diff --git a/src/plugins/vuetify.ts b/src/plugins/vuetify.ts
index 343d31ef..59b83194 100644
--- a/src/plugins/vuetify.ts
+++ b/src/plugins/vuetify.ts
@@ -20,21 +20,6 @@ const variables = {
   tag: '#048B9A',
   tracker: '#C97D09',
 
-  // State filter colors
-  'state-downloading': '#5BB974',
-  'state-stalled_downloading': '#5BB974',
-  'state-seeding': '#4ECDE6',
-  'state-stalled_uploading': '#4ECDE6',
-  'state-completed': '#16573E',
-  'state-resumed': '#BDBDBD',
-  'state-active': '#BDBDBD',
-  'state-stalled': '#696969',
-  'state-paused': '#696969',
-  'state-inactive': '#696969',
-  'state-checking': '#FF7043',
-  'state-moving': '#FFAA2C',
-  'state-errored': '#F83E70',
-
   // Torrent state colors
   'torrent-error': '#F83E70',
   'torrent-missingFiles': '#F83E70',
diff --git a/src/services/qbit.ts b/src/services/qbit.ts
index 5fa975d2..8fdab8e6 100644
--- a/src/services/qbit.ts
+++ b/src/services/qbit.ts
@@ -86,7 +86,7 @@ export class QBitApi {
     return this.execute('/transfer/toggleSpeedLimitsMode')
   }
 
-  async getTorrents(payload: GetTorrentPayload): Promise<Torrent[]> {
+  async getTorrents(payload?: GetTorrentPayload): Promise<Torrent[]> {
     return this.axios.get('/torrents/info', { params: payload }).then(r => r.data)
   }
 
diff --git a/src/stores/dashboard.ts b/src/stores/dashboard.ts
index f223bf91..dda028dc 100644
--- a/src/stores/dashboard.ts
+++ b/src/stores/dashboard.ts
@@ -1,10 +1,8 @@
 import { useSearchQuery } from '@/composables'
-import { FilterState } from '@/constants/qbit'
 import { SortOptions } from '@/constants/qbit/SortOptions'
 import { formatData } from '@/helpers'
 import { useMaindataStore } from '@/stores/maindata'
 import { useVueTorrentStore } from '@/stores/vuetorrent'
-import { GetTorrentPayload } from '@/types/qbit/payloads'
 import { defineStore } from 'pinia'
 import { computed, reactive, ref, watch } from 'vue'
 import { useI18n } from 'vue-i18n'
@@ -21,18 +19,14 @@ export const useDashboardStore = defineStore(
     const sortOptions = reactive({
       isCustomSortEnabled: false,
       sortBy: SortOptions.DEFAULT,
-      reverseOrder: false,
-      statusFilter: FilterState.ALL as FilterState,
-      categoryFilter: null as string | null,
-      tagFilter: null as string | null,
-      trackerFilter: null as string | null
+      reverseOrder: false
     })
 
     const { t } = useI18n()
     const maindataStore = useMaindataStore()
     const vuetorrentStore = useVueTorrentStore()
     const searchQuery = useSearchQuery(
-      () => maindataStore.torrents,
+      () => maindataStore.torrentsWithFilters,
       searchFilter,
       torrent => torrent.name,
       results => {
@@ -71,16 +65,6 @@ export const useDashboardStore = defineStore(
       }
     })
 
-    const getTorrentsPayload = computed<GetTorrentPayload>(() => {
-      return {
-        filter: sortOptions.statusFilter ?? FilterState.ALL,
-        category: sortOptions.categoryFilter ?? undefined,
-        tag: sortOptions.tagFilter ?? undefined,
-        sort: sortOptions.isCustomSortEnabled ? SortOptions.DEFAULT : sortOptions.sortBy,
-        reverse: sortOptions.reverseOrder
-      }
-    })
-
     function isTorrentInSelection(hash: string) {
       return selectedTorrents.value.includes(hash)
     }
@@ -157,8 +141,7 @@ export const useDashboardStore = defineStore(
       spanTorrentSelection,
       selectAllTorrents,
       unselectAllTorrents,
-      toggleSelect,
-      getTorrentsPayload
+      toggleSelect
     }
   },
   {
diff --git a/src/stores/maindata.ts b/src/stores/maindata.ts
index 19b07f9c..c3cc1eb4 100644
--- a/src/stores/maindata.ts
+++ b/src/stores/maindata.ts
@@ -1,5 +1,5 @@
 import { useTorrentBuilder } from '@/composables'
-import { FilePriority } from '@/constants/qbit'
+import { FilePriority, TorrentState } from '@/constants/qbit'
 import { SortOptions } from '@/constants/qbit/SortOptions'
 import { extractHostname } from '@/helpers'
 import { qbit } from '@/services'
@@ -12,7 +12,7 @@ import { AddTorrentPayload } from '@/types/qbit/payloads'
 import { Torrent } from '@/types/vuetorrent'
 import { generateMultiple } from '@/utils/faker'
 import { defineStore } from 'pinia'
-import { MaybeRefOrGetter, computed, ref, toValue } from 'vue'
+import { computed, MaybeRefOrGetter, reactive, ref, toValue } from 'vue'
 
 const isProduction = computed(() => process.env.NODE_ENV === 'production')
 
@@ -25,6 +25,26 @@ export const useMaindataStore = defineStore('maindata', () => {
   const torrents = ref<Torrent[]>([])
   const trackers = ref<string[]>([])
 
+  const filters = reactive({
+    statusFilter: [] as TorrentState[],
+    categoryFilter: [] as string[],
+    tagFilter: [] as (string | null)[],
+    trackerFilter: [] as (string | null)[]
+  })
+
+  const torrentsWithFilters = computed(() => {
+    return torrents.value.filter(torrent => {
+      if (filters.statusFilter.length > 0 && !filters.statusFilter.includes(torrent.state)) return false
+      if (filters.categoryFilter.length > 0 && !filters.categoryFilter.includes(torrent.category)) return false
+      if (filters.tagFilter.length > 0) {
+        if (torrent.tags.length === 0 && filters.tagFilter.includes(null)) return true
+        if (!torrent.tags.some(tag => filters.tagFilter.includes(tag))) return false
+      }
+      if (filters.trackerFilter.length > 0 && !filters.trackerFilter.includes(extractHostname(torrent.tracker))) return false
+      return true
+    })
+  })
+
   const authStore = useAuthStore()
   const dashboardStore = useDashboardStore()
   const navbarStore = useNavbarStore()
@@ -143,7 +163,7 @@ export const useMaindataStore = defineStore('maindata', () => {
 
       // fetch torrent data
       dashboardStore.sortOptions.isCustomSortEnabled = torrentBuilder.computedValues.indexOf(dashboardStore.sortOptions.sortBy) !== -1
-      let data = await qbit.getTorrents(dashboardStore.getTorrentsPayload)
+      let data = await qbit.getTorrents()
 
       if (vueTorrentStore.showTrackerFilter) {
         trackers.value = data
@@ -153,16 +173,10 @@ export const useMaindataStore = defineStore('maindata', () => {
           .sort()
       }
 
-      if (vueTorrentStore.showTrackerFilter && dashboardStore.sortOptions.trackerFilter !== null) {
-        // don't calculate trackers when disabled
-        data = data.filter(d => extractHostname(d.tracker) === dashboardStore.sortOptions.trackerFilter)
-      }
-
       // update torrents
       torrents.value = data.map(t => torrentBuilder.buildFromQbit(t))
 
-      if (!isProduction.value) {
-        if (import.meta.env.VITE_USE_FAKE_TORRENTS === 'false') return
+      if (!isProduction.value && import.meta.env.VITE_USE_FAKE_TORRENTS === 'true') {
         const count = import.meta.env.VITE_FAKE_TORRENT_COUNT
         torrents.value.push(...generateMultiple(count).map(t => torrentBuilder.buildFromQbit(t)))
       }
@@ -296,7 +310,9 @@ export const useMaindataStore = defineStore('maindata', () => {
     serverState,
     tags,
     torrents,
+    torrentsWithFilters,
     trackers,
+    filters,
     getTorrentByHash,
     getTorrentIndexByHash,
     deleteTorrents,
@@ -340,4 +356,15 @@ export const useMaindataStore = defineStore('maindata', () => {
     setTorrentFilePriority,
     exportTorrent
   }
+}, {
+  persist: {
+    enabled: true,
+    strategies: [
+      {
+        storage: localStorage,
+        key: 'vuetorrent_maindata',
+        paths: ['filters']
+      }
+    ]
+  }
 })
diff --git a/src/styles/colors.scss b/src/styles/colors.scss
index eb4db4ab..52fa967c 100644
--- a/src/styles/colors.scss
+++ b/src/styles/colors.scss
@@ -8,21 +8,6 @@ $category: #04669a;
 $tag: #048b9a;
 $tracker: #c97d09;
 
-// State filter colors
-$state-downloading: #5bb974;
-$state-stalled_downloading: #5bb974;
-$state-seeding: #4ecde6;
-$state-stalled_uploading: #4ecde6;
-$state-completed: #16573e;
-$state-resumed: #bdbdbd;
-$state-active: #bdbdbd;
-$state-stalled: #696969;
-$state-paused: #696969;
-$state-inactive: #696969;
-$state-checking: #ff7043;
-$state-moving: #ffaa2c;
-$state-errored: #f83e70;
-
 // Torrent state colors
 $torrent-error: #f83e70;
 $torrent-missingFiles: #f83e70;
diff --git a/src/types/vuetorrent/Torrent.ts b/src/types/vuetorrent/Torrent.ts
index ff1877e5..028cb0ee 100644
--- a/src/types/vuetorrent/Torrent.ts
+++ b/src/types/vuetorrent/Torrent.ts
@@ -38,7 +38,7 @@ export default interface Torrent {
   size: number
   state: TorrentState
   super_seeding: boolean
-  tags: string[] | null
+  tags: string[]
   time_active: number
   total_size: number
   tracker: string