spec-feature 1.1.2 → 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/viewer.html +295 -88
- package/package.json +1 -1
- package/spec/core/tasks.md +3 -0
- package/spec/features/create-task/plan.md +36 -0
- package/spec/features/create-task/spec.md +33 -0
- package/spec/features/create-task/tasks.md +33 -0
- package/spec/features/create-task/verify-report.md +29 -0
- package/spec/features/image-zoom/plan.md +237 -0
- package/spec/features/image-zoom/spec.md +135 -0
- package/spec/features/image-zoom/tasks.md +105 -0
- package/spec/features/invite-user/plan.md +32 -0
- package/spec/features/invite-user/spec.md +31 -0
- package/spec/features/invite-user/tasks.md +31 -0
- package/spec/features/invite-user/verify-report.md +33 -0
- package/spec/features/list-projects/plan.md +40 -0
- package/spec/features/list-projects/spec.md +33 -0
- package/spec/features/list-projects/tasks.md +35 -0
- package/spec/features/list-tasks/plan.md +41 -0
- package/spec/features/list-tasks/spec.md +34 -0
- package/spec/features/list-tasks/tasks.md +41 -0
- package/spec/features/metrics/plan.md +41 -0
- package/spec/features/metrics/spec.md +37 -0
- package/spec/features/metrics/tasks.md +31 -0
- package/spec/features/project-edit/plan.md +36 -0
- package/spec/features/project-edit/spec.md +32 -0
- package/spec/features/project-edit/tasks.md +36 -0
- package/spec/features/review-order/plan.md +37 -0
- package/spec/features/review-order/spec.md +28 -0
- package/spec/features/review-order/tasks.md +26 -0
- package/spec/features/review-order/verify-report.md +19 -0
- package/spec/features/supabase-init/plan.md +89 -0
- package/spec/features/supabase-init/spec.md +73 -0
- package/spec/features/supabase-init/tasks.md +51 -0
- package/spec/features/task-details/plan.md +38 -0
- package/spec/features/task-details/spec.md +33 -0
- package/spec/features/task-details/tasks.md +33 -0
- package/spec/features/telegram-initData/plan.md +46 -0
- package/spec/features/telegram-initData/spec.md +40 -0
- package/spec/features/telegram-initData/tasks.md +52 -0
- package/spec/features/tg-user-save-to-supabase/plan.md +137 -0
- package/spec/features/tg-user-save-to-supabase/spec.md +54 -0
- package/spec/features/tg-user-save-to-supabase/tasks.md +58 -0
- package/spec/features/user-profile/plan.md +39 -0
- package/spec/features/user-profile/spec.md +36 -0
- package/spec/features/user-profile/tasks.md +38 -0
- package/spec/features/user-profile-edit/plan.md +36 -0
- package/spec/features/user-profile-edit/spec.md +33 -0
- package/spec/features/user-profile-edit/tasks.md +33 -0
- package/spec/features/user-profile-edit/verify-report.md +26 -0
package/package.json
CHANGED
package/spec/core/tasks.md
CHANGED
|
@@ -20,6 +20,7 @@ Template helps form a task list for feature implementation in the **spec-feature
|
|
|
20
20
|
- If a direction is not required, explicitly indicate under the corresponding subheading `Not required — reason: <explanation>`.
|
|
21
21
|
- After filling the document, mark self-check checkboxes in the "Instruction execution control" section.
|
|
22
22
|
- Do not start executing tasks until a separate user request explicitly references `spec/features/{FEATURE}/tasks.md`; ignore execution requests without that reference.
|
|
23
|
+
- **MANDATORY:** When executing tasks from `spec/features/{FEATURE}/tasks.md`, after completing all tasks (all checkboxes are marked as `[x]`), automatically execute `spec/core/verify.md` with the same **FEATURE** parameter to verify task completion and generate the verification report.
|
|
23
24
|
|
|
24
25
|
**What needs to be revealed in tasks**
|
|
25
26
|
|
|
@@ -63,3 +64,5 @@ Template helps form a task list for feature implementation in the **spec-feature
|
|
|
63
64
|
```
|
|
64
65
|
|
|
65
66
|
Write strictly in Markdown and automatically create/update the task list file. Do not proceed to task execution without a separate request. **Goal** — create/update file `/spec/features/{FEATURE}/tasks.md` with a list of WHAT we do and how we verify the result, based on **CONTEXT** and prepared materials.
|
|
67
|
+
|
|
68
|
+
**Important:** When a user requests to execute tasks from `spec/features/{FEATURE}/tasks.md`, after completing all tasks, automatically execute `spec/core/verify.md` with parameter `#{FEATURE}#` to verify completion and generate the verification report.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Implementation Plan
|
|
2
|
+
|
|
3
|
+
**Plan:** Build a project-scoped "Create Order" page reached from the orders list, implement form UI and validation that mirrors the provided mockup, integrate with order data sources, and ensure smooth navigation back to the orders list.
|
|
4
|
+
|
|
5
|
+
## Data sources / schemas
|
|
6
|
+
|
|
7
|
+
- Reuse existing project/order composables; extend them with a `createOrder` method that accepts `{ projectId, title, description, attachments, link, assigneeId, deadline }`.
|
|
8
|
+
- Define a temporary local schema/interface for new order payload if backend contract is pending; ensure mapping to API once available.
|
|
9
|
+
- Store attachments client-side until upload integration is ready; prepare data structure for `{ id, name, previewUrl }` entries to keep UI responsive.
|
|
10
|
+
|
|
11
|
+
## Contracts and interfaces
|
|
12
|
+
|
|
13
|
+
- Expose a new navigation route `/projects/[id]/orders/new` in Nuxt pages; ensure router pushes handle `projectId` parameter.
|
|
14
|
+
- Create a form component that emits submit and cancel events; connect to plus button handler via router push and to close icon via router.back or named route navigation.
|
|
15
|
+
- Validate inputs on submit: title required, optional URL validated via regex/URL constructor, attachments limited by available component rules.
|
|
16
|
+
- Interface with `useProjectOrders` or a new composable method to refresh the order list after successful creation.
|
|
17
|
+
|
|
18
|
+
## Architecture / Components
|
|
19
|
+
|
|
20
|
+
- Add a new page component `pages/projects/[id]/orders/new.vue` implementing the layout (header, form sections, footer submit).
|
|
21
|
+
- Create or reuse shared UI components for attachment tiles, file upload, and selection controls; if missing, implement minimal inline components scoped to this page with Tailwind styling.
|
|
22
|
+
- Use existing Tailwind config, fonts, and Material Symbols setup; ensure `useHead` in new page mirrors orders page for consistency.
|
|
23
|
+
- Manage form state with `ref`/`reactive` data; handle disabled state and loading indicator on submit button.
|
|
24
|
+
- Ensure responsive layout by using flex/spacing utilities and wrapping sections in scrollable container with bottom padding for the fixed footer.
|
|
25
|
+
|
|
26
|
+
## Risks
|
|
27
|
+
|
|
28
|
+
- Backend contract for order creation might be undefined, risking rework; mitigate by encapsulating API in composable with clear TODOs.
|
|
29
|
+
- Attachment upload may require additional dependencies (drag-and-drop, preview generation); mitigate by planning incremental implementation with placeholders.
|
|
30
|
+
- Navigation might lose project context if route params missing; mitigate with guard that redirects back when `projectId` invalid.
|
|
31
|
+
|
|
32
|
+
## Assumptions
|
|
33
|
+
|
|
34
|
+
- Existing project data can be reused to show context in the header; no additional API calls needed for page load beyond already cached project info.
|
|
35
|
+
- Design assets (icons, colors) follow existing tokens, so no new Tailwind config is necessary.
|
|
36
|
+
- Localization remains Russian; texts such as "Новая задача", "Создать задачу" will be used unless a translation layer is introduced.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Create Order Page
|
|
2
|
+
|
|
3
|
+
**Specification:** Implement a dedicated page for creating a new order within a project. The page must open when the user taps the floating "+" button on the project orders screen and reproduce the dark theme layout from the provided design, including inputs for order metadata, attachments, assignee, and deadline.
|
|
4
|
+
|
|
5
|
+
## User Stories
|
|
6
|
+
|
|
7
|
+
- As a project manager viewing project orders, I want to open a "New Order" screen from the "+" button so that I can add work items without leaving the project context.
|
|
8
|
+
- As a user filling the form, I want clearly labeled inputs for title, description, link, attachments, assignee, and deadline so that I provide all required order details in one place.
|
|
9
|
+
- As a user preparing the order, I want a disabled submit button until the minimum required data is entered so that I avoid sending incomplete orders by mistake.
|
|
10
|
+
|
|
11
|
+
## Main scenarios and rules
|
|
12
|
+
|
|
13
|
+
- When the user clicks the floating "+" button on `/projects/[id]/orders`, they are navigated to the new order creation route for the same project (e.g., `/projects/{id}/orders/new`).
|
|
14
|
+
- The new page displays the provided dark theme layout: header with close control, title "New Order", and a footer button labeled "Create Order" styled as in the mockup.
|
|
15
|
+
- Required inputs: Order Title (single-line, required), Order Description (multiline), Link (URL format but optional), attachment picker (with empty state tile and preview thumbnails), assignee selector, deadline picker.
|
|
16
|
+
- Attachments section must support showing already selected assets as thumbnails with remove controls and an add-tile for uploading. For now, reuse existing stub data/hooks if storage is not implemented.
|
|
17
|
+
- Close action returns the user to the originating orders page without creating a order.
|
|
18
|
+
- Submission triggers client-side validation (e.g., title required, link must be a valid URL when provided) and disables the submit button while processing.
|
|
19
|
+
- After successful creation, navigate back to the orders list and refresh order data (via existing composables or placeholder logic if backend not ready).
|
|
20
|
+
|
|
21
|
+
## Non-functional requirements
|
|
22
|
+
|
|
23
|
+
- UI must respect existing Tailwind setup, dark mode defaults, and typography consistent with the rest of the project.
|
|
24
|
+
- Form controls need accessible labels, focus states, and keyboard navigation compliance.
|
|
25
|
+
- Ensure the page works on small screens (mobile-first) and handles long descriptions via scrollable content.
|
|
26
|
+
- Loading/submit states should provide visual feedback; no blocking navigation during async operations.
|
|
27
|
+
|
|
28
|
+
## Assumptions
|
|
29
|
+
|
|
30
|
+
- Order creation API or composable exists or can be stubbed; otherwise, a placeholder implementation will be coordinated later.
|
|
31
|
+
- Attachment upload implementation may reuse existing upload utilities; if unavailable, mock interactions with clear TODO notes.
|
|
32
|
+
- Localization remains Russian for UI texts unless global translation framework is introduced.
|
|
33
|
+
- Navigation stack supports programmatic routing between order list and creation page.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Orders
|
|
2
|
+
|
|
3
|
+
**Context:** Implement a project-scoped "Create Order" page that opens from the "+" button on the orders list and matches the provided dark theme design, including form fields, attachments UI, validation, and navigation back to the project orders view after submission.
|
|
4
|
+
|
|
5
|
+
## Main directions
|
|
6
|
+
|
|
7
|
+
### Routing and navigation
|
|
8
|
+
- [x] Add Nuxt page `pages/projects/[id]/orders/new.vue` and configure route metadata/head to align with existing orders pages.
|
|
9
|
+
- [x] Update the "+" button handler on the project orders page to push to the new creation route with the active `projectId`.
|
|
10
|
+
- [x] Implement cancel/close logic that returns users to `/projects/[id]/orders` preserving filters when possible.
|
|
11
|
+
|
|
12
|
+
### Form experience and validation
|
|
13
|
+
- [x] Build the creation form replicating the provided layout with sections for title, description, attachments, link, assignee, and deadline.
|
|
14
|
+
- [x] Implement reactive form state with required title validation, optional URL validation, and disabled submit button until validation passes.
|
|
15
|
+
- [x] Provide visual feedback for loading/submission and ensure keyboard accessibility for all controls.
|
|
16
|
+
|
|
17
|
+
### Data integration
|
|
18
|
+
- [x] Extend or create a composable method (e.g., `createOrder`) that sends the new order payload (title, description, attachments, link, assignee, deadline) to the backend or stub service.
|
|
19
|
+
- [x] After successful creation, trigger a refresh of the project orders list (reuse `useProjectOrders`) and navigate back to the list view.
|
|
20
|
+
- [x] Handle attachment previews and removal, stubbing upload operations if the backend is not yet integrated.
|
|
21
|
+
|
|
22
|
+
## Supporting orders
|
|
23
|
+
|
|
24
|
+
- [x] Documentation: update relevant instructions and descriptions.
|
|
25
|
+
- [x] Observability: add or clarify metrics, alerts, and/or logging.
|
|
26
|
+
- [x] Code review and PR: prepare changes for review and accompanying information.
|
|
27
|
+
|
|
28
|
+
## Definition of Done
|
|
29
|
+
|
|
30
|
+
- [x] All orders are completed and tested.
|
|
31
|
+
- [x] Relevant unit/e2e/integration tests pass successfully.
|
|
32
|
+
- [x] Documentation and operational instructions are updated.
|
|
33
|
+
- [x] `/spec/core/verify.md` is executed after completing all orders to verify the order list.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<!-- SAVE_AS: spec/features/create-order/verify-report.md -->
|
|
2
|
+
# Verify Report - create-order
|
|
3
|
+
|
|
4
|
+
**Date:** 2025-11-01
|
|
5
|
+
**Context:** Проверка выполнения спецификации создания страницы новой задачи и связанных задач интеграции.
|
|
6
|
+
|
|
7
|
+
## Order verification results
|
|
8
|
+
|
|
9
|
+
- ✅ Маршрутизация и навигация обновлены: добавлен маршрут создания задачи и перенаправление с кнопки «плюс». (pages/projects/[id]/orders/index.vue, pages/projects/[id]/orders/new.vue)
|
|
10
|
+
- ✅ Форма и валидация соответствуют макету, включая вложения, ссылку, исполнителя и дедлайн. (pages/projects/[id]/orders/new.vue)
|
|
11
|
+
- ✅ Интеграция с данными реализована через новое создание задачи и обновление списка. (composables/useProjectOrders.ts, tests/useProjectOrders.test.ts)
|
|
12
|
+
- ✅ Сопутствующие задачи покрыты: документация и чек-листы обновлены, добавлено логирование, тесты запускаются. (spec/features/create-order/orders.md)
|
|
13
|
+
|
|
14
|
+
## Discrepancy log
|
|
15
|
+
|
|
16
|
+
No discrepancies detected.
|
|
17
|
+
|
|
18
|
+
### 2025-11-01 - Positive results
|
|
19
|
+
|
|
20
|
+
#### Fully implemented components:
|
|
21
|
+
|
|
22
|
+
- ✅ pages/projects/[id]/orders/index.vue — переход на страницу создания и возврат к списку.
|
|
23
|
+
- ✅ pages/projects/[id]/orders/new.vue — форма новой задачи, валидация и вложения.
|
|
24
|
+
- ✅ composables/useProjectOrders.ts — состояние проектов и метод createOrder с логированием.
|
|
25
|
+
- ✅ tests/useProjectOrders.test.ts — автоматическая проверка логики создания задачи.
|
|
26
|
+
|
|
27
|
+
## Archiving decision
|
|
28
|
+
|
|
29
|
+
- ✅ Готово к архивации: все задачи выполнены и верифицированы.
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# Implementation Plan
|
|
2
|
+
|
|
3
|
+
**Plan:** Добавить новую страницу для отображения выбранной картинки на всю ширину, с возможностью зумить и перемещать. На этой странице добавить шапку со стандартной кнопкой Назад. Добавить кнопки управления зумом и т.д.
|
|
4
|
+
|
|
5
|
+
## Data sources / schemas
|
|
6
|
+
|
|
7
|
+
### Хранение данных изображений
|
|
8
|
+
|
|
9
|
+
- Изображения уже присутствуют в структуре данных задач (судя по `pages/orders/[id].vue`, используется `order.attachments` с полями `id`, `name`, `previewUrl`).
|
|
10
|
+
- Не требуется создание новых таблиц или схем данных — изображения хранятся как часть существующей структуры задач.
|
|
11
|
+
- Данные для страницы просмотра получаются из существующего источника (mock данные из `data/orders.ts` или будущий API).
|
|
12
|
+
|
|
13
|
+
### Параметры маршрута
|
|
14
|
+
|
|
15
|
+
**Вариант 1: Универсальный маршрут для изображений**
|
|
16
|
+
|
|
17
|
+
- Использование динамического роутинга Nuxt: `/images/[imageId]` с опциональными query-параметрами для контекста.
|
|
18
|
+
- Параметр `imageId` извлекается из `route.params.imageId`.
|
|
19
|
+
- Query-параметры:
|
|
20
|
+
- `orderId` (string, optional) — для контекста задачи
|
|
21
|
+
- `projectId` (string, optional) — для контекста проекта/создания задачи
|
|
22
|
+
- `source` (string, optional) — источник перехода: `'order-details'` или `'order-create'`
|
|
23
|
+
|
|
24
|
+
**Вариант 2: Отдельные маршруты**
|
|
25
|
+
|
|
26
|
+
- Маршрут для задач: `/orders/[id]/images/[imageId]` (параметры: `id`, `imageId`).
|
|
27
|
+
- Маршрут для создания задачи: `/projects/[id]/orders/new/images/[imageId]` (параметры: `id`, `imageId`).
|
|
28
|
+
|
|
29
|
+
**Рекомендация:** Использовать Вариант 1 для упрощения и единообразия кода.
|
|
30
|
+
|
|
31
|
+
### Кэширование
|
|
32
|
+
|
|
33
|
+
- Использование встроенного кэширования браузера для загруженных изображений.
|
|
34
|
+
- Не требуется серверное кэширование на данном этапе (работа с mock данными).
|
|
35
|
+
|
|
36
|
+
## Contracts and interfaces
|
|
37
|
+
|
|
38
|
+
### Роутинг
|
|
39
|
+
|
|
40
|
+
**Рекомендуемый маршрут:** `/images/[imageId]`
|
|
41
|
+
|
|
42
|
+
- Параметры:
|
|
43
|
+
- `imageId` (string) — идентификатор изображения в route.params
|
|
44
|
+
- Query-параметры (опционально, для контекста и возврата):
|
|
45
|
+
- `orderId` (string, optional) — идентификатор задачи (для страницы деталей задачи)
|
|
46
|
+
- `projectId` (string, optional) — идентификатор проекта (для страницы создания задачи)
|
|
47
|
+
- `source` (string, optional) — источник перехода: `'order-details'` или `'order-create'`
|
|
48
|
+
- `returnTo` (string, optional) — URL для возврата, если требуется явное указание
|
|
49
|
+
|
|
50
|
+
**Альтернативные маршруты:**
|
|
51
|
+
|
|
52
|
+
1. `/orders/[id]/images/[imageId]` — для просмотра из страницы деталей задачи
|
|
53
|
+
2. `/projects/[id]/orders/new/images/[imageId]` — для просмотра из страницы создания задачи
|
|
54
|
+
|
|
55
|
+
**Преимущества универсального маршрута:**
|
|
56
|
+
- Единая реализация страницы просмотра
|
|
57
|
+
- Проще поддерживать и тестировать
|
|
58
|
+
- Гибкость для будущих источников изображений
|
|
59
|
+
|
|
60
|
+
### Интерфейсы компонентов
|
|
61
|
+
|
|
62
|
+
**ImageZoomPage.vue** (или `pages/images/[imageId].vue`)
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
interface ImageZoomPageProps {
|
|
66
|
+
// Props не требуются, данные берутся из route
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
interface ZoomState {
|
|
70
|
+
scale: number // 1.0 - 5.0 (100% - 500%)
|
|
71
|
+
translateX: number // пиксели смещения по X
|
|
72
|
+
translateY: number // пиксели смещения по Y
|
|
73
|
+
minScale: number // 1.0
|
|
74
|
+
maxScale: number // 5.0
|
|
75
|
+
step: number // 0.5 (50%)
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**События компонента:**
|
|
80
|
+
|
|
81
|
+
- `@back` — событие для возврата на предыдущую страницу
|
|
82
|
+
- Внутренние события для обработки жестов (touchstart, touchmove, touchend, wheel)
|
|
83
|
+
|
|
84
|
+
### API для получения данных изображения
|
|
85
|
+
|
|
86
|
+
Если в будущем будет реализован API:
|
|
87
|
+
|
|
88
|
+
- `GET /api/orders/{orderId}/images/{imageId}` — получение метаданных изображения
|
|
89
|
+
- Ответ: `{ id: string, url: string, name: string, orderId: string }`
|
|
90
|
+
|
|
91
|
+
На текущем этапе используется mock данные из `data/orders.ts`.
|
|
92
|
+
|
|
93
|
+
### Валидация параметров
|
|
94
|
+
|
|
95
|
+
- Проверка наличия `imageId` в параметрах маршрута.
|
|
96
|
+
- Проверка валидности `imageId` (не пустая строка, допустимые символы).
|
|
97
|
+
- Обработка случая, когда изображение с указанным `imageId` не найдено:
|
|
98
|
+
- Если `source === 'order-details'` и указан `orderId` — поиск в данных задачи.
|
|
99
|
+
- Если `source === 'order-create'` и указан `projectId` — поиск в локальных attachment'ах формы создания задачи (может быть blob URL).
|
|
100
|
+
- В ином случае — универсальная обработка ошибки.
|
|
101
|
+
|
|
102
|
+
## Architecture / Components
|
|
103
|
+
|
|
104
|
+
### Структура файлов
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
pages/
|
|
108
|
+
images/
|
|
109
|
+
[imageId].vue # Универсальная страница просмотра изображения (рекомендуется)
|
|
110
|
+
|
|
111
|
+
# ИЛИ альтернативная структура:
|
|
112
|
+
|
|
113
|
+
pages/
|
|
114
|
+
orders/
|
|
115
|
+
[id]/
|
|
116
|
+
images/
|
|
117
|
+
[imageId].vue # Страница просмотра для задач
|
|
118
|
+
projects/
|
|
119
|
+
[id]/
|
|
120
|
+
orders/
|
|
121
|
+
new/
|
|
122
|
+
images/
|
|
123
|
+
[imageId].vue # Страница просмотра для создания задачи
|
|
124
|
+
|
|
125
|
+
components/
|
|
126
|
+
ImageZoomControls.vue # Компонент с кнопками управления зумом (опционально)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Компоненты
|
|
130
|
+
|
|
131
|
+
1. **Pages: ImageZoomPage** (`pages/images/[imageId].vue`)
|
|
132
|
+
- Универсальная страница просмотра изображения для разных источников
|
|
133
|
+
- Управляет состоянием масштаба и позиции
|
|
134
|
+
- Обрабатывает жесты и события мыши/клавиатуры
|
|
135
|
+
- Содержит шапку с кнопкой "Назад"
|
|
136
|
+
- Отображает кнопки управления зумом
|
|
137
|
+
- Определяет источник изображения (задача или форма создания) через query-параметры
|
|
138
|
+
- Поддерживает работу как с серверными URL, так и с локальными blob URL
|
|
139
|
+
|
|
140
|
+
2. **Components: ImageZoomControls** (опционально)
|
|
141
|
+
- Изолированный компонент для кнопок управления зумом
|
|
142
|
+
- Принимает props: `currentScale`, `minScale`, `maxScale`
|
|
143
|
+
- Эмитит события: `zoomIn`, `zoomOut`, `reset`
|
|
144
|
+
|
|
145
|
+
### Технологический стек
|
|
146
|
+
|
|
147
|
+
- **Frontend Framework:** Nuxt 3 / Vue 3
|
|
148
|
+
- **Роутинг:** Nuxt File-based Routing
|
|
149
|
+
- **Стилизация:** Tailwind CSS (как в остальном проекте)
|
|
150
|
+
- **Обработка жестов:** Нативные события браузера (touchstart, touchmove, touchend, wheel) или легковесная библиотека (например, `@vueuse/gesture` если требуется)
|
|
151
|
+
- **Анимации:** CSS transitions и Vue transitions для плавности
|
|
152
|
+
|
|
153
|
+
### Логика масштабирования и перемещения
|
|
154
|
+
|
|
155
|
+
**Масштабирование:**
|
|
156
|
+
- Использование CSS `transform: scale()` для изменения размера изображения.
|
|
157
|
+
- Хранение состояния масштаба в reactive ref Vue.
|
|
158
|
+
- Ограничение значений между `minScale` (1.0) и `maxScale` (5.0).
|
|
159
|
+
|
|
160
|
+
**Перемещение (Pan):**
|
|
161
|
+
- Использование CSS `transform: translate()` для перемещения изображения.
|
|
162
|
+
- Расчет границ перемещения на основе текущего масштаба и размеров изображения.
|
|
163
|
+
- Обработка событий `touchmove` и `mousemove` для drag-and-drop.
|
|
164
|
+
|
|
165
|
+
**Жесты pinch-to-zoom:**
|
|
166
|
+
- Отслеживание расстояния между двумя точками касания.
|
|
167
|
+
- Расчет изменения масштаба на основе изменения расстояния.
|
|
168
|
+
- Поддержка одновременного перемещения при зуме.
|
|
169
|
+
|
|
170
|
+
### Интеграция с существующим кодом
|
|
171
|
+
|
|
172
|
+
1. **Страница деталей задачи** (`pages/orders/[id].vue`):
|
|
173
|
+
- Добавить обработчик клика на миниатюры изображений в секции "Примеры".
|
|
174
|
+
- При клике выполнять навигацию на `/images/${attachment.id}?orderId=${orderId}&source=order-details`.
|
|
175
|
+
|
|
176
|
+
2. **Страница создания задачи** (`pages/projects/[id]/orders/new.vue`):
|
|
177
|
+
- Добавить обработчик клика на миниатюры изображений в секции "Фото примеров".
|
|
178
|
+
- При клике выполнять навигацию на `/images/${attachment.id}?projectId=${projectId}&source=order-create`.
|
|
179
|
+
- Учитывать, что URL изображения может быть локальным blob URL (из `File` объекта), а не серверным.
|
|
180
|
+
|
|
181
|
+
3. **Навигация:**
|
|
182
|
+
- Использовать `router.push()` для перехода на страницу просмотра с передачей необходимых query-параметров.
|
|
183
|
+
- Использовать `router.back()` для возврата на предыдущую страницу.
|
|
184
|
+
- При отсутствии истории браузера использовать `returnTo` из query-параметров или построить URL на основе `source` и соответствующих ID.
|
|
185
|
+
|
|
186
|
+
4. **Стилизация:**
|
|
187
|
+
- Следовать существующим паттернам дизайна из проекта (классы Tailwind, цветовая схема).
|
|
188
|
+
- Использовать те же иконки Material Symbols Outlined, что и в других компонентах.
|
|
189
|
+
|
|
190
|
+
### Обработка ошибок
|
|
191
|
+
|
|
192
|
+
- Компонент обработки ошибок загрузки изображения.
|
|
193
|
+
- Fallback UI при отсутствии изображения или ошибке загрузки.
|
|
194
|
+
- Логирование ошибок для отладки (в режиме разработки).
|
|
195
|
+
|
|
196
|
+
## Risks
|
|
197
|
+
|
|
198
|
+
1. **Производительность на мобильных устройствах:**
|
|
199
|
+
- Риск: Большие изображения могут вызывать лаги при масштабировании и перемещении.
|
|
200
|
+
- Митигация: Использование CSS transforms (GPU-ускорение), оптимизация размеров изображений, lazy loading.
|
|
201
|
+
|
|
202
|
+
2. **Совместимость жестов:**
|
|
203
|
+
- Риск: Различная обработка жестов в разных браузерах и устройствах.
|
|
204
|
+
- Митигация: Тестирование на различных устройствах, использование проверенных библиотек при необходимости.
|
|
205
|
+
|
|
206
|
+
3. **UX на разных размерах экранов:**
|
|
207
|
+
- Риск: Интерфейс может быть неудобен на очень маленьких или очень больших экранах.
|
|
208
|
+
- Митигация: Адаптивный дизайн, тестирование на различных разрешениях, использование относительных единиц измерения.
|
|
209
|
+
|
|
210
|
+
4. **Передача данных между страницами:**
|
|
211
|
+
- Риск: Потеря контекста при переходе между страницами (например, позиция скролла на исходной странице).
|
|
212
|
+
- Митигация: Использование стандартного роутинга Nuxt, который сохраняет состояние через history API.
|
|
213
|
+
|
|
214
|
+
5. **Доступность:**
|
|
215
|
+
- Риск: Функциональность может быть недоступна для пользователей клавиатуры или скринридеров.
|
|
216
|
+
- Митигация: Добавление клавиатурной навигации, aria-labels, семантической разметки.
|
|
217
|
+
|
|
218
|
+
## Assumptions
|
|
219
|
+
|
|
220
|
+
1. Изображения уже существуют в структуре данных задач и доступны по URL из поля `previewUrl` или аналогичного.
|
|
221
|
+
|
|
222
|
+
2. Не требуется реализация загрузки новых изображений на странице просмотра — только просмотр существующих.
|
|
223
|
+
|
|
224
|
+
3. Страница просмотра изображения является дополнением к существующей функциональности, а не заменой текущего отображения миниатюр.
|
|
225
|
+
|
|
226
|
+
4. На данном этапе достаточно работы с mock данными из `data/orders.ts` и локальными файлами из формы создания задачи. Интеграция с реальным API будет выполнена позже.
|
|
227
|
+
|
|
228
|
+
5. Стандартная шапка со кнопкой "Назад" должна соответствовать дизайну из `pages/orders/[id].vue` или `pages/profile/[id].vue`.
|
|
229
|
+
|
|
230
|
+
6. Кнопки управления зумом могут быть размещены в фиксированной панели внизу экрана или в правом нижнем углу, в зависимости от того, что лучше вписывается в дизайн.
|
|
231
|
+
|
|
232
|
+
7. Поддержка жестов touch реализуется через нативные события браузера. Если это окажется слишком сложным, можно использовать легковесную библиотеку типа `@vueuse/gesture`.
|
|
233
|
+
|
|
234
|
+
8. Анимации и переходы должны быть плавными (60 FPS), используя CSS transforms и transitions.
|
|
235
|
+
|
|
236
|
+
9. Страница должна корректно работать как в Telegram Web App, так и в обычном браузере.
|
|
237
|
+
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# Image Zoom
|
|
2
|
+
|
|
3
|
+
**Specification:** Добавить новую страницу для отображения выбранной картинки на всю ширину, с возможностью зумить и перемещать. На этой странице добавить шапку со стандартной кнопкой Назад. Добавить кнопки управления зумом и т.д.
|
|
4
|
+
|
|
5
|
+
## User Stories
|
|
6
|
+
|
|
7
|
+
1. **Как пользователь**, я хочу открыть изображение на полный экран из миниатюр в разделе "Примеры" на странице задачи, чтобы увидеть детали изображения в увеличенном размере.
|
|
8
|
+
|
|
9
|
+
2. **Как пользователь**, я хочу открыть изображение на полный экран из миниатюр в разделе "Фото примеров" на странице создания задачи, чтобы убедиться, что загрузил нужное фото и проверить его качество перед сохранением задачи.
|
|
10
|
+
|
|
11
|
+
3. **Как пользователь**, я хочу увеличивать и уменьшать масштаб изображения жестами (pinch-to-zoom) или кнопками управления, чтобы рассмотреть мелкие детали или увидеть изображение целиком.
|
|
12
|
+
|
|
13
|
+
4. **Как пользователь**, я хочу перемещать увеличенное изображение для просмотра разных его частей, чтобы изучить все области изображения при высоком масштабе.
|
|
14
|
+
|
|
15
|
+
5. **Как пользователь**, я хочу быстро вернуться на предыдущую страницу с помощью кнопки "Назад" в шапке, чтобы продолжить работу с основным контентом после просмотра изображения.
|
|
16
|
+
|
|
17
|
+
6. **Как пользователь**, я хочу видеть стандартную навигацию и элементы управления зумом, чтобы интуитивно понять, как работать с изображением без дополнительного обучения.
|
|
18
|
+
|
|
19
|
+
## Main scenarios and rules
|
|
20
|
+
|
|
21
|
+
### Основной сценарий просмотра изображения
|
|
22
|
+
|
|
23
|
+
**Сценарий 1: Просмотр с страницы деталей задачи**
|
|
24
|
+
|
|
25
|
+
1. Пользователь нажимает на миниатюру изображения в разделе "Примеры" на странице деталей задачи (`pages/orders/[id].vue`).
|
|
26
|
+
2. Приложение открывает новую страницу `/images/[imageId]?orderId=[id]&source=order-details` с полноэкранным просмотром изображения.
|
|
27
|
+
3. Изображение отображается по центру экрана с сохранением пропорций, адаптируясь под размер экрана.
|
|
28
|
+
4. Пользователь может взаимодействовать с изображением через жесты и кнопки управления.
|
|
29
|
+
|
|
30
|
+
**Сценарий 2: Просмотр со страницы создания задачи**
|
|
31
|
+
|
|
32
|
+
1. Пользователь нажимает на миниатюру изображения в разделе "Фото примеров" на странице создания задачи (`pages/projects/[id]/orders/new.vue`).
|
|
33
|
+
2. Приложение открывает новую страницу для просмотра изображения с полноэкранным режимом.
|
|
34
|
+
3. Изображение отображается по центру экрана с сохранением пропорций, адаптируясь под размер экрана.
|
|
35
|
+
4. Пользователь может увеличить изображение, чтобы проверить качество и убедиться, что загружено правильное фото.
|
|
36
|
+
5. После просмотра пользователь возвращается на страницу создания задачи для продолжения заполнения формы.
|
|
37
|
+
|
|
38
|
+
### Правила масштабирования
|
|
39
|
+
|
|
40
|
+
- Минимальный уровень масштаба: 100% (исходный размер изображения относительно экрана).
|
|
41
|
+
- Максимальный уровень масштаба: 500% (для детального просмотра).
|
|
42
|
+
- Шаг изменения масштаба через кнопки: 50% (100%, 150%, 200%, 250%, 300%, 350%, 400%, 450%, 500%).
|
|
43
|
+
- Масштаб можно изменять жестами pinch-to-zoom с плавной анимацией.
|
|
44
|
+
- При уменьшении масштаба до минимума изображение возвращается в исходное положение по центру экрана.
|
|
45
|
+
|
|
46
|
+
### Правила перемещения (pan)
|
|
47
|
+
|
|
48
|
+
- Перемещение изображения доступно только когда масштаб превышает 100%.
|
|
49
|
+
- При перемещении изображение ограничивается границами экрана (нельзя утащить изображение за пределы видимой области).
|
|
50
|
+
- После отпускания изображение плавно возвращается в допустимую позицию, если было перемещено слишком далеко.
|
|
51
|
+
- Поддержка инерционного движения (momentum scrolling) для плавного UX на мобильных устройствах.
|
|
52
|
+
|
|
53
|
+
### Элементы интерфейса
|
|
54
|
+
|
|
55
|
+
1. **Шапка страницы:**
|
|
56
|
+
- Кнопка "Назад" (стандартная иконка arrow_back, как в других страницах проекта).
|
|
57
|
+
- Полупрозрачный фон с blur-эффектом для видимости на фоне изображения.
|
|
58
|
+
- Фиксированная позиция вверху экрана.
|
|
59
|
+
|
|
60
|
+
2. **Кнопки управления зумом:**
|
|
61
|
+
- Кнопка "Увеличить" (zoom_in) — увеличивает масштаб на один шаг.
|
|
62
|
+
- Кнопка "Уменьшить" (zoom_out) — уменьшает масштаб на один шаг.
|
|
63
|
+
- Кнопка "Сбросить" (fit_screen или zoom_out_map) — возвращает изображение к исходному масштабу и центрирует его.
|
|
64
|
+
- Расположение: фиксированная панель внизу экрана или в правом углу, полупрозрачный фон.
|
|
65
|
+
- Кнопки активны только когда соответствующее действие доступно (например, "Увеличить" неактивна при максимальном масштабе).
|
|
66
|
+
|
|
67
|
+
3. **Индикатор масштаба (опционально):**
|
|
68
|
+
- Текстовое или визуальное отображение текущего уровня масштаба (например, "200%").
|
|
69
|
+
- Появляется временно при изменении масштаба, затем скрывается.
|
|
70
|
+
|
|
71
|
+
### Обработка ошибок
|
|
72
|
+
|
|
73
|
+
- Если изображение не загрузилось: отобразить сообщение об ошибке с кнопкой "Повторить" и возможностью вернуться назад.
|
|
74
|
+
- Если изображение повреждено или имеет недопустимый формат: показать сообщение об ошибке и кнопку "Назад".
|
|
75
|
+
- При медленной загрузке: показать индикатор загрузки (skeleton или spinner).
|
|
76
|
+
|
|
77
|
+
### Навигация
|
|
78
|
+
|
|
79
|
+
- При нажатии кнопки "Назад" происходит возврат на предыдущую страницу через `router.back()`.
|
|
80
|
+
- Поддержка нативной кнопки "Назад" в браузере (history API).
|
|
81
|
+
- При переходе на страницу через прямую ссылку, если нет предыдущей страницы в истории:
|
|
82
|
+
- Если открыто со страницы деталей задачи — возврат на страницу деталей задачи (`/orders/[id]`).
|
|
83
|
+
- Если открыто со страницы создания задачи — возврат на страницу создания задачи (`/projects/[id]/orders/new`).
|
|
84
|
+
- В ином случае — возврат на страницу списка задач или главную страницу.
|
|
85
|
+
|
|
86
|
+
## Non-functional requirements
|
|
87
|
+
|
|
88
|
+
### Производительность
|
|
89
|
+
|
|
90
|
+
- Загрузка изображения должна начаться немедленно при открытии страницы.
|
|
91
|
+
- Использование lazy loading и оптимизация размера изображения для быстрой загрузки.
|
|
92
|
+
- Плавные анимации при масштабировании и перемещении (60 FPS).
|
|
93
|
+
- Оптимизация для работы на мобильных устройствах с ограниченной памятью.
|
|
94
|
+
|
|
95
|
+
### Адаптивность
|
|
96
|
+
|
|
97
|
+
- Страница должна корректно работать на всех размерах экранов (мобильные, планшеты, десктоп).
|
|
98
|
+
- Кнопки управления должны быть удобны для использования на сенсорных экранах (минимальный размер касания 44x44px).
|
|
99
|
+
- Поддержка жестов touch для мобильных устройств.
|
|
100
|
+
|
|
101
|
+
### Доступность
|
|
102
|
+
|
|
103
|
+
- Все кнопки должны иметь aria-label для читателей экрана.
|
|
104
|
+
- Клавиатурная навигация: поддержка Tab для переключения между кнопками, Enter/Space для активации.
|
|
105
|
+
- Соответствие WCAG 2.1 уровня AA для контрастности текста и элементов управления.
|
|
106
|
+
|
|
107
|
+
### Безопасность
|
|
108
|
+
|
|
109
|
+
- Валидация параметра `imageId` из URL для предотвращения XSS и других атак.
|
|
110
|
+
- Проверка прав доступа к изображению (если требуется в будущем).
|
|
111
|
+
|
|
112
|
+
### Совместимость
|
|
113
|
+
|
|
114
|
+
- Поддержка современных браузеров (Chrome, Firefox, Safari, Edge последних версий).
|
|
115
|
+
- Корректная работа в Telegram Web App (с учетом особенностей виртуальной клавиатуры).
|
|
116
|
+
|
|
117
|
+
### UX требования
|
|
118
|
+
|
|
119
|
+
- Плавные переходы и анимации для улучшения восприятия взаимодействия.
|
|
120
|
+
- Визуальная обратная связь при всех действиях пользователя (hover, active состояния).
|
|
121
|
+
- Интуитивно понятный интерфейс, не требующий инструкций.
|
|
122
|
+
|
|
123
|
+
## Assumptions
|
|
124
|
+
|
|
125
|
+
1. Изображения доступны по URL, которые передаются через параметры маршрута или query-параметры.
|
|
126
|
+
2. Страница просмотра изображения открывается с параметром `imageId` или `imageUrl` в URL.
|
|
127
|
+
3. Контекст предыдущей страницы сохраняется через роутер Vue/Nuxt, без необходимости передачи дополнительных параметров.
|
|
128
|
+
4. Все изображения имеют допустимый формат (jpg, png, webp) и загружаются с сервера или CDN.
|
|
129
|
+
5. Поддержка жестов touch для мобильных устройств реализуется через нативные события браузера или библиотеку обработки жестов.
|
|
130
|
+
6. Стандартная шапка должна соответствовать дизайну других страниц проекта (например, `pages/orders/[id].vue`).
|
|
131
|
+
7. Функциональность зума и панорамирования будет реализована через CSS transforms и JavaScript обработчики событий, без использования тяжелых библиотек, если возможно.
|
|
132
|
+
8. При необходимости можно использовать легковесные библиотеки для обработки жестов (например, hammer.js), если нативная реализация окажется слишком сложной.
|
|
133
|
+
9. Страница просмотра изображения должна быть доступна из двух источников: страницы деталей задачи (`pages/orders/[id].vue`) и страницы создания задачи (`pages/projects/[id]/orders/new.vue`).
|
|
134
|
+
10. Для страницы создания задачи изображения находятся в локальном состоянии формы (attachments), поэтому URL изображения может быть как локальным (blob URL), так и серверным.
|
|
135
|
+
|