237 lines
11 KiB
PHP
237 lines
11 KiB
PHP
@php
|
||
$accent = $get('meta.accent_color') ?? 'indigo';
|
||
$accentColor = match($accent) {
|
||
'emerald' => '#059669',
|
||
'cyberpunk' => '#ec4899',
|
||
'coral' => '#ea580c',
|
||
'amber' => '#d97706',
|
||
default => '#4f46e5',
|
||
};
|
||
$accentGradient = match($accent) {
|
||
'emerald' => 'linear-gradient(135deg, #059669 0%, #10b981 100%)',
|
||
'cyberpunk' => 'linear-gradient(135deg, #ec4899 0%, #f43f5e 100%)',
|
||
'coral' => 'linear-gradient(135deg, #ea580c 0%, #f97316 100%)',
|
||
'amber' => 'linear-gradient(135deg, #d97706 0%, #f59e0b 100%)',
|
||
default => 'linear-gradient(135deg, #4f46e5 0%, #6366f1 100%)',
|
||
};
|
||
$uid = 'mdprev_' . uniqid();
|
||
@endphp
|
||
|
||
{{-- Google Fonts --}}
|
||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Outfit:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
||
|
||
{{-- Marked.js CDN --}}
|
||
<script src="https://cdn.jsdelivr.net/npm/marked@9/marked.min.js"></script>
|
||
|
||
<div id="{{ $uid }}" style="font-family: 'Inter', system-ui, sans-serif;">
|
||
|
||
{{-- Browser Chrome --}}
|
||
<div style="border: 1px solid #e2e8f0; border-radius: 12px; overflow: hidden; box-shadow: 0 4px 24px rgba(0,0,0,0.08); background: #f8fafc; height: 700px; display: flex; flex-direction: column;">
|
||
|
||
{{-- Title Bar --}}
|
||
<div style="background: #f1f5f9; border-bottom: 1px solid #e2e8f0; padding: 10px 16px; display: flex; align-items: center; gap: 12px; flex-shrink: 0;">
|
||
<div style="display: flex; gap: 6px; flex-shrink: 0;">
|
||
<span style="width: 12px; height: 12px; border-radius: 50%; background: #ff5f57; display:inline-block;"></span>
|
||
<span style="width: 12px; height: 12px; border-radius: 50%; background: #febc2e; display:inline-block;"></span>
|
||
<span style="width: 12px; height: 12px; border-radius: 50%; background: #28c840; display:inline-block;"></span>
|
||
</div>
|
||
<div style="flex: 1; max-width: 480px; margin: 0 auto; background: white; border: 1px solid #e2e8f0; border-radius: 6px; padding: 5px 10px; display: flex; align-items: center; gap: 6px; font-size: 12px; color: #94a3b8;">
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="#22c55e" style="width:14px;height:14px;flex-shrink:0;">
|
||
<path fill-rule="evenodd" d="M10 1a4.5 4.5 0 00-4.5 4.5V9H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-.5V5.5A4.5 4.5 0 0010 1zm3 8V5.5a3 3 0 10-6 0V9h6z" clip-rule="evenodd"/>
|
||
</svg>
|
||
<span style="font-family: monospace; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
|
||
truncgil.com/teklif/<strong style="color: #334155;">{{ $get('slug') ?: '...' }}</strong>
|
||
</span>
|
||
</div>
|
||
<div style="width: 60px; flex-shrink: 0;"></div>
|
||
</div>
|
||
|
||
{{-- Page Body --}}
|
||
<div style="flex: 1; overflow-y: auto; background: #f1f5f9; padding: 24px;">
|
||
<div style="max-width: 800px; margin: 0 auto; background: white; border-radius: 12px; box-shadow: 0 1px 3px rgba(0,0,0,0.06); border: 1px solid #e5e7eb; overflow: hidden;">
|
||
|
||
{{-- Accent stripe --}}
|
||
<div style="height: 4px; background: {{ $accentGradient }};"></div>
|
||
|
||
{{-- Document --}}
|
||
<div style="padding: 32px 40px;">
|
||
|
||
{{-- Header --}}
|
||
<div style="margin-bottom: 24px; padding-bottom: 20px; border-bottom: 1px solid #f1f5f9;">
|
||
<div style="display: flex; align-items: center; gap: 8px; margin-bottom: 10px;">
|
||
<span style="font-size: 9px; text-transform: uppercase; letter-spacing: 1.5px; font-weight: 800; padding: 3px 8px; border-radius: 4px; color: white; background: {{ $accentColor }};">TEKNİK VE MALİ TEKLİF</span>
|
||
@if($get('client_name'))
|
||
<span style="font-size: 11px; background: #f8fafc; color: #64748b; font-weight: 600; padding: 3px 8px; border-radius: 4px; border: 1px solid #e2e8f0;">{{ $get('client_name') }}</span>
|
||
@endif
|
||
</div>
|
||
<h1 style="font-family: 'Outfit', sans-serif; font-size: 22px; font-weight: 800; color: #0f172a; margin: 0 0 8px 0; line-height: 1.3;">{{ $get('title') ?: 'Teklif Başlığı' }}</h1>
|
||
<div style="font-size: 11px; color: #94a3b8; font-weight: 500; display: flex; gap: 12px; flex-wrap: wrap;">
|
||
<span>REF: {{ $get('slug') ?: '—' }}</span>
|
||
<span>•</span>
|
||
<span style="font-weight: 700; color: #334155;">{{ $get('total_price') ? number_format((float) $get('total_price'), 2, ',', '.') : '—' }} {{ $get('currency') ?: 'TRY' }}</span>
|
||
<span>•</span>
|
||
<span>Geçerlilik: {{ $get('valid_until') ? date('d.m.Y', strtotime($get('valid_until'))) : '—' }}</span>
|
||
</div>
|
||
</div>
|
||
|
||
{{-- Markdown Output (plain div, updated by vanilla JS) --}}
|
||
<div id="{{ $uid }}_placeholder" style="text-align:center; padding: 60px 0; color: #94a3b8; font-style: italic; font-size: 14px;">
|
||
✏️ Sol taraftaki editöre Markdown yazın, canlı önizleme burada görünecektir.
|
||
</div>
|
||
<div id="{{ $uid }}_body" class="mdprev-body" style="display:none;"></div>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
(function() {
|
||
var uid = '{{ $uid }}';
|
||
var bodyEl = null;
|
||
var phEl = null;
|
||
var lastContent = null;
|
||
|
||
function getBodyEl() {
|
||
if (!bodyEl) bodyEl = document.getElementById(uid + '_body');
|
||
return bodyEl;
|
||
}
|
||
function getPhEl() {
|
||
if (!phEl) phEl = document.getElementById(uid + '_placeholder');
|
||
return phEl;
|
||
}
|
||
|
||
function readEditorContent() {
|
||
// Method 1: Read from CodeMirror 6 .cm-content
|
||
var cmContents = document.querySelectorAll('.cm-content');
|
||
for (var i = 0; i < cmContents.length; i++) {
|
||
var text = cmContents[i].innerText || cmContents[i].textContent;
|
||
if (text && text.trim().length > 0) return text;
|
||
}
|
||
// Method 2: Livewire data via wire:model textarea (hidden)
|
||
var textareas = document.querySelectorAll('textarea[wire\\:model], textarea[wire\\:model\\.live]');
|
||
for (var j = 0; j < textareas.length; j++) {
|
||
var ta = textareas[j];
|
||
if ((ta.name && ta.name.indexOf('content') !== -1) || (ta.id && ta.id.indexOf('content') !== -1)) {
|
||
if (ta.value && ta.value.trim()) return ta.value;
|
||
}
|
||
}
|
||
return '';
|
||
}
|
||
|
||
function renderMarkdown(content) {
|
||
var body = getBodyEl();
|
||
var ph = getPhEl();
|
||
if (!body || !ph) return;
|
||
|
||
if (!content || !content.trim()) {
|
||
body.style.display = 'none';
|
||
ph.style.display = 'block';
|
||
return;
|
||
}
|
||
|
||
if (content === lastContent) return;
|
||
lastContent = content;
|
||
|
||
if (typeof marked === 'undefined') return;
|
||
|
||
try {
|
||
var html = marked.parse(content, { gfm: true, breaks: true });
|
||
body.innerHTML = html;
|
||
body.style.display = 'block';
|
||
ph.style.display = 'none';
|
||
} catch(e) {
|
||
body.innerHTML = '<p style="color:red;">Markdown parse error: ' + e.message + '</p>';
|
||
body.style.display = 'block';
|
||
ph.style.display = 'none';
|
||
}
|
||
}
|
||
|
||
function poll() {
|
||
renderMarkdown(readEditorContent());
|
||
}
|
||
|
||
// Start polling once DOM is ready
|
||
if (document.readyState === 'loading') {
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
setInterval(poll, 400);
|
||
});
|
||
} else {
|
||
setInterval(poll, 400);
|
||
}
|
||
|
||
// Also hook into Livewire updates
|
||
document.addEventListener('livewire:morph', function() {
|
||
setTimeout(poll, 100);
|
||
});
|
||
})();
|
||
</script>
|
||
|
||
<style>
|
||
.mdprev-body {
|
||
font-family: 'Inter', system-ui, -apple-system, sans-serif;
|
||
font-size: 14px;
|
||
line-height: 1.7;
|
||
color: #334155;
|
||
}
|
||
.mdprev-body h1 {
|
||
font-family: 'Outfit', 'Inter', sans-serif;
|
||
font-size: 1.5rem; font-weight: 800; color: #0f172a;
|
||
margin: 2rem 0 0.8rem; line-height: 1.25; letter-spacing: -0.02em;
|
||
}
|
||
.mdprev-body h2 {
|
||
font-family: 'Outfit', 'Inter', sans-serif;
|
||
font-size: 1.25rem; font-weight: 700; color: #1e293b;
|
||
margin: 1.8rem 0 0.7rem; padding-bottom: 0.5rem;
|
||
border-bottom: 1px solid #f1f5f9; line-height: 1.3;
|
||
}
|
||
.mdprev-body h3 {
|
||
font-family: 'Outfit', 'Inter', sans-serif;
|
||
font-size: 1.1rem; font-weight: 600; color: #334155;
|
||
margin: 1.5rem 0 0.5rem;
|
||
}
|
||
.mdprev-body h4 {
|
||
font-size: 1rem; font-weight: 600; color: #475569;
|
||
margin: 1.2rem 0 0.4rem;
|
||
}
|
||
.mdprev-body p { margin: 0 0 1rem; color: #475569; }
|
||
.mdprev-body a { color: {{ $accentColor }}; text-underline-offset: 2px; }
|
||
.mdprev-body strong { font-weight: 700; color: #1e293b; }
|
||
.mdprev-body em { font-style: italic; }
|
||
.mdprev-body img { max-width: 100%; border-radius: 8px; margin: 1rem 0; display: block; }
|
||
.mdprev-body hr { border: 0; height: 1px; background: #e2e8f0; margin: 1.8rem 0; }
|
||
.mdprev-body ul { list-style-type: disc; padding-left: 1.5rem; margin: 0 0 1rem; }
|
||
.mdprev-body ol { list-style-type: decimal; padding-left: 1.5rem; margin: 0 0 1rem; }
|
||
.mdprev-body li { margin-bottom: 0.3rem; color: #475569; line-height: 1.6; }
|
||
.mdprev-body table {
|
||
width: 100%; border-collapse: collapse; margin: 1.5rem 0;
|
||
font-size: 13px; border: 1px solid #e2e8f0; border-radius: 8px; overflow: hidden;
|
||
}
|
||
.mdprev-body th {
|
||
background: #f8fafc; color: #0f172a; font-weight: 600;
|
||
text-align: left; padding: 10px 14px; border-bottom: 2px solid #e2e8f0;
|
||
}
|
||
.mdprev-body td { padding: 10px 14px; border-bottom: 1px solid #f1f5f9; color: #475569; }
|
||
.mdprev-body tr:nth-child(even) td { background: #fafbfc; }
|
||
.mdprev-body tr:last-child td { border-bottom: none; }
|
||
.mdprev-body code {
|
||
font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace;
|
||
font-size: 0.85em; padding: 2px 6px; border-radius: 4px;
|
||
background: #f1f5f9; color: #e11d48;
|
||
}
|
||
.mdprev-body pre {
|
||
background: #0f172a; border-radius: 8px;
|
||
padding: 16px; overflow-x: auto; margin: 1rem 0;
|
||
}
|
||
.mdprev-body pre code { background: transparent; color: #e2e8f0; padding: 0; font-size: 13px; }
|
||
.mdprev-body blockquote {
|
||
border-left: 3px solid {{ $accentColor }}; margin: 1rem 0;
|
||
padding: 0.5rem 0 0.5rem 1rem; color: #64748b;
|
||
background: #f8fafc; border-radius: 0 6px 6px 0;
|
||
}
|
||
.mdprev-body blockquote p { margin: 0; }
|
||
</style>
|