feat: E-Mail Templates neu gestaltet + Mail-Preview unter /admin/mail-preview

Einheitliches Design für alle Templates:
- Neues Layout: weißes Card, 3px Indigo-Gradient-Akzentbalken, aziros-Wordmark
- Icon-Badge pro Template (52px, border-radius:14px, thematische Farbe)
- Konsistente Typografie, Info-Boxen, Button-Stil
- reset-password, smtp-test, aria-composed auf @extends migriert

Preview-Route: /admin/mail-preview (Index) + /admin/mail-preview/{template}
→ Alle 8 Templates mit Fake-Daten in einer skalierten Vorschau-Grid-Ansicht.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
main
boban 2026-04-20 20:20:29 +02:00
parent b8afe0cb70
commit cd2e466f09
13 changed files with 426 additions and 236 deletions

View File

@ -2,26 +2,32 @@
@section('content') @section('content')
<div style="text-align:center;margin-bottom:20px;"> {{-- Icon --}}
<x-heroicon-o-gift width="65" <table cellpadding="0" cellspacing="0" role="presentation" style="margin:0 auto 28px;">
style="opacity:0.8;stroke:#4f46e5;stroke-width:1" /> <tr>
</div> <td style="width:52px;height:52px;background:#EEF2FF;border-radius:14px;text-align:center;vertical-align:middle;">
<x-heroicon-o-star style="width:24px;height:24px;stroke:#4F46E5;stroke-width:1.5;display:block;margin:14px auto;" />
</td>
</tr>
</table>
<h2 style="margin:0 0 10px;font-size:22px;color:#111;text-align:center;"> {{-- Title --}}
Du hast {{ $credits }} Credits verdient! <h1 style="margin:0 0 8px;font-size:22px;font-weight:700;color:#111827;text-align:center;line-height:1.3;letter-spacing:-0.3px;">
</h2> Dein Referral hat sich qualifiziert!
</h1>
<p style="margin:0 0 20px;color:#6b7280;font-size:14px;text-align:center;line-height:1.6;"> <p style="margin:0 0 24px;font-size:14px;color:#6B7280;text-align:center;line-height:1.6;">
<strong>{{ $referredUser->name }}</strong> nutzt Aziros jetzt seit 3 Monaten <strong style="color:#374151;">{{ $referredUser->name }}</strong> nutzt Aziros jetzt seit 3 Monaten.
dein Referral hat sich qualifiziert!
</p> </p>
<div style="background:#EEF2FF;border-radius:12px;padding:20px;margin:24px 0;text-align:center;"> {{-- Credits badge --}}
<div style="font-size:36px;font-weight:700;color:#4F46E5;">+{{ $credits }}</div> <div style="background:#EEF2FF;border:1px solid #C7D2FE;border-radius:12px;padding:22px 20px;margin-bottom:28px;text-align:center;">
<div style="font-size:14px;color:#6B7280;">Credits wurden deinem Konto gutgeschrieben</div> <p style="margin:0 0 4px;font-size:11px;color:#818CF8;text-transform:uppercase;letter-spacing:0.6px;font-weight:600;">Gutschrift</p>
<p style="margin:0 0 4px;font-size:36px;font-weight:800;color:#4F46E5;line-height:1;letter-spacing:-1px;">+{{ $credits }}</p>
<p style="margin:0;font-size:13px;color:#6B7280;">Credits wurden deinem Konto gutgeschrieben</p>
</div> </div>
<x-mail.button url="{{ config('app.url') }}/settings?tab=affiliate"> {{-- CTA --}}
<x-mail.button :url="config('app.url') . '/settings?tab=affiliate'">
Mein Affiliate-Dashboard Mein Affiliate-Dashboard
</x-mail.button> </x-mail.button>

View File

