Add DV zuschuss

This commit is contained in:
philipp lang 2022-08-23 23:49:19 +02:00
parent 9d53dfc772
commit 5eee14e0de
20 changed files with 442 additions and 91 deletions

View File

@ -2,6 +2,7 @@
namespace App\Contribution; namespace App\Contribution;
use App\Country;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Member\Member; use App\Member\Member;
use App\Member\MemberResource; use App\Member\MemberResource;
@ -19,6 +20,8 @@ class ContributionController extends Controller
return Inertia::render('contribution/VIndex', [ return Inertia::render('contribution/VIndex', [
'allMembers' => MemberResource::collection(Member::slangOrdered()->get()), 'allMembers' => MemberResource::collection(Member::slangOrdered()->get()),
'countries' => Country::pluck('name', 'id'),
'defaultCountry' => Country::firstWhere('name', 'Deutschland')->id,
]); ]);
} }

110
app/Contribution/DvData.php Normal file
View File

@ -0,0 +1,110 @@
<?php
namespace App\Contribution;
use App\Country;
use App\Member\Member;
use App\Pdf\EnvType;
use App\Pdf\PdfRepository;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\Request;
use Spatie\LaravelData\Data;
class DvData extends Data implements PdfRepository
{
public function __construct(
public string $dateFrom,
public string $dateUntil,
public string $zipLocation,
public ?Country $country,
public array $members,
public ?string $filename = '',
public $type = 'F',
) {
}
public static function fromRequest(Request $request): self
{
return new self(
dateFrom: $request->dateFrom,
dateUntil: $request->dateUntil,
zipLocation: $request->zipLocation,
country: Country::findOrFail($request->country),
members: $request->members,
);
}
public function members(): Collection
{
return Member::whereIn('id', $this->members)->orderByRaw('lastname, firstname')->get();
}
public function memberShort(Member $member): string
{
return $member->isLeader() ? 'L' : '';
}
public function memberName(Member $member): string
{
return $member->lastname.', '.$member->firstname;
}
public function memberAddress(Member $member): string
{
return $member->fullAddress;
}
public function memberGender(Member $member): string
{
if (!$member->gender) {
return '';
}
return strtolower(substr($member->gender->name, 0, 1));
}
public function memberAge(Member $member): string
{
return (string) $member->getAge();
}
public function countryName(): string
{
return $this->country->name;
}
public function dateRange(): string
{
return Carbon::parse($this->dateFrom)->format('d.m.Y')
.' - '
.Carbon::parse($this->dateUntil)->format('d.m.Y');
}
public function getFilename(): string
{
return 'zuschuesse-dv';
}
public function getView(): string
{
return 'tex.zuschuss-dv';
}
public function getTemplate(): ?string
{
return 'zuschussdv';
}
public function setFilename(string $filename): static
{
$this->filename = $filename;
return $this;
}
public function getScript(): EnvType
{
return EnvType::PDFLATEX;
}
}

View File

@ -73,9 +73,9 @@ class SolingenData extends Data implements PdfRepository
return 'tex.zuschuss-stadt'; return 'tex.zuschuss-stadt';
} }
public function getTemplate(): string public function getTemplate(): ?string
{ {
return 'efz'; return null;
} }
public function setFilename(string $filename): static public function setFilename(string $filename): static

View File

