Эх сурвалжийг харах

docs: заметка о редактировании/удалении тегов через админку

neyrogovnarik 2 долоо хоног өмнө
parent
commit
1dc567df80

+ 2 - 0
obsidian_data/Photoplaces_data/MOC-frontend-patterns.md

@@ -41,6 +41,7 @@ graph TB
 | Ad-hoc модалки → общий компонент (DRY) | decision record | [[decision-modal-component-extraction]] |
 | Auth через Context + custom hook | `hooks/useAuth.tsx` | [[frontend-api-client]] |
 | Ghost markers для гостей | `MapView.tsx:82-83` | [[atomic-ghost-markers]] |
+| Inline-редактирование + анимация кнопок | `app/admin/tags/page.tsx` | [[atomic-tag-admin-edit-delete]] |
 | Diff-обновление маркеров (markerIdsRef) | `MapView.tsx:70-87` | [[architecture-overview]] |
 | API client с auto-refresh токена | `lib/api.ts` | [[frontend-api-client]] |
 | Error suppression (антипаттерн) | `PlaceForm.tsx:42-43` | [[atomic-error-swallowing-frontend]] |
@@ -82,6 +83,7 @@ graph TB
 - [[decision-modal-component-extraction]] — решение об извлечении Modal
 - [[atomic-error-swallowing-frontend]] — подавление ошибок
 - [[atomic-ghost-markers]] — ghost-маркеры на карте
+- [[atomic-tag-admin-edit-delete]] — inline-редактирование и анимация кнопок в админке
 - [[MOC-backend-patterns]] — бэкенд-паттерны
 - [[MOC-security-patterns]] — безопасность
 

+ 120 - 0
obsidian_data/Photoplaces_data/atomic-tag-admin-edit-delete.md

@@ -0,0 +1,120 @@
+# Редактирование и удаление тегов/характеристик через админку
+
+**Контекст**: В админке на странице `/admin/tags` отсутствовала возможность редактировать и удалять существующие теги и характеристики. Только создание новых.
+
+## Решение
+
+Добавлен полный CRUD с inline-редактированием и анимированным подтверждением удаления.
+
+### Бэкенд
+
+```go
+// repository/tags.go — методы Update
+func (r *TagRepo) Update(ctx context.Context, id string, tag *models.Tag) error {
+    _, err := r.pool.Exec(ctx,
+        `UPDATE tags SET name = $1, category = $2, sort_order = $3 WHERE id = $4`,
+        tag.Name, tag.Category, tag.SortOrder, id)
+    return err
+}
+```
+
+Аналогично для `FeatureRepo`.
+
+Роуты:
+```
+PUT /admin/tags      → tagHandler.UpdateTag
+PUT /admin/features  → tagHandler.UpdateFeature
+```
+
+Редактируется только `name` (ID/slug не меняется во избежание поломки связей).
+
+### Фронтенд — компонент `/admin/tags`
+
+```mermaid
+graph LR
+    A[Строка] --> B{showConfirm?}
+    B -->|нет| C[✏️🗑️]
+    B -->|да| D[✓✕]
+    C -->|✏️| E[input + ✓✕]
+    C -->|🗑️| F[text + ✓✕]
+    D -->|✓| G[saveTag / confirmDeleteTag]
+    D -->|✕| H[отмена]
+```
+
+### Анимация кнопок
+
+Используется паттерн с `absolute inset-0 overflow-hidden` контейнером и `translate-y` + `opacity`:
+
+```tsx
+<div className="relative h-5 w-12 overflow-hidden">
+  {/* ✏️🗑️ — уезжают вверх */}
+  <div className={`absolute inset-0 flex items-center gap-2 [&>button]:w-5 transition-all duration-200 ${
+    showConfirm ? '-translate-y-full opacity-0' : 'translate-y-0 opacity-100'
+  }`}>
+    <button>✏️</button>
+    <button>🗑️</button>
+  </div>
+  {/* ✓✕ — выезжают снизу */}
+  <div className={`absolute inset-0 flex items-center gap-2 [&>button]:w-5 transition-all duration-200 ${
+    showConfirm ? 'translate-y-0 opacity-100' : 'translate-y-full opacity-0'
+  }`}>
+    <button>✓</button>
+    <button>✕</button>
+  </div>
+</div>
+```
+
+`[&>button]:w-5` гарантирует идентичную ширину всех кнопок — значки ✓✕ встают точно на места ✏️🗑️.
+
+- ✓ зелёный при редактировании, красный при удалении
+- Escape / Enter работают при редактировании (input autoFocus)
+- `confirm()` браузера заменён на inline-анимацию
+
+### Единая строка
+
+Редактирование и удаление используют общий layout:
+```
+[имя (span → input)  |  id  |  кнопки]
+```
+При редактировании `span` заменяется на `input`. При удалении имя не меняется. Блок кнопок анимируется одинаково в обоих случаях.
+
+## Обнаруженные проблемы
+
+### 1. CORS: PUT не был в AllowedMethods
+
+```go
+// Было:
+AllowedMethods: []string{"GET", "POST", "PATCH", "DELETE", "OPTIONS"}
+// Стало:
+AllowedMethods: []string{"GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"}
+```
+
+Без PUT браузер блокировал preflight OPTIONS — фронтенд получал «Failed to fetch».
+
+### 2. 204 No Content при DELETE — ошибка парсинга JSON
+
+Бэкенд возвращает `w.WriteHeader(http.StatusNoContent)` (204) — тело пустое. `res.json()` на пустом теле бросал `"Unexpected end of JSON input"`.
+
+```typescript
+// api.ts — добавлена проверка
+if (res.status === 204) return undefined as T
+return res.json()
+```
+
+### 3. `api.put()` отсутствовал в клиенте
+
+Добавлен метод `put` в объект `api` (рядом с `patch`).
+
+## Связанные заметки
+
+- [[atomic-api-contract-deleted-fulldelete]] — удаление через query-параметр
+- [[MOC-frontend-patterns]] — фронтенд-паттерны
+- [[frontend-api-client]] — API client
+
+## Источник
+
+Задача: «Добавь возможность редактировать и удалять теги через админку». Коммиты: `86b0c22`, `603a3d4`, `5a4f50f`, `f137544`, `bf098a7`, `7b97fd1`, `679cdd7`.
+
+## Теги
+
+#frontend #backend #golang #nextjs #admin #animation #cors #api