b2in/resources/views/livewire/admin/users.blade.php
2026-01-23 17:33:10 +01:00

1011 lines
45 KiB
PHP

<?php
use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Livewire\Volt\Component;
use Livewire\WithPagination;
use function Livewire\Volt\{layout, title, state};
layout('components.layouts.app');
title('Users Management');
new class extends Component {
use WithPagination;
public string $search = '';
public string $roleFilter = '';
public string $parentPartnerFilter = '';
public string $brandFilter = '';
public string $setupStatusFilter = '';
public string $sortField = 'created_at';
public string $sortDirection = 'desc';
// Modal state for roles
public bool $showRoleModal = false;
public ?int $selectedUserId = null;
public array $selectedRoles = [];
// Modal state for editing user
public bool $showEditModal = false;
public ?int $editUserId = null;
public string $userName = '';
public string $displayName = '';
public string $userEmail = '';
public bool $emailVerified = false;
// Modal state for viewing partner data
public bool $showViewModal = false;
public ?int $viewUserId = null;
public function with(): array
{
$query = User::with(['roles', 'registrationCode', 'partner.parentPartner'])
->when($this->search, fn($q, $search) =>
$q->where('name', 'like', "%{$search}%")
->orWhere('email', 'like', "%{$search}%")
)
->when($this->roleFilter, fn($q, $role) =>
$q->whereHas('roles', fn($roleQuery) =>
$roleQuery->where('name', $role)
)
)
->when($this->parentPartnerFilter, fn($q, $parentPartnerId) =>
$q->whereHas('partner', fn($partnerQuery) =>
$partnerQuery->where('parent_partner_id', $parentPartnerId)
)
)
->when($this->brandFilter, fn($q, $brand) =>
$q->whereHas('partner', fn($partnerQuery) =>
$partnerQuery->where('brand', $brand)
)
)
->when($this->setupStatusFilter === 'completed', fn($q) =>
$q->whereHas('partner', fn($partnerQuery) =>
$partnerQuery->whereNotNull('setup_completed_at')
)
)
->when($this->setupStatusFilter === 'pending', fn($q) =>
$q->whereHas('partner', fn($partnerQuery) =>
$partnerQuery->whereNull('setup_completed_at')
)
)
->when($this->setupStatusFilter === 'no_partner', fn($q) =>
$q->whereNull('partner_id')
);
// Finde alle Partner, die als parent_partner_id verwendet werden
$parentPartnerIds = \App\Models\Partner::whereNotNull('parent_partner_id')
->distinct()
->pluck('parent_partner_id');
$availableParentPartners = \App\Models\Partner::whereIn('id', $parentPartnerIds)
->orderBy('company_name')
->get();
// Finde alle verfügbaren Brands
$availableBrands = \App\Models\Partner::whereNotNull('brand')
->distinct()
->pluck('brand')
->sort();
// Zähle User mit abgeschlossenem Setup
$setupCompletedCount = User::whereHas('partner', function($q) {
$q->whereNotNull('setup_completed_at');
})->count();
return [
'users' => $query->orderBy($this->sortField, $this->sortDirection)->paginate(15),
'totalUsers' => User::count(),
'verifiedUsers' => User::whereNotNull('email_verified_at')->count(),
'setupCompletedUsers' => $setupCompletedCount,
'availableRoles' => \Spatie\Permission\Models\Role::orderBy('name')->get(),
'availableParentPartners' => $availableParentPartners,
'availableBrands' => $availableBrands,
'selectedUser' => $this->selectedUserId ? User::find($this->selectedUserId) : null,
'editUser' => $this->editUserId ? User::find($this->editUserId) : null,
'viewUser' => $this->viewUserId ? User::with(['partner.brand', 'roles'])->find($this->viewUserId) : null,
];
}
public function sortBy(string $field): void
{
if ($this->sortField === $field) {
$this->sortDirection = $this->sortDirection === 'asc' ? 'desc' : 'asc';
} else {
$this->sortField = $field;
$this->sortDirection = 'asc';
}
}
public function updatingSearch(): void
{
$this->resetPage();
}
public function updatingRoleFilter(): void
{
$this->resetPage();
}
public function updatingParentPartnerFilter(): void
{
$this->resetPage();
}
public function updatingBrandFilter(): void
{
$this->resetPage();
}
public function updatingSetupStatusFilter(): void
{
$this->resetPage();
}
public function openRoleModal(int $userId): void
{
$user = User::with('roles')->findOrFail($userId);
$this->selectedUserId = $userId;
$this->selectedRoles = $user->roles->pluck('name')->toArray();
$this->showRoleModal = true;
}
public function saveRoles(): void
{
if (!$this->selectedUserId) {
return;
}
$user = User::findOrFail($this->selectedUserId);
$user->syncRoles($this->selectedRoles);
$this->showRoleModal = false;
$this->selectedUserId = null;
$this->selectedRoles = [];
// Optional: Flash message
session()->flash('message', __('Roles updated successfully!'));
}
public function closeRoleModal(): void
{
$this->showRoleModal = false;
$this->selectedUserId = null;
$this->selectedRoles = [];
}
public function openEditModal(int $userId): void
{
$user = User::findOrFail($userId);
$this->editUserId = $userId;
$this->userName = $user->name;
$this->displayName = $user->display_name ?? '';
$this->userEmail = $user->email;
$this->emailVerified = !is_null($user->email_verified_at);
$this->showEditModal = true;
}
public function saveUser(): void
{
if (!$this->editUserId) {
return;
}
$user = User::with('roles')->findOrFail($this->editUserId);
// Prüfe ob User eine Rolle hat, die display_name erfordert
$requiresDisplayName = $user->roles->whereIn('name', ['Broker', 'Retailer', 'Manufacturer'])->isNotEmpty();
$rules = [
'userName' => 'required|string|max:255',
'displayName' => $requiresDisplayName ? 'required|string|max:255' : 'nullable|string|max:255',
'userEmail' => 'required|email|max:255|unique:users,email,' . $this->editUserId,
];
$messages = [
'displayName.required' => __('Name für die Zuordnung von Kunden ist für Makler, Händler und Hersteller erforderlich.'),
];
$this->validate($rules, $messages);
$user->update([
'name' => $this->userName,
'display_name' => $this->displayName ?: null,
'email' => $this->userEmail,
'email_verified_at' => $this->emailVerified ? ($user->email_verified_at ?? now()) : null,
]);
$this->showEditModal = false;
$this->reset(['editUserId', 'userName', 'displayName', 'userEmail', 'emailVerified']);
session()->flash('message', __('User updated successfully!'));
}
public function closeEditModal(): void
{
$this->showEditModal = false;
$this->reset(['editUserId', 'userName', 'displayName', 'userEmail', 'emailVerified']);
}
public function openViewModal(int $userId): void
{
$this->viewUserId = $userId;
$this->showViewModal = true;
}
public function closeViewModal(): void
{
$this->showViewModal = false;
$this->viewUserId = null;
}
public function deleteUser(int $userId): void
{
$user = User::findOrFail($userId);
// Prüfe auf Verknüpfungen
if ($user->hasDependencies()) {
// Anonymisiere statt zu löschen
$user->anonymize();
session()->flash('message', __('User wurde anonymisiert, da Verknüpfungen existieren.'));
} else {
// Soft Delete
$user->delete();
session()->flash('message', __('User deleted successfully!'));
}
// Schließe ggf. offene Modals
$this->showRoleModal = false;
$this->showEditModal = false;
$this->reset(['selectedUserId', 'editUserId']);
}
public function loginAsUser(int $userId): void
{
$currentUser = Auth::user();
$targetUser = User::findOrFail($userId);
// Speichere den aktuellen Admin-User in der Session
session(['impersonate_from' => $currentUser->id]);
// Logge als Ziel-User ein
Auth::login($targetUser);
// Weiterleitung zum Dashboard
$this->redirect(route('dashboard'), navigate: false);
}
}; ?>
<div class="space-y-6 p-6">
{{-- Header --}}
<div class="flex items-center justify-between">
<div>
<flux:heading size="xl" class="mb-2">{{ __('Benutzerverwaltung') }}</flux:heading>
<flux:subheading>{{ __('Manage users and their roles in your application') }}</flux:subheading>
</div>
{{-- <div class="flex gap-2">
<flux:button variant="primary" icon="plus">{{ __('Create User') }}</flux:button>
</div> --}}
</div>
{{-- Statistics --}}
<div class="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-4">
<flux:card class="shadow-elegant">
<div class="flex items-center justify-between">
<div>
<flux:subheading>{{ __('Total Users') }}</flux:subheading>
<flux:heading size="2xl" class="mt-2">{{ $totalUsers }}</flux:heading>
</div>
<div class="flex h-12 w-12 items-center justify-center rounded-lg bg-accent-100 dark:bg-accent-900/20">
<flux:icon.users class="h-6 w-6 text-accent-600 dark:text-accent-400" />
</div>
</div>
</flux:card>
<flux:card class="shadow-elegant">
<div class="flex items-center justify-between">
<div>
<flux:subheading>{{ __('Verified Users') }}</flux:subheading>
<flux:heading size="2xl" class="mt-2">{{ $verifiedUsers }}</flux:heading>
</div>
<div class="flex h-12 w-12 items-center justify-center rounded-lg bg-blue-100 dark:bg-blue-900/20">
<flux:icon.shield-check class="h-6 w-6 text-blue-600 dark:text-blue-400" />
</div>
</div>
</flux:card>
<flux:card class="shadow-elegant">
<div class="flex items-center justify-between">
<div>
<flux:subheading>{{ __('Setup abgeschlossen') }}</flux:subheading>
<flux:heading size="2xl" class="mt-2">{{ $setupCompletedUsers }}</flux:heading>
</div>
<div class="flex h-12 w-12 items-center justify-center rounded-lg bg-green-100 dark:bg-green-900/20">
<flux:icon.check-circle class="h-6 w-6 text-green-600 dark:text-green-400" />
</div>
</div>
</flux:card>
<flux:card class="shadow-elegant">
<div class="flex items-center justify-between">
<div>
<flux:subheading>{{ __('Active Roles') }}</flux:subheading>
<flux:heading size="2xl" class="mt-2">{{ $availableRoles->count() }}</flux:heading>
</div>
<div class="flex h-12 w-12 items-center justify-center rounded-lg bg-purple-100 dark:bg-purple-900/20">
<flux:icon.user-group class="h-6 w-6 text-purple-600 dark:text-purple-400" />
</div>
</div>
</flux:card>
</div>
{{-- Filters --}}
<flux:card class="shadow-elegant">
<div class="grid grid-cols-1 gap-4 md:grid-cols-3 lg:grid-cols-6">
<flux:input wire:model.live.debounce.300ms="search" icon="magnifying-glass" placeholder="{{ __('Search users...') }}" />
<flux:select wire:model.live="roleFilter" placeholder="{{ __('All Roles') }}">
<flux:select.option value="">{{ __('All Roles') }}</flux:select.option>
@foreach($availableRoles as $role)
<flux:select.option :value="$role->name">{{ $role->display_name ?? $role->name }}</flux:select.option>
@endforeach
</flux:select>
<flux:select wire:model.live="brandFilter" placeholder="{{ __('Alle Brands') }}">
<flux:select.option value="">{{ __('Alle Brands') }}</flux:select.option>
@foreach($availableBrands as $brand)
<flux:select.option :value="$brand">{{ strtoupper($brand) }}</flux:select.option>
@endforeach
</flux:select>
<flux:select variant="listbox" searchable wire:model.live="parentPartnerFilter" placeholder="{{ __('Alle Partner-Zuordnungen') }}">
<flux:select.option value="">{{ __('Alle Partner-Zuordnungen') }}</flux:select.option>
@foreach($availableParentPartners as $partner)
<flux:select.option :value="$partner->id">
{{ $partner->company_name }}
</flux:select.option>
@endforeach
</flux:select>
<flux:select wire:model.live="setupStatusFilter" placeholder="{{ __('Setup Status') }}">
<flux:select.option value="">{{ __('Alle Setup-Status') }}</flux:select.option>
<flux:select.option value="completed">{{ __('Setup abgeschlossen') }}</flux:select.option>
<flux:select.option value="pending">{{ __('Setup ausstehend') }}</flux:select.option>
<flux:select.option value="no_partner">{{ __('Kein Partner') }}</flux:select.option>
</flux:select>
@if($search || $roleFilter || $parentPartnerFilter || $brandFilter || $setupStatusFilter)
<flux:button wire:click="$set('search', ''); $set('roleFilter', ''); $set('parentPartnerFilter', ''); $set('brandFilter', ''); $set('setupStatusFilter', '')" variant="ghost" icon="x-mark">
{{ __('Clear Filters') }}
</flux:button>
@endif
</div>
</flux:card>
{{-- Users Table --}}
<flux:card class="shadow-elegant">
<flux:table>
<flux:table.columns>
<flux:table.column class="w-1/4" wire:click="sortBy('name')" class="cursor-pointer">
<div class="flex items-center gap-2">
{{ __('User') }}
@if($sortField === 'name')
<flux:icon.{{ $sortDirection === 'asc' ? 'chevron-up' : 'chevron-down' }} variant="micro" />
@endif
</div>
</flux:table.column>
<flux:table.column wire:click="sortBy('email')" class="cursor-pointer">
<div class="flex items-center gap-2">
{{ __('Email') }}
@if($sortField === 'email')
<flux:icon.{{ $sortDirection === 'asc' ? 'chevron-up' : 'chevron-down' }} variant="micro" />
@endif
</div>
</flux:table.column>
<flux:table.column>{{ __('roles.role') }}</flux:table.column>
<flux:table.column class="w-48" wire:click="sortBy('created_at')" class="cursor-pointer">
<div class="flex items-center gap-2">
{{ __('Registrierung & Setup') }}
@if($sortField === 'created_at')
<flux:icon.{{ $sortDirection === 'asc' ? 'chevron-up' : 'chevron-down' }} variant="micro" />
@endif
</div>
</flux:table.column>
<flux:table.column class="w-32">{{ __('Status') }}</flux:table.column>
<flux:table.column class="w-40">{{ __('Actions') }}</flux:table.column>
</flux:table.columns>
<flux:table.rows>
@forelse($users as $user)
<flux:table.row :key="$user->id" class="odd:bg-zinc-50 dark:odd:bg-zinc-800/30">
<flux:table.cell>
<div class="flex items-center gap-3 pl-2">
<div class="flex h-10 w-10 items-center justify-center rounded-lg bg-accent-100 text-accent-600 dark:bg-accent-900/20 dark:text-accent-400 font-semibold">
{{ $user->initials() }}
</div>
<div>
<div class="font-semibold text-zinc-900 dark:text-white">{{ $user->name }}</div>
@if($user->display_name)
<div class="text-xs font-medium text-accent-600 dark:text-accent-400">
{{ $user->display_name }}
</div>
@endif
<div class="flex items-center gap-2 text-xs text-zinc-500 dark:text-zinc-400">
@if($user->registrationCode)
<span class="font-mono">{{ $user->registrationCode->code }}</span>
@else
<span class="text-zinc-400">{{ __('Kein Code') }}</span>
@endif
@if($user->partner && $user->partner->brand)
<span class="text-zinc-300 dark:text-zinc-600">•</span>
@php
$brandColors = [
'b2in' => 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400',
'style2own' => 'bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-400',
'stileigentum' => 'bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-400',
'b2a' => 'bg-teal-100 text-teal-700 dark:bg-teal-900/30 dark:text-teal-400',
];
$brandColor = $brandColors[$user->partner->brand] ?? 'bg-zinc-100 text-zinc-700 dark:bg-zinc-800 dark:text-zinc-400';
@endphp
<span class="inline-flex items-center rounded-md px-2 py-0.5 text-xs font-medium {{ $brandColor }}">
{{ strtoupper($user->partner->brand) }}
</span>
@endif
</div>
</div>
</div>
</flux:table.cell>
<flux:table.cell>
<div class="flex items-center gap-2">
<flux:icon.envelope variant="micro" class="text-zinc-400" />
<span>{{ $user->email }}</span>
</div>
</flux:table.cell>
<flux:table.cell>
<div class="flex flex-wrap gap-1.5">
<button
type="button"
wire:click="openRoleModal({{ $user->id }})"
class="flex flex-wrap gap-1.5 cursor-pointer hover:opacity-80 transition-opacity"
>
@forelse($user->roles as $role)
<flux:badge size="sm" :color="$role->color ?? 'zinc'">
@svg('heroicon-o-'.$role->icon, 'w-5 h-5') &nbsp; {{ $role->display_name ?? $role->name }}
</flux:badge>
@empty
<flux:badge size="sm" color="zinc" icon="plus">{{ __('Assign Role') }}</flux:badge>
@endforelse
</button>
</div>
</flux:table.cell>
<flux:table.cell>
<div class="flex flex-col space-y-1 text-sm">
{{-- Registrierungsdatum --}}
<div class="flex items-center gap-2">
<flux:icon.user-plus variant="micro" class="text-zinc-400" />
<div class="flex flex-col">
<span class="font-medium text-zinc-900 dark:text-white">
{{ $user->created_at->format('d.m.Y H:i') }}
</span>
<span class="text-xs text-zinc-500 dark:text-zinc-400">
{{ __('Registriert') }}
</span>
</div>
</div>
{{-- Setup-Abschluss --}}
@if($user->partner && $user->partner->setup_completed_at)
<div class="flex items-center gap-2">
<flux:icon.check-circle variant="micro" class="text-green-500" />
<div class="flex flex-col">
<span class="font-medium text-green-600 dark:text-green-400">
{{ $user->partner->setup_completed_at->format('d.m.Y H:i') }}
</span>
<span class="text-xs text-zinc-500 dark:text-zinc-400">
{{ __('Setup abgeschlossen') }}
</span>
</div>
</div>
@else
<div class="flex items-center gap-2">
<flux:icon.clock variant="micro" class="text-orange-400" />
<span class="text-xs text-orange-600 dark:text-orange-400">
{{ __('Setup ausstehend') }}
</span>
</div>
@endif
</div>
</flux:table.cell>
<flux:table.cell>
@if($user->email_verified_at)
<flux:badge size="sm" color="green" icon="check-circle">
{{ __('Verified') }}
</flux:badge>
@else
<flux:badge size="sm" color="zinc" icon="exclamation-circle">
{{ __('Unverified') }}
</flux:badge>
@endif
</flux:table.cell>
<flux:table.cell>
<div class="flex gap-2">
@if($user->partner_id)
<flux:button size="sm" variant="ghost" icon="eye"
wire:click="openViewModal({{ $user->id }})"
tooltip="{{ __('Partner-Daten ansehen') }}"></flux:button>
@endif
@if($user->id !== Auth::id())
<flux:button size="sm" variant="ghost" icon="arrow-right-start-on-rectangle"
wire:click="loginAsUser({{ $user->id }})"
wire:confirm="{{ __('Als :name einloggen? Sie können später zurück zum Admin wechseln.', ['name' => $user->name]) }}"
tooltip="{{ __('Login als User') }}"></flux:button>
@endif
<flux:button size="sm" variant="ghost" icon="pencil"
wire:click="openEditModal({{ $user->id }})"
tooltip="{{ __('Edit User') }}"></flux:button>
@if($user->id !== Auth::id())
<flux:button size="sm" variant="ghost" icon="trash"
wire:click="deleteUser({{ $user->id }})"
wire:confirm="{{ __('Möchten Sie diesen Benutzer wirklich löschen? Falls Verknüpfungen existieren, wird der Benutzer anonymisiert.') }}"
tooltip="{{ __('Delete User') }}"></flux:button>
@endif
</div>
</flux:table.cell>
</flux:table.row>
@empty
<flux:table.row>
<flux:table.cell colspan="6">
<div class="py-12 text-center">
<flux:icon.users variant="outline" class="mx-auto h-12 w-12 text-zinc-400" />
<flux:heading size="lg" class="mt-4">{{ __('No users found') }}</flux:heading>
<flux:subheading class="mt-2">
@if($search || $roleFilter || $parentPartnerFilter || $brandFilter || $setupStatusFilter)
{{ __('Try adjusting your filters.') }}
@else
{{ __('Get started by creating a new user.') }}
@endif
</flux:subheading>
</div>
</flux:table.cell>
</flux:table.row>
@endforelse
</flux:table.rows>
</flux:table>
{{-- Pagination --}}
@if($users->hasPages())
<div class="border-t border-zinc-200 px-6 py-4 dark:border-zinc-700">
{{ $users->links() }}
</div>
@endif
</flux:card>
{{-- Role Assignment Modal --}}
<flux:modal name="role-modal" :variant="'flyout'" wire:model="showRoleModal">
<form wire:submit="saveRoles" class="space-y-6">
<div>
<flux:heading size="lg">{{ __('Assign Roles') }}</flux:heading>
<flux:subheading>
@if($selectedUser)
{{ __('Managing roles for') }} <strong>{{ $selectedUser->name }}</strong>
@endif
</flux:subheading>
</div>
<flux:separator />
<div class="space-y-4">
<flux:field>
<flux:label>{{ __('roles.role') }}</flux:label>
<flux:description>{{ __('Select one or multiple roles for this user') }}</flux:description>
<div class="space-y-2 mt-3">
@foreach($availableRoles as $role)
<flux:checkbox
wire:model="selectedRoles"
:value="$role->name"
:label="$role->display_name ?? $role->name"
/>
@endforeach
</div>
</flux:field>
@if(!empty($selectedRoles))
<div class="rounded-lg bg-zinc-50 p-4 dark:bg-zinc-800/50">
<flux:subheading class="mb-2">{{ __('Selected Roles:') }}</flux:subheading>
<div class="flex flex-wrap gap-2">
@foreach($selectedRoles as $roleName)
@php
$roleObj = $availableRoles->firstWhere('name', $roleName);
@endphp
<flux:badge size="sm" :color="$roleObj?->color ?? 'zinc'">
{{ $roleName }}
</flux:badge>
@endforeach
</div>
</div>
@endif
</div>
<flux:separator />
<div class="flex justify-between gap-2">
<flux:button type="button" variant="ghost" wire:click="closeRoleModal">
{{ __('Cancel') }}
</flux:button>
<flux:button type="submit" variant="primary">
{{ __('Save Roles') }}
</flux:button>
</div>
</form>
</flux:modal>
{{-- Edit User Modal --}}
<flux:modal name="edit-user-modal" :variant="'flyout'" wire:model="showEditModal">
<form wire:submit="saveUser" class="space-y-6 max-w-2xl">
<div>
<flux:heading size="lg">{{ __('Edit User') }}</flux:heading>
<flux:subheading>
@if($editUser)
{{ __('Editing user') }}: <strong>{{ $editUser->name }}</strong>
@endif
</flux:subheading>
</div>
<flux:separator />
<div class="space-y-4">
<flux:field>
<flux:label>{{ __('Name') }}</flux:label>
<flux:input wire:model="userName" placeholder="{{ __('Enter user name') }}" />
@error('userName') <flux:error>{{ $message }}</flux:error> @enderror
</flux:field>
<flux:field>
<flux:label>
{{ __('Name für die Zuordnung von Kunden') }}
@if($editUser && $editUser->roles->whereIn('name', ['Broker', 'Retailer', 'Manufacturer'])->isNotEmpty())
<span class="text-red-500">*</span>
@endif
</flux:label>
<flux:description>
{{ __('Pflichtfeld für Makler, Händler und Hersteller') }}
</flux:description>
<flux:input wire:model="displayName" placeholder="{{ __('z.B. Max Mustermann Immobilien') }}" />
@error('displayName') <flux:error>{{ $message }}</flux:error> @enderror
</flux:field>
<flux:field>
<flux:label>{{ __('Email') }}</flux:label>
<flux:input type="email" wire:model="userEmail" placeholder="{{ __('Enter email address') }}" />
@error('userEmail') <flux:error>{{ $message }}</flux:error> @enderror
</flux:field>
<flux:field>
<flux:label>{{ __('Email Verification') }}</flux:label>
<flux:description>{{ __('Set whether the email address is verified') }}</flux:description>
<flux:checkbox wire:model="emailVerified" :label="__('Email verified')" />
</flux:field>
@if($editUser && $editUser->registrationCode)
<flux:field>
<flux:label>{{ __('Registration Code') }}</flux:label>
<div class="rounded-lg bg-zinc-50 p-4 dark:bg-zinc-800/50">
<span class="font-mono font-semibold text-lg">{{ $editUser->registrationCode->code }}</span>
<div class="text-sm text-zinc-500 mt-1">
{{ __('Registered with this code') }}
</div>
</div>
</flux:field>
@endif
</div>
<flux:separator />
<div class="flex justify-between gap-2">
<flux:button type="button" variant="ghost" wire:click="closeEditModal">
{{ __('Cancel') }}
</flux:button>
<flux:button type="submit" variant="primary">
{{ __('Save User') }}
</flux:button>
</div>
</form>
</flux:modal>
{{-- View Partner Data Modal --}}
<flux:modal name="view-partner-modal" :variant="'flyout'" wire:model="showViewModal" class="md:w-2xl">
@if($viewUser && $viewUser->partner)
@php
$partner = $viewUser->partner;
$normalizedType = strtolower(str_replace('-', '', $partner->type));
$isCustomer = $normalizedType === 'customer';
$isBroker = $normalizedType === 'broker' || $normalizedType === 'estateagent';
$isRetailer = $normalizedType === 'retailer';
$isManufacturer = $normalizedType === 'manufacturer';
$role = $viewUser->roles->first();
$roleIcon = $role?->icon ?? 'shield-check';
$roleName = $role?->display_name ?? $role?->name ?? '-';
@endphp
<div class="space-y-6">
{{-- Header --}}
<div>
<div class="flex items-center justify-between">
<flux:heading size="lg">{{ __('Partner-Daten') }}</flux:heading>
<div class="flex items-center gap-2">
@svg('heroicon-o-'.$roleIcon, 'w-5 h-5 text-accent-600 dark:text-accent-400')
<span class="text-sm font-medium text-zinc-700 dark:text-zinc-300">{{ $roleName }}</span>
</div>
</div>
<flux:subheading class="mt-2">
{{ __('Benutzer') }}: <strong>{{ $viewUser->name }}</strong>
</flux:subheading>
</div>
<flux:separator />
{{-- Firmeninformationen --}}
@if (!$isCustomer)
<div class="space-y-4">
<flux:subheading class="font-semibold text-zinc-900 dark:text-white">
{{ __('Firmeninformationen') }}
</flux:subheading>
<div class="grid grid-cols-1 gap-4">
<div>
<flux:label>{{ __('Firmenname') }}</flux:label>
<div class="mt-1 text-sm text-zinc-900 dark:text-white">
{{ $partner->company_name ?: '-' }}
</div>
</div>
@if ($isBroker)
<div>
<flux:label>{{ __('Anzeigename') }}</flux:label>
<div class="mt-1 text-sm text-zinc-900 dark:text-white">
{{ $partner->display_name ?: '-' }}
</div>
</div>
@endif
@if ($partner->description)
<div>
<flux:label>{{ __('Kurzbeschreibung') }}</flux:label>
<div class="mt-1 text-sm text-zinc-700 dark:text-zinc-300">
{{ $partner->description }}
</div>
</div>
@endif
</div>
</div>
<flux:separator />
@endif
{{-- Persönliche Daten --}}
<div class="space-y-4">
<flux:subheading class="font-semibold text-zinc-900 dark:text-white">
{{ __('Persönliche Daten') }}
</flux:subheading>
<div class="grid grid-cols-3 gap-4">
<div>
<flux:label>{{ __('Anrede') }}</flux:label>
<div class="mt-1 text-sm text-zinc-900 dark:text-white">
{{ $partner->salutation ?: '-' }}
</div>
</div>
<div>
<flux:label>{{ __('Vorname') }}</flux:label>
<div class="mt-1 text-sm text-zinc-900 dark:text-white">
{{ $partner->first_name ?: '-' }}
</div>
</div>
<div>
<flux:label>{{ __('Nachname') }}</flux:label>
<div class="mt-1 text-sm text-zinc-900 dark:text-white">
{{ $partner->last_name ?: '-' }}
</div>
</div>
</div>
</div>
<flux:separator />
{{-- Adresse --}}
<div class="space-y-4">
<flux:subheading class="font-semibold text-zinc-900 dark:text-white">
{{ __('Adresse') }}
</flux:subheading>
<div class="grid grid-cols-1 gap-4">
<div class="grid grid-cols-4 gap-2">
<div class="col-span-3">
<flux:label>{{ __('Straße') }}</flux:label>
<div class="mt-1 text-sm text-zinc-900 dark:text-white">
{{ $partner->street ?: '-' }}
</div>
</div>
<div>
<flux:label>{{ __('Hausnummer') }}</flux:label>
<div class="mt-1 text-sm text-zinc-900 dark:text-white">
{{ $partner->house_number ?: '-' }}
</div>
</div>
</div>
<div class="grid grid-cols-3 gap-4">
<div>
<flux:label>{{ __('Postleitzahl') }}</flux:label>
<div class="mt-1 text-sm text-zinc-900 dark:text-white">
{{ $partner->zip ?: '-' }}
</div>
</div>
<div class="col-span-2">
<flux:label>{{ __('Ort') }}</flux:label>
<div class="mt-1 text-sm text-zinc-900 dark:text-white">
{{ $partner->city ?: '-' }}
</div>
</div>
</div>
<div>
<flux:label>{{ __('Land') }}</flux:label>
<div class="mt-1 text-sm text-zinc-900 dark:text-white">
{{ $partner->country ?: '-' }}
</div>
</div>
</div>
</div>
<flux:separator />
{{-- Kontaktdaten --}}
<div class="space-y-4">
<flux:subheading class="font-semibold text-zinc-900 dark:text-white">
{{ __('Kontaktdaten') }}
</flux:subheading>
<div class="grid grid-cols-1 gap-4">
<div>
<flux:label>{{ __('Telefon') }}</flux:label>
<div class="mt-1 text-sm text-zinc-900 dark:text-white">
{{ $partner->phone ?: '-' }}
</div>
</div>
@if (!$isCustomer)
<div>
<flux:label>{{ __('Website') }}</flux:label>
<div class="mt-1 text-sm text-zinc-900 dark:text-white">
@if($partner->website)
<a href="{{ $partner->website }}" target="_blank" class="text-accent-600 hover:text-accent-700 dark:text-accent-400 dark:hover:text-accent-300">
{{ $partner->website }}
</a>
@else
-
@endif
</div>
</div>
@endif
</div>
</div>
{{-- Liefergebiete für Händler --}}
@if ($isRetailer)
<flux:separator />
<div class="space-y-4">
<flux:subheading class="font-semibold text-zinc-900 dark:text-white">
{{ __('Liefergebiete') }}
</flux:subheading>
<div class="grid grid-cols-2 gap-4">
<div>
<flux:label>{{ __('Lieferradius') }}</flux:label>
<div class="mt-1 text-sm text-zinc-900 dark:text-white">
{{ $partner->delivery_radius_km ? $partner->delivery_radius_km . ' km' : '-' }}
</div>
</div>
<div>
<flux:label>{{ __('Montageradius') }}</flux:label>
<div class="mt-1 text-sm text-zinc-900 dark:text-white">
{{ $partner->assembly_radius_km ? $partner->assembly_radius_km . ' km' : '-' }}
</div>
</div>
</div>
</div>
@endif
{{-- Marke für Hersteller --}}
@if ($isManufacturer && $partner->brand)
<flux:separator />
<div class="space-y-4">
<flux:subheading class="font-semibold text-zinc-900 dark:text-white">
{{ __('Markeninformationen') }}
</flux:subheading>
<div class="grid grid-cols-1 gap-4">
<div>
<flux:label>{{ __('Markenname') }}</flux:label>
<div class="mt-1 text-sm text-zinc-900 dark:text-white">
@if(isset($partner->brand->name))
{{ $partner->brand->name }}
@else
-
@endif
</div>
</div>
@if(isset($partner->brand->description))
<div>
<flux:label>{{ __('Marken-Beschreibung') }}</flux:label>
<div class="mt-1 text-sm text-zinc-700 dark:text-zinc-300">
{{ $partner->brand->description }}
</div>
</div>
@endif
<div>
<flux:label>{{ __('Status') }}</flux:label>
<div class="mt-1">
@if(isset($partner->brand->is_active) && $partner->brand->is_active === true)
<flux:badge color="green" size="sm" icon="check-circle">{{ __('Aktiv') }}</flux:badge>
@else
<flux:badge color="zinc" size="sm" icon="x-circle">{{ __('Inaktiv') }}</flux:badge>
@endif
</div>
</div>
</div>
</div>
@endif
<flux:separator />
{{-- Close Button --}}
<div class="flex justify-end">
<flux:button type="button" variant="primary" wire:click="closeViewModal">
{{ __('Schließen') }}
</flux:button>
</div>
</div>
@else
<div class="space-y-6">
<div>
<flux:heading size="lg">{{ __('Partner-Daten') }}</flux:heading>
<flux:subheading class="mt-2">
{{ __('Dieser Benutzer hat keine Partner-Daten') }}
</flux:subheading>
</div>
<flux:separator />
<div class="flex justify-end">
<flux:button type="button" variant="primary" wire:click="closeViewModal">
{{ __('Schließen') }}
</flux:button>
</div>
</div>
@endif
</flux:modal>
{{-- Success Message --}}
@if (session()->has('message'))
<flux:toast :variant="'success'">
{{ session('message') }}
</flux:toast>
@endif
</div>