@ -91,9 +91,14 @@ class Member extends Model
return $this->firstname.' '.$this->lastname; return $this->firstname.' '.$this->lastname;
} }
public function getFullAddressAttribute(): string
{
return $this->address.', '.$this->zip.' '.$this->location;
}
public function getEfzLink(): ?string public function getEfzLink(): ?string
{ {
return $this->memberships()->whereHas('activity', fn (Builder $query) => $query->where('has_efz', true))->exists() return $this->isLeader()
? route('efz', ['member' => $this]) ? route('efz', ['member' => $this])
: null; : null;
} }
@ -120,6 +125,16 @@ class Member extends Model
return $this->subscription->fee->nami_id; return $this->subscription->fee->nami_id;
} }
public function isLeader(): bool
{
return $this->memberships()->whereHas('activity', fn (Builder $query) => $query->where('has_efz', true))->exists();
}
public function getAge(): int
{
return $this->birthday->diffInYears(now());
}
// ---------------------------------- Relations ---------------------------------- // ---------------------------------- Relations ----------------------------------
public function country(): BelongsTo public function country(): BelongsTo
{ {

View File

@ -71,7 +71,7 @@ class MemberResource extends JsonResource
'without_efz_at' => $this->without_efz_at, 'without_efz_at' => $this->without_efz_at,
'multiply_pv' => $this->multiply_pv, 'multiply_pv' => $this->multiply_pv,
'multiply_more_pv' => $this->multiply_more_pv, 'multiply_more_pv' => $this->multiply_more_pv,
'age' => $this->birthday->diffInYears(now()), 'age' => $this->getModel()->getAge(),
]; ];
} }
} }

View File

@ -47,7 +47,7 @@ class BillType extends Repository implements LetterRepository
return 'tex.bill'; return 'tex.bill';
} }
public function getTemplate(): string public function getTemplate(): ?string
{ {
return 'default'; return 'default';
} }

View File

@ -49,7 +49,7 @@ class MemberEfzData extends Data implements PdfRepository
return 'tex.efz'; return 'tex.efz';
} }
public function getTemplate(): string public function getTemplate(): ?string
{ {
return 'efz'; return 'efz';
} }

View File

@ -27,7 +27,9 @@ class PdfGenerator implements Responsable
Storage::disk('temp')->put($this->dir.'/'.$this->repo->getFilename().'.tex', $this->compileView()); Storage::disk('temp')->put($this->dir.'/'.$this->repo->getFilename().'.tex', $this->compileView());
Storage::disk('temp')->makeDirectory($this->dir); Storage::disk('temp')->makeDirectory($this->dir);
$this->copyTemplateTo(Storage::disk('temp')->path($this->dir)); if ($this->repo->getTemplate()) {
$this->copyTemplateTo(Storage::disk('temp')->path($this->dir));
}
$command = 'cd '.Storage::disk('temp')->path($this->dir); $command = 'cd '.Storage::disk('temp')->path($this->dir);
$command .= ' && '.env($this->repo->getScript()->value).' --halt-on-error '.$this->repo->getFilename().'.tex'; $command .= ' && '.env($this->repo->getScript()->value).' --halt-on-error '.$this->repo->getFilename().'.tex';

View File

@ -10,7 +10,7 @@ interface PdfRepository
public function getView(): string; public function getView(): string;
public function getTemplate(): string; public function getTemplate(): ?string;
public function getScript(): EnvType; public function getScript(): EnvType;
} }

View File

@ -47,7 +47,7 @@ class RememberType extends Repository implements LetterRepository
return 'tex.remember'; return 'tex.remember';
} }
public function getTemplate(): string public function getTemplate(): ?string
{ {
return 'default'; return 'default';
} }

View File

