Skip to content

[UX] Редирект на список проектов после успешного удаления #65

@kapitulin24

Description

@kapitulin24

Контекст

После подтверждения удаления проекта (RemoveProjectDialoguseRemoveProjectProjectHttp.removeProject) выполняется инвалидация кэша списка проектов и показывается toast, но навигация не меняется. Если удаление инициировано со страницы проекта (/team/projects/[projectId], /team/projects/[projectId]/settings), пользователь остаётся на URL несуществующего ресурса — возможны 404, ошибки загрузки деталей проекта и некорректное состояние UI (сайдбар, breadcrumbs). Требуется единообразное поведение: после успешного удаления переводить пользователя на страницу со всеми проектами команды.


Технические требования

  • Локация логики: src/features/projects/remove/ (useRemoveProject.ts, RemoveProjectDialog.tsx); точки входа: src/pages/project/ui/settings/ProjectDangerZone.tsx, src/pages/team/ui/projects/ProjectCard.tsx; маршрут назначения — routes.team.projects() (/team/projects) в src/shared/config/routes.ts
  • Инструменты: Next.js App Router (useRouter из next/navigation), TanStack Query (useMutation, invalidateQueries), существующий ProjectHttp.removeProject, sonner (toast уже в хуке)
  • Логика работы:
    1. В колбэке onSuccess мутации удаления (после успешного ответа API и до/после invalidateQueries по projectFabricKeys.list(teamSlug)) выполнить router.replace(routes.team.projects()) (предпочтительно replace, чтобы нельзя было вернуться «Назад» на удалённый проект).
    2. Редирект должен срабатывать для всех сценариев использования RemoveProjectDialog (настройки проекта, карточка на ProjectsPage) без дублирования логики в каждом потребителе — централизовать в useRemoveProject или в RemoveProjectDialog после успешной мутации.
    3. При ошибке мутации (onError) навигация не выполняется; диалог остаётся открытым или закрывается по текущему UX — без перехода.
    4. Если текущий pathname уже равен routes.team.projects(), допускается пропуск редиректа (опционально) — достаточно инвалидации списка; главное — обязательный уход со страниц /team/projects/[projectId]/*.
    5. После редиректа список проектов должен отражать удаление (существующая инвалидация projectFabricKeys.list); при необходимости сбросить projectFabricKeys.detail(teamSlug, id) для удалённого id.

Цель и критерии приемки (Definition of Done)

  • База: Навигация подключена через routes.team.projects() (без хардкода строк URL в компонентах).
  • Функционал: После успешного удаления с /team/projects/[projectId]/settings (и любой вложенной страницы проекта) пользователь оказывается на /team/projects; удалённый проект отсутствует в списке; toast «Проект удалён» сохраняется.
  • Функционал: Удаление с ProjectsPage (карточка проекта) не ломает UX: список обновляется, лишних полноэкранных переходов нет (допустим no-op редирект на ту же страницу).
  • Лимиты/SLA: Редирект выполняется один раз на успешный ответ API; нет гонки с повторным push при двойном клике (кнопка «Удалить» disabled на время isPending).
  • Интеграция: Ручная проверка: Danger Zone → удаление → URL /team/projects; карточка на списке → удаление → карточка исчезает; кнопка «Назад» в браузере не возвращает на страницу удалённого проекта (при использовании replace).

Важные указания

  • Производительность: Дополнительных запросов не требуется; один router.replace и существующая инвалидация списка.
  • Ошибки: При 4xx/5xx от DELETE /teams/{teamSlug}/projects/{id} оставить текущую обработку мутации (toast error при наличии в проекте); редирект только на onSuccess.
  • Безопасность: Не ослаблять проверки canEdit / disabled на RemoveProjectDialog; редирект не должен маскировать отказ API (403/404). Удаление по-прежнему только через подтверждение имени проекта в диалоге.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions