Add: Store participant

This commit is contained in:
philipp lang 2024-07-13 18:24:43 +02:00
parent d9c45f5236
commit 657a648f46
6 changed files with 115 additions and 6 deletions

View File

@ -0,0 +1,56 @@
<?php
namespace App\Form\Actions;
use App\Form\Models\Form;
use App\Form\Models\Participant;
use App\Lib\Events\Succeeded;
use Illuminate\Http\JsonResponse;
use Lorisleiva\Actions\ActionRequest;
use Lorisleiva\Actions\Concerns\AsAction;
class ParticipantStoreAction
{
use AsAction;
/**
* @return array<string, mixed>
*/
public function rules(): array
{
/** @var Form */
$form = request()->route('form');
return $form->getRegistrationRules();
}
/**
* @return array<string, mixed>
*/
public function getValidationAttributes(): array
{
/** @var Form */
$form = request()->route('form');
return $form->getRegistrationAttributes();
}
/**
* @return array<string, mixed>
*/
public function getValidationMessages(): array
{
/** @var Form */
$form = request()->route('form');
return $form->getRegistrationMessages();
}
public function handle(Form $form, ActionRequest $request): JsonResponse
{
$form->participants()->create(['data' => $request->validated()]);
ExportSyncAction::dispatch($form->id);
Succeeded::message('Teilnehmer*in erstellt.')->dispatch();
return response()->json([]);
}
}

View File

