feat: rich text editor, image crop component, empty DB resilience
- RichTextarea with toolbar (Bold, Italic, List, Heading) + Ctrl+B/I
hotkeys (layout-independent), active state highlighting, preview mode
- Shared ImageCropField component (replaces duplicate in news/classes)
with drag-to-reposition, Ctrl+scroll zoom, compact layout
- SectionEditor defaultData prop — all admin pages handle empty DB
- Team: section title editable, toast notifications, unsaved data warning
on navigation (back button, sidebar links, browser close)
- Carousel: continuous card wrapping during drag, edge fade for small teams
- Markup renderer: **bold**, *italic*, ## headings, 🤍 bullet points
- Empty DB guards on all public site sections
- Fix: upload error handling, contact phone field, "team" section key
This commit is contained in:
@@ -28,7 +28,7 @@ function PhoneField({ value, onChange }: { value: string; onChange: (v: string)
|
||||
onChange(formatted);
|
||||
}
|
||||
|
||||
const digits = value.replace(/\D/g, "");
|
||||
const digits = (value ?? "").replace(/\D/g, "");
|
||||
const isComplete = digits.length === 12;
|
||||
|
||||
return (
|
||||
@@ -163,7 +163,7 @@ function AddressList({ items, onChange }: { items: string[]; onChange: (items: s
|
||||
|
||||
export default function ContactEditorPage() {
|
||||
return (
|
||||
<SectionEditor<ContactInfo> sectionKey="contact" title="Контакты">
|
||||
<SectionEditor<ContactInfo> sectionKey="contact" title="Контакты" defaultData={{ addresses: [] }}>
|
||||
{(data, update) => (
|
||||
<div className="space-y-4">
|
||||
<InputField
|
||||
|
||||
Reference in New Issue
Block a user