@ -2,25 +2,31 @@
@section('content') @section('content')
<div style="text-align:center;margin-bottom:20px;"> {{-- Icon --}}
<x-heroicon-o-chat-bubble-left-right width="55" <table cellpadding="0" cellspacing="0" role="presentation" style="margin:0 auto 28px;">
style="opacity:0.8;stroke:#4f46e5;stroke-width:1" /> <tr>
</div> <td style="width:52px;height:52px;background:#EEF2FF;border-radius:14px;text-align:center;vertical-align:middle;">
<x-heroicon-o-chat-bubble-left-right style="width:24px;height:24px;stroke:#4F46E5;stroke-width:1.5;display:block;margin:14px auto;" />
</td>
</tr>
</table>
<h2 style="margin:0 0 6px;font-size:22px;color:#111;text-align:center;"> {{-- Title --}}
Nachricht <h1 style="margin:0 0 4px;font-size:22px;font-weight:700;color:#111827;text-align:center;line-height:1.3;letter-spacing:-0.3px;">
</h2> Neue Nachricht
</h1>
<p style="margin:0 0 24px;color:#9ca3af;font-size:13px;text-align:center;"> <p style="margin:0 0 28px;font-size:13px;color:#9CA3AF;text-align:center;">
von {{ $sender_name }} von {{ $sender_name }}
</p> </p>
<p style="margin:0 0 6px;font-size:11px;color:#9ca3af;text-transform:uppercase;letter-spacing:0.5px;"> {{-- Recipient label --}}
<p style="margin:0 0 8px;font-size:11px;color:#9CA3AF;text-transform:uppercase;letter-spacing:0.6px;font-weight:600;">
Nachricht an {{ $recipient_name }} Nachricht an {{ $recipient_name }}
</p> </p>
<div style="background:#f8fafc;border-radius:12px;padding:20px;margin-bottom:20px;"> {{-- Message box --}}
<p style="margin:0;font-size:14px;color:#374151;line-height:1.6;">{{ $message }}</p> <div style="background:#F9FAFB;border:1px solid #F3F4F6;border-radius:12px;padding:20px;margin-bottom:0;">
<p style="margin:0;font-size:14px;color:#374151;line-height:1.7;">{{ $message }}</p>
</div> </div>
@endsection @endsection

View File

