Compare commits
No commits in common. "develop" and "v1.0.0-alpha.1" have entirely different histories.
develop
...
v1.0.0-alp
19
.eslintrc.js
19
.eslintrc.js
|
@ -17,11 +17,11 @@ module.exports = {
|
||||||
project: resolve(__dirname, './tsconfig.json'),
|
project: resolve(__dirname, './tsconfig.json'),
|
||||||
tsconfigRootDir: __dirname,
|
tsconfigRootDir: __dirname,
|
||||||
ecmaVersion: 2019, // Allows for the parsing of modern ECMAScript features
|
ecmaVersion: 2019, // Allows for the parsing of modern ECMAScript features
|
||||||
sourceType: 'module', // Allows for the use of imports
|
sourceType: 'module' // Allows for the use of imports
|
||||||
},
|
},
|
||||||
|
|
||||||
env: {
|
env: {
|
||||||
browser: true,
|
browser: true
|
||||||
},
|
},
|
||||||
|
|
||||||
// Rules order is important, please avoid shuffling them
|
// Rules order is important, please avoid shuffling them
|
||||||
|
@ -44,7 +44,7 @@ module.exports = {
|
||||||
|
|
||||||
// https://github.com/prettier/eslint-config-prettier#installation
|
// https://github.com/prettier/eslint-config-prettier#installation
|
||||||
// usage with Prettier, provided by 'eslint-config-prettier'.
|
// usage with Prettier, provided by 'eslint-config-prettier'.
|
||||||
'plugin:prettier/recommended',
|
'prettier', //'plugin:prettier/recommended'
|
||||||
],
|
],
|
||||||
|
|
||||||
plugins: [
|
plugins: [
|
||||||
|
@ -54,6 +54,10 @@ module.exports = {
|
||||||
// https://eslint.vuejs.org/user-guide/#why-doesn-t-it-work-on-vue-file
|
// https://eslint.vuejs.org/user-guide/#why-doesn-t-it-work-on-vue-file
|
||||||
// required to lint *.vue files
|
// required to lint *.vue files
|
||||||
'vue',
|
'vue',
|
||||||
|
|
||||||
|
// https://github.com/typescript-eslint/typescript-eslint/issues/389#issuecomment-509292674
|
||||||
|
// Prettier has not been included as plugin to avoid performance impact
|
||||||
|
// add it as an extension for your IDE
|
||||||
],
|
],
|
||||||
|
|
||||||
// add your custom rules here
|
// add your custom rules here
|
||||||
|
@ -61,12 +65,11 @@ module.exports = {
|
||||||
'prefer-promise-reject-errors': 'off',
|
'prefer-promise-reject-errors': 'off',
|
||||||
|
|
||||||
// TypeScript
|
// TypeScript
|
||||||
quotes: ['error', 'single', { avoidEscape: true }],
|
quotes: ['warn', 'single', { avoidEscape: true }],
|
||||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||||
'vue/multi-word-component-names': 'off',
|
|
||||||
|
|
||||||
// allow debugger during development only
|
// allow debugger during development only
|
||||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
|
||||||
},
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -2,5 +2,4 @@ node_modules
|
||||||
yarn-error.log
|
yarn-error.log
|
||||||
# No need for sharing this
|
# No need for sharing this
|
||||||
yarn.lock
|
yarn.lock
|
||||||
.idea
|
|
||||||
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
.woodpecker/
|
|
|
@ -1,14 +0,0 @@
|
||||||
pipeline:
|
|
||||||
deploy:
|
|
||||||
when:
|
|
||||||
event: tag
|
|
||||||
tag: v*
|
|
||||||
image: node:lts-alpine
|
|
||||||
commands:
|
|
||||||
- echo "//registry.npmjs.org/:_authToken=$NODE_AUTH_TOKEN" > .npmrc
|
|
||||||
- yarn publish --non-interactive
|
|
||||||
secrets: [ node_auth_token ]
|
|
||||||
|
|
||||||
depends_on:
|
|
||||||
- lint
|
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
pipeline:
|
|
||||||
lint:
|
|
||||||
when:
|
|
||||||
branch: [main, develop]
|
|
||||||
image: node:lts-alpine
|
|
||||||
commands:
|
|
||||||
- yarn install
|
|
||||||
- yarn lint
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
# Flaschengeist `pricelist` fontend-plugin
|
# Flaschengeist `pricelist` fontend-plugin
|
||||||

|
|
||||||
|
|
||||||
This package provides the [Flaschengeist](https://flaschengeist.dev/Flaschengeist/flaschengeist) frontend for the pricelist plugin (build and manage drinks, show pricelist and calculate prices).
|
This package provides the [Flaschengeist](https://flaschengeist.dev/Flaschengeist/flaschengeist) frontend for the pricelist plugin (build and manage drinks, show pricelist and calculate prices).
|
||||||
|
|
||||||
|
|
34
package.json
34
package.json
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"version": "1.0.0-alpha.5",
|
"version": "1.0.0-alpha.1",
|
||||||
"name": "@flaschengeist/pricelist",
|
"name": "@flaschengeist/pricelist",
|
||||||
"author": "Tim Gröger <flaschengeist@wu5.de>",
|
"author": "Tim Gröger <flaschengeist@wu5.de>",
|
||||||
"homepage": "https://flaschengeist.dev/Flaschengeist",
|
"homepage": "https://flaschengeist.dev/Flaschengeist",
|
||||||
|
@ -15,34 +15,34 @@
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"types": "src/api.d.ts",
|
"types": "src/api.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"format": "prettier --config ./package.json --write '{,!(node_modules)/**/}*.{ts,vue,js}'",
|
"format": "prettier --config ./package.json --write '{,!(node_modules)/**/}*.ts'",
|
||||||
"lint": "eslint --ext .js,.ts,.vue ./src"
|
"lint": "eslint --ext .js,.ts,.vue ./src"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"vuedraggable": "^4.1.0"
|
"vuedraggable": "^4.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@flaschengeist/types": "^1.0.0-alpha.10",
|
"@flaschengeist/types": "^1.0.0-alpha.1",
|
||||||
"@quasar/app": "^3.2.4",
|
"@quasar/app": "^3.0.0-beta.26",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.5.0",
|
"@typescript-eslint/eslint-plugin": "^4.24.0",
|
||||||
"@typescript-eslint/parser": "^5.5.0",
|
"@typescript-eslint/parser": "^4.24.0",
|
||||||
"eslint": "^8.2.0",
|
"axios": "^0.21.1",
|
||||||
|
"eslint": "^7.26.0",
|
||||||
"eslint-config-prettier": "^8.3.0",
|
"eslint-config-prettier": "^8.3.0",
|
||||||
"eslint-plugin-prettier": "^4.0.0",
|
"eslint-plugin-vue": "^7.9.0",
|
||||||
"eslint-plugin-vue": "^8.1.1",
|
"pinia": "^2.0.0-alpha.18",
|
||||||
"pinia": "^2.0.6",
|
"prettier": "^2.3.0",
|
||||||
"prettier": "^2.5.1",
|
"quasar": "^2.0.0-beta.18",
|
||||||
"quasar": "^2.3.3",
|
"typescript": "^4.2.4"
|
||||||
"typescript": "^4.5.2"
|
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@flaschengeist/api": "^1.0.0-alpha.7",
|
"@flaschengeist/api": "^1.0.0-alpha.1",
|
||||||
"@flaschengeist/users": "^1.0.0-alpha.3"
|
"@flaschengeist/users": "^1.0.0-alpha.1"
|
||||||
},
|
},
|
||||||
"prettier": {
|
"prettier": {
|
||||||
"singleQuote": true,
|
"singleQuote": true,
|
||||||
"semi": true,
|
"semi": true,
|
||||||
"printWidth": 100,
|
"printWidth": 120,
|
||||||
"arrowParens": "always"
|
"arrowParens": "always"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ declare namespace FG {
|
||||||
volume?: number;
|
volume?: number;
|
||||||
cost_per_volume?: number;
|
cost_per_volume?: number;
|
||||||
cost_per_package?: number;
|
cost_per_package?: number;
|
||||||
has_image: boolean;
|
uuid: string;
|
||||||
receipt?: Array<string>;
|
receipt?: Array<string>;
|
||||||
tags?: Array<Tag>;
|
tags?: Array<Tag>;
|
||||||
type?: DrinkType;
|
type?: DrinkType;
|
||||||
|
@ -17,19 +17,15 @@ declare namespace FG {
|
||||||
id: number;
|
id: number;
|
||||||
volume: number;
|
volume: number;
|
||||||
ingredient_id: number;
|
ingredient_id: number;
|
||||||
cost_per_volume: number;
|
|
||||||
name: string;
|
|
||||||
}
|
}
|
||||||
interface DrinkPrice {
|
interface DrinkPrice {
|
||||||
id: number;
|
id: number;
|
||||||
price: number;
|
price: number;
|
||||||
volume?: DrinkPriceVolume;
|
|
||||||
public: boolean;
|
public: boolean;
|
||||||
description?: string;
|
description?: string;
|
||||||
}
|
}
|
||||||
interface DrinkPriceVolume {
|
interface DrinkPriceVolume {
|
||||||
id: number;
|
id: number;
|
||||||
drink?: Drink;
|
|
||||||
volume: number;
|
volume: number;
|
||||||
min_prices: Array<MinPrices>;
|
min_prices: Array<MinPrices>;
|
||||||
prices: Array<DrinkPrice>;
|
prices: Array<DrinkPrice>;
|
||||||
|
|
|
@ -5,8 +5,7 @@
|
||||||
<div v-if="ingredient.drink_ingredient">
|
<div v-if="ingredient.drink_ingredient">
|
||||||
<div class="full-width row q-gutter-sm q-py-sm">
|
<div class="full-width row q-gutter-sm q-py-sm">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<!--{{ name(ingredient.drink_ingredient?.ingredient_id) }}-->
|
{{ name(ingredient.drink_ingredient?.ingredient_id) }}
|
||||||
{{ ingredient.drink_ingredient?.name }}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
{{
|
{{
|
||||||
|
|
|
@ -5,20 +5,15 @@
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:rows="drinks"
|
:rows="drinks"
|
||||||
dense
|
dense
|
||||||
row-key="id"
|
|
||||||
grid
|
|
||||||
:loading="loading"
|
|
||||||
:filter="search"
|
:filter="search"
|
||||||
@request="onRequest"
|
|
||||||
>
|
|
||||||
<!--
|
|
||||||
:filter-method="filter"
|
:filter-method="filter"
|
||||||
-->
|
grid
|
||||||
|
:rows-per-page-options="[0]"
|
||||||
|
>
|
||||||
<template #top-right>
|
<template #top-right>
|
||||||
<div class="row justify-end q-gutter-sm">
|
<div class="row justify-end q-gutter-sm">
|
||||||
<search-input v-model="search" :keys="search_keys" />
|
<search-input v-model="search" :keys="search_keys" />
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
<q-toggle v-model="showPic" icon="mdi-camera-burst" />
|
|
||||||
<q-btn v-if="!public && !nodetails" label="Aufpreise">
|
<q-btn v-if="!public && !nodetails" label="Aufpreise">
|
||||||
<q-menu anchor="center middle" self="center middle">
|
<q-menu anchor="center middle" self="center middle">
|
||||||
<min-price-setting />
|
<min-price-setting />
|
||||||
|
@ -38,62 +33,7 @@
|
||||||
<template #item="props">
|
<template #item="props">
|
||||||
<div class="q-pa-xs col-xs-12 col-sm-6 col-md-4">
|
<div class="q-pa-xs col-xs-12 col-sm-6 col-md-4">
|
||||||
<q-card>
|
<q-card>
|
||||||
<q-img
|
<q-img style="max-height: 256px" :src="image(props.row.uuid)">
|
||||||
v-if="showPic && props.row.has_image"
|
|
||||||
style="max-height: 256px"
|
|
||||||
:src="image(props.row.id)"
|
|
||||||
fit="contain"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
v-if="!public && !nodetails && editable"
|
|
||||||
class="absolute-top-right justify-end"
|
|
||||||
style="background-color: transparent"
|
|
||||||
>
|
|
||||||
<q-btn
|
|
||||||
round
|
|
||||||
icon="mdi-pencil"
|
|
||||||
style="background-color: rgba(0, 0, 0, 0.5)"
|
|
||||||
@click="editDrink = props.row"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="absolute-bottom-right justify-end">
|
|
||||||
<div class="text-subtitle1 text-right">
|
|
||||||
{{ props.row.name }}
|
|
||||||
</div>
|
|
||||||
<div class="text-caption text-right">
|
|
||||||
{{ props.row.type.name }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<template #error>
|
|
||||||
<q-img class="bg-white" style="max-height: 256px" src="no-image.svg" />
|
|
||||||
<div
|
|
||||||
v-if="!public && !nodetails && editable"
|
|
||||||
class="absolute-top-right justify-end"
|
|
||||||
style="background-color: transparent"
|
|
||||||
>
|
|
||||||
<q-btn
|
|
||||||
round
|
|
||||||
icon="mdi-pencil"
|
|
||||||
style="background-color: rgba(0, 0, 0, 0.5)"
|
|
||||||
@click="editDrink = props.row"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="absolute-bottom-right justify-end">
|
|
||||||
<div class="text-subtitle1 text-right">
|
|
||||||
{{ props.row.name }}
|
|
||||||
</div>
|
|
||||||
<div class="text-caption text-right">
|
|
||||||
{{ props.row.type.name }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</q-img>
|
|
||||||
<q-img
|
|
||||||
v-if="showPic && !props.row.has_image"
|
|
||||||
class="bg-white"
|
|
||||||
style="max-height: 256px"
|
|
||||||
src="no-image.svg"
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
v-if="!public && !nodetails && editable"
|
v-if="!public && !nodetails && editable"
|
||||||
class="absolute-top-right justify-end"
|
class="absolute-top-right justify-end"
|
||||||
|
@ -115,19 +55,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</q-img>
|
</q-img>
|
||||||
<q-card-section v-if="!showPic">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col">
|
|
||||||
<div class="text-h4 text-center">
|
|
||||||
{{ props.row.name }}
|
|
||||||
</div>
|
|
||||||
<div class="text-caption text-center">
|
|
||||||
{{ props.row.type.name }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<q-btn rounded icon="mdi-pencil" @click="editDrink = props.row" />
|
|
||||||
</div>
|
|
||||||
</q-card-section>
|
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<q-badge
|
<q-badge
|
||||||
v-for="tag in props.row.tags"
|
v-for="tag in props.row.tags"
|
||||||
|
@ -223,8 +150,8 @@ import { filter, Search } from '../utils/filter';
|
||||||
import SearchInput from './SearchInput.vue';
|
import SearchInput from './SearchInput.vue';
|
||||||
import DrinkModify from './DrinkModify.vue';
|
import DrinkModify from './DrinkModify.vue';
|
||||||
import { DeleteObjects } from '../utils/utils';
|
import { DeleteObjects } from '../utils/utils';
|
||||||
import { setNewImage, getNewImage } from '../utils/image';
|
|
||||||
import { PERMISSIONS } from '../permissions';
|
import { PERMISSIONS } from '../permissions';
|
||||||
|
import { sort } from '../utils/sort';
|
||||||
import { Notify } from 'quasar';
|
import { Notify } from 'quasar';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
|
@ -253,11 +180,7 @@ export default defineComponent({
|
||||||
const store = usePricelistStore();
|
const store = usePricelistStore();
|
||||||
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
//void store.getDrinks();
|
void store.getDrinks();
|
||||||
void onRequest({
|
|
||||||
pagination: pagination.value,
|
|
||||||
filter: undefined,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
|
@ -269,6 +192,8 @@ export default defineComponent({
|
||||||
name: 'name',
|
name: 'name',
|
||||||
label: 'Name',
|
label: 'Name',
|
||||||
field: 'name',
|
field: 'name',
|
||||||
|
sortable: true,
|
||||||
|
sort,
|
||||||
filterable: true,
|
filterable: true,
|
||||||
public: true,
|
public: true,
|
||||||
},
|
},
|
||||||
|
@ -278,6 +203,8 @@ export default defineComponent({
|
||||||
label: 'Kategorie',
|
label: 'Kategorie',
|
||||||
field: 'type',
|
field: 'type',
|
||||||
format: (val: FG.DrinkType) => `${val.name}`,
|
format: (val: FG.DrinkType) => `${val.name}`,
|
||||||
|
sortable: true,
|
||||||
|
sort: (a: FG.DrinkType, b: FG.DrinkType) => sort(a.name, b.name),
|
||||||
filterable: true,
|
filterable: true,
|
||||||
public: true,
|
public: true,
|
||||||
},
|
},
|
||||||
|
@ -303,6 +230,7 @@ export default defineComponent({
|
||||||
label: 'Artikelnummer',
|
label: 'Artikelnummer',
|
||||||
field: 'article_id',
|
field: 'article_id',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
|
sort,
|
||||||
filterable: true,
|
filterable: true,
|
||||||
public: false,
|
public: false,
|
||||||
},
|
},
|
||||||
|
@ -311,6 +239,7 @@ export default defineComponent({
|
||||||
label: 'Inhalt in l des Gebinde',
|
label: 'Inhalt in l des Gebinde',
|
||||||
field: 'volume',
|
field: 'volume',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
|
sort,
|
||||||
public: false,
|
public: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -318,6 +247,7 @@ export default defineComponent({
|
||||||
label: 'Gebindegröße',
|
label: 'Gebindegröße',
|
||||||
field: 'package_size',
|
field: 'package_size',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
|
sort,
|
||||||
public: false,
|
public: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -326,6 +256,7 @@ export default defineComponent({
|
||||||
field: 'cost_per_package',
|
field: 'cost_per_package',
|
||||||
format: (val: number | null) => (val ? `${val.toFixed(3)}€` : ''),
|
format: (val: number | null) => (val ? `${val.toFixed(3)}€` : ''),
|
||||||
sortable: true,
|
sortable: true,
|
||||||
|
sort,
|
||||||
public: false,
|
public: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -334,6 +265,7 @@ export default defineComponent({
|
||||||
field: 'cost_per_volume',
|
field: 'cost_per_volume',
|
||||||
format: (val: number | null) => (val ? `${val.toFixed(3)}€` : ''),
|
format: (val: number | null) => (val ? `${val.toFixed(3)}€` : ''),
|
||||||
sortable: true,
|
sortable: true,
|
||||||
|
sort: (a: ComputedRef, b: ComputedRef) => sort(a.value, b.value),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'volumes',
|
name: 'volumes',
|
||||||
|
@ -365,7 +297,7 @@ export default defineComponent({
|
||||||
});
|
});
|
||||||
return retVal;
|
return retVal;
|
||||||
},
|
},
|
||||||
filterable: false,
|
filterable: true,
|
||||||
sortable: false,
|
sortable: false,
|
||||||
public: false,
|
public: false,
|
||||||
},
|
},
|
||||||
|
@ -415,47 +347,9 @@ export default defineComponent({
|
||||||
const pagination = ref({
|
const pagination = ref({
|
||||||
sortBy: 'name',
|
sortBy: 'name',
|
||||||
descending: false,
|
descending: false,
|
||||||
page: 1,
|
rowsPerPage: store.drinks.length,
|
||||||
rowsPerPage: 10,
|
|
||||||
rowsNumber: 10,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
interface PaginationInterface {
|
|
||||||
sortBy: string;
|
|
||||||
descending: boolean;
|
|
||||||
page: number;
|
|
||||||
rowsPerPage: number;
|
|
||||||
rowsNumber: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
const loading = ref(false);
|
|
||||||
|
|
||||||
async function onRequest(props: { pagination: PaginationInterface; filter?: Search }) {
|
|
||||||
const { page, rowsPerPage, sortBy, descending } = props.pagination;
|
|
||||||
loading.value = true;
|
|
||||||
console.log('search_keys', search_keys);
|
|
||||||
const fetchCount = rowsPerPage === 0 ? pagination.value.rowsNumber : rowsPerPage;
|
|
||||||
const startRow = (page - 1) * rowsPerPage;
|
|
||||||
try {
|
|
||||||
const result = await store.getDrinks({
|
|
||||||
offset: startRow,
|
|
||||||
limit: fetchCount,
|
|
||||||
descending,
|
|
||||||
search_name: props.filter?.value,
|
|
||||||
search_key: props.filter?.key,
|
|
||||||
});
|
|
||||||
pagination.value.page = page;
|
|
||||||
pagination.value.rowsPerPage = rowsPerPage;
|
|
||||||
pagination.value.sortBy = sortBy;
|
|
||||||
pagination.value.descending = descending;
|
|
||||||
console.log('result', result.count);
|
|
||||||
if (result.count) pagination.value.rowsNumber = result.count;
|
|
||||||
} catch (error) {
|
|
||||||
console.warn(error);
|
|
||||||
}
|
|
||||||
loading.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const drinkTypes = computed(() => store.drinkTypes);
|
const drinkTypes = computed(() => store.drinkTypes);
|
||||||
|
|
||||||
function updateDrink(drink: Drink) {
|
function updateDrink(drink: Drink) {
|
||||||
|
@ -467,7 +361,6 @@ export default defineComponent({
|
||||||
store.deleteDrink(editDrink.value);
|
store.deleteDrink(editDrink.value);
|
||||||
}
|
}
|
||||||
editDrink.value = undefined;
|
editDrink.value = undefined;
|
||||||
void onRequest({ pagination: pagination.value, filter: search.value });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const showNewDrink = ref(false);
|
const showNewDrink = ref(false);
|
||||||
|
@ -519,7 +412,7 @@ export default defineComponent({
|
||||||
tags: [],
|
tags: [],
|
||||||
type: undefined,
|
type: undefined,
|
||||||
volumes: [],
|
volumes: [],
|
||||||
has_image: false,
|
uuid: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
function newDrink() {
|
function newDrink() {
|
||||||
|
@ -544,9 +437,6 @@ export default defineComponent({
|
||||||
for (const volume of toDeleteObjects.volumes) {
|
for (const volume of toDeleteObjects.volumes) {
|
||||||
await store.deleteVolume(volume, drink);
|
await store.deleteVolume(volume, drink);
|
||||||
}
|
}
|
||||||
if (deletePic) {
|
|
||||||
await deletePicture();
|
|
||||||
}
|
|
||||||
if (drink.id > 0) {
|
if (drink.id > 0) {
|
||||||
await store.updateDrink(drink);
|
await store.updateDrink(drink);
|
||||||
} else {
|
} else {
|
||||||
|
@ -555,15 +445,14 @@ export default defineComponent({
|
||||||
editDrink.value.id = _drink.id;
|
editDrink.value.id = _drink.id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (drinkPic instanceof File && drinkPic.name) {
|
if (deletePic) {
|
||||||
|
await deletePicture();
|
||||||
|
}
|
||||||
|
if (drinkPic instanceof File) {
|
||||||
await savePicture(drinkPic);
|
await savePicture(drinkPic);
|
||||||
if (drink.id > 0) {
|
|
||||||
setNewImage(drink.id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
editDrink.value = undefined;
|
editDrink.value = undefined;
|
||||||
notLoading.value = true;
|
notLoading.value = true;
|
||||||
void onRequest({ pagination: pagination.value, filter: search.value });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_volumes(drink_id: number) {
|
function get_volumes(drink_id: number) {
|
||||||
|
@ -572,21 +461,22 @@ export default defineComponent({
|
||||||
|
|
||||||
const notLoading = ref(true);
|
const notLoading = ref(true);
|
||||||
|
|
||||||
function image(id: number | undefined) {
|
const imageloading = ref<Array<{ id: number; loading: boolean }>>([]);
|
||||||
if (id) {
|
function getImageLoading(id: number) {
|
||||||
const _newImage = getNewImage(id);
|
const loading = imageloading.value.find((a) => a.id === id);
|
||||||
if (_newImage) {
|
if (loading) {
|
||||||
return `${
|
return loading.loading;
|
||||||
api.defaults.baseURL || ''
|
}
|
||||||
}/pricelist/drinks/${id}/picture?thumbnail?t=${_newImage.lastModified.toString()}`;
|
return false;
|
||||||
}
|
}
|
||||||
return `${api.defaults.baseURL || ''}/pricelist/drinks/${id}/picture?thumbnail`;
|
|
||||||
|
function image(uuid: string | undefined) {
|
||||||
|
if (uuid) {
|
||||||
|
return `${api.defaults.baseURL||''}/pricelist/picture/${uuid}?size=256`;
|
||||||
}
|
}
|
||||||
return 'no-image.svg';
|
return 'no-image.svg';
|
||||||
}
|
}
|
||||||
|
|
||||||
const showPic = ref(true);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
drinks: computed(() => store.drinks),
|
drinks: computed(() => store.drinks),
|
||||||
pagination,
|
pagination,
|
||||||
|
@ -608,13 +498,11 @@ export default defineComponent({
|
||||||
editing_drink,
|
editing_drink,
|
||||||
get_volumes,
|
get_volumes,
|
||||||
notLoading,
|
notLoading,
|
||||||
|
getImageLoading,
|
||||||
newDrink,
|
newDrink,
|
||||||
hasPermission,
|
hasPermission,
|
||||||
PERMISSIONS,
|
PERMISSIONS,
|
||||||
image,
|
image,
|
||||||
loading,
|
|
||||||
onRequest,
|
|
||||||
showPic,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="q-pa-sm">
|
<div class="q-pa-sm">
|
||||||
<div v-for="(price, index) in filterPublic(volume.prices)" :key="price.id">
|
<div v-for="(price, index) in volume.prices" :key="price.id">
|
||||||
<div class="fit row justify-around q-py-sm">
|
<div class="fit row justify-around q-py-sm">
|
||||||
<div
|
<div
|
||||||
v-if="!editable || !hasPermission(PERMISSIONS.EDIT_PRICE)"
|
v-if="!editable || !hasPermission(PERMISSIONS.EDIT_PRICE)"
|
||||||
|
@ -93,7 +93,7 @@
|
||||||
</q-btn>
|
</q-btn>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<q-separator v-if="index < filterPublic(volume.prices).length - 1" />
|
<q-separator v-if="index < volume.prices.length - 1" />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="!public && !nodetails && isUnderMinPrice"
|
v-if="!public && !nodetails && isUnderMinPrice"
|
||||||
|
@ -294,13 +294,6 @@ export default defineComponent({
|
||||||
emit('update:modelValue', volumes.value);
|
emit('update:modelValue', volumes.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterPublic(prices: Array<FG.DrinkPrice>) {
|
|
||||||
if (props.public) {
|
|
||||||
return prices.filter((price) => price.public);
|
|
||||||
}
|
|
||||||
return prices;
|
|
||||||
}
|
|
||||||
|
|
||||||
const isUnderMinPrice = computed(() => {
|
const isUnderMinPrice = computed(() => {
|
||||||
if (volumes.value) {
|
if (volumes.value) {
|
||||||
const this_volume = volumes.value.find((a) => a.id === volume.value);
|
const this_volume = volumes.value.find((a) => a.id === volume.value);
|
||||||
|
@ -335,7 +328,6 @@ export default defineComponent({
|
||||||
isUnderMinPrice,
|
isUnderMinPrice,
|
||||||
hasPermission,
|
hasPermission,
|
||||||
PERMISSIONS,
|
PERMISSIONS,
|
||||||
filterPublic,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,8 +9,7 @@
|
||||||
<div v-if="ingredient.drink_ingredient" class="col">
|
<div v-if="ingredient.drink_ingredient" class="col">
|
||||||
<div class="full-width row justify-evenly q-py-xs">
|
<div class="full-width row justify-evenly q-py-xs">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<!--{{ get_drink_ingredient_name(ingredient.drink_ingredient.ingredient_id) }}-->
|
{{ get_drink_ingredient_name(ingredient.drink_ingredient.ingredient_id) }}
|
||||||
{{ ingredient.drink_ingredient.name }}
|
|
||||||
<q-popup-edit
|
<q-popup-edit
|
||||||
v-if="editable"
|
v-if="editable"
|
||||||
v-slot="scope"
|
v-slot="scope"
|
||||||
|
@ -26,8 +25,6 @@
|
||||||
label="Getränk"
|
label="Getränk"
|
||||||
filled
|
filled
|
||||||
dense
|
dense
|
||||||
use-input
|
|
||||||
@filter="filter_drinks"
|
|
||||||
:options="drinks"
|
:options="drinks"
|
||||||
option-label="name"
|
option-label="name"
|
||||||
option-value="id"
|
option-value="id"
|
||||||
|
@ -81,8 +78,6 @@
|
||||||
v-model="ingredient.extra_ingredient"
|
v-model="ingredient.extra_ingredient"
|
||||||
filled
|
filled
|
||||||
dense
|
dense
|
||||||
use-input
|
|
||||||
@filter="filter_extra_ingredients"
|
|
||||||
:options="extra_ingredients"
|
:options="extra_ingredients"
|
||||||
option-label="name"
|
option-label="name"
|
||||||
/>
|
/>
|
||||||
|
@ -112,10 +107,8 @@
|
||||||
v-model="newIngredient"
|
v-model="newIngredient"
|
||||||
filled
|
filled
|
||||||
dense
|
dense
|
||||||
use-input
|
|
||||||
label="Zutat"
|
label="Zutat"
|
||||||
:options="[...drinks, ...extra_ingredients]"
|
:options="[...drinks, ...extra_ingredients]"
|
||||||
@filter="filter"
|
|
||||||
option-label="name"
|
option-label="name"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -162,7 +155,7 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { computed, defineComponent, PropType, ref, onBeforeMount, unref } from 'vue';
|
import { computed, defineComponent, PropType, ref, onBeforeMount, unref } from 'vue';
|
||||||
import { usePricelistStore, Drink } from '../../store';
|
import { usePricelistStore } from '../../store';
|
||||||
import { clone } from '../../utils/utils';
|
import { clone } from '../../utils/utils';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
|
@ -203,8 +196,6 @@ export default defineComponent({
|
||||||
id: -1,
|
id: -1,
|
||||||
ingredient_id: newIngredient.value.id,
|
ingredient_id: newIngredient.value.id,
|
||||||
volume: newIngredientVolume.value,
|
volume: newIngredientVolume.value,
|
||||||
cost_per_volume: <number>(<FG.Drink>newIngredient.value).cost_per_volume,
|
|
||||||
name: newIngredient.value.name,
|
|
||||||
},
|
},
|
||||||
extra_ingredient: undefined,
|
extra_ingredient: undefined,
|
||||||
};
|
};
|
||||||
|
@ -243,44 +234,13 @@ export default defineComponent({
|
||||||
emit('update:modelValue', unref(edit_ingredients));
|
emit('update:modelValue', unref(edit_ingredients));
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
const drinks = ref<Array<Drink>>([]);
|
const drinks = computed(() =>
|
||||||
const _extra_ingredients = computed(() => store.extraIngredients);
|
store.drinks.filter((drink) => {
|
||||||
const extra_ingredients = ref(_extra_ingredients.value);
|
console.log('computed drinks', drink.name, drink.cost_per_volume);
|
||||||
|
return drink.cost_per_volume;
|
||||||
async function filter_drinks(val: string, update: (a: () => void) => void) {
|
})
|
||||||
let result = <Array<Drink>>[];
|
);
|
||||||
if (val === '') {
|
const extra_ingredients = computed(() => store.extraIngredients);
|
||||||
result = await store.getDrinks_no_store({ limit: 5, ingredient: true });
|
|
||||||
} else {
|
|
||||||
result = await store.getDrinks_no_store({
|
|
||||||
limit: 5,
|
|
||||||
search_name: val,
|
|
||||||
search_key: 'name',
|
|
||||||
ingredient: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
update(() => {
|
|
||||||
drinks.value = result;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function filter_extra_ingredients(val: string, update: (a: () => void) => void) {
|
|
||||||
if (val === '') {
|
|
||||||
update(() => {
|
|
||||||
extra_ingredients.value = _extra_ingredients.value;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
update(() => {
|
|
||||||
extra_ingredients.value = _extra_ingredients.value.filter((ingredient) => {
|
|
||||||
return ingredient.name.toLowerCase().includes(val.toLowerCase());
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function filter(val: string, update: () => void) {
|
|
||||||
await filter_drinks(val, update);
|
|
||||||
filter_extra_ingredients(val, update);
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_drink_ingredient_name(id: number) {
|
function get_drink_ingredient_name(id: number) {
|
||||||
return store.drinks.find((a) => a.id === id)?.name;
|
return store.drinks.find((a) => a.id === id)?.name;
|
||||||
|
@ -303,9 +263,6 @@ export default defineComponent({
|
||||||
deleteIngredient,
|
deleteIngredient,
|
||||||
get_drink_ingredient_name,
|
get_drink_ingredient_name,
|
||||||
edit_ingredients,
|
edit_ingredients,
|
||||||
filter,
|
|
||||||
filter_drinks,
|
|
||||||
filter_extra_ingredients,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -24,28 +24,26 @@
|
||||||
</div>
|
</div>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
|
<q-img :src="image" style="max-height: 256px" fit="contain" />
|
||||||
<div class="full-width row">
|
<div class="full-width row">
|
||||||
<div class="col-10 q-pa-sm">
|
<div class="col-10 q-pa-sm">
|
||||||
<q-file
|
<q-file
|
||||||
v-model="drinkPic"
|
v-model="drinkPic"
|
||||||
filled
|
filled
|
||||||
:clearable="drinkPic.name != ''"
|
clearable
|
||||||
dense
|
dense
|
||||||
accept=".jpg, .jpeg, .png, image/*"
|
|
||||||
@update:model-value="imagePreview"
|
@update:model-value="imagePreview"
|
||||||
@clear="clear"
|
@clear="imgsrc = undefined"
|
||||||
>
|
>
|
||||||
<template #file>
|
<template #prepend>
|
||||||
<q-img :src="image" style="max-height: 256px" fit="contain" />
|
<q-icon name="mdi-image" />
|
||||||
</template>
|
</template>
|
||||||
</q-file>
|
</q-file>
|
||||||
</div>
|
</div>
|
||||||
<div class="column justify-center">
|
<div class="col-2 q-pa-sm text-right">
|
||||||
<div class="col-2 q-pa-sm">
|
<q-btn round icon="mdi-delete" color="negative" size="sm" @click="delete_pic">
|
||||||
<q-btn round icon="mdi-delete" color="negative" size="sm" @click="delete_pic">
|
<q-tooltip> Bild entfernen </q-tooltip>
|
||||||
<q-tooltip> Bild entfernen </q-tooltip>
|
</q-btn>
|
||||||
</q-btn>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
|
@ -140,15 +138,13 @@
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-actions class="justify-around">
|
<q-card-actions class="justify-around">
|
||||||
<q-btn label="Abbrechen" @click="cancel" />
|
<q-btn label="Abbrechen" @click="cancel" />
|
||||||
<!--<q-btn v-if="can_delete" label="Löschen" color="negative" @click="delete_drink" />-->
|
<q-btn v-if="can_delete" label="Löschen" color="negative" @click="delete_drink" />
|
||||||
<q-btn label="Löschen" color="negative" @click="delete_drink" />
|
|
||||||
<q-btn label="Speichern" color="primary" @click="save" />
|
<q-btn label="Speichern" color="primary" @click="save" />
|
||||||
</q-card-actions>
|
</q-card-actions>
|
||||||
</q-card>
|
</q-card>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { clone, calc_min_prices, DeleteObjects, calc_cost_per_volume } from '../utils/utils';
|
import { clone, calc_min_prices, DeleteObjects, calc_cost_per_volume } from '../utils/utils';
|
||||||
import { getNewImage } from '../utils/image';
|
|
||||||
import { defineComponent, PropType, ref, onBeforeMount, computed } from 'vue';
|
import { defineComponent, PropType, ref, onBeforeMount, computed } from 'vue';
|
||||||
import DrinkPriceVolumes from './CalculationTable/DrinkPriceVolumes.vue';
|
import DrinkPriceVolumes from './CalculationTable/DrinkPriceVolumes.vue';
|
||||||
import BuildManual from '../components/CalculationTable/BuildManual.vue';
|
import BuildManual from '../components/CalculationTable/BuildManual.vue';
|
||||||
|
@ -178,6 +174,7 @@ export default defineComponent({
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
//edit_drink.value = <Drink>JSON.parse(JSON.stringify(props.drink));
|
//edit_drink.value = <Drink>JSON.parse(JSON.stringify(props.drink));
|
||||||
|
edit_drink.value = clone(props.drink);
|
||||||
edit_volumes.value = clone(props.drink.volumes);
|
edit_volumes.value = clone(props.drink.volumes);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -191,12 +188,10 @@ export default defineComponent({
|
||||||
ingredients: [],
|
ingredients: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
const edit_drink = ref<Drink>(clone(props.drink));
|
const edit_drink = ref<Drink>();
|
||||||
const edit_volumes = ref<Array<DrinkPriceVolume>>([]);
|
const edit_volumes = ref<Array<DrinkPriceVolume>>([]);
|
||||||
function save() {
|
function save() {
|
||||||
(<Drink>edit_drink.value).volumes = edit_volumes.value;
|
(<Drink>edit_drink.value).volumes = edit_volumes.value;
|
||||||
edit_drink.value.cost_per_volume = calc_cost_per_volume(edit_drink.value);
|
|
||||||
edit_drink.value._cost_per_volume = edit_drink.value.cost_per_volume;
|
|
||||||
emit('save', <Drink>edit_drink.value, toDeleteObjects.value, drinkPic.value, deletePic.value);
|
emit('save', <Drink>edit_drink.value, toDeleteObjects.value, drinkPic.value, deletePic.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,7 +238,7 @@ export default defineComponent({
|
||||||
edit_drink.value?.receipt?.splice(event, 1);
|
edit_drink.value?.receipt?.splice(event, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const drinkPic = ref<File>(new File([], '', {}));
|
const drinkPic = ref();
|
||||||
const imgsrc = ref();
|
const imgsrc = ref();
|
||||||
|
|
||||||
const deletePic = ref(false);
|
const deletePic = ref(false);
|
||||||
|
@ -251,9 +246,9 @@ export default defineComponent({
|
||||||
function delete_pic() {
|
function delete_pic() {
|
||||||
deletePic.value = true;
|
deletePic.value = true;
|
||||||
imgsrc.value = undefined;
|
imgsrc.value = undefined;
|
||||||
drinkPic.value = new File([], '', {});
|
drinkPic.value = undefined;
|
||||||
if (edit_drink.value) {
|
if (edit_drink.value) {
|
||||||
edit_drink.value.has_image = false;
|
edit_drink.value.uuid = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,23 +265,14 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
|
|
||||||
const image = computed(() => {
|
const image = computed(() => {
|
||||||
console.log(imgsrc.value, deletePic.value, edit_drink.value);
|
if (deletePic.value) {
|
||||||
|
return 'no-image.svg';
|
||||||
|
}
|
||||||
if (imgsrc.value) {
|
if (imgsrc.value) {
|
||||||
return <string>imgsrc.value;
|
return <string>imgsrc.value;
|
||||||
}
|
}
|
||||||
if (deletePic.value && !imgsrc.value) {
|
if (edit_drink.value?.uuid) {
|
||||||
return 'no-image.svg';
|
return `${api.defaults.baseURL||''}/pricelist/picture/${edit_drink.value.uuid}?size=256`;
|
||||||
}
|
|
||||||
if (edit_drink.value?.has_image) {
|
|
||||||
const _image = getNewImage(edit_drink.value?.id);
|
|
||||||
if (_image) {
|
|
||||||
return `${api.defaults.baseURL || ''}/pricelist/drinks/${
|
|
||||||
edit_drink.value.id
|
|
||||||
}/picture?thumbnail?t=${_image.lastModified.toString()}`;
|
|
||||||
}
|
|
||||||
return `${api.defaults.baseURL || ''}/pricelist/drinks/${
|
|
||||||
edit_drink.value.id
|
|
||||||
}/picture?thumbnail`;
|
|
||||||
}
|
}
|
||||||
return 'no-image.svg';
|
return 'no-image.svg';
|
||||||
});
|
});
|
||||||
|
@ -335,11 +321,6 @@ export default defineComponent({
|
||||||
edit_volumes.value?.some((a) => a.ingredients.length > 0)
|
edit_volumes.value?.some((a) => a.ingredients.length > 0)
|
||||||
);
|
);
|
||||||
|
|
||||||
function clear(val: File) {
|
|
||||||
drinkPic.value = new File([], '', {});
|
|
||||||
imgsrc.value = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
edit_drink,
|
edit_drink,
|
||||||
save,
|
save,
|
||||||
|
@ -366,7 +347,6 @@ export default defineComponent({
|
||||||
hasIngredients,
|
hasIngredients,
|
||||||
hasPermission,
|
hasPermission,
|
||||||
PERMISSIONS,
|
PERMISSIONS,
|
||||||
clear,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,13 +5,11 @@
|
||||||
:rows="drinks"
|
:rows="drinks"
|
||||||
:visible-columns="visibleColumns"
|
:visible-columns="visibleColumns"
|
||||||
:filter="search"
|
:filter="search"
|
||||||
|
:filter-method="filter"
|
||||||
dense
|
dense
|
||||||
v-model:pagination="pagination"
|
:pagination="pagination"
|
||||||
:fullscreen="fullscreen"
|
:fullscreen="fullscreen"
|
||||||
@request="onRequest"
|
|
||||||
>
|
>
|
||||||
<!--
|
|
||||||
:filter-method="filter"-->
|
|
||||||
<template #top-right>
|
<template #top-right>
|
||||||
<div class="row justify-end q-gutter-sm">
|
<div class="row justify-end q-gutter-sm">
|
||||||
<search-input v-model="search" :keys="options" />
|
<search-input v-model="search" :keys="options" />
|
||||||
|
@ -29,7 +27,7 @@
|
||||||
options-cover
|
options-cover
|
||||||
/>
|
/>
|
||||||
<q-btn round icon="mdi-backburger">
|
<q-btn round icon="mdi-backburger">
|
||||||
<q-tooltip anchor="top middle" self="bottom middle"> Reihenfolge ändern </q-tooltip>
|
<q-tooltip anchor='top middle' self='bottom middle'> Reihenfolge ändern </q-tooltip>
|
||||||
<q-menu anchor="bottom middle" self="top middle">
|
<q-menu anchor="bottom middle" self="top middle">
|
||||||
<drag v-model="order" class="q-list" ghost-class="ghost" group="people" item-key="id">
|
<drag v-model="order" class="q-list" ghost-class="ghost" group="people" item-key="id">
|
||||||
<template #item="{ element }">
|
<template #item="{ element }">
|
||||||
|
@ -82,7 +80,7 @@ import SearchInput from '../components/SearchInput.vue';
|
||||||
import { usePricelistStore, Order } from '../store';
|
import { usePricelistStore, Order } from '../store';
|
||||||
import { useMainStore } from '@flaschengeist/api';
|
import { useMainStore } from '@flaschengeist/api';
|
||||||
import { Search, filter } from '../utils/filter';
|
import { Search, filter } from '../utils/filter';
|
||||||
import draggableComponent from 'vuedraggable';
|
import drag from 'vuedraggable';
|
||||||
|
|
||||||
interface Row {
|
interface Row {
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -96,7 +94,7 @@ interface Row {
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'Pricelist',
|
name: 'Pricelist',
|
||||||
components: { SearchInput, drag: draggableComponent },
|
components: { SearchInput, drag: <ComponentPublicInstance>drag },
|
||||||
props: {
|
props: {
|
||||||
public: {
|
public: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
|
@ -111,11 +109,11 @@ export default defineComponent({
|
||||||
if (!props.public) {
|
if (!props.public) {
|
||||||
user.value = useMainStore().currentUser.userid;
|
user.value = useMainStore().currentUser.userid;
|
||||||
void store.getPriceListColumnOrder(user.value);
|
void store.getPriceListColumnOrder(user.value);
|
||||||
|
void store.getDrinks();
|
||||||
void store.getPriceCalcColumn(user.value);
|
void store.getPriceCalcColumn(user.value);
|
||||||
} else {
|
} else {
|
||||||
user.value = '';
|
user.value = '';
|
||||||
}
|
}
|
||||||
void onRequest({ pagination: pagination.value });
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const _order = ref<Array<Order>>([
|
const _order = ref<Array<Order>>([
|
||||||
|
@ -172,9 +170,7 @@ export default defineComponent({
|
||||||
{
|
{
|
||||||
name: 'name',
|
name: 'name',
|
||||||
label: 'Name',
|
label: 'Name',
|
||||||
//field: 'name',
|
field: 'name',
|
||||||
field: 'volume',
|
|
||||||
format: (val: FG.DrinkPriceVolume) => <string>val.drink?.name,
|
|
||||||
sortable: true,
|
sortable: true,
|
||||||
filterable: true,
|
filterable: true,
|
||||||
align: 'left',
|
align: 'left',
|
||||||
|
@ -182,23 +178,21 @@ export default defineComponent({
|
||||||
{
|
{
|
||||||
name: 'type',
|
name: 'type',
|
||||||
label: 'Kategorie',
|
label: 'Kategorie',
|
||||||
//field: 'type',
|
field: 'type',
|
||||||
field: 'volume',
|
|
||||||
sortable: true,
|
sortable: true,
|
||||||
filterable: true,
|
filterable: true,
|
||||||
format: (val: FG.DrinkPriceVolume) => <string>val.drink?.type?.name,
|
format: (val: FG.DrinkType) => val.name,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'tags',
|
name: 'tags',
|
||||||
label: 'Tags',
|
label: 'Tags',
|
||||||
//field: 'tags',
|
field: 'tags',
|
||||||
field: 'volume',
|
|
||||||
filterable: true,
|
filterable: true,
|
||||||
|
|
||||||
format: (val: FG.DrinkPriceVolume) => {
|
format: (val: Array<FG.Tag>) => {
|
||||||
let retVal = '';
|
let retVal = '';
|
||||||
val.drink?.tags?.forEach((tag, index) => {
|
val.forEach((tag, index) => {
|
||||||
if (index >= (<Array<FG.Tag>>val.drink?.tags).length - 1 && index > 0) {
|
if (index >= val.length - 1 && index > 0) {
|
||||||
retVal += ', ';
|
retVal += ', ';
|
||||||
}
|
}
|
||||||
retVal += tag.name;
|
retVal += tag.name;
|
||||||
|
@ -209,11 +203,10 @@ export default defineComponent({
|
||||||
{
|
{
|
||||||
name: 'volume',
|
name: 'volume',
|
||||||
label: 'Inhalt',
|
label: 'Inhalt',
|
||||||
//field: 'volume',
|
|
||||||
field: 'volume',
|
field: 'volume',
|
||||||
filterable: true,
|
filterable: true,
|
||||||
sortable: true,
|
sortable: true,
|
||||||
format: (val: FG.DrinkPriceVolume) => `${val.volume.toFixed(3)}L`,
|
format: (val: number) => `${val.toFixed(3)}L`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'price',
|
name: 'price',
|
||||||
|
@ -304,48 +297,9 @@ export default defineComponent({
|
||||||
label: '',
|
label: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
interface PaginationInterface {
|
|
||||||
sortBy: string;
|
|
||||||
descending: boolean;
|
|
||||||
page: number;
|
|
||||||
rowsPerPage: number;
|
|
||||||
rowsNumber: number;
|
|
||||||
}
|
|
||||||
async function onRequest(props: { pagination: PaginationInterface; filter?: Search }) {
|
|
||||||
const { page, rowsPerPage, sortBy, descending } = props.pagination;
|
|
||||||
loading.value = true;
|
|
||||||
//console.log('search_keys', search_keys);
|
|
||||||
const fetchCount = rowsPerPage === 0 ? pagination.value.rowsNumber : rowsPerPage;
|
|
||||||
const startRow = (page - 1) * rowsPerPage;
|
|
||||||
console.log('descending', descending);
|
|
||||||
try {
|
|
||||||
const result = await store.getPricelist({
|
|
||||||
offset: startRow,
|
|
||||||
limit: fetchCount,
|
|
||||||
descending: descending ? true : undefined,
|
|
||||||
search_name: props.filter?.value,
|
|
||||||
search_key: props.filter?.key,
|
|
||||||
sortBy: sortBy,
|
|
||||||
});
|
|
||||||
pagination.value.page = page;
|
|
||||||
pagination.value.rowsPerPage = rowsPerPage;
|
|
||||||
pagination.value.sortBy = sortBy;
|
|
||||||
pagination.value.descending = descending;
|
|
||||||
console.log('result', result);
|
|
||||||
if (result) pagination.value.rowsNumber = result;
|
|
||||||
} catch (error) {
|
|
||||||
console.warn(error);
|
|
||||||
}
|
|
||||||
loading.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const loading = ref(false);
|
|
||||||
const pagination = ref({
|
const pagination = ref({
|
||||||
sortBy: 'name',
|
sortBy: 'name',
|
||||||
rowsPerPage: 10,
|
rowsPerPage: 10,
|
||||||
rowsNumber: 10,
|
|
||||||
descending: false,
|
|
||||||
page: 1,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const fullscreen = ref(false);
|
const fullscreen = ref(false);
|
||||||
|
@ -360,8 +314,6 @@ export default defineComponent({
|
||||||
filter,
|
filter,
|
||||||
pagination,
|
pagination,
|
||||||
fullscreen,
|
fullscreen,
|
||||||
loading,
|
|
||||||
onRequest,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
import { innerRoutes, outerRoutes } from './routes';
|
import { innerRoutes, outerRoutes } from './routes';
|
||||||
import { FG_Plugin } from '@flaschengeist/types';
|
import { FG_Plugin } from '@flaschengeist/typings';
|
||||||
|
|
||||||
const plugin: FG_Plugin.Plugin = {
|
const plugin: FG_Plugin.Plugin = {
|
||||||
id: 'pricelist',
|
id: 'pricelist',
|
||||||
name: 'Pricelist',
|
name: 'Pricelist',
|
||||||
innerRoutes,
|
innerRoutes,
|
||||||
outerRoutes,
|
outerRoutes,
|
||||||
requiredModules: [['pricelist']],
|
requiredModules: [],
|
||||||
|
requiredBackendModules: ['pricelist'],
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
widgets: [],
|
widgets: [],
|
||||||
};
|
};
|
||||||
|
|
|
@ -39,7 +39,7 @@ export default defineComponent({
|
||||||
void store.get_min_prices().finally(() => {
|
void store.get_min_prices().finally(() => {
|
||||||
volume.value.min_prices = calc_min_prices(volume.value, undefined, store.min_prices);
|
volume.value.min_prices = calc_min_prices(volume.value, undefined, store.min_prices);
|
||||||
});
|
});
|
||||||
void store.getDrinks({ limit: 10 });
|
void store.getDrinks();
|
||||||
void store.getDrinkTypes();
|
void store.getDrinkTypes();
|
||||||
void store.getExtraIngredients();
|
void store.getExtraIngredients();
|
||||||
});
|
});
|
||||||
|
|
|
@ -25,7 +25,7 @@ export default defineComponent({
|
||||||
const mainStore = useMainStore();
|
const mainStore = useMainStore();
|
||||||
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
void store.getDrinks({ limit: 10 });
|
void store.getDrinks();
|
||||||
void store.getPriceListView(mainStore.currentUser.userid);
|
void store.getPriceListView(mainStore.currentUser.userid);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,14 @@
|
||||||
<template>
|
<template>
|
||||||
<q-table
|
<q-table
|
||||||
v-model:pagination="pagination"
|
|
||||||
grid
|
grid
|
||||||
title="Rezepte"
|
title="Rezepte"
|
||||||
:rows="drinks"
|
:rows="drinks"
|
||||||
row-key="id"
|
row-key="id"
|
||||||
hide-header
|
hide-header
|
||||||
@request="onRequest"
|
|
||||||
:columns="options"
|
|
||||||
:filter="search"
|
:filter="search"
|
||||||
|
:filter-method="filter"
|
||||||
|
:columns="options"
|
||||||
>
|
>
|
||||||
<!--:filter="search"
|
|
||||||
:filter-method="filter"-->
|
|
||||||
<template #top-right>
|
<template #top-right>
|
||||||
<search-input v-model="search" :keys="search_keys" />
|
<search-input v-model="search" :keys="search_keys" />
|
||||||
</template>
|
</template>
|
||||||
|
@ -21,7 +18,7 @@
|
||||||
<q-img
|
<q-img
|
||||||
style="max-height: 256px"
|
style="max-height: 256px"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
:src="image(props.row.id)"
|
:src="image(props.row.uuid)"
|
||||||
placeholder-src="no-image.svg"
|
placeholder-src="no-image.svg"
|
||||||
>
|
>
|
||||||
<div class="absolute-bottom-right justify-end">
|
<div class="absolute-bottom-right justify-end">
|
||||||
|
@ -71,16 +68,12 @@ export default defineComponent({
|
||||||
setup() {
|
setup() {
|
||||||
const store = usePricelistStore();
|
const store = usePricelistStore();
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
void onRequest({
|
void store.getDrinks();
|
||||||
pagination: pagination.value,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
const drinks = computed(
|
const drinks = computed(() =>
|
||||||
() =>
|
store.drinks.filter((drink) => {
|
||||||
//store.drinks.filter((drink) => {
|
return drink.volumes.some((volume) => volume.ingredients.length > 0);
|
||||||
// return drink.volumes.some((volume) => volume.ingredients.length > 0);
|
})
|
||||||
//})
|
|
||||||
store.drinks
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const columns_drinks = [
|
const columns_drinks = [
|
||||||
|
@ -88,7 +81,6 @@ export default defineComponent({
|
||||||
name: 'picture',
|
name: 'picture',
|
||||||
label: 'Bild',
|
label: 'Bild',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
filterable: false,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'name',
|
name: 'name',
|
||||||
|
@ -128,7 +120,6 @@ export default defineComponent({
|
||||||
label: 'Preise',
|
label: 'Preise',
|
||||||
field: 'volumes',
|
field: 'volumes',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
filterable: false,
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const columns_volumes = [
|
const columns_volumes = [
|
||||||
|
@ -164,53 +155,12 @@ export default defineComponent({
|
||||||
|
|
||||||
const search = ref<Search>({ value: '', key: '', label: '' });
|
const search = ref<Search>({ value: '', key: '', label: '' });
|
||||||
const search_keys = computed(() => columns_drinks.filter((column) => column.filterable));
|
const search_keys = computed(() => columns_drinks.filter((column) => column.filterable));
|
||||||
function image(id: number) {
|
function image(uuid: string | undefined) {
|
||||||
if (id) {
|
if (uuid) {
|
||||||
return `${api.defaults.baseURL || ''}/pricelist/drinks/${id}/picture?thumbnail`;
|
return `${api.defaults.baseURL||''}/pricelist/picture/${uuid}?size=256`;
|
||||||
}
|
}
|
||||||
return 'no-image.svg';
|
return 'no-image.svg';
|
||||||
}
|
}
|
||||||
const loading = ref(false);
|
|
||||||
const pagination = ref({
|
|
||||||
sortBy: 'name',
|
|
||||||
descending: false,
|
|
||||||
page: 1,
|
|
||||||
rowsPerPage: 10,
|
|
||||||
rowsNumber: 10,
|
|
||||||
});
|
|
||||||
|
|
||||||
async function onRequest(props: { pagination: PaginationInterface; filter?: Search }) {
|
|
||||||
const { page, rowsPerPage, sortBy, descending } = props.pagination;
|
|
||||||
loading.value = true;
|
|
||||||
console.log('search_keys', search_keys);
|
|
||||||
const fetchCount = rowsPerPage === 0 ? pagination.value.rowsNumber : rowsPerPage;
|
|
||||||
const startRow = (page - 1) * rowsPerPage;
|
|
||||||
try {
|
|
||||||
const result = await store.getDrinks({
|
|
||||||
offset: startRow,
|
|
||||||
limit: fetchCount,
|
|
||||||
descending,
|
|
||||||
search_name: props.filter?.value,
|
|
||||||
search_key: props.filter?.key,
|
|
||||||
receipt: true,
|
|
||||||
});
|
|
||||||
pagination.value.page = page;
|
|
||||||
pagination.value.rowsPerPage = rowsPerPage;
|
|
||||||
pagination.value.sortBy = sortBy;
|
|
||||||
pagination.value.descending = descending;
|
|
||||||
if (result.count) pagination.value.rowsNumber = result.count;
|
|
||||||
} catch (error) {
|
|
||||||
//..
|
|
||||||
}
|
|
||||||
loading.value = false;
|
|
||||||
}
|
|
||||||
interface PaginationInterface {
|
|
||||||
sortBy: string;
|
|
||||||
descending: boolean;
|
|
||||||
page: number;
|
|
||||||
rowsPerPage: number;
|
|
||||||
rowsNumber: number;
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
drinks,
|
drinks,
|
||||||
options: [...columns_drinks, ...columns_volumes, ...columns_prices],
|
options: [...columns_drinks, ...columns_volumes, ...columns_prices],
|
||||||
|
@ -218,9 +168,6 @@ export default defineComponent({
|
||||||
filter,
|
filter,
|
||||||
search_keys,
|
search_keys,
|
||||||
image,
|
image,
|
||||||
onRequest,
|
|
||||||
loading,
|
|
||||||
pagination,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -77,7 +77,7 @@ export default defineComponent({
|
||||||
.catch((err) => console.log(err));
|
.catch((err) => console.log(err));
|
||||||
void store.getTags();
|
void store.getTags();
|
||||||
void store.getDrinkTypes();
|
void store.getDrinkTypes();
|
||||||
void store.getDrinks({ limit: 10 });
|
void store.getDrinks();
|
||||||
void store.get_min_prices();
|
void store.get_min_prices();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
141
src/store.ts
141
src/store.ts
|
@ -1,7 +1,6 @@
|
||||||
import { api } from '@flaschengeist/api';
|
import { api } from '@flaschengeist/api';
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { calc_volume, calc_cost_per_volume, calc_all_min_prices } from './utils/utils';
|
import { calc_volume, calc_cost_per_volume, calc_all_min_prices } from './utils/utils';
|
||||||
import Ingredient = FG.Ingredient;
|
|
||||||
|
|
||||||
interface DrinkPriceVolume extends Omit<FG.DrinkPriceVolume, 'volume'> {
|
interface DrinkPriceVolume extends Omit<FG.DrinkPriceVolume, 'volume'> {
|
||||||
_volume: number;
|
_volume: number;
|
||||||
|
@ -14,6 +13,16 @@ interface Drink extends Omit<Omit<FG.Drink, 'cost_per_volume'>, 'volumes'> {
|
||||||
_cost_per_volume?: number;
|
_cost_per_volume?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Pricelist {
|
||||||
|
name: string;
|
||||||
|
type: FG.DrinkType;
|
||||||
|
tags: Array<FG.Tag>;
|
||||||
|
volume: number;
|
||||||
|
price: number;
|
||||||
|
public: boolean;
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
|
|
||||||
class DrinkPriceVolume implements DrinkPriceVolume {
|
class DrinkPriceVolume implements DrinkPriceVolume {
|
||||||
constructor({ id, volume, prices, ingredients }: FG.DrinkPriceVolume) {
|
constructor({ id, volume, prices, ingredients }: FG.DrinkPriceVolume) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
@ -36,7 +45,7 @@ class Drink {
|
||||||
cost_per_package,
|
cost_per_package,
|
||||||
tags,
|
tags,
|
||||||
type,
|
type,
|
||||||
has_image,
|
uuid,
|
||||||
receipt,
|
receipt,
|
||||||
}: FG.Drink) {
|
}: FG.Drink) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
@ -50,7 +59,7 @@ class Drink {
|
||||||
this.tags = tags;
|
this.tags = tags;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.volumes = [];
|
this.volumes = [];
|
||||||
this.has_image = has_image;
|
this.uuid = uuid;
|
||||||
this.receipt = receipt || [];
|
this.receipt = receipt || [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,7 +75,6 @@ export const usePricelistStore = defineStore({
|
||||||
state: () => ({
|
state: () => ({
|
||||||
drinkTypes: [] as Array<FG.DrinkType>,
|
drinkTypes: [] as Array<FG.DrinkType>,
|
||||||
drinks: [] as Array<Drink>,
|
drinks: [] as Array<Drink>,
|
||||||
pricelist: [] as Array<FG.DrinkPrice>,
|
|
||||||
extraIngredients: [] as Array<FG.ExtraIngredient>,
|
extraIngredients: [] as Array<FG.ExtraIngredient>,
|
||||||
min_prices: [] as Array<number>,
|
min_prices: [] as Array<number>,
|
||||||
tags: [] as Array<FG.Tag>,
|
tags: [] as Array<FG.Tag>,
|
||||||
|
@ -98,16 +106,11 @@ export const usePricelistStore = defineStore({
|
||||||
if (itm.length > 0) itm[0].name = drinkType.name;
|
if (itm.length > 0) itm[0].name = drinkType.name;
|
||||||
},
|
},
|
||||||
async getExtraIngredients() {
|
async getExtraIngredients() {
|
||||||
const { data } = await api.get<Array<FG.ExtraIngredient>>(
|
const { data } = await api.get<Array<FG.ExtraIngredient>>('pricelist/ingredients/extraIngredients');
|
||||||
'pricelist/ingredients/extraIngredients'
|
|
||||||
);
|
|
||||||
this.extraIngredients = data;
|
this.extraIngredients = data;
|
||||||
},
|
},
|
||||||
async setExtraIngredient(ingredient: FG.ExtraIngredient) {
|
async setExtraIngredient(ingredient: FG.ExtraIngredient) {
|
||||||
const { data } = await api.post<FG.ExtraIngredient>(
|
const { data } = await api.post<FG.ExtraIngredient>('pricelist/ingredients/extraIngredients', ingredient);
|
||||||
'pricelist/ingredients/extraIngredients',
|
|
||||||
ingredient
|
|
||||||
);
|
|
||||||
this.extraIngredients.push(data);
|
this.extraIngredients.push(data);
|
||||||
},
|
},
|
||||||
async updateExtraIngredient(ingredient: FG.ExtraIngredient) {
|
async updateExtraIngredient(ingredient: FG.ExtraIngredient) {
|
||||||
|
@ -129,24 +132,10 @@ export const usePricelistStore = defineStore({
|
||||||
this.extraIngredients.splice(index, 1);
|
this.extraIngredients.splice(index, 1);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async getDrinks(filter: {
|
async getDrinks() {
|
||||||
limit?: number;
|
const { data } = await api.get<Array<FG.Drink>>('pricelist/drinks');
|
||||||
offset?: number;
|
|
||||||
descending?: boolean;
|
|
||||||
search_name?: string;
|
|
||||||
search_key?: string;
|
|
||||||
receipt?: boolean;
|
|
||||||
}) {
|
|
||||||
if (!filter) filter = { limit: 10 };
|
|
||||||
console.log('filter_api', filter);
|
|
||||||
const { data } = await api.get<{ drinks: Array<FG.Drink>; count: number }>(
|
|
||||||
'pricelist/drinks',
|
|
||||||
{
|
|
||||||
params: filter,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
this.drinks = [];
|
this.drinks = [];
|
||||||
data.drinks.forEach((drink) => {
|
data.forEach((drink) => {
|
||||||
const _drink = new Drink(drink);
|
const _drink = new Drink(drink);
|
||||||
drink.volumes.forEach((volume) => {
|
drink.volumes.forEach((volume) => {
|
||||||
const _volume = new DrinkPriceVolume(volume);
|
const _volume = new DrinkPriceVolume(volume);
|
||||||
|
@ -155,7 +144,6 @@ export const usePricelistStore = defineStore({
|
||||||
this.drinks.push(_drink);
|
this.drinks.push(_drink);
|
||||||
});
|
});
|
||||||
calc_all_min_prices(this.drinks, this.min_prices);
|
calc_all_min_prices(this.drinks, this.min_prices);
|
||||||
return data;
|
|
||||||
},
|
},
|
||||||
sortPrices(volume: DrinkPriceVolume) {
|
sortPrices(volume: DrinkPriceVolume) {
|
||||||
volume.prices.sort((a, b) => {
|
volume.prices.sort((a, b) => {
|
||||||
|
@ -164,54 +152,6 @@ export const usePricelistStore = defineStore({
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
async getDrinks_no_store(filter: {
|
|
||||||
limit?: number;
|
|
||||||
offset?: number;
|
|
||||||
descending?: boolean;
|
|
||||||
search_name?: string;
|
|
||||||
search_key?: string;
|
|
||||||
ingredient?: boolean;
|
|
||||||
}) {
|
|
||||||
if (!filter) filter = { limit: 10 };
|
|
||||||
console.log('filter_api', filter);
|
|
||||||
const { data } = await api.get<{ drinks: Array<FG.Drink>; count: number }>(
|
|
||||||
'pricelist/drinks',
|
|
||||||
{
|
|
||||||
params: filter,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const drinks: Array<Drink> = [];
|
|
||||||
data.drinks.forEach((drink) => {
|
|
||||||
const _drink = new Drink(drink);
|
|
||||||
drink.volumes.forEach((volume) => {
|
|
||||||
const _volume = new DrinkPriceVolume(volume);
|
|
||||||
_drink.volumes.push(_volume);
|
|
||||||
});
|
|
||||||
drinks.push(_drink);
|
|
||||||
});
|
|
||||||
calc_all_min_prices(drinks, this.min_prices);
|
|
||||||
return drinks;
|
|
||||||
},
|
|
||||||
async getPricelist(filter: {
|
|
||||||
limit?: number;
|
|
||||||
offset?: number;
|
|
||||||
descending?: boolean;
|
|
||||||
search_name?: string;
|
|
||||||
search_key?: string;
|
|
||||||
sortBy?: string;
|
|
||||||
}) {
|
|
||||||
const { data } = await api.get<{ pricelist: Array<FG.DrinkPrice>; count: number }>(
|
|
||||||
'pricelist/list',
|
|
||||||
{
|
|
||||||
params: filter,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
this.pricelist = [];
|
|
||||||
console.log(data);
|
|
||||||
this.pricelist = data.pricelist;
|
|
||||||
console.log(this.pricelist);
|
|
||||||
return data.count;
|
|
||||||
},
|
|
||||||
async deletePrice(price: FG.DrinkPrice) {
|
async deletePrice(price: FG.DrinkPrice) {
|
||||||
await api.delete(`pricelist/prices/${price.id}`);
|
await api.delete(`pricelist/prices/${price.id}`);
|
||||||
},
|
},
|
||||||
|
@ -251,23 +191,6 @@ export const usePricelistStore = defineStore({
|
||||||
});
|
});
|
||||||
this.drinks[index] = _drink;
|
this.drinks[index] = _drink;
|
||||||
}
|
}
|
||||||
if (!!drink.cost_per_volume) {
|
|
||||||
this.drinks.forEach((_drink: Drink) => {
|
|
||||||
_drink.volumes.forEach((_volume: DrinkPriceVolume) => {
|
|
||||||
_volume.ingredients.forEach((_ingredient: Ingredient) => {
|
|
||||||
if (
|
|
||||||
_ingredient.drink_ingredient &&
|
|
||||||
_ingredient.drink_ingredient.ingredient_id === drink.id
|
|
||||||
) {
|
|
||||||
if (drink.cost_per_volume != null) {
|
|
||||||
_ingredient.drink_ingredient.cost_per_volume = drink.cost_per_volume;
|
|
||||||
}
|
|
||||||
_ingredient.drink_ingredient.name = drink.name;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
calc_all_min_prices(this.drinks, this.min_prices);
|
calc_all_min_prices(this.drinks, this.min_prices);
|
||||||
},
|
},
|
||||||
deleteDrink(drink: Drink) {
|
deleteDrink(drink: Drink) {
|
||||||
|
@ -299,12 +222,12 @@ export const usePricelistStore = defineStore({
|
||||||
});
|
});
|
||||||
const _drink = this.drinks.find((a) => a.id === drink.id);
|
const _drink = this.drinks.find((a) => a.id === drink.id);
|
||||||
if (_drink) {
|
if (_drink) {
|
||||||
_drink.has_image = data.has_image;
|
_drink.uuid = data.uuid;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async delete_drink_picture(drink: Drink) {
|
async delete_drink_picture(drink: Drink) {
|
||||||
await api.delete(`pricelist/drinks/${drink.id}/picture`);
|
await api.delete(`pricelist/drinks/${drink.id}/picture`);
|
||||||
drink.has_image = false;
|
drink.uuid = '';
|
||||||
},
|
},
|
||||||
async getTags() {
|
async getTags() {
|
||||||
const { data } = await api.get<Array<FG.Tag>>('/pricelist/tags');
|
const { data } = await api.get<Array<FG.Tag>>('/pricelist/tags');
|
||||||
|
@ -345,9 +268,7 @@ export const usePricelistStore = defineStore({
|
||||||
this.pricelist_view = data;
|
this.pricelist_view = data;
|
||||||
},
|
},
|
||||||
async getPriceListColumnOrder(userid: string) {
|
async getPriceListColumnOrder(userid: string) {
|
||||||
const { data } = await api.get<Array<Order>>(
|
const { data } = await api.get<Array<Order>>(`pricelist/users/${userid}/pricecalc_columns_order`);
|
||||||
`pricelist/users/${userid}/pricecalc_columns_order`
|
|
||||||
);
|
|
||||||
this.pricelist_columns_order = data;
|
this.pricelist_columns_order = data;
|
||||||
},
|
},
|
||||||
async updatePriceListColumnOrder(userid: string, data: Array<Order>) {
|
async updatePriceListColumnOrder(userid: string, data: Array<Order>) {
|
||||||
|
@ -355,7 +276,27 @@ export const usePricelistStore = defineStore({
|
||||||
this.pricelist_columns_order = data;
|
this.pricelist_columns_order = data;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
getters: {},
|
getters: {
|
||||||
|
pricelist() {
|
||||||
|
const retVal: Array<Pricelist> = [];
|
||||||
|
this.drinks.forEach((drink) => {
|
||||||
|
drink.volumes.forEach((volume) => {
|
||||||
|
volume.prices.forEach((price) => {
|
||||||
|
retVal.push({
|
||||||
|
name: drink.name,
|
||||||
|
type: <FG.DrinkType>drink.type,
|
||||||
|
tags: <Array<FG.Tag>>drink.tags,
|
||||||
|
volume: <number>volume.volume,
|
||||||
|
price: price.price,
|
||||||
|
public: price.public,
|
||||||
|
description: <string>price.description,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return retVal;
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export { DrinkPriceVolume, Drink, Order };
|
export { DrinkPriceVolume, Drink, Order };
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
import { Drink } from '../store';
|
import { Drink } from '../store';
|
||||||
|
|
||||||
function filter(
|
function filter(rows: Array<Drink>, terms: Search, cols: Array<Col>, cellValue: { (col: Col, row: Drink): string }) {
|
||||||
rows: Array<Drink>,
|
|
||||||
terms: Search,
|
|
||||||
cols: Array<Col>,
|
|
||||||
cellValue: { (col: Col, row: Drink): string }
|
|
||||||
) {
|
|
||||||
if (terms.value) {
|
if (terms.value) {
|
||||||
return rows.filter((row) => {
|
return rows.filter((row) => {
|
||||||
if (!terms.key || terms.key === '') {
|
if (!terms.key || terms.key === '') {
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
import { ref } from 'vue';
|
|
||||||
|
|
||||||
const newImage = ref<Array<{ id: number; lastModified: Date }>>([]);
|
|
||||||
|
|
||||||
export function getNewImage(id: number) {
|
|
||||||
const image = newImage.value.find((a) => a.id === id);
|
|
||||||
if (image) {
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setNewImage(id: number) {
|
|
||||||
const image = newImage.value.find((a) => a.id === id);
|
|
||||||
if (image) {
|
|
||||||
image.lastModified = new Date();
|
|
||||||
} else {
|
|
||||||
newImage.value.push({ id, lastModified: new Date() });
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -17,8 +17,7 @@ function calc_volume(volume: DrinkPriceVolume) {
|
||||||
function calc_cost_per_volume(drink: Drink) {
|
function calc_cost_per_volume(drink: Drink) {
|
||||||
let retVal = drink._cost_per_volume;
|
let retVal = drink._cost_per_volume;
|
||||||
if (!!drink.volume && !!drink.package_size && !!drink.cost_per_package) {
|
if (!!drink.volume && !!drink.package_size && !!drink.cost_per_package) {
|
||||||
retVal =
|
retVal = ((drink.cost_per_package || 0) / ((drink.volume || 0) * (drink.package_size || 0))) * 1.19;
|
||||||
((drink.cost_per_package || 0) / ((drink.volume || 0) * (drink.package_size || 0))) * 1.19;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return retVal ? Math.round(retVal * 1000) / 1000 : retVal;
|
return retVal ? Math.round(retVal * 1000) / 1000 : retVal;
|
||||||
|
@ -37,9 +36,8 @@ function helper(volume: DrinkPriceVolume, min_price: number) {
|
||||||
let extraIngredientPrice = 0;
|
let extraIngredientPrice = 0;
|
||||||
volume.ingredients.forEach((ingredient) => {
|
volume.ingredients.forEach((ingredient) => {
|
||||||
if (ingredient.drink_ingredient) {
|
if (ingredient.drink_ingredient) {
|
||||||
//const _drink = usePricelistStore().drinks.find((a) => a.id === ingredient.drink_ingredient?.ingredient_id);
|
const _drink = usePricelistStore().drinks.find((a) => a.id === ingredient.drink_ingredient?.ingredient_id);
|
||||||
//retVal += ingredient.drink_ingredient.volume * <number>(<unknown>_drink?.cost_per_volume);
|
retVal += ingredient.drink_ingredient.volume * <number>(<unknown>_drink?.cost_per_volume);
|
||||||
retVal += ingredient.drink_ingredient.volume * ingredient.drink_ingredient.cost_per_volume;
|
|
||||||
}
|
}
|
||||||
if (ingredient.extra_ingredient) {
|
if (ingredient.extra_ingredient) {
|
||||||
extraIngredientPrice += ingredient.extra_ingredient.price;
|
extraIngredientPrice += ingredient.extra_ingredient.price;
|
||||||
|
@ -48,11 +46,7 @@ function helper(volume: DrinkPriceVolume, min_price: number) {
|
||||||
return (retVal * min_price) / 100 + extraIngredientPrice;
|
return (retVal * min_price) / 100 + extraIngredientPrice;
|
||||||
}
|
}
|
||||||
|
|
||||||
function calc_min_prices(
|
function calc_min_prices(volume: DrinkPriceVolume, cost_per_volume: number | undefined, min_prices: Array<number>) {
|
||||||
volume: DrinkPriceVolume,
|
|
||||||
cost_per_volume: number | undefined,
|
|
||||||
min_prices: Array<number>
|
|
||||||
) {
|
|
||||||
const retVal: Array<FG.MinPrices> = [];
|
const retVal: Array<FG.MinPrices> = [];
|
||||||
volume.min_prices = [];
|
volume.min_prices = [];
|
||||||
if (min_prices) {
|
if (min_prices) {
|
||||||
|
|
Loading…
Reference in New Issue