add basic functionality
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
ff2dea6a76
commit
d5b29bdc91
68
package-lock.json
generated
68
package-lock.json
generated
@ -9,6 +9,7 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mdi/font": "5.9.55",
|
"@mdi/font": "5.9.55",
|
||||||
|
"pinia": "^2.0.28",
|
||||||
"roboto-fontface": "*",
|
"roboto-fontface": "*",
|
||||||
"sass": "^1.57.1",
|
"sass": "^1.57.1",
|
||||||
"typescript": "^4.9.4",
|
"typescript": "^4.9.4",
|
||||||
@ -1696,6 +1697,56 @@
|
|||||||
"url": "https://github.com/sponsors/jonschlinkert"
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/pinia": {
|
||||||
|
"version": "2.0.28",
|
||||||
|
"resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.28.tgz",
|
||||||
|
"integrity": "sha512-YClq9DkqCblq9rlyUual7ezMu/iICWdBtfJrDt4oWU9Zxpijyz7xB2xTwx57DaBQ96UGvvTMORzALr+iO5PVMw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@vue/devtools-api": "^6.4.5",
|
||||||
|
"vue-demi": "*"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/posva"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@vue/composition-api": "^1.4.0",
|
||||||
|
"typescript": ">=4.4.4",
|
||||||
|
"vue": "^2.6.14 || ^3.2.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@vue/composition-api": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"typescript": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pinia/node_modules/vue-demi": {
|
||||||
|
"version": "0.13.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz",
|
||||||
|
"integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"bin": {
|
||||||
|
"vue-demi-fix": "bin/vue-demi-fix.js",
|
||||||
|
"vue-demi-switch": "bin/vue-demi-switch.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/antfu"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@vue/composition-api": "^1.0.0-rc.1",
|
||||||
|
"vue": "^3.0.0-0 || ^2.6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@vue/composition-api": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/pkg-dir": {
|
"node_modules/pkg-dir": {
|
||||||
"version": "4.2.0",
|
"version": "4.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
|
||||||
@ -3548,6 +3599,23 @@
|
|||||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="
|
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="
|
||||||
},
|
},
|
||||||
|
"pinia": {
|
||||||
|
"version": "2.0.28",
|
||||||
|
"resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.28.tgz",
|
||||||
|
"integrity": "sha512-YClq9DkqCblq9rlyUual7ezMu/iICWdBtfJrDt4oWU9Zxpijyz7xB2xTwx57DaBQ96UGvvTMORzALr+iO5PVMw==",
|
||||||
|
"requires": {
|
||||||
|
"@vue/devtools-api": "^6.4.5",
|
||||||
|
"vue-demi": "*"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"vue-demi": {
|
||||||
|
"version": "0.13.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz",
|
||||||
|
"integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==",
|
||||||
|
"requires": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"pkg-dir": {
|
"pkg-dir": {
|
||||||
"version": "4.2.0",
|
"version": "4.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mdi/font": "5.9.55",
|
"@mdi/font": "5.9.55",
|
||||||
|
"pinia": "^2.0.28",
|
||||||
"roboto-fontface": "*",
|
"roboto-fontface": "*",
|
||||||
"sass": "^1.57.1",
|
"sass": "^1.57.1",
|
||||||
"typescript": "^4.9.4",
|
"typescript": "^4.9.4",
|
||||||
|
58
src/App.vue
58
src/App.vue
@ -7,64 +7,6 @@ const drawer = ref();
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-app>
|
<v-app>
|
||||||
<v-app-bar
|
|
||||||
:collapse="false"
|
|
||||||
:collapse-on-scroll="true"
|
|
||||||
absolute
|
|
||||||
color="orange accent-4"
|
|
||||||
dark
|
|
||||||
scroll-target="#scrolling-techniques-6"
|
|
||||||
>
|
|
||||||
<v-app-bar-nav-icon @click.stop="drawer = !drawer"></v-app-bar-nav-icon>
|
|
||||||
<v-toolbar-title>IID Hausarbeit</v-toolbar-title>
|
|
||||||
<template v-slot:extension>
|
|
||||||
<v-tabs align-with-title>
|
|
||||||
<v-tab>Aktuelles</v-tab>
|
|
||||||
<v-tab>Chat</v-tab>
|
|
||||||
<v-tab>Termine</v-tab>
|
|
||||||
</v-tabs>
|
|
||||||
</template>
|
|
||||||
</v-app-bar>
|
|
||||||
|
|
||||||
<v-main>
|
|
||||||
<router-view />
|
<router-view />
|
||||||
</v-main>
|
|
||||||
|
|
||||||
<v-navigation-drawer absolute bottom temporary v-model="drawer">
|
|
||||||
<v-list nav dense>
|
|
||||||
<v-list-item-group active-class="deep-purple--text text--accent-4">
|
|
||||||
<v-list-item>
|
|
||||||
<v-list-item-title>Foo</v-list-item-title>
|
|
||||||
</v-list-item>
|
|
||||||
|
|
||||||
<v-list-item>
|
|
||||||
<v-list-item-title>Bar</v-list-item-title>
|
|
||||||
</v-list-item>
|
|
||||||
|
|
||||||
<v-list-item>
|
|
||||||
<v-list-item-title>Fizz</v-list-item-title>
|
|
||||||
</v-list-item>
|
|
||||||
|
|
||||||
<v-list-item>
|
|
||||||
<v-list-item-title>Buzz</v-list-item-title>
|
|
||||||
</v-list-item>
|
|
||||||
</v-list-item-group>
|
|
||||||
</v-list>
|
|
||||||
</v-navigation-drawer>
|
|
||||||
|
|
||||||
<v-bottom-navigation v-model="bottomNav">
|
|
||||||
<v-btn value="recent">
|
|
||||||
<span>Aktuelles</span>
|
|
||||||
<v-icon>mdi-history</v-icon>
|
|
||||||
</v-btn>
|
|
||||||
<v-btn value="favorites">
|
|
||||||
<span>Chat</span>
|
|
||||||
<v-icon>mdi-heart</v-icon>
|
|
||||||
</v-btn>
|
|
||||||
<v-btn value="nearby">
|
|
||||||
<span>Termine</span>
|
|
||||||
<v-icon>mdi-map-marker</v-icon>
|
|
||||||
</v-btn>
|
|
||||||
</v-bottom-navigation>
|
|
||||||
</v-app>
|
</v-app>
|
||||||
</template>
|
</template>
|
||||||
|
49
src/components/AddItemForm.vue
Normal file
49
src/components/AddItemForm.vue
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { useShoppingListStore } from '../store/shoppingList';
|
||||||
|
import { ref, reactive } from 'vue';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
|
const store = useShoppingListStore();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const isValid = ref(false);
|
||||||
|
const item = reactive({
|
||||||
|
name: '',
|
||||||
|
price: 0.99,
|
||||||
|
user: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
const form = ref(null);
|
||||||
|
|
||||||
|
const submit = () => {
|
||||||
|
store.items.push({
|
||||||
|
name: item.name,
|
||||||
|
price: item.price * 100,
|
||||||
|
user: store.users.find(user => user.name === item.user),
|
||||||
|
});
|
||||||
|
router.push('/shopping-list');
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<v-form ref="form" v-model="isValid" lazy-validation>
|
||||||
|
<v-text-field
|
||||||
|
label="Item Name"
|
||||||
|
required
|
||||||
|
v-model="item.name"
|
||||||
|
/>
|
||||||
|
<v-text-field
|
||||||
|
label="Price"
|
||||||
|
suffix="€"
|
||||||
|
required
|
||||||
|
v-model="item.price"
|
||||||
|
/>
|
||||||
|
<v-select
|
||||||
|
label="User"
|
||||||
|
:items="store.users.map(user => user.name)"
|
||||||
|
required
|
||||||
|
v-model="item.user"
|
||||||
|
/>
|
||||||
|
<v-btn color="primary" @click="submit()">add item</v-btn>
|
||||||
|
</v-form>
|
||||||
|
</template>
|
39
src/components/DefaultPage.vue
Normal file
39
src/components/DefaultPage.vue
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, defineProps } from 'vue';
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
tabs: Array,
|
||||||
|
title: String,
|
||||||
|
});
|
||||||
|
const tab = ref(null);
|
||||||
|
|
||||||
|
const back = () => {
|
||||||
|
window.history.back();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<v-app-bar
|
||||||
|
:collapse="false"
|
||||||
|
:collapse-on-scroll="true"
|
||||||
|
absolute
|
||||||
|
color="blue accent-4"
|
||||||
|
dark
|
||||||
|
scroll-target="#scrolling-techniques-6"
|
||||||
|
>
|
||||||
|
<v-btn icon @click="back()">
|
||||||
|
<v-icon>mdi-arrow-left</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
<v-toolbar-title>{{ title }}</v-toolbar-title>
|
||||||
|
<template v-if="tabs?.length" v-slot:extension>
|
||||||
|
<v-tabs align-with-title v-model="tab">
|
||||||
|
<slot name="tabs">
|
||||||
|
<v-tab v-for="tab of tabs" :value="tab.name.toLowerCase().replaceAll(' ', '-')">{{ tab.name }}</v-tab>
|
||||||
|
</slot>
|
||||||
|
</v-tabs>
|
||||||
|
</template>
|
||||||
|
</v-app-bar>
|
||||||
|
<v-main>
|
||||||
|
<slot :tab="tab"/>
|
||||||
|
</v-main>
|
||||||
|
</template>
|
@ -1,152 +0,0 @@
|
|||||||
<template>
|
|
||||||
<v-container>
|
|
||||||
<v-row class="text-center">
|
|
||||||
<v-col cols="12">
|
|
||||||
<v-img
|
|
||||||
:src="logo"
|
|
||||||
class="my-3"
|
|
||||||
contain
|
|
||||||
height="200"
|
|
||||||
/>
|
|
||||||
</v-col>
|
|
||||||
|
|
||||||
<v-col class="mb-4">
|
|
||||||
<h1 class="display-2 font-weight-bold mb-3">
|
|
||||||
Welcome to the Vuetify 3 Beta
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<h4>Vite Preview</h4>
|
|
||||||
|
|
||||||
<p class="subheading font-weight-regular">
|
|
||||||
For help and collaboration with other Vuetify developers,
|
|
||||||
<br>please join our online
|
|
||||||
<a
|
|
||||||
href="https://community.vuetifyjs.com"
|
|
||||||
target="_blank"
|
|
||||||
>Discord Community</a>
|
|
||||||
</p>
|
|
||||||
</v-col>
|
|
||||||
|
|
||||||
<v-col
|
|
||||||
class="mb-5"
|
|
||||||
cols="12"
|
|
||||||
>
|
|
||||||
<h2 class="headline font-weight-bold mb-5">
|
|
||||||
What's next?
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<v-row justify="center">
|
|
||||||
<a
|
|
||||||
v-for="(next, i) in whatsNext"
|
|
||||||
:key="i"
|
|
||||||
:href="next.href"
|
|
||||||
class="subheading mx-3"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
{{ next.text }}
|
|
||||||
</a>
|
|
||||||
</v-row>
|
|
||||||
</v-col>
|
|
||||||
|
|
||||||
<v-col
|
|
||||||
class="mb-5"
|
|
||||||
cols="12"
|
|
||||||
>
|
|
||||||
<h2 class="headline font-weight-bold mb-5">
|
|
||||||
Important Links
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<v-row justify="center">
|
|
||||||
<a
|
|
||||||
v-for="(link, i) in importantLinks"
|
|
||||||
:key="i"
|
|
||||||
:href="link.href"
|
|
||||||
class="subheading mx-3"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
{{ link.text }}
|
|
||||||
</a>
|
|
||||||
</v-row>
|
|
||||||
</v-col>
|
|
||||||
|
|
||||||
<v-col
|
|
||||||
class="mb-5"
|
|
||||||
cols="12"
|
|
||||||
>
|
|
||||||
<h2 class="headline font-weight-bold mb-5">
|
|
||||||
Ecosystem
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<v-row justify="center">
|
|
||||||
<a
|
|
||||||
v-for="(eco, i) in ecosystem"
|
|
||||||
:key="i"
|
|
||||||
:href="eco.href"
|
|
||||||
class="subheading mx-3"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
{{ eco.text }}
|
|
||||||
</a>
|
|
||||||
</v-row>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
</v-container>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import logo from '../assets/logo.svg'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'HelloWorld',
|
|
||||||
|
|
||||||
data: () => ({
|
|
||||||
ecosystem: [
|
|
||||||
{
|
|
||||||
text: 'vuetify-loader',
|
|
||||||
href: 'https://github.com/vuetifyjs/vuetify-loader/tree/next',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'github',
|
|
||||||
href: 'https://github.com/vuetifyjs/vuetify/tree/next',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'awesome-vuetify',
|
|
||||||
href: 'https://github.com/vuetifyjs/awesome-vuetify',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
importantLinks: [
|
|
||||||
{
|
|
||||||
text: 'Chat',
|
|
||||||
href: 'https://community.vuetifyjs.com',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Made with Vuetify',
|
|
||||||
href: 'https://madewithvuejs.com/vuetify',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Twitter',
|
|
||||||
href: 'https://twitter.com/vuetifyjs',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Articles',
|
|
||||||
href: 'https://medium.com/vuetify',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
logo,
|
|
||||||
whatsNext: [
|
|
||||||
{
|
|
||||||
text: 'Explore components',
|
|
||||||
href: 'https://vuetifyjs.com',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Roadmap',
|
|
||||||
href: 'https://vuetifyjs.com/introduction/roadmap/',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Frequently Asked Questions',
|
|
||||||
href: 'https://vuetifyjs.com/getting-started/frequently-asked-questions',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
</script>
|
|
23
src/components/ItemList.vue
Normal file
23
src/components/ItemList.vue
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { defineProps } from 'vue';
|
||||||
|
import { groupItemsByUser } from '../store/shoppingList';
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
items: Array,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<v-list v-if="items.length" lines="theee" select-strategy="multiple">
|
||||||
|
<div v-for="(items, user) of groupItemsByUser(items)">
|
||||||
|
<v-list-subheader>{{ user }}</v-list-subheader>
|
||||||
|
<div v-for="item in items">
|
||||||
|
<v-list-item @click="item.isBought = !item.isBought">
|
||||||
|
<v-list-item-title>{{ item.name }}</v-list-item-title>
|
||||||
|
<v-list-item-subtitle>{{ item.price / 100 }} €</v-list-item-subtitle>
|
||||||
|
</v-list-item>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</v-list>
|
||||||
|
<p v-else>There are no items in this list.</p>
|
||||||
|
</template>
|
@ -3,10 +3,12 @@ import App from './App.vue'
|
|||||||
import vuetify from './plugins/vuetify'
|
import vuetify from './plugins/vuetify'
|
||||||
import { loadFonts } from './plugins/webfontloader'
|
import { loadFonts } from './plugins/webfontloader'
|
||||||
import router from './router';
|
import router from './router';
|
||||||
|
import { createPinia } from 'pinia';
|
||||||
|
|
||||||
loadFonts()
|
loadFonts()
|
||||||
|
|
||||||
createApp(App)
|
createApp(App)
|
||||||
.use(router)
|
.use(router)
|
||||||
.use(vuetify)
|
.use(vuetify)
|
||||||
|
.use(createPinia())
|
||||||
.mount('#app')
|
.mount('#app')
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
|
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
|
||||||
import HomeView from '../views/HomeView.vue';
|
import HomeView from '../views/HomeView.vue';
|
||||||
|
import ShoppingList from '../views/ShoppingList.vue';
|
||||||
|
import AddItem from '../views/AddItem.vue';
|
||||||
|
|
||||||
const routes: Array<RouteRecordRaw> = [
|
const routes: Array<RouteRecordRaw> = [
|
||||||
{
|
{
|
||||||
@ -7,6 +9,16 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
name: "home",
|
name: "home",
|
||||||
component: HomeView,
|
component: HomeView,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/shopping-list",
|
||||||
|
name: "shopping-list",
|
||||||
|
component: ShoppingList,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/add-item",
|
||||||
|
name: "add-item",
|
||||||
|
component: AddItem,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
|
30
src/store/dummyData.ts
Normal file
30
src/store/dummyData.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
const lukas = {
|
||||||
|
name: 'lukas',
|
||||||
|
};
|
||||||
|
|
||||||
|
const laura = {
|
||||||
|
name: 'laura'
|
||||||
|
};
|
||||||
|
|
||||||
|
export const users = [ lukas, laura ];
|
||||||
|
|
||||||
|
export const dummyList = [
|
||||||
|
{
|
||||||
|
name: 'Banana',
|
||||||
|
price: 200,
|
||||||
|
user: lukas,
|
||||||
|
isBought: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Apple',
|
||||||
|
price: 150,
|
||||||
|
user: lukas,
|
||||||
|
isBought: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Butter',
|
||||||
|
price: 149,
|
||||||
|
user: laura,
|
||||||
|
isBought: false,
|
||||||
|
},
|
||||||
|
];
|
36
src/store/shoppingList.ts
Normal file
36
src/store/shoppingList.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import { defineStore } from 'pinia';
|
||||||
|
import { dummyList, users } from './dummyData';
|
||||||
|
|
||||||
|
type User = {
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ShoppingItem = {
|
||||||
|
name: string;
|
||||||
|
price: number;
|
||||||
|
isBought: boolean;
|
||||||
|
user: User;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useShoppingListStore = defineStore('shoppingList', {
|
||||||
|
state() {
|
||||||
|
return {
|
||||||
|
items: dummyList as Array<ShoppingItem>,
|
||||||
|
users: users as Array<User>,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
actions: {},
|
||||||
|
getters: {
|
||||||
|
openItems: state => state.items.filter(item => !item.isBought),
|
||||||
|
boughtItems: state => state.items.filter(item => !!item.isBought),
|
||||||
|
itemsByUser: state => groupItemsByUser(state.items),
|
||||||
|
openItemsByUser: state => groupItemsByUser(state.items.filter(item => !item.isBought)),
|
||||||
|
boughtItemsByUser: state => groupItemsByUser(state.items.filter(item => !!item.isBought)),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const groupItemsByUser = items => items.reduce((groups, item) => {
|
||||||
|
if (!groups[item.user.name]) groups[item.user.name] = [];
|
||||||
|
groups[item.user.name].push(item);
|
||||||
|
return groups;
|
||||||
|
}, {});
|
12
src/views/AddItem.vue
Normal file
12
src/views/AddItem.vue
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import DefaultPage from '../components/DefaultPage.vue';
|
||||||
|
import AddItemForm from '../components/AddItemForm.vue';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<DefaultPage title="Add Item">
|
||||||
|
<v-container>
|
||||||
|
<AddItemForm/>
|
||||||
|
</v-container>
|
||||||
|
</DefaultPage>
|
||||||
|
</template>
|
@ -3,16 +3,15 @@
|
|||||||
<v-row class="text-center">
|
<v-row class="text-center">
|
||||||
<v-col class="mb-4">
|
<v-col class="mb-4">
|
||||||
<h1 class="display-2 font-weight-bold mb-3">
|
<h1 class="display-2 font-weight-bold mb-3">
|
||||||
Hallo World
|
Welcome :D
|
||||||
</h1>
|
</h1>
|
||||||
<p class="subheading font-weight-regular">
|
<p class="subheading font-weight-regular">
|
||||||
bla bla
|
a simple app to organize your shopping list
|
||||||
</p>
|
</p>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
<v-row align="center" justify="space-around">
|
<v-row align="center" justify="space-around">
|
||||||
<v-btn depressed>Login</v-btn>
|
<v-btn color="primary" to="/shopping-list">get started</v-btn>
|
||||||
<v-btn depressed color="primary">Chat</v-btn>
|
|
||||||
</v-row>
|
</v-row>
|
||||||
</v-container>
|
</v-container>
|
||||||
</template>
|
</template>
|
||||||
|
36
src/views/ShoppingList.vue
Normal file
36
src/views/ShoppingList.vue
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import DefaultPage from '../components/DefaultPage.vue';
|
||||||
|
import ItemList from '../components/ItemList.vue';
|
||||||
|
import { useShoppingListStore } from '../store/shoppingList';
|
||||||
|
|
||||||
|
const store = useShoppingListStore();
|
||||||
|
|
||||||
|
const tabs = [
|
||||||
|
{ name: 'open items' },
|
||||||
|
{ name: 'bought items' },
|
||||||
|
];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<DefaultPage :tabs="tabs" v-slot="slot" title="Shopping List">
|
||||||
|
<v-container>
|
||||||
|
<v-window v-model="slot.tab">
|
||||||
|
<v-window-item value="open-items">
|
||||||
|
<ItemList :items="store.openItems"></ItemList>
|
||||||
|
</v-window-item>
|
||||||
|
<v-window-item value="bought-items">
|
||||||
|
<ItemList :items="store.boughtItems"></ItemList>
|
||||||
|
</v-window-item>
|
||||||
|
</v-window>
|
||||||
|
</v-container>
|
||||||
|
<v-card-text style="display: flex; justify-content: end">
|
||||||
|
<v-btn
|
||||||
|
icon="mdi-plus"
|
||||||
|
color="red"
|
||||||
|
to="/add-item"
|
||||||
|
elevation="8"
|
||||||
|
size="large"
|
||||||
|
/>
|
||||||
|
</v-card-text>
|
||||||
|
</DefaultPage>
|
||||||
|
</template>
|
Loading…
Reference in New Issue
Block a user