@ -2,55 +2,70 @@
@section('content') @section('content')
<div style="text-align:center;margin-bottom:20px;"> {{-- Icon --}}
<x-heroicon-o-calendar-days width="55" <table cellpadding="0" cellspacing="0" role="presentation" style="margin:0 auto 28px;">
style="opacity:0.8;stroke:#4f46e5;stroke-width:1" /> <tr>
</div> <td style="width:52px;height:52px;background:#EEF2FF;border-radius:14px;text-align:center;vertical-align:middle;">
<x-heroicon-o-calendar-days style="width:24px;height:24px;stroke:#4F46E5;stroke-width:1.5;display:block;margin:14px auto;" />
</td>
</tr>
</table>
<h2 style="margin:0 0 6px;font-size:22px;color:#111;text-align:center;"> {{-- Title --}}
<h1 style="margin:0 0 4px;font-size:22px;font-weight:700;color:#111827;text-align:center;line-height:1.3;letter-spacing:-0.3px;">
Terminerinnerung Terminerinnerung
</h2> </h1>
<p style="margin:0 0 28px;font-size:13px;color:#9CA3AF;text-align:center;">
<p style="margin:0 0 24px;color:#9ca3af;font-size:13px;text-align:center;">
von {{ $sender_name }} von {{ $sender_name }}
</p> </p>
{{-- Event Details --}} {{-- Event card --}}
<div style="background:#f8fafc;border-radius:12px;padding:20px;margin-bottom:20px;"> <div style="background:#F9FAFB;border:1px solid #F3F4F6;border-radius:12px;padding:20px 20px 16px;margin-bottom:20px;">
<table width="100%" style="font-size:14px;color:#374151;"> <table width="100%" cellpadding="0" cellspacing="0" role="presentation">
<tr> <tr>
<td style="padding:6px 0;color:#9ca3af;width:80px;">Termin</td> <td style="padding:5px 0 5px;width:72px;font-size:12px;color:#9CA3AF;vertical-align:top;">Termin</td>
<td style="padding:6px 0;font-weight:600;">{{ $event_title }}</td> <td style="padding:5px 0 5px;font-size:14px;color:#111827;font-weight:600;">{{ $event_title }}</td>
</tr> </tr>
<tr> <tr>
<td style="padding:6px 0;color:#9ca3af;">Datum</td> <td style="padding:5px 0;height:1px;" colspan="2">
<td style="padding:6px 0;">{{ $event_date }}</td> <div style="height:1px;background:#F3F4F6;"></div>
</td>
</tr> </tr>
<tr> <tr>
<td style="padding:6px 0;color:#9ca3af;">Uhrzeit</td> <td style="padding:5px 0;font-size:12px;color:#9CA3AF;vertical-align:top;">Datum</td>
<td style="padding:6px 0;"> <td style="padding:5px 0;font-size:13px;color:#374151;">{{ $event_date }}</td>
{{ $event_time }}@if(!empty($event_end)) - {{ $event_end }}@endif Uhr </tr>
<tr>
<td style="padding:5px 0;font-size:12px;color:#9CA3AF;vertical-align:top;">Uhrzeit</td>
<td style="padding:5px 0;font-size:13px;color:#374151;">
{{ $event_time }}@if(!empty($event_end)) &ndash; {{ $event_end }}@endif Uhr
</td> </td>
</tr> </tr>
@if(!empty($event_notes)) @if(!empty($event_notes))
<tr> <tr>
<td style="padding:6px 0;color:#9ca3af;vertical-align:top;">Info</td> <td style="padding:5px 0;height:1px;" colspan="2">
<td style="padding:6px 0;">{{ $event_notes }}</td> <div style="height:1px;background:#F3F4F6;"></div>
</td>
</tr>
<tr>
<td style="padding:5px 0;font-size:12px;color:#9CA3AF;vertical-align:top;">Info</td>
<td style="padding:5px 0;font-size:13px;color:#374151;line-height:1.5;">{{ $event_notes }}</td>
</tr> </tr>
@endif @endif
</table> </table>
</div> </div>
{{-- Persönliche Nachricht --}} {{-- Personal message --}}
@if(!empty($message)) @if(!empty($message))
<div style="border-left:3px solid #4f46e5;padding:12px 16px;margin-bottom:20px;background:#f8fafc;border-radius:0 8px 8px 0;"> <div style="border-left:3px solid #4F46E5;padding:12px 16px;background:#F9FAFB;border-radius:0 10px 10px 0;margin-bottom:24px;">
<p style="margin:0 0 4px;font-size:11px;color:#9ca3af;text-transform:uppercase;letter-spacing:0.5px;">Nachricht</p> <p style="margin:0 0 3px;font-size:10px;color:#9CA3AF;text-transform:uppercase;letter-spacing:0.6px;font-weight:600;">Nachricht</p>
<p style="margin:0;font-size:14px;color:#374151;line-height:1.5;">{{ $message }}</p> <p style="margin:0;font-size:13px;color:#374151;line-height:1.6;">{{ $message }}</p>
</div> </div>
@endif @endif
<p style="text-align:center;font-size:12px;color:#d1d5db;margin-top:24px;"> {{-- Recipient note --}}
Hallo {{ $recipient_name }}, dies ist eine automatische Terminerinnerung. <p style="margin:0;text-align:center;font-size:11px;color:#D1D5DB;line-height:1.6;">
Hallo {{ $recipient_name }} &mdash; dies ist eine automatische Terminerinnerung.
</p> </p>
@endsection @endsection

View File

@ -1,3 +1,26 @@
<p>{!! nl2br(e($body)) !!}</p> @extends('emails.layout')
<hr style="margin: 24px 0; border: none; border-top: 1px solid #eee;">
<p style="font-size: 12px; color: #999;">Gesendet von Aria · aziros.com</p> @section('content')
{{-- Icon --}}
<table cellpadding="0" cellspacing="0" role="presentation" style="margin:0 auto 28px;">
<tr>
<td style="width:52px;height:52px;background:#EEF2FF;border-radius:14px;text-align:center;vertical-align:middle;">
<x-heroicon-o-sparkles style="width:24px;height:24px;stroke:#4F46E5;stroke-width:1.5;display:block;margin:14px auto;" />
</td>
</tr>
</table>
{{-- Message body --}}
<div style="font-size:14px;color:#374151;line-height:1.7;">
{!! nl2br(e($body)) !!}
</div>
{{-- Sent by footer --}}
<div style="margin-top:24px;padding-top:18px;border-top:1px solid #F3F4F6;">
<p style="margin:0;font-size:11px;color:#D1D5DB;text-align:center;letter-spacing:0.2px;">
Gesendet von <strong style="color:#9CA3AF;">Aria</strong> &middot; aziros.com
</p>
</div>
@endsection

View File

