Add member registration via nami type

This commit is contained in:
philipp lang 2024-02-16 14:18:16 +01:00
parent 35b269c647
commit ef47480cc9
17 changed files with 196 additions and 12 deletions

View File

@ -2,6 +2,7 @@
namespace App\Form\Actions;
use App\Form\Fields\Field;
use App\Form\Models\Form;
use App\Form\Models\Participant;
use Illuminate\Http\JsonResponse;
@ -17,9 +18,13 @@ class RegisterAction
*/
public function handle(Form $form, array $input): Participant
{
return $form->participants()->create([
$participant = $form->participants()->create([
'data' => $input
]);
$form->getFields()->each(fn ($field) => Field::fromConfig($field)->afterRegistration($form, $participant, $input));
return $participant;
}
/**

View File

@ -2,7 +2,9 @@
namespace App\Form\Enums;
enum NamiField: string
use App\Member\Member;
enum NamiType: string
{
case FIRSTNAME = 'Vorname';
case LASTNAME = 'Nachname';
@ -17,4 +19,13 @@ enum NamiField: string
->map(fn ($case) => ['id' => $case->value, 'name' => $case->value])
->toArray();
}
public function getMemberAttribute(Member $member): ?string
{
return match ($this) {
static::FIRSTNAME => $member->firstname,
static::LASTNAME => $member->lastname,
static::BIRTHDAY => $member->birthday?->format('Y-m-d'),
};
}
}

View File

@ -2,6 +2,8 @@
namespace App\Form\Fields;
use App\Form\Models\Form;
use App\Form\Models\Participant;
use Faker\Generator;
use Illuminate\Validation\Rule;
@ -63,4 +65,8 @@ class CheckboxField extends Field
{
return [];
}
public function afterRegistration(Form $form, Participant $participant, array $input): void
{
}
}

View File

@ -2,6 +2,8 @@
namespace App\Form\Fields;
use App\Form\Models\Form;
use App\Form\Models\Participant;
use App\Form\Presenters\EnumPresenter;
use App\Form\Presenters\Presenter;
use Faker\Generator;
@ -70,4 +72,8 @@ class CheckboxesField extends Field
{
return app(EnumPresenter::class);
}
public function afterRegistration(Form $form, Participant $participant, array $input): void
{
}
}

View File

@ -3,6 +3,8 @@
namespace App\Form\Fields;
use App\Form\Contracts\Displayable;
use App\Form\Models\Form;
use App\Form\Models\Participant;
use App\Form\Presenters\DatePresenter;
use App\Form\Presenters\Presenter;
use Carbon\Carbon;
@ -80,4 +82,8 @@ class DateField extends Field
{
return app(DatePresenter::class);
}
public function afterRegistration(Form $form, Participant $participant, array $input): void
{
}
}

View File

@ -2,6 +2,8 @@
namespace App\Form\Fields;
use App\Form\Models\Form;
use App\Form\Models\Participant;
use Faker\Generator;
use Illuminate\Validation\Rule;
@ -62,4 +64,8 @@ class DropdownField extends Field
{
return [];
}
public function afterRegistration(Form $form, Participant $participant, array $input): void
{
}
}

View File

@ -2,6 +2,9 @@
namespace App\Form\Fields;
use App\Form\Enums\NamiType;
use App\Form\Models\Form;
use App\Form\Models\Participant;
use App\Form\Presenters\DefaultPresenter;
use App\Form\Presenters\Presenter;
use Faker\Generator;
@ -15,6 +18,9 @@ abstract class Field extends Data
public string $key;
public string $name;
public ?NamiType $namiType = null;
abstract public function afterRegistration(Form $form, Participant $participant, array $input): void;
abstract public static function name(): string;
@ -129,7 +135,7 @@ abstract class Field extends Data
'columns' => ['mobile' => 2, 'tablet' => 4, 'desktop' => 6],
'default' => static::default(),
'required' => false,
'nami_field' => null,
'nami_type' => null,
...collect(static::meta())->mapWithKeys(fn ($meta) => [$meta['key'] => $meta['default']])->toArray(),
],
];

View File

@ -2,6 +2,8 @@
namespace App\Form\Fields;
use App\Form\Models\Form;
use App\Form\Models\Participant;
use App\Form\Presenters\GroupPresenter;
use App\Form\Presenters\Presenter;
use App\Group;
@ -84,4 +86,8 @@ class GroupField extends Field
{
return app(GroupPresenter::class);
}
public function afterRegistration(Form $form, Participant $participant, array $input): void
{
}
}

View File

@ -0,0 +1,76 @@
<?php
namespace App\Form\Fields;
use App\Form\Models\Form;
use App\Form\Models\Participant;
use App\Member\Member;
use Faker\Generator;
class NamiField extends Field
{
public static function name(): string
{
return 'NaMi-Mitglieder';
}
public static function meta(): array
{
return [];
}
public static function default(): array
{
return [];
}
public static function fake(Generator $faker): array
{
return [];
}
/**
* @inheritdoc
*/
public function getRegistrationRules(): array
{
return [$this->key => []];
}
/**
* @inheritdoc
*/
public function getRegistrationAttributes(): array
{
return [$this->key => $this->name];
}
/**
* @inheritdoc
*/
public function getRegistrationMessages(): array
{
return [];
}
public function afterRegistration(Form $form, Participant $participant, array $input): void
{
$memberIds = array_column($input[$this->key], 'id');
foreach ($memberIds as $memberId) {
$member = Member::firstWhere(['mitgliedsnr' => $memberId]);
$data = [];
foreach ($form->getFields() as $field) {
$field = Field::fromConfig($field);
$data[$field->key] = $field->namiType === null
? $field->default()
: $field->namiType->getMemberAttribute($member);
}
$data[$this->key] = [];
$form->participants()->create(['data' => $data]);
}
}
}

View File

@ -2,6 +2,8 @@
namespace App\Form\Fields;
use App\Form\Models\Form;
use App\Form\Models\Participant;
use App\Form\Presenters\Presenter;
use Faker\Generator;
use Illuminate\Validation\Rule;
@ -63,4 +65,8 @@ class RadioField extends Field
{
return [];
}
public function afterRegistration(Form $form, Participant $participant, array $input): void
{
}
}

