Compare commits

...

20 Commits

Author SHA1 Message Date
Philipp Lang 9e1fe63c33 Fix svg sprite
continuous-integration/drone/tag Build is passing Details
continuous-integration/drone/push Build is passing Details
2023-06-01 11:31:12 +02:00
Philipp Lang 1d8b5b4670 Mod gitignore 2023-06-01 11:07:48 +02:00
Philipp Lang 526f2d3a6c add vite config 2023-06-01 11:05:24 +02:00
Philipp Lang fbb501519a add vite script 2023-06-01 11:05:13 +02:00
Philipp Lang 3485832262 fix component names 2023-06-01 11:05:03 +02:00
Philipp Lang 4bece4a761 Remove tailwind component layer 2023-06-01 11:03:59 +02:00
Philipp Lang b2b53c558e Lint 2023-06-01 11:03:53 +02:00
Philipp Lang 2e5385b565 Add vite package 2023-06-01 11:03:14 +02:00
Philipp Lang 754e3a0a82 ignore build folder 2023-06-01 11:02:55 +02:00
philipp lang 4e27dbfe67 Move other components
continuous-integration/drone/push Build is failing Details
2023-05-20 02:48:08 +02:00
philipp lang c68f1e00c4 Move boolean display 2023-05-20 02:44:41 +02:00
philipp lang d78740d508 Add new slot scope syntax 2023-05-20 02:38:38 +02:00
philipp lang 641f3a1098 Lint 2023-05-20 01:59:20 +02:00
philipp lang dbbe6f6171 Remove links 2023-05-20 01:46:59 +02:00
philipp lang e26b572575 Move page header component 2023-05-20 01:45:43 +02:00
philipp lang a526683082 Add tooltip slot to sidebar header 2023-05-20 01:12:53 +02:00
philipp lang 07d309f606 Update Tailwindcss 2023-05-20 00:57:57 +02:00
philipp lang 234380120e Load page components synchronously 2023-05-20 00:57:05 +02:00
Philipp Lang 72375affee Move components
continuous-integration/drone/push Build is passing Details
2023-05-19 01:07:34 +02:00
Philipp Lang d01322b1ad Move component subfolders 2023-05-18 23:22:45 +02:00
64 changed files with 1181 additions and 7073 deletions

View File

@ -24,7 +24,7 @@ steps:
- name: node
image: node:17.9.0-slim
commands:
- npm ci && npm run prod && npm run img && rm -R node_modules
- npm ci && npm run img && npm run prod && rm -R node_modules
- name: phpunit_tests
image: php:8.1.6

10
.gitignore vendored
View File

@ -1,11 +1,7 @@
/node_modules
/public/build
/public/sprite.svg
/public/hot
/public/storage
/public/js
/public/css
/public/fonts
/public/img
/public/images
/storage/*.key
/vendor
.env
@ -17,14 +13,12 @@ Homestead.yaml
npm-debug.log
yarn-error.log
tags
/public/vendor
/storage/temp
# Temporary files
*.swp
*.swo
*.swm
/public/mix-manifest.json
resources/img/sprite.svg
/.php-cs-fixer.cache
/data

7185
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -2,12 +2,12 @@
"private": true,
"scripts": {
"dev": "npm run development",
"development": "npx mix build",
"watch": "npx mix watch",
"hot": "npx mix watch --hot",
"prod": "npx mix build --production",
"development": "npx vite",
"watch": "npx vite",
"hot": "npx vite",
"prod": "npx vite build",
"production": "npm run prod",
"img": "rm -R public/img && cd resources/img/svg && npx svg-sprite -s --symbol-dest=sprite *.svg && mv sprite/svg/sprite.css.svg ../sprite.svg && rm -R sprite && cd ../../../ && cp -R resources/img public/img",
"img": "cd resources/img/svg && npx svg-sprite -s --symbol-dest=sprite *.svg && mv sprite/svg/sprite.css.svg ../../../public/sprite.svg && rm -R sprite",
"lint": "eslint \"resources/js/**/*.{js,vue}\"",
"fix": "eslint \"resources/js/**/*.{js,vue}\" --fix"
},
@ -16,9 +16,8 @@
"axios": "^1.3.4",
"eslint": "^8.9.0",
"eslint-plugin-vue": "^8.4.1",
"laravel-mix": "^6.0.1",
"postcss": "^8.4.6",
"tailwindcss": "^3.2",
"tailwindcss": "^3.3",
"vue": "2.7",
"vue-axios": "^3.5.2",
"vue-loader": "^15.9.8",
@ -28,6 +27,9 @@
"@inertiajs/inertia": "^0.11.0",
"@inertiajs/inertia-vue": "^0.8.0",
"@tailwindcss/typography": "^0.5.9",
"@vitejs/plugin-vue2": "^2.2.0",
"change-case": "^4.1.2",
"laravel-vite-plugin": "^0.7.7",
"leaflet": "^1.9.3",
"lodash": "^4.17.21",
"merge": "^2.1.1",
@ -36,6 +38,7 @@
"postcss-import": "^14.0.1",
"svg-sprite": "^2.0.2",
"v-tooltip": "^2.1.3",
"vite": "^4.3.8",
"vue-toasted": "^1.1.28",
"vue2-leaflet": "^2.7.1",
"wnumb": "^1.2.0"

10
postcss.config.js vendored Normal file
View File

@ -0,0 +1,10 @@
const tailwindcss = require('tailwindcss');
module.exports = {
plugins: {
'postcss-import': {},
'tailwindcss/nesting': {},
'tailwindcss': {},
'autoprefixer': {},
},
};

22
resources/css/app.css vendored
View File

@ -2,15 +2,13 @@
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
@layer components {
@import 'base';
@import 'switch';
@import 'layout';
@import 'buttons';
@import 'table';
@import 'sidebar';
@import 'bool';
@import 'form';
@import 'tooltip';
@import 'leaflet';
}
@import 'base.css';
@import 'switch';
@import 'layout';
@import 'buttons';
@import 'table';
@import 'sidebar';
@import 'bool';
@import 'form';
@import 'tooltip';
@import 'leaflet';

View File

