refactor(admin): split workflow page.tsx into colocated components
Split 1175-LOC workflow page into _components, _hooks and _types modules. page.tsx now 256 LOC (wire-up only). Behavior preserved. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
'use client'
|
||||
|
||||
import { RefObject } from 'react'
|
||||
|
||||
interface RichTextToolbarProps {
|
||||
fileInputRef: RefObject<HTMLInputElement | null>
|
||||
uploading: boolean
|
||||
onFormatDoc: (cmd: string, value?: string | null) => void
|
||||
onFormatBlock: (tag: string) => void
|
||||
onInsertLink: () => void
|
||||
onWordUpload: (event: React.ChangeEvent<HTMLInputElement>) => void
|
||||
}
|
||||
|
||||
export default function RichTextToolbar({
|
||||
fileInputRef,
|
||||
uploading,
|
||||
onFormatDoc,
|
||||
onFormatBlock,
|
||||
onInsertLink,
|
||||
onWordUpload,
|
||||
}: RichTextToolbarProps) {
|
||||
return (
|
||||
<div className="bg-white rounded-xl shadow-sm border p-3">
|
||||
<div className="flex items-center gap-1 flex-wrap">
|
||||
{/* Formatting */}
|
||||
<div className="flex items-center gap-1 border-r border-slate-200 pr-2 mr-2">
|
||||
<button onClick={() => onFormatDoc('bold')} className="p-2 hover:bg-slate-100 rounded" title="Fett">
|
||||
<span className="font-bold">B</span>
|
||||
</button>
|
||||
<button onClick={() => onFormatDoc('italic')} className="p-2 hover:bg-slate-100 rounded" title="Kursiv">
|
||||
<span className="italic">I</span>
|
||||
</button>
|
||||
<button onClick={() => onFormatDoc('underline')} className="p-2 hover:bg-slate-100 rounded" title="Unterstrichen">
|
||||
<span className="underline">U</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Headings */}
|
||||
<div className="flex items-center gap-1 border-r border-slate-200 pr-2 mr-2">
|
||||
<button onClick={() => onFormatBlock('h1')} className="p-2 hover:bg-slate-100 rounded text-sm" title="Ueberschrift 1">
|
||||
H1
|
||||
</button>
|
||||
<button onClick={() => onFormatBlock('h2')} className="p-2 hover:bg-slate-100 rounded text-sm" title="Ueberschrift 2">
|
||||
H2
|
||||
</button>
|
||||
<button onClick={() => onFormatBlock('h3')} className="p-2 hover:bg-slate-100 rounded text-sm" title="Ueberschrift 3">
|
||||
H3
|
||||
</button>
|
||||
<button onClick={() => onFormatBlock('p')} className="p-2 hover:bg-slate-100 rounded text-sm" title="Absatz">
|
||||
P
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Lists */}
|
||||
<div className="flex items-center gap-1 border-r border-slate-200 pr-2 mr-2">
|
||||
<button onClick={() => onFormatDoc('insertUnorderedList')} className="p-2 hover:bg-slate-100 rounded" title="Aufzaehlung">
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
|
||||
</svg>
|
||||
</button>
|
||||
<button onClick={() => onFormatDoc('insertOrderedList')} className="p-2 hover:bg-slate-100 rounded" title="Nummerierung">
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M7 20l4-16m2 16l4-16M6 9h14M4 15h14" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Links */}
|
||||
<div className="flex items-center gap-1 border-r border-slate-200 pr-2 mr-2">
|
||||
<button onClick={onInsertLink} className="p-2 hover:bg-slate-100 rounded" title="Link einfuegen">
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Word Upload */}
|
||||
<div className="flex items-center gap-1">
|
||||
<input
|
||||
type="file"
|
||||
ref={fileInputRef}
|
||||
onChange={onWordUpload}
|
||||
accept=".docx,.doc"
|
||||
className="hidden"
|
||||
/>
|
||||
<button
|
||||
onClick={() => fileInputRef.current?.click()}
|
||||
disabled={uploading}
|
||||
className="px-3 py-2 bg-blue-50 text-blue-700 hover:bg-blue-100 rounded text-sm flex items-center gap-1"
|
||||
title="Word-Dokument importieren"
|
||||
>
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12" />
|
||||
</svg>
|
||||
{uploading ? 'Importiere...' : 'Word importieren'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user