@ -5,7 +5,7 @@
<span v-show="required" class="text-red-800">&nbsp;*</span> <span v-show="required" class="text-red-800">&nbsp;*</span>
</span> </span>
<div class="real-field-wrap" :class="`size-${size}`"> <div class="real-field-wrap" :class="`size-${size}`">
<select :disabled="disabled" :value="value" @change="trigger"> <select :disabled="disabled" :name="name" :value="value" @change="trigger">
<option v-if="placeholder" v-html="placeholder" :value="null"></option> <option v-if="placeholder" v-html="placeholder" :value="null"></option>
<option <option
@ -74,6 +74,9 @@ export default {
type: Number, type: Number,
default: -1, default: -1,
}, },
name: {
required: true,
},
hint: {}, hint: {},
options: { options: {
default: function () { default: function () {

View File

@ -18,6 +18,16 @@
required required
></f-text> ></f-text>
<f-text id="zipLocation" name="zipLocation" v-model="values.zipLocation" label="PLZ / Ort" required></f-text>
<f-select
id="country"
:options="countries"
name="country"
v-model="values.country"
label="Land"
required
></f-select>
<div class="border-gray-200 shadow shadow-primary-700 p-3 shadow-[0_0_4px_gray] col-span-2"> <div class="border-gray-200 shadow shadow-primary-700 p-3 shadow-[0_0_4px_gray] col-span-2">
<f-text <f-text
class="col-span-2" class="col-span-2"
@ -52,6 +62,15 @@
> >
Für Stadt erstellen Für Stadt erstellen
</button> </button>
<button
target="_BLANK"
type="submit"
name="type"
value="\App\Contribution\DvData"
class="btn btn-primary mt-3 inline-block"
>
Für DV erstellen
</button>
</form> </form>
</template> </template>
@ -65,10 +84,14 @@ export default {
event_name: '', event_name: '',
dateFrom: '', dateFrom: '',
dateUntil: '', dateUntil: '',
zipLocation: '',
country: null,
}, },
}; };
}, },
props: { props: {
countries: {},
defaultCountry: {},
allMembers: {}, allMembers: {},
}, },
computed: { computed: {
@ -105,5 +128,9 @@ export default {
this.onSubmitMemberResult(this.memberResults[0]); this.onSubmitMemberResult(this.memberResults[0]);
}, },
}, },
created() {
this.values.country = this.defaultCountry;
},
}; };
</script> </script>

View File

