Compare commits

..

No commits in common. "adf9341dd76ea69938368812a9d323f6424ec0d3" and "9d41cdb0103044986025dd1af7682ec749f78644" have entirely different histories.

14 changed files with 936 additions and 1110 deletions

View File

@ -10,7 +10,6 @@ use App\Maildispatcher\Actions\ResyncAction;
use App\Member\Member; use App\Member\Member;
use App\Member\Membership; use App\Member\Membership;
use App\Subactivity; use App\Subactivity;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Lorisleiva\Actions\ActionRequest; use Lorisleiva\Actions\ActionRequest;
use Lorisleiva\Actions\Concerns\AsAction; use Lorisleiva\Actions\Concerns\AsAction;
@ -27,12 +26,7 @@ class MassStoreAction
{ {
return [ return [
'group_id' => 'required|numeric|exists:groups,id', 'group_id' => 'required|numeric|exists:groups,id',
'activity_id' => ['required', 'numeric', 'exists:activities,id', function($key, $value, $fail) { 'activity_id' => 'required|numeric|exists:activities,id',
$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', 'subactivity_id' => 'required|numeric|exists:subactivities,id',
'members' => 'array', 'members' => 'array',
'members.*' => 'numeric|exists:members,id', 'members.*' => 'numeric|exists:members,id',
@ -70,7 +64,7 @@ class MassStoreAction
}); });
} }
public function asController(ActionRequest $request): JsonResponse public function asController(ActionRequest $request): void
{ {
/** /**
* @var array{members: array<int, int>, group_id: int, activity_id: int, subactivity_id: int} * @var array{members: array<int, int>, group_id: int, activity_id: int, subactivity_id: int}
@ -83,16 +77,6 @@ class MassStoreAction
Subactivity::findOrFail($input['subactivity_id']), Subactivity::findOrFail($input['subactivity_id']),
$input['members'], $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", "cviebrock/eloquent-sluggable": "^11.0",
"doctrine/dbal": "^3.1", "doctrine/dbal": "^3.1",
"guzzlehttp/guzzle": "^7.0.1", "guzzlehttp/guzzle": "^7.0.1",
"inertiajs/inertia-laravel": "^2.0", "inertiajs/inertia-laravel": "^1.0",
"laravel/framework": "^11.0", "laravel/framework": "^11.0",
"laravel/horizon": "^5.0", "laravel/horizon": "^5.0",
"laravel/pail": "^1.1", "laravel/pail": "^1.1",

1103
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/header": "^2.8.1",
"@editorjs/nested-list": "^1.4.2", "@editorjs/nested-list": "^1.4.2",
"@editorjs/paragraph": "^2.11.3", "@editorjs/paragraph": "^2.11.3",
"@inertiajs/vue3": "^2.0", "@inertiajs/vue3": "^1.0.14",
"@tailwindcss/forms": "^0.5.7", "@tailwindcss/forms": "^0.5.7",
"@tailwindcss/typography": "^0.5.10", "@tailwindcss/typography": "^0.5.10",
"@vitejs/plugin-vue": "^4.6.2", "@vitejs/plugin-vue": "^4.6.2",
@ -40,7 +40,6 @@
"dayjs": "^1.11.10", "dayjs": "^1.11.10",
"postcss": "^8.4.33", "postcss": "^8.4.33",
"tailwindcss": "^3.4.1", "tailwindcss": "^3.4.1",
"unplugin-vue-components": "^28.7.0",
"vue-axios": "^3.5.2" "vue-axios": "^3.5.2"
} }
}, },
@ -527,9 +526,9 @@
} }
}, },
"node_modules/@eslint/config-array": { "node_modules/@eslint/config-array": {
"version": "0.20.1", "version": "0.20.0",
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.1.tgz", "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz",
"integrity": "sha512-OL0RJzC/CBzli0DrrR31qzj6d6i6Mm3HByuhflhl4LOBiWxN+3i6/t/ZQQNii4tjksXi8r2CRW1wMpWA2ULUEw==", "integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==",
"dependencies": { "dependencies": {
"@eslint/object-schema": "^2.1.6", "@eslint/object-schema": "^2.1.6",
"debug": "^4.3.1", "debug": "^4.3.1",
@ -540,9 +539,9 @@
} }
}, },
"node_modules/@eslint/config-helpers": { "node_modules/@eslint/config-helpers": {
"version": "0.2.3", "version": "0.2.2",
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.3.tgz", "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.2.tgz",
"integrity": "sha512-u180qk2Um1le4yf0ruXH3PYFeEZeYC3p/4wCTKrr2U1CmGdzGi3KtY0nuPDH48UJxlKCC5RDzbcbh4X0XlqgHg==", "integrity": "sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==",
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
} }
@ -600,28 +599,17 @@
} }
}, },
"node_modules/@eslint/plugin-kit": { "node_modules/@eslint/plugin-kit": {
"version": "0.3.2", "version": "0.3.1",
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.2.tgz", "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.1.tgz",
"integrity": "sha512-4SaFZCNfJqvk/kenHpI8xvN42DMaoycy4PzKc5otHxRswww1kAt82OlBuwRVLofCACCTZEcla2Ydxv8scMXaTg==", "integrity": "sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==",
"dependencies": { "dependencies": {
"@eslint/core": "^0.15.0", "@eslint/core": "^0.14.0",
"levn": "^0.4.1" "levn": "^0.4.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "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": { "node_modules/@floating-ui/core": {
"version": "1.7.1", "version": "1.7.1",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.1.tgz", "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.1.tgz",
@ -700,22 +688,24 @@
} }
}, },
"node_modules/@inertiajs/core": { "node_modules/@inertiajs/core": {
"version": "2.0.12", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/@inertiajs/core/-/core-2.0.12.tgz", "resolved": "https://registry.npmjs.org/@inertiajs/core/-/core-1.3.0.tgz",
"integrity": "sha512-TxMRUcSB/w2Or9KSsldgcx49u+1xveLg7HuwRkqrs196ZrDwYRjtc984uc838vDP+dsFIz//+Tn0n7ysG/MgMQ==", "integrity": "sha512-TJ8R1eUYY473m9DaKlCPRdHTdznFWTDuy5VvEzXg3t/hohbDQedLj46yn/uAqziJPEUZJrSftZzPI2NMzL9tQA==",
"dependencies": { "dependencies": {
"axios": "^1.8.2", "axios": "^1.6.0",
"es-toolkit": "^1.34.1", "deepmerge": "^4.0.0",
"nprogress": "^0.2.0",
"qs": "^6.9.0" "qs": "^6.9.0"
} }
}, },
"node_modules/@inertiajs/vue3": { "node_modules/@inertiajs/vue3": {
"version": "2.0.12", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/@inertiajs/vue3/-/vue3-2.0.12.tgz", "resolved": "https://registry.npmjs.org/@inertiajs/vue3/-/vue3-1.3.0.tgz",
"integrity": "sha512-ruvThr3BKunFjh+EamcGilAI8RGSF/upL//E9bnchYEWFCwQtZ2NzQ0tBOFLQ+qYnaRiDjsyTa63h1R36PUmbg==", "integrity": "sha512-GizqdCM3u4JWunit3uUbW4fEmTLKQTi1W7VvPRdrNy8XDt4Qy2cCmfFjq+aH5tHBSS3fI/ngYuhN7XvwqNaKvw==",
"dependencies": { "dependencies": {
"@inertiajs/core": "2.0.12", "@inertiajs/core": "1.3.0",
"es-toolkit": "^1.33.0" "lodash.clonedeep": "^4.5.0",
"lodash.isequal": "^4.5.0"
}, },
"peerDependencies": { "peerDependencies": {
"vue": "^3.0.0" "vue": "^3.0.0"
@ -1774,9 +1764,9 @@
} }
}, },
"node_modules/caniuse-lite": { "node_modules/caniuse-lite": {
"version": "1.0.30001723", "version": "1.0.30001722",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001723.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001722.tgz",
"integrity": "sha512-1R/elMjtehrFejxwmexeXAtae5UO9iSyFn6G/I806CYC/BLyyBk1EPhrKBkWhy6wM6Xnm47dSJQec+tLJ39WHw==", "integrity": "sha512-DCQHBBZtiK6JVkAGw7drvAMK0Q0POD/xZvEmDp6baiMMP6QXXk9HpD6mNYBZWhOPG6LvIDb82ITqtWjhDckHCA==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@ -1995,12 +1985,6 @@
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" "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": { "node_modules/constant-case": {
"version": "3.0.4", "version": "3.0.4",
"resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz", "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz",
@ -2131,6 +2115,14 @@
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" "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": { "node_modules/delayed-stream": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@ -2233,9 +2225,9 @@
"integrity": "sha512-m6w/cRxnFucC3dyfrB+DTNXw70SnJNv05AX6P3bZ8qkbzB1OAJTuaFrEKZBdN0YvEvTe1zvg3S344EkPAveemQ==" "integrity": "sha512-m6w/cRxnFucC3dyfrB+DTNXw70SnJNv05AX6P3bZ8qkbzB1OAJTuaFrEKZBdN0YvEvTe1zvg3S344EkPAveemQ=="
}, },
"node_modules/electron-to-chromium": { "node_modules/electron-to-chromium": {
"version": "1.5.167", "version": "1.5.166",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.167.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.166.tgz",
"integrity": "sha512-LxcRvnYO5ez2bMOFpbuuVuAI5QNeY1ncVytE/KXaL6ZNfzX1yPlAO0nSOyIHx2fVAuUprMqPs/TdVhUFZy7SIQ==", "integrity": "sha512-QPWqHL0BglzPYyJJ1zSSmwFFL6MFXhbACOCcsCdUMCkzPdS9/OIBVxg516X/Ado2qwAq8k0nJJ7phQPCqiaFAw==",
"dev": true "dev": true
}, },
"node_modules/emoji-regex": { "node_modules/emoji-regex": {
@ -2297,15 +2289,6 @@
"node": ">= 0.4" "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": { "node_modules/esbuild": {
"version": "0.18.20", "version": "0.18.20",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz",
@ -2537,12 +2520,6 @@
"node": ">=0.10.0" "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": { "node_modules/fast-deep-equal": {
"version": "3.1.3", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@ -3160,23 +3137,6 @@
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" "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": { "node_modules/locate-path": {
"version": "6.0.0", "version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
@ -3201,11 +3161,22 @@
"resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz",
"integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==" "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": { "node_modules/lodash.escape": {
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz",
"integrity": "sha512-nXEOnb/jK9g0DYMr1/Xvq6l5xMD7GDG55+GSYIYmS0G4tBk/hURD4JR9WCavs04t33WmJx9kCyp9vJ+mr4BOUw==" "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": { "node_modules/lodash.isplainobject": {
"version": "4.0.6", "version": "4.0.6",
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
@ -3337,35 +3308,6 @@
"node": ">=16 || 14 >=14.17" "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": { "node_modules/ms": {
"version": "2.1.3", "version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@ -3443,6 +3385,11 @@
"node": ">=0.10.0" "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": { "node_modules/nth-check": {
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
@ -3628,12 +3575,6 @@
"url": "https://github.com/sponsors/isaacs" "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": { "node_modules/picocolors": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@ -3687,21 +3628,10 @@
"node": ">= 6" "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": { "node_modules/postcss": {
"version": "8.5.5", "version": "8.5.4",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.5.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.4.tgz",
"integrity": "sha512-d/jtm+rdNT8tpXuHY5MMtcbJFBkhXE6593XVR9UoGCH8jSFGci7jGvMGH5RYd5PBJW+00NZQt6gf7CbagJCrhg==", "integrity": "sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==",
"funding": [ "funding": [
{ {
"type": "opencollective", "type": "opencollective",
@ -3899,22 +3829,6 @@
"url": "https://github.com/sponsors/ljharb" "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": { "node_modules/queue-microtask": {
"version": "1.2.3", "version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@ -4544,48 +4458,6 @@
"node": ">=0.8" "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": { "node_modules/to-regex-range": {
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@ -4676,101 +4548,6 @@
"typescript": ">=4.8.4 <5.9.0" "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": { "node_modules/update-browserslist-db": {
"version": "1.1.3", "version": "1.1.3",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
@ -5015,12 +4792,6 @@
"vue": "^3.0.1" "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": { "node_modules/which": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",

View File

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

4
resources/js/app.js vendored
View File

@ -5,6 +5,7 @@ import VueAxios from 'vue-axios';
import {Plugin as FloatingVue, options as FloatingVueOptions} from './lib/floatingVue.js'; import {Plugin as FloatingVue, options as FloatingVueOptions} from './lib/floatingVue.js';
import {createPinia, PiniaVuePlugin} from 'pinia'; import {createPinia, PiniaVuePlugin} from 'pinia';
import Echo from './lib/echo.js'; import Echo from './lib/echo.js';
import requireModules from './lib/requireModules.js';
import AppLayout from './layouts/AppLayout.vue'; import AppLayout from './layouts/AppLayout.vue';
import hasModule from './mixins/hasModule.js'; import hasModule from './mixins/hasModule.js';
@ -46,6 +47,9 @@ createInertiaApp({
.mixin(hasModule) .mixin(hasModule)
.mixin(hasFlash); .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( app.component(
'FSinglefile', 'FSinglefile',
defineAsyncComponent(() => import('!/medialibrary-helper/assets/components/SingleFile.vue')) defineAsyncComponent(() => import('!/medialibrary-helper/assets/components/SingleFile.vue'))

View File

@ -1,57 +0,0 @@
/* 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,25 +1,38 @@
<template> <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-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"> <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" <a
:class="index === modelValue ? `bg-gray-700 group-[.is-popup]:bg-zinc-600` : ''" @click.prevent="openMenu(index)" 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" v-text="item.title"
/> ></a>
</div> </div>
</div> </div>
</template> </template>
<script lang="ts" setup> <script>
defineProps<{ export default {
modelValue: number, props: {
entries: {title: string}[] modelValue: {
}>(); type: Number,
required: true,
const emits = defineEmits<{ },
'update:modelValue': [number], entries: {
}>(); required: true,
validator: function (entries) {
function openMenu(index: number) { return entries.filter((e) => e.title === undefined || typeof e.title !== 'string' || e.title.length === 0).length === 0;
emits('update:modelValue', index); },
} },
},
emits: ['update:modelValue'],
methods: {
openMenu(index) {
this.$emit('update:modelValue', index);
},
},
};
</script> </script>

10
resources/js/lib/requireModules.js vendored Normal file
View File

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

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

View File

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

30
vite.config.js vendored
View File

@ -2,39 +2,9 @@ import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin'; import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue'; import vue from '@vitejs/plugin-vue';
import path from 'path'; import path from 'path';
import Components from 'unplugin-vue-components/vite'
export default defineConfig({ export default defineConfig({
plugins: [ 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']), laravel(['resources/js/app.js']),
vue({ vue({
template: { template: {