diff --git a/frontend/.storybook/ApolloWrapper.vue b/frontend/.storybook/ApolloWrapper.vue
index 33872d5e2a..60c6b6c7fb 100644
--- a/frontend/.storybook/ApolloWrapper.vue
+++ b/frontend/.storybook/ApolloWrapper.vue
@@ -3,30 +3,54 @@
diff --git a/frontend/scripts/tests/mock.apolloClient.ts b/frontend/scripts/tests/mock.apolloClient.ts
index c9b2a78be1..0cfbcd8f7a 100644
--- a/frontend/scripts/tests/mock.apolloClient.ts
+++ b/frontend/scripts/tests/mock.apolloClient.ts
@@ -1,9 +1,19 @@
import { DefaultApolloClient } from '@vue/apollo-composable'
import { config } from '@vue/test-utils'
import { createMockClient } from 'mock-apollo-client'
+import { vi } from 'vitest'
+
+import { openRoomsQuery } from '#src/graphql/queries/openRoomsQuery'
export const mockClient = createMockClient()
+export const openRoomsQueryMock = vi.fn()
+
+mockClient.setRequestHandler(
+ openRoomsQuery,
+ openRoomsQueryMock.mockResolvedValue({ data: { openRooms: [] } }),
+)
+
config.global.provide = {
...config.global.provide,
[DefaultApolloClient]: mockClient,
diff --git a/frontend/src/components/menu/BottomMenu.vue b/frontend/src/components/menu/BottomMenu.vue
index b449801740..f6552917e9 100644
--- a/frontend/src/components/menu/BottomMenu.vue
+++ b/frontend/src/components/menu/BottomMenu.vue
@@ -1,8 +1,15 @@
+
+
+
+
diff --git a/frontend/src/components/menu/__snapshots__/BottomMenu.test.ts.snap b/frontend/src/components/menu/__snapshots__/BottomMenu.test.ts.snap
index 9a3f34941b..981a619ee1 100644
--- a/frontend/src/components/menu/__snapshots__/BottomMenu.test.ts.snap
+++ b/frontend/src/components/menu/__snapshots__/BottomMenu.test.ts.snap
@@ -8,8 +8,129 @@ exports[`BottomMenu > renders BottomMenu 1`] = `
class="v-application__wrap"
>
+
+
+
+
+
+
+
+
+
`;
diff --git a/frontend/src/components/menu/__snapshots__/TopMenu.test.ts.snap b/frontend/src/components/menu/__snapshots__/TopMenu.test.ts.snap
index fd3067d195..125baee1eb 100644
--- a/frontend/src/components/menu/__snapshots__/TopMenu.test.ts.snap
+++ b/frontend/src/components/menu/__snapshots__/TopMenu.test.ts.snap
@@ -8,6 +8,7 @@ exports[`TopMenu > renders 1`] = `
class="v-application__wrap"
>
+
+
+
+
+
+
+
+
`;
diff --git a/frontend/src/components/vuetify/Atoms/ListElement.stories.ts b/frontend/src/components/vuetify/Atoms/ListElement.stories.ts
new file mode 100644
index 0000000000..18e3cf998e
--- /dev/null
+++ b/frontend/src/components/vuetify/Atoms/ListElement.stories.ts
@@ -0,0 +1,153 @@
+// import { VIcon, VBtn, VAvatar, VImg } from 'vuetify/components'
+
+import { SBComp } from '#types/SBComp'
+
+import ListElement from './ListElement.vue'
+
+import type { Meta, StoryObj } from '@storybook/vue3'
+
+const meta: Meta = {
+ title: 'MOLECULES/ListElement',
+ component: ListElement as SBComp,
+ tags: ['autodocs'],
+ argTypes: {},
+ args: {
+ items: [
+ {
+ meetingName: 'Beispiel Titel 1',
+ meetingID: 'xxx',
+ startTime: '1234',
+ participantCount: 4,
+ attendees: [],
+ joinLink: 'https://my.link',
+ // rounded: true,
+ // prepend: VIcon,
+ // prependProps: { icon: 'mdi-home' },
+ // append: VBtn,
+ // appendProps: { icon: 'mdi-menu' },
+ },
+ {
+ meetingName: 'Beispiel Titel 2',
+ meetingID: 'xxx',
+ startTime: '1234',
+ participantCount: 4,
+ attendees: [],
+ joinLink: 'https://my.link',
+ // rounded: true,
+ // prepend: VAvatar,
+ // prependProps: { src: 'https://via.placeholder.com/40' },
+ // append: VIcon,
+ // appendProps: { icon: 'mdi-menu' },
+ },
+ ],
+ },
+ parameters: {
+ appHeight: '100vh',
+ },
+} satisfies Meta
+
+export default meta
+type Story = StoryObj
+
+export const Basic: Story = {
+ args: {
+ items: [
+ {
+ meetingName: 'Beispiel Titel 1',
+ meetingID: 'xxx',
+ startTime: '1234',
+ participantCount: 4,
+ attendees: [],
+ joinLink: 'https://my.link',
+ // append: VBtn,
+ // appendProps: { icon: 'mdi-menu' },
+ },
+ {
+ meetingName: 'Beispiel Titel 2',
+ meetingID: 'xxx',
+ startTime: '1234',
+ participantCount: 4,
+ attendees: [],
+ joinLink: 'https://my.link',
+ // append: VIcon,
+ // appendProps: { icon: 'mdi-menu' },
+ },
+ ],
+ },
+}
+
+/*
+export const WithIcons: Story = {
+ args: {
+ items: [
+ {
+ title: 'Home',
+ prepend: VIcon,
+ prependProps: { icon: 'mdi-home' },
+ append: VIcon,
+ appendProps: { icon: 'mdi-menu' },
+ },
+ {
+ title: 'Profile',
+ prepend: VIcon,
+ prependProps: { icon: 'mdi-account' },
+ append: VIcon,
+ appendProps: { icon: 'mdi-menu' },
+ },
+ {
+ title: 'Settings',
+ prepend: VIcon,
+ prependProps: { icon: 'mdi-settings' },
+ append: VIcon,
+ appendProps: { icon: 'mdi-menu' },
+ },
+ {
+ title: 'Logout',
+ prepend: VIcon,
+ prependProps: { icon: 'mdi-logout' },
+ append: VIcon,
+ appendProps: { icon: 'mdi-menu' },
+ },
+ ],
+ },
+}
+
+export const WithImages: Story = {
+ args: {
+ items: [
+ {
+ title: 'Item 1',
+ subtitle: 'Subtitle 1',
+ prepend: VImg,
+ prependProps: { src: 'https://via.placeholder.com/40' },
+ append: VIcon,
+ appendProps: { icon: 'mdi-menu' },
+ },
+ {
+ title: 'Item 2',
+ subtitle: 'Subtitle 2',
+ prepend: VImg,
+ prependProps: { src: 'https://via.placeholder.com/40' },
+ append: VIcon,
+ appendProps: { icon: 'mdi-menu' },
+ },
+ {
+ title: 'Item 3',
+ subtitle: 'Subtitle 3',
+ prepend: VImg,
+ prependProps: { src: 'https://via.placeholder.com/40' },
+ append: VIcon,
+ appendProps: { icon: 'mdi-menu' },
+ },
+ {
+ title: 'Item 4',
+ subtitle: 'Subtitle 4',
+ prepend: VImg,
+ prependProps: { src: 'https://via.placeholder.com/40' },
+ append: VIcon,
+ appendProps: { icon: 'mdi-menu' },
+ },
+ ],
+ },
+}
+*/
diff --git a/frontend/src/components/vuetify/Atoms/ListElement.test.ts b/frontend/src/components/vuetify/Atoms/ListElement.test.ts
new file mode 100644
index 0000000000..f5254232ce
--- /dev/null
+++ b/frontend/src/components/vuetify/Atoms/ListElement.test.ts
@@ -0,0 +1,30 @@
+import { mount } from '@vue/test-utils'
+import { describe, it, expect, beforeEach } from 'vitest'
+import { h } from 'vue'
+import { VApp } from 'vuetify/components'
+
+import ListElement from './ListElement.vue'
+
+describe('ListElement', () => {
+ const Wrapper = () => {
+ return mount(VApp, {
+ slots: {
+ default: h(ListElement),
+ },
+ })
+ }
+
+ let wrapper: ReturnType
+
+ beforeEach(() => {
+ wrapper = Wrapper()
+ })
+
+ it('renders correctly', () => {
+ expect(wrapper.element).toMatchSnapshot()
+ })
+
+ it('renders list', () => {
+ expect(wrapper.find('.v-list--density-default').exists()).toBe(true)
+ })
+})
diff --git a/frontend/src/components/vuetify/Atoms/ListElement.vue b/frontend/src/components/vuetify/Atoms/ListElement.vue
new file mode 100644
index 0000000000..aefe4060fb
--- /dev/null
+++ b/frontend/src/components/vuetify/Atoms/ListElement.vue
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/components/vuetify/Atoms/__snapshots__/ListElement.test.ts.snap b/frontend/src/components/vuetify/Atoms/__snapshots__/ListElement.test.ts.snap
new file mode 100644
index 0000000000..315cd5865f
--- /dev/null
+++ b/frontend/src/components/vuetify/Atoms/__snapshots__/ListElement.test.ts.snap
@@ -0,0 +1,81 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`ListElement > renders correctly 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/frontend/src/components/vuetify/Molecules/SearchField.stories.ts b/frontend/src/components/vuetify/Molecules/SearchField.stories.ts
new file mode 100644
index 0000000000..b59cb6b67f
--- /dev/null
+++ b/frontend/src/components/vuetify/Molecules/SearchField.stories.ts
@@ -0,0 +1,24 @@
+/* eslint-disable @typescript-eslint/no-unsafe-assignment */
+
+import { Meta, StoryFn } from '@storybook/vue3'
+
+import SearchDrawerField from './SearchField.vue'
+
+export default {
+ title: 'Molecules/SearchField',
+ component: SearchDrawerField,
+} as Meta
+
+const Template: StoryFn = (args) => ({
+ components: { SearchDrawerField },
+ setup() {
+ return { args }
+ },
+ template: '',
+})
+
+export const Default = Template.bind({})
+Default.args = {
+ label: 'Search',
+ prependInnerIcon: 'mdi-tune',
+}
diff --git a/frontend/src/components/vuetify/Molecules/SearchField.test.ts b/frontend/src/components/vuetify/Molecules/SearchField.test.ts
new file mode 100644
index 0000000000..15f051e19d
--- /dev/null
+++ b/frontend/src/components/vuetify/Molecules/SearchField.test.ts
@@ -0,0 +1,26 @@
+import { mount } from '@vue/test-utils'
+import { describe, it, expect, beforeEach } from 'vitest'
+import { h } from 'vue'
+import { VApp } from 'vuetify/components'
+
+import SearchField from './SearchField.vue'
+
+describe('SearchField', () => {
+ const Wrapper = () => {
+ return mount(VApp, {
+ slots: {
+ default: h(SearchField),
+ },
+ })
+ }
+
+ let wrapper: ReturnType
+
+ beforeEach(() => {
+ wrapper = Wrapper()
+ })
+
+ it('renders', () => {
+ expect(wrapper.element).toMatchSnapshot()
+ })
+})
diff --git a/frontend/src/components/vuetify/Molecules/SearchField.vue b/frontend/src/components/vuetify/Molecules/SearchField.vue
new file mode 100644
index 0000000000..5587ce848b
--- /dev/null
+++ b/frontend/src/components/vuetify/Molecules/SearchField.vue
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
diff --git a/frontend/src/components/vuetify/Molecules/__snapshots__/SearchField.test.ts.snap b/frontend/src/components/vuetify/Molecules/__snapshots__/SearchField.test.ts.snap
new file mode 100644
index 0000000000..eeebdfb3a2
--- /dev/null
+++ b/frontend/src/components/vuetify/Molecules/__snapshots__/SearchField.test.ts.snap
@@ -0,0 +1,169 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`SearchField > renders 1`] = `
+
+`;
diff --git a/frontend/src/components/vuetify/Organisms/ListWithNavigationDrawer.stories.ts b/frontend/src/components/vuetify/Organisms/ListWithNavigationDrawer.stories.ts
new file mode 100644
index 0000000000..096986a91d
--- /dev/null
+++ b/frontend/src/components/vuetify/Organisms/ListWithNavigationDrawer.stories.ts
@@ -0,0 +1,27 @@
+import { SBComp } from '#types/SBComp'
+
+import ListWithNavigationDrawer from './ListWithNavigationDrawer.vue'
+
+import type { Meta, StoryObj } from '@storybook/vue3'
+
+const meta = {
+ title: 'ORGANISMS/ListWithNavigationDrawer',
+ component: ListWithNavigationDrawer as SBComp,
+ tags: ['autodocs'],
+ argTypes: {},
+ args: {
+ drawer: false,
+ },
+ parameters: {
+ appHeight: '100vh',
+ },
+} satisfies Meta
+
+export default meta
+type Story = StoryObj
+
+export const Example: Story = {
+ args: {
+ drawer: false,
+ },
+}
diff --git a/frontend/src/components/vuetify/Organisms/ListWithNavigationDrawer.test.ts b/frontend/src/components/vuetify/Organisms/ListWithNavigationDrawer.test.ts
new file mode 100644
index 0000000000..5a5d86b717
--- /dev/null
+++ b/frontend/src/components/vuetify/Organisms/ListWithNavigationDrawer.test.ts
@@ -0,0 +1,26 @@
+import { mount } from '@vue/test-utils'
+import { describe, it, expect, beforeEach } from 'vitest'
+import { Component, h } from 'vue'
+import { VApp } from 'vuetify/components'
+
+import ListWithNavigationDrawer from './ListWithNavigationDrawer.vue'
+
+describe('ListWithNavigationDrawer', () => {
+ const Wrapper = () => {
+ return mount(VApp, {
+ slots: {
+ default: h(ListWithNavigationDrawer as Component),
+ },
+ })
+ }
+
+ let wrapper: ReturnType
+
+ beforeEach(() => {
+ wrapper = Wrapper()
+ })
+
+ it('renders correctly', () => {
+ expect(wrapper.element).toMatchSnapshot()
+ })
+})
diff --git a/frontend/src/components/vuetify/Organisms/ListWithNavigationDrawer.vue b/frontend/src/components/vuetify/Organisms/ListWithNavigationDrawer.vue
new file mode 100644
index 0000000000..c7c0740b3b
--- /dev/null
+++ b/frontend/src/components/vuetify/Organisms/ListWithNavigationDrawer.vue
@@ -0,0 +1,69 @@
+
+
+
+
+
+
diff --git a/frontend/src/components/vuetify/Organisms/__snapshots__/ListWithNavigationDrawer.test.ts.snap b/frontend/src/components/vuetify/Organisms/__snapshots__/ListWithNavigationDrawer.test.ts.snap
new file mode 100644
index 0000000000..e865793f62
--- /dev/null
+++ b/frontend/src/components/vuetify/Organisms/__snapshots__/ListWithNavigationDrawer.test.ts.snap
@@ -0,0 +1,129 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`ListWithNavigationDrawer > renders correctly 1`] = `
+
+`;
diff --git a/frontend/src/components/vuetify/__snapshots__/ListElement.test.ts.snap b/frontend/src/components/vuetify/__snapshots__/ListElement.test.ts.snap
new file mode 100644
index 0000000000..f7871493a0
--- /dev/null
+++ b/frontend/src/components/vuetify/__snapshots__/ListElement.test.ts.snap
@@ -0,0 +1,81 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`ListElement > renders correctly 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/frontend/src/graphql/queries/openRoomsQuery.ts b/frontend/src/graphql/queries/openRoomsQuery.ts
new file mode 100644
index 0000000000..2d780b612a
--- /dev/null
+++ b/frontend/src/graphql/queries/openRoomsQuery.ts
@@ -0,0 +1,16 @@
+import { gql } from 'graphql-tag'
+
+export const openRoomsQuery = gql`
+ query {
+ openRooms {
+ meetingID
+ meetingName
+ startTime
+ participantCount
+ attendees {
+ fullName
+ }
+ joinLink
+ }
+ }
+`
diff --git a/frontend/src/layouts/__snapshots__/DefaultLayout.test.ts.snap b/frontend/src/layouts/__snapshots__/DefaultLayout.test.ts.snap
index dded014614..c9ec6877bb 100644
--- a/frontend/src/layouts/__snapshots__/DefaultLayout.test.ts.snap
+++ b/frontend/src/layouts/__snapshots__/DefaultLayout.test.ts.snap
@@ -14,15 +14,15 @@ exports[`DefaultLayout > renders 1`] = `
style="--v-layout-left: 0px; --v-layout-right: 0px; --v-layout-top: NaN; --v-layout-bottom: 0px; transition: none !important;"
>
+
+
+
+
+
+
+
+
renders 1`] = `
+
+
+
+
+
+