@ -2,27 +2,32 @@
@section('content') @section('content')
<div style="text-align:center;margin-bottom:20px;"> {{-- Icon --}}
<x-heroicon-o-envelope width="65" <table cellpadding="0" cellspacing="0" role="presentation" style="margin:0 auto 28px;">
style="opacity:0.8;stroke:#4f46e5;stroke-width:1" /> <tr>
</div> <td style="width:52px;height:52px;background:#EEF2FF;border-radius:14px;text-align:center;vertical-align:middle;">
<x-heroicon-o-envelope style="width:24px;height:24px;stroke:#4F46E5;stroke-width:1.5;display:block;margin:14px auto;" />
</td>
</tr>
</table>
<h2 style="margin:0 0 10px;font-size:22px;color:#111;text-align:center;"> {{-- Title --}}
<h1 style="margin:0 0 8px;font-size:22px;font-weight:700;color:#111827;text-align:center;line-height:1.3;letter-spacing:-0.3px;">
{{ t('mail.auth.verify.title') }} {{ t('mail.auth.verify.title') }}
</h2> </h1>
<p style="margin:0 0 28px;font-size:14px;color:#6B7280;text-align:center;line-height:1.6;">
<p style="margin:0 0 20px;color:#6b7280;font-size:14px;text-align:center;">
{{ t('mail.auth.verify.text') }} {{ t('mail.auth.verify.text') }}
</p> </p>
{{-- BUTTON --}} {{-- Button --}}
@if(!empty($url)) @if(!empty($url))
<x-mail.button :url="$url"> <x-mail.button :url="$url">
{{ t('mail.auth.verify.button') }} {{ t('mail.auth.verify.button') }}
</x-mail.button> </x-mail.button>
@endif @endif
<p style="text-align:center;font-size:13px;color:#9ca3af;"> {{-- Expiry --}}
<p style="margin:20px 0 0;text-align:center;font-size:12px;color:#9CA3AF;line-height:1.6;">
{{ t('mail.auth.verify.expires') }} {{ t('mail.auth.verify.expires') }}
</p> </p>

View File

@ -1,14 +1,6 @@
<div style="text-align:center;margin-top:10px;"> <p style="margin:28px 0 0;text-align:center;">
<a href="{{ $url }}" <a href="{{ $url }}"
style=" style="display:inline-block;background:#4F46E5;color:#ffffff;padding:14px 32px;border-radius:10px;text-decoration:none;font-size:14px;font-weight:600;letter-spacing:0.1px;line-height:1;">
display:inline-block;
padding:12px 20px;
background:#4f46e5;
color:#fff;
border-radius:8px;
text-decoration:none;
font-size:14px;
">
{{ $slot }} {{ $slot }}
</a> </a>
</div> </p>

View File

@ -1,25 +1,13 @@
<table align="center" cellpadding="0" cellspacing="0" style="margin:25px auto;"> <table cellpadding="0" cellspacing="0" role="presentation" style="margin:28px auto;">
<tr> <tr>
@foreach(str_split($slot) as $index => $digit) @foreach(str_split($slot) as $digit)
<td align="center"
<td align="center" style=" style="width:46px;height:56px;background:#F4F6FB;border:1px solid #E5E7EB;border-radius:12px;font-size:24px;font-weight:700;color:#111827;letter-spacing:-0.5px;">
width:44px;
height:52px;
font-size:22px;
font-weight:600;
color:#111;
background:#f3f4f6;
border-radius:10px;
box-shadow:0 2px 6px rgba(0,0,0,0.05);
">
{{ $digit }} {{ $digit }}
</td> </td>
{{-- Abstand --}}
@if(!$loop->last) @if(!$loop->last)
<td width="8"></td> <td width="8"></td>
@endif @endif
@endforeach @endforeach
</tr> </tr>
</table> </table>

View File

