Compare commits

...

7 Commits

Author SHA1 Message Date
philipp lang adf9341dd7 Update to inertia 2.0
continuous-integration/drone/push Build is failing Details
2025-06-13 13:42:31 +02:00
philipp lang 9853d4e82e Fix: Dont run massstore when activities and subactivities dont match 2025-06-13 13:13:11 +02:00
philipp lang 4698c808f8 Add global modules via unplugin-vue-components 2025-06-11 21:27:07 +02:00
philipp lang ea2eb08052 Lint tabs component 2025-06-11 19:21:35 +02:00
philipp lang 09f401055a Remove member tabs component 2025-06-11 19:21:21 +02:00
philipp lang 2c786b62ce Lint 2025-06-11 19:20:52 +02:00
philipp lang 4cd18e9b3c Lint 2025-06-11 18:29:47 +02:00
14 changed files with 1103 additions and 929 deletions

View File

@ -10,6 +10,7 @@ use App\Maildispatcher\Actions\ResyncAction;
use App\Member\Member;
use App\Member\Membership;
use App\Subactivity;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;
use Lorisleiva\Actions\ActionRequest;
use Lorisleiva\Actions\Concerns\AsAction;
@ -26,7 +27,12 @@ class MassStoreAction
{
return [
'group_id' => 'required|numeric|exists:groups,id',
'activity_id' => 'required|numeric|exists:activities,id',
'activity_id' => ['required', 'numeric', 'exists:activities,id', function($key, $value, $fail) {
$activity = Activity::findOrFail($value);
if ($activity->subactivities->pluck('id')->doesntContain(request()->subactivity_id)) {
return $fail(':attribute ist nicht vorhanden.');
}
}],
'subactivity_id' => 'required|numeric|exists:subactivities,id',
'members' => 'array',
'members.*' => 'numeric|exists:members,id',
@ -64,7 +70,7 @@ class MassStoreAction
});
}
public function asController(ActionRequest $request): void
public function asController(ActionRequest $request): JsonResponse
{
/**
* @var array{members: array<int, int>, group_id: int, activity_id: int, subactivity_id: int}
@ -77,6 +83,16 @@ class MassStoreAction
Subactivity::findOrFail($input['subactivity_id']),
$input['members'],
);
return response()->json([], 200);
}
public function getValidationAttributes(): array {
return [
'activity_id' => 'Tätigkeit',
'subactivity_id' => 'Untertätigkeit',
'group_id' => 'Gruppe',
];
}
/**

View File

@ -50,7 +50,7 @@
"cviebrock/eloquent-sluggable": "^11.0",
"doctrine/dbal": "^3.1",
"guzzlehttp/guzzle": "^7.0.1",
"inertiajs/inertia-laravel": "^1.0",
"inertiajs/inertia-laravel": "^2.0",
"laravel/framework": "^11.0",
"laravel/horizon": "^5.0",
"laravel/pail": "^1.1",

1105
composer.lock generated

File diff suppressed because it is too large Load Diff

341
package-lock.json generated
View File

@ -9,7 +9,7 @@
"@editorjs/header": "^2.8.1",
"@editorjs/nested-list": "^1.4.2",
"@editorjs/paragraph": "^2.11.3",
"@inertiajs/vue3": "^1.0.14",
"@inertiajs/vue3": "^2.0",
"@tailwindcss/forms": "^0.5.7",
"@tailwindcss/typography": "^0.5.10",
"@vitejs/plugin-vue": "^4.6.2",
@ -40,6 +40,7 @@
"dayjs": "^1.11.10",
"postcss": "^8.4.33",
"tailwindcss": "^3.4.1",
"unplugin-vue-components": "^28.7.0",
"vue-axios": "^3.5.2"
}
},
@ -526,9 +527,9 @@
}
},
"node_modules/@eslint/config-array": {
"version": "0.20.0",
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz",
"integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==",
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.1.tgz",
"integrity": "sha512-OL0RJzC/CBzli0DrrR31qzj6d6i6Mm3HByuhflhl4LOBiWxN+3i6/t/ZQQNii4tjksXi8r2CRW1wMpWA2ULUEw==",
"dependencies": {
"@eslint/object-schema": "^2.1.6",
"debug": "^4.3.1",
@ -539,9 +540,9 @@
}
},
"node_modules/@eslint/config-helpers": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.2.tgz",
"integrity": "sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==",
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.3.tgz",
"integrity": "sha512-u180qk2Um1le4yf0ruXH3PYFeEZeYC3p/4wCTKrr2U1CmGdzGi3KtY0nuPDH48UJxlKCC5RDzbcbh4X0XlqgHg==",
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
@ -599,17 +600,28 @@
}
},
"node_modules/@eslint/plugin-kit": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.1.tgz",
"integrity": "sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==",
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.2.tgz",
"integrity": "sha512-4SaFZCNfJqvk/kenHpI8xvN42DMaoycy4PzKc5otHxRswww1kAt82OlBuwRVLofCACCTZEcla2Ydxv8scMXaTg==",
"dependencies": {
"@eslint/core": "^0.14.0",
"@eslint/core": "^0.15.0",
"levn": "^0.4.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@eslint/plugin-kit/node_modules/@eslint/core": {
"version": "0.15.0",
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.0.tgz",
"integrity": "sha512-b7ePw78tEWWkpgZCDYkbqDOP8dmM6qe+AOC6iuJqlq1R/0ahMAeH3qynpnqKFGkMltrp44ohV4ubGyvLX28tzw==",
"dependencies": {
"@types/json-schema": "^7.0.15"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@floating-ui/core": {
"version": "1.7.1",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.1.tgz",
@ -688,24 +700,22 @@
}
},
"node_modules/@inertiajs/core": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@inertiajs/core/-/core-1.3.0.tgz",
"integrity": "sha512-TJ8R1eUYY473m9DaKlCPRdHTdznFWTDuy5VvEzXg3t/hohbDQedLj46yn/uAqziJPEUZJrSftZzPI2NMzL9tQA==",
"version": "2.0.12",
"resolved": "https://registry.npmjs.org/@inertiajs/core/-/core-2.0.12.tgz",
"integrity": "sha512-TxMRUcSB/w2Or9KSsldgcx49u+1xveLg7HuwRkqrs196ZrDwYRjtc984uc838vDP+dsFIz//+Tn0n7ysG/MgMQ==",
"dependencies": {
"axios": "^1.6.0",
"deepmerge": "^4.0.0",
"nprogress": "^0.2.0",
"axios": "^1.8.2",
"es-toolkit": "^1.34.1",
"qs": "^6.9.0"
}
},
"node_modules/@inertiajs/vue3": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@inertiajs/vue3/-/vue3-1.3.0.tgz",
"integrity": "sha512-GizqdCM3u4JWunit3uUbW4fEmTLKQTi1W7VvPRdrNy8XDt4Qy2cCmfFjq+aH5tHBSS3fI/ngYuhN7XvwqNaKvw==",
"version": "2.0.12",
"resolved": "https://registry.npmjs.org/@inertiajs/vue3/-/vue3-2.0.12.tgz",
"integrity": "sha512-ruvThr3BKunFjh+EamcGilAI8RGSF/upL//E9bnchYEWFCwQtZ2NzQ0tBOFLQ+qYnaRiDjsyTa63h1R36PUmbg==",
"dependencies": {
"@inertiajs/core": "1.3.0",
"lodash.clonedeep": "^4.5.0",
"lodash.isequal": "^4.5.0"
"@inertiajs/core": "2.0.12",
"es-toolkit": "^1.33.0"
},
"peerDependencies": {
"vue": "^3.0.0"
@ -1764,9 +1774,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001722",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001722.tgz",
"integrity": "sha512-DCQHBBZtiK6JVkAGw7drvAMK0Q0POD/xZvEmDp6baiMMP6QXXk9HpD6mNYBZWhOPG6LvIDb82ITqtWjhDckHCA==",
"version": "1.0.30001723",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001723.tgz",
"integrity": "sha512-1R/elMjtehrFejxwmexeXAtae5UO9iSyFn6G/I806CYC/BLyyBk1EPhrKBkWhy6wM6Xnm47dSJQec+tLJ39WHw==",
"dev": true,
"funding": [
{
@ -1985,6 +1995,12 @@
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
},
"node_modules/confbox": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz",
"integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==",
"dev": true
},
"node_modules/constant-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz",
@ -2115,14 +2131,6 @@
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="
},
"node_modules/deepmerge": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@ -2225,9 +2233,9 @@
"integrity": "sha512-m6w/cRxnFucC3dyfrB+DTNXw70SnJNv05AX6P3bZ8qkbzB1OAJTuaFrEKZBdN0YvEvTe1zvg3S344EkPAveemQ=="
},
"node_modules/electron-to-chromium": {
"version": "1.5.166",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.166.tgz",
"integrity": "sha512-QPWqHL0BglzPYyJJ1zSSmwFFL6MFXhbACOCcsCdUMCkzPdS9/OIBVxg516X/Ado2qwAq8k0nJJ7phQPCqiaFAw==",
"version": "1.5.167",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.167.tgz",
"integrity": "sha512-LxcRvnYO5ez2bMOFpbuuVuAI5QNeY1ncVytE/KXaL6ZNfzX1yPlAO0nSOyIHx2fVAuUprMqPs/TdVhUFZy7SIQ==",
"dev": true
},
"node_modules/emoji-regex": {
@ -2289,6 +2297,15 @@
"node": ">= 0.4"
}
},
"node_modules/es-toolkit": {
"version": "1.39.3",
"resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.39.3.tgz",
"integrity": "sha512-Qb/TCFCldgOy8lZ5uC7nLGdqJwSabkQiYQShmw4jyiPk1pZzaYWTwaYKYP7EgLccWYgZocMrtItrwh683voaww==",
"workspaces": [
"docs",
"benchmarks"
]
},
"node_modules/esbuild": {
"version": "0.18.20",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz",
@ -2520,6 +2537,12 @@
"node": ">=0.10.0"
}
},
"node_modules/exsolve": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.5.tgz",
"integrity": "sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg==",
"dev": true
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@ -3137,6 +3160,23 @@
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
},
"node_modules/local-pkg": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.1.1.tgz",
"integrity": "sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg==",
"dev": true,
"dependencies": {
"mlly": "^1.7.4",
"pkg-types": "^2.0.1",
"quansync": "^0.2.8"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/locate-path": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
@ -3161,22 +3201,11 @@
"resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz",
"integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q=="
},
"node_modules/lodash.clonedeep": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
"integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ=="
},
"node_modules/lodash.escape": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz",
"integrity": "sha512-nXEOnb/jK9g0DYMr1/Xvq6l5xMD7GDG55+GSYIYmS0G4tBk/hURD4JR9WCavs04t33WmJx9kCyp9vJ+mr4BOUw=="
},
"node_modules/lodash.isequal": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
"integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
"deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead."
},
"node_modules/lodash.isplainobject": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
@ -3308,6 +3337,35 @@
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/mlly": {
"version": "1.7.4",
"resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.4.tgz",
"integrity": "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==",
"dev": true,
"dependencies": {
"acorn": "^8.14.0",
"pathe": "^2.0.1",
"pkg-types": "^1.3.0",
"ufo": "^1.5.4"
}
},
"node_modules/mlly/node_modules/confbox": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz",
"integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==",
"dev": true
},
"node_modules/mlly/node_modules/pkg-types": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz",
"integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==",
"dev": true,
"dependencies": {
"confbox": "^0.1.8",
"mlly": "^1.7.4",
"pathe": "^2.0.1"
}
},
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@ -3385,11 +3443,6 @@
"node": ">=0.10.0"
}
},
"node_modules/nprogress": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz",
"integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA=="
},
"node_modules/nth-check": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
@ -3575,6 +3628,12 @@
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/pathe": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
"integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
"dev": true
},
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@ -3628,10 +3687,21 @@
"node": ">= 6"
}
},
"node_modules/pkg-types": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.1.0.tgz",
"integrity": "sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A==",
"dev": true,
"dependencies": {
"confbox": "^0.2.1",
"exsolve": "^1.0.1",
"pathe": "^2.0.3"
}
},
"node_modules/postcss": {
"version": "8.5.4",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.4.tgz",
"integrity": "sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==",
"version": "8.5.5",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.5.tgz",
"integrity": "sha512-d/jtm+rdNT8tpXuHY5MMtcbJFBkhXE6593XVR9UoGCH8jSFGci7jGvMGH5RYd5PBJW+00NZQt6gf7CbagJCrhg==",
"funding": [
{
"type": "opencollective",
@ -3829,6 +3899,22 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/quansync": {
"version": "0.2.10",
"resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.10.tgz",
"integrity": "sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==",
"dev": true,
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/antfu"
},
{
"type": "individual",
"url": "https://github.com/sponsors/sxzz"
}
]
},
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@ -4458,6 +4544,48 @@
"node": ">=0.8"
}
},
"node_modules/tinyglobby": {
"version": "0.2.14",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz",
"integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==",
"dev": true,
"dependencies": {
"fdir": "^6.4.4",
"picomatch": "^4.0.2"
},
"engines": {
"node": ">=12.0.0"
},
"funding": {
"url": "https://github.com/sponsors/SuperchupuDev"
}
},
"node_modules/tinyglobby/node_modules/fdir": {
"version": "6.4.6",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz",
"integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==",
"dev": true,
"peerDependencies": {
"picomatch": "^3 || ^4"
},
"peerDependenciesMeta": {
"picomatch": {
"optional": true
}
}
},
"node_modules/tinyglobby/node_modules/picomatch": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@ -4548,6 +4676,101 @@
"typescript": ">=4.8.4 <5.9.0"
}
},
"node_modules/ufo": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz",
"integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==",
"dev": true
},
"node_modules/unplugin": {
"version": "2.3.5",
"resolved": "https://registry.npmjs.org/unplugin/-/unplugin-2.3.5.tgz",
"integrity": "sha512-RyWSb5AHmGtjjNQ6gIlA67sHOsWpsbWpwDokLwTcejVdOjEkJZh7QKu14J00gDDVSh8kGH4KYC/TNBceXFZhtw==",
"dev": true,
"dependencies": {
"acorn": "^8.14.1",
"picomatch": "^4.0.2",
"webpack-virtual-modules": "^0.6.2"
},
"engines": {
"node": ">=18.12.0"
}
},
"node_modules/unplugin-utils": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/unplugin-utils/-/unplugin-utils-0.2.4.tgz",
"integrity": "sha512-8U/MtpkPkkk3Atewj1+RcKIjb5WBimZ/WSLhhR3w6SsIj8XJuKTacSP8g+2JhfSGw0Cb125Y+2zA/IzJZDVbhA==",
"dev": true,
"dependencies": {
"pathe": "^2.0.2",
"picomatch": "^4.0.2"
},
"engines": {
"node": ">=18.12.0"
},
"funding": {
"url": "https://github.com/sponsors/sxzz"
}
},
"node_modules/unplugin-utils/node_modules/picomatch": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/unplugin-vue-components": {
"version": "28.7.0",
"resolved": "https://registry.npmjs.org/unplugin-vue-components/-/unplugin-vue-components-28.7.0.tgz",
"integrity": "sha512-3SuWAHlTjOiZckqRBGXRdN/k6IMmKyt2Ch5/+DKwYaT321H0ItdZDvW4r8/YkEKQpN9TN3F/SZ0W342gQROC3Q==",
"dev": true,
"dependencies": {
"chokidar": "^3.6.0",
"debug": "^4.4.1",
"local-pkg": "^1.1.1",
"magic-string": "^0.30.17",
"mlly": "^1.7.4",
"tinyglobby": "^0.2.14",
"unplugin": "^2.3.4",
"unplugin-utils": "^0.2.4"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@babel/parser": "^7.15.8",
"@nuxt/kit": "^3.2.2",
"vue": "2 || 3"
},
"peerDependenciesMeta": {
"@babel/parser": {
"optional": true
},
"@nuxt/kit": {
"optional": true
}
}
},
"node_modules/unplugin/node_modules/picomatch": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/update-browserslist-db": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
@ -4792,6 +5015,12 @@
"vue": "^3.0.1"
}
},
"node_modules/webpack-virtual-modules": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz",
"integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==",
"dev": true
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",

View File

@ -18,6 +18,7 @@
"dayjs": "^1.11.10",
"postcss": "^8.4.33",
"tailwindcss": "^3.4.1",
"unplugin-vue-components": "^28.7.0",
"vue-axios": "^3.5.2"
},
"dependencies": {
@ -25,7 +26,7 @@
"@editorjs/header": "^2.8.1",
"@editorjs/nested-list": "^1.4.2",
"@editorjs/paragraph": "^2.11.3",
"@inertiajs/vue3": "^1.0.14",
"@inertiajs/vue3": "^2.0",
"@tailwindcss/forms": "^0.5.7",
"@tailwindcss/typography": "^0.5.10",
"@vitejs/plugin-vue": "^4.6.2",

18
resources/js/app.js vendored
View File

@ -1,16 +1,15 @@
import {createApp, h, defineAsyncComponent} from 'vue';
import {Head, createInertiaApp, Link as ILink} from '@inertiajs/vue3';
import { createApp, h, defineAsyncComponent } from 'vue';
import { Head, createInertiaApp, Link as ILink } from '@inertiajs/vue3';
import axios from 'axios';
import VueAxios from 'vue-axios';
import {Plugin as FloatingVue, options as FloatingVueOptions} from './lib/floatingVue.js';
import {createPinia, PiniaVuePlugin} from 'pinia';
import { Plugin as FloatingVue, options as FloatingVueOptions } from './lib/floatingVue.js';
import { createPinia, PiniaVuePlugin } from 'pinia';
import Echo from './lib/echo.js';
import requireModules from './lib/requireModules.js';
import AppLayout from './layouts/AppLayout.vue';
import hasModule from './mixins/hasModule.js';
import hasFlash from './mixins/hasFlash.js';
import {Toast, options as toastOptions, interceptor as toastInterceptor} from './lib/toast.js';
import { Toast, options as toastOptions, interceptor as toastInterceptor } from './lib/toast.js';
// ---------------------------------- Assets -----------------------------------
import '../css/app.css';
@ -35,8 +34,8 @@ createInertiaApp({
return page;
},
setup({el, App, props, plugin}) {
var app = createApp({pinia, render: () => h(App, props)})
setup({ el, App, props, plugin }) {
var app = createApp({ pinia, render: () => h(App, props) })
.use(plugin)
.use(FloatingVue, FloatingVueOptions)
.use(Toast, toastOptions)
@ -47,9 +46,6 @@ createInertiaApp({
.mixin(hasModule)
.mixin(hasFlash);
requireModules(import.meta.glob('./components/form/*.vue'), app, 'f');
requireModules(import.meta.glob('./components/ui/*.vue'), app, 'ui');
requireModules(import.meta.glob('./components/page/*.vue', {eager: true}), app, 'page');
app.component(
'FSinglefile',
defineAsyncComponent(() => import('!/medialibrary-helper/assets/components/SingleFile.vue'))

57
resources/js/components/components.d.ts vendored Normal file
View File

@ -0,0 +1,57 @@
/* eslint-disable */
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
// biome-ignore lint: disable
export {}
/* prettier-ignore */
declare module 'vue' {
export interface GlobalComponents {
FCheckboxesLabel: typeof import('@/components/form/CheckboxesLabel.vue')['default']
FEditor: typeof import('@/components/form/Editor.vue')['default']
FHint: typeof import('@/components/form/Hint.vue')['default']
FLabel: typeof import('@/components/form/Label.vue')['default']
FMemberFilter: typeof import('@/components/form/MemberFilter.vue')['default']
FMultipleselect: typeof import('@/components/form/Multipleselect.vue')['default']
FSaveButton: typeof import('@/components/form/SaveButton.vue')['default']
FSelect: typeof import('@/components/form/Select.vue')['default']
FSwitch: typeof import('@/components/form/Switch.vue')['default']
FText: typeof import('@/components/form/Text.vue')['default']
FTextarea: typeof import('@/components/form/Textarea.vue')['default']
PageFilter: typeof import('@/components/page/Filter.vue')['default']
PageFullHeading: typeof import('@/components/page/FullHeading.vue')['default']
PageFullHeadingBanner: typeof import('@/components/page/FullHeadingBanner.vue')['default']
PageFullLayout: typeof import('@/components/page/FullLayout.vue')['default']
PageHeader: typeof import('@/components/page/Header.vue')['default']
PageLayout: typeof import('@/components/page/Layout.vue')['default']
PageSearchModal: typeof import('@/components/page/SearchModal.vue')['default']
PageTitle: typeof import('@/components/page/Title.vue')['default']
PageToolbarButton: typeof import('@/components/page/ToolbarButton.vue')['default']
UiActionButton: typeof import('@/components/ui/ActionButton.vue')['default']
UiAgeGroups: typeof import('@/components/ui/AgeGroups.vue')['default']
UiBool: typeof import('@/components/ui/Bool.vue')['default']
UiBooleanDisplay: typeof import('@/components/ui/BooleanDisplay.vue')['default']
UiBox: typeof import('@/components/ui/Box.vue')['default']
UiButton: typeof import('@/components/ui/Button.vue')['default']
UiFilterSidebar: typeof import('@/components/ui/FilterSidebar.vue')['default']
UiIconButton: typeof import('@/components/ui/IconButton.vue')['default']
UiLabel: typeof import('@/components/ui/Label.vue')['default']
UiLoading: typeof import('@/components/ui/Loading.vue')['default']
UiMenulist: typeof import('@/components/ui/Menulist.vue')['default']
UiNote: typeof import('@/components/ui/Note.vue')['default']
UiPagination: typeof import('@/components/ui/Pagination.vue')['default']
UiPopup: typeof import('@/components/ui/Popup.vue')['default']
UiRemoteResource: typeof import('@/components/ui/RemoteResource.vue')['default']
UiRemoteSelector: typeof import('@/components/ui/RemoteSelector.vue')['default']
UiSearchPagination: typeof import('@/components/ui/SearchPagination.vue')['default']
UiSearchResult: typeof import('@/components/ui/SearchResult.vue')['default']
UiSidebar: typeof import('@/components/ui/Sidebar.vue')['default']
UiSpinner: typeof import('@/components/ui/Spinner.vue')['default']
UiSprite: typeof import('@/components/ui/Sprite.vue')['default']
UiTableToggleButton: typeof import('@/components/ui/TableToggleButton.vue')['default']
UiTabs: typeof import('@/components/ui/Tabs.vue')['default']
UiTextDisplay: typeof import('@/components/ui/TextDisplay.vue')['default']
UiTh: typeof import('@/components/ui/Th.vue')['default']
}
}

View File

@ -1,38 +1,25 @@
<template>
<div class="flex-none w-maxc flex flex-col justify-between border-b-2 border-gray-500 group-[.is-popup]:border-zinc-500 mb-3">
<div class="flex space-x-1 px-2">
<a
v-for="(item, index) in entries"
:key="index"
href="#"
class="rounded-t-lg py-1 px-3 text-zinc-300"
:class="index === modelValue ? `bg-gray-700 group-[.is-popup]:bg-zinc-600` : ''"
@click.prevent="openMenu(index)"
v-text="item.title"
></a>
<a v-for="(item, index) in entries" :key="index" href="#" class="rounded-t-lg py-1 px-3 text-zinc-300"
:class="index === modelValue ? `bg-gray-700 group-[.is-popup]:bg-zinc-600` : ''" @click.prevent="openMenu(index)"
v-text="item.title"
/>
</div>
</div>
</template>
<script>
export default {
props: {
modelValue: {
type: Number,
required: true,
},
entries: {
required: true,
validator: function (entries) {
return entries.filter((e) => e.title === undefined || typeof e.title !== 'string' || e.title.length === 0).length === 0;
},
},
},
emits: ['update:modelValue'],
methods: {
openMenu(index) {
this.$emit('update:modelValue', index);
},
},
};
<script lang="ts" setup>
defineProps<{
modelValue: number,
entries: {title: string}[]
}>();
const emits = defineEmits<{
'update:modelValue': [number],
}>();
function openMenu(index: number) {
emits('update:modelValue', index);
}
</script>

View File

@ -1,10 +0,0 @@
import {paramCase} from 'change-case';
import {defineAsyncComponent} from 'vue';
export default function (context, app, prefix) {
for (const file in context) {
let componentName = paramCase(`${prefix}${file.replace(/^.*\/(.*?)\.vue$/g, '$1')}`);
app.component(componentName, typeof context[file] === 'function' ? defineAsyncComponent(context[file]) : context[file].default);
}
}

View File

@ -4,175 +4,71 @@
<page-toolbar-button :href="meta.links.index" color="primary" icon="undo">zurück</page-toolbar-button>
<page-toolbar-button :href="data.links.edit" color="warning" icon="pencil">bearbeiten</page-toolbar-button>
</template>
<div class="p-3 grid gap-3 this-grid grow">
<ui-box heading="Stammdaten" class="area-stamm hidden xl:block">
<stamm :inner="inner"></stamm>
</ui-box>
<ui-box heading="Kontakt" class="area-kontakt hidden xl:block">
<kontakt :inner="inner"></kontakt>
</ui-box>
<ui-box class="area-stammkontakt block xl:hidden">
<tabs v-model="tabs.stammkontakt">
<stamm v-show="tabs.stammkontakt.active === 'stamm'" :inner="inner"></stamm>
<kontakt v-show="tabs.stammkontakt.active === 'kontakt'" :inner="inner"></kontakt>
</tabs>
</ui-box>
<div class="p-3 grid gap-3 xl:grid-rows-[max-content_1fr] xl:grid-cols-[max-content_max-content_max-content_1fr] grow">
<section class="mobile hidden xl:contents">
<ui-box heading="Stammdaten">
<stamm :inner="props.data" />
</ui-box>
<ui-box heading="Kontakt">
<kontakt :inner="props.data" />
</ui-box>
<ui-box heading="Prävention">
<prae :inner="props.data" />
</ui-box>
<ui-box heading="System">
<system :inner="props.data" />
</ui-box>
<ui-box class="col-span-full">
<ui-tabs v-model="tabs.membershipcourse.active" :entries="tabs.membershipcourse.entries" />
<memberships v-show="tabs.membershipcourse.active === 0" :value="props.data.memberships" />
<courses v-show="tabs.membershipcourse.active === 1" :value="props.data.courses" />
<payments v-show="tabs.membershipcourse.active === 2" :value="props.data.invoicePositions" />
<div v-show="tabs.membershipcourse.active === 3" class="h-full flex items-center justify-center text-gray-400 text-center">Keine Karte vorhanden</div>
</ui-box>
</section>
<ui-box container-class="" heading="Prävention" class="area-praev hidden xl:block">
<prae :inner="inner"></prae>
</ui-box>
<ui-box heading="System" class="area-system hidden xl:block">
<system :inner="inner"></system>
</ui-box>
<ui-box class="area-praesystem block xl:hidden">
<tabs v-model="tabs.praesystem">
<prae v-show="tabs.praesystem.active === 'prae'" :inner="inner"></prae>
<system v-show="tabs.praesystem.active === 'system'" :inner="inner"></system>
</tabs>
</ui-box>
<ui-box class="area-membershipcourse hidden xl:block">
<tabs v-model="tabs.membershipcourse">
<courses v-show="tabs.membershipcourse.active === 'course'" :value="inner.courses"></courses>
<memberships v-show="tabs.membershipcourse.active === 'membership'" :value="inner.memberships"> </memberships>
</tabs>
</ui-box>
<ui-box heading="Ausbildungen" class="area-courses xl:hidden">
<courses :value="inner.courses"></courses>
</ui-box>
<ui-box heading="Mitgliedschaften" class="area-memberships xl:hidden">
<memberships :value="inner.memberships"></memberships>
</ui-box>
<ui-box heading="Zahlungen" class="area-payments">
<payments :value="inner.invoicePositions"></payments>
</ui-box>
<ui-box heading="Karte" container-class="grow" class="area-map hidden xl:flex">
<div class="h-full flex items-center justify-center text-gray-400 text-center">Keine Karte vorhanden</div>
</ui-box>
<section class="mobile contents xl:hidden">
<ui-box heading="Stammdaten"> <stamm :inner="props.data" /> </ui-box>
<ui-box heading="Kontakt"> <kontakt :inner="props.data" /> </ui-box>
<ui-box heading="Prävention"> <prae :inner="props.data" /> </ui-box>
<ui-box heading="System"> <system :inner="props.data" /> </ui-box>
<ui-box heading="Mitgliedschaften"> <memberships :value="props.data.memberships" /> </ui-box>
<ui-box heading="Ausbildungen"> <courses :value="props.data.courses" /> </ui-box>
<ui-box heading="Zahlungen"> <payments :value="props.data.invoicePositions" /> </ui-box>
<ui-box heading="Karte"> <div class="h-full flex items-center justify-center text-gray-400 text-center">Keine Karte vorhanden</div> </ui-box>
</section>
</div>
</page-layout>
</template>
<script>
import {defineAsyncComponent} from 'vue';
<script lang="ts" setup>
import {defineAsyncComponent, ref} from 'vue';
export default {
props: {
data: {},
meta: {},
},
data: function () {
return {
inner: {},
tabs: {
stammkontakt: {
children: {
stamm: 'Stammdaten',
kontakt: 'Kontakt',
},
active: 'stamm',
},
praesystem: {
children: {
system: 'System',
prae: 'Prävention',
},
active: 'system',
},
membershipcourse: {
children: {
membership: 'Mitgliedschaften',
course: 'Ausbildungen',
},
active: 'membership',
},
},
};
},
const stamm = defineAsyncComponent(() => import('./boxes/Stamm.vue'));
const kontakt = defineAsyncComponent(() => import('./boxes/Kontakt.vue'));
const prae = defineAsyncComponent(() => import('./boxes/Prae.vue'));
const courses = defineAsyncComponent(() => import('./boxes/Courses.vue'));
const system = defineAsyncComponent(() => import('./boxes/System.vue'));
const payments = defineAsyncComponent(() => import('./boxes/Payments.vue'));
const memberships = defineAsyncComponent(() => import('./boxes/Memberships.vue'));
methods: {},
components: {
stamm: defineAsyncComponent(() => import('./boxes/Stamm.vue')),
kontakt: defineAsyncComponent(() => import('./boxes/Kontakt.vue')),
prae: defineAsyncComponent(() => import('./boxes/Prae.vue')),
courses: defineAsyncComponent(() => import('./boxes/Courses.vue')),
system: defineAsyncComponent(() => import('./boxes/System.vue')),
payments: defineAsyncComponent(() => import('./boxes/Payments.vue')),
memberships: defineAsyncComponent(() => import('./boxes/Memberships.vue')),
tabs: defineAsyncComponent(() => import('./Tabs.vue')),
const tabs = ref({
stammkontakt: {
active: 0,
entries: [{title: 'Stammdaten'}, {title: 'Kontakt'}],
},
created() {
this.inner = this.data;
praesystem: {
active: 0,
entries: [{title: 'System'}, {title: 'Prävention'}],
},
};
membershipcourse: {
active: 0,
entries: [{title: 'Mitgliedschaften'}, {title: 'Ausbildungen'}, {title: 'Zahlungen'}, {title: 'Karte'}],
},
});
const props = defineProps<{
data: object,
meta: object,
}>();
</script>
<style scoped>
.this-grid {
grid-template-areas:
'stammkontakt'
'praesystem'
'courses'
'memberships'
'payments';
grid-template-columns: 1fr;
}
@media screen and (min-width: 1280px) {
.this-grid {
grid-template-areas:
'stamm kontakt praev system'
'membershipcourse membershipcourse membershipcourse membershipcourse'
'payments payments map map';
grid-template-columns: max-content max-content max-content 1fr;
}
}
.area-stamm {
grid-area: stamm;
}
.area-kontakt {
grid-area: kontakt;
}
.area-praev {
grid-area: praev;
}
.area-courses {
grid-area: courses;
}
.area-system {
grid-area: system;
}
.area-memberships {
grid-area: memberships;
}
.area-payments {
grid-area: payments;
}
.area-map {
grid-area: map;
}
.area-stammkontakt {
grid-area: stammkontakt;
}
.area-membershipcourse {
grid-area: membershipcourse;
}
.area-praesystem {
grid-area: praesystem;
}
</style>

View File

@ -1,46 +0,0 @@
<template>
<section>
<div class="flex space-x-2 border-b border-teal-200">
<a
v-for="(v, index) in inner.children"
href="#"
class="font-semibold hover:text-teal-600 transition-all"
:class="{'text-teal-800': inner.active !== index, 'text-teal-600': inner.active === index}"
@click.prevent="navigate(index)"
>
<span v-text="v"></span>
</a>
</div>
<div class="mt-3">
<slot></slot>
</div>
</section>
</template>
<script>
export default {
props: {
modelValue: {},
},
data: function () {
return {
inner: {
children: {},
active: null,
},
};
},
created() {
this.inner = this.modelValue;
},
methods: {
navigate(v) {
this.inner.active = v;
this.$emit('update:modelValue', this.inner);
},
},
};
</script>

View File

@ -16,68 +16,79 @@ use Tests\EndToEndTestCase;
use Throwable;
use Zoomyboy\LaravelNami\Fakes\MembershipFake;
class MassstoreActionTest extends EndToEndTestCase
{
uses(EndToEndTestCase::class);
public function testItFiresActionJobWhenUsingController(): void
{
Queue::fake();
$this->login()->loginNami()->withoutExceptionHandling();
$member = Member::factory()->defaults()->create();
$activity = Activity::factory()->create();
$subactivity = Subactivity::factory()->create();
$group = Group::factory()->create();
it('testItFiresActionJobWhenUsingController', function() {
Queue::fake();
$this->login()->loginNami()->withoutExceptionHandling();
$member = Member::factory()->defaults()->create();
$activity = Activity::factory()
->hasAttached(Subactivity::factory())
->create();
$group = Group::factory()->create();
$this->postJson(route('membership.masslist.store'), [
'members' => [$member->id],
'activity_id' => $activity->id,
'subactivity_id' => $subactivity->id,
'group_id' => $group->id,
]);
MassStoreAction::assertPushed(fn ($action, $params) => $params[0]->is($group) && $params[1]->is($activity) && $params[2]->is($subactivity) && $params[3][0] === $member->id);
}
$subactivity = $activity->subactivities()->first();
$this->postJson(route('membership.masslist.store'), [
'members' => [$member->id],
'activity_id' => $activity->id,
'subactivity_id' => $subactivity->id,
'group_id' => $group->id,
]);
MassStoreAction::assertPushed(fn ($action, $params) => $params[0]->is($group) && $params[1]->is($activity) && $params[2]->is($subactivity) && $params[3][0] === $member->id);
});
public function testItCreatesAMembership(): void
{
MembershipDestroyAction::partialMock()->shouldReceive('handle')->never();
MembershipStoreAction::partialMock()->shouldReceive('handle')->once();
$member = Member::factory()->defaults()->create();
$activity = Activity::factory()->create();
$subactivity = Subactivity::factory()->create();
$group = Group::factory()->create();
it('testItCreatesAMembership', function() {
MembershipDestroyAction::partialMock()->shouldReceive('handle')->never();
MembershipStoreAction::partialMock()->shouldReceive('handle')->once();
$member = Member::factory()->defaults()->create();
$activity = Activity::factory()->create();
$subactivity = Subactivity::factory()->create();
$group = Group::factory()->create();
MassStoreAction::run($group, $activity, $subactivity, [$member->id]);
}
MassStoreAction::run($group, $activity, $subactivity, [$member->id]);
});
public function testItDeletesAMembership(): void
{
MembershipDestroyAction::partialMock()->shouldReceive('handle')->once();
MembershipStoreAction::partialMock()->shouldReceive('handle')->never();
ResyncAction::partialMock()->shouldReceive('handle')->once();
it('cannot create membership when activity and subactivity doesnt belong together', function() {
$this->login()->loginNami();
$member = Member::factory()->defaults()->create();
$activity = Activity::factory()->create();
$subactivity = Subactivity::factory()->create();
$group = Group::factory()->create();
$member = Member::factory()->defaults()->has(Membership::factory()->inLocal('Leiter*in', 'Rover'))->create();
$this->postJson(route('membership.masslist.store'), [
'members' => [$member->id],
'activity_id' => $activity->id,
'subactivity_id' => $subactivity->id,
'group_id' => $group->id,
])->assertJsonValidationErrors(['activity_id' => 'Tätigkeit ist nicht vorhanden.']);
});
it('testItDeletesAMembership', function() {
MembershipDestroyAction::partialMock()->shouldReceive('handle')->once();
MembershipStoreAction::partialMock()->shouldReceive('handle')->never();
ResyncAction::partialMock()->shouldReceive('handle')->once();
$member = Member::factory()->defaults()->has(Membership::factory()->inLocal('Leiter*in', 'Rover'))->create();
MassStoreAction::run($member->memberships->first()->group, $member->memberships->first()->activity, $member->memberships->first()->subactivity, []);
});
it('testItRollsbackWhenDeletionFails', function() {
app(MembershipFake::class)
->shows(3, ['id' => 55])
->shows(3, ['id' => 56])
->destroysSuccessfully(3, 55)
->failsDeleting(3, 56);
$this->login()->loginNami();
$member = Member::factory()->defaults()->inNami(3)
->has(Membership::factory()->in('Leiter*in', 10, 'Rover', 11)->inNami(55))
->has(Membership::factory()->in('Leiter*in', 10, 'Jungpfadfinder', 12)->inNami(56))
->create();
try {
MassStoreAction::run($member->memberships->first()->group, $member->memberships->first()->activity, $member->memberships->first()->subactivity, []);
} catch (Throwable $e) {
}
public function testItRollsbackWhenDeletionFails(): void
{
app(MembershipFake::class)
->shows(3, ['id' => 55])
->shows(3, ['id' => 56])
->destroysSuccessfully(3, 55)
->failsDeleting(3, 56);
$this->login()->loginNami();
$member = Member::factory()->defaults()->inNami(3)
->has(Membership::factory()->in('Leiter*in', 10, 'Rover', 11)->inNami(55))
->has(Membership::factory()->in('Leiter*in', 10, 'Jungpfadfinder', 12)->inNami(56))
->create();
try {
MassStoreAction::run($member->memberships->first()->group, $member->memberships->first()->activity, $member->memberships->first()->subactivity, []);
} catch (Throwable $e) {
}
$this->assertDatabaseCount('memberships', 2);
}
}
$this->assertDatabaseCount('memberships', 2);
});

View File

@ -54,6 +54,10 @@
"forceConsistentCasingInFileNames": true,
// See <https://github.com/vuejs/vue-cli/pull/5688>
"skipLibCheck": true,
"types": ["vite/client"]
}
"types": ["vite/client"],
"paths": {
"@/*": ["./resources/js/*"]
}
},
"include": ["**/*", "resources/js/components/components.d.ts"]
}

32
vite.config.js vendored
View File

@ -1,10 +1,40 @@
import {defineConfig} from 'vite';
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue';
import path from 'path';
import Components from 'unplugin-vue-components/vite'
export default defineConfig({
plugins: [
Components({
globs: [],
directives: false,
directoryAsNamespace: false,
types: [],
dts: 'resources/js/components/components.d.ts',
resolvers: [
(componentName) => {
if (componentName === 'FMultiplefiles') {
return;
}
if (componentName === 'FSinglefile') {
return;
}
if (componentName.startsWith('Ui')) {
let singleComponentName = componentName.replace(/^Ui/, '');
return { name: 'default', from: `@/components/ui/${singleComponentName}.vue` };
}
if (componentName.startsWith('F')) {
let singleComponentName = componentName.replace(/^F/, '');
return { name: 'default', from: `@/components/form/${singleComponentName}.vue` };
}
if (componentName.startsWith('Page')) {
let singleComponentName = componentName.replace(/^Page/, '');
return { name: 'default', from: `@/components/page/${singleComponentName}.vue` };
}
},
]
}),
laravel(['resources/js/app.js']),
vue({
template: {