View File

@ -2,6 +2,8 @@
namespace App\Form\Fields;
use App\Form\Models\Form;
use App\Form\Models\Participant;
use Faker\Generator;
class TextField extends Field
@ -56,4 +58,8 @@ class TextField extends Field
{
return [];
}
public function afterRegistration(Form $form, Participant $participant, array $input): void
{
}
}

View File

@ -2,6 +2,8 @@
namespace App\Form\Fields;
use App\Form\Models\Form;
use App\Form\Models\Participant;
use Faker\Generator;
class TextareaField extends Field
@ -57,4 +59,8 @@ class TextareaField extends Field
{
return [];
}
public function afterRegistration(Form $form, Participant $participant, array $input): void
{
}
}

View File

@ -2,7 +2,7 @@
namespace App\Form\Resources;
use App\Form\Enums\NamiField;
use App\Form\Enums\NamiType;
use App\Form\Fields\Field;
use App\Form\FilterScope;
use App\Form\Models\Form;
@ -65,7 +65,7 @@ class FormResource extends JsonResource
'formtemplate_index' => route('formtemplate.index'),
],
'templates' => FormtemplateResource::collection(Formtemplate::get()),
'namiFields' => NamiField::forSelect(),
'namiFields' => NamiType::forSelect(),
'default' => [
'description' => [],
'name' => '',

View File

@ -2,11 +2,10 @@
namespace App\Form\Resources;
use App\Form\Enums\NamiField;
use App\Form\Enums\NamiType;
use App\Form\Fields\Field;
use App\Form\Models\Formtemplate;
use App\Group;
use App\Group\Enums\Level;
use App\Lib\HasMeta;
use Illuminate\Http\Resources\Json\JsonResource;
@ -43,7 +42,7 @@ class FormtemplateResource extends JsonResource
'base_url' => url(''),
'groups' => Group::forSelect(),
'fields' => Field::asMeta(),
'namiFields' => NamiField::forSelect(),
'namiFields' => NamiType::forSelect(),
'links' => [
'store' => route('formtemplate.store'),
'form_index' => route('form.index'),

View File

@ -2,16 +2,20 @@
namespace Tests\Feature\Form;
use App\Form\Enums\NamiField as EnumsNamiField;
use App\Form\Enums\NamiType;
use App\Form\Fields\CheckboxesField;
use App\Form\Fields\CheckboxField;
use App\Form\Fields\DateField;
use App\Form\Fields\DropdownField;
use App\Form\Fields\GroupField;
use App\Form\Fields\NamiField;
use App\Form\Fields\RadioField;
use App\Form\Fields\TextareaField;
use App\Form\Fields\TextField;
use App\Form\Models\Form;
use App\Group;
use App\Member\Member;
use Generator;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Tests\TestCase;
@ -275,4 +279,35 @@ class FormRegisterActionTest extends TestCase
$this->postJson(route('form.register', ['form' => $form]), ['parentgroup' => $group->children->first()->id, 'group' => $group->children->first()->children->first()->id])
->assertOk();
}
public function testItAddsMembersViaNami(): void
{
$this->login()->loginNami();
Member::factory()->defaults()->create(['mitgliedsnr' => '5505', 'firstname' => 'Abc', 'birthday' => '2023-01-05']);
Member::factory()->defaults()->create(['mitgliedsnr' => '5506', 'firstname' => 'Def', 'birthday' => '2023-01-06']);
$form = Form::factory()
->sections([FormtemplateSectionRequest::new()->fields([
FormtemplateFieldRequest::type(NamiField::class)->key('members'),
FormtemplateFieldRequest::type(TextField::class)->key('firstname')->required(true)->namiType(NamiType::FIRSTNAME),
FormtemplateFieldRequest::type(DateField::class)->key('birthday')->required(true)->namiType(NamiType::BIRTHDAY),
FormtemplateFieldRequest::type(TextField::class)->key('other')->namiType(null),
])])
->create();
$this->postJson(route('form.register', ['form' => $form]), ['firstname' => 'Aaaa', 'birthday' => '2021-04-05', 'other' => 'ooo', 'members' => [['id' => '5505'], ['id' => '5506']]])
->assertOk();
$this->assertCount(3, $form->participants()->get());
$this->assertEquals('Aaaa', $form->participants->get(0)->data['firstname']);
$this->assertEquals('Abc', $form->participants->get(1)->data['firstname']);
$this->assertEquals('Def', $form->participants->get(2)->data['firstname']);
$this->assertEquals('2021-04-05', $form->participants->get(0)->data['birthday']);
$this->assertEquals('2023-01-05', $form->participants->get(1)->data['birthday']);
$this->assertEquals('2023-01-06', $form->participants->get(2)->data['birthday']);
$this->assertEquals([['id' => '5505'], ['id' => '5506']], $form->participants->get(0)->data['members']);
$this->assertEquals([], $form->participants->get(1)->data['members']);
$this->assertEquals([], $form->participants->get(2)->data['members']);
$this->assertEquals('ooo', $form->participants->get(0)->data['other']);
$this->assertEquals('', $form->participants->get(1)->data['other']);
$this->assertEquals('', $form->participants->get(2)->data['other']);
}
}

