diff --git a/app/Contribution/ContributionController.php b/app/Contribution/ContributionController.php index 63a8f5d2..a4cbff8c 100644 --- a/app/Contribution/ContributionController.php +++ b/app/Contribution/ContributionController.php @@ -2,6 +2,7 @@ namespace App\Contribution; +use App\Country; use App\Http\Controllers\Controller; use App\Member\Member; use App\Member\MemberResource; @@ -19,6 +20,8 @@ class ContributionController extends Controller return Inertia::render('contribution/VIndex', [ 'allMembers' => MemberResource::collection(Member::slangOrdered()->get()), + 'countries' => Country::pluck('name', 'id'), + 'defaultCountry' => Country::firstWhere('name', 'Deutschland')->id, ]); } diff --git a/app/Contribution/DvData.php b/app/Contribution/DvData.php new file mode 100644 index 00000000..8a70812c --- /dev/null +++ b/app/Contribution/DvData.php @@ -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; + } +} diff --git a/app/Contribution/SolingenData.php b/app/Contribution/SolingenData.php index 7b2f5c56..41b5266d 100644 --- a/app/Contribution/SolingenData.php +++ b/app/Contribution/SolingenData.php @@ -73,9 +73,9 @@ class SolingenData extends Data implements PdfRepository return 'tex.zuschuss-stadt'; } - public function getTemplate(): string + public function getTemplate(): ?string { - return 'efz'; + return null; } public function setFilename(string $filename): static diff --git a/app/Member/Member.php b/app/Member/Member.php index d67d8247..105a749c 100644 --- a/app/Member/Member.php +++ b/app/Member/Member.php @@ -91,9 +91,14 @@ class Member extends Model return $this->firstname.' '.$this->lastname; } + public function getFullAddressAttribute(): string + { + return $this->address.', '.$this->zip.' '.$this->location; + } + 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]) : null; } @@ -120,6 +125,16 @@ class Member extends Model 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 ---------------------------------- public function country(): BelongsTo { diff --git a/app/Member/MemberResource.php b/app/Member/MemberResource.php index 11672a46..51ef0765 100644 --- a/app/Member/MemberResource.php +++ b/app/Member/MemberResource.php @@ -71,7 +71,7 @@ class MemberResource extends JsonResource 'without_efz_at' => $this->without_efz_at, 'multiply_pv' => $this->multiply_pv, 'multiply_more_pv' => $this->multiply_more_pv, - 'age' => $this->birthday->diffInYears(now()), + 'age' => $this->getModel()->getAge(), ]; } } diff --git a/app/Pdf/BillType.php b/app/Pdf/BillType.php index fa521100..60a897ca 100644 --- a/app/Pdf/BillType.php +++ b/app/Pdf/BillType.php @@ -47,7 +47,7 @@ class BillType extends Repository implements LetterRepository return 'tex.bill'; } - public function getTemplate(): string + public function getTemplate(): ?string { return 'default'; } diff --git a/app/Pdf/Data/MemberEfzData.php b/app/Pdf/Data/MemberEfzData.php index 27d27e9a..725c0ac4 100644 --- a/app/Pdf/Data/MemberEfzData.php +++ b/app/Pdf/Data/MemberEfzData.php @@ -49,7 +49,7 @@ class MemberEfzData extends Data implements PdfRepository return 'tex.efz'; } - public function getTemplate(): string + public function getTemplate(): ?string { return 'efz'; } diff --git a/app/Pdf/PdfGenerator.php b/app/Pdf/PdfGenerator.php index 5aea082d..fc0d5164 100644 --- a/app/Pdf/PdfGenerator.php +++ b/app/Pdf/PdfGenerator.php @@ -27,7 +27,9 @@ class PdfGenerator implements Responsable Storage::disk('temp')->put($this->dir.'/'.$this->repo->getFilename().'.tex', $this->compileView()); 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 .= ' && '.env($this->repo->getScript()->value).' --halt-on-error '.$this->repo->getFilename().'.tex'; diff --git a/app/Pdf/PdfRepository.php b/app/Pdf/PdfRepository.php index 79879680..f392ebcb 100644 --- a/app/Pdf/PdfRepository.php +++ b/app/Pdf/PdfRepository.php @@ -10,7 +10,7 @@ interface PdfRepository public function getView(): string; - public function getTemplate(): string; + public function getTemplate(): ?string; public function getScript(): EnvType; } diff --git a/app/Pdf/RememberType.php b/app/Pdf/RememberType.php index 30208ef0..4b6c86a5 100644 --- a/app/Pdf/RememberType.php +++ b/app/Pdf/RememberType.php @@ -47,7 +47,7 @@ class RememberType extends Repository implements LetterRepository return 'tex.remember'; } - public function getTemplate(): string + public function getTemplate(): ?string { return 'default'; } diff --git a/resources/js/components/FSelect.vue b/resources/js/components/FSelect.vue index 22e9f7ac..45cca843 100644 --- a/resources/js/components/FSelect.vue +++ b/resources/js/components/FSelect.vue @@ -5,7 +5,7 @@ <span v-show="required" class="text-red-800"> *</span> </span> <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 @@ -74,6 +74,9 @@ export default { type: Number, default: -1, }, + name: { + required: true, + }, hint: {}, options: { default: function () { diff --git a/resources/js/views/contribution/VIndex.vue b/resources/js/views/contribution/VIndex.vue index 47733db3..ddd0853a 100644 --- a/resources/js/views/contribution/VIndex.vue +++ b/resources/js/views/contribution/VIndex.vue @@ -18,6 +18,16 @@ required ></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"> <f-text class="col-span-2" @@ -52,6 +62,15 @@ > Für Stadt erstellen </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> </template> @@ -65,10 +84,14 @@ export default { event_name: '', dateFrom: '', dateUntil: '', + zipLocation: '', + country: null, }, }; }, props: { + countries: {}, + defaultCountry: {}, allMembers: {}, }, computed: { @@ -105,5 +128,9 @@ export default { this.onSubmitMemberResult(this.memberResults[0]); }, }, + + created() { + this.values.country = this.defaultCountry; + }, }; </script> diff --git a/resources/js/views/member/MemberCourses.vue b/resources/js/views/member/MemberCourses.vue index 22541d52..b552e73c 100644 --- a/resources/js/views/member/MemberCourses.vue +++ b/resources/js/views/member/MemberCourses.vue @@ -1,10 +1,25 @@ <template> <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"> <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="organizer" v-model="single.organizer" label="Veranstalter" required></f-text> <button type="submit" class="btn btn-primary">Absenden</button> @@ -20,14 +35,24 @@ <th></th> </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.event_name"></td> <td v-text="course.organizer"></td> <td v-text="course.completed_at_human"></td> <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> - <i-link href="#" @click.prevent="remove(course)" class="inline-flex btn btn-danger btn-sm"><svg-sprite src="trash"></svg-sprite></i-link> + <a + 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> </tr> </table> @@ -39,22 +64,20 @@ import SidebarHeader from '../../components/SidebarHeader.vue'; export default { - data: function() { + data: function () { return { mode: null, single: null, - indexLinks: [ - {event: 'create', label: 'Neuer Kurs'} - ] + indexLinks: [{event: 'create', label: 'Neuer Kurs'}], }; }, props: { courses: {}, - value: {} + value: {}, }, - components: { SidebarHeader }, + components: {SidebarHeader}, methods: { remove(payment) { @@ -72,18 +95,18 @@ export default { submit() { var _self = this; - this.mode === 'create' + this.mode === 'create' ? this.$inertia.post(`/member/${this.value.id}/course`, this.single, { - onFinish() { - _self.single = null; - } - }) + onFinish() { + _self.single = null; + }, + }) : this.$inertia.patch(`/member/${this.value.id}/course/${this.single.id}`, this.single, { - onFinish() { - _self.single = null; - } - }); - } - } + onFinish() { + _self.single = null; + }, + }); + }, + }, }; </script> diff --git a/resources/js/views/member/MemberFilter.vue b/resources/js/views/member/MemberFilter.vue index a2979daf..51cd494a 100644 --- a/resources/js/views/member/MemberFilter.vue +++ b/resources/js/views/member/MemberFilter.vue @@ -1,9 +1,41 @@ <template> <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-select v-show="hasModule('bill')" 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"></f-select> - <f-select id="subactivity_id" @input="reload" :options="subactivities" v-model="inner.subactivity_id" label="Untertätigkeit" size="sm"></f-select> + <f-switch + v-show="hasModule('bill')" + id="ausstand" + @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> </template> @@ -11,10 +43,9 @@ import mergesQueryString from '../../mixins/mergesQueryString.js'; export default { - - data: function() { + data: function () { return { - inner: {} + inner: {}, }; }, @@ -30,14 +61,13 @@ export default { methods: { reload() { this.$inertia.visit(this.qs({filter: JSON.stringify(this.inner)}), { - preserveState: true + preserveState: true, }); - } + }, }, created() { this.inner = this.value; - } - + }, }; </script> diff --git a/resources/js/views/member/MemberMemberships.vue b/resources/js/views/member/MemberMemberships.vue index 8fddf780..3a79f4bb 100644 --- a/resources/js/views/member/MemberMemberships.vue +++ b/resources/js/views/member/MemberMemberships.vue @@ -1,10 +1,32 @@ <template> <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"> - <f-select id="activity_id" :options="activities" v-model="single.activity_id" label="Tätigkeit" required></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> + <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> </form> @@ -17,13 +39,23 @@ <th></th> </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.subactivity_name"></td> <td v-text="membership.human_date"></td> <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> - <i-link href="#" @click.prevent="remove(membership)" class="inline-flex btn btn-danger btn-sm"><svg-sprite src="trash"></svg-sprite></i-link> + <a + 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> </tr> </table> @@ -35,17 +67,15 @@ import SidebarHeader from '../../components/SidebarHeader.vue'; export default { - data: function() { + data: function () { return { mode: null, single: null, - links: [ - { event: 'create', label: 'Neu' } - ] + links: [{event: 'create', label: 'Neu'}], }; }, - components: { SidebarHeader }, + components: {SidebarHeader}, methods: { remove(membership) { @@ -53,7 +83,7 @@ export default { }, 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) { @@ -71,19 +101,19 @@ export default { onFinish() { _self.single = null; _self.mode = null; - } + }, }; - this.mode === 'create' + this.mode === 'create' ? 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); - } + }, }, props: { value: {}, activities: {}, subactivities: {}, - } + }, }; </script> diff --git a/resources/js/views/member/MemberPayments.vue b/resources/js/views/member/MemberPayments.vue index f013e9d2..1ecf5bad 100644 --- a/resources/js/views/member/MemberPayments.vue +++ b/resources/js/views/member/MemberPayments.vue @@ -1,11 +1,33 @@ <template> <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"> <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 id="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> @@ -18,20 +40,45 @@ <th></th> </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.status_name"></td> <td v-text="payment.subscription_name"></td> <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> - <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> + <a + href="#" + @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> </tr> </table> </div> <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> </template> @@ -40,17 +87,15 @@ import SidebarHeader from '../../components/SidebarHeader.vue'; export default { - data: function() { + data: function () { return { mode: null, single: null, - indexLinks: [ - {event: 'create', label: 'Neue Zahlung'} - ] + indexLinks: [{event: 'create', label: 'Neue Zahlung'}], }; }, - components: { SidebarHeader }, + components: {SidebarHeader}, methods: { remove(payment) { @@ -58,7 +103,7 @@ export default { }, 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) { @@ -72,24 +117,24 @@ export default { submit() { var _self = this; - this.mode === 'create' + this.mode === 'create' ? this.$inertia.post(`/member/${this.value.id}/payment`, this.single, { - onFinish() { - _self.single = null; - } - }) + onFinish() { + _self.single = null; + }, + }) : this.$inertia.patch(`/member/${this.value.id}/payment/${this.single.id}`, this.single, { - onFinish() { - _self.single = null; - } - }); - } + onFinish() { + _self.single = null; + }, + }); + }, }, props: { value: {}, subscriptions: {}, statuses: {}, - } + }, }; </script> diff --git a/resources/js/views/member/VForm.vue b/resources/js/views/member/VForm.vue index 6595d8bf..9714e4fb 100644 --- a/resources/js/views/member/VForm.vue +++ b/resources/js/views/member/VForm.vue @@ -46,7 +46,13 @@ <!-- ***************************** Hauptbereich ****************************** --> <div class="grow"> <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="lastname" v-model="inner.lastname" label="Nachname" 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="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-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 :options="countries" id="country_id" v-model="inner.country_id" label="Land" + name="country_id" required ></f-select> <f-select @@ -67,6 +80,7 @@ id="nationality_id" v-model="inner.nationality_id" label="Staatsangehörigkeit" + name="nationality_id" required ></f-select> <f-text @@ -83,6 +97,7 @@ id="first_activity_id" v-model="inner.first_activity_id" label="Erste Tätigkeit" + name="first_activity_id" required ></f-select> <f-select @@ -91,6 +106,7 @@ id="first_subactivity_id" v-model="inner.first_subactivity_id" label="Erste Untertätigkeit" + name="first_subactivity_id" required ></f-select> </div> @@ -110,6 +126,7 @@ id="bill_kind_id" v-model="inner.bill_kind_id" label="Rechnung versenden über" + name="bill_kind_id" ></f-select> </div> <div class="grid grid-cols-2 gap-3 p-4" v-show="menuTitle == 'Prävention'"> @@ -200,6 +217,7 @@ id="subscription_id" v-model="inner.subscription_id" label="Beitrag" + name="subscription_id" ></f-select> <f-textarea class="col-span-2" diff --git a/resources/js/views/subscription/SubscriptionForm.vue b/resources/js/views/subscription/SubscriptionForm.vue index 6322f5e1..49a47307 100644 --- a/resources/js/views/subscription/SubscriptionForm.vue +++ b/resources/js/views/subscription/SubscriptionForm.vue @@ -1,8 +1,14 @@ <template> <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-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> <button type="submit" class="btn btn-primary">Absenden</button> @@ -11,7 +17,7 @@ <script> export default { - data: function() { + data: function () { return { inner: {}, }; @@ -28,11 +34,11 @@ export default { this.mode === 'create' ? this.$inertia.post(`/subscription`, this.inner) : this.$inertia.patch(`/subscription/${this.inner.id}`, this.inner); - } + }, }, created() { this.inner = this.data; - } + }, }; </script> diff --git a/resources/views/tex/templates/zuschussdv/teilnahmeliste.pdf b/resources/views/tex/templates/zuschussdv/teilnahmeliste.pdf new file mode 100644 index 00000000..345736a5 Binary files /dev/null and b/resources/views/tex/templates/zuschussdv/teilnahmeliste.pdf differ diff --git a/resources/views/tex/zuschuss-dv.tex b/resources/views/tex/zuschuss-dv.tex new file mode 100644 index 00000000..6ed4184f --- /dev/null +++ b/resources/views/tex/zuschuss-dv.tex @@ -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} +