@ -7,7 +7,6 @@
@apply mb-4;
}
.form-control-font {
@apply leading-tight text-gray-600 text-sm;
}
@ -18,7 +17,8 @@
top: 34px;
transition: color 02s, padding-bottom 02s, font-size 02s, top 02s;
}
.field-wrapperfocused label-placeholder, label-placeholder-focused {
.field-wrapperfocused label-placeholder,
label-placeholder-focused {
top: 0;
@apply text-sm text-gray-600;
padding-bottom: 10px;
@ -42,24 +42,25 @@
@apply py-2;
}
input, select {
input,
select {
outline: none;
}
input[type="date"],
input[type="datetime-local"],
input[type="time"],
input[type="month"],
input[type='date'],
input[type='datetime-local'],
input[type='time'],
input[type='month'],
select,
input[type="week"] {
input[type='week'] {
height: 37px;
&::-webkit-inner-spin-button {
display: none;
}
}
input[type="date"]::-webkit-inner-spin-button,
input[type="date"]::-webkit-calendar-picker-indicator {
input[type='date']::-webkit-inner-spin-button,
input[type='date']::-webkit-calendar-picker-indicator {
display: none;
-webkit-appearance: none;
}

View File

@ -82,10 +82,8 @@
}
&.popover {
$color: #f9f9f9;
.popover-inner {
background: $color;
background: #f9f9f9;
color: black;
padding: 24px;
border-radius: 5px;
@ -93,7 +91,7 @@
}
.popover-arrow {
border-color: $color;
border-color: #f9f9f9;
}
}

62
resources/js/app.js vendored
View File

@ -1,64 +1,50 @@
import Vue from 'vue';
import {App as InertiaApp, plugin, Link as ILink} from '@inertiajs/inertia-vue';
import {Inertia} from '@inertiajs/inertia';
import SvgSprite from './components/SvgSprite.js';
import VPages from './components/VPages.vue';
import VLabel from './components/VLabel.vue';
import VBool from './components/VBool.vue';
import Box from './components/Box.vue';
import Heading from './components/Heading.vue';
import IconButton from './components/Ui/IconButton.vue';
import ToolbarButton from './components/Ui/ToolbarButton.vue';
import PageLayout from './components/Page/Layout.vue';
import AppLayout from './layouts/AppLayout.vue';
import VTooltip from 'v-tooltip';
import hasModule from './mixins/hasModule.js';
import hasFlash from './mixins/hasFlash.js';
import PortalVue from 'portal-vue';
import axios from 'axios';
import VueAxios from 'vue-axios';
import Toasted from 'vue-toasted';
import VTooltip from 'v-tooltip';
import {createPinia, PiniaVuePlugin} from 'pinia';
import requireModules from './lib/requireModules.js';
import AppLayout from './layouts/AppLayout.vue';
import hasModule from './mixins/hasModule.js';
import hasFlash from './mixins/hasFlash.js';
import '../css/app.css';
// ---------------------------------- Assets -----------------------------------
import.meta.glob(['../img/**']);
// ---------------------------------- Plugins ----------------------------------
Vue.use(plugin);
Vue.use(PortalVue);
Vue.use(VTooltip);
Vue.use(Toasted);
Vue.use(VueAxios, axios);
Vue.use(PiniaVuePlugin);
Vue.component('f-text', () => import(/* webpackChunkName: "form" */ './components/FText'));
Vue.component('f-switch', () => import(/* webpackChunkName: "form" */ './components/FSwitch'));
Vue.component('f-select', () => import(/* webpackChunkName: "form" */ './components/FSelect'));
Vue.component('f-textarea', () => import(/* webpackChunkName: "form" */ './components/FTextarea'));
Vue.component('SvgSprite', SvgSprite);
Vue.component('VPages', VPages);
Vue.component('v-bool', VBool);
Vue.component('v-label', VLabel);
Vue.component('box', Box);
Vue.component('heading', Heading);
Vue.component('icon-button', IconButton);
Vue.component('toolbar-button', ToolbarButton);
Vue.component('page-layout', PageLayout);
Vue.component('save-button', () => import(/* webpackChunkName: "form" */ './components/SaveButton'));
// ------------------------------ Full components ------------------------------
Vue.component('full-page-heading', () => import(/* webpackChunkName: "full" */ './components/Full/PageHeading.vue'));
Vue.component('SvgSprite', () => import('./components/SvgSprite.js'));
Vue.component('ILink', ILink);
// ------------------------------- UI Components -------------------------------
Vue.component('ui-button', () => import(/* webpackChunkName: "ui" */ './components/Ui/Button.vue'));
Vue.component('ui-spinner', () => import(/* webpackChunkName: "ui" */ './components/Ui/Spinner.vue'));
// -------------------------------- Components ---------------------------------
requireModules(import.meta.glob('./components/form/*.vue'), Vue, 'f');
requireModules(import.meta.glob('./components/ui/*.vue'), Vue, 'ui');
requireModules(import.meta.glob('./components/page/*.vue', {eager: true}), Vue, 'page');
// ---------------------------------- mixins -----------------------------------
Vue.mixin(hasModule);
Vue.mixin(hasFlash);
// ----------------------------------- init ------------------------------------
const el = document.getElementById('app');
const pinia = createPinia();
Vue.mixin(hasModule);
Vue.mixin(hasFlash);
Vue.component('ILink', ILink);
Inertia.on('start', (event) => window.dispatchEvent(new Event('inertiaStart')));
let views = import.meta.glob('./views/**/*.vue');
new Vue({
pinia,
render: (h) =>
@ -66,7 +52,7 @@ new Vue({
props: {
initialPage: JSON.parse(el.dataset.page),
resolveComponent: async (name) => {
var page = (await import(`./views/${name}`)).default;
var page = (await views[`./views/${name}.vue`]()).default;
if (page.layout === undefined) {
page.layout = AppLayout;

View File

@ -1,144 +0,0 @@
<template>
<label class="flex flex-col relative field-checkbox cursor-pointer" :for="id" :class="{[`size-${size}`]: true}">
<span
v-if="label && inset"
class="z-10 absolute top-0 left-0 -mt-2 px-1 ml-3 inset-bg font-semibold text-gray-700"
>{{ label }}</span
>
<div class="relative flex items-start">
<input :id="id" type="checkbox" v-model="v" :disabled="disabled" class="invisible absolute" />
<span class="display-wrapper flex items-center">
<span
class="relative cursor-pointer flex flex-none justify-center items-center display"
:class="{'bg-terminoto-2': v === true, 'bg-white': v === false}"
>
<svg-sprite src="check" class="w-4 h-4 check-icon text-white"></svg-sprite>
</span>
</span>
<span
v-if="label && !inset"
class="text-sm leading-tight ml-3 text-gray-700 checkbox-label flex items-center"
>
<span>
<span v-text="label" v-if="!html"></span>
<span v-html="label" v-if="html"></span>
<span v-show="required" class="font-semibold text-red-700">*</span>
</span>
</span>
</div>
</label>
</template>
<script>
export default {
model: {
prop: 'items',
event: 'input',
},
props: {
html: {
type: Boolean,
default: false,
},
required: {
type: Boolean,
default: false,
},
inset: {
type: Boolean,
default: false,
},
size: {
default: null,
required: false,
},
id: {
required: true,
},
disabled: {
type: Boolean,
default: false,
},
value: {
default: false,
},
label: {
default: false,
},
items: {
default: undefined,
},
},
computed: {
v: {
set(v) {
if (this.disabled === true) {
return;
}
if (typeof this.items === 'boolean') {
this.$emit('input', v);
return;
}
var a = this.items.filter((i) => i !== this.value);
if (v) {
a.push(this.value);
}
this.$emit('input', a);
},
get() {
if (typeof this.items === 'boolean') {
return this.items;
}
if (typeof this.items === 'undefined') {
return this.$emit('input', false);
}
return this.items.indexOf(this.value) !== -1;
},
},
},
created() {
if (typeof this.items === 'undefined') {
this.$emit('input', false);
}
},
};
</script>
<style lang="css">
:root {
--checkbox-width: 30px;
--margin: 0.2rem;
}
.field-checkbox {
input:checked + span {
transition: background 0.2s;
}
.display-wrapper,
.checkbox-label {
min-height: 34px;
}
.display {
width: var(--checkbox-width);
height: var(--checkbox-width);
border-radius: 0.3rem;
border: solid 2px hsl(60, 1.8%, 10.8%);
.check-icon {
opacity: 0;
transition: opacity 0.2s;
}
}
input:checked + .display-wrapper .display .check-icon {
opacity: 1;
transition: opacity 0.2s;
}
}
</style>

View File

@ -1,9 +0,0 @@
<template>
<div class="font-semibold text-gray-300">
<slot></slot>
</div>
</template>
<script>
export default {};
</script>

View File

@ -1,48 +0,0 @@
<template>
<div class="h-16 px-6 flex justify-between items-center border-b border-solid border-gray-500">
<div class="flex items-center">
<span class="mr-1 text-xl font-semibold leading-none text-white" v-html="title"></span>
<a
v-for="(link, index) in links.filter((link) => link.icon === undefined)"
:key="index"
@click.prevent="$emit(link.event)"
href="#"
class="btn label btn-primary-light"
>
<span v-if="link.label" v-text="link.label"></span>
<svg-sprite v-if="link.icon" :src="link.icon"></svg-sprite>
</a>
<a
v-for="(link, index) in links.filter((link) => link.icon !== undefined)"
:key="index"
:href="link.href"
class="btn label icon btn-primary-light ml-1"
>
<span v-if="link.label" v-text="link.label"></span>
<svg-sprite v-if="link.icon" :src="link.icon"></svg-sprite>
</a>
</div>
<div class="flex ml-4">
<a href="#" @click.prevent="$emit('close')" class="btn label btn-primary-light icon">
<svg-sprite class="w-3 h-3" src="close"></svg-sprite>
</a>
</div>
</div>
</template>
<script>
export default {
props: {
links: {
default: function () {
return [];
},
},
title: {
default: function () {
return '';
},
},
},
};
</script>

View File

@ -1,17 +1,25 @@
export default {
props: {
src: { required: true, type: String }
src: {required: true, type: String},
},
render: function(createElement) {
render: function (createElement) {
var attr = this.$attrs.class ? this.$attrs.class : '';
return createElement('svg', {
class: attr + ' fill-current'
}, [
createElement('use', {
'attrs': {
'xlink:href': `/img/sprite.svg#${this.$props.src}`
}
}, '')
] );
}
return createElement(
'svg',
{
class: attr + ' fill-current',
},
[
createElement(
'use',
{
attrs: {
'xlink:href': `/sprite.svg#${this.$props.src}`,
},
},
''
),
]
);
},
};

View File

@ -0,0 +1,27 @@
<template>
<div class="h-16 px-6 flex items-center justify-between border-b border-solid border-gray-600 group-[.is-bright]:border-gray-500">
<div class="flex items-center space-x-2">
<slot name="before-title"></slot>
<page-title>{{ title }}</page-title>
<slot name="toolbar"></slot>
</div>
<div class="flex items-center space-x-2 ml-2">
<a href="#" v-if="$listeners.close" @click.prevent="$emit('close')" class="btn label btn-primary-light icon">
<svg-sprite class="w-3 h-3" src="close"></svg-sprite>
</a>
<slot name="right"></slot>
</div>
</div>
</template>
<script>
export default {
props: {
title: {
default: function () {
return '';
},
},
},
};
</script>

View File

@ -1,16 +1,18 @@
<template>
<div class="grow bg-gray-900 flex flex-col transition-all" :class="{'ml-56': menuStore.visible, 'ml-0': !menuStore.visible}">
<div class="h-16 px-6 flex items-center space-x-3 border-b border-gray-600">
<a href="#" @click.prevent="menuStore.toggle()" class="lg:hidden">
<svg-sprite src="menu" class="text-gray-100 w-5 h-5"></svg-sprite>
</a>
<span class="text-sm md:text-xl font-semibold text-white leading-none" v-html="$page.props.title"></span>
<slot name="toolbar"></slot>
<div class="flex grow justify-between">
<portal-target name="toolbar-left"> </portal-target>
<page-header :title="$page.props.title">
<template #before-title>
<a href="#" @click.prevent="menuStore.toggle()" class="mr-2 lg:hidden">
<svg-sprite src="menu" class="text-gray-100 w-5 h-5"></svg-sprite>
</a>
</template>
<template #toolbar>
<slot name="toolbar"></slot>
</template>
<template #right>
<portal-target name="toolbar-right"> </portal-target>
</div>
</div>
</template>
</page-header>
<div :class="pageClass" class="grow flex flex-col">
<slot></slot>

View File

@ -0,0 +1,7 @@
<template>
<span class="text-sm md:text-xl font-semibold leading-none text-white"><slot></slot></span>
</template>
<script>
export default {};
</script>

View File

@ -1,5 +1,5 @@
<template>
<i-link :href="href" class="btn label mr-2" :class="colors[color]" v-tooltip="menuStore.tooltipsVisible ? $slots.default[0].text : ''">
<i-link :href="href" v-on="$listeners" class="btn label" :class="colors[color]" v-tooltip="menuStore.tooltipsVisible ? $slots.default[0].text : ''">
<svg-sprite v-show="icon" class="w-3 h-3 xl:mr-2" :src="icon"></svg-sprite>
<span class="hidden xl:inline"><slot></slot></span>
</i-link>

View File

@ -1,14 +1,7 @@
<template>
<div v-tooltip="longLabel" class="flex space-x-2 items-center">
<div
class="border-2 rounded-full w-4 h-4 flex items-center justify-center"
:class="value ? 'border-green-700' : 'border-red-700'"
>
<svg-sprite
:src="value ? 'check' : 'close'"
:class="value ? 'text-green-800' : 'text-red-800'"
class="w-3 h-3 flex-none"
></svg-sprite>
<div class="border-2 rounded-full w-5 h-5 flex items-center justify-center" :class="value ? 'border-green-700' : 'border-red-700'">
<svg-sprite :src="value ? 'check' : 'close'" :class="value ? 'text-green-800' : 'text-red-800'" class="w-3 h-3 flex-none"></svg-sprite>
</div>
<div class="text-gray-400 text-xs" v-text="label"></div>
</div>

View File

@ -1,7 +1,7 @@
<template>
<section class="p-3 rounded-lg flex flex-col" :class="{'bg-gray-800': second === false, 'bg-gray-700': second === true}">
<div class="flex items-center">
<heading class="col-span-full" v-if="heading">{{ heading }}</heading>
<div class="col-span-full font-semibold text-gray-300" v-if="heading" v-text="heading"></div>
<slot name="in-title"></slot>
</div>
<main :class="{'mt-2': heading, [containerClass]: true}">

9
resources/js/lib/requireModules.js vendored Normal file
View File

@ -0,0 +1,9 @@
import {paramCase} from 'change-case';
export default function (context, Vue, prefix) {
for (const file in context) {
let componentName = paramCase(`${prefix}${file.replace(/^.*\/(.*?)\.vue$/g, '$1')}`);
Vue.component(componentName, typeof context[file] === 'function' ? context[file] : context[file].default);
}
}

View File

@ -1,7 +1,7 @@
<template>
<div>
<div v-if="step === 0">
<full-page-heading>Willkommen im Adrema-Setup.<br /></full-page-heading>
<page-full-heading>Willkommen im Adrema-Setup.<br /></page-full-heading>
<div class="prose prose-invert">
<p>Bitte gib deine NaMi-Zugangsdaten ein,<br />um eine erste Synchronisation durchzuführen.</p>
</div>
@ -12,7 +12,7 @@
</form>
</div>
<div v-if="step === 1" class="grid grid-cols-5 w-full gap-3">
<full-page-heading class="col-span-full !mb-0">Suchkriterien festlegen</full-page-heading>
<page-full-heading class="col-span-full !mb-0">Suchkriterien festlegen</page-full-heading>
<form @submit.prevent="storeSearch" class="border-2 border-primary-800 border-solid p-3 rounded-lg grid gap-3 col-span-2">
<div class="prose prose-invert max-w-none col-span-full">
<p>
@ -105,13 +105,13 @@
</table>
<div v-if="preview !== null" class="px-6">
<v-pages class="mt-4" :value="preview" @reload="reloadPage"></v-pages>
<ui-pagination class="mt-4" :value="preview" @reload="reloadPage"></ui-pagination>
</div>
</section>
<section class="col-span-3 items-center justify-center flex text-xl text-gray-200 border-2 border-primary-800 border-solid p-3 rounded-lg mt-4" v-else>Keine Mitglieder gefunden</section>
</div>
<div v-if="step === 2">
<full-page-heading>Standard-Gruppierung</full-page-heading>
<page-full-heading>Standard-Gruppierung</page-full-heading>
<div class="prose prose-invert">
<p>Bitte gib hier deine Standard-Gruppierungsnummer ein.</p>
<p>Dieser Gruppierung werden Mitglieder automatisch zugeordnet,<br />falls nichts anderes angegeben wurde.</p>
@ -123,7 +123,7 @@
</form>
</div>
<div v-if="step === 3">
<full-page-heading>Einrichtung abgeschlossen</full-page-heading>
<page-full-heading>Einrichtung abgeschlossen</page-full-heading>
<div class="prose prose-invert">
<p>Wir werden nun die Mitgliederdaten anhand deiner festgelegten Kriterien abrufen.</p>
<p>Per Klick auf "Abschließen" gelangst du zum Dashboard</p>

View File

@ -2,7 +2,7 @@
<form @submit.prevent="submit">
<div class="h-24 p-6 md:px-10 bg-primary-800 flex justify-between items-center w-full">
<span class="text-primary-500 text-xl">Login</span>
<img src="/img/dpsg.gif" class="w-24" />
<img src="../../img/dpsg.gif" class="w-24" />
</div>
<div class="p-6 md:p-10 grid gap-5">
<f-text id="email" label="E-Mail-Adresse" v-model="values.email"></f-text>
@ -13,7 +13,7 @@
</template>
<script>
import FullLayout from '../layouts/FullLayout';
import FullLayout from '../layouts/FullLayout.vue';
export default {
layout: FullLayout,

View File

@ -4,7 +4,7 @@
<f-text size="sm" id="name" v-model="model.name" label="Name" required></f-text>
<f-switch size="sm" v-model="model.is_filterable" name="subactivity_is_filterable" id="subactivity_is_filterable" label="Filterbar"></f-switch>
</div>
<icon-button class="mt-3" icon="save" @click.prevent="store">Speichern</icon-button>
<ui-icon-button class="mt-3" icon="save" @click.prevent="store">Speichern</ui-icon-button>
</div>
</template>

View File

@ -1,19 +1,19 @@
<template>
<page-layout>
<div class="flex" slot="toolbar">
<toolbar-button :href="meta.links.index" color="primary" icon="undo">zurück</toolbar-button>
</div>
<template #toolbar>
<page-toolbar-button :href="meta.links.index" color="primary" icon="undo">zurück</page-toolbar-button>
</template>
<form id="actionform" class="grow p-3" @submit.prevent="submit">
<popup heading="Neue Untertätigkeit" v-if="mode === 'edit' && currentSubactivity !== null" @close="currentSubactivity = null">
<ui-popup heading="Neue Untertätigkeit" v-if="mode === 'edit' && currentSubactivity !== null" @close="currentSubactivity = null">
<subactivity-form class="mt-4" v-if="currentSubactivity" :value="currentSubactivity" @stored="reloadSubactivities" @updated="mergeSubactivity"></subactivity-form>
</popup>
</ui-popup>
<div class="flex space-x-3">
<f-text id="name" v-model="inner.name" label="Name" required></f-text>
<f-switch v-model="inner.is_filterable" name="is_filterable" id="is_filterable" label="Filterbar"></f-switch>
</div>
<div class="flex space-x-3 items-center mt-6 mb-2">
<checkboxes-label>Untertätigkeiten</checkboxes-label>
<icon-button icon="plus" v-if="mode === 'edit'" @click.prevent="currentSubactivity = inner.subactivity_model">Neu</icon-button>
<f-checkboxes-label>Untertätigkeiten</f-checkboxes-label>
<ui-icon-button icon="plus" v-if="mode === 'edit'" @click.prevent="currentSubactivity = inner.subactivity_model">Neu</ui-icon-button>
</div>
<div class="grid gap-2 sm:grid-cols-2 md:grid-cols-4">
<div v-for="option in subactivities" class="flex items-center space-x-2">
@ -32,7 +32,7 @@
></f-switch>
</div>
</div>
<save-button form="actionform"></save-button>
<f-save-button form="actionform"></f-save-button>
</form>
</page-layout>
</template>
@ -54,9 +54,7 @@ export default {
},
components: {
'checkboxes-label': () => import('../../components/Form/CheckboxesLabel'),
'subactivity-form': () => import('./SubactivityForm.vue'),
'popup': () => import(/* webpackChunkName: "ui" */ '../../components/Ui/Popup.vue'),
},
methods: {

View File

@ -1,9 +1,9 @@
<template>
<page-layout page-class="pb-6">
<div class="flex" slot="toolbar">
<toolbar-button :href="data.meta.links.create" color="primary" icon="plus">Tätigkeit erstellen</toolbar-button>
</div>
<popup heading="Bitte bestätigen" v-if="deleting !== null">
<template #toolbar>
<page-toolbar-button :href="data.meta.links.create" color="primary" icon="plus">Tätigkeit erstellen</page-toolbar-button>
</template>
<ui-popup heading="Bitte bestätigen" v-if="deleting !== null">
<div>
<p class="mt-4">Diese Aktivität löschen?</p>
<div class="grid grid-cols-2 gap-3 mt-6">
@ -11,7 +11,7 @@
<a href="#" @click.prevent="deleting = null" class="text-center btn btn-primary">Abbrechen</a>
</div>
</div>
</popup>
</ui-popup>
<table cellspacing="0" cellpadding="0" border="0" class="custom-table custom-table-sm table">
<thead>
<th>Name</th>
@ -30,7 +30,7 @@
</table>
<div class="px-6">
<v-pages class="mt-4" :value="data.meta" :only="['data']"></v-pages>
<ui-pagination class="mt-4" :value="data.meta" :only="['data']"></ui-pagination>
</div>
</page-layout>
</template>
@ -58,10 +58,6 @@ export default {
},
},
components: {
popup: () => import(/* webpackChunkName: "ui" */ '../../components/Ui/Popup.vue'),
},
mixins: [indexHelpers],
};
</script>

View File

@ -16,7 +16,7 @@ export default {
},
components: {
'VBlock': () => import('./VBlock'),
'VBlock': () => import('./VBlock.vue'),
'age-group-count': () => import('./AgeGroupCount.vue'),
'efz-pending': () => import('./EfzPending.vue'),
'ps-pending': () => import('./PsPending.vue'),

View File

@ -1,25 +1,15 @@
<template>
<div class="sidebar flex flex-col">
<sidebar-header
:links="indexLinks"
@close="$emit('close')"
@create="
mode = 'create';
single = {};
"
title="Ausbildungen"
></sidebar-header>
<div class="sidebar flex flex-col group is-bright">
<page-header @close="$emit('close')" title="Ausbildungen">
<template #toolbar>
<page-toolbar-button @click.prevent="create" color="primary" icon="plus" v-if="single === null">Neue Ausbildung</page-toolbar-button>
<page-toolbar-button @click.prevent="cancel" color="primary" icon="undo" v-if="single !== null">Zurück</page-toolbar-button>
</template>
</page-header>
<form v-if="single" class="p-6 grid gap-4 justify-start" @submit.prevent="submit">
<f-text id="completed_at" type="date" v-model="single.completed_at" label="Datum" required></f-text>
<f-select
id="course_id"
name="course_id"
:options="courses"
v-model="single.course_id"
label="Baustein"
required
></f-select>
<f-select id="course_id" name="course_id" :options="courses" v-model="single.course_id" label="Baustein" required></f-select>
<f-text id="event_name" v-model="single.event_name" label="Veranstaltung" required></f-text>
<f-text id="organizer" v-model="single.organizer" label="Veranstalter" required></f-text>
<button type="submit" class="btn btn-primary">Absenden</button>
@ -50,9 +40,7 @@
class="inline-flex btn btn-warning btn-sm"
><svg-sprite src="pencil"></svg-sprite
></a>
<i-link href="#" @click.prevent="remove(course)" class="inline-flex btn btn-danger btn-sm"
><svg-sprite src="trash"></svg-sprite
></i-link>
<i-link href="#" @click.prevent="remove(course)" class="inline-flex btn btn-danger btn-sm"><svg-sprite src="trash"></svg-sprite></i-link>
</td>
</tr>
</table>
@ -61,14 +49,11 @@
</template>
<script>
import SidebarHeader from '../../components/SidebarHeader.vue';
export default {
data: function () {
return {
mode: null,
single: null,
indexLinks: [{event: 'create', label: 'Neuer Kurs'}],
};
},
@ -77,9 +62,14 @@ export default {
value: {},
},
components: {SidebarHeader},
methods: {
create() {
this.mode = 'create';
this.single = {};
},
cancel() {
this.mode = this.single = null;
},
remove(payment) {
this.$inertia.delete(`/member/${this.value.id}/course/${payment.id}`);
},

View File

@ -1,34 +1,15 @@
<template>
<div class="sidebar flex flex-col">
<sidebar-header
:links="links"
@create="
mode = 'create';
single = {...def};
"
@close="$emit('close')"
title="Mitgliedschaften"
></sidebar-header>
<div class="sidebar flex flex-col group is-bright">
<page-header @close="$emit('close')" title="Mitgliedschaften">
<template #toolbar>
<page-toolbar-button @click.prevent="create" color="primary" icon="plus" v-if="single === null">Neue Mitgliedschaft</page-toolbar-button>
<page-toolbar-button @click.prevent="cancel" color="primary" icon="undo" v-if="single !== null">Zurück</page-toolbar-button>
</template>
</page-header>
<form v-if="single" class="p-6 grid gap-4 justify-start" @submit.prevent="submit">
<f-select
id="group_id"
name="group_id"
:options="groups"
v-model="single.group_id"
label="Gruppierung"
size="sm"
required
></f-select>
<f-select
id="activity_id"
name="activity_id"
:options="activities"
v-model="single.activity_id"
label="Tätigkeit"
size="sm"
required
></f-select>
<f-select id="group_id" name="group_id" :options="groups" v-model="single.group_id" label="Gruppierung" size="sm" required></f-select>
<f-select id="activity_id" name="activity_id" :options="activities" v-model="single.activity_id" label="Tätigkeit" size="sm" required></f-select>
<f-select
v-if="single.activity_id"
name="subactivity_id"
@ -38,21 +19,8 @@
label="Untertätigkeit"
size="sm"
></f-select>
<f-switch
id="has_promise"
:items="single.promised_at !== null"
@input="single.promised_at = $event ? '2000-02-02' : null"
size="sm"
label="Hat Versprechen"
></f-switch>
<f-text
v-show="single.promised_at !== null"
type="date"
id="promised_at"
v-model="single.promised_at"
label="Versprechensdatum"
size="sm"
></f-text>
<f-switch id="has_promise" :items="single.promised_at !== null" @input="single.promised_at = $event ? '2000-02-02' : null" size="sm" label="Hat Versprechen"></f-switch>
<f-text v-show="single.promised_at !== null" type="date" id="promised_at" v-model="single.promised_at" label="Versprechensdatum" size="sm"></f-text>
<button type="submit" class="btn btn-primary">Absenden</button>
</form>
@ -79,9 +47,7 @@
class="inline-flex btn btn-warning btn-sm"
><svg-sprite src="pencil"></svg-sprite
></a>
<i-link href="#" @click.prevent="remove(membership)" class="inline-flex btn btn-danger btn-sm"
><svg-sprite src="trash"></svg-sprite
></i-link>
<i-link href="#" @click.prevent="remove(membership)" class="inline-flex btn btn-danger btn-sm"><svg-sprite src="trash"></svg-sprite></i-link>
</td>
</tr>
</table>
@ -90,31 +56,33 @@
</template>
<script>
import SidebarHeader from '../../components/SidebarHeader.vue';
export default {
data: function () {
return {
mode: null,
single: null,
links: [{event: 'create', label: 'Neu'}],
};
},
components: {SidebarHeader},
computed: {
def() {
return {
group_id: this.value.group_id,
activity_id: null,
subactivity_id: null,
promised_at: null
promised_at: null,
};
}
},
},
methods: {
create() {
this.mode = 'create';
this.single = {...this.def};
},
cancel() {
this.mode = this.single = null;
},
remove(membership) {
this.$inertia.delete(`/member/${this.value.id}/membership/${membership.id}`);
},

View File

@ -1,33 +1,16 @@
<template>
<div class="sidebar flex flex-col">
<sidebar-header
:links="indexLinks"
@close="$emit('close')"
@create="
mode = 'create';
single = {};
"
title="Zahlungen"
></sidebar-header>
<div class="sidebar flex flex-col group is-bright">
<page-header @close="$emit('close')" title="Zahlungen">
<template #toolbar>
<page-toolbar-button @click.prevent="create" color="primary" icon="plus" v-if="single === null">Neue Zahlung</page-toolbar-button>
<page-toolbar-button @click.prevent="cancel" color="primary" icon="undo" v-if="single !== null">Zurück</page-toolbar-button>
</template>
</page-header>
<form v-if="single" class="p-6 grid gap-4 justify-start" @submit.prevent="submit">
<f-text id="nr" v-model="single.nr" label="Jahr" required></f-text>
<f-select
id="subscription_id"
name="subscription_id"
:options="subscriptions"
v-model="single.subscription_id"
label="Beitrag"
required
></f-select>
<f-select
id="status_id"
name="status_id"
:options="statuses"
v-model="single.status_id"
label="Status"
required
></f-select>
<f-select id="subscription_id" name="subscription_id" :options="subscriptions" v-model="single.subscription_id" label="Beitrag" required></f-select>
<f-select id="status_id" name="status_id" :options="statuses" v-model="single.status_id" label="Status" required></f-select>
<button type="submit" class="btn btn-primary">Absenden</button>
</form>
@ -54,16 +37,8 @@
class="inline-flex btn btn-warning btn-sm"
><svg-sprite src="pencil"></svg-sprite
></a>
<i-link
v-show="!payment.is_accepted"
href="#"
@click.prevent="accept(payment)"
class="inline-flex btn btn-success btn-sm"
><svg-sprite src="check"></svg-sprite
></i-link>
<i-link href="#" @click.prevent="remove(payment)" class="inline-flex btn btn-danger btn-sm"
><svg-sprite src="trash"></svg-sprite
></i-link>
<i-link v-show="!payment.is_accepted" href="#" @click.prevent="accept(payment)" class="inline-flex btn btn-success btn-sm"><svg-sprite src="check"></svg-sprite></i-link>
<i-link href="#" @click.prevent="remove(payment)" class="inline-flex btn btn-danger btn-sm"><svg-sprite src="trash"></svg-sprite></i-link>
</td>
</tr>
</table>
@ -84,20 +59,22 @@
</template>
<script>
import SidebarHeader from '../../components/SidebarHeader.vue';
export default {
data: function () {
return {
mode: null,
single: null,
indexLinks: [{event: 'create', label: 'Neue Zahlung'}],
};
},
components: {SidebarHeader},
methods: {
create() {
this.mode = 'create';
this.single = {};
},
cancel() {
this.mode = this.single = null;
},
remove(payment) {
this.$inertia.delete(`/member/${this.value.id}/payment/${payment.id}`);
},

View File

@ -1,57 +1,57 @@
<template>
<page-layout>
<div class="flex" slot="toolbar">
<toolbar-button :href="meta.links.index" color="primary" icon="undo">zurück</toolbar-button>
<toolbar-button :href="data.links.edit" color="warning" icon="pencil">bearbeiten</toolbar-button>
</div>
<template #toolbar>
<page-toolbar-button :href="meta.links.index" color="primary" icon="undo">zurück</page-toolbar-button>
<page-toolbar-button :href="data.links.edit" color="warning" icon="pencil">bearbeiten</page-toolbar-button>
</template>
<div class="p-3 grid gap-3 this-grid grow">
<box heading="Stammdaten" class="area-stamm hidden xl:block">
<ui-box heading="Stammdaten" class="area-stamm hidden xl:block">
<stamm :inner="inner"></stamm>
</box>
<box heading="Kontakt" class="area-kontakt hidden xl:block">
</ui-box>
<ui-box heading="Kontakt" class="area-kontakt hidden xl:block">
<kontakt :inner="inner"></kontakt>
</box>
<box class="area-stammkontakt block xl:hidden">
</ui-box>
<ui-box class="area-stammkontakt block xl:hidden">
<tabs v-model="tabs.stammkontakt">
<stamm v-show="tabs.stammkontakt.active === 'stamm'" :inner="inner"></stamm>
<kontakt v-show="tabs.stammkontakt.active === 'kontakt'" :inner="inner"></kontakt>
</tabs>
</box>
</ui-box>
<box container-class="" heading="Prävention" class="area-praev hidden xl:block">
<ui-box container-class="" heading="Prävention" class="area-praev hidden xl:block">
<prae :inner="inner"></prae>
</box>
<box heading="System" class="area-system hidden xl:block">
</ui-box>
<ui-box heading="System" class="area-system hidden xl:block">
<system :inner="inner"></system>
</box>
<box class="area-praesystem block xl:hidden">
</ui-box>
<ui-box class="area-praesystem block xl:hidden">
<tabs v-model="tabs.praesystem">
<prae v-show="tabs.praesystem.active === 'prae'" :inner="inner"></prae>
<system v-show="tabs.praesystem.active === 'system'" :inner="inner"></system>
</tabs>
</box>
</ui-box>
<box class="area-membershipcourse hidden xl:block">
<ui-box class="area-membershipcourse hidden xl:block">
<tabs v-model="tabs.membershipcourse">
<courses v-show="tabs.membershipcourse.active === 'course'" :value="inner.courses"></courses>
<memberships v-show="tabs.membershipcourse.active === 'membership'" :value="inner.memberships"></memberships>
</tabs>
</box>
<box heading="Ausbildungen" class="area-courses xl:hidden">
</ui-box>
<ui-box heading="Ausbildungen" class="area-courses xl:hidden">
<courses :value="inner.courses"></courses>
</box>
<box heading="Mitgliedschaften" class="area-memberships xl:hidden">
</ui-box>
<ui-box heading="Mitgliedschaften" class="area-memberships xl:hidden">
<memberships :value="inner.memberships"></memberships>
</box>
</ui-box>
<box heading="Zahlungen" class="area-payments">
<ui-box heading="Zahlungen" class="area-payments">
<payments :value="inner.payments"></payments>
</box>
</ui-box>
<box heading="Karte" container-class="grow" class="area-map hidden xl:flex">
<ui-box heading="Karte" container-class="grow" class="area-map hidden xl:flex">
<vmap v-if="inner.lat && inner.lon" :value="[inner.lat, inner.lon]"></vmap>
<div class="h-full flex items-center justify-center text-gray-400 text-center" v-else>Keine Karte vorhanden</div>
</box>
</ui-box>
</div>
</page-layout>
</template>
@ -95,15 +95,15 @@ export default {
},
components: {
stamm: () => import(/* webpackChunkName: "member" */ './boxes/Stamm'),
kontakt: () => import(/* webpackChunkName: "member" */ './boxes/Kontakt'),
prae: () => import(/* webpackChunkName: "member" */ './boxes/Prae'),
courses: () => import(/* webpackChunkName: "member" */ './boxes/Courses'),
system: () => import(/* webpackChunkName: "member" */ './boxes/System'),
payments: () => import(/* webpackChunkName: "member" */ './boxes/Payments'),
memberships: () => import(/* webpackChunkName: "member" */ './boxes/Memberships'),
vmap: () => import(/* webpackChunkName: "member" */ './boxes/Vmap'),
tabs: () => import(/* webpackChunkName: "member" */ './Tabs'),
stamm: () => import(/* webpackChunkName: "member" */ './boxes/Stamm.vue'),
kontakt: () => import(/* webpackChunkName: "member" */ './boxes/Kontakt.vue'),
prae: () => import(/* webpackChunkName: "member" */ './boxes/Prae.vue'),
courses: () => import(/* webpackChunkName: "member" */ './boxes/Courses.vue'),
system: () => import(/* webpackChunkName: "member" */ './boxes/System.vue'),
payments: () => import(/* webpackChunkName: "member" */ './boxes/Payments.vue'),
memberships: () => import(/* webpackChunkName: "member" */ './boxes/Memberships.vue'),
vmap: () => import(/* webpackChunkName: "member" */ './boxes/Vmap.vue'),
tabs: () => import(/* webpackChunkName: "member" */ './Tabs.vue'),
},
created() {

View File

@ -1,14 +1,7 @@
<template>
<div class="bool-row">
<v-bool
true-comment="Mittendrin abonniert"
false-comment="Mittendrin nicht abonníert"
v-model="member.send_newspaper"
>M</v-bool
>
<v-bool true-comment="In NaMi eingetragen" false-comment="Nicht in NaMi eingetragen" v-model="member.has_nami"
>N</v-bool
>
<ui-bool true-comment="Mittendrin abonniert" false-comment="Mittendrin nicht abonníert" v-model="member.send_newspaper">M</ui-bool>
<ui-bool true-comment="In NaMi eingetragen" false-comment="Nicht in NaMi eingetragen" v-model="member.has_nami">N</ui-bool>
</div>
</template>

View File

@ -1,12 +1,12 @@
<template>
<page-layout>
<div class="flex" slot="toolbar">
<toolbar-button :href="meta.links.index" color="primary" icon="undo">zurück</toolbar-button>
<toolbar-button v-if="mode === 'edit'" :href="data.links.show" color="primary" icon="eye">anschauen</toolbar-button>
</div>
<template #toolbar>
<page-toolbar-button :href="meta.links.index" color="primary" icon="undo">zurück</page-toolbar-button>
<page-toolbar-button v-if="mode === 'edit'" :href="data.links.show" color="primary" icon="eye">anschauen</page-toolbar-button>
</template>
<form class="flex grow relative" id="memberedit" @submit.prevent="submit">
<save-button form="memberedit"></save-button>
<popup heading="Ein Konflikt ist aufgetreten" v-if="conflict === true">
<f-save-button form="memberedit"></f-save-button>
<ui-popup heading="Ein Konflikt ist aufgetreten" v-if="conflict === true">
<div>
<p class="mt-4">Dieses Mitglied wurde vorher bereits aktualisiert. Daher könnte ein Update zu Datenverlust führen.</p>
<p class="mt-2">Wir empfehlen, die Daten aus NaMi zunächst neu zu synchronisieren und dann die Änderungen hier in der Adrema erneut vorzunehmen.</p>
@ -15,11 +15,11 @@
<a href="#" @click.prevent="forceWrite" class="text-center btn btn-danger">Änderungen schreiben</a>
</div>
</div>
</popup>
</ui-popup>
<!-- ***************************** Hauptbereich ****************************** -->
<div class="grow grid md:grid-cols-2 gap-3 p-3">
<box heading="Stammdaten">
<ui-box heading="Stammdaten">
<div class="grid sm:grid-cols-2 gap-3">
<div class="grid grid-cols-2 gap-3">
<f-select id="gender_id" name="gender_id" :options="meta.genders" v-model="inner.gender_id" label="Geschlecht" size="sm"></f-select>
@ -37,8 +37,8 @@
<f-select :options="meta.countries" id="country_id" v-model="inner.country_id" label="Land" name="country_id" size="sm" required></f-select>
<f-text id="other_country" v-model="inner.other_country" label="Andere Staatsangehörigkeit" size="sm"></f-text>
</div>
</box>
<box heading="Kontakt">
</ui-box>
<ui-box heading="Kontakt">
<div class="grid gap-3 sm:grid-cols-2">
<f-text id="main_phone" v-model="inner.main_phone" size="sm" label="Telefon (Eltern)"></f-text>
<f-text id="mobile_phone" v-model="inner.mobile_phone" size="sm" label="Handy (Eltern)"></f-text>
@ -49,8 +49,8 @@
<f-text id="fax" v-model="inner.fax" size="sm" label="Fax"></f-text>
<f-textarea class="sm:col-span-2" rows="3" id="letter_address" v-model="inner.letter_address" label="Brief-Adresse" size="sm"></f-textarea>
</div>
</box>
<box heading="System">
</ui-box>
<ui-box heading="System">
<div class="grid gap-3">
<f-select :options="meta.billKinds" id="bill_kind" v-model="inner.bill_kind" label="Rechnung versenden über" name="bill_kind" size="sm"></f-select>
<f-select :options="meta.subscriptions" id="subscription_id" v-model="inner.subscription_id" label="Beitrag" name="subscription_id" size="sm"></f-select>
@ -80,8 +80,8 @@
></f-select>
</div>
</div>
</box>
<box heading="Prävention">
</ui-box>
<ui-box heading="Prävention">
<div class="grid sm:grid-cols-[minmax(min-content,max-content)_minmax(min-content,max-content)] gap-2">
<div class="grid grid-cols-[minmax(min-content,max-content)_8rem] gap-1">
<f-switch id="has_efz" v-model="hasEfz" size="sm" label="Führungszeugnis eingesehen"></f-switch>
@ -112,7 +112,7 @@
<f-switch id="multiply_more_pv" v-model="inner.multiply_more_pv" label="Multiplikator*in Vertierungsschulung" size="sm"></f-switch>
</div>
</div>
</box>
</ui-box>
</div>
</form>
</page-layout>
@ -155,10 +155,6 @@ export default {
forceWrite() {},
},
components: {
popup: () => import(/* webpackChunkName: "ui" */ '../../components/Ui/Popup.vue'),
},
computed: {
hasEfz: issetComputed('efz'),
hasPs: issetComputed('ps_at'),

View File

@ -1,24 +1,24 @@
<template>
<page-layout page-class="pb-6">
<div class="flex" slot="toolbar">
<toolbar-button :href="data.meta.links.create" color="primary" icon="plus">Mitglied anlegen</toolbar-button>
<toolbar-button :href="data.meta.links.allpayment" color="primary" icon="invoice" v-if="hasModule('bill')">Rechnungen erstellen</toolbar-button>
<toolbar-button :href="data.meta.links.sendpayment" color="info" icon="envelope" v-if="hasModule('bill')">Rechnungen versenden</toolbar-button>
</div>
<popup heading="Mitglied löschen?" v-if="deleting !== null" @close="deleting.reject()">
<template #toolbar>
<page-toolbar-button :href="data.meta.links.create" color="primary" icon="plus">Mitglied anlegen</page-toolbar-button>
<page-toolbar-button :href="data.meta.links.allpayment" color="primary" icon="invoice" v-if="hasModule('bill')">Rechnungen erstellen</page-toolbar-button>
<page-toolbar-button :href="data.meta.links.sendpayment" color="info" icon="envelope" v-if="hasModule('bill')">Rechnungen versenden</page-toolbar-button>
</template>
<ui-popup heading="Mitglied löschen?" v-if="deleting !== null" @close="deleting.reject()">
<div>
<p class="mt-4">Das Mitglied "{{ deleting.member.fullname }}" löschen?</p>
<p class="mt-2">Alle Zuordnungen (Ausbildungen, Rechnungen, Zahlungen, Tätigkeiten) werden ebenfalls entfernt.</p>
<note class="mt-5" type="warning" v-if="!deleting.member.has_nami"> Dieses Mitglied ist nicht in NaMi vorhanden und wird daher nur in der AdReMa gelöscht werden. </note>
<note class="mt-5" type="danger" v-if="deleting.member.has_nami">
<ui-note class="mt-5" type="warning" v-if="!deleting.member.has_nami"> Dieses Mitglied ist nicht in NaMi vorhanden und wird daher nur in der AdReMa gelöscht werden. </ui-note>
<ui-note class="mt-5" type="danger" v-if="deleting.member.has_nami">
Dieses Mitglied ist in NaMi vorhanden und wird daher in NaMi abgemeldet werden. Sofern "Datenweiterverwendung" eingeschaltet ist, wird das Mitglied auf inaktiv gesetzt.
</note>
</ui-note>
<div class="grid grid-cols-2 gap-3 mt-6">
<a href="#" @click.prevent="deleting.resolve()" class="text-center btn btn-danger">Mitglied loschen</a>
<a href="#" @click.prevent="deleting.reject()" class="text-center btn btn-primary">Abbrechen</a>
</div>
</div>
</popup>
</ui-popup>
<div class="px-6 py-2 flex border-b border-gray-600 items-center space-x-3">
<f-text :value="getFilter('search')" @input="setFilter('search', $event)" id="search" name="search" label="Suchen …" size="sm"></f-text>
<f-switch v-show="hasModule('bill')" id="ausstand" @input="setFilter('ausstand', $event)" :items="getFilter('ausstand')" label="Nur Ausstände" size="sm"></f-switch>
@ -78,10 +78,10 @@
<td><tags :member="member"></tags></td>
<td class="hidden xl:table-cell" v-text="member.age"></td>
<td class="hidden xl:table-cell" v-show="hasModule('bill')">
<v-label :value="member.bill_kind_name" fallback="kein"></v-label>
<ui-label :value="member.bill_kind_name" fallback="kein"></ui-label>
</td>
<td v-show="hasModule('bill')">
<v-label :value="member.pending_payment" fallback="---"></v-label>
<ui-label :value="member.pending_payment" fallback="---"></ui-label>
</td>
<td>
<actions :member="member" @sidebar="openSidebar(index, $event)" @remove="remove(member)"></actions>
@ -90,24 +90,24 @@
</table>
<div class="md:hidden p-3 grid gap-3">
<box class="relative" :heading="member.fullname" v-for="(member, index) in data.data" :key="index">
<ui-box class="relative" :heading="member.fullname" v-for="(member, index) in data.data" :key="index">
<div slot="in-title">
<age-groups class="ml-2" :member="member" icon-class="w-4 h-4"></age-groups>
</div>
<div class="text-xs text-gray-200" v-text="member.full_address"></div>
<div class="flex items-center mt-1 space-x-4">
<tags :member="member"></tags>
<v-label class="text-gray-100 block" v-show="hasModule('bill')" :value="member.pending_payment" fallback=""></v-label>
<ui-label class="text-gray-100 block" v-show="hasModule('bill')" :value="member.pending_payment" fallback=""></ui-label>
</div>
<actions class="mt-2" :member="member" @sidebar="openSidebar(index, $event)" @remove="remove(member)"></actions>
<div class="absolute right-0 top-0 h-full flex items-center mr-2">
<i-link :href="member.links.show" v-tooltip="`Details`"><svg-sprite src="chevron-down" class="w-6 h-6 text-teal-100 -rotate-90"></svg-sprite></i-link>
</div>
</box>
</ui-box>
</div>
<div class="px-6">
<v-pages class="mt-4" :value="data.meta" :only="['data']"></v-pages>
<ui-pagination class="mt-4" :value="data.meta" :only="['data']"></ui-pagination>
</div>
<transition name="sidebar">
@ -153,11 +153,9 @@ export default {
MemberMemberships,
MemberPayments,
MemberCourses,
'age-groups': () => import(/* webpackChunkName: "member" */ './AgeGroups'),
'tags': () => import(/* webpackChunkName: "member" */ './Tags'),
'actions': () => import(/* webpackChunkName: "member" */ './index/Actions'),
'popup': () => import(/* webpackChunkName: "ui" */ '../../components/Ui/Popup.vue'),
'note': () => import(/* webpackChunkName: "ui" */ '../../components/Ui/Note.vue'),
'age-groups': () => import('./AgeGroups.vue'),
'tags': () => import('./Tags.vue'),
'actions': () => import('./index/Actions.vue'),
},
methods: {

View File

@ -1,12 +1,6 @@
<template>
<div>
<table
cellspacing="0"
cellpadding="0"
border="0"
class="hidden md:table custom-table overflow-auto custom-table-sm text-sm"
v-if="inner.length"
>
<table cellspacing="0" cellpadding="0" border="0" class="hidden md:table custom-table overflow-auto custom-table-sm text-sm" v-if="inner.length">
<thead>
<th>Datum</th>
<th>Baustein</th>
@ -22,17 +16,11 @@
</table>
<div class="py-3 text-gray-400 text-center" v-else>Keine Ausbildungen vorhanden</div>
<div class="md:hidden grid gap-3">
<box
class="relative"
:heading="course.course.short_name"
v-for="(course, index) in inner"
:key="index"
second
>
<ui-box class="relative" :heading="course.course.short_name" v-for="(course, index) in inner" :key="index" second>
<div class="text-xs text-gray-200" v-text="course.event_name"></div>
<div class="text-xs text-gray-200" v-text="course.completed_at_human"></div>
<div class="text-xs text-gray-200" v-text="course.organizer"></div>
</box>
</ui-box>
</div>
</div>
</template>

View File

@ -1,27 +1,12 @@
<template>
<div class="grid gap-3">
<key-value v-show="inner.main_phone" label="Telefon Eltern" :value="inner.main_phone" type="tel"></key-value>
<key-value v-show="inner.mobile_phone" label="Handy Eltern" :value="inner.mobile_phone" type="tel"></key-value>
<key-value
v-show="inner.work_phone"
label="Telefon Eltern geschäftlich"
:value="inner.work_phone"
type="tel"
></key-value>
<key-value
v-show="inner.children_phone"
label="Telefon Kind"
:value="inner.children_phone"
type="tel"
></key-value>
<key-value v-show="inner.email" label="E-Mail-Adresse Kind" :value="inner.email" type="email"></key-value>
<key-value
v-show="inner.email_parents"
label="E-Mail-Adresse Eltern"
:value="inner.email_parents"
type="email"
></key-value>
<key-value v-show="inner.fax" label="Fax" :value="inner.fax" type="tel"></key-value>
<ui-text-display v-show="inner.main_phone" label="Telefon Eltern" :value="inner.main_phone" type="tel"></ui-text-display>
<ui-text-display v-show="inner.mobile_phone" label="Handy Eltern" :value="inner.mobile_phone" type="tel"></ui-text-display>
<ui-text-display v-show="inner.work_phone" label="Telefon Eltern geschäftlich" :value="inner.work_phone" type="tel"></ui-text-display>
<ui-text-display v-show="inner.children_phone" label="Telefon Kind" :value="inner.children_phone" type="tel"></ui-text-display>
<ui-text-display v-show="inner.email" label="E-Mail-Adresse Kind" :value="inner.email" type="email"></ui-text-display>
<ui-text-display v-show="inner.email_parents" label="E-Mail-Adresse Eltern" :value="inner.email_parents" type="email"></ui-text-display>
<ui-text-display v-show="inner.fax" label="Fax" :value="inner.fax" type="tel"></ui-text-display>
</div>
</template>
@ -30,8 +15,5 @@ export default {
props: {
inner: {},
},
components: {
'key-value': () => import(/* webpackChunkName: "member" */ '../KeyValue'),
},
};
</script>

View File

@ -1,11 +1,6 @@
<template>
<div>
<table
cellspacing="0"
cellpadding="0"
border="0"
class="hidden md:table custom-table overflow-auto custom-table-sm text-sm"
>
<table cellspacing="0" cellpadding="0" border="0" class="hidden md:table custom-table overflow-auto custom-table-sm text-sm">
<thead>
<th>Tätigkeit</th>
<th>Untertätigkeit</th>
@ -19,16 +14,10 @@
</table>
<div class="md:hidden grid gap-3">
<box
class="relative"
:heading="membership.activity_name"
v-for="(membership, index) in inner"
:key="index"
second
>
<ui-box class="relative" :heading="membership.activity_name" v-for="(membership, index) in inner" :key="index" second>
<div class="text-xs text-gray-200" v-text="membership.subactivity_name"></div>
<div class="text-xs text-gray-200" v-text="membership.human_date"></div>
</box>
</ui-box>
</div>
</div>
</template>

View File

@ -14,13 +14,10 @@
</table>
<div class="md:hidden grid gap-3">
<box class="relative" :heading="payment.nr" v-for="(payment, index) in inner" :key="index" second>
<div
class="text-xs text-gray-200"
v-text="`${payment.subscription.name} (${payment.subscription.amount_human})`"
></div>
<ui-box class="relative" :heading="payment.nr" v-for="(payment, index) in inner" :key="index" second>
<div class="text-xs text-gray-200" v-text="`${payment.subscription.name} (${payment.subscription.amount_human})`"></div>
<div class="text-xs text-gray-200" v-text="payment.status_name"></div>
</box>
</ui-box>
</div>
</div>
</template>

View File

@ -1,45 +1,17 @@
<template>
<div class="flex gap-3">
<div class="grid gap-3">
<key-value
class="col-start-1"
label="Führungszeugnis eingesehen"
:value="inner.efz_human ? inner.efz_human : 'nie'"
></key-value>
<key-value
class="col-start-1"
label="Präventionsschulung"
:value="inner.ps_at_human ? inner.ps_at_human : 'nie'"
></key-value>
<key-value
class="col-start-1"
label="Vertiefungsschulung"
:value="inner.more_ps_at_human ? inner.more_ps_at_human : 'nie'"
></key-value>
<key-value
class="col-start-1"
label="Einsatz ohne Schulung"
:value="inner.without_education_at_human ? inner.without_education_at_human : 'nie'"
></key-value>
<key-value
class="col-start-1"
label="Einsatz ohne EFZ"
:value="inner.without_efz_at_human ? inner.without_efz_at_human : 'nie'"
></key-value>
<ui-text-display class="col-start-1" label="Führungszeugnis eingesehen" :value="inner.efz_human ? inner.efz_human : 'nie'"></ui-text-display>
<ui-text-display class="col-start-1" label="Präventionsschulung" :value="inner.ps_at_human ? inner.ps_at_human : 'nie'"></ui-text-display>
<ui-text-display class="col-start-1" label="Vertiefungsschulung" :value="inner.more_ps_at_human ? inner.more_ps_at_human : 'nie'"></ui-text-display>
<ui-text-display class="col-start-1" label="Einsatz ohne Schulung" :value="inner.without_education_at_human ? inner.without_education_at_human : 'nie'"></ui-text-display>
<ui-text-display class="col-start-1" label="Einsatz ohne EFZ" :value="inner.without_efz_at_human ? inner.without_efz_at_human : 'nie'"></ui-text-display>
</div>
<div class="grid gap-3 content-start">
<boolean :value="inner.has_vk" long-label="Verhaltenskodex unterschrieben" label="VK"></boolean>
<boolean :value="inner.has_svk" long-label="SVK unterschrieben" label="SVK"></boolean>
<boolean
:value="inner.multiply_pv"
long-label="Multiplikator*in Präventionsschulung"
label="Multipl. PS"
></boolean>
<boolean
:value="inner.multiply_more_pv"
long-label="Multiplikator*in Vertierungsschulung"
label="Multipl. VS"
></boolean>
<ui-boolean-display :value="inner.has_vk" long-label="Verhaltenskodex unterschrieben" label="VK"></ui-boolean-display>
<ui-boolean-display :value="inner.has_svk" long-label="SVK unterschrieben" label="SVK"></ui-boolean-display>
<ui-boolean-display :value="inner.multiply_pv" long-label="Multiplikator*in Präventionsschulung" label="Multipl. PS"></ui-boolean-display>
<ui-boolean-display :value="inner.multiply_more_pv" long-label="Multiplikator*in Vertierungsschulung" label="Multipl. VS"></ui-boolean-display>
</div>
</div>
</template>
@ -49,9 +21,5 @@ export default {
props: {
inner: {},
},
components: {
'key-value': () => import(/* webpackChunkName: "member" */ '../KeyValue'),
'boolean': () => import(/* webpackChunkName: "member" */ '../Boolean'),
},
};
</script>

View File

@ -1,16 +1,12 @@
<template>
<div class="grid grid-cols-2 gap-3">
<key-value class="col-span-2" label="Name" :value="inner.fullname"></key-value>
<key-value class="col-span-2" label="Adresse" :value="inner.full_address"></key-value>
<key-value label="Geburtsdatum" :value="inner.birthday_human"></key-value>
<key-value label="Alter" :value="inner.age"></key-value>
<key-value label="Bundesland" :value="inner.region.name"></key-value>
<key-value label="Nationalität" :value="inner.nationality.name"></key-value>
<key-value
v-show="inner.other_country"
label="Andere Staatsangehörigkeit"
:value="inner.other_country"
></key-value>
<ui-text-display class="col-span-2" label="Name" :value="inner.fullname"></ui-text-display>
<ui-text-display class="col-span-2" label="Adresse" :value="inner.full_address"></ui-text-display>
<ui-text-display label="Geburtsdatum" :value="inner.birthday_human"></ui-text-display>
<ui-text-display label="Alter" :value="inner.age"></ui-text-display>
<ui-text-display label="Bundesland" :value="inner.region.name"></ui-text-display>
<ui-text-display label="Nationalität" :value="inner.nationality.name"></ui-text-display>
<ui-text-display v-show="inner.other_country" label="Andere Staatsangehörigkeit" :value="inner.other_country"></ui-text-display>
</div>
</template>
@ -19,8 +15,5 @@ export default {
props: {
inner: {},
},
components: {
'key-value': () => import(/* webpackChunkName: "member" */ '../KeyValue'),
},
};
</script>

View File

@ -1,11 +1,11 @@
<template>
<div class="grid gap-3">
<key-value v-show="inner.nami_id" label="NaMi ID" :value="inner.nami_id"></key-value>
<key-value v-show="inner.nami_id" label="NaMi Mitgliedsnummer" :value="inner.mitgliedsnr"></key-value>
<key-value label="Beitrag" :value="inner.subscription ? inner.subscription.name : 'kein'"></key-value>
<key-value v-if="inner.joined_at_human" label="Eintrittsdatum" :value="inner.joined_at_human"></key-value>
<key-value v-if="inner.bill_kind_name" label="Rechnung" :value="inner.bill_kind_name"></key-value>
<boolean :value="inner.send_newspaper" label="Mittendrin versenden"></boolean>
<ui-text-display v-show="inner.nami_id" label="NaMi ID" :value="inner.nami_id"></ui-text-display>
<ui-text-display v-show="inner.nami_id" label="NaMi Mitgliedsnummer" :value="inner.mitgliedsnr"></ui-text-display>
<ui-text-display label="Beitrag" :value="inner.subscription ? inner.subscription.name : 'kein'"></ui-text-display>
<ui-text-display v-if="inner.joined_at_human" label="Eintrittsdatum" :value="inner.joined_at_human"></ui-text-display>
<ui-text-display v-if="inner.bill_kind_name" label="Rechnung" :value="inner.bill_kind_name"></ui-text-display>
<ui-boolean-display :value="inner.send_newspaper" label="Mittendrin versenden"></ui-boolean-display>
</div>
</template>
@ -14,9 +14,5 @@ export default {
props: {
inner: {},
},
components: {
'key-value': () => import(/* webpackChunkName: "member" */ '../KeyValue'),
'boolean': () => import(/* webpackChunkName: "member" */ '../Boolean'),
},
};
</script>

View File

@ -1,6 +1,6 @@
<template>
<form id="billsettingform" class="grow p-6 grid grid-cols-2 gap-3 items-start content-start" @submit.prevent="submit">
<save-button form="billsettingform"></save-button>
<f-save-button form="billsettingform"></f-save-button>
<f-text label="Absender" hint="Absender-Name in Kurzform, i.d.R. der kurze Stammesname" name="from" id="from" v-model="inner.from"></f-text>
<f-text label="Absender (lang)" v-model="inner.from_long" name="from_long" id="from_long" hint="Absender-Name in Langform, i.d.R. der Stammesname"></f-text>
<h2 class="text-lg font-semibold text-gray-300 col-span-2 mt-5">Kontaktdaten</h2>

View File

@ -1,7 +1,7 @@
<template>
<page-layout>
<div class="flex grow relative">
<v-tabs v-model="active" :entries="$page.props.setting_menu"></v-tabs>
<ui-tabs v-model="active" :entries="$page.props.setting_menu"></ui-tabs>
<slot></slot>
</div>
</page-layout>
@ -14,9 +14,6 @@ export default {
innerActive: 0,
};
},
components: {
'v-tabs': () => import('../../components/VTabs.vue'),
},
computed: {
active: {
get() {

View File

@ -1,6 +1,6 @@
<template>
<form id="mailmansettingform" class="grow p-6 grid grid-cols-2 gap-3 items-start content-start" @submit.prevent="submit">
<save-button form="mailmansettingform"></save-button>
<f-save-button form="mailmansettingform"></f-save-button>
<div class="col-span-full text-gray-100 mb-3">
<p class="text-sm">
Scoutrobot kann automatisch Mailinglisten erstellen, wenn es mit einem existierenden

View File

@ -1,19 +1,19 @@
<template>
<page-layout>
<div class="flex" slot="toolbar">
<toolbar-button :href="meta.links.index" color="primary" icon="undo">zurück</toolbar-button>
</div>
<template #toolbar>
<page-toolbar-button :href="meta.links.index" color="primary" icon="undo">zurück</page-toolbar-button>
</template>
<form id="subedit" class="p-3 grid gap-3" @submit.prevent="submit">
<save-button form="subedit"></save-button>
<box heading="Beitrag">
<f-save-button form="subedit"></f-save-button>
<ui-box heading="Beitrag">
<div class="grid gap-4 sm:grid-cols-2">
<f-text id="name" v-model="inner.name" label="Name" size="sm" required></f-text>
<f-select id="fee_id" name="fee_id" :options="fees" v-model="inner.fee_id" label="Nami-Beitrag" size="sm" required></f-select>
<f-switch id="split" label="Rechnung aufsplitten" v-model="inner.split" size="sm"></f-switch>
<f-switch id="for_promise" label="Für Versprechen benutzen" v-model="inner.for_promise" size="sm"></f-switch>
</div>
</box>
<box heading="Positionen">
</ui-box>
<ui-box heading="Positionen">
<div class="flex flex-col space-y-4">
<div v-for="(pos, index) in inner.children" :key="index" class="flex space-x-2 items-end">
<f-text :id="`name-${index}`" v-model="pos.name" label="Name" size="sm" required></f-text>
@ -27,7 +27,7 @@
Position hinzufügen
</a>
</div>
</box>
</ui-box>
</form>
</page-layout>
</template>

View File

@ -1,8 +1,8 @@
<template>
<page-layout>
<div class="flex" slot="toolbar">
<toolbar-button :href="data.meta.links.create" color="primary" icon="plus">Beitrag hinzufügen</toolbar-button>
</div>
<template #toolbar>
<page-toolbar-button :href="data.meta.links.create" color="primary" icon="plus">Beitrag hinzufügen</page-toolbar-button>
</template>
<table cellspacing="0" cellpadding="0" border="0" class="custom-table custom-table-sm">
<thead>
<th>Name</th>

View File

@ -4,8 +4,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<meta name="socketport" content="{{env('SOCKET_PORT')}}" />
<link href="{{ mix('/css/app.css') }}" rel="stylesheet" />
<script src="{{ mix('/js/app.js') }}" defer></script>
@vite('resources/js/app.js')
</head>
<body class="min-h-full flex flex-col">
@inertia

27
vite.config.js vendored Normal file
View File

@ -0,0 +1,27 @@
import {defineConfig} from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue2';
export default defineConfig({
plugins: [
laravel(['resources/js/app.js']),
vue({
template: {
transformAssetUrls: {
// The Vue plugin will re-write asset URLs, when referenced
// in Single File Components, to point to the Laravel web
// server. Setting this to `null` allows the Laravel plugin
// to instead re-write asset URLs to point to the Vite
// server instead.
base: null,
// The Vue plugin will parse absolute URLs and treat them
// as absolute paths to files on disk. Setting this to
// `false` will leave absolute URLs un-touched so they can
// reference assets in the public directory as expected.
includeAbsolute: false,
},
},
}),
],
});