mailwolt/resources/views/livewire/ui/webmail/inbox.blade.php

613 lines
39 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<div>
@php
$folderLabels = ['INBOX'=>'Posteingang','Sent'=>'Gesendet','Drafts'=>'Entwürfe','Junk'=>'Spam','Trash'=>'Papierkorb','Archive'=>'Archiv','_starred'=>'Markiert'];
$isDrafts = $folder === 'Drafts';
$isTrash = $folder === 'Trash';
$hasTabs = in_array($folder, ['INBOX', '_starred']);
$unread = collect($messages)->where('seen', false)->count();
$mailbox = session('webmail_email');
$allUids = collect($messages)->pluck('uid')->values()->toJson();
$moveTargets = array_filter(
['INBOX'=>'Posteingang','Sent'=>'Gesendet','Archive'=>'Archiv','Junk'=>'Spam','Trash'=>'Papierkorb'],
fn($k) => $k !== $folder, ARRAY_FILTER_USE_KEY
);
$tabCounts = $hasTabs ? [
'all' => count($messages),
'general' => collect($messages)->where('category', 'general')->count(),
'promo' => collect($messages)->where('category', 'promo')->count(),
'social' => collect($messages)->where('category', 'social')->count(),
] : [];
@endphp
<div x-data="{
/* --- Auswahl --- */
selected: [],
allUids: {{ $allUids }},
get allSelected() { return this.allUids.length > 0 && this.selected.length === this.allUids.length; },
get someSelected() { return this.selected.length > 0 && !this.allSelected; },
toggleAll() { this.selected = this.allSelected ? [] : [...this.allUids]; },
toggle(uid) { const i = this.selected.indexOf(uid); i === -1 ? this.selected.push(uid) : this.selected.splice(i,1); },
clear() { this.selected = []; },
/* --- Sender-Tooltip --- */
tipShow: false, tipName: '', tipEmail: '', tipX: 0, tipY: 0,
showTip(name, email, el) {
const r = el.getBoundingClientRect();
this.tipName = name;
this.tipEmail = email;
this.tipX = r.left;
this.tipY = r.bottom + 8;
this.tipShow = true;
},
/* --- Rechtsklick-Menü --- */
ctxOpen: false, ctxUid: null, ctxSeen: true, ctxX: 0, ctxY: 0,
showCtx(uid, seen, x, y) {
this.ctxUid = uid;
this.ctxSeen = seen;
this.ctxX = Math.min(x, window.innerWidth - 205);
this.ctxY = Math.min(y, window.innerHeight - 160);
this.ctxOpen = true;
},
}"
x-init="
Livewire.hook('commit', ({ component, succeed, fail }) => {
if (component.id !== $wire.id) return;
window.dispatchEvent(new CustomEvent('mw-skel-show'));
succeed(() => { Promise.resolve().then(() => { window.dispatchEvent(new CustomEvent('mw-skel-hide')); }); });
fail(() => { window.dispatchEvent(new CustomEvent('mw-skel-hide')); });
});
"
@click.window="ctxOpen = false; tipShow = false;"
@keydown.escape.window="ctxOpen = false;">
{{-- ═══ 1. TITEL ═══ --}}
<div style="margin-bottom:18px;">
<div style="font-size:22px;font-weight:800;color:var(--mw-t1);letter-spacing:-.4px;">{{ $mailbox }}</div>
<div style="display:flex;align-items:center;gap:10px;margin-top:4px;flex-wrap:wrap;">
<span style="font-size:13px;color:var(--mw-t4);">{{ $folderLabels[$folder] ?? $folder }}</span>
@if($unread > 0)
<span style="font-size:11.5px;font-weight:700;color:var(--mw-v2);
background:var(--mw-vbg);border:1px solid var(--mw-vbd);
padding:2px 9px;border-radius:20px;">{{ $unread }} ungelesen</span>
@endif
</div>
</div>
{{-- ═══ 2. SUCHE ═══ --}}
<div style="position:relative;margin-bottom:12px;">
<div style="display:flex;align-items:center;gap:10px;
background:var(--mw-bg3);border:1px solid var(--mw-b1);border-radius:10px;
padding:10px 14px;">
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" style="color:var(--mw-t4);flex-shrink:0;">
<circle cx="6" cy="6" r="4.5" stroke="currentColor" stroke-width="1.3"/>
<path d="M9.5 9.5l3 3" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/>
</svg>
<input wire:model.live.debounce.500ms="search" type="text"
placeholder="In {{ $folderLabels[$folder] ?? $folder }} suchen …"
style="flex:1;background:none;border:none;outline:none;font-size:13.5px;color:var(--mw-t1);">
@if($searching)
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" style="animation:spin 1s linear infinite;color:var(--mw-t4);flex-shrink:0;">
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2.5" stroke-dasharray="60" stroke-dashoffset="20"/>
</svg>
@elseif($search)
<button wire:click="clearSearch" style="background:none;border:none;cursor:pointer;color:var(--mw-t4);font-size:18px;line-height:1;padding:0;">×</button>
@endif
</div>
@if($search && !$searching)
<div style="position:absolute;left:0;right:0;top:calc(100% + 6px);z-index:300;
background:var(--mw-bg);border:1px solid var(--mw-b1);border-radius:10px;
box-shadow:0 8px 28px rgba(0,0,0,.3);overflow:hidden;">
@if(empty($searchResults))
<div style="padding:20px;text-align:center;font-size:13px;color:var(--mw-t4);">Keine Ergebnisse für {{ $search }}"</div>
@else
@foreach($searchResults as $r)
<a href="{{ route('ui.webmail.view', ['uid'=>$r['uid'],'folder'=>$folder]) }}" wire:navigate
style="display:flex;align-items:center;gap:12px;padding:10px 14px;text-decoration:none;
border-bottom:1px solid var(--mw-b1);{{ !$r['seen'] ? 'font-weight:600;' : '' }}"
onmouseover="this.style.background='var(--mw-bg3)'" onmouseout="this.style.background='none'">
<div style="width:30px;height:30px;border-radius:8px;flex-shrink:0;background:var(--mw-vbg);
border:1px solid var(--mw-vbd);display:flex;align-items:center;justify-content:center;
font-size:11px;font-weight:700;color:var(--mw-v2);">
{{ strtoupper(substr($r['from_name'] ?: $r['from'], 0, 1)) }}
</div>
<div style="flex:1;min-width:0;">
<div style="font-size:12.5px;color:{{ !$r['seen'] ? 'var(--mw-v2)' : 'var(--mw-t2)' }};overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">
{{ $r['from_name'] ?: $r['from'] }}
</div>
<div style="font-size:12px;color:var(--mw-t4);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">
{{ $r['subject'] ?: '(kein Betreff)' }}
</div>
</div>
<div style="font-size:11px;color:var(--mw-t4);white-space:nowrap;">
{{ $r['date'] ? \Carbon\Carbon::parse($r['date'])->format('d.m. H:i') : '' }}
</div>
</a>
@endforeach
@endif
</div>
@endif
</div>
{{-- ═══ 3. TOOLBAR ═══ --}}
<div style="display:flex;align-items:center;gap:8px;padding:8px 12px;margin-bottom:12px;
background:var(--mw-bg3);border:1px solid var(--mw-b1);border-radius:9px;">
<input type="checkbox" class="mbx-cbx" :checked="allSelected" :indeterminate="someSelected" @change="toggleAll()">
<template x-if="!someSelected && !allSelected">
<span style="font-size:12px;color:var(--mw-t4);">Alle</span>
</template>
<template x-if="someSelected || allSelected">
<span style="font-size:12px;font-weight:600;color:var(--mw-v2);">
<span x-text="selected.length"></span> ausgewählt
</span>
</template>
<div style="width:1px;height:16px;background:var(--mw-b2);flex-shrink:0;"></div>
<template x-if="someSelected || allSelected"><div style="display:flex;flex-direction:row;align-items:center;gap:4px;">
@if(!$isDrafts)
{{-- Als ungelesen --}}
<button title="Als ungelesen markieren"
@click="$wire.bulkMarkUnseen(selected); clear()"
style="display:flex;align-items:center;justify-content:center;width:28px;height:28px;
border:1px solid var(--mw-b1);border-radius:6px;background:var(--mw-bg4);
color:var(--mw-t3);cursor:pointer;flex-shrink:0;"
onmouseover="this.style.background='var(--mw-bg3)';this.style.color='var(--mw-t1)'"
onmouseout="this.style.background='var(--mw-bg4)';this.style.color='var(--mw-t3)'">
<svg width="13" height="13" viewBox="0 0 14 14" fill="none">
<rect x=".5" y="2.5" width="13" height="9" rx="1.5" stroke="currentColor" stroke-width="1.2"/>
<path d="M.5 5l6.5 4 6.5-4" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/>
<circle cx="11" cy="3" r="2.2" fill="var(--mw-v2)"/>
</svg>
</button>
{{-- Als gelesen --}}
<button title="Als gelesen markieren"
@click="$wire.bulkMarkSeen(selected); clear()"
style="display:flex;align-items:center;justify-content:center;width:28px;height:28px;
border:1px solid var(--mw-b1);border-radius:6px;background:var(--mw-bg4);
color:var(--mw-t3);cursor:pointer;flex-shrink:0;"
onmouseover="this.style.background='var(--mw-bg3)';this.style.color='var(--mw-t1)'"
onmouseout="this.style.background='var(--mw-bg4)';this.style.color='var(--mw-t3)'">
<svg width="13" height="13" viewBox="0 0 14 14" fill="none">
<rect x=".5" y="2.5" width="13" height="9" rx="1.5" stroke="currentColor" stroke-width="1.2"/>
<path d="M.5 5l6.5 4 6.5-4" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/>
<path d="M4.5 8.5l2 2 3.5-4" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
{{-- Verschieben --}}
<div style="position:relative;" x-data="{ mv:false }" @click.outside="mv=false">
<button title="Verschieben nach "
@click="mv=!mv"
style="display:flex;align-items:center;justify-content:center;width:28px;height:28px;
border:1px solid var(--mw-b1);border-radius:6px;background:var(--mw-bg4);
color:var(--mw-t3);cursor:pointer;flex-shrink:0;"
onmouseover="this.style.background='var(--mw-bg3)';this.style.color='var(--mw-t1)'"
onmouseout="this.style.background='var(--mw-bg4)';this.style.color='var(--mw-t3)'">
<svg width="13" height="13" viewBox="0 0 14 14" fill="none">
<path d="M1 7h9M7 4l3 3-3 3" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
<div x-show="mv" x-cloak x-transition
style="position:absolute;left:0;top:calc(100% + 5px);z-index:200;min-width:150px;
background:var(--mw-bg);border:1px solid var(--mw-b1);border-radius:9px;
box-shadow:0 6px 20px rgba(0,0,0,.25);padding:4px;">
@foreach($moveTargets as $key => $label)
<button @click="$wire.bulkMoveTo(selected,'{{ $key }}'); clear(); mv=false"
style="display:flex;align-items:center;width:100%;text-align:left;padding:7px 11px;
border:none;background:none;cursor:pointer;border-radius:6px;font-size:12.5px;color:var(--mw-t2);"
onmouseover="this.style.background='var(--mw-bg3)'" onmouseout="this.style.background='none'">{{ $label }}</button>
@endforeach
</div>
</div>
@endif
{{-- Löschen --}}
<button title="{{ $isTrash ? 'Endgültig löschen' : 'In Papierkorb' }}"
@click="if(confirm('{{ $isTrash ? 'Endgültig löschen?' : 'In Papierkorb?' }}')) { $wire.bulkDelete(selected); clear(); }"
style="display:flex;align-items:center;justify-content:center;width:28px;height:28px;
border:1px solid var(--mw-rdbd);border-radius:6px;background:var(--mw-rdbg);
color:var(--mw-rd);cursor:pointer;flex-shrink:0;"
onmouseover="this.style.background='var(--mw-rd)';this.style.color='#fff'"
onmouseout="this.style.background='var(--mw-rdbg)';this.style.color='var(--mw-rd)'">
<svg width="12" height="12" viewBox="0 0 14 14" fill="none">
<path d="M2 3.5h10M5 3.5V2h4v1.5M5.5 6v4.5M8.5 6v4.5" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/>
<path d="M3 3.5l.7 8h6.6l.7-8" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/>
</svg>
</button>
{{-- Auswahl aufheben --}}
<button title="Auswahl aufheben"
@click="clear()"
style="display:flex;align-items:center;justify-content:center;width:28px;height:28px;
border:1px solid var(--mw-b1);border-radius:6px;background:none;
color:var(--mw-t4);cursor:pointer;flex-shrink:0;font-size:15px;line-height:1;"
onmouseover="this.style.color='var(--mw-t1)'"
onmouseout="this.style.color='var(--mw-t4)'">×</button>
</div></template>
<div style="flex:1;"></div>
@if($isTrash && $total > 0)
<button wire:click="emptyTrash" wire:confirm="Papierkorb endgültig leeren?"
style="display:flex;align-items:center;gap:5px;padding:5px 10px;border-radius:7px;
border:1px solid var(--mw-rdbd);background:var(--mw-rdbg);color:var(--mw-rd);font-size:12px;cursor:pointer;">
Leeren
</button>
@endif
<button wire:click="load" wire:loading.attr="disabled"
style="display:flex;align-items:center;justify-content:center;width:30px;height:30px;
border-radius:7px;border:1px solid var(--mw-b1);background:var(--mw-bg4);
color:var(--mw-t3);cursor:pointer;flex-shrink:0;transition:color .15s;"
onmouseover="this.style.color='var(--mw-t1)'" onmouseout="this.style.color='var(--mw-t3)'"
title="Aktualisieren">
<svg wire:loading.remove wire:target="load" width="13" height="13" viewBox="0 0 14 14" fill="none">
{{-- 270° clockwise arc from top → right → bottom → left --}}
<path d="M7 2A5 5 0 1 1 2 7" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/>
{{-- Arrowhead at (2,7) pointing upward (clockwise travel direction) --}}
<path d="M0 8.5L2 7L4 8.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
<svg wire:loading wire:target="load" width="13" height="13" viewBox="0 0 24 24" fill="none" style="animation:spin 1s linear infinite;">
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2.5" stroke-dasharray="60" stroke-dashoffset="20"/>
</svg>
</button>
<a href="{{ route('ui.webmail.compose') }}" wire:navigate class="mbx-btn-primary" style="height:30px;border-radius:7px;font-size:12px;">
<svg width="11" height="11" viewBox="0 0 14 14" fill="none">
<path d="M7 1.5v11M1.5 7h11" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/>
</svg>
Schreiben
</a>
</div>
{{-- ═══ 4+5. TABS + TABELLE ═══ --}}
<div class="mbx-section" style="padding:0;width:100%;box-sizing:border-box;overflow:hidden;">
@if($hasTabs && !empty($messages))
@php
$tabs = ['all'=>'Alle', 'general'=>'Allgemein', 'promo'=>'Werbung', 'social'=>'Soziale Medien'];
@endphp
<div style="display:flex;align-items:stretch;border-bottom:2px solid var(--mw-b1);padding:0 8px;background:var(--mw-bg4);">
@foreach($tabs as $tabKey => $tabLabel)
@php $cnt = $tabCounts[$tabKey] ?? 0; $isActive = $tab === $tabKey; @endphp
@if($tabKey === 'all' || $cnt > 0)
<button wire:click="switchTab('{{ $tabKey }}')"
style="display:inline-flex;align-items:center;gap:7px;padding:11px 16px;
border:none;border-bottom:2px solid {{ $isActive ? 'var(--mw-v2)' : 'transparent' }};
margin-bottom:-2px;background:none;cursor:pointer;font-size:13px;
white-space:nowrap;outline:none;
color:{{ $isActive ? 'var(--mw-v2)' : 'var(--mw-t4)' }};
font-weight:{{ $isActive ? '600' : '400' }};"
@if(!$isActive)
onmouseover="this.style.color='var(--mw-t2)'"
onmouseout="this.style.color='var(--mw-t4)'"
@endif>
{{ $tabLabel }}
<span style="display:inline-flex;align-items:center;justify-content:center;
min-width:20px;padding:1px 6px;border-radius:10px;
font-size:10.5px;font-weight:500;line-height:1.6;
background:{{ $isActive ? 'var(--mw-vbg)' : 'var(--mw-bg3)' }};
color:{{ $isActive ? 'var(--mw-v2)' : 'var(--mw-t4)' }};">{{ $cnt }}</span>
</button>
@endif
@endforeach
</div>
@endif
{{-- Skeleton: sichtbar während Livewire lädt --}}
@php $wt = 'load,switchFolder,switchTab,nextPage,prevPage,bulkDelete,bulkMoveTo,bulkMarkSeen,bulkMarkUnseen,toggleFlag,deleteDraft,emptyTrash'; @endphp
{{-- Tabelle: thead immer sichtbar, tbody wechselt zwischen Skeleton und Inhalt --}}
<table class="mbx-table" style="table-layout:fixed;width:100%;box-sizing:border-box;">
<colgroup>
<col style="width:5%">
<col style="width:1.5%">
<col style="width:2.5%">
<col style="width:18%">
<col>{{-- Betreff: nimmt den gesamten Rest --}}
<col style="width:11%">
<col style="width:5%">
</colgroup>
<thead>
<tr>
<th class="mbx-th" style="padding:0 10px 0 16px;"></th>
<th class="mbx-th" style="padding:0;"></th>
<th class="mbx-th" style="padding:0 4px;"></th>
<th class="mbx-th">{{ $isDrafts ? 'An' : 'Von' }}</th>
<th class="mbx-th">Betreff</th>
<th class="mbx-th">Datum</th>
<th class="mbx-th" style="padding:0;"></th>
</tr>
</thead>
{{-- Skeleton tbody: via Custom-Events gesteuert --}}
<tbody style="display:none"
@mw-skel-show.window="$el.style.display='table-row-group'"
@mw-skel-hide.window="$el.style.display='none'">
@for($i = 0; $i < 7; $i++)
@php
$senderW = [55,75,45,82,50,70,42,78,60,68][$i];
$subjW = [72,88,55,92,65,80,60,85,70,78][$i];
$delay = round($i * 0.09, 2);
$delay2 = round($i * 0.09 + 0.12, 2);
@endphp
<tr style="border-bottom:1px solid var(--mw-b1);">
<td style="padding:11px 10px 11px 16px;">
<div style="width:15px;height:15px;border-radius:4px;background:var(--mw-b2);"></div>
</td>
<td style="padding:0;text-align:center;">
<div style="width:7px;height:7px;border-radius:50%;background:var(--mw-b1);margin:0 auto;"></div>
</td>
<td style="padding:0 4px;text-align:center;">
<div style="width:13px;height:13px;border-radius:3px;background:var(--mw-b2);margin:0 auto;"></div>
</td>
<td style="padding:11px 10px 11px 0;">
<div style="width:{{ $senderW }}%;height:11px;border-radius:5px;background:var(--mw-b2);
animation:skel-pulse 1.6s ease-in-out {{ $delay }}s infinite;"></div>
</td>
<td style="padding:11px 10px 11px 0;">
<div style="width:{{ $subjW }}%;height:11px;border-radius:5px;background:var(--mw-b2);
animation:skel-pulse 1.6s ease-in-out {{ $delay2 }}s infinite;"></div>
</td>
<td style="padding:11px 8px;">
<div style="width:75%;height:11px;border-radius:5px;background:var(--mw-b2);
animation:skel-pulse 1.6s ease-in-out {{ $delay }}s infinite;"></div>
</td>
<td style="padding:11px 6px;text-align:center;">
<div style="width:22px;height:22px;border-radius:5px;background:var(--mw-b1);margin:0 auto;"></div>
</td>
</tr>
@endfor
</tbody>
{{-- Echter Inhalt tbody --}}
<tbody @mw-skel-show.window="$el.style.display='none'"
@mw-skel-hide.window="$el.style.display='table-row-group'">
@if(empty($messages))
<tr>
<td colspan="7" style="padding:56px 24px;text-align:center;color:var(--mw-t4);font-size:13px;">
<svg width="36" height="36" viewBox="0 0 14 14" fill="none" style="display:block;margin:0 auto 14px;opacity:.2;">
<rect x=".5" y="2.5" width="13" height="9" rx="1.5" stroke="currentColor" stroke-width="1.2"/>
<path d="M.5 5l6.5 4 6.5-4" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/>
</svg>
Keine Nachrichten
</td>
</tr>
@else
@foreach($messages as $msg)
@php
$uid = $msg['uid'];
$unseen = !($msg['seen'] ?? true);
$msgCat = $msg['category'] ?? 'general';
if ($hasTabs && $tab !== 'all' && $msgCat !== $tab) continue;
$rowUrl = $isDrafts
? route('ui.webmail.compose', ['draftUid'=>$uid,'draftFolder'=>$folder])
: route('ui.webmail.view', ['uid'=>$uid,'folder'=>$folder]);
$sName = $msg['from_name'] ?: $msg['from'];
$sEmail = $msg['from'];
@endphp
<tr class="mbx-tr"
:class="{ 'mbx-tr-selected': selected.includes({{ $uid }}) }"
style="cursor:pointer;{{ $unseen ? 'font-weight:600;' : '' }}"
onclick="if(!event.target.closest('[data-noclick]')) Livewire.navigate('{{ $rowUrl }}')"
@contextmenu.prevent="showCtx({{ $uid }}, {{ $unseen ? 'false' : 'true' }}, $event.clientX, $event.clientY)">
{{-- Checkbox --}}
<td class="mbx-td" style="padding:0 10px 0 16px;" data-noclick>
<input type="checkbox" class="mbx-cbx"
:checked="selected.includes({{ $uid }})"
@change="toggle({{ $uid }})" @click.stop>
</td>
{{-- Ungelesen-Dot --}}
<td style="padding:0;vertical-align:middle;">
@if($unseen)
<span style="display:inline-block;width:7px;height:7px;border-radius:50%;
background:var(--mw-v2);box-shadow:0 0 6px var(--mw-v2);"></span>
@endif
</td>
{{-- Stern --}}
<td class="mbx-td" style="padding:0 4px;" data-noclick>
@if($isDrafts)
<button wire:click="deleteDraft({{ $uid }})" wire:confirm="Entwurf löschen?" @click.stop
style="background:none;border:none;cursor:pointer;padding:2px;font-size:12px;line-height:1;color:var(--mw-t4);">✕</button>
@else
<button wire:click="toggleFlag({{ $uid }})" @click.stop
style="background:none;border:none;cursor:pointer;padding:2px;font-size:13px;line-height:1;
color:{{ ($msg['flagged'] ?? false) ? '#f59e0b' : 'var(--mw-b2)' }};">★</button>
@endif
</td>
{{-- Absender (mit Hover-Tooltip nur auf dem Namen) --}}
<td class="mbx-td" data-noclick
style="overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:pointer;
{{ $unseen ? 'color:var(--mw-v2);' : 'color:var(--mw-t3);font-size:12px;' }}"
onclick="Livewire.navigate('{{ $rowUrl }}')">
@if($isDrafts)
{{ $msg['to'] ?? '—' }}
@else
<span style="display:inline-block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;"
@mouseenter.stop="showTip(@js($sName), @js($sEmail), $event.currentTarget)"
@mouseleave.stop="tipShow = false">{{ $sName }}</span>
@endif
</td>
{{-- Betreff --}}
<td class="mbx-td" style="overflow:hidden;text-overflow:ellipsis;white-space:nowrap;{{ $unseen ? 'color:var(--mw-t1);' : '' }}">
<span style="display:inline-flex;align-items:center;gap:5px;max-width:100%;overflow:hidden;">
<span style="overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">{{ $msg['subject'] ?: '(kein Betreff)' }}</span>
@if($msg['flagged'] ?? false)
<span style="color:#f59e0b;font-size:11px;flex-shrink:0;">★</span>
@endif
@if($msg['has_attachments'] ?? false)
<svg width="11" height="11" viewBox="0 0 14 14" fill="none" style="flex-shrink:0;opacity:.5;"
title="Hat Anhänge">
<path d="M12 6.5L6.8 11.7a3.18 3.18 0 01-4.5-4.5l5.5-5.5a2.12 2.12 0 013 3L5.3 10.2a1.06 1.06 0 01-1.5-1.5L9 3.5" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
@endif
</span>
</td>
{{-- Datum --}}
<td class="mbx-td mbx-td-muted" style="white-space:nowrap;font-size:11.5px;padding-right:4px;">
{{ $msg['date'] ? \Carbon\Carbon::parse($msg['date'])->format('d.m. H:i') : '—' }}
</td>
{{-- ··· Aktionen --}}
<td style="padding:0 6px 0 0;vertical-align:middle;text-align:right;" data-noclick
x-data="{ open: false, tx: 0, ty: 0 }"
@close-row-act.window="open = false"
:class="open ? 'mbx-row-acts-open' : 'mbx-row-acts'">
<button class="mbx-row-acts-btn"
@click.stop="
const btn = $event.currentTarget;
$dispatch('close-row-act');
$nextTick(() => {
const r = btn.getBoundingClientRect();
tx = Math.max(4, r.right - 190);
ty = r.bottom + 4;
open = true;
});">
<svg width="13" height="13" viewBox="0 0 14 14" fill="none">
<circle cx="2.5" cy="7" r="1.2" fill="currentColor"/>
<circle cx="7" cy="7" r="1.2" fill="currentColor"/>
<circle cx="11.5" cy="7" r="1.2" fill="currentColor"/>
</svg>
</button>
<template x-teleport="body">
<div x-show="open" x-cloak @click.outside="open=false"
x-transition:enter="transition ease-out duration-100"
x-transition:enter-start="opacity-0 scale-95"
x-transition:enter-end="opacity-100 scale-100"
x-transition:leave="transition ease-in duration-75"
x-transition:leave-end="opacity-0 scale-95"
:style="`position:fixed;top:${ty}px;left:${tx}px;z-index:9999;min-width:190px;
background:var(--mw-bg);border:1px solid var(--mw-b1);border-radius:9px;
box-shadow:0 8px 24px rgba(0,0,0,.32);padding:4px;`">
@if(!$isDrafts)
@if($unseen)
<button @click.stop="$wire.bulkMarkSeen([{{ $uid }}]); open=false"
style="display:flex;align-items:center;gap:8px;width:100%;text-align:left;padding:7px 11px;border:none;background:none;cursor:pointer;border-radius:6px;font-size:12.5px;color:var(--mw-t2);"
onmouseover="this.style.background='var(--mw-bg3)'" onmouseout="this.style.background='none'">
<svg width="11" height="11" viewBox="0 0 14 14" fill="none"><path d="M1 7l3.5 3.5L13 3" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
Als gelesen markieren
</button>
@else
<button @click.stop="$wire.bulkMarkUnseen([{{ $uid }}]); open=false"
style="display:flex;align-items:center;gap:8px;width:100%;text-align:left;padding:7px 11px;border:none;background:none;cursor:pointer;border-radius:6px;font-size:12.5px;color:var(--mw-t2);"
onmouseover="this.style.background='var(--mw-bg3)'" onmouseout="this.style.background='none'">
<svg width="11" height="11" viewBox="0 0 14 14" fill="none"><rect x=".5" y="2.5" width="13" height="9" rx="1.5" stroke="currentColor" stroke-width="1.2"/><path d="M.5 5l6.5 4 6.5-4" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg>
Als ungelesen markieren
</button>
@endif
<div style="position:relative;" x-data="{ mv:false }" @click.outside.stop="mv=false">
<button @click.stop="mv=!mv"
style="display:flex;align-items:center;justify-content:space-between;width:100%;text-align:left;padding:7px 11px;border:none;background:none;cursor:pointer;border-radius:6px;font-size:12.5px;color:var(--mw-t2);"
onmouseover="this.style.background='var(--mw-bg3)'" onmouseout="this.style.background='none'">
<span style="display:flex;align-items:center;gap:8px;">
<svg width="11" height="11" viewBox="0 0 14 14" fill="none"><path d="M1 7h9M7 4l3 3-3 3" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg>
Verschieben nach
</span>
<svg width="8" height="8" viewBox="0 0 14 14" fill="none" :style="mv?'transform:rotate(90deg)':''"><path d="M5 3l4 4-4 4" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
</button>
<div x-show="mv" x-cloak x-transition
style="position:absolute;left:calc(100% + 4px);top:0;z-index:10000;min-width:150px;
background:var(--mw-bg);border:1px solid var(--mw-b1);border-radius:9px;
box-shadow:0 6px 20px rgba(0,0,0,.28);padding:4px;">
@foreach($moveTargets as $key => $label)
<button @click.stop="$wire.bulkMoveTo([{{ $uid }}],'{{ $key }}'); open=false; mv=false"
style="display:flex;align-items:center;width:100%;text-align:left;padding:7px 11px;border:none;background:none;cursor:pointer;border-radius:6px;font-size:12.5px;color:var(--mw-t2);"
onmouseover="this.style.background='var(--mw-bg3)'" onmouseout="this.style.background='none'">{{ $label }}</button>
@endforeach
</div>
</div>
@endif
<div style="height:1px;background:var(--mw-b1);margin:3px 0;"></div>
<button @click.stop="if(confirm('{{ $isTrash ? 'Endgültig löschen?' : 'In Papierkorb?' }}')) { $wire.bulkDelete([{{ $uid }}]); open=false; }"
style="display:flex;align-items:center;gap:8px;width:100%;text-align:left;padding:7px 11px;border:none;background:none;cursor:pointer;border-radius:6px;font-size:12.5px;color:var(--mw-rd);"
onmouseover="this.style.background='var(--mw-rdbg)'" onmouseout="this.style.background='none'">
<svg width="11" height="11" viewBox="0 0 14 14" fill="none"><path d="M2 3.5h10M5 3.5V2h4v1.5M5.5 6v4.5M8.5 6v4.5" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/><path d="M3 3.5l.7 8h6.6l.7-8" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg>
{{ $isTrash ? 'Endgültig löschen' : 'In Papierkorb' }}
</button>
</div>
</template>
</td>
</tr>
@endforeach
@endif
</tbody>
</table>
@if($total > $perPage)
<div wire:loading.remove wire:target="{{ $wt }}"
style="display:flex;align-items:center;justify-content:space-between;padding:10px 16px;border-top:1px solid var(--mw-b1);">
<span style="font-size:12px;color:var(--mw-t4);">
{{ ($page-1)*$perPage+1 }}{{ min($page*$perPage,$total) }} von {{ $total }}
</span>
<div style="display:flex;gap:6px;">
<button wire:click="prevPage" @disabled($page<=1) class="mbx-act-btn mbx-act-muted"></button>
<button wire:click="nextPage" @disabled($page*$perPage>=$total) class="mbx-act-btn mbx-act-muted"></button>
</div>
</div>
@endif
</div>{{-- /mbx-section --}}
{{-- ═══ SENDER-TOOLTIP (position:fixed, kein x-teleport) ═══ --}}
<div x-show="tipShow" x-cloak
style="pointer-events:none;"
:style="`position:fixed;top:${tipY}px;left:${tipX}px;z-index:8000;
background:var(--mw-bg);border:1px solid var(--mw-b1);border-radius:8px;
box-shadow:0 4px 16px rgba(0,0,0,.25);padding:8px 12px;min-width:180px;max-width:280px;`">
<div style="font-size:13px;font-weight:600;color:var(--mw-t1);" x-text="tipName"></div>
<div style="font-size:12px;color:var(--mw-t4);margin-top:2px;" x-text="tipEmail"></div>
</div>
{{-- ═══ RECHTSKLICK-MENÜ (position:fixed, kein x-teleport) ═══ --}}
<div x-show="ctxOpen" x-cloak
@click.stop
x-transition:enter="transition ease-out duration-100"
x-transition:enter-start="opacity-0 scale-95"
x-transition:enter-end="opacity-100 scale-100"
x-transition:leave="transition ease-in duration-75"
x-transition:leave-end="opacity-0 scale-95"
:style="`position:fixed;top:${ctxY}px;left:${ctxX}px;z-index:9998;min-width:190px;
background:var(--mw-bg);border:1px solid var(--mw-b1);border-radius:9px;
box-shadow:0 8px 24px rgba(0,0,0,.32);padding:4px;`">
@if(!$isDrafts)
@php $btnStyle = "display:flex;align-items:center;gap:8px;width:100%;text-align:left;padding:7px 11px;border:none;background:none;cursor:pointer;border-radius:6px;font-size:12.5px;color:var(--mw-t2);"; @endphp
<template x-if="ctxSeen">
<button @click="$wire.bulkMarkUnseen([ctxUid]); ctxOpen=false"
style="{{ $btnStyle }}"
onmouseover="this.style.background='var(--mw-bg3)'" onmouseout="this.style.background='none'">
<svg width="11" height="11" viewBox="0 0 14 14" fill="none" style="flex-shrink:0;"><rect x=".5" y="2.5" width="13" height="9" rx="1.5" stroke="currentColor" stroke-width="1.2"/><path d="M.5 5l6.5 4 6.5-4" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg>
Als ungelesen markieren
</button>
</template>
<template x-if="!ctxSeen">
<button @click="$wire.bulkMarkSeen([ctxUid]); ctxOpen=false"
style="{{ $btnStyle }}"
onmouseover="this.style.background='var(--mw-bg3)'" onmouseout="this.style.background='none'">
<svg width="11" height="11" viewBox="0 0 14 14" fill="none" style="flex-shrink:0;"><path d="M1 7l3.5 3.5L13 3" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
Als gelesen markieren
</button>
</template>
@endif
<div style="height:1px;background:var(--mw-b1);margin:3px 0;"></div>
<button @click="$wire.bulkDelete([ctxUid]); ctxOpen=false"
style="display:flex;align-items:center;gap:8px;width:100%;text-align:left;padding:7px 11px;border:none;background:none;cursor:pointer;border-radius:6px;font-size:12.5px;color:var(--mw-rd);"
onmouseover="this.style.background='var(--mw-rdbg)'" onmouseout="this.style.background='none'">
<svg width="11" height="11" viewBox="0 0 14 14" fill="none"><path d="M2 3.5h10M5 3.5V2h4v1.5M5.5 6v4.5M8.5 6v4.5" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/><path d="M3 3.5l.7 8h6.6l.7-8" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg>
{{ $isTrash ? 'Endgültig löschen' : 'In Papierkorb' }}
</button>
</div>
</div>
</div>