@ -2,33 +2,37 @@
@section('content') @section('content')
<div style="text-align:center;margin-bottom:20px;"> {{-- Icon --}}
<x-heroicon-o-gift width="65" <table cellpadding="0" cellspacing="0" role="presentation" style="margin:0 auto 28px;">
style="opacity:0.8;stroke:#4f46e5;stroke-width:1" /> <tr>
<td style="width:52px;height:52px;background:#F0FDF4;border-radius:14px;text-align:center;vertical-align:middle;">
<x-heroicon-o-gift style="width:24px;height:24px;stroke:#10B981;stroke-width:1.5;display:block;margin:14px auto;" />
</td>
</tr>
</table>
{{-- Title --}}
<h1 style="margin:0 0 8px;font-size:22px;font-weight:700;color:#111827;text-align:center;line-height:1.3;letter-spacing:-0.3px;">
Hallo {{ $user->name }}!
</h1>
<p style="margin:0 0 24px;font-size:14px;color:#6B7280;text-align:center;line-height:1.6;">
Du hast kostenlosen Zugang zum
<strong style="color:#4F46E5;">{{ $plan->name }}</strong>-Plan erhalten &mdash; {{ $durationLabel }}.
</p>
{{-- Validity badge --}}
<div style="background:#F0FDF4;border:1px solid #D1FAE5;border-radius:12px;padding:18px 20px;margin-bottom:28px;text-align:center;">
@if($endsAt)
<p style="margin:0 0 3px;font-size:11px;color:#6EE7B7;text-transform:uppercase;letter-spacing:0.6px;font-weight:600;">Gültig bis</p>
<p style="margin:0;font-size:20px;font-weight:700;color:#059669;">{{ $endsAt->format('d.m.Y') }}</p>
@else
<p style="margin:0 0 3px;font-size:11px;color:#6EE7B7;text-transform:uppercase;letter-spacing:0.6px;font-weight:600;">Gültigkeit</p>
<p style="margin:0;font-size:18px;font-weight:700;color:#059669;">Unbegrenzt</p>
@endif
</div> </div>
<h2 style="margin:0 0 10px;font-size:22px;color:#111;text-align:center;"> {{-- CTA --}}
Hallo {{ $user->name }}! <x-mail.button :url="config('app.url') . '/agent'">
</h2>
<p style="margin:0 0 20px;color:#6b7280;font-size:14px;text-align:center;line-height:1.6;">
Du hast kostenlosen Zugang zum
<strong style="color:#4F46E5;">{{ $plan->name }}</strong>
erhalten {{ $durationLabel }}.
</p>
@if($endsAt)
<p style="margin:0 0 20px;color:#6b7280;font-size:13px;text-align:center;">
Dein Zugang ist gültig bis:
<strong>{{ $endsAt->format('d.m.Y') }}</strong>
</p>
@else
<p style="margin:0 0 20px;color:#6b7280;font-size:13px;text-align:center;">
Dein Zugang ist <strong>unbegrenzt gültig</strong>.
</p>
@endif
<x-mail.button url="{{ config('app.url') }}/agent">
Jetzt Aria nutzen Jetzt Aria nutzen
</x-mail.button> </x-mail.button>

View File

@ -1,30 +1,56 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html lang="de">
<body style="margin:0;background:#f4f6fb;font-family:Arial,sans-serif;"> <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Aziros</title>
</head>
<body style="margin:0;padding:0;background:#F4F6FB;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;">
<table width="100%"> <table width="100%" cellpadding="0" cellspacing="0" role="presentation" style="background:#F4F6FB;padding:48px 16px;">
<tr><td align="center">
<table width="100%" cellpadding="0" cellspacing="0" role="presentation" style="max-width:560px;">
{{-- Wordmark --}}
<tr> <tr>
<td align="center"> <td style="padding-bottom:20px;padding-left:4px;">
<a href="{{ config('app.url') }}" style="text-decoration:none;">
<table width="100%" style="max-width:520px;background:#fff;border-radius:16px;overflow:hidden;box-shadow:0 20px 40px rgba(0,0,0,0.08);"> <span style="font-size:19px;font-weight:300;color:#111827;letter-spacing:-0.5px;">aziros</span>
</a>
{{-- HEADER --}}
@include('emails.components.header')
{{-- CONTENT --}}
<tr>
<td style="padding:32px;">
@yield('content')
</td> </td>
</tr> </tr>
{{-- FOOTER --}} {{-- Card --}}
@include('emails.components.footer') <tr>
<td style="background:#ffffff;border:1px solid #E5E7EB;border-radius:16px;overflow:hidden;box-shadow:0 1px 3px rgba(0,0,0,0.06),0 4px 12px rgba(0,0,0,0.04);">
{{-- Accent bar --}}
<div style="height:3px;background:linear-gradient(90deg,#4F46E5 0%,#818CF8 55%,#C7D2FE 100%);font-size:0;line-height:3px;">&zwnj;</div>
{{-- Content --}}
<div style="padding:40px 40px 36px;">
@yield('content')
</div>
</td>
</tr>
{{-- Footer --}}
<tr>
<td style="padding-top:28px;text-align:center;">
<p style="margin:0 0 4px;font-size:12px;color:#9CA3AF;line-height:1.7;">
Du erhältst diese E-Mail, weil du <strong style="font-weight:500;color:#6B7280;">{{ config('app.name') }}</strong> nutzt.<br>
Falls du sie nicht erwartet hast, kannst du sie ignorieren.
</p>
<p style="margin:0;font-size:11px;color:#D1D5DB;letter-spacing:0.2px;">
&copy; {{ date('Y') }} Aziros GmbH &middot; Made with &#9825; in Austria
</p>
</td>
</tr>
</table> </table>
</td></tr>
</td>
</tr>
</table> </table>
</body> </body>

