Переглянути джерело

feat(admin): заменить confirm() на анимированную замену кнопок удаления

neyrogovnarik 2 тижнів тому
батько
коміт
5a4f50fff2
1 змінених файлів з 74 додано та 24 видалено
  1. 74 24
      frontend/src/app/admin/tags/page.tsx

+ 74 - 24
frontend/src/app/admin/tags/page.tsx

@@ -23,8 +23,10 @@ export default function AdminTagsPage() {
 
   const [editingTagId, setEditingTagId] = useState<string | null>(null)
   const [editTagName, setEditTagName] = useState('')
+  const [deletingTagId, setDeletingTagId] = useState<string | null>(null)
   const [editingFeatureId, setEditingFeatureId] = useState<string | null>(null)
   const [editFeatureName, setEditFeatureName] = useState('')
+  const [deletingFeatureId, setDeletingFeatureId] = useState<string | null>(null)
 
   const fetchData = async () => {
     try {
@@ -89,10 +91,10 @@ export default function AdminTagsPage() {
     }
   }
 
-  const deleteTag = async (id: string) => {
-    if (!confirm('Удалить тег «' + id + '»?')) return
+  const confirmDeleteTag = async (id: string) => {
     try {
       await api.delete('/admin/tags?id=' + encodeURIComponent(id))
+      setDeletingTagId(null)
       setError('')
       fetchData()
     } catch (err) {
@@ -122,10 +124,10 @@ export default function AdminTagsPage() {
     }
   }
 
-  const deleteFeature = async (id: string) => {
-    if (!confirm('Удалить характеристику «' + id + '»?')) return
+  const confirmDeleteFeature = async (id: string) => {
     try {
       await api.delete('/admin/features?id=' + encodeURIComponent(id))
+      setDeletingFeatureId(null)
       setError('')
       fetchData()
     } catch (err) {
@@ -184,16 +186,40 @@ export default function AdminTagsPage() {
                   <span className="text-sm text-white">{tag.name}</span>
                   <div className="flex items-center gap-2">
                     <span className="text-xs text-white/40">{tag.id}</span>
-                    <button onClick={() => startEditTag(tag)}
-                      className="text-xs text-white/40 hover:text-white"
-                      title="Редактировать">
-                      ✏️
-                    </button>
-                    <button onClick={() => deleteTag(tag.id)}
-                      className="text-xs text-white/40 hover:text-red-400"
-                      title="Удалить">
-                      🗑️
-                    </button>
+                    <div className="relative h-5 w-12 overflow-hidden">
+                      <div className={`absolute inset-0 flex items-center gap-2 transition-all duration-200 ${
+                        deletingTagId === tag.id
+                          ? '-translate-y-full opacity-0'
+                          : 'translate-y-0 opacity-100'
+                      }`}>
+                        <button onClick={() => startEditTag(tag)}
+                          className="text-xs text-white/40 hover:text-white"
+                          title="Редактировать">
+                          ✏️
+                        </button>
+                        <button onClick={() => setDeletingTagId(tag.id)}
+                          className="text-xs text-white/40 hover:text-red-400"
+                          title="Удалить">
+                          🗑️
+                        </button>
+                      </div>
+                      <div className={`absolute inset-0 flex items-center gap-2 transition-all duration-200 ${
+                        deletingTagId === tag.id
+                          ? 'translate-y-0 opacity-100'
+                          : 'translate-y-full opacity-0'
+                      }`}>
+                        <button onClick={() => confirmDeleteTag(tag.id)}
+                          className="text-xs text-green-400 hover:text-green-300"
+                          title="Подтвердить удаление">
+                          ✓
+                        </button>
+                        <button onClick={() => setDeletingTagId(null)}
+                          className="text-xs text-white/40 hover:text-white"
+                          title="Отмена">
+                          ✕
+                        </button>
+                      </div>
+                    </div>
                   </div>
                 </>
               )}
@@ -244,16 +270,40 @@ export default function AdminTagsPage() {
                   <span className="text-sm text-white">{feat.name}</span>
                   <div className="flex items-center gap-2">
                     <span className="text-xs text-white/40">{feat.id}</span>
-                    <button onClick={() => startEditFeature(feat)}
-                      className="text-xs text-white/40 hover:text-white"
-                      title="Редактировать">
-                      ✏️
-                    </button>
-                    <button onClick={() => deleteFeature(feat.id)}
-                      className="text-xs text-white/40 hover:text-red-400"
-                      title="Удалить">
-                      🗑️
-                    </button>
+                    <div className="relative h-5 w-12 overflow-hidden">
+                      <div className={`absolute inset-0 flex items-center gap-2 transition-all duration-200 ${
+                        deletingFeatureId === feat.id
+                          ? '-translate-y-full opacity-0'
+                          : 'translate-y-0 opacity-100'
+                      }`}>
+                        <button onClick={() => startEditFeature(feat)}
+                          className="text-xs text-white/40 hover:text-white"
+                          title="Редактировать">
+                          ✏️
+                        </button>
+                        <button onClick={() => setDeletingFeatureId(feat.id)}
+                          className="text-xs text-white/40 hover:text-red-400"
+                          title="Удалить">
+                          🗑️
+                        </button>
+                      </div>
+                      <div className={`absolute inset-0 flex items-center gap-2 transition-all duration-200 ${
+                        deletingFeatureId === feat.id
+                          ? 'translate-y-0 opacity-100'
+                          : 'translate-y-full opacity-0'
+                      }`}>
+                        <button onClick={() => confirmDeleteFeature(feat.id)}
+                          className="text-xs text-green-400 hover:text-green-300"
+                          title="Подтвердить удаление">
+                          ✓
+                        </button>
+                        <button onClick={() => setDeletingFeatureId(null)}
+                          className="text-xs text-white/40 hover:text-white"
+                          title="Отмена">
+                          ✕
+                        </button>
+                      </div>
+                    </div>
                   </div>
                 </>
               )}