Add form api to display event overview on website

This commit is contained in:
philipp lang 2024-01-12 22:52:42 +01:00
parent e005ed0d0d
commit e011b52534
8 changed files with 194 additions and 2 deletions

View File

@ -0,0 +1,29 @@
<?php
namespace App\Form\Actions;
use App\Form\FilterScope;
use App\Form\Models\Form;
use App\Form\Resources\FormApiResource;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
use Lorisleiva\Actions\ActionRequest;
use Lorisleiva\Actions\Concerns\AsAction;
class FormApiListAction
{
use AsAction;
/**
* @return Collection<int, Form>
*/
public function handle(FilterScope $filter): Collection
{
return Form::withFilter($filter)->get();
}
public function asController(ActionRequest $request): AnonymousResourceCollection
{
return FormApiResource::collection($this->handle(FilterScope::fromRequest($request->input('filter', ''))));
}
}

40
app/Form/FilterScope.php Normal file
View File

@ -0,0 +1,40 @@
<?php
namespace App\Form;
use App\Form\Models\Form;
use App\Lib\Filter;
use Illuminate\Database\Eloquent\Builder;
use Spatie\LaravelData\Attributes\MapInputName;
use Spatie\LaravelData\Attributes\MapOutputName;
use Spatie\LaravelData\Mappers\SnakeCaseMapper;
/**
* @extends Filter<Form>
*/
#[MapInputName(SnakeCaseMapper::class)]
#[MapOutputName(SnakeCaseMapper::class)]
class FilterScope extends Filter
{
public function __construct()
{
}
/**
* {@inheritdoc}
*/
public function locks(): array
{
return [];
}
/**
* @param Builder<Form> $query
*
* @return Builder<Form>
*/
public function apply(Builder $query): Builder
{
return $query;
}
}

View File

@ -2,12 +2,16 @@
namespace App\Form\Models; namespace App\Form\Models;
use App\Form\FilterScope;
use Cviebrock\EloquentSluggable\Sluggable;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
class Form extends Model class Form extends Model
{ {
use HasFactory; use HasFactory;
use Sluggable;
public $guarded = []; public $guarded = [];
@ -15,6 +19,23 @@ class Form extends Model
'config' => 'json', 'config' => 'json',
]; ];
public function sluggable(): array
{
return [
'slug' => ['source' => ['name']],
];
}
/** @var array<int, string> */ /** @var array<int, string> */
public $dates = ['from', 'to', 'registration_from', 'registration_until']; public $dates = ['from', 'to', 'registration_from', 'registration_until'];
/**
* @param Builder<self> $query
*
* @return Builder<self>
*/
public function scopeWithFilter(Builder $query, FilterScope $filter): Builder
{
return $filter->apply($query);
}
} }

View File

@ -0,0 +1,46 @@
<?php
namespace App\Form\Resources;
use App\Form\Models\Form;
use App\Lib\HasMeta;
use Illuminate\Http\Resources\Json\JsonResource;
/**
* @mixin Form
*/
class FormApiResource extends JsonResource
{
use HasMeta;
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array<string, mixed>
*/
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'from_human' => $this->from->format('d.m.Y'),
'to_human' => $this->to->format('d.m.Y'),
'excerpt' => $this->excerpt,
'description' => $this->description,
'config' => $this->config,
'slug' => $this->slug,
'dates' => $this->from->equalTo($this->to) ? $this->from->format('d.m.Y') : $this->from->format('d.m.Y') . ' - ' . $this->to->format('d.m.Y'),
];
}
/**
* @return array<string, mixed>
*/
public static function meta(): array
{
return [
'base_url' => url(''),
];
}
}

View File