@ -60,12 +60,14 @@ class ParticipantResource extends JsonResource
return [ return [
'filter' => ParticipantFilterScope::fromRequest(request()->input('filter', ''))->setForm($form), 'filter' => ParticipantFilterScope::fromRequest(request()->input('filter', ''))->setForm($form),
'form_config' => $form->config,
'default_filter_value' => ParticipantFilterScope::$nan, 'default_filter_value' => ParticipantFilterScope::$nan,
'filters' => $filterData, 'filters' => $filterData,
'form_meta' => $form->meta, 'form_meta' => $form->meta,
'has_nami_field' => $form->getFields()->hasNamiField(), 'has_nami_field' => $form->getFields()->hasNamiField(),
'links' => [ 'links' => [
'update_form_meta' => route('form.update-meta', ['form' => $form]), 'update_form_meta' => route('form.update-meta', ['form' => $form]),
'store_participant' => route('form.participant.store', ['form' => $form]),
], ],
'columns' => $fieldData->push([ 'columns' => $fieldData->push([
'name' => 'Registriert am', 'name' => 'Registriert am',

View File

@ -1,8 +1,8 @@
<template> <template>
<div class="mt-5"> <div>
<ui-popup v-if="editing !== null" heading="Mitglied bearbeiten" closeable full @close="editing = null"> <ui-popup v-if="editing !== null" heading="Mitglied bearbeiten" closeable full @close="editing = null">
<event-form <event-form
:value="editingPreviewString" :value="editing.preview"
:base-url="meta.base_url" :base-url="meta.base_url"
style="--primary: hsl(181, 75%, 26%); --secondary: hsl(181, 75%, 35%); --font: hsl(181, 84%, 78%); --circle: hsl(181, 86%, 16%)" style="--primary: hsl(181, 75%, 26%); --secondary: hsl(181, 75%, 35%); --font: hsl(181, 84%, 78%); --circle: hsl(181, 86%, 16%)"
as-form as-form
@ -22,6 +22,7 @@
</div> </div>
</ui-popup> </ui-popup>
<page-filter breakpoint="lg"> <page-filter breakpoint="lg">
<ui-icon-button icon="plus" @click="editing = {participant: null, preview: JSON.stringify(meta.form_config)}">Hinzufügen</ui-icon-button>
<f-switch v-if="meta.has_nami_field" id="group_participants" v-model="groupParticipants" label="Gruppieren" size="sm" name="group_participants"></f-switch> <f-switch v-if="meta.has_nami_field" id="group_participants" v-model="groupParticipants" label="Gruppieren" size="sm" name="group_participants"></f-switch>
<f-multipleselect id="active_columns" v-model="activeColumnsConfig" :options="meta.columns" label="Aktive Spalten" size="sm"></f-multipleselect> <f-multipleselect id="active_columns" v-model="activeColumnsConfig" :options="meta.columns" label="Aktive Spalten" size="sm"></f-multipleselect>
@ -216,12 +217,16 @@ async function editReal(participant) {
const response = await axios.get(participant.links.fields); const response = await axios.get(participant.links.fields);
editing.value = { editing.value = {
participant: participant, participant: participant,
config: response.data.data.config, preview: JSON.stringify(response.data.data.config),
}; };
} }
async function updateParticipant(payload) { async function updateParticipant(payload) {
await axios.patch(editing.value.participant.links.update, {data: payload}); if (editing.value.participant === null) {
await axios.post(meta.value.links.store_participant, payload);
} else {
await axios.patch(editing.value.participant.links.update, payload);
}
await reload(); await reload();
@ -229,5 +234,4 @@ async function updateParticipant(payload) {
} }
const editing = ref(null); const editing = ref(null);
const editingPreviewString = computed(() => editing.value === null ? '' : JSON.stringify(editing.value.config));
</script> </script>

View File

@ -40,6 +40,7 @@ use App\Form\Actions\ParticipantAssignAction;
use App\Form\Actions\ParticipantDestroyAction; use App\Form\Actions\ParticipantDestroyAction;
use App\Form\Actions\ParticipantFieldsAction; use App\Form\Actions\ParticipantFieldsAction;
use App\Form\Actions\ParticipantIndexAction; use App\Form\Actions\ParticipantIndexAction;
use App\Form\Actions\ParticipantStoreAction;
use App\Form\Actions\ParticipantUpdateAction; use App\Form\Actions\ParticipantUpdateAction;
use App\Initialize\Actions\InitializeAction; use App\Initialize\Actions\InitializeAction;
use App\Initialize\Actions\InitializeFormAction; use App\Initialize\Actions\InitializeFormAction;
@ -176,6 +177,7 @@ Route::group(['middleware' => 'auth:web'], function (): void {
Route::post('/participant/{participant}/assign', ParticipantAssignAction::class)->name('participant.assign'); Route::post('/participant/{participant}/assign', ParticipantAssignAction::class)->name('participant.assign');
Route::get('/participant/{participant}/fields', ParticipantFieldsAction::class)->name('participant.fields'); Route::get('/participant/{participant}/fields', ParticipantFieldsAction::class)->name('participant.fields');
Route::patch('/participant/{participant}', ParticipantUpdateAction::class)->name('participant.update'); Route::patch('/participant/{participant}', ParticipantUpdateAction::class)->name('participant.update');
Route::post('/form/{form}/participant', ParticipantStoreAction::class)->name('form.participant.store');
// ------------------------------------ fileshare ----------------------------------- // ------------------------------------ fileshare -----------------------------------
Route::post('/fileshare', FileshareStoreAction::class)->name('fileshare.store'); Route::post('/fileshare', FileshareStoreAction::class)->name('fileshare.store');

View File

@ -58,7 +58,9 @@ class ParticipantIndexActionTest extends FormTestCase
->assertJsonPath('meta.form_meta.active_columns', ['vorname', 'select', 'stufe', 'test1']) ->assertJsonPath('meta.form_meta.active_columns', ['vorname', 'select', 'stufe', 'test1'])
->assertJsonPath('meta.has_nami_field', false) ->assertJsonPath('meta.has_nami_field', false)
->assertJsonPath('meta.links.update_form_meta', route('form.update-meta', ['form' => $form])) ->assertJsonPath('meta.links.update_form_meta', route('form.update-meta', ['form' => $form]))
->assertJsonPath('meta.form_meta.sorting', ['vorname', 'asc']); ->assertJsonPath('meta.links.store_participant', route('form.participant.store', ['form' => $form]))
->assertJsonPath('meta.form_meta.sorting', ['vorname', 'asc'])
->assertJsonPath('meta.form_config.sections.0.fields.0.key', 'vorname');
} }
public function testItShowsEmptyFilters(): void public function testItShowsEmptyFilters(): void

View File

@ -0,0 +1,43 @@
<?php
namespace Tests\Feature\Form;
use App\Form\Actions\ExportSyncAction;
use App\Form\Models\Form;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Queue;
class ParticipantStoreActionTest extends FormTestCase
{
use DatabaseTransactions;
public function testItStoresParticipant(): void
{
Queue::fake();
$this->login()->loginNami()->withoutExceptionHandling();
$form = Form::factory()->fields([
$this->textField('vorname')->name('Vorname')->required(true),
])
->create();
$this->postJson(route('form.participant.store', ['form' => $form->id]), ['vorname' => 'Jane'])
->assertOk();
$this->assertEquals('Jane', $form->participants->first()->data['vorname']);
ExportSyncAction::assertPushed();
}
public function testItHasValidation(): void
{
Queue::fake();
$this->login()->loginNami();
$form = Form::factory()->fields([
$this->textField('vorname')->name('Vorname')->required(true),
])
->create();
$this->postJson(route('form.participant.store', ['form' => $form->id]), ['vorname' => ''])
->assertJsonValidationErrors(['vorname' => 'Vorname ist erforderlich.']);
}
}