parent
a8b137ef67
commit
c38f92314e
app
resources/js
|
@ -18,7 +18,7 @@ class ContributionController extends Controller
|
|||
session()->put('title', 'Zuschüsse');
|
||||
|
||||
return Inertia::render('contribution/VIndex', [
|
||||
'allMembers' => MemberResource::collection(Member::get()),
|
||||
'allMembers' => MemberResource::collection(Member::slangOrdered()->get()),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
@ -194,6 +194,16 @@ class Member extends Model
|
|||
}
|
||||
|
||||
// ---------------------------------- Scopes -----------------------------------
|
||||
public function scopeOrdered(Builder $q): Builder
|
||||
{
|
||||
return $q->orderByRaw('lastname, firstname');
|
||||
}
|
||||
|
||||
public function scopeSlangOrdered(Builder $q): Builder
|
||||
{
|
||||
return $q->orderByRaw('firstname, lastname');
|
||||
}
|
||||
|
||||
public function scopeWithIsConfirmed(Builder $q): Builder
|
||||
{
|
||||
return $q->selectSub('DATEDIFF(NOW(), IFNULL(confirmed_at, DATE_SUB(NOW(), INTERVAL 3 YEAR))) < 712', 'is_confirmed');
|
||||
|
|
|
@ -1,14 +1,24 @@
|
|||
<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>
|
||||
<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}">
|
||||
<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
|
||||
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>
|
||||
|
@ -23,41 +33,41 @@
|
|||
export default {
|
||||
model: {
|
||||
prop: 'items',
|
||||
event: 'input'
|
||||
event: 'input',
|
||||
},
|
||||
props: {
|
||||
html: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
required: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
inset: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
size: {
|
||||
default: null,
|
||||
required: false
|
||||
required: false,
|
||||
},
|
||||
id: {
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
value: {
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
label: {
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
items: {
|
||||
default: undefined
|
||||
}
|
||||
default: undefined,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
v: {
|
||||
|
@ -71,7 +81,7 @@ export default {
|
|||
return;
|
||||
}
|
||||
|
||||
var a = this.items.filter(i => i !== this.value);
|
||||
var a = this.items.filter((i) => i !== this.value);
|
||||
if (v) {
|
||||
a.push(this.value);
|
||||
}
|
||||
|
@ -88,15 +98,15 @@ export default {
|
|||
}
|
||||
|
||||
return this.items.indexOf(this.value) !== -1;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
created() {
|
||||
if (typeof this.items === 'undefined') {
|
||||
this.$emit('input', false);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
@ -111,7 +121,8 @@ export default {
|
|||
transition: background 0.2s;
|
||||
}
|
||||
|
||||
.display-wrapper, .checkbox-label {
|
||||
.display-wrapper,
|
||||
.checkbox-label {
|
||||
min-height: 34px;
|
||||
}
|
||||
|
||||
|
@ -119,7 +130,7 @@ export default {
|
|||
width: var(--checkbox-width);
|
||||
height: var(--checkbox-width);
|
||||
border-radius: 0.3rem;
|
||||
border: solid 2px hsl(60.0, 1.8%, 10.8%);
|
||||
border: solid 2px hsl(60, 1.8%, 10.8%);
|
||||
.check-icon {
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s;
|
||||
|
|
|
@ -17,10 +17,11 @@
|
|||
:value="value"
|
||||
v-model="v"
|
||||
:disabled="disabled"
|
||||
class="invisible absolute"
|
||||
class="absolute peer"
|
||||
@keypress="$emit('keypress', $event)"
|
||||
/>
|
||||
<span
|
||||
class="relative cursor-pointer flex grow display"
|
||||
class="relative cursor-pointer peer-focus:bg-red-500 flex grow display"
|
||||
:class="{'bg-switch': v === true, 'bg-gray-700': v === false}"
|
||||
>
|
||||
<span
|
||||
|
|
|
@ -5,7 +5,18 @@
|
|||
<span v-show="required" class="text-red-800"> *</span>
|
||||
</span>
|
||||
<div class="real-field-wrap" :class="`size-${size}`">
|
||||
<input :name="name" :type="type" :value="transformedValue" @input="onInput" @change="onChange" :disabled="disabled" :placeholder="placeholder" @focus="onFocus" @blur="onBlur">
|
||||
<input
|
||||
@keypress="$emit('keypress', $event)"
|
||||
:name="name"
|
||||
:type="type"
|
||||
:value="transformedValue"
|
||||
@input="onInput"
|
||||
@change="onChange"
|
||||
:disabled="disabled"
|
||||
:placeholder="placeholder"
|
||||
@focus="onFocus"
|
||||
@blur="onBlur"
|
||||
/>
|
||||
<div v-if="hint" class="info-wrap">
|
||||
<div v-tooltip="hint">
|
||||
<svg-sprite src="info-button" class="info-button"></svg-sprite>
|
||||
|
@ -28,7 +39,7 @@ var numb = {
|
|||
},
|
||||
encoder(a) {
|
||||
return a / 100;
|
||||
}
|
||||
},
|
||||
}),
|
||||
naturalRaw: wNumb({
|
||||
mark: '',
|
||||
|
@ -39,7 +50,7 @@ var numb = {
|
|||
},
|
||||
encoder(a) {
|
||||
return a / 100;
|
||||
}
|
||||
},
|
||||
}),
|
||||
naturalDetailRaw: wNumb({
|
||||
mark: '',
|
||||
|
@ -50,7 +61,7 @@ var numb = {
|
|||
},
|
||||
encoder(a) {
|
||||
return a / 10000;
|
||||
}
|
||||
},
|
||||
}),
|
||||
area: wNumb({
|
||||
mark: ',',
|
||||
|
@ -61,7 +72,7 @@ var numb = {
|
|||
},
|
||||
encoder(a) {
|
||||
return a / 100;
|
||||
}
|
||||
},
|
||||
}),
|
||||
areaDetail: wNumb({
|
||||
mark: ',',
|
||||
|
@ -72,7 +83,7 @@ var numb = {
|
|||
},
|
||||
encoder(a) {
|
||||
return a / 10000;
|
||||
}
|
||||
},
|
||||
}),
|
||||
twoDecimalRaw: wNumb({
|
||||
mark: ',',
|
||||
|
@ -83,7 +94,7 @@ var numb = {
|
|||
},
|
||||
encoder(a) {
|
||||
return a / 100;
|
||||
}
|
||||
},
|
||||
}),
|
||||
fourDecimalRaw: wNumb({
|
||||
mark: ',',
|
||||
|
@ -94,142 +105,198 @@ var numb = {
|
|||
},
|
||||
encoder(a) {
|
||||
return a / 10000;
|
||||
}
|
||||
})
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
var transformers = {
|
||||
none: {
|
||||
display: {
|
||||
to(v) { return v; },
|
||||
from(v) { return v; }
|
||||
to(v) {
|
||||
return v;
|
||||
},
|
||||
from(v) {
|
||||
return v;
|
||||
},
|
||||
},
|
||||
edit: {
|
||||
to(v) { return v; },
|
||||
from(v) { return v; }
|
||||
}
|
||||
to(v) {
|
||||
return v;
|
||||
},
|
||||
from(v) {
|
||||
return v;
|
||||
},
|
||||
},
|
||||
},
|
||||
natural: {
|
||||
display: {
|
||||
to(v) { return isNaN(parseInt(v)) ? '' : numb.natural.to(v); },
|
||||
from(v) { return v === '' ? null : numb.natural.from(v); }
|
||||
to(v) {
|
||||
return isNaN(parseInt(v)) ? '' : numb.natural.to(v);
|
||||
},
|
||||
from(v) {
|
||||
return v === '' ? null : numb.natural.from(v);
|
||||
},
|
||||
},
|
||||
edit: {
|
||||
to(v) { return isNaN(parseInt(v)) ? '' : numb.naturalRaw.to(v); },
|
||||
from(v) { return v === '' ? null : numb.naturalRaw.from(v); }
|
||||
}
|
||||
to(v) {
|
||||
return isNaN(parseInt(v)) ? '' : numb.naturalRaw.to(v);
|
||||
},
|
||||
from(v) {
|
||||
return v === '' ? null : numb.naturalRaw.from(v);
|
||||
},
|
||||
},
|
||||
},
|
||||
area: {
|
||||
display: {
|
||||
to(v) { return v === null ? '' : numb.area.to(v); },
|
||||
from(v) { return v === '' ? null : numb.area.from(v); }
|
||||
to(v) {
|
||||
return v === null ? '' : numb.area.to(v);
|
||||
},
|
||||
from(v) {
|
||||
return v === '' ? null : numb.area.from(v);
|
||||
},
|
||||
},
|
||||
edit: {
|
||||
to(v) {
|
||||
if (v === null) { return ''; }
|
||||
if (Math.round(v / 100) * 100 === v) { return numb.naturalRaw.to(v); }
|
||||
if (v === null) {
|
||||
return '';
|
||||
}
|
||||
if (Math.round(v / 100) * 100 === v) {
|
||||
return numb.naturalRaw.to(v);
|
||||
}
|
||||
return numb.twoDecimalRaw.to(v);
|
||||
},
|
||||
from(v) {
|
||||
if (v === '') { return null; }
|
||||
if (v.indexOf(',') === -1) { return numb.naturalRaw.from(v); }
|
||||
if (v === '') {
|
||||
return null;
|
||||
}
|
||||
if (v.indexOf(',') === -1) {
|
||||
return numb.naturalRaw.from(v);
|
||||
}
|
||||
|
||||
return numb.twoDecimalRaw.from(v);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
currency: {
|
||||
display: {
|
||||
to(v) { return v === null ? '' : numb.area.to(v); },
|
||||
from(v) { return v === '' ? null : numb.area.from(v); }
|
||||
to(v) {
|
||||
return v === null ? '' : numb.area.to(v);
|
||||
},
|
||||
from(v) {
|
||||
return v === '' ? null : numb.area.from(v);
|
||||
},
|
||||
},
|
||||
edit: {
|
||||
to(v) {
|
||||
if (v === null) { return ''; }
|
||||
if (Math.round(v / 100) * 100 === v) { return numb.naturalRaw.to(v); }
|
||||
if (v === null) {
|
||||
return '';
|
||||
}
|
||||
if (Math.round(v / 100) * 100 === v) {
|
||||
return numb.naturalRaw.to(v);
|
||||
}
|
||||
return numb.twoDecimalRaw.to(v);
|
||||
},
|
||||
from(v) {
|
||||
if (v === '') { return null; }
|
||||
if (v.indexOf(',') === -1) { return numb.naturalRaw.from(v); }
|
||||
if (v === '') {
|
||||
return null;
|
||||
}
|
||||
if (v.indexOf(',') === -1) {
|
||||
return numb.naturalRaw.from(v);
|
||||
}
|
||||
|
||||
return numb.twoDecimalRaw.from(v);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
currencyDetail: {
|
||||
display: {
|
||||
to(v) { return v === null ? '' : numb.areaDetail.to(v); },
|
||||
from(v) { return v === '' ? null : numb.areaDetail.from(v); }
|
||||
to(v) {
|
||||
return v === null ? '' : numb.areaDetail.to(v);
|
||||
},
|
||||
from(v) {
|
||||
return v === '' ? null : numb.areaDetail.from(v);
|
||||
},
|
||||
},
|
||||
edit: {
|
||||
to(v) {
|
||||
if (v === null) { return ''; }
|
||||
if (Math.round(v / 10000) * 10000 === v) { return numb.naturalDetailRaw.to(v); }
|
||||
if (v === null) {
|
||||
return '';
|
||||
}
|
||||
if (Math.round(v / 10000) * 10000 === v) {
|
||||
return numb.naturalDetailRaw.to(v);
|
||||
}
|
||||
return numb.fourDecimalRaw.to(v);
|
||||
},
|
||||
from(v) {
|
||||
if (v === '') { return null; }
|
||||
if (v.indexOf(',') === -1) { return numb.naturalDetailRaw.from(v); }
|
||||
if (v === '') {
|
||||
return null;
|
||||
}
|
||||
if (v.indexOf(',') === -1) {
|
||||
return numb.naturalDetailRaw.from(v);
|
||||
}
|
||||
|
||||
return numb.fourDecimalRaw.from(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
data: function() {
|
||||
data: function () {
|
||||
return {
|
||||
focus: false
|
||||
focus: false,
|
||||
};
|
||||
},
|
||||
props: {
|
||||
placeholder: {
|
||||
default: function() {
|
||||
default: function () {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
mode: {
|
||||
default: function() { return 'none'; }
|
||||
default: function () {
|
||||
return 'none';
|
||||
},
|
||||
},
|
||||
required: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
inset: {
|
||||
default: function() {
|
||||
default: function () {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
},
|
||||
size: {
|
||||
default: function() {
|
||||
default: function () {
|
||||
return 'base';
|
||||
}
|
||||
},
|
||||
},
|
||||
id: {
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
hint: {
|
||||
default: null
|
||||
default: null,
|
||||
},
|
||||
value: {
|
||||
default: undefined
|
||||
default: undefined,
|
||||
},
|
||||
mask: {
|
||||
default: undefined
|
||||
default: undefined,
|
||||
},
|
||||
label: {
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
type: {
|
||||
required: false,
|
||||
default: function() { return 'text'; }
|
||||
default: function () {
|
||||
return 'text';
|
||||
},
|
||||
},
|
||||
disabled: {
|
||||
default: false,
|
||||
type: Boolean
|
||||
type: Boolean,
|
||||
},
|
||||
name: {},
|
||||
},
|
||||
|
@ -249,7 +316,7 @@ export default {
|
|||
if (this.mode === 'none') {
|
||||
this.transformedValue = v.target.value;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
transformedValue: {
|
||||
|
@ -258,25 +325,35 @@ export default {
|
|||
},
|
||||
set(v) {
|
||||
this.$emit('input', transformers[this.mode][this.focus ? 'edit' : 'display'].from(v));
|
||||
}
|
||||
},
|
||||
},
|
||||
insetClass() {
|
||||
if (this.inset === '') { return 'bg-inset'; }
|
||||
if (this.inset === undefined) { return null; }
|
||||
if (this.inset === '') {
|
||||
return 'bg-inset';
|
||||
}
|
||||
if (this.inset === undefined) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return `bg-${this.inset}`;
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
if (typeof this.value === 'undefined') {
|
||||
this.$emit('input', this.default === undefined ? '' : this.default);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scope>
|
||||
.bg-inset {
|
||||
background: linear-gradient(to bottom, hsl(247.5, 66.7%, 97.6%) 0%, hsl(247.5, 66.7%, 97.6%) 41%, hsl(0deg 0% 100%) 41%, hsl(180deg 0% 100%) 100%);
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
hsl(247.5, 66.7%, 97.6%) 0%,
|
||||
hsl(247.5, 66.7%, 97.6%) 41%,
|
||||
hsl(0deg 0% 100%) 41%,
|
||||
hsl(180deg 0% 100%) 100%
|
||||
);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -18,16 +18,29 @@
|
|||
required
|
||||
></f-text>
|
||||
|
||||
<div class="col-span-2">
|
||||
<f-switch
|
||||
:id="`members-${member.id}`"
|
||||
:key="member.id"
|
||||
:label="`${member.firstname} ${member.lastname}`"
|
||||
v-for="member in allMembers"
|
||||
name="members[]"
|
||||
:value="member.id"
|
||||
v-model="values.members"
|
||||
></f-switch>
|
||||
<div class="border-gray-200 shadow shadow-primary-700 p-3 shadow-[0_0_4px_gray] col-span-2">
|
||||
<f-text
|
||||
class="col-span-2"
|
||||
id="membersearch"
|
||||
name="membersearch"
|
||||
v-model="membersearch"
|
||||
label="Suchen …"
|
||||
size="sm"
|
||||
ref="membersearchfield"
|
||||
@keypress.enter.prevent="onSubmitFirstMemberResult"
|
||||
></f-text>
|
||||
<div class="mt-2 grid grid-cols-[repeat(auto-fill,minmax(160px,1fr))] gap-2 col-span-2">
|
||||
<f-switch
|
||||
:id="`members-${member.id}`"
|
||||
:key="member.id"
|
||||
:label="`${member.firstname} ${member.lastname}`"
|
||||
v-for="member in memberResults"
|
||||
name="members[]"
|
||||
:value="member.id"
|
||||
v-model="values.members"
|
||||
@keypress.enter.prevent="onSubmitMemberResult(member)"
|
||||
></f-switch>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
|
@ -46,6 +59,7 @@
|
|||
export default {
|
||||
data: function () {
|
||||
return {
|
||||
membersearch: '',
|
||||
values: {
|
||||
members: [],
|
||||
event_name: '',
|
||||
|
@ -57,5 +71,39 @@ export default {
|
|||
props: {
|
||||
allMembers: {},
|
||||
},
|
||||
computed: {
|
||||
memberResults() {
|
||||
if (this.membersearch.length === 0) {
|
||||
return this.allMembers;
|
||||
}
|
||||
|
||||
return this.allMembers.filter(
|
||||
(member) =>
|
||||
(member.firstname + ' ' + member.lastname)
|
||||
.toLowerCase()
|
||||
.indexOf(this.membersearch.toLowerCase()) !== -1
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onSubmitMemberResult(selected) {
|
||||
if (this.values.members.find((m) => m === selected.id) !== undefined) {
|
||||
this.values.members = this.values.members.filter((m) => m === selected.id);
|
||||
} else {
|
||||
this.values.members.push(selected.id);
|
||||
}
|
||||
|
||||
this.membersearch = '';
|
||||
this.$refs.membersearchfield.$el.querySelector('input').focus();
|
||||
},
|
||||
onSubmitFirstMemberResult() {
|
||||
if (this.memberResults.length === 0) {
|
||||
this.membersearch = '';
|
||||
return;
|
||||
}
|
||||
|
||||
this.onSubmitMemberResult(this.memberResults[0]);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
Loading…
Reference in New Issue