From 0c4e12132a4583e3212ef41db7fe9c2ea5683b77 Mon Sep 17 00:00:00 2001 From: philipp lang Date: Wed, 11 Jun 2025 23:25:50 +0200 Subject: [PATCH] Add types for membership --- app/Lib/Data/DateData.php | 32 ++ app/Lib/Normalizers/DateNormalizer.php | 21 + app/Lib/Transformers/DateTransformer.php | 16 + app/Member/Data/ActivityData.php | 2 + app/Member/Data/GroupData.php | 2 + app/Member/Data/MembershipData.php | 14 +- app/Member/Data/SubactivityData.php | 2 + composer.json | 1 + composer.lock | 186 +++++++-- config/typescript-transformer.php | 88 +++++ resources/types/generated.d.ts | 480 +++++++++++++++++++++++ tests/Feature/Membership/IndexTest.php | 3 +- 12 files changed, 811 insertions(+), 36 deletions(-) create mode 100644 app/Lib/Data/DateData.php create mode 100644 app/Lib/Normalizers/DateNormalizer.php create mode 100644 app/Lib/Transformers/DateTransformer.php create mode 100644 config/typescript-transformer.php create mode 100644 resources/types/generated.d.ts diff --git a/app/Lib/Data/DateData.php b/app/Lib/Data/DateData.php new file mode 100644 index 00000000..5c86aeaa --- /dev/null +++ b/app/Lib/Data/DateData.php @@ -0,0 +1,32 @@ + $value, + 'human' => $value->format('d.m.Y'), + ]; + } +} diff --git a/app/Lib/Transformers/DateTransformer.php b/app/Lib/Transformers/DateTransformer.php new file mode 100644 index 00000000..472b0f47 --- /dev/null +++ b/app/Lib/Transformers/DateTransformer.php @@ -0,0 +1,16 @@ +format('Y-m-d'); + } +} diff --git a/app/Member/Data/ActivityData.php b/app/Member/Data/ActivityData.php index 2e346d2c..51717a34 100644 --- a/app/Member/Data/ActivityData.php +++ b/app/Member/Data/ActivityData.php @@ -6,9 +6,11 @@ use Spatie\LaravelData\Data; use Spatie\LaravelData\Attributes\MapInputName; use Spatie\LaravelData\Attributes\MapOutputName; use Spatie\LaravelData\Mappers\SnakeCaseMapper; +use Spatie\TypeScriptTransformer\Attributes\Typescript; #[MapInputName(SnakeCaseMapper::class)] #[MapOutputName(SnakeCaseMapper::class)] +#[TypeScript] class ActivityData extends Data { public function __construct( diff --git a/app/Member/Data/GroupData.php b/app/Member/Data/GroupData.php index 892b665f..84599e9c 100644 --- a/app/Member/Data/GroupData.php +++ b/app/Member/Data/GroupData.php @@ -6,9 +6,11 @@ use Spatie\LaravelData\Data; use Spatie\LaravelData\Attributes\MapInputName; use Spatie\LaravelData\Attributes\MapOutputName; use Spatie\LaravelData\Mappers\SnakeCaseMapper; +use Spatie\TypeScriptTransformer\Attributes\Typescript; #[MapInputName(SnakeCaseMapper::class)] #[MapOutputName(SnakeCaseMapper::class)] +#[TypeScript] class GroupData extends Data { public function __construct( diff --git a/app/Member/Data/MembershipData.php b/app/Member/Data/MembershipData.php index 3c7df8cd..c1590f71 100644 --- a/app/Member/Data/MembershipData.php +++ b/app/Member/Data/MembershipData.php @@ -6,13 +6,15 @@ use Spatie\LaravelData\Data; use Spatie\LaravelData\Attributes\MapInputName; use Spatie\LaravelData\Attributes\MapOutputName; use Spatie\LaravelData\Mappers\SnakeCaseMapper; -use Carbon\Carbon; use App\Member\Membership; use App\Member\Member; use App\Activity; +use App\Lib\Data\DateData; +use Spatie\TypeScriptTransformer\Attributes\Typescript; #[MapInputName(SnakeCaseMapper::class)] #[MapOutputName(SnakeCaseMapper::class)] +#[TypeScript] class MembershipData extends Data { @@ -21,8 +23,8 @@ class MembershipData extends Data public ActivityData $activity, public SubactivityData $subactivity, public GroupData $group, - public Carbon $from, - public ?Carbon $promisedAt, + public ?DateData $promisedAt, + public DateData $from, public bool $isActive, ) {} @@ -45,9 +47,9 @@ class MembershipData extends Data public function with(): array { return [ - 'human_date' => $this->from->format('d.m.Y'), - 'promised_at_human' => $this->promisedAt?->format('d.m.Y'), - 'promised_at' => $this->promisedAt?->format('Y-m-d'), + // 'human_date' => $this->from->format('d.m.Y'), + // 'promised_at_human' => $this->promisedAt?->format('d.m.Y'), + // 'promised_at' => $this->promisedAt?->format('Y-m-d'), 'links' => [ 'update' => route('membership.update', ['membership' => $this->id]), 'destroy' => route('membership.destroy', ['membership' => $this->id]), diff --git a/app/Member/Data/SubactivityData.php b/app/Member/Data/SubactivityData.php index e8dea078..fdea4742 100644 --- a/app/Member/Data/SubactivityData.php +++ b/app/Member/Data/SubactivityData.php @@ -6,9 +6,11 @@ use Spatie\LaravelData\Data; use Spatie\LaravelData\Attributes\MapInputName; use Spatie\LaravelData\Attributes\MapOutputName; use Spatie\LaravelData\Mappers\SnakeCaseMapper; +use Spatie\TypeScriptTransformer\Attributes\Typescript; #[MapInputName(SnakeCaseMapper::class)] #[MapOutputName(SnakeCaseMapper::class)] +#[TypeScript] class SubactivityData extends Data { public function __construct( diff --git a/composer.json b/composer.json index 119e7bde..32a80fcf 100644 --- a/composer.json +++ b/composer.json @@ -70,6 +70,7 @@ "spatie/laravel-data": "^4.0", "spatie/laravel-ignition": "^2.0", "spatie/laravel-settings": "^3.0", + "spatie/laravel-typescript-transformer": "^2.5", "worksome/request-factories": "^3.0", "zoomyboy/laravel-nami": "dev-master", "zoomyboy/medialibrary-helper": "dev-master as 1.0", diff --git a/composer.lock b/composer.lock index 87bbf04d..fc723615 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b901e66375d81c04e5067a7352780f13", + "content-hash": "e5a34643b9d5b3f0fe8e4cc9c7e9570d", "packages": [ { "name": "amphp/amp", @@ -11389,6 +11389,87 @@ ], "time": "2025-02-14T14:40:11+00:00" }, + { + "name": "spatie/laravel-typescript-transformer", + "version": "2.5.2", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-typescript-transformer.git", + "reference": "a268a08341f5a5d8f80a79493642a43275d219a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-typescript-transformer/zipball/a268a08341f5a5d8f80a79493642a43275d219a5", + "reference": "a268a08341f5a5d8f80a79493642a43275d219a5", + "shasum": "" + }, + "require": { + "illuminate/console": "^8.83|^9.30|^10.0|^11.0|^12.0", + "php": "^8.1", + "spatie/laravel-package-tools": "^1.12", + "spatie/typescript-transformer": "^2.4" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.0", + "mockery/mockery": "^1.4", + "nesbot/carbon": "^2.63|^3.0", + "orchestra/testbench": "^6.0|^7.0|^8.0|^9.0|^10.0", + "pestphp/pest": "^1.22|^2.0|^3.0", + "phpunit/phpunit": "^9.0|^10.0|^11.0|^12.0", + "spatie/data-transfer-object": "^2.0", + "spatie/enum": "^3.0", + "spatie/laravel-model-states": "^1.6|^2.0", + "spatie/pest-plugin-snapshots": "^1.1|^2.0", + "spatie/phpunit-snapshot-assertions": "^4.2|^5.0", + "spatie/temporary-directory": "^1.2" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\LaravelTypeScriptTransformer\\TypeScriptTransformerServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Spatie\\LaravelTypeScriptTransformer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ruben Van Assche", + "email": "ruben@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "Transform your PHP structures to TypeScript types", + "homepage": "https://github.com/spatie/typescript-transformer", + "keywords": [ + "spatie", + "typescript-transformer" + ], + "support": { + "issues": "https://github.com/spatie/laravel-typescript-transformer/issues", + "source": "https://github.com/spatie/laravel-typescript-transformer/tree/2.5.2" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2025-04-25T14:09:28+00:00" + }, { "name": "spatie/php-structure-discoverer", "version": "2.3.1", @@ -11529,6 +11610,78 @@ ], "time": "2025-01-13T13:04:43+00:00" }, + { + "name": "spatie/typescript-transformer", + "version": "2.5.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/typescript-transformer.git", + "reference": "dd7cbb90b6b8c34f2aee68701cf39c5432400c0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/typescript-transformer/zipball/dd7cbb90b6b8c34f2aee68701cf39c5432400c0d", + "reference": "dd7cbb90b6b8c34f2aee68701cf39c5432400c0d", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18|^5.0", + "php": "^8.1", + "phpdocumentor/type-resolver": "^1.6.2", + "symfony/process": "^5.2|^6.0|^7.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.40", + "larapack/dd": "^1.1", + "myclabs/php-enum": "^1.7", + "pestphp/pest": "^1.22", + "phpstan/extension-installer": "^1.1", + "phpunit/phpunit": "^9.0", + "spatie/data-transfer-object": "^2.0", + "spatie/enum": "^3.0", + "spatie/pest-plugin-snapshots": "^1.1", + "spatie/temporary-directory": "^1.2|^2.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\TypeScriptTransformer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ruben Van Assche", + "email": "ruben@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "Transform your PHP structures to TypeScript types", + "homepage": "https://github.com/spatie/typescript-transformer", + "keywords": [ + "spatie", + "typescript-transformer" + ], + "support": { + "issues": "https://github.com/spatie/typescript-transformer/issues", + "source": "https://github.com/spatie/typescript-transformer/tree/2.5.0" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2025-04-25T13:53:57+00:00" + }, { "name": "staabm/side-effects-detector", "version": "1.0.5", @@ -14702,7 +14855,7 @@ "dist": { "type": "path", "url": "./packages/tex", - "reference": "48251272de62e3fea044a7ad31e1a411c15eb4c6" + "reference": "ed283d97ca7680b3c27b2d75da9937f4f379e321" }, "type": "library", "extra": { @@ -15792,32 +15945,7 @@ "time": "2025-03-03T07:12:39+00:00" } ], - "aliases": [ - { - "package": "league/flysystem-webdav", - "version": "9999999-dev", - "alias": "3.28.0", - "alias_normalized": "3.28.0.0" - }, - { - "package": "zoomyboy/medialibrary-helper", - "version": "9999999-dev", - "alias": "1.0", - "alias_normalized": "1.0.0.0" - }, - { - "package": "zoomyboy/table-document", - "version": "9999999-dev", - "alias": "1.0", - "alias_normalized": "1.0.0.0" - }, - { - "package": "zoomyboy/tex", - "version": "dev-main", - "alias": "1.0", - "alias_normalized": "1.0.0.0" - } - ], + "aliases": [], "minimum-stability": "dev", "stability-flags": { "league/flysystem-webdav": 20, @@ -15832,5 +15960,5 @@ "php": "^8.3" }, "platform-dev": [], - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.2.0" } diff --git a/config/typescript-transformer.php b/config/typescript-transformer.php new file mode 100644 index 00000000..08a1d4cc --- /dev/null +++ b/config/typescript-transformer.php @@ -0,0 +1,88 @@ + [ + app_path(), + ], + + /* + * Collectors will search for classes in the `auto_discover_types` paths and choose the correct + * transformer to transform them. By default, we include a DefaultCollector which will search + * for @typescript annotated and #[TypeScript] attributed classes to transform. + */ + + 'collectors' => [ + Spatie\TypeScriptTransformer\Collectors\DefaultCollector::class, + Spatie\TypeScriptTransformer\Collectors\EnumCollector::class, + Spatie\LaravelData\Support\TypeScriptTransformer\DataTypeScriptCollector::class, + ], + + /* + * Transformers take PHP classes(e.g., enums) as an input and will output + * a TypeScript representation of the PHP class. + */ + + 'transformers' => [ + Spatie\LaravelTypeScriptTransformer\Transformers\SpatieStateTransformer::class, + Spatie\TypeScriptTransformer\Transformers\EnumTransformer::class, + Spatie\TypeScriptTransformer\Transformers\SpatieEnumTransformer::class, + Spatie\LaravelData\Support\TypeScriptTransformer\DataTypeScriptTransformer::class, + Spatie\LaravelTypeScriptTransformer\Transformers\DtoTransformer::class, + ], + + /* + * In your classes, you sometimes have types that should always be replaced + * by the same TypeScript representations. For example, you can replace a + * Datetime always with a string. You define these replacements here. + */ + + 'default_type_replacements' => [ + DateTime::class => 'string', + DateTimeImmutable::class => 'string', + Carbon\CarbonInterface::class => 'string', + Carbon\CarbonImmutable::class => 'string', + Carbon\Carbon::class => 'string', + ], + + /* + * The package will write the generated TypeScript to this file. + */ + + 'output_file' => resource_path('types/generated.d.ts'), + + /* + * When the package is writing types to the output file, a writer is used to + * determine the format. By default, this is the `TypeDefinitionWriter`. + * But you can also use the `ModuleWriter` or implement your own. + */ + + 'writer' => Spatie\TypeScriptTransformer\Writers\TypeDefinitionWriter::class, + + /* + * The generated TypeScript file can be formatted. We ship a Prettier formatter + * out of the box: `PrettierFormatter` but you can also implement your own one. + * The generated TypeScript will not be formatted when no formatter was set. + */ + + 'formatter' => null, + + /* + * Enums can be transformed into types or native TypeScript enums, by default + * the package will transform them to types. + */ + + 'transform_to_native_enums' => false, + + /* + * By default, this package will convert PHP nullable properties to TypeScript + * types using a `null` type union. Setting `transform_null_to_optional` will + * make them optional instead. + */ + + 'transform_null_to_optional' => false, +]; diff --git a/resources/types/generated.d.ts b/resources/types/generated.d.ts new file mode 100644 index 00000000..ee948cea --- /dev/null +++ b/resources/types/generated.d.ts @@ -0,0 +1,480 @@ +declare namespace App.Contribution.Data { +export type MemberData = { +firstname: string; +lastname: string; +address: string; +zip: string; +location: string; +birthday: string; +gender: any | null; +isLeader: boolean; +}; +} +declare namespace App.Contribution.Documents { +export type BdkjHesse = { +dateFrom: string; +dateUntil: string; +zipLocation: string; +country: any | null; +members: any; +eventName: string; +filename: string | null; +type: string; +}; +export type CityFrankfurtMainDocument = { +fromName: string; +dateFrom: string; +dateUntil: string; +zipLocation: string; +country: any | null; +members: any; +eventName: string; +filename: string | null; +type: string; +}; +export type CityRemscheidDocument = { +dateFrom: string; +dateUntil: string; +zipLocation: string; +country: any | null; +leaders: any; +children: any; +filename: string | null; +type: string; +eventName: string; +}; +export type CitySolingenDocument = { +fromName: string; +dateFrom: string; +dateUntil: string; +zipLocation: string; +members: Array; +eventName: string; +type: string; +}; +export type ContributionDocument = { +}; +export type RdpNrwDocument = { +dateFrom: string; +dateUntil: string; +zipLocation: string; +country: any | null; +members: any; +filename: string | null; +type: string; +eventName: string; +}; +export type WuppertalDocument = { +dateFrom: string; +dateUntil: string; +zipLocation: string; +country: any | null; +members: any; +filename: string | null; +type: string; +eventName: string; +}; +} +declare namespace App.Efz { +export type EfzDocument = { +name: string; +slug: string; +secondLine: string; +now: string; +sender: App.Pdf.Sender; +member: any; +}; +} +declare namespace App.Fileshare.ConnectionTypes { +export type ConnectionType = { +}; +export type NextcloudConnection = { +user: string; +password: string; +base_url: string; +}; +export type OwncloudConnection = { +user: string; +password: string; +base_url: string; +}; +} +declare namespace App.Fileshare.Data { +export type FileshareResourceData = { +connection_id: number; +resource: string; +}; +export type ResourceData = { +name: string; +path: string; +parent: string; +}; +} +declare namespace App.Form.Data { +export type ColumnData = { +mobile: number; +tablet: number; +desktop: number; +}; +export type ExportData = { +root: App.Fileshare.Data.FileshareResourceData | null; +group_by: string | null; +to_group_field: string | null; +}; +export type FormConfigData = { +sections: Array; +}; +export type SectionData = { +name: string; +fields: Array; +intro: string | null; +}; +} +declare namespace App.Form.Enums { +export type NamiType = 'Vorname' | 'Nachname' | 'Spitzname' | 'Geburtstag' | 'Bezirk' | 'Stamm' | 'E-Mail-Adresse' | 'Adresse' | 'PLZ' | 'Ort' | 'Geschlecht' | 'Handynummer' | 'Alter (zum Zeitpunkt der Anmeldung)' | 'Alter (zum Zeitpunkt der Veranstaltung)'; +export type SpecialType = 'Vorname' | 'Nachname' | 'E-Mail-Adresse'; +} +declare namespace App.Form.Fields { +export type CheckboxField = { +required: boolean; +description: string; +key: string; +name: string; +nami_type: App.Form.Enums.NamiType | null; +columns: App.Form.Data.ColumnData; +for_members: boolean; +special_type: App.Form.Enums.SpecialType | null; +hint: string | null; +intro: string | null; +value: any; +}; +export type CheckboxesField = { +options: { [key: number]: string }; +min: number | null; +max: number | null; +key: string; +name: string; +nami_type: App.Form.Enums.NamiType | null; +columns: App.Form.Data.ColumnData; +for_members: boolean; +special_type: App.Form.Enums.SpecialType | null; +hint: string | null; +intro: string | null; +value: any; +}; +export type DateField = { +required: boolean; +max_today: boolean; +key: string; +name: string; +nami_type: App.Form.Enums.NamiType | null; +columns: App.Form.Data.ColumnData; +for_members: boolean; +special_type: App.Form.Enums.SpecialType | null; +hint: string | null; +intro: string | null; +value: any; +}; +export type DropdownField = { +required: boolean; +options: { [key: number]: string }; +allowcustom: boolean; +key: string; +name: string; +nami_type: App.Form.Enums.NamiType | null; +columns: App.Form.Data.ColumnData; +for_members: boolean; +special_type: App.Form.Enums.SpecialType | null; +hint: string | null; +intro: string | null; +value: any; +}; +export type EmailField = { +required: boolean; +key: string; +name: string; +nami_type: App.Form.Enums.NamiType | null; +columns: App.Form.Data.ColumnData; +for_members: boolean; +special_type: App.Form.Enums.SpecialType | null; +hint: string | null; +intro: string | null; +value: any; +}; +export type Field = { +key: string; +name: string; +nami_type: App.Form.Enums.NamiType | null; +columns: App.Form.Data.ColumnData; +for_members: boolean; +special_type: App.Form.Enums.SpecialType | null; +hint: string | null; +intro: string | null; +value: any; +}; +export type GroupField = { +required: boolean; +parent_field: string | null; +parent_group: number | null; +has_empty_option: boolean; +empty_option_value: string | null; +key: string; +name: string; +nami_type: App.Form.Enums.NamiType | null; +columns: App.Form.Data.ColumnData; +for_members: boolean; +special_type: App.Form.Enums.SpecialType | null; +hint: string | null; +intro: string | null; +value: any; +}; +export type NamiField = { +key: string; +name: string; +nami_type: App.Form.Enums.NamiType | null; +columns: App.Form.Data.ColumnData; +for_members: boolean; +special_type: App.Form.Enums.SpecialType | null; +hint: string | null; +intro: string | null; +value: any; +}; +export type NumberField = { +required: boolean; +min: number | null; +max: number | null; +key: string; +name: string; +nami_type: App.Form.Enums.NamiType | null; +columns: App.Form.Data.ColumnData; +for_members: boolean; +special_type: App.Form.Enums.SpecialType | null; +hint: string | null; +intro: string | null; +value: any; +}; +export type RadioField = { +required: boolean; +options: { [key: number]: string }; +allowcustom: boolean; +key: string; +name: string; +nami_type: App.Form.Enums.NamiType | null; +columns: App.Form.Data.ColumnData; +for_members: boolean; +special_type: App.Form.Enums.SpecialType | null; +hint: string | null; +intro: string | null; +value: any; +}; +export type TextField = { +required: boolean; +key: string; +name: string; +nami_type: App.Form.Enums.NamiType | null; +columns: App.Form.Data.ColumnData; +for_members: boolean; +special_type: App.Form.Enums.SpecialType | null; +hint: string | null; +intro: string | null; +value: any; +}; +export type TextareaField = { +required: boolean; +rows: number; +key: string; +name: string; +nami_type: App.Form.Enums.NamiType | null; +columns: App.Form.Data.ColumnData; +for_members: boolean; +special_type: App.Form.Enums.SpecialType | null; +hint: string | null; +intro: string | null; +value: any; +}; +} +declare namespace App.Form.Scopes { +export type FormFilterScope = { +search: string | null; +past: boolean; +inactive: boolean; +}; +export type ParticipantFilterScope = { +data: Array; +search: string; +options: Array; +parent: number | null; +sort: App.Lib.Sorting | null; +}; +} +declare namespace App.Group.Enums { +export type Level = 'Diözese' | 'Bezirk' | 'Stamm'; +} +declare namespace App.Invoice { +export type BillKind = 'E-Mail' | 'Post'; +export type BillDocument = { +until: string; +filename: string; +toName: string; +toAddress: string; +toZip: string; +toLocation: string; +greeting: string; +positions: Array; +usage: string; +}; +export type InvoiceDocument = { +until: string; +filename: string; +toName: string; +toAddress: string; +toZip: string; +toLocation: string; +greeting: string; +positions: Array; +usage: string; +}; +export type RememberDocument = { +until: string; +filename: string; +toName: string; +toAddress: string; +toZip: string; +toLocation: string; +greeting: string; +positions: Array; +usage: string; +}; +} +declare namespace App.Invoice.Enums { +export type InvoiceStatus = 'Neu' | 'Rechnung gestellt' | 'Rechnung beglichen'; +} +declare namespace App.Invoice.Scopes { +export type InvoiceFilterScope = { +statuses: Array | null; +search: string | null; +}; +} +declare namespace App.Lib { +export type Filter = { +}; +export type ScoutFilter = { +}; +export type Sorting = { +by: string; +direction: boolean; +}; +} +declare namespace App.Lib.Data { +export type DateData = { +raw: string; +human: string; +}; +} +declare namespace App.Lib.Editor { +export type Comparator = 'isEqual' | 'isNotEqual' | 'isIn' | 'isNotIn'; +export type ConditionMode = 'all' | 'any'; +export type Condition = { +mode: App.Lib.Editor.ConditionMode; +ifs: Array; +}; +export type EditorData = { +version: string; +blocks: Array; +time: number; +}; +export type Statement = { +field: string; +value: any; +comparator: App.Lib.Editor.Comparator; +}; +} +declare namespace App.Maildispatcher.Data { +export type MailEntry = { +email: string; +}; +} +declare namespace App.Mailman.Data { +export type MailingList = { +description: string; +display_name: string; +name: string; +id: string; +list_name: string; +mail_host: string; +member_count: number; +self_link: string; +volume: number; +}; +export type Member = { +email: string; +member_id: string; +}; +} +declare namespace App.Member { +export type FilterScope = { +options: { [key: string]: any }; +ausstand: boolean; +bill_kind: string | null; +memberships: Array; +activity_ids: Array; +subactivity_ids: Array; +search: string | null; +group_ids: Array; +include: Array; +exclude: Array; +has_full_address: boolean | null; +has_birthday: boolean | null; +has_svk: boolean | null; +has_vk: boolean | null; +}; +} +declare namespace App.Member.Data { +export type ActivityData = { +id: number; +name: string; +}; +export type FullMember = { +member: any; +courses: Array; +memberships: Array; +}; +export type GroupData = { +id: number; +name: string; +}; +export type MembershipData = { +id: number; +activity: App.Member.Data.ActivityData; +subactivity: App.Member.Data.SubactivityData; +group: App.Member.Data.GroupData; +promised_at: App.Lib.Data.DateData | null; +from: App.Lib.Data.DateData; +is_active: boolean; +}; +export type NestedGroup = { +id: number; +name: string; +}; +export type SubactivityData = { +id: number; +name: string; +}; +} +declare namespace App.Module { +export type Module = 'bill' | 'course' | 'event'; +} +declare namespace App.Pdf { +export type Sender = { +name: string; +address: string; +zipLocation: string; +mglnr?: string; +}; +} +declare namespace App.Prevention.Data { +export type PreventionData = { +type: any; +expires: string; +}; +} diff --git a/tests/Feature/Membership/IndexTest.php b/tests/Feature/Membership/IndexTest.php index bf7348f8..11c6a40b 100644 --- a/tests/Feature/Membership/IndexTest.php +++ b/tests/Feature/Membership/IndexTest.php @@ -32,7 +32,8 @@ class IndexTest extends TestCase ->assertJsonPath('data.0.subactivity.id', $membership->subactivity_id) ->assertJsonPath('data.0.activity.name', '€ Mitglied') ->assertJsonPath('data.0.subactivity.name', 'Wölfling') - ->assertJsonPath('data.0.human_date', '02.11.2022') + ->assertJsonPath('data.0.from.human', '02.11.2022') + ->assertJsonPath('data.0.from.raw', '2022-11-02') ->assertJsonPath('data.0.group.id', $group->id) ->assertJsonPath('data.0.id', $membership->id) ->assertJsonPath('data.0.links.update', route('membership.update', ['membership' => $membership]))