Basic design created
This commit is contained in:
32
app/Domains/Dashboard/Controllers/DashboardController.php
Normal file
32
app/Domains/Dashboard/Controllers/DashboardController.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Dashboard\Controllers;
|
||||
|
||||
use App\Providers\AuthCheckProvider;
|
||||
use App\Providers\InertiaProvider;
|
||||
use App\Scopes\CommonController;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class DashboardController extends CommonController {
|
||||
public function __invoke(Request $request) {
|
||||
if ($this->checkAuth()) {
|
||||
return $this->renderForLoggedInUser($request);
|
||||
}
|
||||
|
||||
return redirect()->intended('/login');
|
||||
|
||||
dd('U');
|
||||
return $this->renderForGuest($request);
|
||||
|
||||
}
|
||||
|
||||
private function renderForLoggedInUser(Request $request) {
|
||||
$authCheckProvider = new AuthCheckProvider;
|
||||
$inertiaProvider = new InertiaProvider('Dashboard/Dashboard', ['appName' => app('tenant')->name]);
|
||||
return $inertiaProvider->render();
|
||||
}
|
||||
|
||||
private function renderForGuest(Request $request) {
|
||||
}
|
||||
}
|
||||
42
app/Domains/Dashboard/Views/Dashboard.vue
Normal file
42
app/Domains/Dashboard/Views/Dashboard.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<script setup>
|
||||
import AppLayout from '../../../../resources/js/layouts/AppLayout.vue'
|
||||
import ShadowedBox from "../../../Views/Components/ShadowedBox.vue";
|
||||
|
||||
const props = defineProps({
|
||||
navbar: Object,
|
||||
tenant: String,
|
||||
user: Object,
|
||||
currentPath: String,
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AppLayout title='Dashboard' :user="props.user" :navbar="props.navbar" :tenant="props.tenant" :currentPath="props.currentPath">
|
||||
<diV class="dashboard-widget-container">
|
||||
<shadowed-box class="dashboard-widget-box" style="width: 60%;">
|
||||
Meine Anmeldungen
|
||||
</shadowed-box>
|
||||
|
||||
<shadowed-box class="dashboard-widget-box">
|
||||
Meine Abrechnungen
|
||||
</shadowed-box>
|
||||
</diV>
|
||||
</AppLayout>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.dashboard-widget-container {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
flex-wrap: wrap;
|
||||
position: relative;
|
||||
|
||||
|
||||
}
|
||||
|
||||
.dashboard-widget-box {
|
||||
flex-grow: 1; display: inline-block;
|
||||
height: 150px;
|
||||
margin: 0 10px;
|
||||
}
|
||||
</style>
|
||||
21
app/Domains/UserManagement/Controllers/LogOutController.php
Normal file
21
app/Domains/UserManagement/Controllers/LogOutController.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\UserManagement\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class LogOutController {
|
||||
public function __invoke(Request $request) {
|
||||
Auth::logout();
|
||||
|
||||
// Session invalidieren
|
||||
$request->session()->invalidate();
|
||||
|
||||
// CSRF-Token regenerieren (für Sicherheit)
|
||||
$request->session()->regenerateToken();
|
||||
|
||||
// Redirect z.B. zur Login-Seite
|
||||
return redirect()->intended('/')->with('status', 'Erfolgreich abgemeldet!');
|
||||
}
|
||||
}
|
||||
51
app/Domains/UserManagement/Controllers/LoginController.php
Normal file
51
app/Domains/UserManagement/Controllers/LoginController.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\UserManagement\Controllers;
|
||||
|
||||
use App\Providers\InertiaProvider;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class LoginController {
|
||||
public function loginForm(Request $request) {
|
||||
$errors = [];
|
||||
|
||||
if ($request->session()->has('errors')) {
|
||||
$errors = $request->session()->get('errors')->getBag('default')->getMessages();
|
||||
}
|
||||
|
||||
|
||||
$inertiaProvider = new InertiaProvider('UserManagement/Login', ['errors' => $errors, 'appName' => app('tenant')->name]);
|
||||
return $inertiaProvider->render();
|
||||
}
|
||||
|
||||
public function doLogin(Request $request)
|
||||
{
|
||||
|
||||
$credentials = $request->validate([
|
||||
'username' => ['required', 'string'],
|
||||
'password' => ['required'],
|
||||
],
|
||||
[
|
||||
'username.required' => 'Bitte gib deinen Anmeldenamen ein.',
|
||||
'username.string' => 'Der Anmeldename muss eine E-Mail-Adresse sein.',
|
||||
'password.required' => 'Bitte gib dein Passwort ein.',
|
||||
]);
|
||||
|
||||
#$credentials = ['username' => 'development', 'password' => 'development'];
|
||||
|
||||
if (!Auth::attempt($credentials)) {
|
||||
return back()->withErrors([
|
||||
'username' => 'Diese Zugangsdaten sind ungültig.',
|
||||
]);
|
||||
}
|
||||
|
||||
$request->session()->regenerate();
|
||||
$user = Auth::user();
|
||||
|
||||
|
||||
# dd($user->firstname . ' ' . $user->lastname);
|
||||
|
||||
return redirect()->intended('/');
|
||||
}
|
||||
}
|
||||
64
app/Domains/UserManagement/Views/Login.vue
Normal file
64
app/Domains/UserManagement/Views/Login.vue
Normal file
@@ -0,0 +1,64 @@
|
||||
<script setup>
|
||||
import AppLayout from '../../../../resources/js/layouts/AppLayout.vue'
|
||||
import {onMounted, ref} from 'vue'
|
||||
import { toast } from 'vue3-toastify'
|
||||
import ShadowedBox from "../../../Views/Components/ShadowedBox.vue";
|
||||
|
||||
|
||||
const props = defineProps({
|
||||
navbar: Object,
|
||||
tenant: String,
|
||||
user: Object,
|
||||
currentPath: String,
|
||||
errors: Object,
|
||||
})
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
if (undefined !== props.errors && undefined !== props.errors.username) {
|
||||
toast.error(props.errors.username[0])
|
||||
}
|
||||
})
|
||||
|
||||
//console.log(props.errors.password[0])
|
||||
const username = ref('')
|
||||
const password = ref('')
|
||||
|
||||
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AppLayout title='Anmelden' :user="props.user" :navbar="props.navbar" :tenant="props.tenant" :currentPath="props.currentPath">
|
||||
<form method="POST" action="/login">
|
||||
<input type="hidden" name="_token" :value="csrfToken" />
|
||||
<shadowed-box style="width: 50%; margin: 150px auto; padding: 20px;">
|
||||
<table>
|
||||
<tr>
|
||||
<th>Anmeldename</th>
|
||||
<td>
|
||||
<input type="text" name="username" id="username"></input>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>Passwort</th>
|
||||
<td><input type="password" name="password" id="password"></input></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<input type="submit" value="Anmelden" style="margin-top: 20px;" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</shadowed-box>
|
||||
</form>
|
||||
</AppLayout>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
th {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
</style>
|
||||
13
app/Http/Controllers/TestRenderInertiaProvider.php
Normal file
13
app/Http/Controllers/TestRenderInertiaProvider.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Providers\InertiaProvider;
|
||||
|
||||
class TestRenderInertiaProvider
|
||||
{
|
||||
public function index() {
|
||||
$inertiaProvider = new InertiaProvider('Invoice/CreateInvoice', ['appName' => app('tenant')->name]);
|
||||
return $inertiaProvider->render();
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,7 @@ class User extends Authenticatable
|
||||
'first_aid_permission',
|
||||
'bank_account_iban',
|
||||
'password',
|
||||
'active',
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
23
app/Providers/AuthCheckProvider.php
Normal file
23
app/Providers/AuthCheckProvider.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
class AuthCheckProvider {
|
||||
public function checkLoggedIn() : bool {
|
||||
if (!auth()->check()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$user = auth()->user();
|
||||
$tenant = app('tenant');
|
||||
return $user->active && $tenant->slug === $user->tenant;
|
||||
}
|
||||
|
||||
public function getUserRole() : ?string {
|
||||
if (!$this->checkLoggedIn()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return auth()->user()->user_role;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Models\User;
|
||||
use Inertia\Inertia;
|
||||
use Inertia\Response;
|
||||
|
||||
@@ -10,17 +11,43 @@ final class InertiaProvider
|
||||
private string $vueFile;
|
||||
private array $props;
|
||||
|
||||
private ?User $user;
|
||||
|
||||
public function __construct(string $vueFile, array $props) {
|
||||
$this->user = auth()->user();
|
||||
$this->vueFile = $vueFile;
|
||||
$this->props = $props;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function render() : Response {
|
||||
$this->props['navbar'] = $this->generateNavbar();
|
||||
$this->props['tenant'] = app('tenant')->local_group_name;
|
||||
$this->props['user'] = $this->user;
|
||||
$this->props['currentPath'] = request()->path();
|
||||
|
||||
return Inertia::render(
|
||||
str_replace('/', '/Views/', $this->vueFile),
|
||||
$this->props
|
||||
);
|
||||
}
|
||||
|
||||
private function generateNavbar() : array {
|
||||
$navigation = [
|
||||
'personal' => [],
|
||||
'common' => [],
|
||||
'costunits' => [],
|
||||
'events' => [],
|
||||
];
|
||||
|
||||
$navigation['personal'][] = ['url' => '/', 'display' => 'Home'];
|
||||
if (null !== $this->user) {
|
||||
$navigation['personal'][] = ['url' => '/personal-data', 'display' => 'Meine Daten'];
|
||||
$navigation['personal'][] = ['url' => '/messages', 'display' => 'Meine Nachrichten'];
|
||||
}
|
||||
|
||||
$navigation['common'][] = ['url' => '/capture-invoice', 'display' => 'Neue Abrechnung'];
|
||||
$navigation['common'][] = ['url' => '/available-events', 'display' => 'Verfügbare Veranstaltungen'];
|
||||
|
||||
return $navigation;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,11 @@ class TenantUserProvider extends EloquentUserProvider
|
||||
}
|
||||
}
|
||||
|
||||
$query->where('tenant', app('tenant')->slug);
|
||||
$query->where([
|
||||
'tenant' => app('tenant')->slug,
|
||||
'active' => true
|
||||
|
||||
]);
|
||||
|
||||
return $query->first();
|
||||
}
|
||||
|
||||
12
app/Scopes/CommonController.php
Normal file
12
app/Scopes/CommonController.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace App\Scopes;
|
||||
|
||||
use App\Providers\AuthCheckProvider;
|
||||
|
||||
abstract class CommonController {
|
||||
protected function checkAuth() {
|
||||
$authCheckProvider = new AuthCheckProvider;
|
||||
return $authCheckProvider->checkLoggedIn();
|
||||
}
|
||||
}
|
||||
17
app/Views/Components/Icon.vue
Normal file
17
app/Views/Components/Icon.vue
Normal file
@@ -0,0 +1,17 @@
|
||||
<script setup>
|
||||
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
|
||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||
import * as SolidIcons from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
const props = defineProps({
|
||||
name: { type: String, required: true },
|
||||
})
|
||||
|
||||
if (SolidIcons[`fa${props.name.charAt(0).toUpperCase()}${props.name.slice(1)}`]) {
|
||||
library.add(SolidIcons[`fa${props.name.charAt(0).toUpperCase()}${props.name.slice(1)}`])
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<font-awesome-icon :icon="name" />
|
||||
</template>
|
||||
23
app/Views/Components/ShadowedBox.vue
Normal file
23
app/Views/Components/ShadowedBox.vue
Normal file
@@ -0,0 +1,23 @@
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
style: { type: String},
|
||||
class: { type: String},
|
||||
})
|
||||
|
||||
console.log(props.style)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="shadowed-box" :style=props.style :class=props.class>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.shadowed-box {
|
||||
box-shadow: 2px 2px 5px #c0c0c0;
|
||||
border-radius: 10px;
|
||||
padding: 10px;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
</style>
|
||||
41
app/Views/Partials/GlobalWidgets/GlobalWidgets.vue
Normal file
41
app/Views/Partials/GlobalWidgets/GlobalWidgets.vue
Normal file
@@ -0,0 +1,41 @@
|
||||
<script setup>
|
||||
|
||||
import ShadowedBox from "../../Components/ShadowedBox.vue";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<diV class="widget-container">
|
||||
<shadowed-box class="widget-box">
|
||||
Widget 1
|
||||
</shadowed-box>
|
||||
|
||||
<shadowed-box class="widget-box">
|
||||
Widget 2
|
||||
</shadowed-box>
|
||||
<shadowed-box class="widget-box">
|
||||
Widget 3
|
||||
</shadowed-box>
|
||||
<shadowed-box class="widget-box">
|
||||
Widget 4
|
||||
</shadowed-box>
|
||||
</diV>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.widget-container {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
flex-wrap: wrap;
|
||||
position: relative;
|
||||
|
||||
|
||||
}
|
||||
|
||||
.widget-box {
|
||||
flex-grow: 1; display: inline-block;
|
||||
width: calc(25% - 40px);
|
||||
height: 150px;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user