View File

@ -1,63 +1,35 @@
<!DOCTYPE html> @extends('emails.layout')
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Passwort zurücksetzen</title>
</head>
<body style="margin:0;padding:0;background:#F9FAFB;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;">
<table width="100%" cellpadding="0" cellspacing="0" style="background:#F9FAFB;padding:40px 16px;">
<tr>
<td align="center">
<table width="100%" cellpadding="0" cellspacing="0" style="max-width:560px;">
{{-- Logo --}} @section('content')
{{-- Icon --}}
<table cellpadding="0" cellspacing="0" role="presentation" style="margin:0 auto 28px;">
<tr> <tr>
<td style="padding-bottom:24px;"> <td style="width:52px;height:52px;background:#EEF2FF;border-radius:14px;text-align:center;vertical-align:middle;">
<span style="font-size:22px;font-weight:300;color:#0D0D18;letter-spacing:-0.5px;">aziros</span> <x-heroicon-o-lock-closed style="width:22px;height:22px;stroke:#4F46E5;stroke-width:1.5;display:block;margin:15px auto;" />
</td> </td>
</tr> </tr>
</table>
{{-- Card --}} {{-- Title --}}
<tr> <h1 style="margin:0 0 8px;font-size:22px;font-weight:700;color:#111827;text-align:center;line-height:1.3;letter-spacing:-0.3px;">
<td style="background:#fff;border-radius:16px;border:1px solid #E5E7EB;padding:40px;">
<p style="margin:0 0 8px;font-size:18px;font-weight:600;color:#111827;">
Passwort zurücksetzen Passwort zurücksetzen
</p> </h1>
<p style="margin:0 0 24px;font-size:14px;color:#6B7280;"> <p style="margin:0 0 28px;font-size:14px;color:#6B7280;text-align:center;line-height:1.6;">
Hallo {{ $user->name }}, Hallo {{ $user->name }}, klicke auf den Button um ein neues Passwort zu setzen.
</p>
<p style="margin:0 0 24px;font-size:14px;color:#374151;line-height:1.6;">
Du hast ein Zurücksetzen deines Passworts angefordert.
Klicke auf den Button, um ein neues Passwort zu setzen.
</p> </p>
<a href="{{ $url }}" {{-- Button --}}
style="display:inline-block;background:#4F46E5;color:#fff; <x-mail.button :url="$url">
padding:14px 28px;border-radius:10px;
text-decoration:none;font-size:14px;font-weight:600;">
Passwort zurücksetzen Passwort zurücksetzen
</a> </x-mail.button>
<p style="margin:24px 0 0;font-size:12px;color:#9CA3AF;line-height:1.6;"> {{-- Expiry note --}}
Dieser Link ist <strong>60 Minuten</strong> gültig.<br> <div style="margin-top:24px;background:#F9FAFB;border:1px solid #F3F4F6;border-radius:10px;padding:14px 16px;text-align:center;">
<p style="margin:0;font-size:12px;color:#9CA3AF;line-height:1.7;">
Dieser Link ist <strong style="color:#6B7280;">60 Minuten</strong> gültig.<br>
Falls du kein Passwort-Reset angefordert hast, ignoriere diese E-Mail. Falls du kein Passwort-Reset angefordert hast, ignoriere diese E-Mail.
</p> </p>
</div>
</td> @endsection
</tr>
{{-- Footer --}}
<tr>
<td style="padding-top:24px;text-align:center;font-size:12px;color:#9CA3AF;">
© {{ date('Y') }} Aziros · Made in Austria
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

View File

