From 9e6ce4359a616708bf810f816abf62a285243ea5 Mon Sep 17 00:00:00 2001 From: BOHA Date: Tue, 24 Mar 2026 11:23:34 +0100 Subject: [PATCH] fix: use RichEditor with readOnly prop instead of raw HTML for locked/invalidated offers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RichEditor now supports readOnly prop — hides toolbar and disables editing via ReactQuill's built-in readOnly. Content renders with proper Quill CSS (list margins, indentation, fonts) instead of broken browser defaults from dangerouslySetInnerHTML. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/admin/components/RichEditor.tsx | 9 ++++++--- src/admin/pages/OfferDetail.tsx | 23 +++++++---------------- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/admin/components/RichEditor.tsx b/src/admin/components/RichEditor.tsx index 9c93d85..c4e5f88 100644 --- a/src/admin/components/RichEditor.tsx +++ b/src/admin/components/RichEditor.tsx @@ -64,23 +64,25 @@ interface RichEditorProps { onChange: (value: string) => void placeholder?: string minHeight?: string + readOnly?: boolean } export default function RichEditor({ value, onChange, placeholder = 'Obsah...', - minHeight = '120px' + minHeight = '120px', + readOnly = false, }: RichEditorProps) { const quillRef = useRef(null) const lastValueRef = useRef(value) const modules = useMemo(() => ({ - toolbar: TOOLBAR, + toolbar: readOnly ? false : TOOLBAR, clipboard: { matchVisual: false, }, - }), []) + }), [readOnly]) const handleChange = useCallback((content: string, _delta: any, source: string) => { if (source !== 'user') return @@ -99,6 +101,7 @@ export default function RichEditor({ modules={modules} formats={FORMATS} placeholder={placeholder} + readOnly={readOnly} /> ) diff --git a/src/admin/pages/OfferDetail.tsx b/src/admin/pages/OfferDetail.tsx index 525efba..b94bb25 100644 --- a/src/admin/pages/OfferDetail.tsx +++ b/src/admin/pages/OfferDetail.tsx @@ -1097,22 +1097,13 @@ export default function OfferDetail() {
- {(isInvalidated || isLockedByOther) ? ( -
-
Prázdný obsah' }} - /> -
- ) : ( - setSections(prev => prev.map((s, i) => i === idx ? { ...s, content: val } : s))} - placeholder="Obsah sekce..." - minHeight="120px" - /> - )} + setSections(prev => prev.map((s, i) => i === idx ? { ...s, content: val } : s))} + placeholder="Obsah sekce..." + minHeight="120px" + readOnly={isInvalidated || isLockedByOther} + />
))}