171 lines
7.3 KiB
PHP
171 lines
7.3 KiB
PHP
<div>
|
|
<div class="mx-auto container mt-8 mb-12">
|
|
<div class="mb-6">
|
|
<a href="{{ route('knowledgebase.index') }}" wire:navigate
|
|
class="inline-flex items-center text-primary hover:text-primary-dark transition-colors duration-200 group">
|
|
<x-ri-arrow-left-line class="size-4 mr-2 transform transition-transform duration-300 group-hover:-translate-x-1" />
|
|
<span class="font-medium">{{ __('Back to Documentation') }}</span>
|
|
</a>
|
|
</div>
|
|
|
|
<div class="bg-background-secondary border border-neutral rounded-2xl shadow-xl overflow-hidden">
|
|
<div class="relative p-6 sm:p-8 lg:p-10">
|
|
<div class="absolute inset-0 bg-gradient-to-br from-success/5 to-success/10 opacity-70 z-0"></div>
|
|
<div class="relative z-10 flex flex-col md:flex-row md:items-center md:justify-between gap-4">
|
|
<div class="flex-1 space-y-3">
|
|
<div class="inline-flex items-center gap-2 bg-success/10 text-success px-3 py-1 rounded-full text-xs font-semibold uppercase tracking-wide">
|
|
<x-ri-book-open-fill class="size-4" />
|
|
<span>{{ $article->category->name ?? __('General') }}</span>
|
|
</div>
|
|
<h1 class="text-3xl sm:text-4xl font-extrabold text-color-base leading-tight">
|
|
{{ $article->title }}
|
|
</h1>
|
|
<div class="flex flex-wrap items-center gap-4 text-color-muted text-sm">
|
|
<span class="inline-flex items-center gap-1">
|
|
<x-ri-calendar-line class="size-4" />
|
|
{{ optional($article->published_at)->format('F d, Y') ?? $article->created_at->format('F d, Y') }}
|
|
</span>
|
|
<span class="inline-flex items-center gap-1">
|
|
<x-ri-time-line class="size-4" />
|
|
{{ optional($article->published_at)->diffForHumans() ?? $article->created_at->diffForHumans() }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="p-6 sm:p-8 lg:p-10 prose dark:prose-invert max-w-full text-color-base leading-relaxed" id="article-content">
|
|
{!! $article->content !!}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
.code-block-wrapper {
|
|
position: relative;
|
|
}
|
|
|
|
.copy-code-button {
|
|
position: absolute;
|
|
top: 8px;
|
|
right: 8px;
|
|
padding: 6px 12px;
|
|
background-color: rgba(0, 0, 0, 0.6);
|
|
color: white;
|
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
border-radius: 6px;
|
|
cursor: pointer;
|
|
font-size: 12px;
|
|
font-weight: 500;
|
|
transition: all 0.2s ease;
|
|
z-index: 10;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
}
|
|
|
|
.copy-code-button:hover {
|
|
background-color: rgba(0, 0, 0, 0.8);
|
|
border-color: rgba(255, 255, 255, 0.4);
|
|
}
|
|
|
|
.copy-code-button.copied {
|
|
background-color: rgba(34, 197, 94, 0.8);
|
|
border-color: rgba(34, 197, 94, 1);
|
|
}
|
|
|
|
.dark .copy-code-button {
|
|
background-color: rgba(255, 255, 255, 0.1);
|
|
color: white;
|
|
border-color: rgba(255, 255, 255, 0.2);
|
|
}
|
|
|
|
.dark .copy-code-button:hover {
|
|
background-color: rgba(255, 255, 255, 0.2);
|
|
border-color: rgba(255, 255, 255, 0.4);
|
|
}
|
|
|
|
.dark .copy-code-button.copied {
|
|
background-color: rgba(34, 197, 94, 0.3);
|
|
border-color: rgba(34, 197, 94, 0.6);
|
|
}
|
|
</style>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Find all code blocks within pre tags
|
|
const codeBlocks = document.querySelectorAll('#article-content pre');
|
|
|
|
codeBlocks.forEach((preBlock) => {
|
|
// Create wrapper if not already wrapped
|
|
if (!preBlock.parentElement.classList.contains('code-block-wrapper')) {
|
|
const wrapper = document.createElement('div');
|
|
wrapper.className = 'code-block-wrapper';
|
|
preBlock.parentNode.insertBefore(wrapper, preBlock);
|
|
wrapper.appendChild(preBlock);
|
|
}
|
|
|
|
const wrapper = preBlock.parentElement;
|
|
|
|
// Create copy button
|
|
const copyButton = document.createElement('button');
|
|
copyButton.className = 'copy-code-button';
|
|
copyButton.innerHTML = `
|
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"><\/rect>
|
|
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><\/path>
|
|
<\/svg>
|
|
<span class="button-text">Copy<\/span>
|
|
`;
|
|
|
|
copyButton.addEventListener('click', async function() {
|
|
// Get the code content
|
|
const codeElement = preBlock.querySelector('code') || preBlock;
|
|
const code = codeElement.textContent;
|
|
|
|
try {
|
|
// Copy to clipboard
|
|
await navigator.clipboard.writeText(code);
|
|
|
|
// Update button to show success
|
|
copyButton.classList.add('copied');
|
|
const buttonText = copyButton.querySelector('.button-text');
|
|
const originalText = buttonText.textContent;
|
|
buttonText.textContent = 'Copied!';
|
|
|
|
copyButton.innerHTML = `
|
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<polyline points="20 6 9 17 4 12"><\/polyline>
|
|
<\/svg>
|
|
<span class="button-text">Copied!<\/span>
|
|
`;
|
|
|
|
// Reset button after 2 seconds
|
|
setTimeout(() => {
|
|
copyButton.classList.remove('copied');
|
|
copyButton.innerHTML = `
|
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"><\/rect>
|
|
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><\/path>
|
|
<\/svg>
|
|
<span class="button-text">Copy<\/span>
|
|
`;
|
|
}, 2000);
|
|
} catch (err) {
|
|
console.error('Failed to copy code:', err);
|
|
const buttonText = copyButton.querySelector('.button-text');
|
|
buttonText.textContent = 'Failed';
|
|
|
|
setTimeout(() => {
|
|
buttonText.textContent = 'Copy';
|
|
}, 2000);
|
|
}
|
|
});
|
|
|
|
// Add button to wrapper
|
|
wrapper.appendChild(copyButton);
|
|
});
|
|
});
|
|
</script>
|
|
</div>
|