@ -1,2 +1,30 @@
<p>Dein SMTP Server ist korrekt konfiguriert.</p> @extends('emails.layout')
<p>E-Mails können von Aria in deinem Namen gesendet werden.</p>
@section('content')
{{-- Icon --}}
<table cellpadding="0" cellspacing="0" role="presentation" style="margin:0 auto 28px;">
<tr>
<td style="width:52px;height:52px;background:#F0FDF4;border-radius:14px;text-align:center;vertical-align:middle;">
<x-heroicon-o-check-circle style="width:24px;height:24px;stroke:#10B981;stroke-width:1.5;display:block;margin:14px auto;" />
</td>
</tr>
</table>
{{-- Title --}}
<h1 style="margin:0 0 8px;font-size:22px;font-weight:700;color:#111827;text-align:center;line-height:1.3;letter-spacing:-0.3px;">
SMTP erfolgreich konfiguriert
</h1>
<p style="margin:0 0 24px;font-size:14px;color:#6B7280;text-align:center;line-height:1.6;">
Dein SMTP-Server ist korrekt eingerichtet.<br>
E-Mails können von Aria in deinem Namen versendet werden.
</p>
{{-- Status box --}}
<div style="background:#F0FDF4;border:1px solid #D1FAE5;border-radius:10px;padding:14px 18px;text-align:center;">
<p style="margin:0;font-size:13px;color:#059669;font-weight:500;">
&#10003;&ensp;Verbindung hergestellt
</p>
</div>
@endsection

View File

