b2in/resources/views/livewire/admin/documentation.blade.php
2026-04-10 17:18:17 +02:00

442 lines
20 KiB
PHP

<?php
use App\Services\ProjectDocumentationContent;
use function Livewire\Volt\computed;
use function Livewire\Volt\state;
state(['showToc' => false]);
$content = computed(fn () => ProjectDocumentationContent::html());
$tableOfContents = computed(fn () => ProjectDocumentationContent::tableOfContents());
$fileInfo = computed(fn () => ProjectDocumentationContent::fileInfo());
?>
<div class="space-y-6 pb-12">
{{-- Sticky Header --}}
<div class="sticky top-0 z-10 bg-zinc-50 dark:bg-zinc-800 pb-4 border-b border-zinc-200 dark:border-zinc-700">
<div class="flex items-center justify-between">
<div>
<flux:heading size="xl">{{ __('Projekt-Dokumentation') }}</flux:heading>
<flux:subheading>{{ __('Entwicklungsstand & Technische Übersicht') }}</flux:subheading>
</div>
<div class="flex gap-2">
<flux:button
variant="ghost"
size="sm"
icon="list-bullet"
wire:click="$toggle('showToc')"
>
{{ __('Inhaltsverzeichnis') }}
</flux:button>
<flux:button
variant="ghost"
size="sm"
icon="arrow-down-tray"
href="{{ route('admin.documentation.download') }}"
>
{{ __('Download') }}
</flux:button>
</div>
</div>
{{-- File Info Bar --}}
@if($this->fileInfo)
<div class="flex items-center gap-4 mt-3 text-xs text-zinc-600 dark:text-zinc-400">
<div class="flex items-center gap-1">
<flux:icon.document-text class="w-3 h-3" />
<span>{{ $this->fileInfo['size'] }}</span>
</div>
<div class="flex items-center gap-1">
<flux:icon.clock class="w-3 h-3" />
<span>{{ __('Aktualisiert:') }} {{ $this->fileInfo['modified'] }}</span>
</div>
<div class="flex items-center gap-1">
<flux:icon.bars-3 class="w-3 h-3" />
<span>{{ $this->fileInfo['lines'] }} {{ __('Zeilen') }}</span>
</div>
</div>
@endif
</div>
{{-- Table of Contents Sidebar (Collapsible) --}}
@if($showToc)
<flux:card class="p-6 bg-gradient-to-br from-accent-50 to-blue-50 dark:from-accent-900/20 dark:to-blue-900/20 border-accent-200 dark:border-accent-800">
<div class="flex items-center justify-between mb-4">
<flux:heading size="lg">{{ __('Inhaltsverzeichnis') }}</flux:heading>
<flux:button variant="ghost" size="sm" icon="x-mark" wire:click="$set('showToc', false)" />
</div>
<div class="space-y-2">
@foreach($this->tableOfContents as $item)
<a href="#{{ $item['slug'] }}"
class="block py-1.5 px-3 rounded-lg hover:bg-white dark:hover:bg-zinc-800 transition-colors
{{ $item['level'] === 2 ? 'font-semibold text-zinc-900 dark:text-zinc-100' : 'ml-4 text-sm text-zinc-700 dark:text-zinc-300' }}"
wire:click="$set('showToc', false)">
{{ $item['level'] === 3 ? '• ' : '' }}{{ $item['title'] }}
</a>
@endforeach
</div>
</flux:card>
@endif
{{-- Markdown Content with Enhanced Styling --}}
<div class="relative">
<flux:card class="p-6 lg:p-8 shadow-lg">
<style>
/* Force headings visibility and styling - reduced by 30% */
.prose h1 {
display: block !important;
font-size: 2.1rem !important;
font-weight: 700 !important;
line-height: 1.2 !important;
margin-top: 2.1rem !important;
margin-bottom: 1.4rem !important;
padding-bottom: 1rem !important;
border-bottom: 2px solid #e5e7eb !important;
background: linear-gradient(to right, #3b82f6, #2563eb) !important;
-webkit-background-clip: text !important;
-webkit-text-fill-color: transparent !important;
background-clip: text !important;
}
.prose h2 {
display: block !important;
font-size: 1.3125rem !important;
font-weight: 700 !important;
line-height: 1.3 !important;
margin-top: 2.1rem !important;
margin-bottom: 1rem !important;
padding-bottom: 0.5rem !important;
border-bottom: 1px solid #e5e7eb !important;
scroll-margin-top: 5rem !important;
}
.prose h3 {
display: block !important;
font-size: 1.05rem !important;
font-weight: 700 !important;
line-height: 1.4 !important;
margin-top: 1.4rem !important;
margin-bottom: 0.7rem !important;
scroll-margin-top: 5rem !important;
}
.prose h4 {
display: block !important;
font-size: 0.875rem !important;
font-weight: 600 !important;
line-height: 1.5 !important;
margin-top: 1rem !important;
margin-bottom: 0.5rem !important;
}
/* Dark mode headings */
.dark .prose h1 {
border-bottom-color: #374151 !important;
}
.dark .prose h2 {
border-bottom-color: #374151 !important;
color: #f9fafb !important;
}
.dark .prose h3 {
color: #e5e7eb !important;
}
.dark .prose h4 {
color: #d1d5db !important;
}
/* Force list indentation and visibility - reduced by 30% */
.prose ul {
list-style-type: disc !important;
margin-left: 1.75rem !important;
padding-left: 0.7rem !important;
margin-top: 0.7rem !important;
margin-bottom: 0.7rem !important;
}
.prose ol {
list-style-type: decimal !important;
margin-left: 1.75rem !important;
padding-left: 0.7rem !important;
margin-top: 0.7rem !important;
margin-bottom: 0.7rem !important;
}
.prose li {
display: list-item !important;
margin-bottom: 0.35rem !important;
padding-left: 0.35rem !important;
font-size: 0.95rem !important;
line-height: 1.5 !important;
}
.prose ul ul, .prose ol ol,
.prose ul ol, .prose ol ul {
margin-left: 1.4rem !important;
margin-top: 0.35rem !important;
margin-bottom: 0.35rem !important;
}
/* Paragraphs - reduced by 30% */
.prose p {
margin-top: 0.7rem !important;
margin-bottom: 0.7rem !important;
line-height: 1.6 !important;
font-size: 0.95rem !important;
}
/* Strong/Bold */
.prose strong {
font-weight: 700 !important;
color: #111827 !important;
font-size: 0.95rem !important;
}
.dark .prose strong {
color: #f9fafb !important;
}
/* Code - reduced by 30% */
.prose code {
background-color: #f3f4f6 !important;
padding: 0.175rem 0.35rem !important;
border-radius: 0.25rem !important;
font-size: 0.8rem !important;
font-weight: 600 !important;
}
.dark .prose code {
background-color: #1f2937 !important;
color: #60a5fa !important;
}
/* HR - reduced by 30% */
.prose hr {
margin-top: 2.1rem !important;
margin-bottom: 2.1rem !important;
border-color: #e5e7eb !important;
}
.dark .prose hr {
border-color: #374151 !important;
}
</style>
<div class="prose prose-zinc dark:prose-invert max-w-none
{{-- Headings --}}
prose-headings:font-bold prose-headings:tracking-tight
prose-h1:text-5xl prose-h1:mb-8 prose-h1:mt-12 prose-h1:pb-6
prose-h1:border-b-2 prose-h1:border-accent-300 dark:prose-h1:border-accent-700
prose-h1:text-transparent prose-h1:bg-clip-text prose-h1:bg-gradient-to-r prose-h1:from-accent-600 prose-h1:to-blue-600 dark:prose-h1:from-accent-400 dark:prose-h1:to-blue-400
prose-h2:text-3xl prose-h2:mb-6 prose-h2:mt-12 prose-h2:pb-3
prose-h2:border-b prose-h2:border-zinc-200 dark:prose-h2:border-zinc-700
prose-h2:text-zinc-900 dark:prose-h2:text-zinc-100
prose-h2:scroll-mt-20
prose-h3:text-2xl prose-h3:mb-4 prose-h3:mt-8
prose-h3:text-zinc-800 dark:prose-h3:text-zinc-200
prose-h3:scroll-mt-20
prose-h4:text-xl prose-h4:mb-3 prose-h4:mt-6
prose-h4:text-zinc-700 dark:prose-h4:text-zinc-300
{{-- Paragraphs & Text --}}
prose-p:mb-6 prose-p:leading-relaxed prose-p:text-zinc-700 dark:prose-p:text-zinc-300
{{-- Links --}}
prose-a:text-accent-600 dark:prose-a:text-accent-400
prose-a:font-medium prose-a:no-underline
prose-a:transition-all prose-a:duration-200
hover:prose-a:text-accent-700 dark:hover:prose-a:text-accent-300
hover:prose-a:underline hover:prose-a:decoration-2 hover:prose-a:underline-offset-4
{{-- Strong & Emphasis --}}
prose-strong:text-zinc-900 dark:prose-strong:text-zinc-100
prose-strong:font-bold
prose-em:text-zinc-800 dark:prose-em:text-zinc-200
{{-- Code --}}
prose-code:bg-accent-100 dark:prose-code:bg-accent-900/30
prose-code:text-accent-900 dark:prose-code:text-accent-100
prose-code:px-2 prose-code:py-1 prose-code:rounded-md
prose-code:text-sm prose-code:font-mono prose-code:font-semibold
prose-code:before:content-none prose-code:after:content-none
prose-code:border prose-code:border-accent-200 dark:prose-code:border-accent-800
{{-- Code Blocks --}}
prose-pre:bg-gradient-to-br prose-pre:from-zinc-900 prose-pre:to-zinc-800
dark:prose-pre:from-zinc-950 dark:prose-pre:to-zinc-900
prose-pre:p-6 prose-pre:rounded-xl prose-pre:overflow-x-auto
prose-pre:shadow-xl prose-pre:border prose-pre:border-zinc-700 dark:prose-pre:border-zinc-800
prose-pre:my-8
{{-- Lists --}}
prose-ul:list-disc prose-ul:ml-8 prose-ul:pl-6 prose-ul:mb-6 prose-ul:space-y-2
prose-ol:list-decimal prose-ol:ml-8 prose-ol:pl-6 prose-ol:mb-6 prose-ol:space-y-2
prose-li:text-zinc-700 dark:prose-li:text-zinc-300
prose-li:leading-relaxed prose-li:pl-3
prose-li:marker:text-accent-500 dark:prose-li:marker:text-accent-400
prose-li:marker:font-bold
{{-- Nested Lists --}}
prose-ul prose-ul:ml-8 prose-ul prose-ul:space-y-1
prose-ol prose-ol:ml-8 prose-ol prose-ol:space-y-1
{{-- Blockquotes --}}
prose-blockquote:border-l-4 prose-blockquote:border-accent-500 dark:prose-blockquote:border-accent-400
prose-blockquote:bg-accent-50 dark:prose-blockquote:bg-accent-900/10
prose-blockquote:pl-6 prose-blockquote:pr-4 prose-blockquote:py-4
prose-blockquote:italic prose-blockquote:text-zinc-700 dark:prose-blockquote:text-zinc-300
prose-blockquote:rounded-r-lg prose-blockquote:my-8
prose-blockquote:shadow-sm
{{-- HR --}}
prose-hr:border-zinc-300 dark:prose-hr:border-zinc-600
prose-hr:my-12 prose-hr:border-t-2
{{-- Tables --}}
prose-table:border-collapse prose-table:w-full
prose-table:shadow-lg prose-table:rounded-lg prose-table:overflow-hidden
prose-table:my-8
prose-thead:bg-gradient-to-r prose-thead:from-accent-100 prose-thead:to-blue-100
dark:prose-thead:from-accent-900/40 dark:prose-thead:to-blue-900/40
prose-th:p-4 prose-th:text-left prose-th:font-bold
prose-th:text-zinc-900 dark:prose-th:text-zinc-100
prose-th:border-b-2 prose-th:border-accent-300 dark:prose-th:border-accent-700
prose-td:p-4 prose-td:border-b prose-td:border-zinc-200 dark:prose-td:border-zinc-700
prose-td:text-zinc-700 dark:prose-td:text-zinc-300
prose-tr:transition-colors
hover:prose-tr:bg-zinc-50 dark:hover:prose-tr:bg-zinc-800/50
{{-- Images --}}
prose-img:rounded-xl prose-img:shadow-2xl prose-img:my-8
prose-img:border prose-img:border-zinc-200 dark:prose-img:border-zinc-700
">
{!! $this->content !!}
</div>
{{-- Scroll to top button --}}
<div class="flex justify-center mt-12 pt-8 border-t border-zinc-200 dark:border-zinc-700">
<flux:button
variant="ghost"
icon="arrow-up"
onclick="window.scrollTo({top: 0, behavior: 'smooth'})"
>
{{ __('Zurück nach oben') }}
</flux:button>
</div>
</flux:card>
</div>
{{-- Quick Reference Grid --}}
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<flux:card class="p-6 bg-gradient-to-br from-blue-50 to-indigo-50 dark:from-blue-900/20 dark:to-indigo-900/20 border-blue-200 dark:border-blue-800">
<div class="flex items-center gap-3 mb-4">
<div class="p-2 bg-blue-500 rounded-lg">
<flux:icon.cube class="w-5 h-5 text-white" />
</div>
<flux:heading size="sm" class="text-blue-900 dark:text-blue-100">{{ __('Module') }}</flux:heading>
</div>
<ul class="space-y-2 text-sm text-blue-800 dark:text-blue-200">
<li class="flex items-center gap-2">
<flux:icon.check class="w-4 h-4 text-blue-600 dark:text-blue-400" />
Multi-Domain-System
</li>
<li class="flex items-center gap-2">
<flux:icon.check class="w-4 h-4 text-blue-600 dark:text-blue-400" />
Benutzer-Management
</li>
<li class="flex items-center gap-2">
<flux:icon.check class="w-4 h-4 text-blue-600 dark:text-blue-400" />
Partner-Verwaltung
</li>
<li class="flex items-center gap-2">
<flux:icon.check class="w-4 h-4 text-blue-600 dark:text-blue-400" />
Hub-System
</li>
</ul>
</flux:card>
<flux:card class="p-6 bg-gradient-to-br from-purple-50 to-pink-50 dark:from-purple-900/20 dark:to-pink-900/20 border-purple-200 dark:border-purple-800">
<div class="flex items-center gap-3 mb-4">
<div class="p-2 bg-purple-500 rounded-lg">
<flux:icon.code-bracket class="w-5 h-5 text-white" />
</div>
<flux:heading size="sm" class="text-purple-900 dark:text-purple-100">{{ __('Technologien') }}</flux:heading>
</div>
<ul class="space-y-2 text-sm text-purple-800 dark:text-purple-200">
<li class="flex items-center gap-2">
<flux:icon.check class="w-4 h-4 text-purple-600 dark:text-purple-400" />
Laravel 12
</li>
<li class="flex items-center gap-2">
<flux:icon.check class="w-4 h-4 text-purple-600 dark:text-purple-400" />
Livewire 3 + Volt
</li>
<li class="flex items-center gap-2">
<flux:icon.check class="w-4 h-4 text-purple-600 dark:text-purple-400" />
Flux UI Pro
</li>
<li class="flex items-center gap-2">
<flux:icon.check class="w-4 h-4 text-purple-600 dark:text-purple-400" />
Spatie Permissions
</li>
</ul>
</flux:card>
<flux:card class="p-6 bg-gradient-to-br from-green-50 to-emerald-50 dark:from-green-900/20 dark:to-emerald-900/20 border-green-200 dark:border-green-800">
<div class="flex items-center gap-3 mb-4">
<div class="p-2 bg-green-500 rounded-lg">
<flux:icon.chart-bar class="w-5 h-5 text-white" />
</div>
<flux:heading size="sm" class="text-green-900 dark:text-green-100">{{ __('Status-Legende') }}</flux:heading>
</div>
<div class="space-y-3 text-sm">
<div class="flex items-center gap-2">
<flux:badge color="green" size="sm">✓</flux:badge>
<span class="text-green-800 dark:text-green-200">{{ __('Vollständig implementiert') }}</span>
</div>
<div class="flex items-center gap-2">
<flux:badge color="yellow" size="sm">●</flux:badge>
<span class="text-green-800 dark:text-green-200">{{ __('In Entwicklung') }}</span>
</div>
<div class="flex items-center gap-2">
<flux:badge color="zinc" size="sm">○</flux:badge>
<span class="text-green-800 dark:text-green-200">{{ __('Geplant') }}</span>
</div>
</div>
</flux:card>
</div>
{{-- Footer Metadata --}}
<flux:card class="p-6 bg-gradient-to-r from-zinc-50 to-zinc-100 dark:from-zinc-900 dark:to-zinc-800 border-0">
<div class="flex items-center justify-between">
<div class="flex items-center gap-6 text-sm text-zinc-600 dark:text-zinc-400">
<div class="flex items-center gap-2">
<flux:icon.document-text class="w-4 h-4" />
<span class="font-mono">entwicklung.md</span>
</div>
@if($this->fileInfo)
<div class="flex items-center gap-2">
<flux:icon.clock class="w-4 h-4" />
<span>{{ __('Zuletzt aktualisiert:') }} {{ $this->fileInfo['modified'] }}</span>
</div>
@endif
</div>
<div>
<flux:badge color="accent" size="sm">
{{ __('Live-Dokumentation') }}
</flux:badge>
</div>
</div>
</flux:card>
</div>