Add Dashboard
This commit is contained in:
parent
8feac575ad
commit
dcb25c8814
|
@ -1,44 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Efz;
|
|
||||||
|
|
||||||
use App\Dashboard\Blocks\Block;
|
|
||||||
use App\Member\Member;
|
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
|
||||||
|
|
||||||
class EfzPendingBlock extends Block
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @return Builder<Member>
|
|
||||||
*/
|
|
||||||
public function query(): Builder
|
|
||||||
{
|
|
||||||
return Member::where(function ($query) {
|
|
||||||
return $query->where('efz', '<=', now()->subYears(5)->endOfYear())
|
|
||||||
->orWhereNull('efz');
|
|
||||||
})
|
|
||||||
->whereCurrentGroup()
|
|
||||||
->orderByRaw('lastname, firstname')
|
|
||||||
->whereHas('memberships', fn ($builder) => $builder->isLeader()->active());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array{members: array<int, string>}
|
|
||||||
*/
|
|
||||||
public function data(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'members' => $this->query()->get()->map(fn ($member) => $member->fullname)->toArray(),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function component(): string
|
|
||||||
{
|
|
||||||
return 'efz-pending';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function title(): string
|
|
||||||
{
|
|
||||||
return 'Ausstehende Führungszeugnisse';
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Invoice;
|
|
||||||
|
|
||||||
use App\Dashboard\Blocks\Block;
|
|
||||||
use App\Invoice\Models\InvoicePosition;
|
|
||||||
use App\Member\Member;
|
|
||||||
|
|
||||||
class MemberPaymentBlock extends Block
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @return array<string, string|int>
|
|
||||||
*/
|
|
||||||
public function data(): array
|
|
||||||
{
|
|
||||||
$amount = InvoicePosition::whereHas('invoice', fn ($query) => $query->whereNeedsPayment())
|
|
||||||
->selectRaw('sum(price) AS price')
|
|
||||||
->first();
|
|
||||||
$members = Member::whereHasPendingPayment()->count();
|
|
||||||
|
|
||||||
return [
|
|
||||||
'members' => $members,
|
|
||||||
'total_members' => Member::count(),
|
|
||||||
'amount' => number_format((int) $amount->price / 100, 2, ',', '.') . ' €',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function component(): string
|
|
||||||
{
|
|
||||||
return 'member-payment';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function title(): string
|
|
||||||
{
|
|
||||||
return 'Ausstehende Mitgliedsbeiträge';
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Member;
|
|
||||||
|
|
||||||
use App\Dashboard\Blocks\Block;
|
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
|
||||||
|
|
||||||
class PsPendingBlock extends Block
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @return Builder<Member>
|
|
||||||
*/
|
|
||||||
public function query(): Builder
|
|
||||||
{
|
|
||||||
return Member::where(function ($query) {
|
|
||||||
$time = now()->subYears(5)->endOfYear();
|
|
||||||
|
|
||||||
return $query
|
|
||||||
->orWhere(fn ($query) => $query->whereNull('ps_at')->whereNull('more_ps_at'))
|
|
||||||
->orWhere(fn ($query) => $query->whereNull('ps_at')->where('more_ps_at', '<=', $time))
|
|
||||||
->orWhere(fn ($query) => $query->where('ps_at', '<=', $time)->whereNull('more_ps_at'))
|
|
||||||
->orWhere(fn ($query) => $query->where('ps_at', '>=', $time)->where('more_ps_at', '<=', $time));
|
|
||||||
})
|
|
||||||
->whereCurrentGroup()
|
|
||||||
->orderByRaw('lastname, firstname')
|
|
||||||
->whereHas('memberships', fn ($builder) => $builder->isLeader()->active());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array{members: array{fullname: string}}
|
|
||||||
*/
|
|
||||||
public function data(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'members' => $this->query()->get()->map(fn ($member) => [
|
|
||||||
'fullname' => $member->fullname,
|
|
||||||
])->toArray(),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function component(): string
|
|
||||||
{
|
|
||||||
return 'ps-pending';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function title(): string
|
|
||||||
{
|
|
||||||
return 'Ausstehende Präventionsschulungen';
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Membership;
|
|
||||||
|
|
||||||
use App\Dashboard\Blocks\Block;
|
|
||||||
use App\Member\Member;
|
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
|
||||||
|
|
||||||
class TestersBlock extends Block
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @return Builder<Member>
|
|
||||||
*/
|
|
||||||
public function query(): Builder
|
|
||||||
{
|
|
||||||
return Member::whereHas('memberships', fn ($q) => $q->isTrying())
|
|
||||||
->with('memberships', fn ($q) => $q->isTrying());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array{members: array<int, array{name: string, try_ends_at: string, try_ends_at_human: string}>}
|
|
||||||
*/
|
|
||||||
public function data(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'members' => $this->query()->get()->map(fn ($member) => [
|
|
||||||
'name' => $member->fullname,
|
|
||||||
'try_ends_at' => $member->memberships->first()->from->addWeeks(8)->format('d.m.Y'),
|
|
||||||
'try_ends_at_human' => $member->memberships->first()->from->addWeeks(8)->diffForHumans(),
|
|
||||||
])->toArray(),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function component(): string
|
|
||||||
{
|
|
||||||
return 'testers';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function title(): string
|
|
||||||
{
|
|
||||||
return 'Endende Schhnupperzeiten';
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Modules\Base;
|
namespace App\Providers;
|
||||||
|
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
use Illuminate\Support\Facades\Blade;
|
use Illuminate\Support\Facades\Blade;
|
||||||
|
@ -21,9 +21,8 @@ class BaseServiceProvider extends ServiceProvider
|
||||||
*/
|
*/
|
||||||
public function register(): void
|
public function register(): void
|
||||||
{
|
{
|
||||||
Blade::componentNamespace('Modules\\Base\\Components\\Ui', 'ui');
|
Blade::componentNamespace('App\\View\\Ui', 'ui');
|
||||||
Blade::componentNamespace('Modules\\Base\\Components\\Page', 'page');
|
Blade::componentNamespace('App\\View\\Page', 'page');
|
||||||
|
|
||||||
|
|
||||||
app(DashboardFactory::class)->register(AgeGroupCountBlock::class);
|
app(DashboardFactory::class)->register(AgeGroupCountBlock::class);
|
||||||
app(DashboardFactory::class)->register(MemberPaymentBlock::class);
|
app(DashboardFactory::class)->register(MemberPaymentBlock::class);
|
||||||
|
@ -31,8 +30,6 @@ class BaseServiceProvider extends ServiceProvider
|
||||||
app(DashboardFactory::class)->register(EfzPendingBlock::class);
|
app(DashboardFactory::class)->register(EfzPendingBlock::class);
|
||||||
app(DashboardFactory::class)->register(PsPendingBlock::class);
|
app(DashboardFactory::class)->register(PsPendingBlock::class);
|
||||||
|
|
||||||
Livewire::component('page.sidebar', Sidebar::class);
|
|
||||||
|
|
||||||
ComponentAttributeBag::macro('mergeWhen', function ($condition, $key, $attributes) {
|
ComponentAttributeBag::macro('mergeWhen', function ($condition, $key, $attributes) {
|
||||||
/** @var ComponentAttributeBag */
|
/** @var ComponentAttributeBag */
|
||||||
$self = $this;
|
$self = $this;
|
||||||
|
@ -45,7 +42,5 @@ class BaseServiceProvider extends ServiceProvider
|
||||||
*/
|
*/
|
||||||
public function boot(): void
|
public function boot(): void
|
||||||
{
|
{
|
||||||
Livewire::component('pagesidebar', Sidebar::class);
|
|
||||||
//
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Modules\Base\Components\Page;
|
namespace App\View\Page;
|
||||||
|
|
||||||
use Illuminate\View\Component;
|
use Illuminate\View\Component;
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\View\Page;
|
||||||
|
|
||||||
|
use Illuminate\View\Component;
|
||||||
|
|
||||||
|
class Layout extends Component
|
||||||
|
{
|
||||||
|
|
||||||
|
public function __construct(public string $pageClass = '')
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function userName(): string
|
||||||
|
{
|
||||||
|
return auth()->user()->firstname . ' ' . auth()->user()->lastname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function userAvatar(): string
|
||||||
|
{
|
||||||
|
return auth()->user()->getGravatarUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render()
|
||||||
|
{
|
||||||
|
return <<<'HTML'
|
||||||
|
<div class="grow flex flex-col">
|
||||||
|
<div class="grow bg-gray-900 flex flex-col duration-300 navbar:ml-60">
|
||||||
|
<x-page::header title="{{ session()->get('title') }}">
|
||||||
|
<x-slot:beforeTitle>
|
||||||
|
<a href="#" class="mr-2 lg:hidden" wire:click.prevent="dispatch('toggle-sidebar')">
|
||||||
|
<x-ui::sprite src="menu" class="text-gray-100 w-5 h-5"></x-ui::sprite>
|
||||||
|
</a>
|
||||||
|
</x-slot:beforeTitle>
|
||||||
|
<x-slot:toolbar>
|
||||||
|
{{ $toolbar ?? ''}}
|
||||||
|
</x-slot:toolbar>
|
||||||
|
<x-slot:right>
|
||||||
|
{{ $right ?? '' }}
|
||||||
|
<div class="flex items-center space-x-2">
|
||||||
|
<div class="rounded-full overflow-hidden border-2 border-solid border-gray-300">
|
||||||
|
<img src="{{ $userAvatar() }}" class="w-8 h-8 object-cover" />
|
||||||
|
</div>
|
||||||
|
<div class="text-gray-300"">{{ $userName() }}</div>
|
||||||
|
</div>
|
||||||
|
</x-slot:right>
|
||||||
|
</x-page::header>
|
||||||
|
|
||||||
|
<div class="grow flex flex-col {{$pageClass}}">
|
||||||
|
{{ $slot }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<livewire:page.sidebar :mobile="true" />
|
||||||
|
</div>
|
||||||
|
HTML;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Modules\Base\Components\Page;
|
namespace App\View\Page;
|
||||||
|
|
||||||
use Illuminate\View\Component;
|
use Illuminate\View\Component;
|
||||||
|
|
|
@ -1,19 +1,25 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Modules\Base\Components\Page;
|
namespace App\View\Page;
|
||||||
|
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class Sidebar extends Component
|
class Sidebar extends Component
|
||||||
{
|
{
|
||||||
|
|
||||||
public $isShifted = false;
|
public $mobile = false;
|
||||||
|
|
||||||
public function render()
|
public function render()
|
||||||
{
|
{
|
||||||
return <<<'HTML'
|
return <<<'HTML'
|
||||||
<div
|
<div
|
||||||
class="fixed z-40 bg-gray-800 p-6 w-56 top-0 h-screen border-r border-gray-600 border-solid flex flex-col justify-between transition-all {{ $isShifted ? '-left-[14rem]' : 'left-0' }}"
|
class="fixed z-40 bg-gray-800 p-6 w-60 top-0 h-screen border-r border-gray-600 border-solid flex flex-col justify-between duration-300
|
||||||
|
@if (!$mobile) left-[-16rem] navbar:left-0 @endif"
|
||||||
|
@if($mobile)
|
||||||
|
x-data="{ visible: false }"
|
||||||
|
x-on:toggle-sidebar.window="visible = true"
|
||||||
|
:class="{'left-[-16rem]' : !visible, 'left-0': visible}"
|
||||||
|
@endif
|
||||||
>
|
>
|
||||||
<div class="grid gap-2">
|
<div class="grid gap-2">
|
||||||
<x-page::menu-entry href="/" menu="dashboard" icon="loss">Dashboard</x-page::menu-entry>
|
<x-page::menu-entry href="/" menu="dashboard" icon="loss">Dashboard</x-page::menu-entry>
|
||||||
|
@ -27,16 +33,18 @@ class Sidebar extends Component
|
||||||
<x-page::menu-entry href="/maildispatcher" menu="maildispatcher" icon="at">Mail-Verteiler</x-page::menu-entry>
|
<x-page::menu-entry href="/maildispatcher" menu="maildispatcher" icon="at">Mail-Verteiler</x-page::menu-entry>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid gap-2">
|
<div class="grid gap-2">
|
||||||
<a href="#" class="flex w-full px-3 py-2 rounded-xl text-gray-300 bg-gray-700" @click.prevent="searchVisible = true">
|
<a href="#" class="flex w-full px-3 py-2 rounded-xl text-gray-300 bg-gray-700" @click.prevent="dispatch('show-search')">
|
||||||
<x-ui::sprite class="text-white w-6 h-6 mr-4" src="search"></x-ui::sprite>
|
<x-ui::sprite class="text-white w-6 h-6 mr-4" src="search"></x-ui::sprite>
|
||||||
<div class="">Suchen</div>
|
<div class="">Suchen</div>
|
||||||
</a>
|
</a>
|
||||||
<x-page::menu-entry href="/setting" menu="setting" icon="setting">Einstellungen</x-page::menu-entry>
|
<x-page::menu-entry href="/setting" menu="setting" icon="setting">Einstellungen</x-page::menu-entry>
|
||||||
<x-page::menu-entry href="/logout" menu="" icon="logout">Abmelden</x-page::menu-entry>
|
<x-page::menu-entry href="/logout" menu="" icon="logout">Abmelden</x-page::menu-entry>
|
||||||
</div>
|
</div>
|
||||||
<a v-if="menuStore.hideable" href="#" class="absolute right-0 top-0 mr-2 mt-2" @click.prevent="menuStore.hide()">
|
@if($mobile)
|
||||||
<ui-sprite src="close" class="w-5 h-5 text-gray-300"></ui-sprite>
|
<a href="#" class="absolute right-0 top-0 mr-2 mt-2" @click.prevent="visible = false">
|
||||||
|
<x-ui::sprite src="close" class="w-5 h-5 text-gray-300"></x-ui::sprite>
|
||||||
</a>
|
</a>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
HTML;
|
HTML;
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Modules\Base\Components\Ui;
|
namespace App\View\Ui;
|
||||||
|
|
||||||
use Illuminate\View\Component;
|
use Illuminate\View\Component;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Modules\Base\Components\Ui;
|
namespace App\View\Ui;
|
||||||
|
|
||||||
use Illuminate\View\Component;
|
use Illuminate\View\Component;
|
||||||
|
|
|
@ -178,7 +178,7 @@ return [
|
||||||
// App\Dashboard\DashboardServiceProvider::class,
|
// App\Dashboard\DashboardServiceProvider::class,
|
||||||
App\Providers\PluginServiceProvider::class,
|
App\Providers\PluginServiceProvider::class,
|
||||||
Modules\Dashboard\DashboardServiceProvider::class,
|
Modules\Dashboard\DashboardServiceProvider::class,
|
||||||
Modules\Base\BaseServiceProvider::class,
|
App\Providers\BaseServiceProvider::class,
|
||||||
],
|
],
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Modules\Base\Components\Page;
|
|
||||||
|
|
||||||
use Illuminate\View\Component;
|
|
||||||
|
|
||||||
class Layout extends Component
|
|
||||||
{
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public function userName(): string
|
|
||||||
{
|
|
||||||
return auth()->user()->firstname . ' ' . auth()->user()->lastname;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function userAvatar(): string
|
|
||||||
{
|
|
||||||
return auth()->user()->getGravatarUrl();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function render()
|
|
||||||
{
|
|
||||||
return <<<'HTML'
|
|
||||||
<div class="grow bg-gray-900 flex flex-col transition-all ml-56" :class="{'ml-56': menuStore.visible, 'ml-0': !menuStore.visible}">
|
|
||||||
<x-page::header title="{{ session()->get('title') }}">
|
|
||||||
<x-slot:beforeTitle>
|
|
||||||
<a href="#" class="mr-2 lg:hidden" @click.prevent="menuStore.toggle()">
|
|
||||||
<ui-sprite src="menu" class="text-gray-100 w-5 h-5"></ui-sprite>
|
|
||||||
</a>
|
|
||||||
</x-slot:beforeTitle>
|
|
||||||
<x-slot:toolbar>
|
|
||||||
{{ $toolbar ?? ''}}
|
|
||||||
</x-slot:toolbar>
|
|
||||||
<x-slot:right>
|
|
||||||
{{ $right ?? '' }}
|
|
||||||
<div class="flex items-center space-x-2">
|
|
||||||
<div class="rounded-full overflow-hidden border-2 border-solid border-gray-300">
|
|
||||||
<img src="{{ $userAvatar() }}" class="w-8 h-8 object-cover" />
|
|
||||||
</div>
|
|
||||||
<div class="text-gray-300"">{{ $userName() }}</div>
|
|
||||||
</div>
|
|
||||||
</x-slot:right>
|
|
||||||
</x-page::header>
|
|
||||||
|
|
||||||
<div :class="pageClass" class="grow flex flex-col">
|
|
||||||
{{ $slot }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
HTML;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -8,21 +8,20 @@ use App\Member\Member;
|
||||||
|
|
||||||
class MemberPaymentBlock extends Block
|
class MemberPaymentBlock extends Block
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @return array<string, string|int>
|
public string $amount = '';
|
||||||
*/
|
public int $members = 0;
|
||||||
public function data(): array
|
public int $totalMembers = 0;
|
||||||
|
|
||||||
|
public function mount(): void
|
||||||
{
|
{
|
||||||
$amount = InvoicePosition::whereHas('invoice', fn ($query) => $query->whereNeedsPayment())
|
$amount = InvoicePosition::whereHas('invoice', fn ($query) => $query->whereNeedsPayment())
|
||||||
->selectRaw('sum(price) AS price')
|
->selectRaw('sum(price) AS price')
|
||||||
->first();
|
->first();
|
||||||
$members = Member::whereHasPendingPayment()->count();
|
|
||||||
|
|
||||||
return [
|
$this->amount = number_format((int) $amount->price / 100, 2, ',', '.') . ' €';
|
||||||
'members' => $members,
|
$this->members = Member::whereHasPendingPayment()->count();
|
||||||
'total_members' => Member::count(),
|
$this->totalMembers = Member::count();
|
||||||
'amount' => number_format((int) $amount->price / 100, 2, ',', '.') . ' €',
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function title(): string
|
public function title(): string
|
||||||
|
@ -32,6 +31,13 @@ class MemberPaymentBlock extends Block
|
||||||
|
|
||||||
public function render(): string
|
public function render(): string
|
||||||
{
|
{
|
||||||
return '<div></div>';
|
return <<<'HTML'
|
||||||
|
<div>
|
||||||
|
<div class="text-gray-100">
|
||||||
|
<span class="text-xl mr-1 font-semibold">{{$amount}}</span>
|
||||||
|
<span class="text-sm">von {{$members}} / {{$totalMembers}} Mitgliedern</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
HTML;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,13 @@ use Illuminate\Database\Eloquent\Builder;
|
||||||
|
|
||||||
class AgeGroupCountBlock extends Block
|
class AgeGroupCountBlock extends Block
|
||||||
{
|
{
|
||||||
|
|
||||||
|
public $groups;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Builder<Membership>
|
* @return Builder<Membership>
|
||||||
*/
|
*/
|
||||||
public function memberQuery(): Builder
|
protected function memberQuery(): Builder
|
||||||
{
|
{
|
||||||
return Membership::select('subactivities.slug', 'subactivities.name')
|
return Membership::select('subactivities.slug', 'subactivities.name')
|
||||||
->selectRaw('COUNT(member_id) AS count')
|
->selectRaw('COUNT(member_id) AS count')
|
||||||
|
@ -27,7 +30,7 @@ class AgeGroupCountBlock extends Block
|
||||||
/**
|
/**
|
||||||
* @return Builder<Membership>
|
* @return Builder<Membership>
|
||||||
*/
|
*/
|
||||||
public function leaderQuery(): Builder
|
protected function leaderQuery(): Builder
|
||||||
{
|
{
|
||||||
return Membership::selectRaw('"leiter" AS slug, "Leiter" AS name, COUNT(member_id) AS count')
|
return Membership::selectRaw('"leiter" AS slug, "Leiter" AS name, COUNT(member_id) AS count')
|
||||||
->join('activities', 'memberships.activity_id', 'activities.id')
|
->join('activities', 'memberships.activity_id', 'activities.id')
|
||||||
|
@ -36,13 +39,11 @@ class AgeGroupCountBlock extends Block
|
||||||
->isLeader();
|
->isLeader();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function data(): array
|
public function mount(): void
|
||||||
{
|
{
|
||||||
return [
|
$this->groups = [
|
||||||
'groups' => [
|
...$this->memberQuery()->get(),
|
||||||
...$this->memberQuery()->get()->toArray(),
|
...$this->leaderQuery()->get(),
|
||||||
...$this->leaderQuery()->get()->toArray(),
|
|
||||||
],
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,11 +52,30 @@ class AgeGroupCountBlock extends Block
|
||||||
return 'Gruppierungs-Verteilung';
|
return 'Gruppierungs-Verteilung';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function groupColor(string $slug): string
|
||||||
|
{
|
||||||
|
return data_get([
|
||||||
|
'biber' => 'text-biber',
|
||||||
|
'woelfling' => 'text-woelfling',
|
||||||
|
'jungpfadfinder' => 'text-jungpfadfinder',
|
||||||
|
'pfadfinder' => 'text-pfadfinder',
|
||||||
|
'rover' => 'text-rover',
|
||||||
|
'leiter' => 'text-leiter',
|
||||||
|
], $slug);
|
||||||
|
}
|
||||||
|
|
||||||
public function render(): string
|
public function render(): string
|
||||||
{
|
{
|
||||||
return '<div>
|
return <<<'HTML'
|
||||||
|
<div>
|
||||||
lalala
|
@foreach($groups as $group)
|
||||||
</div>';
|
<div class="flex mt-2 items-center leading-none text-gray-100">
|
||||||
|
<x-ui::sprite class="w-4 h-4 mr-2 {{ $this->groupColor($group->slug) }}" src="lilie"></x-ui::sprite>
|
||||||
|
<span class="grow">{{$group->name}}</span>
|
||||||
|
<span>{{$group->count}}</span>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
HTML;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,30 +5,23 @@ namespace Modules\Member;
|
||||||
use Modules\Dashboard\Block;
|
use Modules\Dashboard\Block;
|
||||||
use App\Member\Member;
|
use App\Member\Member;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
|
||||||
class TestersBlock extends Block
|
class TestersBlock extends Block
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @return Builder<Member>
|
private $months = 8;
|
||||||
*/
|
|
||||||
public function query(): Builder
|
|
||||||
{
|
|
||||||
return Member::whereHas('memberships', fn ($q) => $q->isTrying())
|
|
||||||
->with('memberships', fn ($q) => $q->isTrying());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array{members: array<int, array{name: string, try_ends_at: string, try_ends_at_human: string}>}
|
* @var Collection<Member>
|
||||||
*/
|
*/
|
||||||
public function data(): array
|
public Collection $members;
|
||||||
|
|
||||||
|
public function mount(): void
|
||||||
{
|
{
|
||||||
return [
|
$this->members = Member::whereHas('memberships', fn ($q) => $q->isTrying())
|
||||||
'members' => $this->query()->get()->map(fn ($member) => [
|
->with('memberships', fn ($q) => $q->isTrying())
|
||||||
'name' => $member->fullname,
|
->get();
|
||||||
'try_ends_at' => $member->memberships->first()->from->addWeeks(8)->format('d.m.Y'),
|
|
||||||
'try_ends_at_human' => $member->memberships->first()->from->addWeeks(8)->diffForHumans(),
|
|
||||||
])->toArray(),
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function title(): string
|
public function title(): string
|
||||||
|
@ -38,6 +31,16 @@ class TestersBlock extends Block
|
||||||
|
|
||||||
public function render(): string
|
public function render(): string
|
||||||
{
|
{
|
||||||
return '<div></div>';
|
return <<<'HTML'
|
||||||
|
<div>
|
||||||
|
@foreach($members as $member)
|
||||||
|
<div class="flex mt-2 items-center leading-none text-gray-100">
|
||||||
|
<span class="grow">{{ $member->fullname }}</span>
|
||||||
|
<span class="mr-2 text-sm tex-gray-600">{{ $member->memberships->first()->from->addWeeks($this->months)->format('d.m.Y') }}</span>
|
||||||
|
<span class="text-xs tex-gray-600">{{ $member->memberships->first()->from->addWeeks($this->months)->diffForHumans() }}</span>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
HTML;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,31 +5,26 @@ namespace Modules\Prevention;
|
||||||
use Modules\Dashboard\Block;
|
use Modules\Dashboard\Block;
|
||||||
use App\Member\Member;
|
use App\Member\Member;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
|
||||||
class EfzPendingBlock extends Block
|
class EfzPendingBlock extends Block
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Builder<Member>
|
* @var Collection<Member>
|
||||||
*/
|
*/
|
||||||
public function query(): Builder
|
public Collection $members;
|
||||||
|
|
||||||
|
public function mount(): void
|
||||||
{
|
{
|
||||||
return Member::where(function ($query) {
|
$this->members = Member::where(function ($query) {
|
||||||
return $query->where('efz', '<=', now()->subYears(5)->endOfYear())
|
return $query->where('efz', '<=', now()->subYears(5)->endOfYear())
|
||||||
->orWhereNull('efz');
|
->orWhereNull('efz');
|
||||||
})
|
})
|
||||||
->whereCurrentGroup()
|
->whereCurrentGroup()
|
||||||
->orderByRaw('lastname, firstname')
|
->orderByRaw('lastname, firstname')
|
||||||
->whereHas('memberships', fn ($builder) => $builder->isLeader()->active());
|
->whereHas('memberships', fn ($builder) => $builder->isLeader()->active())
|
||||||
}
|
->get();
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array{members: array<int, string>}
|
|
||||||
*/
|
|
||||||
public function data(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'members' => $this->query()->get()->map(fn ($member) => $member->fullname)->toArray(),
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function title(): string
|
public function title(): string
|
||||||
|
@ -39,6 +34,14 @@ class EfzPendingBlock extends Block
|
||||||
|
|
||||||
public function render(): string
|
public function render(): string
|
||||||
{
|
{
|
||||||
return '<div></div>';
|
return <<<'HTML'
|
||||||
|
<div>
|
||||||
|
@foreach($members as $member)
|
||||||
|
<div class="flex mt-2 items-center leading-none text-gray-100">
|
||||||
|
<span class="grow">{{$member->fullname}}</span>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
HTML;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,17 +2,22 @@
|
||||||
|
|
||||||
namespace Modules\Prevention;
|
namespace Modules\Prevention;
|
||||||
|
|
||||||
|
use App\Member\Member;
|
||||||
use Modules\Dashboard\Block;
|
use Modules\Dashboard\Block;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
|
||||||
class PsPendingBlock extends Block
|
class PsPendingBlock extends Block
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Builder<Member>
|
* @var Collection<Member>
|
||||||
*/
|
*/
|
||||||
public function query(): Builder
|
public Collection $members;
|
||||||
|
|
||||||
|
public function mount(): void
|
||||||
{
|
{
|
||||||
return Member::where(function ($query) {
|
$this->members = Member::where(function ($query) {
|
||||||
$time = now()->subYears(5)->endOfYear();
|
$time = now()->subYears(5)->endOfYear();
|
||||||
|
|
||||||
return $query
|
return $query
|
||||||
|
@ -23,19 +28,8 @@ class PsPendingBlock extends Block
|
||||||
})
|
})
|
||||||
->whereCurrentGroup()
|
->whereCurrentGroup()
|
||||||
->orderByRaw('lastname, firstname')
|
->orderByRaw('lastname, firstname')
|
||||||
->whereHas('memberships', fn ($builder) => $builder->isLeader()->active());
|
->whereHas('memberships', fn ($builder) => $builder->isLeader()->active())
|
||||||
}
|
->get();
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array{members: array{fullname: string}}
|
|
||||||
*/
|
|
||||||
public function data(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'members' => $this->query()->get()->map(fn ($member) => [
|
|
||||||
'fullname' => $member->fullname,
|
|
||||||
])->toArray(),
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function title(): string
|
public function title(): string
|
||||||
|
@ -45,6 +39,14 @@ class PsPendingBlock extends Block
|
||||||
|
|
||||||
public function render(): string
|
public function render(): string
|
||||||
{
|
{
|
||||||
return '<div></div>';
|
return <<<'HTML'
|
||||||
|
<div>
|
||||||
|
@foreach ($members as $member)
|
||||||
|
<div class="flex mt-2 items-center leading-none text-gray-100">
|
||||||
|
<span class="grow">{{ $member->fullname }}</span>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
HTML;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<div v-for="(group, index) in inner.groups" :key="index" class="flex mt-2 items-center leading-none text-gray-100">
|
|
||||||
<ui-sprite class="w-4 h-4 mr-2" src="lilie" :class="`text-${group.slug}`"></ui-sprite>
|
|
||||||
<span v-text="group.name" class="grow"></span>
|
|
||||||
<span v-text="group.count"></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data: function () {
|
|
||||||
return {
|
|
||||||
inner: {
|
|
||||||
groups: [],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
props: {
|
|
||||||
data: {},
|
|
||||||
},
|
|
||||||
|
|
||||||
created() {
|
|
||||||
this.inner = this.data;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
|
@ -1,31 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
v-for="(member, index) in inner.members"
|
|
||||||
:key="index"
|
|
||||||
class="flex mt-2 items-center leading-none text-gray-100"
|
|
||||||
>
|
|
||||||
<span class="grow" v-text="`${member}`"></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data: function () {
|
|
||||||
return {
|
|
||||||
inner: {
|
|
||||||
members: [],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
props: {
|
|
||||||
data: {},
|
|
||||||
},
|
|
||||||
|
|
||||||
created() {
|
|
||||||
this.inner = this.data;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
|
@ -1,26 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<div class="text-gray-100">
|
|
||||||
<span class="text-xl mr-1 font-semibold" v-text="inner.amount"></span>
|
|
||||||
<span class="text-sm" v-text="`von ${inner.members} / ${inner.total_members} Mitgliedern`"></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data: function () {
|
|
||||||
return {
|
|
||||||
inner: {},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
props: {
|
|
||||||
data: {},
|
|
||||||
},
|
|
||||||
|
|
||||||
created() {
|
|
||||||
this.inner = this.data;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
|
@ -1,31 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
v-for="(member, index) in inner.members"
|
|
||||||
:key="index"
|
|
||||||
class="flex mt-2 items-center leading-none text-gray-100"
|
|
||||||
>
|
|
||||||
<span class="grow" v-text="`${member.fullname}`"></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data: function () {
|
|
||||||
return {
|
|
||||||
inner: {
|
|
||||||
members: [],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
props: {
|
|
||||||
data: {},
|
|
||||||
},
|
|
||||||
|
|
||||||
created() {
|
|
||||||
this.inner = this.data;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
|
@ -1,33 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
v-for="(member, index) in inner.members"
|
|
||||||
:key="index"
|
|
||||||
class="flex mt-2 items-center leading-none text-gray-100"
|
|
||||||
>
|
|
||||||
<span class="grow" v-text="`${member.name}`"></span>
|
|
||||||
<span class="mr-2 text-sm tex-gray-600" v-text="`${member.try_ends_at}`"></span>
|
|
||||||
<span class="text-xs tex-gray-600" v-text="`${member.try_ends_at_human}`"></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data: function () {
|
|
||||||
return {
|
|
||||||
inner: {
|
|
||||||
members: [],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
props: {
|
|
||||||
data: {},
|
|
||||||
},
|
|
||||||
|
|
||||||
created() {
|
|
||||||
this.inner = this.data;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
|
@ -0,0 +1 @@
|
||||||
|
import '../css/app.css';
|
|
@ -1,14 +1,7 @@
|
||||||
const {colors} = require('tailwindcss/defaultTheme');
|
const {colors} = require('tailwindcss/defaultTheme');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
content: [
|
content: ['app/View/**/*.php', 'resources/views/**/*.blade.php', 'modules/**/*.php'],
|
||||||
'resources/js/views/**/*.vue',
|
|
||||||
'resources/js/components/**/*.vue',
|
|
||||||
'resources/js/layouts/**/*.vue',
|
|
||||||
'resources/views/**/*.blade.php',
|
|
||||||
'resources/js/composables/**/*.js',
|
|
||||||
'packages/medialibrary-helper/**/*.vue',
|
|
||||||
],
|
|
||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
colors: {
|
colors: {
|
||||||
|
@ -30,6 +23,9 @@ module.exports = {
|
||||||
900: 'hsl(181, 94%, 10%)',
|
900: 'hsl(181, 94%, 10%)',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
screens: {
|
||||||
|
navbar: '1024px',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Modules\Dashboard\Tests;
|
namespace Tests\Feature\Base;
|
||||||
|
|
||||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
use Livewire\Livewire;
|
use Livewire\Livewire;
|
||||||
use Tests\TestCase;
|
|
||||||
|
|
||||||
uses(DatabaseTransactions::class);
|
uses(DatabaseTransactions::class);
|
||||||
uses(TestCase::class);
|
|
||||||
|
|
||||||
it('renders successfully', function () {
|
it('renders successfully', function () {
|
||||||
$this->login()->loginNami();
|
$this->login()->loginNami();
|
|
@ -8,6 +8,8 @@ use App\Invoice\Models\Invoice;
|
||||||
use App\Invoice\Models\InvoicePosition;
|
use App\Invoice\Models\InvoicePosition;
|
||||||
use App\Member\Member;
|
use App\Member\Member;
|
||||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
|
use Livewire\Livewire;
|
||||||
|
use Modules\Invoice\MemberPaymentBlock as InvoiceMemberPaymentBlock;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class MemberPaymentBlockTest extends TestCase
|
class MemberPaymentBlockTest extends TestCase
|
||||||
|
@ -27,12 +29,8 @@ class MemberPaymentBlockTest extends TestCase
|
||||||
Invoice::factory()->has(InvoicePosition::factory()->price(600)->for($member), 'positions')->status(InvoiceStatus::NEW)->create();
|
Invoice::factory()->has(InvoicePosition::factory()->price(600)->for($member), 'positions')->status(InvoiceStatus::NEW)->create();
|
||||||
Invoice::factory()->has(InvoicePosition::factory()->price(1000)->for($member), 'positions')->status(InvoiceStatus::PAID)->create();
|
Invoice::factory()->has(InvoicePosition::factory()->price(1000)->for($member), 'positions')->status(InvoiceStatus::PAID)->create();
|
||||||
|
|
||||||
$data = app(MemberPaymentBlock::class)->render()['data'];
|
Livewire::test(InvoiceMemberPaymentBlock::class)
|
||||||
|
->assertSee('1 / 2')
|
||||||
$this->assertEquals([
|
->assertSee('51,00 €');
|
||||||
'amount' => '51,00 €',
|
|
||||||
'members' => 1,
|
|
||||||
'total_members' => 2,
|
|
||||||
], $data);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,9 @@ namespace Tests\Feature\Member;
|
||||||
use App\Group;
|
use App\Group;
|
||||||
use App\Member\Member;
|
use App\Member\Member;
|
||||||
use App\Member\Membership;
|
use App\Member\Membership;
|
||||||
use App\Member\PsPendingBlock;
|
|
||||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
|
use Livewire\Livewire;
|
||||||
|
use Modules\Prevention\PsPendingBlock;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class PsPendingBlockTest extends TestCase
|
class PsPendingBlockTest extends TestCase
|
||||||
|
@ -47,7 +48,7 @@ class PsPendingBlockTest extends TestCase
|
||||||
->defaults()
|
->defaults()
|
||||||
->for($group)
|
->for($group)
|
||||||
->has(Membership::factory()->in('€ LeiterIn', 5, 'Wölfling', 8)->ended())
|
->has(Membership::factory()->in('€ LeiterIn', 5, 'Wölfling', 8)->ended())
|
||||||
->create(['firstname' => 'Nora', 'lastname' => 'Doe', 'more_ps_at' => now()->subYears(5)]);
|
->create(['firstname' => 'Lisa', 'lastname' => 'Doe', 'more_ps_at' => now()->subYears(5)]);
|
||||||
$invalidPsButValidMorePs = Member::factory()
|
$invalidPsButValidMorePs = Member::factory()
|
||||||
->defaults()
|
->defaults()
|
||||||
->for($group)
|
->for($group)
|
||||||
|
@ -59,15 +60,15 @@ class PsPendingBlockTest extends TestCase
|
||||||
->has(Membership::factory()->in('€ Mitglied', 5, 'Wölfling', 8))
|
->has(Membership::factory()->in('€ Mitglied', 5, 'Wölfling', 8))
|
||||||
->create(['firstname' => 'Mae', 'lastname' => 'Doe']);
|
->create(['firstname' => 'Mae', 'lastname' => 'Doe']);
|
||||||
|
|
||||||
$data = app(PsPendingBlock::class)->render()['data'];
|
Livewire::test(PsPendingBlock::class)
|
||||||
|
->assertSee('Jane Doe')
|
||||||
$this->assertEquals([
|
->assertDontSee('Max Doe')
|
||||||
'members' => [
|
->assertDontSee('Joe Doe')
|
||||||
['fullname' => 'Jane Doe'],
|
->assertSee('Mike Doe')
|
||||||
['fullname' => 'Mike Doe'],
|
->assertSee('Nora Doe')
|
||||||
['fullname' => 'Nora Doe'],
|
->assertDontSee('Lisa Doe')
|
||||||
],
|
->assertDontSee('Hey Doe')
|
||||||
], $data);
|
->assertDontSee('Mae Doe');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testItExcludesForeignGroups(): void
|
public function testItExcludesForeignGroups(): void
|
||||||
|
@ -80,10 +81,9 @@ class PsPendingBlockTest extends TestCase
|
||||||
->defaults()
|
->defaults()
|
||||||
->for($otherGroup)
|
->for($otherGroup)
|
||||||
->has(Membership::factory()->in('€ LeiterIn', 5, 'Wölfling', 8))
|
->has(Membership::factory()->in('€ LeiterIn', 5, 'Wölfling', 8))
|
||||||
->create();
|
->create(['lastname' => 'Doe']);
|
||||||
|
|
||||||
$data = app(PsPendingBlock::class)->render()['data'];
|
Livewire::test(PsPendingBlock::class)
|
||||||
|
->assertDontSee('Doe');
|
||||||
$this->assertCount(0, $data['members']);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,9 @@ namespace Tests\Feature\Membership;
|
||||||
|
|
||||||
use App\Member\Member;
|
use App\Member\Member;
|
||||||
use App\Member\Membership;
|
use App\Member\Membership;
|
||||||
use App\Membership\AgeGroupCountBlock;
|
|
||||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
|
use Livewire\Livewire;
|
||||||
|
use Modules\Member\AgeGroupCountBlock;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class AgeGroupCountBlockTest extends TestCase
|
class AgeGroupCountBlockTest extends TestCase
|
||||||
|
@ -33,14 +34,10 @@ class AgeGroupCountBlockTest extends TestCase
|
||||||
->defaults()
|
->defaults()
|
||||||
->create();
|
->create();
|
||||||
|
|
||||||
$data = app(AgeGroupCountBlock::class)->render()['data'];
|
Livewire::test(AgeGroupCountBlock::class)
|
||||||
|
->assertSee('Biber')
|
||||||
$this->assertEquals([
|
->assertSee('Wölfling')
|
||||||
'groups' => [
|
->assertSee('Leiter')
|
||||||
['slug' => 'biber', 'name' => 'Biber', 'count' => 3],
|
->assertSeeInOrder([3, 4, 4]);
|
||||||
['slug' => 'woelfling', 'name' => 'Wölfling', 'count' => 4],
|
|
||||||
['slug' => 'leiter', 'name' => 'Leiter', 'count' => 4],
|
|
||||||
],
|
|
||||||
], $data);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@ use App\Group;
|
||||||
use App\Member\Member;
|
use App\Member\Member;
|
||||||
use App\Member\Membership;
|
use App\Member\Membership;
|
||||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
|
use Livewire\Livewire;
|
||||||
|
use Modules\Prevention\EfzPendingBlock as PreventionEfzPendingBlock;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class EfzPendingBlockTest extends TestCase
|
class EfzPendingBlockTest extends TestCase
|
||||||
|
@ -54,11 +56,10 @@ class EfzPendingBlockTest extends TestCase
|
||||||
->for($group)
|
->for($group)
|
||||||
->create(['firstname' => 'Doe', 'lastname' => 'Muster', 'efz' => now()->subYears(5)]);
|
->create(['firstname' => 'Doe', 'lastname' => 'Muster', 'efz' => now()->subYears(5)]);
|
||||||
|
|
||||||
$data = app(EfzPendingBlock::class)->render()['data'];
|
Livewire::test(PreventionEfzPendingBlock::class)
|
||||||
|
->assertSee('Joe Muster')
|
||||||
$this->assertEquals([
|
->assertSee('Mae Muster')
|
||||||
'members' => ['Joe Muster', 'Mae Muster', 'Moa Muster'],
|
->assertSee('Moa Muster');
|
||||||
], $data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testItExcludesForeignGroups(): void
|
public function testItExcludesForeignGroups(): void
|
||||||
|
@ -73,8 +74,7 @@ class EfzPendingBlockTest extends TestCase
|
||||||
->for($otherGroup)
|
->for($otherGroup)
|
||||||
->create(['firstname' => 'Joe', 'lastname' => 'Muster', 'efz' => now()->subYears(5)->endOfYear()]);
|
->create(['firstname' => 'Joe', 'lastname' => 'Muster', 'efz' => now()->subYears(5)->endOfYear()]);
|
||||||
|
|
||||||
$data = app(EfzPendingBlock::class)->render()['data'];
|
Livewire::test(PreventionEfzPendingBlock::class)
|
||||||
|
->assertDontSee('Joe');
|
||||||
$this->assertCount(0, $data['members']);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,9 @@ namespace Tests\Feature\Membership;
|
||||||
|
|
||||||
use App\Member\Member;
|
use App\Member\Member;
|
||||||
use App\Member\Membership;
|
use App\Member\Membership;
|
||||||
use App\Membership\TestersBlock;
|
|
||||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
|
use Livewire\Livewire;
|
||||||
|
use Modules\Member\TestersBlock;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class TestersBlockTest extends TestCase
|
class TestersBlockTest extends TestCase
|
||||||
|
@ -20,21 +21,15 @@ class TestersBlockTest extends TestCase
|
||||||
->defaults()
|
->defaults()
|
||||||
->has(Membership::factory()->in('Schnuppermitgliedschaft', 7, 'Wölfling', 8)->state(['from' => now()->subMonths(10)]))
|
->has(Membership::factory()->in('Schnuppermitgliedschaft', 7, 'Wölfling', 8)->state(['from' => now()->subMonths(10)]))
|
||||||
->create(['firstname' => 'Max', 'lastname' => 'Muster']);
|
->create(['firstname' => 'Max', 'lastname' => 'Muster']);
|
||||||
$inactiveMember = Member::factory()
|
Member::factory()
|
||||||
->defaults()
|
->defaults()
|
||||||
->has(Membership::factory()->ended()->in('Schnuppermitgliedschaft', 7, 'Wölfling', 8)->state(['from' => now()->subMonths(10)]))
|
->has(Membership::factory()->ended()->in('Schnuppermitgliedschaft', 7, 'Wölfling', 8)->state(['from' => now()->subMonths(10)]))
|
||||||
->create(['firstname' => 'Max', 'lastname' => 'Muster']);
|
->create(['firstname' => 'Jane', 'lastname' => 'Muster']);
|
||||||
|
|
||||||
$data = app(TestersBlock::class)->render()['data'];
|
Livewire::test(TestersBlock::class)
|
||||||
|
->assertSee('Max Muster')
|
||||||
$this->assertEquals([
|
->assertSee(now()->subMonths(10)->addWeeks(8)->format('d.m.Y'))
|
||||||
'members' => [
|
->assertSee(now()->subMonths(10)->addWeeks(8)->diffForHumans())
|
||||||
[
|
->assertDontSee('Jane');
|
||||||
'name' => 'Max Muster',
|
|
||||||
'try_ends_at' => now()->subMonths(10)->addWeeks(8)->format('d.m.Y'),
|
|
||||||
'try_ends_at_human' => now()->subMonths(10)->addWeeks(8)->diffForHumans(),
|
|
||||||
],
|
|
||||||
],
|
|
||||||
], $data);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import path from 'path';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [
|
plugins: [
|
||||||
laravel(['resources/js/app.js', 'resources/livewire-js/app.js']),
|
laravel(['resources/livewire-js/app.js']),
|
||||||
vue({
|
vue({
|
||||||
template: {
|
template: {
|
||||||
transformAssetUrls: {
|
transformAssetUrls: {
|
||||||
|
|
Loading…
Reference in New Issue