@ -0,0 +1,62 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mail Preview · Aziros</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; background: #F4F6FB; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; color: #111827; }
.wrapper { max-width: 960px; margin: 0 auto; padding: 48px 24px; }
.header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 36px; }
.logo { font-size: 18px; font-weight: 300; color: #111827; letter-spacing: -0.5px; text-decoration: none; }
.badge { font-size: 11px; background: #EEF2FF; color: #4F46E5; padding: 3px 10px; border-radius: 20px; font-weight: 600; letter-spacing: 0.3px; }
h1 { margin: 0 0 4px; font-size: 26px; font-weight: 700; letter-spacing: -0.5px; }
.subtitle { margin: 0 0 32px; font-size: 14px; color: #6B7280; }
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 16px; }
.card { background: #fff; border: 1px solid #E5E7EB; border-radius: 14px; overflow: hidden; transition: box-shadow 0.15s, border-color 0.15s; text-decoration: none; color: inherit; display: block; }
.card:hover { box-shadow: 0 4px 16px rgba(0,0,0,0.08); border-color: #C7D2FE; }
.preview-frame { width: 100%; height: 200px; border: none; background: #F9FAFB; pointer-events: none; display: block; }
.card-body { padding: 14px 16px; border-top: 1px solid #F3F4F6; }
.card-name { font-size: 13px; font-weight: 600; color: #111827; margin: 0 0 2px; }
.card-path { font-size: 11px; color: #9CA3AF; margin: 0; font-family: 'SF Mono', Menlo, monospace; }
.card-footer { padding: 10px 16px; background: #F9FAFB; border-top: 1px solid #F3F4F6; display: flex; justify-content: flex-end; }
.btn { font-size: 12px; color: #4F46E5; font-weight: 600; text-decoration: none; padding: 5px 12px; background: #EEF2FF; border-radius: 6px; }
.btn:hover { background: #E0E7FF; }
</style>
</head>
<body>
<div class="wrapper">
<div class="header">
<a href="{{ config('app.url') }}" class="logo">aziros</a>
<span class="badge">Mail Preview</span>
</div>
<h1>E-Mail Templates</h1>
<p class="subtitle">{{ count($templates) }} Templates &mdash; Klicke auf eine Karte für die Vollansicht.</p>
<div class="grid">
@foreach($templates as $tpl)
<a href="{{ url('/admin/mail-preview/' . $tpl['key']) }}" class="card" target="_blank">
<iframe
src="{{ url('/admin/mail-preview/' . $tpl['key']) }}"
class="preview-frame"
title="{{ $tpl['name'] }}"
loading="lazy"
style="transform-origin: top left; transform: scale(0.5); width: 200%; height: 400px; margin-bottom: -200px;">
</iframe>
<div class="card-body">
<p class="card-name">{{ $tpl['name'] }}</p>
<p class="card-path">emails/{{ str_replace('.', '/', $tpl['key']) }}.blade.php</p>
</div>
<div class="card-footer">
<span class="btn">Vollansicht &rarr;</span>
</div>
</a>
@endforeach
</div>
</div>
</body>
</html>

View File

@ -22,13 +22,7 @@ use Illuminate\Support\Facades\Route;
Route::get('/mail-preview', function () { // ── Mail Preview (nur Admin) ──────────────────────────────────────────────────
return view('emails.auth.verify', [
'user' => 'Max Mustermann',
'code' => '123456',
'url' => 'https://example.com/verify' // 🔥 hinzufügen
]);
});
Route::middleware(['auth.custom'])->group(function () { Route::middleware(['auth.custom'])->group(function () {
// intentionally empty — kept for middleware reference // intentionally empty — kept for middleware reference
@ -63,6 +57,75 @@ Route::middleware(['user', 'role:admin'])->prefix('admin')->name('admin.')->grou
Route::get('/affiliates', \App\Livewire\Admin\Affiliates\Index::class)->name('affiliates.index'); Route::get('/affiliates', \App\Livewire\Admin\Affiliates\Index::class)->name('affiliates.index');
Route::get('/translations', TranslationIndex::class)->name('translations.index'); Route::get('/translations', TranslationIndex::class)->name('translations.index');
Route::get('/versions', \App\Livewire\Admin\Versions::class)->name('versions.index'); Route::get('/versions', \App\Livewire\Admin\Versions::class)->name('versions.index');
// ── Mail Preview ──────────────────────────────────────────────────────────
$fakeData = [
'auth.verify' => [
'name' => 'E-Mail verifizieren',
'data' => ['url' => 'https://app.aziros.com/verify?token=preview', 'user' => 'Max Mustermann'],
],
'reset-password' => [
'name' => 'Passwort zurücksetzen',
'data' => ['url' => 'https://app.aziros.com/password/reset/preview', 'user' => (object)['name' => 'Max Mustermann']],
],
'agent.reminder' => [
'name' => 'Terminerinnerung',
'data' => [
'sender_name' => 'Maria Muster',
'event_title' => 'Strategie-Meeting Q2',
'event_date' => 'Montag, 22. April 2026',
'event_time' => '14:00',
'event_end' => '15:30',
'event_notes' => 'Bitte die Präsentation vorbereiten.',
'recipient_name' => 'Max Mustermann',
'message' => 'Vergiss bitte nicht, die Unterlagen mitzubringen!',
],
],
'agent.message' => [
'name' => 'Neue Nachricht (Agent)',
'data' => [
'sender_name' => 'Maria Muster',
'recipient_name' => 'Max Mustermann',
'message' => 'Hallo Max, kannst du mir bitte die Unterlagen für das Meeting zukommen lassen? Ich brauche sie bis morgen früh.',
],
],
'gift-access' => [
'name' => 'Geschenk-Zugang',
'data' => [
'user' => (object)['name' => 'Max Mustermann'],
'plan' => (object)['name' => 'Pro'],
'durationLabel' => '3 Monate kostenlos',
'endsAt' => \Carbon\Carbon::now()->addMonths(3),
],
],
'affiliate-qualified' => [
'name' => 'Affiliate qualifiziert',
'data' => [
'credits' => 50,
'referredUser' => (object)['name' => 'Lisa Müller'],
],
],
'smtp-test' => [
'name' => 'SMTP Test',
'data' => [],
],
'aria-composed' => [
'name' => 'Aria Verfasste E-Mail',
'data' => ['body' => "Hallo!\n\nIch habe deine Aufgabe erledigt und hier ist die Zusammenfassung der Ergebnisse für dein Meeting morgen.\n\nBitte prüfe die Agenda und gib mir Bescheid, ob noch Änderungen nötig sind."],
],
];
Route::get('/mail-preview', function () use ($fakeData) {
$templates = collect($fakeData)->map(fn($v, $k) => ['key' => $k, 'name' => $v['name']])->values();
return view('mail-preview.index', compact('templates'));
})->name('mail-preview.index');
Route::get('/mail-preview/{template}', function (string $template) use ($fakeData) {
abort_unless(isset($fakeData[$template]), 404);
$entry = $fakeData[$template];
$view = 'emails.' . str_replace('.', '/', str_replace('-', '-', $template));
return response(view($view, $entry['data']));
})->name('mail-preview.show');
}); });
Route::middleware('user')->group(function () { Route::middleware('user')->group(function () {