View File

@ -3,6 +3,7 @@
namespace Tests\Feature\Form;
use App\Form\Enums\NamiField;
use App\Form\Enums\NamiType;
use App\Form\Fields\TextField;
use App\Form\Models\Form;
use App\Lib\Events\Succeeded;
@ -38,7 +39,7 @@ class FormStoreActionTest extends TestCase
->mailTop('Guten Tag')
->mailBottom('Viele Grüße')
->headerImage('htzz.jpg')
->sections([FormtemplateSectionRequest::new()->name('sname')->fields([FormtemplateFieldRequest::type(TextField::class)->namiField(NamiField::BIRTHDAY)])])
->sections([FormtemplateSectionRequest::new()->name('sname')->fields([FormtemplateFieldRequest::type(TextField::class)->namiType(NamiType::BIRTHDAY)])])
->fake();
$this->postJson(route('form.store'))->assertOk();
@ -54,7 +55,7 @@ class FormStoreActionTest extends TestCase
$this->assertEquals('2023-07-07 01:00', $form->registration_until->format('Y-m-d H:i'));
$this->assertEquals('2023-07-07', $form->from->format('Y-m-d'));
$this->assertEquals('2023-07-08', $form->to->format('Y-m-d'));
$this->assertEquals('Geburtstag', $form->config['sections'][0]['fields'][0]['nami_field']);
$this->assertEquals('Geburtstag', $form->config['sections'][0]['fields'][0]['nami_type']);
$this->assertCount(1, $form->getMedia('headerImage'));
$this->assertEquals('formname.jpg', $form->getMedia('headerImage')->first()->file_name);
Event::assertDispatched(Succeeded::class, fn (Succeeded $event) => $event->message === 'Veranstaltung gespeichert.');

View File

@ -38,10 +38,11 @@ class FormtemplateIndexActionTest extends TestCase
'columns' => ['mobile' => 2, 'tablet' => 4, 'desktop' => 6],
'default' => null,
'required' => false,
'nami_type' => null,
'options' => [],
]
])
->assertInertiaPath('data.meta.fields.6', [
->assertInertiaPath('data.meta.fields.7', [
'id' => 'TextField',
'name' => 'Text',
'default' => [
@ -50,9 +51,10 @@ class FormtemplateIndexActionTest extends TestCase
'columns' => ['mobile' => 2, 'tablet' => 4, 'desktop' => 6],
'default' => '',
'required' => false,
'nami_type' => null,
]
])
->assertInertiaPath('data.meta.fields.7', [
->assertInertiaPath('data.meta.fields.8', [
'id' => 'TextareaField',
'name' => 'Textarea',
'default' => [
@ -61,6 +63,7 @@ class FormtemplateIndexActionTest extends TestCase
'columns' => ['mobile' => 2, 'tablet' => 4, 'desktop' => 6],
'default' => '',
'required' => false,
'nami_type' => null,
'rows' => 5,
]
])