Script erstellt
This commit is contained in:
11
resources/css/app.css
Executable file
11
resources/css/app.css
Executable file
@@ -0,0 +1,11 @@
|
||||
@import 'tailwindcss';
|
||||
|
||||
@source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php';
|
||||
@source '../../storage/framework/views/*.php';
|
||||
@source '../**/*.blade.php';
|
||||
@source '../**/*.js';
|
||||
|
||||
@theme {
|
||||
--font-sans: 'Instrument Sans', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
|
||||
'Segoe UI Symbol', 'Noto Color Emoji';
|
||||
}
|
||||
1
resources/js/app.js
Executable file
1
resources/js/app.js
Executable file
@@ -0,0 +1 @@
|
||||
import './bootstrap';
|
||||
4
resources/js/bootstrap.js
vendored
Executable file
4
resources/js/bootstrap.js
vendored
Executable file
@@ -0,0 +1,4 @@
|
||||
import axios from 'axios';
|
||||
window.axios = axios;
|
||||
|
||||
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
|
||||
141
resources/views/admin/dashboard.blade.php
Executable file
141
resources/views/admin/dashboard.blade.php
Executable file
@@ -0,0 +1,141 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('title', 'Admin Dashboard - NeoNail DB')
|
||||
|
||||
@section('content')
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h1 class="h3 mb-4">
|
||||
<i class="fas fa-tachometer-alt me-2"></i>Admin Dashboard
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Statistiken -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-3 mb-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<i class="fas fa-users fa-2x text-primary mb-2"></i>
|
||||
<h3 class="fw-bold">{{ $totalUsers }}</h3>
|
||||
<p class="text-muted mb-0">Benutzer</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 mb-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<i class="fas fa-palette fa-2x text-success mb-2"></i>
|
||||
<h3 class="fw-bold">{{ $totalNailPolishes }}</h3>
|
||||
<p class="text-muted mb-0">Nagellacke</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 mb-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<i class="fas fa-chart-line fa-2x text-warning mb-2"></i>
|
||||
<h3 class="fw-bold">{{ $recentUsers->count() }}</h3>
|
||||
<p class="text-muted mb-0">Neue Benutzer</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 mb-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<i class="fas fa-plus-circle fa-2x text-info mb-2"></i>
|
||||
<h3 class="fw-bold">{{ $recentNailPolishes->count() }}</h3>
|
||||
<p class="text-muted mb-0">Neue Lacke</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Schnellaktionen -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0"><i class="fas fa-bolt me-2"></i>Schnellaktionen</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-3 mb-2">
|
||||
<a href="{{ route('admin.users.create') }}" class="btn btn-primary w-100">
|
||||
<i class="fas fa-user-plus me-2"></i>Benutzer erstellen
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-md-3 mb-2">
|
||||
<a href="{{ route('nail-polishes.create') }}" class="btn btn-success w-100">
|
||||
<i class="fas fa-plus me-2"></i>Nagellack hinzufügen
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-md-3 mb-2">
|
||||
<a href="{{ route('admin.users.index') }}" class="btn btn-info w-100">
|
||||
<i class="fas fa-users me-2"></i>Benutzer verwalten
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-md-3 mb-2">
|
||||
<a href="{{ route('admin.statistics') }}" class="btn btn-warning w-100">
|
||||
<i class="fas fa-chart-bar me-2"></i>Statistiken
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Letzte Aktivitäten -->
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-4">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0"><i class="fas fa-users me-2"></i>Neueste Benutzer</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@if($recentUsers->count() > 0)
|
||||
<div class="list-group list-group-flush">
|
||||
@foreach($recentUsers as $user)
|
||||
<div class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h6 class="mb-0">{{ $user->name }}</h6>
|
||||
<small class="text-muted">{{ $user->email }}</small>
|
||||
</div>
|
||||
<small class="text-muted">{{ $user->created_at->diffForHumans() }}</small>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@else
|
||||
<p class="text-muted text-center">Keine Benutzer vorhanden</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 mb-4">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0"><i class="fas fa-palette me-2"></i>Neueste Nagellacke</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@if($recentNailPolishes->count() > 0)
|
||||
<div class="list-group list-group-flush">
|
||||
@foreach($recentNailPolishes as $nailPolish)
|
||||
<div class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h6 class="mb-0">{{ $nailPolish->name }}</h6>
|
||||
<small class="text-muted">Nr. {{ $nailPolish->number }}</small>
|
||||
</div>
|
||||
<small class="text-muted">{{ $nailPolish->created_at->diffForHumans() }}</small>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@else
|
||||
<p class="text-muted text-center">Keine Nagellacke vorhanden</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
128
resources/views/admin/statistics.blade.php
Executable file
128
resources/views/admin/statistics.blade.php
Executable file
@@ -0,0 +1,128 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('title', 'Statistiken - NeoNail DB')
|
||||
|
||||
@section('content')
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h1 class="h3 mb-4">
|
||||
<i class="fas fa-chart-bar me-2"></i>Statistiken
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Übersichtsstatistiken -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-3 mb-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<i class="fas fa-users fa-2x text-primary mb-2"></i>
|
||||
<h3 class="fw-bold">{{ $totalUsers }}</h3>
|
||||
<p class="text-muted mb-0">Gesamte Benutzer</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 mb-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<i class="fas fa-palette fa-2x text-success mb-2"></i>
|
||||
<h3 class="fw-bold">{{ $totalNailPolishes }}</h3>
|
||||
<p class="text-muted mb-0">Gesamte Nagellacke</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 mb-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<i class="fas fa-user-check fa-2x text-info mb-2"></i>
|
||||
<h3 class="fw-bold">{{ $usersWithCollections }}</h3>
|
||||
<p class="text-muted mb-0">Benutzer mit Sammlung</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 mb-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<i class="fas fa-chart-line fa-2x text-warning mb-2"></i>
|
||||
<h3 class="fw-bold">{{ round($averageCollectionSize, 1) }}</h3>
|
||||
<p class="text-muted mb-0">Ø Sammlungsgröße</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Top-Benutzer -->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0"><i class="fas fa-trophy me-2"></i>Top 10 Benutzer nach Sammlungsgröße</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@if($topUsers->count() > 0)
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Rang</th>
|
||||
<th>Benutzer</th>
|
||||
<th>E-Mail</th>
|
||||
<th>Sammlung</th>
|
||||
<th>Registriert</th>
|
||||
<th>Aktionen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($topUsers as $index => $user)
|
||||
<tr>
|
||||
<td>
|
||||
@if($index === 0)
|
||||
<i class="fas fa-trophy text-warning"></i>
|
||||
@elseif($index === 1)
|
||||
<i class="fas fa-medal text-secondary"></i>
|
||||
@elseif($index === 2)
|
||||
<i class="fas fa-award text-bronze"></i>
|
||||
@else
|
||||
<span class="badge bg-light text-dark">{{ $index + 1 }}</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
<div class="d-flex align-items-center">
|
||||
<i class="fas fa-user-circle fa-2x text-primary me-2"></i>
|
||||
<div>
|
||||
<strong>{{ $user->name }}</strong>
|
||||
@if($user->email === 'admin@neonail.com')
|
||||
<span class="badge bg-warning ms-2">Admin</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>{{ $user->email }}</td>
|
||||
<td>
|
||||
<span class="badge bg-success fs-6">
|
||||
{{ $user->nail_polishes_count }} Lacke
|
||||
</span>
|
||||
</td>
|
||||
<td>{{ $user->created_at->format('d.m.Y') }}</td>
|
||||
<td>
|
||||
<a href="{{ route('admin.users.collection', $user) }}"
|
||||
class="btn btn-outline-info btn-sm">
|
||||
<i class="fas fa-palette me-1"></i>Sammlung
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@else
|
||||
<div class="text-center py-4">
|
||||
<i class="fas fa-chart-bar fa-3x text-muted mb-3"></i>
|
||||
<p class="text-muted">Noch keine Daten verfügbar</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
99
resources/views/admin/users/create.blade.php
Executable file
99
resources/views/admin/users/create.blade.php
Executable file
@@ -0,0 +1,99 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('title', 'Neuen User erstellen - NeoNail DB')
|
||||
|
||||
@section('content')
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="mb-0">
|
||||
<i class="fas fa-user-plus me-2"></i>Neuen User erstellen
|
||||
</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@if ($errors->any())
|
||||
<div class="alert alert-danger">
|
||||
<ul class="mb-0">
|
||||
@foreach ($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form method="POST" action="https://neonail.vogt.de.com/admin/users">
|
||||
@csrf
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="name" class="form-label">Name *</label>
|
||||
<input type="text" class="form-control @error('name') is-invalid @enderror"
|
||||
id="name" name="name" value="{{ old('name') }}"
|
||||
placeholder="Vollständiger Name" required>
|
||||
@error('name')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="email" class="form-label">Email-Adresse *</label>
|
||||
<input type="email" class="form-control @error('email') is-invalid @enderror"
|
||||
id="email" name="email" value="{{ old('email') }}"
|
||||
placeholder="user@example.com" required>
|
||||
@error('email')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">Passwort *</label>
|
||||
<input type="password" class="form-control @error('password') is-invalid @enderror"
|
||||
id="password" name="password"
|
||||
placeholder="Mindestens 8 Zeichen" required>
|
||||
@error('password')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
<div class="form-text">
|
||||
<i class="fas fa-info-circle me-1"></i>
|
||||
Das Passwort muss mindestens 8 Zeichen lang sein.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="password_confirmation" class="form-label">Passwort bestätigen *</label>
|
||||
<input type="password" class="form-control"
|
||||
id="password_confirmation" name="password_confirmation"
|
||||
placeholder="Passwort wiederholen" required>
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<button type="submit" class="btn btn-success flex-fill">
|
||||
<i class="fas fa-save me-2"></i>User erstellen
|
||||
</button>
|
||||
<a href="{{ route('admin.users.index') }}" class="btn btn-outline-secondary">
|
||||
<i class="fas fa-times me-2"></i>Abbrechen
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Hinweise -->
|
||||
<div class="card mt-4">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">
|
||||
<i class="fas fa-lightbulb me-2"></i>Hinweise
|
||||
</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<ul class="mb-0">
|
||||
<li>Der neue User kann sich sofort mit der Email-Adresse und dem Passwort anmelden</li>
|
||||
<li>Der User kann eigene Lacke erstellen und verwalten</li>
|
||||
<li>Der User kann Lacke aus dem Hauptkatalog zu seiner Sammlung hinzufügen</li>
|
||||
<li>Sie können den User später bearbeiten oder löschen</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
131
resources/views/admin/users/edit.blade.php
Executable file
131
resources/views/admin/users/edit.blade.php
Executable file
@@ -0,0 +1,131 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('title', 'User bearbeiten - NeoNail DB')
|
||||
|
||||
@section('content')
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="mb-0">
|
||||
<i class="fas fa-edit me-2"></i>User bearbeiten: {{ $user->name }}
|
||||
</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@if ($errors->any())
|
||||
<div class="alert alert-danger">
|
||||
<ul class="mb-0">
|
||||
@foreach ($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form method="POST" action="https://neonail.vogt.de.com/admin/users/{{ $user->id }}">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="name" class="form-label">Name *</label>
|
||||
<input type="text" class="form-control @error('name') is-invalid @enderror"
|
||||
id="name" name="name" value="{{ old('name', $user->name) }}"
|
||||
placeholder="Vollständiger Name" required>
|
||||
@error('name')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="email" class="form-label">Email-Adresse *</label>
|
||||
<input type="email" class="form-control @error('email') is-invalid @enderror"
|
||||
id="email" name="email" value="{{ old('email', $user->email) }}"
|
||||
placeholder="user@example.com" required>
|
||||
@error('email')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">Neues Passwort (optional)</label>
|
||||
<input type="password" class="form-control @error('password') is-invalid @enderror"
|
||||
id="password" name="password"
|
||||
placeholder="Leer lassen für kein Änderung">
|
||||
@error('password')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
<div class="form-text">
|
||||
<i class="fas fa-info-circle me-1"></i>
|
||||
Lassen Sie das Feld leer, um das Passwort nicht zu ändern. Mindestens 8 Zeichen.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="password_confirmation" class="form-label">Neues Passwort bestätigen</label>
|
||||
<input type="password" class="form-control"
|
||||
id="password_confirmation" name="password_confirmation"
|
||||
placeholder="Passwort wiederholen">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="is_admin" name="is_admin" value="1"
|
||||
{{ old('is_admin', $user->is_admin) ? 'checked' : '' }}>
|
||||
<label class="form-check-label" for="is_admin">
|
||||
<strong>Admin-Rechte gewähren</strong>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-text">
|
||||
<i class="fas fa-info-circle me-1"></i>
|
||||
Admins haben Zugriff auf alle Admin-Funktionen und können andere User verwalten.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<button type="submit" class="btn btn-primary flex-fill">
|
||||
<i class="fas fa-save me-2"></i>Änderungen speichern
|
||||
</button>
|
||||
<a href="{{ route('admin.users.index') }}" class="btn btn-outline-secondary">
|
||||
<i class="fas fa-times me-2"></i>Abbrechen
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- User-Info -->
|
||||
<div class="card mt-4">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">
|
||||
<i class="fas fa-info-circle me-2"></i>User-Informationen
|
||||
</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<p><strong>User-ID:</strong> {{ $user->id }}</p>
|
||||
<p><strong>Erstellt:</strong> {{ $user->created_at->format('d.m.Y H:i') }}</p>
|
||||
<p><strong>Letzte Änderung:</strong> {{ $user->updated_at->format('d.m.Y H:i') }}</p>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<p><strong>Sammlung:</strong> {{ $user->nailPolishes()->count() }} Lacke</p>
|
||||
<p><strong>Status:</strong>
|
||||
@if($user->email === 'admin@neonail.com' || $user->email === 'neueradmin@neonail.com')
|
||||
<span class="badge bg-primary">Admin</span>
|
||||
@else
|
||||
<span class="badge bg-success">User</span>
|
||||
@endif
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3">
|
||||
<a href="{{ route('admin.users.collection', $user) }}" class="btn btn-outline-info">
|
||||
<i class="fas fa-palette me-2"></i>Sammlung anzeigen
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
137
resources/views/admin/users/index.blade.php
Executable file
137
resources/views/admin/users/index.blade.php
Executable file
@@ -0,0 +1,137 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('title', 'User-Verwaltung - NeoNail DB')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-8">
|
||||
<h2>
|
||||
<i class="fas fa-users me-2"></i>User-Verwaltung
|
||||
</h2>
|
||||
<p class="text-muted">Verwalten Sie alle Benutzer der Anwendung</p>
|
||||
</div>
|
||||
<div class="col-md-4 text-end">
|
||||
<a href="{{ route('admin.users.create') }}" class="btn btn-success">
|
||||
<i class="fas fa-plus me-2"></i>Neuen User erstellen
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Suchleiste -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-6">
|
||||
<form method="GET" action="{{ route('admin.users.index') }}" class="d-flex">
|
||||
<input type="text" name="search" class="form-control me-2"
|
||||
placeholder="Nach Name oder Email suchen..."
|
||||
value="{{ $search }}">
|
||||
<button type="submit" class="btn btn-outline-primary">
|
||||
<i class="fas fa-search"></i>
|
||||
</button>
|
||||
@if($search)
|
||||
<a href="{{ route('admin.users.index') }}" class="btn btn-outline-secondary ms-2">
|
||||
<i class="fas fa-times"></i>
|
||||
</a>
|
||||
@endif
|
||||
</form>
|
||||
</div>
|
||||
<div class="col-md-6 text-end">
|
||||
<span class="text-muted">
|
||||
{{ $users->total() }} User{{ $users->total() != 1 ? 's' : '' }} gefunden
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if($users->count() > 0)
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Name</th>
|
||||
<th>Email</th>
|
||||
<th>Erstellt</th>
|
||||
<th>Sammlung</th>
|
||||
<th>Aktionen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($users as $user)
|
||||
<tr>
|
||||
<td>{{ $user->id }}</td>
|
||||
<td>
|
||||
<strong>{{ $user->name }}</strong>
|
||||
@if($user->isAdmin())
|
||||
<span class="badge bg-primary ms-2">Admin</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>{{ $user->email }}</td>
|
||||
<td>{{ $user->created_at->format('d.m.Y H:i') }}</td>
|
||||
<td>
|
||||
@php $collectionCount = $user->nailPolishes()->count(); @endphp
|
||||
<span class="badge bg-info">{{ $collectionCount }} Lack{{ $collectionCount != 1 ? 'e' : '' }}</span>
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group" role="group">
|
||||
<a href="{{ route('admin.users.collection', $user) }}"
|
||||
class="btn btn-sm btn-outline-info"
|
||||
title="Sammlung anzeigen">
|
||||
<i class="fas fa-palette"></i>
|
||||
</a>
|
||||
<a href="{{ route('admin.users.edit', $user) }}"
|
||||
class="btn btn-sm btn-outline-primary"
|
||||
title="Bearbeiten">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
@if($user->email !== 'admin@neonail.com')
|
||||
<form method="POST" action="https://neonail.vogt.de.com/admin/users/{{ $user->id }}"
|
||||
class="d-inline"
|
||||
onsubmit="return confirm('Möchten Sie diesen User wirklich löschen?')">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button type="submit" class="btn btn-sm btn-outline-danger"
|
||||
title="Löschen">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
@endif
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
@if($users->hasPages())
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<nav aria-label="Seitennavigation">
|
||||
{{ $users->appends(['search' => $search])->links() }}
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@else
|
||||
<div class="text-center py-5">
|
||||
<i class="fas fa-users fa-4x text-muted mb-3"></i>
|
||||
<h4 class="text-muted">Keine User gefunden</h4>
|
||||
<p class="text-muted mb-4">
|
||||
@if($search)
|
||||
Keine User gefunden, die "{{ $search }}" entsprechen.
|
||||
@else
|
||||
Es sind noch keine User in der Anwendung registriert.
|
||||
@endif
|
||||
</p>
|
||||
<a href="{{ route('admin.users.create') }}" class="btn btn-success">
|
||||
<i class="fas fa-plus me-2"></i>Ersten User erstellen
|
||||
</a>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@endsection
|
||||
68
resources/views/auth/login.blade.php
Executable file
68
resources/views/auth/login.blade.php
Executable file
@@ -0,0 +1,68 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('title', 'Anmelden - NeoNail DB')
|
||||
|
||||
@section('content')
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<div class="card">
|
||||
<div class="card-body p-4">
|
||||
<div class="text-center mb-4">
|
||||
<i class="fas fa-palette fa-3x text-primary mb-3"></i>
|
||||
<h2 class="fw-bold">NeoNail DB</h2>
|
||||
<p class="text-muted">Anmelden um Ihre Sammlung zu verwalten</p>
|
||||
</div>
|
||||
|
||||
<form method="POST" action="https://neonail.vogt.de.com/login">
|
||||
@csrf
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="email" class="form-label">E-Mail-Adresse</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text"><i class="fas fa-envelope"></i></span>
|
||||
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror"
|
||||
name="email" value="{{ old('email') }}" required autocomplete="email" autofocus>
|
||||
</div>
|
||||
@error('email')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">Passwort</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text"><i class="fas fa-lock"></i></span>
|
||||
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror"
|
||||
name="password" required autocomplete="current-password">
|
||||
</div>
|
||||
@error('password')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="remember" id="remember" {{ old('remember') ? 'checked' : '' }}>
|
||||
<label class="form-check-label" for="remember">
|
||||
Angemeldet bleiben
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-grid">
|
||||
<button type="submit" class="btn btn-primary btn-lg">
|
||||
<i class="fas fa-sign-in-alt me-2"></i>Anmelden
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
221
resources/views/emails/welcome-user.blade.php
Normal file
221
resources/views/emails/welcome-user.blade.php
Normal file
@@ -0,0 +1,221 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Willkommen bei der NeoNail DB</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
.container {
|
||||
max-width: 600px;
|
||||
margin: 20px auto;
|
||||
background: white;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.header {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
padding: 30px 20px;
|
||||
text-align: center;
|
||||
}
|
||||
.header h1 {
|
||||
margin: 0;
|
||||
font-size: 28px;
|
||||
}
|
||||
.header p {
|
||||
margin: 10px 0 0 0;
|
||||
opacity: 0.9;
|
||||
}
|
||||
.content {
|
||||
padding: 30px 20px;
|
||||
}
|
||||
.welcome-message {
|
||||
font-size: 18px;
|
||||
margin-bottom: 25px;
|
||||
color: #2c3e50;
|
||||
}
|
||||
.login-details {
|
||||
background: #f8f9fa;
|
||||
border: 2px solid #e9ecef;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.login-details h3 {
|
||||
margin: 0 0 15px 0;
|
||||
color: #495057;
|
||||
font-size: 16px;
|
||||
}
|
||||
.login-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin: 10px 0;
|
||||
padding: 8px 0;
|
||||
border-bottom: 1px solid #dee2e6;
|
||||
}
|
||||
.login-row:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
.login-label {
|
||||
font-weight: bold;
|
||||
color: #495057;
|
||||
}
|
||||
.login-value {
|
||||
font-family: 'Courier New', monospace;
|
||||
background: #fff;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #ced4da;
|
||||
}
|
||||
.warning-box {
|
||||
background: #fff3cd;
|
||||
border: 1px solid #ffeaa7;
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.warning-box h4 {
|
||||
margin: 0 0 10px 0;
|
||||
color: #856404;
|
||||
}
|
||||
.warning-box p {
|
||||
margin: 0;
|
||||
color: #856404;
|
||||
}
|
||||
.action-buttons {
|
||||
text-align: center;
|
||||
margin: 30px 0;
|
||||
}
|
||||
.btn {
|
||||
display: inline-block;
|
||||
padding: 12px 24px;
|
||||
margin: 5px;
|
||||
text-decoration: none;
|
||||
border-radius: 25px;
|
||||
font-weight: bold;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.btn-primary {
|
||||
background: linear-gradient(45deg, #667eea, #764ba2);
|
||||
color: white;
|
||||
}
|
||||
.btn-primary:hover {
|
||||
background: linear-gradient(45deg, #5a6fd8, #6a4190);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
.btn-secondary {
|
||||
background: #6c757d;
|
||||
color: white;
|
||||
}
|
||||
.btn-secondary:hover {
|
||||
background: #5a6268;
|
||||
}
|
||||
.features {
|
||||
margin: 25px 0;
|
||||
}
|
||||
.features h3 {
|
||||
color: #495057;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.feature-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
.feature-list li {
|
||||
padding: 8px 0;
|
||||
border-bottom: 1px solid #f1f3f4;
|
||||
}
|
||||
.feature-list li:before {
|
||||
content: "🎨 ";
|
||||
margin-right: 10px;
|
||||
}
|
||||
.footer {
|
||||
background: #f8f9fa;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
color: #6c757d;
|
||||
font-size: 12px;
|
||||
border-top: 1px solid #dee2e6;
|
||||
}
|
||||
.footer p {
|
||||
margin: 5px 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<h1>🎨 NeoNail DB</h1>
|
||||
<p>Willkommen bei Ihrer persönlichen Nagellack-Datenbank</p>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<div class="welcome-message">
|
||||
<h2>Hallo {{ $user->name }}!</h2>
|
||||
<p>Willkommen bei der NeoNail Datenbank! Ihr Account wurde erfolgreich erstellt.</p>
|
||||
</div>
|
||||
|
||||
<div class="login-details">
|
||||
<h3>🔐 Ihre Login-Daten:</h3>
|
||||
<div class="login-row">
|
||||
<span class="login-label">Website:</span>
|
||||
<span class="login-value">https://neonail.vogt.de.com</span>
|
||||
</div>
|
||||
<div class="login-row">
|
||||
<span class="login-label">E-Mail:</span>
|
||||
<span class="login-value">{{ $user->email }}</span>
|
||||
</div>
|
||||
<div class="login-row">
|
||||
<span class="login-label">Passwort:</span>
|
||||
<span class="login-value">{{ $password }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="warning-box">
|
||||
<h4>⚠️ Wichtig: Passwort ändern</h4>
|
||||
<p>Aus Sicherheitsgründen bitten wir Sie, Ihr Passwort nach dem ersten Login zu ändern. Sie können dies in Ihren Account-Einstellungen tun.</p>
|
||||
</div>
|
||||
|
||||
<div class="action-buttons">
|
||||
<a href="https://neonail.vogt.de.com/login" class="btn btn-primary">🚀 Jetzt anmelden</a>
|
||||
<a href="https://neonail.vogt.de.com/my-collection" class="btn btn-secondary">📋 Meine Sammlung</a>
|
||||
</div>
|
||||
|
||||
<div class="features">
|
||||
<h3>🎯 Was Sie mit der NeoNail DB machen können:</h3>
|
||||
<ul class="feature-list">
|
||||
<li>Ihre persönliche Nagellack-Sammlung verwalten</li>
|
||||
<li>Neue Lacke hinzufügen und fotografieren</li>
|
||||
<li>Nach Lacken suchen (Name oder Nummer)</li>
|
||||
<li>Mobile-optimierte Benutzeroberfläche</li>
|
||||
<li>Kollaborativer Katalog mit anderen Usern</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@if($user->isAdmin())
|
||||
<div class="warning-box" style="background: #d1ecf1; border-color: #bee5eb;">
|
||||
<h4 style="color: #0c5460;">👑 Admin-Account</h4>
|
||||
<p style="color: #0c5460;">Sie haben Admin-Rechte und können andere User verwalten sowie den Nagellack-Katalog administrieren.</p>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<p style="margin-top: 30px; color: #6c757d; font-size: 14px;">
|
||||
Bei Fragen oder Problemen wenden Sie sich bitte an den Administrator.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<p>Diese E-Mail wurde automatisch generiert von der NeoNail DB</p>
|
||||
<p>© {{ date('Y') }} NeoNail DB System - Alle Rechte vorbehalten</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
228
resources/views/layouts/app.blade.php
Executable file
228
resources/views/layouts/app.blade.php
Executable file
@@ -0,0 +1,228 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
<title>@yield("title", "NeoNail Datenbank")</title>
|
||||
|
||||
<!-- Bootstrap CSS -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<!-- Font Awesome -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
|
||||
<style>
|
||||
body {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
background: rgba(255, 255, 255, 0.95) !important;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.card {
|
||||
border: none;
|
||||
border-radius: 15px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
||||
backdrop-filter: blur(10px);
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: linear-gradient(45deg, #667eea, #764ba2);
|
||||
border: none;
|
||||
border-radius: 25px;
|
||||
padding: 10px 25px;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background: linear-gradient(45deg, #5a6fd8, #6a4190);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.nail-polish-card {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.nail-polish-card:hover {
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
|
||||
.nail-polish-image {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
object-fit: cover;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.search-box {
|
||||
border-radius: 25px;
|
||||
border: 2px solid #e9ecef;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
.search-box:focus {
|
||||
border-color: #667eea;
|
||||
box-shadow: 0 0 0 0.2rem rgba(102, 126, 234, 0.25);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.container {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.card {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Dropdown-Menüs über alle anderen Elemente legen */
|
||||
.dropdown-menu {
|
||||
z-index: 9999 !important;
|
||||
position: absolute !important;
|
||||
}
|
||||
|
||||
/* Navbar hat höheren z-index */
|
||||
.navbar {
|
||||
z-index: 1000 !important;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Dropdown-Container */
|
||||
.dropdown {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Sicherstellen, dass Dropdowns über Cards angezeigt werden */
|
||||
.navbar-nav .dropdown-menu {
|
||||
z-index: 9999 !important;
|
||||
position: absolute !important;
|
||||
top: 100% !important;
|
||||
left: 0 !important;
|
||||
float: none !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@yield("styles")
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-light">
|
||||
<div class="container">
|
||||
<a class="navbar-brand fw-bold" href="{{ route("user-nail-polishes.index") }}">
|
||||
<i class="fas fa-palette me-2"></i>NeoNail DB
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav me-auto">
|
||||
@auth
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route("user-nail-polishes.index") }}">
|
||||
<i class="fas fa-home me-1"></i>Meine Sammlung
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route("user-nail-polishes.available") }}">
|
||||
<i class="fas fa-plus me-1"></i>Verfügbare Lacke
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route("manufacturers.index") }}">
|
||||
<i class="fas fa-industry me-1"></i>Hersteller
|
||||
</a>
|
||||
</li>
|
||||
@if(auth()->user()->isAdmin())
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">
|
||||
<i class="fas fa-cog me-1"></i>Admin
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="{{ route("admin.dashboard") }}">Dashboard</a></li>
|
||||
<li><a class="dropdown-item" href="{{ route("admin.users.index") }}">Benutzer</a></li>
|
||||
<li><a class="dropdown-item" href="{{ route("nail-polishes.index") }}">Nagellacke</a></li>
|
||||
<li><a class="dropdown-item" href="{{ route("admin.statistics") }}">Statistiken</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
@endif
|
||||
@endauth
|
||||
</ul>
|
||||
|
||||
<ul class="navbar-nav">
|
||||
@guest
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route("login") }}">Anmelden</a>
|
||||
</li>
|
||||
@else
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">
|
||||
<i class="fas fa-user me-1"></i>{{ Auth::user()->name }}
|
||||
@if(auth()->user()->isAdmin())
|
||||
<span class="badge bg-primary ms-1">Admin</span>
|
||||
@endif
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a class="dropdown-item" href="{{ route("logout") }}"
|
||||
onclick="event.preventDefault(); document.getElementById("logout-form").submit();">
|
||||
<i class="fas fa-sign-out-alt me-1"></i>Abmelden
|
||||
</a>
|
||||
<form id="logout-form" action="{{ route("logout") }}" method="POST" class="d-none">
|
||||
@csrf
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
@endguest
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main class="py-4">
|
||||
<div class="container">
|
||||
@if(session("success"))
|
||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
||||
<i class="fas fa-check-circle me-2"></i>{{ session("success") }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if(session("error"))
|
||||
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
||||
<i class="fas fa-exclamation-circle me-2"></i>{{ session("error") }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@yield("content")
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
<!-- HTTPS Form Security -->
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Alle Formulare mit data-https="true" auf HTTPS umleiten
|
||||
const forms = document.querySelectorAll('form[data-https="true"]');
|
||||
forms.forEach(function(form) {
|
||||
form.addEventListener('submit', function(e) {
|
||||
const currentUrl = window.location.href;
|
||||
if (currentUrl.startsWith('http://')) {
|
||||
const httpsUrl = currentUrl.replace('http://', 'https://');
|
||||
form.action = form.action.replace('http://', 'https://');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@yield("scripts")
|
||||
</body>
|
||||
</html>
|
||||
120
resources/views/manufacturers/create.blade.php
Normal file
120
resources/views/manufacturers/create.blade.php
Normal file
@@ -0,0 +1,120 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('title', 'Neuer Hersteller')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card glass-card">
|
||||
<div class="card-header">
|
||||
<h2 class="mb-0">
|
||||
<i class="fas fa-industry text-primary"></i>
|
||||
Neuer Hersteller
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
@if($errors->any())
|
||||
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
||||
<i class="fas fa-exclamation-circle"></i>
|
||||
<strong>Fehler:</strong>
|
||||
<ul class="mb-0 mt-2">
|
||||
@foreach($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form action="https://neonail.vogt.de.com/manufacturers" method="POST" data-https="true">
|
||||
@csrf
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="name" class="form-label">
|
||||
<i class="fas fa-tag"></i> Name *
|
||||
</label>
|
||||
<input type="text"
|
||||
class="form-control @error('name') is-invalid @enderror"
|
||||
id="name"
|
||||
name="name"
|
||||
value="{{ old('name') }}"
|
||||
required
|
||||
placeholder="z.B. NeoNail, OPI, Essie">
|
||||
@error('name')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
<div class="form-text">
|
||||
Der Name des Herstellers. Dieser muss eindeutig sein.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="description" class="form-label">
|
||||
<i class="fas fa-align-left"></i> Beschreibung
|
||||
</label>
|
||||
<textarea class="form-control @error('description') is-invalid @enderror"
|
||||
id="description"
|
||||
name="description"
|
||||
rows="3"
|
||||
placeholder="Kurze Beschreibung des Herstellers...">{{ old('description') }}</textarea>
|
||||
@error('description')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
<div class="form-text">
|
||||
Optionale Beschreibung des Herstellers.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="website" class="form-label">
|
||||
<i class="fas fa-globe"></i> Website
|
||||
</label>
|
||||
<input type="url"
|
||||
class="form-control @error('website') is-invalid @enderror"
|
||||
id="website"
|
||||
name="website"
|
||||
value="{{ old('website') }}"
|
||||
placeholder="https://www.hersteller.com">
|
||||
@error('website')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
<div class="form-text">
|
||||
Die offizielle Website des Herstellers (optional).
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="country" class="form-label">
|
||||
<i class="fas fa-flag"></i> Land
|
||||
</label>
|
||||
<input type="text"
|
||||
class="form-control @error('country') is-invalid @enderror"
|
||||
id="country"
|
||||
name="country"
|
||||
value="{{ old('country') }}"
|
||||
placeholder="z.B. Deutschland, USA, Frankreich">
|
||||
@error('country')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
<div class="form-text">
|
||||
Das Herkunftsland des Herstellers (optional).
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-between">
|
||||
<a href="https://neonail.vogt.de.com/manufacturers" class="btn btn-secondary">
|
||||
<i class="fas fa-arrow-left"></i> Zurück
|
||||
</a>
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="fas fa-save"></i> Hersteller erstellen
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
121
resources/views/manufacturers/edit.blade.php
Normal file
121
resources/views/manufacturers/edit.blade.php
Normal file
@@ -0,0 +1,121 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('title', 'Hersteller bearbeiten')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card glass-card">
|
||||
<div class="card-header">
|
||||
<h2 class="mb-0">
|
||||
<i class="fas fa-edit text-warning"></i>
|
||||
Hersteller bearbeiten: {{ $manufacturer->name }}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
@if($errors->any())
|
||||
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
||||
<i class="fas fa-exclamation-circle"></i>
|
||||
<strong>Fehler:</strong>
|
||||
<ul class="mb-0 mt-2">
|
||||
@foreach($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form action="https://neonail.vogt.de.com/manufacturers/{{ $manufacturer->id }}" method="POST" data-https="true">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="name" class="form-label">
|
||||
<i class="fas fa-tag"></i> Name *
|
||||
</label>
|
||||
<input type="text"
|
||||
class="form-control @error('name') is-invalid @enderror"
|
||||
id="name"
|
||||
name="name"
|
||||
value="{{ old('name', $manufacturer->name) }}"
|
||||
required
|
||||
placeholder="z.B. NeoNail, OPI, Essie">
|
||||
@error('name')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
<div class="form-text">
|
||||
Der Name des Herstellers. Dieser muss eindeutig sein.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="description" class="form-label">
|
||||
<i class="fas fa-align-left"></i> Beschreibung
|
||||
</label>
|
||||
<textarea class="form-control @error('description') is-invalid @enderror"
|
||||
id="description"
|
||||
name="description"
|
||||
rows="3"
|
||||
placeholder="Kurze Beschreibung des Herstellers...">{{ old('description', $manufacturer->description) }}</textarea>
|
||||
@error('description')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
<div class="form-text">
|
||||
Optionale Beschreibung des Herstellers.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="website" class="form-label">
|
||||
<i class="fas fa-globe"></i> Website
|
||||
</label>
|
||||
<input type="url"
|
||||
class="form-control @error('website') is-invalid @enderror"
|
||||
id="website"
|
||||
name="website"
|
||||
value="{{ old('website', $manufacturer->website) }}"
|
||||
placeholder="https://www.hersteller.com">
|
||||
@error('website')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
<div class="form-text">
|
||||
Die offizielle Website des Herstellers (optional).
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="country" class="form-label">
|
||||
<i class="fas fa-flag"></i> Land
|
||||
</label>
|
||||
<input type="text"
|
||||
class="form-control @error('country') is-invalid @enderror"
|
||||
id="country"
|
||||
name="country"
|
||||
value="{{ old('country', $manufacturer->country) }}"
|
||||
placeholder="z.B. Deutschland, USA, Frankreich">
|
||||
@error('country')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
<div class="form-text">
|
||||
Das Herkunftsland des Herstellers (optional).
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-between">
|
||||
<a href="https://neonail.vogt.de.com/manufacturers" class="btn btn-secondary">
|
||||
<i class="fas fa-arrow-left"></i> Zurück
|
||||
</a>
|
||||
<button type="submit" class="btn btn-warning">
|
||||
<i class="fas fa-save"></i> Änderungen speichern
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
163
resources/views/manufacturers/index.blade.php
Normal file
163
resources/views/manufacturers/index.blade.php
Normal file
@@ -0,0 +1,163 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('title', 'Hersteller')
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card glass-card">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h2 class="mb-0">
|
||||
<i class="fas fa-industry text-primary"></i>
|
||||
Hersteller
|
||||
</h2>
|
||||
<a href="https://neonail.vogt.de.com/manufacturers/create" class="btn btn-primary">
|
||||
<i class="fas fa-plus"></i> Neuer Hersteller
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<!-- Suchformular -->
|
||||
<form method="GET" action="https://neonail.vogt.de.com/manufacturers" class="mb-4" data-https="true">
|
||||
<div class="input-group">
|
||||
<input type="text" name="search" class="form-control"
|
||||
placeholder="Hersteller suchen..."
|
||||
value="{{ $search }}">
|
||||
<button class="btn btn-outline-secondary" type="submit">
|
||||
<i class="fas fa-search"></i>
|
||||
</button>
|
||||
@if($search)
|
||||
<a href="https://neonail.vogt.de.com/manufacturers" class="btn btn-outline-danger">
|
||||
<i class="fas fa-times"></i>
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@if(session('success'))
|
||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
||||
<i class="fas fa-check-circle"></i>
|
||||
{{ session('success') }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if(session('error'))
|
||||
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
||||
<i class="fas fa-exclamation-circle"></i>
|
||||
{{ session('error') }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if($manufacturers->count() > 0)
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Land</th>
|
||||
<th>Website</th>
|
||||
<th>Nagellacke</th>
|
||||
<th>Erstellt</th>
|
||||
<th>Aktionen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($manufacturers as $manufacturer)
|
||||
<tr>
|
||||
<td>
|
||||
<strong>{{ $manufacturer->name }}</strong>
|
||||
@if($manufacturer->description)
|
||||
<br>
|
||||
<small class="text-muted">{{ Str::limit($manufacturer->description, 50) }}</small>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if($manufacturer->country)
|
||||
<span class="badge bg-info">{{ $manufacturer->country }}</span>
|
||||
@else
|
||||
<span class="text-muted">-</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if($manufacturer->website)
|
||||
<a href="{{ $manufacturer->website }}" target="_blank" class="text-decoration-none">
|
||||
<i class="fas fa-external-link-alt"></i>
|
||||
Website
|
||||
</a>
|
||||
@else
|
||||
<span class="text-muted">-</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge bg-primary">{{ $manufacturer->nail_polishes_count }}</span>
|
||||
</td>
|
||||
<td>
|
||||
<small class="text-muted">
|
||||
{{ $manufacturer->created_at->format('d.m.Y') }}
|
||||
</small>
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group" role="group">
|
||||
<a href="https://neonail.vogt.de.com/manufacturers/{{ $manufacturer->id }}"
|
||||
class="btn btn-sm btn-outline-info"
|
||||
title="Anzeigen">
|
||||
<i class="fas fa-eye"></i>
|
||||
</a>
|
||||
<a href="https://neonail.vogt.de.com/manufacturers/{{ $manufacturer->id }}/edit"
|
||||
class="btn btn-sm btn-outline-warning"
|
||||
title="Bearbeiten">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
@if(!$manufacturer->hasNailPolishes())
|
||||
<form action="https://neonail.vogt.de.com/manufacturers/{{ $manufacturer->id }}"
|
||||
method="POST"
|
||||
class="d-inline"
|
||||
data-https="true"
|
||||
onsubmit="return confirm('Sind Sie sicher, dass Sie diesen Hersteller löschen möchten?')">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button type="submit"
|
||||
class="btn btn-sm btn-outline-danger"
|
||||
title="Löschen">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
@endif
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
<div class="d-flex justify-content-center">
|
||||
{{ $manufacturers->appends(['search' => $search])->links() }}
|
||||
</div>
|
||||
@else
|
||||
<div class="text-center py-5">
|
||||
<i class="fas fa-industry fa-3x text-muted mb-3"></i>
|
||||
<h4 class="text-muted">Keine Hersteller gefunden</h4>
|
||||
@if($search)
|
||||
<p class="text-muted">Keine Hersteller für "{{ $search }}" gefunden.</p>
|
||||
<a href="https://neonail.vogt.de.com/manufacturers" class="btn btn-primary">
|
||||
Alle Hersteller anzeigen
|
||||
</a>
|
||||
@else
|
||||
<p class="text-muted">Erstellen Sie den ersten Hersteller.</p>
|
||||
<a href="https://neonail.vogt.de.com/manufacturers/create" class="btn btn-primary">
|
||||
<i class="fas fa-plus"></i> Ersten Hersteller erstellen
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
153
resources/views/manufacturers/show.blade.php
Normal file
153
resources/views/manufacturers/show.blade.php
Normal file
@@ -0,0 +1,153 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('title', $manufacturer->name)
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="card glass-card">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h2 class="mb-0">
|
||||
<i class="fas fa-industry text-primary"></i>
|
||||
{{ $manufacturer->name }}
|
||||
</h2>
|
||||
<div class="btn-group" role="group">
|
||||
<a href="https://neonail.vogt.de.com/manufacturers/{{ $manufacturer->id }}/edit"
|
||||
class="btn btn-warning btn-sm">
|
||||
<i class="fas fa-edit"></i> Bearbeiten
|
||||
</a>
|
||||
<a href="https://neonail.vogt.de.com/manufacturers"
|
||||
class="btn btn-secondary btn-sm">
|
||||
<i class="fas fa-arrow-left"></i> Zurück
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h5><i class="fas fa-info-circle text-info"></i> Informationen</h5>
|
||||
<dl class="row">
|
||||
<dt class="col-sm-4">Name:</dt>
|
||||
<dd class="col-sm-8">{{ $manufacturer->name }}</dd>
|
||||
|
||||
@if($manufacturer->country)
|
||||
<dt class="col-sm-4">Land:</dt>
|
||||
<dd class="col-sm-8">
|
||||
<span class="badge bg-info">{{ $manufacturer->country }}</span>
|
||||
</dd>
|
||||
@endif
|
||||
|
||||
@if($manufacturer->website)
|
||||
<dt class="col-sm-4">Website:</dt>
|
||||
<dd class="col-sm-8">
|
||||
<a href="{{ $manufacturer->website }}" target="_blank" class="text-decoration-none">
|
||||
<i class="fas fa-external-link-alt"></i>
|
||||
{{ $manufacturer->website }}
|
||||
</a>
|
||||
</dd>
|
||||
@endif
|
||||
|
||||
<dt class="col-sm-4">Nagellacke:</dt>
|
||||
<dd class="col-sm-8">
|
||||
<span class="badge bg-primary">{{ $manufacturer->nailPolishes->count() }}</span>
|
||||
</dd>
|
||||
|
||||
<dt class="col-sm-4">Erstellt:</dt>
|
||||
<dd class="col-sm-8">{{ $manufacturer->created_at->format('d.m.Y H:i') }}</dd>
|
||||
|
||||
<dt class="col-sm-4">Aktualisiert:</dt>
|
||||
<dd class="col-sm-8">{{ $manufacturer->updated_at->format('d.m.Y H:i') }}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
@if($manufacturer->description)
|
||||
<h5><i class="fas fa-align-left text-success"></i> Beschreibung</h5>
|
||||
<p class="text-muted">{{ $manufacturer->description }}</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="card glass-card">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">
|
||||
<i class="fas fa-chart-bar text-primary"></i>
|
||||
Statistiken
|
||||
</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="text-center">
|
||||
<div class="display-4 text-primary">{{ $manufacturer->nailPolishes->count() }}</div>
|
||||
<p class="text-muted">Nagellacke</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if($manufacturer->nailPolishes->count() > 0)
|
||||
<div class="row mt-4">
|
||||
<div class="col-12">
|
||||
<div class="card glass-card">
|
||||
<div class="card-header">
|
||||
<h3 class="mb-0">
|
||||
<i class="fas fa-palette text-primary"></i>
|
||||
Nagellacke von {{ $manufacturer->name }}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
@foreach($manufacturer->nailPolishes as $nailPolish)
|
||||
<div class="col-md-3 col-sm-6 mb-3">
|
||||
<div class="card h-100">
|
||||
@if($nailPolish->image_path)
|
||||
<img src="{{ asset('storage/' . $nailPolish->image_path) }}"
|
||||
class="card-img-top"
|
||||
alt="{{ $nailPolish->name }}"
|
||||
style="height: 200px; object-fit: cover;">
|
||||
@else
|
||||
<div class="card-img-top bg-light d-flex align-items-center justify-content-center"
|
||||
style="height: 200px;">
|
||||
<i class="fas fa-image fa-3x text-muted"></i>
|
||||
</div>
|
||||
@endif
|
||||
<div class="card-body">
|
||||
<h6 class="card-title">{{ $nailPolish->name }}</h6>
|
||||
<p class="card-text text-muted">{{ $nailPolish->number }}</p>
|
||||
<a href="https://neonail.vogt.de.com/nail-polishes/{{ $nailPolish->id }}"
|
||||
class="btn btn-sm btn-outline-primary">
|
||||
<i class="fas fa-eye"></i> Anzeigen
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<div class="row mt-4">
|
||||
<div class="col-12">
|
||||
<div class="card glass-card">
|
||||
<div class="card-body text-center py-5">
|
||||
<i class="fas fa-palette fa-3x text-muted mb-3"></i>
|
||||
<h4 class="text-muted">Keine Nagellacke vorhanden</h4>
|
||||
<p class="text-muted">Für diesen Hersteller sind noch keine Nagellacke eingetragen.</p>
|
||||
<a href="https://neonail.vogt.de.com/nail-polishes/create" class="btn btn-primary">
|
||||
<i class="fas fa-plus"></i> Ersten Nagellack hinzufügen
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@endsection
|
||||
75
resources/views/nail-polishes/create.blade.php
Executable file
75
resources/views/nail-polishes/create.blade.php
Executable file
@@ -0,0 +1,75 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('title', 'Neuen Nagellack hinzufügen - NeoNail DB')
|
||||
|
||||
@section('content')
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8 col-lg-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="mb-0">
|
||||
<i class="fas fa-plus me-2"></i>Neuen Nagellack hinzufügen
|
||||
</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ route('nail-polishes.store') }}" enctype="multipart/form-data">
|
||||
@csrf
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="name" class="form-label">Name des Nagellacks *</label>
|
||||
<input type="text" class="form-control @error('name') is-invalid @enderror"
|
||||
id="name" name="name" value="{{ old('name') }}" required>
|
||||
@error('name')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="number" class="form-label">Nummer *</label>
|
||||
<input type="text" class="form-control @error('number') is-invalid @enderror"
|
||||
id="number" name="number" value="{{ old('number') }}" required>
|
||||
@error('number')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="image" class="form-label">Bild (optional)</label>
|
||||
<input type="file" class="form-control @error('image') is-invalid @enderror"
|
||||
id="image" name="image" accept="image/*" capture="camera">
|
||||
<div class="form-text">
|
||||
<i class="fas fa-camera me-1"></i>
|
||||
Sie können ein Bild von Ihrer Kamera aufnehmen oder eine Datei auswählen.
|
||||
</div>
|
||||
@error('image')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<button type="submit" class="btn btn-primary flex-fill">
|
||||
<i class="fas fa-save me-2"></i>Speichern
|
||||
</button>
|
||||
<a href="{{ route('nail-polishes.index') }}" class="btn btn-outline-secondary">
|
||||
<i class="fas fa-times me-2"></i>Abbrechen
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@section('scripts')
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const imageInput = document.getElementById('image');
|
||||
|
||||
// Kamera-Button für mobile Geräte
|
||||
if ('mediaDevices' in navigator && 'getUserMedia' in navigator.mediaDevices) {
|
||||
imageInput.setAttribute('capture', 'camera');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
70
resources/views/nail-polishes/edit.blade.php
Executable file
70
resources/views/nail-polishes/edit.blade.php
Executable file
@@ -0,0 +1,70 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('title', 'Nagellack bearbeiten - NeoNail DB')
|
||||
|
||||
@section('content')
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8 col-lg-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="mb-0">
|
||||
<i class="fas fa-edit me-2"></i>Nagellack bearbeiten
|
||||
</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ route('nail-polishes.update', $nailPolish) }}" enctype="multipart/form-data">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="name" class="form-label">Name des Nagellacks *</label>
|
||||
<input type="text" class="form-control @error('name') is-invalid @enderror"
|
||||
id="name" name="name" value="{{ old('name', $nailPolish->name) }}" required>
|
||||
@error('name')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="number" class="form-label">Nummer *</label>
|
||||
<input type="text" class="form-control @error('number') is-invalid @enderror"
|
||||
id="number" name="number" value="{{ old('number', $nailPolish->number) }}" required>
|
||||
@error('number')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="image" class="form-label">Bild (optional)</label>
|
||||
@if($nailPolish->image_path)
|
||||
<div class="mb-2">
|
||||
<img src="{{ Storage::url($nailPolish->image_path) }}"
|
||||
alt="{{ $nailPolish->name }}" class="img-thumbnail" style="max-width: 200px;">
|
||||
<p class="text-muted small">Aktuelles Bild</p>
|
||||
</div>
|
||||
@endif
|
||||
<input type="file" class="form-control @error('image') is-invalid @enderror"
|
||||
id="image" name="image" accept="image/*" capture="camera">
|
||||
<div class="form-text">
|
||||
<i class="fas fa-camera me-1"></i>
|
||||
Sie können ein neues Bild von Ihrer Kamera aufnehmen oder eine Datei auswählen.
|
||||
</div>
|
||||
@error('image')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<button type="submit" class="btn btn-primary flex-fill">
|
||||
<i class="fas fa-save me-2"></i>Aktualisieren
|
||||
</button>
|
||||
<a href="{{ route('nail-polishes.index') }}" class="btn btn-outline-secondary">
|
||||
<i class="fas fa-times me-2"></i>Abbrechen
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
121
resources/views/nail-polishes/index.blade.php
Executable file
121
resources/views/nail-polishes/index.blade.php
Executable file
@@ -0,0 +1,121 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('title', 'Nagellack-Verwaltung - NeoNail DB')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-8">
|
||||
<h2>
|
||||
<i class="fas fa-palette me-2"></i>NeoNail-Lacke verwalten
|
||||
</h2>
|
||||
<p class="text-muted">Verwalten Sie alle verfügbaren NeoNail-Lacke im System</p>
|
||||
</div>
|
||||
<div class="col-md-4 text-end">
|
||||
<a href="{{ route('nail-polishes.create') }}" class="btn btn-success">
|
||||
<i class="fas fa-plus me-2"></i>Neuen Lack erstellen
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if(session('success'))
|
||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
||||
<i class="fas fa-check-circle me-2"></i>{{ session('success') }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if(session('error'))
|
||||
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
||||
<i class="fas fa-exclamation-triangle me-2"></i>{{ session('error') }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if($nailPolishes->count() > 0)
|
||||
<div class="row">
|
||||
@foreach($nailPolishes as $nailPolish)
|
||||
<div class="col-md-3 col-sm-6 mb-4">
|
||||
<div class="card h-100 nail-polish-card">
|
||||
@if($nailPolish->image_path)
|
||||
<img src="{{ Storage::url($nailPolish->image_path) }}"
|
||||
class="card-img-top nail-polish-image"
|
||||
alt="{{ $nailPolish->name }}"
|
||||
loading="lazy">
|
||||
@else
|
||||
<div class="card-img-top nail-polish-placeholder d-flex align-items-center justify-content-center">
|
||||
<i class="fas fa-palette fa-3x text-muted"></i>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card-body d-flex flex-column">
|
||||
<h6 class="card-title mb-1">{{ $nailPolish->name }}</h6>
|
||||
<p class="card-text text-muted mb-2">Nr. {{ $nailPolish->number }}</p>
|
||||
@if($nailPolish->manufacturer)
|
||||
<p class="card-text text-muted mb-2">
|
||||
<small><i class="fas fa-industry"></i> {{ $nailPolish->manufacturer->name }}</small>
|
||||
</p>
|
||||
@endif
|
||||
|
||||
<!-- Zeige Anzahl der User, die diesen Lack haben -->
|
||||
@php
|
||||
$userCount = $nailPolish->users()->count();
|
||||
@endphp
|
||||
<p class="card-text small text-info mb-2">
|
||||
<i class="fas fa-users me-1"></i>
|
||||
{{ $userCount }} User{{ $userCount != 1 ? 's' : '' }} haben diesen Lack
|
||||
</p>
|
||||
|
||||
<div class="mt-auto">
|
||||
<div class="d-flex gap-1">
|
||||
<a href="{{ route('nail-polishes.showUsers', $nailPolish) }}"
|
||||
class="btn btn-outline-info btn-sm flex-fill">
|
||||
<i class="fas fa-users me-1"></i>User anzeigen
|
||||
</a>
|
||||
<a href="{{ route('nail-polishes.edit', $nailPolish) }}"
|
||||
class="btn btn-outline-primary btn-sm flex-fill">
|
||||
<i class="fas fa-edit me-1"></i>Bearbeiten
|
||||
</a>
|
||||
<form method="POST" action="https://neonail.vogt.de.com/nail-polishes/{{ $nailPolish->id }}"
|
||||
class="d-inline flex-fill"
|
||||
onsubmit="return confirm('Möchten Sie diesen Lack wirklich löschen?')">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button type="submit" class="btn btn-outline-danger btn-sm w-100"
|
||||
{{ $userCount > 0 ? 'disabled' : '' }}
|
||||
title="{{ $userCount > 0 ? 'Lack wird noch von ' . $userCount . ' User(s) verwendet' : '' }}">
|
||||
<i class="fas fa-trash me-1"></i>Löschen
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
@if($nailPolishes->hasPages())
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<nav aria-label="Seitennavigation">
|
||||
{{ $nailPolishes->links() }}
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@else
|
||||
<div class="text-center py-5">
|
||||
<i class="fas fa-palette fa-4x text-muted mb-3"></i>
|
||||
<h4 class="text-muted">Noch keine Lacke vorhanden</h4>
|
||||
<p class="text-muted mb-4">
|
||||
Erstellen Sie den ersten NeoNail-Lack im System!
|
||||
</p>
|
||||
<a href="{{ route('nail-polishes.create') }}" class="btn btn-success">
|
||||
<i class="fas fa-plus me-2"></i>Ersten Lack erstellen
|
||||
</a>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@endsection
|
||||
97
resources/views/nail-polishes/show-users.blade.php
Executable file
97
resources/views/nail-polishes/show-users.blade.php
Executable file
@@ -0,0 +1,97 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('title', 'User mit diesem Lack - NeoNail DB')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-8">
|
||||
<h2>
|
||||
<i class="fas fa-users me-2"></i>User mit "{{ $nailPolish->name }}"
|
||||
</h2>
|
||||
<p class="text-muted">Benutzer, die diesen Lack in ihrer Sammlung haben</p>
|
||||
</div>
|
||||
<div class="col-md-4 text-end">
|
||||
<a href="{{ route('nail-polishes.index') }}" class="btn btn-primary">
|
||||
<i class="fas fa-arrow-left me-2"></i>Zurück zur Übersicht
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Lack-Info -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
@if($nailPolish->image_path)
|
||||
<img src="{{ Storage::url($nailPolish->image_path) }}"
|
||||
class="img-fluid rounded"
|
||||
alt="{{ $nailPolish->name }}">
|
||||
@else
|
||||
<div class="bg-light rounded d-flex align-items-center justify-content-center" style="height: 100px;">
|
||||
<i class="fas fa-palette fa-2x text-muted"></i>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-md-10">
|
||||
<h5>{{ $nailPolish->name }}</h5>
|
||||
<p class="text-muted mb-2">Nummer: {{ $nailPolish->number }}</p>
|
||||
<p class="mb-0">
|
||||
<span class="badge bg-info">{{ $users->total() }} User{{ $users->total() != 1 ? 's' : '' }}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if($users->count() > 0)
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">Benutzer mit diesem Lack</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>E-Mail</th>
|
||||
<th>Registriert am</th>
|
||||
<th>Aktionen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($users as $user)
|
||||
<tr>
|
||||
<td>{{ $user->name }}</td>
|
||||
<td>{{ $user->email }}</td>
|
||||
<td>{{ $user->created_at->format('d.m.Y H:i') }}</td>
|
||||
<td>
|
||||
<a href="{{ route('admin.users.collection', $user) }}"
|
||||
class="btn btn-outline-primary btn-sm">
|
||||
<i class="fas fa-eye me-1"></i>Sammlung anzeigen
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
@if($users->hasPages())
|
||||
<div class="d-flex justify-content-center mt-3">
|
||||
{{ $users->links() }}
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<div class="text-center py-5">
|
||||
<i class="fas fa-users fa-4x text-muted mb-3"></i>
|
||||
<h4 class="text-muted">Keine User gefunden</h4>
|
||||
<p class="text-muted">Dieser Lack wird von keinem Benutzer verwendet.</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@endsection
|
||||
124
resources/views/user-nail-polishes/available.blade.php
Executable file
124
resources/views/user-nail-polishes/available.blade.php
Executable file
@@ -0,0 +1,124 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('title', 'Verfügbare Lacke - NeoNail DB')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-8">
|
||||
<h2>
|
||||
<i class="fas fa-search me-2"></i>Verfügbare NeoNail-Lacke
|
||||
</h2>
|
||||
<p class="text-muted">Lacke, die Sie noch nicht in Ihrer Sammlung haben</p>
|
||||
</div>
|
||||
<div class="col-md-4 text-end">
|
||||
<div class="d-flex gap-2 justify-content-end">
|
||||
<a href="{{ route('user-nail-polishes.create') }}" class="btn btn-success">
|
||||
<i class="fas fa-plus me-2"></i>Neuen Lack hinzufügen
|
||||
</a>
|
||||
<a href="{{ route('user-nail-polishes.index') }}" class="btn btn-primary">
|
||||
<i class="fas fa-palette me-2"></i>Meine Sammlung
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Info-Box -->
|
||||
<div class="alert alert-info mb-4">
|
||||
<i class="fas fa-info-circle me-2"></i>
|
||||
<strong>Hinweis:</strong> Diese Lacke sind Teil des gemeinsamen Hauptkatalogs und können nicht gelöscht werden.
|
||||
Sie können sie nur zu Ihrer persönlichen Sammlung hinzufügen oder entfernen.
|
||||
</div>
|
||||
|
||||
<!-- Suchleiste -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-6">
|
||||
<form method="GET" action="{{ route('user-nail-polishes.available') }}" class="d-flex">
|
||||
<input type="text" name="search" class="form-control me-2"
|
||||
placeholder="Nach Name oder Nummer suchen..."
|
||||
value="{{ $search }}">
|
||||
<button type="submit" class="btn btn-outline-primary">
|
||||
<i class="fas fa-search"></i>
|
||||
</button>
|
||||
@if($search)
|
||||
<a href="{{ route('user-nail-polishes.available') }}" class="btn btn-outline-secondary ms-2">
|
||||
<i class="fas fa-times"></i>
|
||||
</a>
|
||||
@endif
|
||||
</form>
|
||||
</div>
|
||||
<div class="col-md-6 text-end">
|
||||
<span class="text-muted">
|
||||
{{ $nailPolishes->total() }} verfügbare Lack{{ $nailPolishes->total() != 1 ? 'e' : '' }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if($nailPolishes->count() > 0)
|
||||
<div class="row">
|
||||
@foreach($nailPolishes as $nailPolish)
|
||||
<div class="col-md-3 col-sm-6 mb-4">
|
||||
<div class="card h-100 nail-polish-card">
|
||||
@if($nailPolish->image_path)
|
||||
<img src="{{ Storage::url($nailPolish->image_path) }}"
|
||||
class="card-img-top nail-polish-image"
|
||||
alt="{{ $nailPolish->name }}"
|
||||
loading="lazy">
|
||||
@else
|
||||
<div class="card-img-top nail-polish-placeholder d-flex align-items-center justify-content-center">
|
||||
<i class="fas fa-palette fa-3x text-muted"></i>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card-body d-flex flex-column">
|
||||
<h6 class="card-title mb-1">{{ $nailPolish->name }}</h6>
|
||||
<p class="card-text text-muted mb-2">Nr. {{ $nailPolish->number }}</p>
|
||||
|
||||
<div class="mt-auto">
|
||||
<form method="POST" action="{{ route('user-nail-polishes.add', $nailPolish) }}"
|
||||
class="d-inline">
|
||||
@csrf
|
||||
<button type="submit" class="btn btn-success btn-sm w-100">
|
||||
<i class="fas fa-plus me-2"></i>Zur Sammlung hinzufügen
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
@if($nailPolishes->hasPages())
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<nav aria-label="Seitennavigation">
|
||||
{{ $nailPolishes->appends(['search' => $search])->links() }}
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@else
|
||||
<div class="text-center py-5">
|
||||
<i class="fas fa-check-circle fa-4x text-success mb-3"></i>
|
||||
<h4 class="text-success">Glückwunsch!</h4>
|
||||
<p class="text-muted mb-4">
|
||||
@if($search)
|
||||
Keine verfügbaren Lacke gefunden, die "{{ $search }}" entsprechen.
|
||||
@else
|
||||
Sie haben bereits alle verfügbaren NeoNail-Lacke in Ihrer Sammlung!
|
||||
@endif
|
||||
</p>
|
||||
<div class="d-flex gap-2 justify-content-center">
|
||||
<a href="{{ route('user-nail-polishes.create') }}" class="btn btn-success">
|
||||
<i class="fas fa-plus me-2"></i>Neuen Lack hinzufügen
|
||||
</a>
|
||||
<a href="{{ route('user-nail-polishes.index') }}" class="btn btn-primary">
|
||||
<i class="fas fa-palette me-2"></i>Meine Sammlung anzeigen
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@endsection
|
||||
175
resources/views/user-nail-polishes/create.blade.php
Executable file
175
resources/views/user-nail-polishes/create.blade.php
Executable file
@@ -0,0 +1,175 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('title', 'Neuen Lack hinzufügen - NeoNail DB')
|
||||
|
||||
@section('content')
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="mb-0">
|
||||
<i class="fas fa-plus me-2"></i>Neuen NeoNail-Lack hinzufügen
|
||||
</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="alert alert-info">
|
||||
<i class="fas fa-info-circle me-2"></i>
|
||||
<strong>Wichtig:</strong> Der neue Lack wird automatisch zum Hauptkatalog hinzugefügt und steht dann allen Benutzern zur Verfügung.
|
||||
Er wird auch automatisch zu Ihrer Sammlung hinzugefügt.
|
||||
</div>
|
||||
|
||||
@if ($errors->any())
|
||||
<div class="alert alert-danger">
|
||||
<ul class="mb-0">
|
||||
@foreach ($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form method="POST" action="https://neonail.vogt.de.com/create-nail-polish" enctype="multipart/form-data">
|
||||
@csrf
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label for="name" class="form-label">Name des Lackes *</label>
|
||||
<input type="text" class="form-control @error('name') is-invalid @enderror"
|
||||
id="name" name="name" value="{{ old('name') }}"
|
||||
placeholder="z.B. Classic Red" required>
|
||||
@error('name')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label for="number" class="form-label">Nummer des Lackes *</label>
|
||||
<input type="text" class="form-control @error('number') is-invalid @enderror"
|
||||
id="number" name="number" value="{{ old('number') }}"
|
||||
placeholder="z.B. 001" required>
|
||||
@error('number')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label for="manufacturer_id" class="form-label">Hersteller *</label>
|
||||
<select class="form-control @error('manufacturer_id') is-invalid @enderror"
|
||||
id="manufacturer_id" name="manufacturer_id" required>
|
||||
<option value="">Hersteller auswählen...</option>
|
||||
@foreach(\App\Models\Manufacturer::orderBy('name')->get() as $manufacturer)
|
||||
<option value="{{ $manufacturer->id }}" {{ old('manufacturer_id') == $manufacturer->id ? 'selected' : '' }}>
|
||||
{{ $manufacturer->name }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@error('manufacturer_id')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
<div class="form-text">
|
||||
<a href="https://neonail.vogt.de.com/manufacturers/create" target="_blank" class="text-decoration-none">
|
||||
<i class="fas fa-plus"></i> Neuen Hersteller erstellen
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label for="new_manufacturer" class="form-label">Oder neuen Hersteller erstellen</label>
|
||||
<input type="text" class="form-control"
|
||||
id="new_manufacturer" name="new_manufacturer"
|
||||
placeholder="Name des neuen Herstellers">
|
||||
<div class="form-text">
|
||||
Falls der Hersteller noch nicht existiert, können Sie ihn hier erstellen.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="image" class="form-label">Bild des Lackes (optional)</label>
|
||||
<input type="file" class="form-control @error('image') is-invalid @enderror"
|
||||
id="image" name="image" accept="image/*">
|
||||
<div class="form-text">
|
||||
<i class="fas fa-camera me-1"></i>
|
||||
Sie können ein Bild mit der Handykamera aufnehmen oder eine Datei auswählen.
|
||||
Maximale Größe: 10MB. Das Bild wird automatisch optimiert.
|
||||
</div>
|
||||
@error('image')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<button type="submit" class="btn btn-primary flex-fill">
|
||||
<i class="fas fa-save me-2"></i>Lack erstellen & zur Sammlung hinzufügen
|
||||
</button>
|
||||
<a href="{{ route('user-nail-polishes.index') }}" class="btn btn-outline-secondary">
|
||||
<i class="fas fa-times me-2"></i>Abbrechen
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Hinweise -->
|
||||
<div class="card mt-4">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">
|
||||
<i class="fas fa-lightbulb me-2"></i>Hinweise
|
||||
</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<ul class="mb-0">
|
||||
<li>Der Lack wird automatisch zum Hauptkatalog hinzugefügt</li>
|
||||
<li>Andere Benutzer können den Lack dann zu ihrer Sammlung hinzufügen</li>
|
||||
<li>Das Bild wird automatisch auf 400x400 Pixel optimiert</li>
|
||||
<li>Sie können den Lack später in Ihren Einstellungen bearbeiten</li>
|
||||
<li>Neue Hersteller werden automatisch erstellt und stehen allen zur Verfügung</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const manufacturerSelect = document.getElementById('manufacturer_id');
|
||||
const newManufacturerInput = document.getElementById('new_manufacturer');
|
||||
|
||||
// Wenn ein Hersteller ausgewählt wird, leere das neue Hersteller Feld
|
||||
manufacturerSelect.addEventListener('change', function() {
|
||||
if (this.value) {
|
||||
newManufacturerInput.value = '';
|
||||
newManufacturerInput.disabled = true;
|
||||
} else {
|
||||
newManufacturerInput.disabled = false;
|
||||
}
|
||||
});
|
||||
|
||||
// Wenn ein neuer Hersteller eingegeben wird, leere die Auswahl
|
||||
newManufacturerInput.addEventListener('input', function() {
|
||||
if (this.value.trim()) {
|
||||
manufacturerSelect.value = '';
|
||||
manufacturerSelect.disabled = true;
|
||||
} else {
|
||||
manufacturerSelect.disabled = false;
|
||||
}
|
||||
});
|
||||
|
||||
// Initial state
|
||||
if (newManufacturerInput.value.trim()) {
|
||||
manufacturerSelect.disabled = true;
|
||||
}
|
||||
if (manufacturerSelect.value) {
|
||||
newManufacturerInput.disabled = true;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
123
resources/views/user-nail-polishes/index.blade.php
Executable file
123
resources/views/user-nail-polishes/index.blade.php
Executable file
@@ -0,0 +1,123 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('title', 'Meine Sammlung - NeoNail DB')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-8">
|
||||
<h2>
|
||||
<i class="fas fa-palette me-2"></i>Meine NeoNail-Sammlung
|
||||
</h2>
|
||||
<p class="text-muted">Verwalten Sie Ihre persönliche Nagellack-Sammlung</p>
|
||||
</div>
|
||||
<div class="col-md-4 text-end">
|
||||
<div class="d-flex gap-2 justify-content-end">
|
||||
<a href="{{ route('user-nail-polishes.create') }}" class="btn btn-success">
|
||||
<i class="fas fa-plus me-2"></i>Neuen Lack hinzufügen
|
||||
</a>
|
||||
<a href="{{ route('user-nail-polishes.available') }}" class="btn btn-primary">
|
||||
<i class="fas fa-search me-2"></i>Verfügbare Lacke
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Suchleiste -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-6">
|
||||
<form method="GET" action="{{ route('user-nail-polishes.index') }}" class="d-flex">
|
||||
<input type="text" name="search" class="form-control me-2"
|
||||
placeholder="Nach Name oder Nummer suchen..."
|
||||
value="{{ $search }}">
|
||||
<button type="submit" class="btn btn-outline-primary">
|
||||
<i class="fas fa-search"></i>
|
||||
</button>
|
||||
@if($search)
|
||||
<a href="{{ route('user-nail-polishes.index') }}" class="btn btn-outline-secondary ms-2">
|
||||
<i class="fas fa-times"></i>
|
||||
</a>
|
||||
@endif
|
||||
</form>
|
||||
</div>
|
||||
<div class="col-md-6 text-end">
|
||||
<span class="text-muted">
|
||||
{{ $nailPolishes->total() }} Lack{{ $nailPolishes->total() != 1 ? 'e' : '' }} in Ihrer Sammlung
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if($nailPolishes->count() > 0)
|
||||
<div class="row">
|
||||
@foreach($nailPolishes as $nailPolish)
|
||||
<div class="col-md-3 col-sm-6 mb-4">
|
||||
<div class="card h-100 nail-polish-card">
|
||||
@if($nailPolish->image_path)
|
||||
<img src="{{ Storage::url($nailPolish->image_path) }}"
|
||||
class="card-img-top nail-polish-image"
|
||||
alt="{{ $nailPolish->name }}"
|
||||
loading="lazy">
|
||||
@else
|
||||
<div class="card-img-top nail-polish-placeholder d-flex align-items-center justify-content-center">
|
||||
<i class="fas fa-palette fa-3x text-muted"></i>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card-body d-flex flex-column">
|
||||
<h6 class="card-title mb-1">{{ $nailPolish->name }}</h6>
|
||||
<p class="card-text text-muted mb-2">Nr. {{ $nailPolish->number }}</p>
|
||||
@if($nailPolish->manufacturer)
|
||||
<p class="card-text text-muted mb-2">
|
||||
<small><i class="fas fa-industry"></i> {{ $nailPolish->manufacturer->name }}</small>
|
||||
</p>
|
||||
@endif
|
||||
|
||||
<div class="mt-auto">
|
||||
<form method="POST" action="https://neonail.vogt.de.com/remove-from-collection/{{ $nailPolish->id }}"
|
||||
class="d-inline"
|
||||
onsubmit="return confirm('Möchten Sie diesen Lack wirklich aus Ihrer Sammlung entfernen?')">
|
||||
@csrf
|
||||
<button type="submit" class="btn btn-outline-danger btn-sm w-100">
|
||||
<i class="fas fa-trash me-2"></i>Entfernen
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
@if($nailPolishes->hasPages())
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<nav aria-label="Seitennavigation">
|
||||
{{ $nailPolishes->appends(['search' => $search])->links() }}
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@else
|
||||
<div class="text-center py-5">
|
||||
<i class="fas fa-palette fa-4x text-muted mb-3"></i>
|
||||
<h4 class="text-muted">Ihre Sammlung ist noch leer</h4>
|
||||
<p class="text-muted mb-4">
|
||||
@if($search)
|
||||
Keine Lacke gefunden, die "{{ $search }}" entsprechen.
|
||||
@else
|
||||
Fügen Sie Ihren ersten NeoNail-Lack hinzu!
|
||||
@endif
|
||||
</p>
|
||||
<div class="d-flex gap-2 justify-content-center">
|
||||
<a href="{{ route('user-nail-polishes.create') }}" class="btn btn-success">
|
||||
<i class="fas fa-plus me-2"></i>Ersten Lack hinzufügen
|
||||
</a>
|
||||
<a href="{{ route('user-nail-polishes.available') }}" class="btn btn-primary">
|
||||
<i class="fas fa-search me-2"></i>Verfügbare Lacke durchsuchen
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@endsection
|
||||
70
resources/views/user-nail-polishes/show-user.blade.php
Executable file
70
resources/views/user-nail-polishes/show-user.blade.php
Executable file
@@ -0,0 +1,70 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('title', 'Sammlung von ' . $user->name . ' - NeoNail DB')
|
||||
|
||||
@section('content')
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1 class="h3 mb-0">
|
||||
<i class="fas fa-palette me-2"></i>Sammlung von {{ $user->name }}
|
||||
</h1>
|
||||
<a href="{{ route('admin.users.index') }}" class="btn btn-outline-primary">
|
||||
<i class="fas fa-arrow-left me-2"></i>Zurück zur Benutzerliste
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Benutzer-Info -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-body">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-md-8">
|
||||
<div class="d-flex align-items-center">
|
||||
<i class="fas fa-user-circle fa-3x text-primary me-3"></i>
|
||||
<div>
|
||||
<h4 class="mb-1">{{ $user->name }}</h4>
|
||||
<p class="text-muted mb-0">{{ $user->email }}</p>
|
||||
<small class="text-muted">Registriert am {{ $user->created_at->format('d.m.Y') }}</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 text-end">
|
||||
<div class="h2 text-primary mb-0">{{ $nailPolishes->count() }}</div>
|
||||
<p class="text-muted mb-0">Nagellacke in der Sammlung</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sammlung -->
|
||||
@if($nailPolishes->count() > 0)
|
||||
<div class="row">
|
||||
@foreach($nailPolishes as $nailPolish)
|
||||
<div class="col-6 col-md-4 col-lg-3 mb-4">
|
||||
<div class="card nail-polish-card h-100">
|
||||
@if($nailPolish->image_path)
|
||||
<img src="{{ Storage::url($nailPolish->image_path) }}"
|
||||
class="nail-polish-image" alt="{{ $nailPolish->name }}">
|
||||
@else
|
||||
<div class="nail-polish-image d-flex align-items-center justify-content-center bg-light">
|
||||
<i class="fas fa-image fa-3x text-muted"></i>
|
||||
</div>
|
||||
@endif
|
||||
<div class="card-body">
|
||||
<h6 class="card-title fw-bold">{{ $nailPolish->name }}</h6>
|
||||
<p class="card-text text-muted small">Nr. {{ $nailPolish->number }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@else
|
||||
<div class="text-center py-5">
|
||||
<i class="fas fa-palette fa-4x text-muted mb-3"></i>
|
||||
<h4 class="text-muted">Keine Nagellacke in der Sammlung</h4>
|
||||
<p class="text-muted">{{ $user->name }} hat noch keine NeoNail-Lacke hinzugefügt.</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
277
resources/views/welcome.blade.php
Executable file
277
resources/views/welcome.blade.php
Executable file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user