update editor

This commit is contained in:
2026-08-31 12:59:08 +03:00
parent 57f0487f65
commit bf8c805293
+34 -23
View File
@@ -1,4 +1,4 @@
import { useEffect, useRef, useState } from "react"; import { Fragment, useEffect, useRef, useState } from "react";
import { import {
DndContext, DndContext,
closestCenter, closestCenter,
@@ -14,13 +14,13 @@ import {
verticalListSortingStrategy, verticalListSortingStrategy,
} from "@dnd-kit/sortable"; } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities"; import { CSS } from "@dnd-kit/utilities";
import { BiCopy, BiDotsVertical, BiX } from "react-icons/bi"; import { BiCopy, BiDotsVerticalRounded, BiX } from "react-icons/bi";
import { import {
DengiButton, DengiButton,
DengiYesOrNoDialog, DengiYesOrNoDialog,
LoadingSpinner, LoadingSpinner,
} from "./trash-components"; } from "./trash-components";
import { motion, AnimatePresence } from "motion/react"; import { motion, AnimatePresence, LayoutGroup } from "motion/react";
import { import {
BiCheck, BiCheck,
BiPlus, BiPlus,
@@ -145,7 +145,11 @@ const INITIAL_DATA = [
]; ];
function TableInput(props) { function TableInput(props) {
return props.useinput ? <input {...props} /> : <textarea {...props} />; return props.useinput ? (
<input {...{ ...props, useinput: undefined }} />
) : (
<textarea {...{ ...props, useinput: undefined }} />
);
} }
function SortableRow({ function SortableRow({
@@ -178,7 +182,7 @@ function SortableRow({
ref={setNodeRef} ref={setNodeRef}
style={style} style={style}
className={`${ className={`${
pickmeMode ? "bg-pink-500/35" : "bg-zinc-900" pickmeMode ? "bg-pink-900/35" : "bg-zinc-800/35"
} bg-grain rounded-lg mb-2`} } bg-grain rounded-lg mb-2`}
> >
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
@@ -205,24 +209,24 @@ function SortableRow({
/> />
))} ))}
</div> </div>
<span className="w-[98%] mx-auto h-[1px] bg-zinc-500" />
<div className="flex justify-end w-full"> <div className="flex justify-end w-full">
<div
{...attributes}
{...listeners}
className="min-w-12 min-h-12 transition-colors hover:bg-zinc-200 flex items-center justify-center cursor-move touch-none select-none hover:text-black font-black text-white rounded-bl-xl rounded-tr -xl "
>
<BiDotsVerticalRounded size={24} />
</div>
<div className="w-full"></div>
<button <button
onClick={() => { onClick={() => {
onDuplicate(item.id); onDuplicate(item.id);
trigger([{ duration: 25 }], { intensity: 0.7 }); trigger([{ duration: 25 }], { intensity: 0.7 });
}} }}
className="min-w-12 min-h-12 transition-colors bg-zinc-600/20 text-zinc-400 hover:bg-zinc-600/40 hover:text-zinc-300 flex items-center justify-center rounded-l-md" className="min-w-12 min-h-12 transition-colors text-zinc-400 hover:bg-zinc-600/40 hover:text-zinc-300 flex items-center justify-center rounded-l-md"
> >
<BiCopy size={20} /> <BiCopy size={20} />
</button> </button>
<div
{...attributes}
{...listeners}
className="min-w-12 min-h-12 transition-colors hover:bg-zinc-200 flex items-center justify-center cursor-move touch-none select-none hover:text-black font-black text-white bg-zinc-700/60"
>
<BiDotsVertical size={24} />
</div>
<button <button
onClick={() => { onClick={() => {
onDelete(item.id); onDelete(item.id);
@@ -232,7 +236,7 @@ function SortableRow({
{ delay: 40, duration: 40, intensity: 0.9 }, { delay: 40, duration: 40, intensity: 0.9 },
]); ]);
}} }}
className="min-w-12 min-h-12 transition-colors bg-red-600/20 text-red-400 hover:bg-red-600/40 hover:text-red-300 active:bg-red-600/60 flex items-center justify-center rounded-r-md" className="min-w-12 min-h-12 transition-colors text-red-400 hover:bg-red-600/40 hover:text-red-300 active:bg-red-600/60 flex items-center justify-center rounded-r-md"
> >
<BiX size={24} /> <BiX size={24} />
</button> </button>
@@ -388,7 +392,7 @@ export function TableEditor({
// Create new item with unique id // Create new item with unique id
const newItem = { const newItem = {
...itemToDuplicate, ...itemToDuplicate,
id: Date.now(), // or use uuid() or any unique id generator id: String(Date.now()), // or use uuid() or any unique id generator
}; };
// Insert the new item right after the duplicated item // Insert the new item right after the duplicated item
@@ -462,6 +466,9 @@ export function TableEditor({
}; };
const handlePublish = () => { const handlePublish = () => {
if (isLoading) return; if (isLoading) return;
Object.keys(updateTimeoutRef.current).forEach((i) => {
clearTimeout(updateTimeoutRef.current[i]);
});
setUndoItems([]); setUndoItems([]);
setRedoItems([]); setRedoItems([]);
console.log(convertEditorToApi(items)); console.log(convertEditorToApi(items));
@@ -483,7 +490,7 @@ export function TableEditor({
}; };
const { trigger } = useWebHaptics(); const { trigger } = useWebHaptics();
const handleDragOver = (ev) => { const handleDragOver = () => {
trigger([{ duration: 25 }], { intensity: 0.7 }); trigger([{ duration: 25 }], { intensity: 0.7 });
}; };
@@ -493,7 +500,7 @@ export function TableEditor({
<div> <div>
<DengiYesOrNoDialog <DengiYesOrNoDialog
content={{ content={{
message: "ВСЁ БУДЕТ УДАЛЕНО! продолжить?", message: "запись в базе данных будет удалена! продолжить?",
yesBtn: "да", yesBtn: "да",
noBtn: "нет", noBtn: "нет",
yesIcon: <BiTrash />, yesIcon: <BiTrash />,
@@ -558,7 +565,7 @@ export function TableEditor({
<div> <div>
<div className="flex w-full justify-around items-center mb-2"> <div className="flex w-full justify-around items-center mb-2">
{columns.map((col, i) => ( {columns.map((col, i) => (
<> <Fragment key={col.key + i}>
<div <div
key={col.key + i} key={col.key + i}
className={ className={
@@ -581,7 +588,7 @@ export function TableEditor({
pickmeMode ? "bg-pink-600" : "bg-zinc-600" pickmeMode ? "bg-pink-600" : "bg-zinc-600"
} -rotate-45 last:hidden`} } -rotate-45 last:hidden`}
/> />
</> </Fragment>
))} ))}
</div> </div>
<div className="max-w-3xl mx-auto"> <div className="max-w-3xl mx-auto">
@@ -599,7 +606,11 @@ export function TableEditor({
<AnimatePresence mode={items.length > 0 ? "sync" : "wait"}> <AnimatePresence mode={items.length > 0 ? "sync" : "wait"}>
{items.map((item) => ( {items.map((item) => (
<motion.div <motion.div
initial={{ x: -15, filter: "blur(5px)", opacity: 0 }} initial={{
x: -15,
filter: "blur(5px)",
opacity: 0,
}}
animate={{ x: 0, filter: "blur(0px)", opacity: 1 }} animate={{ x: 0, filter: "blur(0px)", opacity: 1 }}
exit={{ x: 15, filter: "blur(5px)", opacity: 0 }} exit={{ x: 15, filter: "blur(5px)", opacity: 0 }}
key={item.id} key={item.id}
@@ -662,13 +673,13 @@ export function TableEditor({
<LoadingSpinner size={35} /> <LoadingSpinner size={35} />
</div> </div>
)} )}
<motion.div layout="position" className="flex w-full justify-end gap-2"> <motion.div className="flex w-full justify-end gap-2 fixed pr-20 bottom-2 left-0">
<DengiButton <DengiButton
onClick={handleDeleteAll} onClick={handleDeleteAll}
className="border-red-600! md:not-disabled:not-hover:border-red-400!" className="border-red-600! md:not-disabled:not-hover:border-red-400!"
> >
<BiTrash /> <BiTrash />
удалить всё удалить из бд
</DengiButton> </DengiButton>
<DengiButton onClick={handleAddRow}> <DengiButton onClick={handleAddRow}>
<BiPlus /> <BiPlus />