@ -41,8 +41,8 @@ class FormFactory extends Factory
'config' => ['sections' => []], 'config' => ['sections' => []],
'from' => $this->faker->dateTime()->format('Y-m-d H:i:s'), 'from' => $this->faker->dateTime()->format('Y-m-d H:i:s'),
'to' => $this->faker->dateTime()->format('Y-m-d H:i:s'), 'to' => $this->faker->dateTime()->format('Y-m-d H:i:s'),
'registration_from' => $this->faker->dateTime()->format('Y-m-d H:i:s'), 'registration_from' => $this->faker->dateTimeBetween('-2 weeks', 'now')->format('Y-m-d H:i:s'),
'registration_until' => $this->faker->dateTime()->format('Y-m-d H:i:s'), 'registration_until' => $this->faker->dateTimeBetween('now', '+2 weeks')->format('Y-m-d H:i:s'),
'mail_top' => $this->faker->text(), 'mail_top' => $this->faker->text(),
'mail_bottom' => $this->faker->text(), 'mail_bottom' => $this->faker->text(),
]; ];

View File

@ -23,6 +23,7 @@ return new class extends Migration
Schema::create('forms', function (Blueprint $table) { Schema::create('forms', function (Blueprint $table) {
$table->id(); $table->id();
$table->string('name'); $table->string('name');
$table->string('slug');
$table->text('description'); $table->text('description');
$table->text('excerpt'); $table->text('excerpt');
$table->json('config'); $table->json('config');
@ -44,5 +45,6 @@ return new class extends Migration
public function down() public function down()
{ {
Schema::dropIfExists('formtemplates'); Schema::dropIfExists('formtemplates');
Schema::dropIfExists('forms');
} }
}; };

View File

@ -19,6 +19,7 @@ use App\Invoice\Actions\InvoiceStoreAction;
use App\Course\Actions\CourseUpdateAction; use App\Course\Actions\CourseUpdateAction;
use App\Dashboard\Actions\IndexAction as DashboardIndexAction; use App\Dashboard\Actions\IndexAction as DashboardIndexAction;
use App\Efz\ShowEfzDocumentAction; use App\Efz\ShowEfzDocumentAction;
use App\Form\Actions\FormApiListAction;
use App\Form\Actions\FormDestroyAction; use App\Form\Actions\FormDestroyAction;
use App\Form\Actions\FormIndexAction; use App\Form\Actions\FormIndexAction;
use App\Group\Actions\GroupApiIndexAction; use App\Group\Actions\GroupApiIndexAction;
@ -158,3 +159,4 @@ Route::group(['middleware' => 'auth:web'], function (): void {
}); });
Route::get('/api/group/{group?}', GroupApiIndexAction::class)->name('api.group'); Route::get('/api/group/{group?}', GroupApiIndexAction::class)->name('api.group');
Route::get('/api/form', FormApiListAction::class)->name('api.form.index');

View File

@ -0,0 +1,52 @@
<?php
namespace Tests\Feature\Form;
use App\Form\Models\Form;
use App\Form\Models\Formtemplate;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Tests\TestCase;
class FormApiListActionTest extends TestCase
{
use DatabaseTransactions;
public function testItDisplaysForms(): void
{
$this->loginNami()->withoutExceptionHandling();
Formtemplate::factory()->name('tname')->sections([FormtemplateSectionRequest::new()->name('sname')])->create();
$form = Form::factory()
->name('lala 2')
->excerpt('fff')
->description('desc')
->from('2023-05-05')
->to('2023-06-07')
->sections([FormtemplateSectionRequest::new()->name('sname')->fields([FormtemplateFieldRequest::new()])])
->create();
$this->get('/api/form')
->assertOk()
->assertJsonPath('data.0.name', 'lala 2')
->assertJsonPath('data.0.config.sections.0.name', 'sname')
->assertJsonPath('data.0.id', $form->id)
->assertJsonPath('data.0.excerpt', 'fff')
->assertJsonPath('data.0.description', 'desc')
->assertJsonPath('data.0.slug', 'lala-2')
->assertJsonPath('data.0.dates', '05.05.2023 - 07.06.2023')
->assertJsonPath('data.0.from_human', '05.05.2023')
->assertJsonPath('data.0.to_human', '07.06.2023');
}
public function testItDisplaysDailyForms(): void
{
$this->loginNami()->withoutExceptionHandling();
Form::factory()
->from('2023-05-05')
->to('2023-05-05')
->create();
$this->get('/api/form')
->assertJsonPath('data.0.dates', '05.05.2023');
}
}