@ -1,10 +1,25 @@
<template> <template>
<div class="sidebar flex flex-col"> <div class="sidebar flex flex-col">
<sidebar-header :links="indexLinks" @close="$emit('close')" @create="mode = 'create'; single = {}" title="Ausbildungen"></sidebar-header> <sidebar-header
:links="indexLinks"
@close="$emit('close')"
@create="
mode = 'create';
single = {};
"
title="Ausbildungen"
></sidebar-header>
<form v-if="single" class="p-6 grid gap-4 justify-start" @submit.prevent="submit"> <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-text id="completed_at" type="date" v-model="single.completed_at" label="Datum" required></f-text>
<f-select id="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="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> <f-text id="organizer" v-model="single.organizer" label="Veranstalter" required></f-text>
<button type="submit" class="btn btn-primary">Absenden</button> <button type="submit" class="btn btn-primary">Absenden</button>
@ -20,14 +35,24 @@
<th></th> <th></th>
</thead> </thead>
<tr v-for="course, index in value.courses" :key="index"> <tr v-for="(course, index) in value.courses" :key="index">
<td v-text="course.course_name"></td> <td v-text="course.course_name"></td>
<td v-text="course.event_name"></td> <td v-text="course.event_name"></td>
<td v-text="course.organizer"></td> <td v-text="course.organizer"></td>
<td v-text="course.completed_at_human"></td> <td v-text="course.completed_at_human"></td>
<td class="flex"> <td class="flex">
<a href="#" @click.prevent="single = course; mode = 'edit'" class="inline-flex btn btn-warning btn-sm"><svg-sprite src="pencil"></svg-sprite></a> <a
<i-link href="#" @click.prevent="remove(course)" class="inline-flex btn btn-danger btn-sm"><svg-sprite src="trash"></svg-sprite></i-link> href="#"
@click.prevent="
single = course;
mode = 'edit';
"
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>
</td> </td>
</tr> </tr>
</table> </table>
@ -39,22 +64,20 @@
import SidebarHeader from '../../components/SidebarHeader.vue'; import SidebarHeader from '../../components/SidebarHeader.vue';
export default { export default {
data: function() { data: function () {
return { return {
mode: null, mode: null,
single: null, single: null,
indexLinks: [ indexLinks: [{event: 'create', label: 'Neuer Kurs'}],
{event: 'create', label: 'Neuer Kurs'}
]
}; };
}, },
props: { props: {
courses: {}, courses: {},
value: {} value: {},
}, },
components: { SidebarHeader }, components: {SidebarHeader},
methods: { methods: {
remove(payment) { remove(payment) {
@ -72,18 +95,18 @@ export default {
submit() { submit() {
var _self = this; var _self = this;
this.mode === 'create' this.mode === 'create'
? this.$inertia.post(`/member/${this.value.id}/course`, this.single, { ? this.$inertia.post(`/member/${this.value.id}/course`, this.single, {
onFinish() { onFinish() {
_self.single = null; _self.single = null;
} },
}) })
: this.$inertia.patch(`/member/${this.value.id}/course/${this.single.id}`, this.single, { : this.$inertia.patch(`/member/${this.value.id}/course/${this.single.id}`, this.single, {
onFinish() { onFinish() {
_self.single = null; _self.single = null;
} },
}); });
} },
} },
}; };
</script> </script>

View File

@ -1,9 +1,41 @@
<template> <template>
<div class="px-6 py-2 flex border-b border-gray-600 space-x-3"> <div class="px-6 py-2 flex border-b border-gray-600 space-x-3">
<f-switch v-show="hasModule('bill')" id="ausstand" @input="reload" v-model="inner.ausstand" label="Nur Ausstände" size="sm"></f-switch> <f-switch
<f-select v-show="hasModule('bill')" id="billKinds" @input="reload" :options="billKinds" v-model="inner.bill_kind" label="Rechnung" size="sm"></f-select> v-show="hasModule('bill')"
<f-select id="activity_id" @input="reload" :options="activities" v-model="inner.activity_id" label="Tätigkeit" size="sm"></f-select> id="ausstand"
<f-select id="subactivity_id" @input="reload" :options="subactivities" v-model="inner.subactivity_id" label="Untertätigkeit" size="sm"></f-select> @input="reload"
v-model="inner.ausstand"
label="Nur Ausstände"
size="sm"
></f-switch>
<f-select
v-show="hasModule('bill')"
name="billKinds"
id="billKinds"
@input="reload"
:options="billKinds"
v-model="inner.bill_kind"
label="Rechnung"
size="sm"
></f-select>
<f-select
id="activity_id"
@input="reload"
:options="activities"
v-model="inner.activity_id"
label="Tätigkeit"
size="sm"
name="activity_id"
></f-select>
<f-select
id="subactivity_id"
@input="reload"
:options="subactivities"
v-model="inner.subactivity_id"
label="Untertätigkeit"
size="sm"
name="subactivity_id"
></f-select>
</div> </div>
</template> </template>
@ -11,10 +43,9 @@
import mergesQueryString from '../../mixins/mergesQueryString.js'; import mergesQueryString from '../../mixins/mergesQueryString.js';
export default { export default {
data: function () {
data: function() {
return { return {
inner: {} inner: {},
}; };
}, },
@ -30,14 +61,13 @@ export default {
methods: { methods: {
reload() { reload() {
this.$inertia.visit(this.qs({filter: JSON.stringify(this.inner)}), { this.$inertia.visit(this.qs({filter: JSON.stringify(this.inner)}), {
preserveState: true preserveState: true,
}); });
} },
}, },
created() { created() {
this.inner = this.value; this.inner = this.value;
} },
}; };
</script> </script>

View File

@ -1,10 +1,32 @@
<template> <template>
<div class="sidebar flex flex-col"> <div class="sidebar flex flex-col">
<sidebar-header :links="links" @create="mode = 'create'; single = {}" @close="$emit('close')" title="Mitgliedschaften"></sidebar-header> <sidebar-header
:links="links"
@create="
mode = 'create';
single = {};
"
@close="$emit('close')"
title="Mitgliedschaften"
></sidebar-header>
<form v-if="single" class="p-6 grid gap-4 justify-start" @submit.prevent="submit"> <form v-if="single" class="p-6 grid gap-4 justify-start" @submit.prevent="submit">
<f-select id="activity_id" :options="activities" v-model="single.activity_id" label="Tätigkeit" required></f-select> <f-select
<f-select v-if="single.activity_id" :options="subactivities[single.activity_id]" id="subactivity_id" v-model="single.subactivity_id" label="Untertätigkeit"></f-select> id="activity_id"
name="activity_id"
:options="activities"
v-model="single.activity_id"
label="Tätigkeit"
required
></f-select>
<f-select
v-if="single.activity_id"
name="subactivity_id"
:options="subactivities[single.activity_id]"
id="subactivity_id"
v-model="single.subactivity_id"
label="Untertätigkeit"
></f-select>
<button type="submit" class="btn btn-primary">Absenden</button> <button type="submit" class="btn btn-primary">Absenden</button>
</form> </form>
@ -17,13 +39,23 @@
<th></th> <th></th>
</thead> </thead>
<tr v-for="membership, index in value.memberships" :key="index"> <tr v-for="(membership, index) in value.memberships" :key="index">
<td v-text="membership.activity_name"></td> <td v-text="membership.activity_name"></td>
<td v-text="membership.subactivity_name"></td> <td v-text="membership.subactivity_name"></td>
<td v-text="membership.human_date"></td> <td v-text="membership.human_date"></td>
<td class="flex"> <td class="flex">
<a href="#" @click.prevent="single = membership; mode = 'edit'" class="inline-flex btn btn-warning btn-sm"><svg-sprite src="pencil"></svg-sprite></a> <a
<i-link href="#" @click.prevent="remove(membership)" class="inline-flex btn btn-danger btn-sm"><svg-sprite src="trash"></svg-sprite></i-link> href="#"
@click.prevent="
single = membership;
mode = 'edit';
"
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>
</td> </td>
</tr> </tr>
</table> </table>
@ -35,17 +67,15 @@
import SidebarHeader from '../../components/SidebarHeader.vue'; import SidebarHeader from '../../components/SidebarHeader.vue';
export default { export default {
data: function() { data: function () {
return { return {
mode: null, mode: null,
single: null, single: null,
links: [ links: [{event: 'create', label: 'Neu'}],
{ event: 'create', label: 'Neu' }
]
}; };
}, },
components: { SidebarHeader }, components: {SidebarHeader},
methods: { methods: {
remove(membership) { remove(membership) {
@ -53,7 +83,7 @@ export default {
}, },
accept(payment) { accept(payment) {
this.$inertia.patch(`/member/${this.value.id}/payment/${payment.id}`, { ...payment, status_id: 3 }); this.$inertia.patch(`/member/${this.value.id}/payment/${payment.id}`, {...payment, status_id: 3});
}, },
openLink(link) { openLink(link) {
@ -71,19 +101,19 @@ export default {
onFinish() { onFinish() {
_self.single = null; _self.single = null;
_self.mode = null; _self.mode = null;
} },
}; };
this.mode === 'create' this.mode === 'create'
? this.$inertia.post(`/member/${this.value.id}/membership`, this.single, options) ? this.$inertia.post(`/member/${this.value.id}/membership`, this.single, options)
: this.$inertia.patch(`/member/${this.value.id}/membership/${this.single.id}`, this.single, options); : this.$inertia.patch(`/member/${this.value.id}/membership/${this.single.id}`, this.single, options);
} },
}, },
props: { props: {
value: {}, value: {},
activities: {}, activities: {},
subactivities: {}, subactivities: {},
} },
}; };
</script> </script>

View File

@ -1,11 +1,33 @@
<template> <template>
<div class="sidebar flex flex-col"> <div class="sidebar flex flex-col">
<sidebar-header :links="indexLinks" @close="$emit('close')" @create="mode = 'create'; single = {}" title="Zahlungen"></sidebar-header> <sidebar-header
:links="indexLinks"
@close="$emit('close')"
@create="
mode = 'create';
single = {};
"
title="Zahlungen"
></sidebar-header>
<form v-if="single" class="p-6 grid gap-4 justify-start" @submit.prevent="submit"> <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-text id="nr" v-model="single.nr" label="Jahr" required></f-text>
<f-select id="subscription_id" :options="subscriptions" v-model="single.subscription_id" label="Beitrag" required></f-select> <f-select
<f-select id="status_id" :options="statuses" v-model="single.status_id" label="Status" required></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> <button type="submit" class="btn btn-primary">Absenden</button>
</form> </form>
@ -18,20 +40,45 @@
<th></th> <th></th>
</thead> </thead>
<tr v-for="payment, index in value.payments" :key="index"> <tr v-for="(payment, index) in value.payments" :key="index">
<td v-text="payment.nr"></td> <td v-text="payment.nr"></td>
<td v-text="payment.status_name"></td> <td v-text="payment.status_name"></td>
<td v-text="payment.subscription_name"></td> <td v-text="payment.subscription_name"></td>
<td class="flex"> <td class="flex">
<a href="#" @click.prevent="single = payment; mode = 'edit'" class="inline-flex btn btn-warning btn-sm"><svg-sprite src="pencil"></svg-sprite></a> <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> href="#"
<i-link href="#" @click.prevent="remove(payment)" class="inline-flex btn btn-danger btn-sm"><svg-sprite src="trash"></svg-sprite></i-link> @click.prevent="
single = payment;
mode = 'edit';
"
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>
</td> </td>
</tr> </tr>
</table> </table>
</div> </div>
<div class="flex flex-col pb-6 px-6"> <div class="flex flex-col pb-6 px-6">
<a href="#" @click.prevent="openLink(link)" :class="{'disabled': link.disabled}" target="_BLANK" v-for="link, index in value.payment_links" :key="index" class="mt-1 text-center btn btn-primary" v-text="link.label"></a> <a
href="#"
@click.prevent="openLink(link)"
:class="{disabled: link.disabled}"
target="_BLANK"
v-for="(link, index) in value.payment_links"
:key="index"
class="mt-1 text-center btn btn-primary"
v-text="link.label"
></a>
</div> </div>
</div> </div>
</template> </template>
@ -40,17 +87,15 @@
import SidebarHeader from '../../components/SidebarHeader.vue'; import SidebarHeader from '../../components/SidebarHeader.vue';
export default { export default {
data: function() { data: function () {
return { return {
mode: null, mode: null,
single: null, single: null,
indexLinks: [ indexLinks: [{event: 'create', label: 'Neue Zahlung'}],
{event: 'create', label: 'Neue Zahlung'}
]
}; };
}, },
components: { SidebarHeader }, components: {SidebarHeader},
methods: { methods: {
remove(payment) { remove(payment) {
@ -58,7 +103,7 @@ export default {
}, },
accept(payment) { accept(payment) {
this.$inertia.patch(`/member/${this.value.id}/payment/${payment.id}`, { ...payment, status_id: 3 }); this.$inertia.patch(`/member/${this.value.id}/payment/${payment.id}`, {...payment, status_id: 3});
}, },
openLink(link) { openLink(link) {
@ -72,24 +117,24 @@ export default {
submit() { submit() {
var _self = this; var _self = this;
this.mode === 'create' this.mode === 'create'
? this.$inertia.post(`/member/${this.value.id}/payment`, this.single, { ? this.$inertia.post(`/member/${this.value.id}/payment`, this.single, {
onFinish() { onFinish() {
_self.single = null; _self.single = null;
} },
}) })
: this.$inertia.patch(`/member/${this.value.id}/payment/${this.single.id}`, this.single, { : this.$inertia.patch(`/member/${this.value.id}/payment/${this.single.id}`, this.single, {
onFinish() { onFinish() {
_self.single = null; _self.single = null;
} },
}); });
} },
}, },
props: { props: {
value: {}, value: {},
subscriptions: {}, subscriptions: {},
statuses: {}, statuses: {},
} },
}; };
</script> </script>

View File

@ -46,7 +46,13 @@
<!-- ***************************** Hauptbereich ****************************** --> <!-- ***************************** Hauptbereich ****************************** -->
<div class="grow"> <div class="grow">
<div class="grid grid-cols-2 gap-3 p-4" v-show="menuTitle == 'Stammdaten'"> <div class="grid grid-cols-2 gap-3 p-4" v-show="menuTitle == 'Stammdaten'">
<f-select id="gender_id" :options="genders" v-model="inner.gender_id" label="Geschlecht"></f-select> <f-select
id="gender_id"
name="gender_id"
:options="genders"
v-model="inner.gender_id"
label="Geschlecht"
></f-select>
<f-text id="firstname" v-model="inner.firstname" label="Vorname" required></f-text> <f-text id="firstname" v-model="inner.firstname" label="Vorname" required></f-text>
<f-text id="lastname" v-model="inner.lastname" label="Nachname" required></f-text> <f-text id="lastname" v-model="inner.lastname" label="Nachname" required></f-text>
<f-text id="address" v-model="inner.address" label="Adresse" required></f-text> <f-text id="address" v-model="inner.address" label="Adresse" required></f-text>
@ -54,12 +60,19 @@
<f-text id="zip" v-model="inner.zip" label="PLZ" required></f-text> <f-text id="zip" v-model="inner.zip" label="PLZ" required></f-text>
<f-text id="location" v-model="inner.location" label="Ort" required></f-text> <f-text id="location" v-model="inner.location" label="Ort" required></f-text>
<f-text type="date" id="birthday" v-model="inner.birthday" label="Geburtsdatum" required></f-text> <f-text type="date" id="birthday" v-model="inner.birthday" label="Geburtsdatum" required></f-text>
<f-select :options="regions" id="region_id" v-model="inner.region_id" label="Bundesland"></f-select> <f-select
:options="regions"
name="region_id"
id="region_id"
v-model="inner.region_id"
label="Bundesland"
></f-select>
<f-select <f-select
:options="countries" :options="countries"
id="country_id" id="country_id"
v-model="inner.country_id" v-model="inner.country_id"
label="Land" label="Land"
name="country_id"
required required
></f-select> ></f-select>
<f-select <f-select
@ -67,6 +80,7 @@
id="nationality_id" id="nationality_id"
v-model="inner.nationality_id" v-model="inner.nationality_id"
label="Staatsangehörigkeit" label="Staatsangehörigkeit"
name="nationality_id"
required required
></f-select> ></f-select>
<f-text <f-text
@ -83,6 +97,7 @@
id="first_activity_id" id="first_activity_id"
v-model="inner.first_activity_id" v-model="inner.first_activity_id"
label="Erste Tätigkeit" label="Erste Tätigkeit"
name="first_activity_id"
required required
></f-select> ></f-select>
<f-select <f-select
@ -91,6 +106,7 @@
id="first_subactivity_id" id="first_subactivity_id"
v-model="inner.first_subactivity_id" v-model="inner.first_subactivity_id"
label="Erste Untertätigkeit" label="Erste Untertätigkeit"
name="first_subactivity_id"
required required
></f-select> ></f-select>
</div> </div>
@ -110,6 +126,7 @@
id="bill_kind_id" id="bill_kind_id"
v-model="inner.bill_kind_id" v-model="inner.bill_kind_id"
label="Rechnung versenden über" label="Rechnung versenden über"
name="bill_kind_id"
></f-select> ></f-select>
</div> </div>
<div class="grid grid-cols-2 gap-3 p-4" v-show="menuTitle == 'Prävention'"> <div class="grid grid-cols-2 gap-3 p-4" v-show="menuTitle == 'Prävention'">
@ -200,6 +217,7 @@
id="subscription_id" id="subscription_id"
v-model="inner.subscription_id" v-model="inner.subscription_id"
label="Beitrag" label="Beitrag"
name="subscription_id"
></f-select> ></f-select>
<f-textarea <f-textarea
class="col-span-2" class="col-span-2"

View File

@ -1,8 +1,14 @@
<template> <template>
<form class="p-6 grid gap-4 justify-start" @submit.prevent="submit"> <form class="p-6 grid gap-4 justify-start" @submit.prevent="submit">
<f-text id="name" v-model="inner.name" label="Name" required></f-text> <f-text id="name" v-model="inner.name" label="Name" required></f-text>
<f-select id="fee_id" :options="fees" v-model="inner.fee_id" label="Nami-Beitrag" required></f-select> <f-select
id="fee_id"
name="fee_id"
:options="fees"
v-model="inner.fee_id"
label="Nami-Beitrag"
required
></f-select>
<f-text id="amount" v-model="inner.amount" label="Interner Beitrag" required></f-text> <f-text id="amount" v-model="inner.amount" label="Interner Beitrag" required></f-text>
<button type="submit" class="btn btn-primary">Absenden</button> <button type="submit" class="btn btn-primary">Absenden</button>
@ -11,7 +17,7 @@
<script> <script>
export default { export default {
data: function() { data: function () {
return { return {
inner: {}, inner: {},
}; };
@ -28,11 +34,11 @@ export default {
this.mode === 'create' this.mode === 'create'
? this.$inertia.post(`/subscription`, this.inner) ? this.$inertia.post(`/subscription`, this.inner)
: this.$inertia.patch(`/subscription/${this.inner.id}`, this.inner); : this.$inertia.patch(`/subscription/${this.inner.id}`, this.inner);
} },
}, },
created() { created() {
this.inner = this.data; this.inner = this.data;
} },
}; };
</script> </script>

View File

@ -0,0 +1,39 @@
\documentclass[a4paper,landscape]{article}
\usepackage[landscape,top=0cm,left=0cm,bottom=0cm,right=0cm]{geometry}
\usepackage{tikz}
\usepackage{background}
\usepackage{blindtext}
\usetikzlibrary{matrix, shapes.misc, calc}
\pagestyle{empty}
\setlength{\parindent}{0cm}
\backgroundsetup{scale = 1, angle = 0, opacity = 1, color=black, contents = {\includegraphics[width = \paperwidth, height = \paperheight] {teilnahmeliste.pdf}}}
\begin{document}
\noindent \sffamily
@foreach($data->members()->chunk(17) as $chunk)
\begin{tikzpicture}[remember picture,overlay,yscale=-1]
\node[anchor=base west] at (38mm,41.62mm) {\bfseries{\large{<<<!!$data->dateRange()!!>>>}}};
\node[anchor=base west] at (135.2mm,41.62mm) {\bfseries{\large{<<<!!$data->zipLocation!!>>>}}};
\node[anchor=base west] at (242.7mm,41.62mm) {\bfseries{\large{<<<!!$data->countryName()!!>>>}}};
\node[thick, cross out,draw=black,text width=2.4mm, text height=2.4mm, inner sep=0mm] at (17.76mm,47.10mm) {};
@foreach($chunk as $i => $member)
\node[anchor=base, text width=7.75mm, align=center] at ($(16.35mm, 76.6mm + 7mm * <<<$i % 17>>>)$) {<<<$i+1>>>};
\node[anchor=base, text width=18mm, align=center] at ($(32.55mm, 76.6mm + 7mm * <<<$i%17>>>)$) {<<<$data->memberShort($member)>>>};
\node[anchor=base, text width=70mm, align=center] at ($(80.25mm, 76.6mm + 7mm * <<<$i%17>>>)$) {<<<$data->memberName($member)>>>};
\node[anchor=base, text width=118mm, align=center] at ($(178.25mm, 76.6mm + 7mm * <<<$i%17>>>)$) {<<<$data->memberAddress($member)>>>};
\node[anchor=base, text width=16mm, align=center] at ($(249.50mm, 76.6mm + 7mm * <<<$i%17>>>)$) {<<<$data->memberGender($member)>>>};
\node[anchor=base, text width=16mm, align=center] at ($(269.50mm, 76.6mm + 7mm * <<<$i%17>>>)$) {<<<$data->memberAge($member)>>>};
@endforeach
\end{tikzpicture}
\pagebreak
@endforeach
\end{document}