@nexttylabs/echo 0.4.0 → 0.5.0

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.
Files changed (247) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/app/(public)/[organizationSlug]/roadmap/page.tsx +19 -1
  3. package/app/api/admin/backup/route.ts +22 -4
  4. package/app/api/auth/register/handler.ts +1 -2
  5. package/lib/auth/config.ts +0 -7
  6. package/lib/db/migrations/0000_needy_leech.sql +335 -0
  7. package/lib/db/migrations/meta/0000_snapshot.json +2186 -1
  8. package/lib/db/migrations/meta/_journal.json +2 -135
  9. package/lib/db/schema/auth.ts +0 -1
  10. package/lib/db/schema/index.ts +0 -1
  11. package/lib/portal/public-context.tsx +5 -0
  12. package/package.json +20 -1
  13. package/.changeset/README.md +0 -21
  14. package/.changeset/config.json +0 -11
  15. package/.changeset/cozy-ghosts-care.md +0 -5
  16. package/.changeset/sharp-lines-stand.md +0 -5
  17. package/.changeset/sour-doodles-eat.md +0 -5
  18. package/.changeset/tender-moose-shop.md +0 -5
  19. package/.github/pull_request_template.md +0 -13
  20. package/.github/workflows/ci.yml +0 -41
  21. package/.github/workflows/publish.yml +0 -44
  22. package/.github/workflows/release.yml +0 -73
  23. package/AGENTS.md +0 -92
  24. package/Dockerfile +0 -57
  25. package/Makefile +0 -77
  26. package/bun.lock +0 -2503
  27. package/components/portal/project-switcher.tsx +0 -20
  28. package/docker-compose.dev.yml +0 -26
  29. package/docker-compose.yml +0 -98
  30. package/docs/architecture.md +0 -259
  31. package/docs/component-inventory.md +0 -261
  32. package/docs/database-migrations.md +0 -76
  33. package/docs/development-guide.md +0 -209
  34. package/docs/e2e-user-flows.csv +0 -31
  35. package/docs/er-diagram-feedback.mmd +0 -138
  36. package/docs/er-diagram.mmd +0 -281
  37. package/docs/i18n-check-report.md +0 -296
  38. package/docs/index.md +0 -214
  39. package/docs/logic-chain.md +0 -94
  40. package/docs/plans/2026-01-02-database-migration-scripts.md +0 -496
  41. package/docs/plans/2026-01-02-user-login-design.md +0 -37
  42. package/docs/plans/2026-01-02-user-login.md +0 -437
  43. package/docs/plans/2026-01-02-user-registration-design.md +0 -47
  44. package/docs/plans/2026-01-02-user-registration.md +0 -628
  45. package/docs/plans/2026-01-03-roles-permissions-design.md +0 -20
  46. package/docs/plans/2026-01-03-roles-permissions.md +0 -266
  47. package/docs/plans/2026-01-05-authentication-middleware.md +0 -207
  48. package/docs/plans/2026-01-05-member-removal.md +0 -186
  49. package/docs/plans/2026-01-05-organization-creation.md +0 -374
  50. package/docs/plans/2026-01-05-rbac-middleware.md +0 -112
  51. package/docs/plans/2026-01-05-role-configuration.md +0 -441
  52. package/docs/plans/2026-01-06-file-upload-support.md +0 -804
  53. package/docs/plans/2026-01-06-permission-check-hook.md +0 -155
  54. package/docs/plans/2026-01-06-resource-ownership-check.md +0 -231
  55. package/docs/plans/2026-01-07-feedback-tracking-link.md +0 -459
  56. package/docs/plans/2026-01-09-logout-redirect-design.md +0 -52
  57. package/docs/plans/2026-01-09-phase2-3-plan.md +0 -654
  58. package/docs/plans/2026-01-09-portal-execution-plan.md +0 -408
  59. package/docs/plans/2026-01-09-project-delete-feature-design.md +0 -163
  60. package/docs/plans/2026-01-09-project-delete-implementation.md +0 -451
  61. package/docs/plans/2026-01-09-project-edit-delete-design.md +0 -52
  62. package/docs/plans/2026-01-09-settings-center-design.md +0 -114
  63. package/docs/plans/2026-01-09-settings-center.md +0 -948
  64. package/docs/plans/2026-01-10-organization-only-design.md +0 -66
  65. package/docs/plans/2026-01-10-organization-only-implementation.md +0 -433
  66. package/docs/plans/2026-01-10-portal-settings-restructure-plan.md +0 -18
  67. package/docs/plans/2026-01-10-project-settings-tabs-design-implementation.md +0 -296
  68. package/docs/plans/2026-01-14-e2e-playwright-feedback.md +0 -173
  69. package/docs/plans/2026-01-15-feedback-management-org-context-design.md +0 -82
  70. package/docs/plans/2026-01-15-feedback-management-org-context-implementation-plan.md +0 -521
  71. package/docs/plans/2026-01-16-admin-feedback-filters-design.md +0 -75
  72. package/docs/plans/2026-01-16-admin-feedback-filters-implementation.md +0 -293
  73. package/docs/plans/2026-01-16-admin-feedback-route-consolidation.md +0 -180
  74. package/docs/plans/2026-01-16-e2e-test-fixes.md +0 -158
  75. package/docs/plans/2026-01-17-admin-feedback-filters.md +0 -214
  76. package/docs/plans/2026-01-17-admin-feedback-improvements.md +0 -453
  77. package/docs/plans/2026-01-18-changesets-design.md +0 -40
  78. package/docs/product_changes.md +0 -37
  79. package/docs/project-overview.md +0 -159
  80. package/docs/project-scan-report.json +0 -104
  81. package/docs/route-role-visibility.md +0 -51
  82. package/docs/source-tree-analysis.md +0 -150
  83. package/docs/testing/delete-project-manual-tests.md +0 -18
  84. package/docs/user-story-tracking.md +0 -191
  85. package/eslint.config.mjs +0 -19
  86. package/lib/db/migrations/.gitkeep +0 -0
  87. package/lib/db/migrations/0000_cynical_gladiator.sql +0 -53
  88. package/lib/db/migrations/0001_wandering_sunfire.sql +0 -27
  89. package/lib/db/migrations/0002_shallow_speedball.sql +0 -1
  90. package/lib/db/migrations/0003_add_org_description.sql +0 -1
  91. package/lib/db/migrations/0003_boring_wild_pack.sql +0 -13
  92. package/lib/db/migrations/0004_windy_tyrannus.sql +0 -27
  93. package/lib/db/migrations/0005_perpetual_doorman.sql +0 -5
  94. package/lib/db/migrations/0006_aberrant_captain_midlands.sql +0 -13
  95. package/lib/db/migrations/0007_clever_captain_cross.sql +0 -14
  96. package/lib/db/migrations/0008_sparkling_pandemic.sql +0 -2
  97. package/lib/db/migrations/0009_happy_black_tom.sql +0 -29
  98. package/lib/db/migrations/0010_kind_junta.sql +0 -8
  99. package/lib/db/migrations/0011_mute_squadron_supreme.sql +0 -25
  100. package/lib/db/migrations/0012_giant_power_man.sql +0 -24
  101. package/lib/db/migrations/0013_damp_titanium_man.sql +0 -17
  102. package/lib/db/migrations/0014_blue_alice.sql +0 -18
  103. package/lib/db/migrations/0015_webhook_tables.sql +0 -41
  104. package/lib/db/migrations/0016_github_integration.sql +0 -30
  105. package/lib/db/migrations/0016_overjoyed_ghost_rider.sql +0 -22
  106. package/lib/db/migrations/0017_slimy_inhumans.sql +0 -6
  107. package/lib/db/migrations/0018_same_spitfire.sql +0 -1
  108. package/lib/db/migrations/0019_jittery_loners.sql +0 -16
  109. package/lib/db/migrations/0019_remove_projects_add_org_settings.sql +0 -14
  110. package/lib/db/migrations/meta/0001_snapshot.json +0 -553
  111. package/lib/db/migrations/meta/0002_snapshot.json +0 -560
  112. package/lib/db/migrations/meta/0003_snapshot.json +0 -650
  113. package/lib/db/migrations/meta/0004_snapshot.json +0 -852
  114. package/lib/db/migrations/meta/0005_snapshot.json +0 -900
  115. package/lib/db/migrations/meta/0006_snapshot.json +0 -1011
  116. package/lib/db/migrations/meta/0007_snapshot.json +0 -1125
  117. package/lib/db/migrations/meta/0008_snapshot.json +0 -1146
  118. package/lib/db/migrations/meta/0009_snapshot.json +0 -1386
  119. package/lib/db/migrations/meta/0010_snapshot.json +0 -1419
  120. package/lib/db/migrations/meta/0011_snapshot.json +0 -1615
  121. package/lib/db/migrations/meta/0012_snapshot.json +0 -1805
  122. package/lib/db/migrations/meta/0013_snapshot.json +0 -1948
  123. package/lib/db/migrations/meta/0014_snapshot.json +0 -2082
  124. package/lib/db/migrations/meta/0015_snapshot.json +0 -2476
  125. package/lib/db/migrations/meta/0016_snapshot.json +0 -2633
  126. package/lib/db/migrations/meta/0017_snapshot.json +0 -2680
  127. package/lib/db/migrations/meta/0018_snapshot.json +0 -2686
  128. package/lib/db/migrations/meta/0019_snapshot.json +0 -2741
  129. package/lib/db/schema/projects.ts +0 -145
  130. package/lib/db/schema/user-profiles.ts +0 -31
  131. package/lib/validations/projects.ts +0 -49
  132. package/next-env.d.ts +0 -6
  133. package/playwright.config.ts +0 -44
  134. package/proxy.test.ts +0 -131
  135. package/proxy.ts +0 -116
  136. package/scripts/backup-db.sh +0 -57
  137. package/scripts/backup-db.ts +0 -24
  138. package/scripts/generate-openapi.ts +0 -22
  139. package/scripts/migration-helper.ts +0 -39
  140. package/scripts/pre-deploy.ts +0 -75
  141. package/scripts/restore-db.sh +0 -60
  142. package/scripts/rollback.ts +0 -72
  143. package/scripts/seed-tags.ts +0 -48
  144. package/tests/api/feedback-bulk.test.ts +0 -47
  145. package/tests/api/feedback-by-id.test.ts +0 -67
  146. package/tests/api/feedback-comments-route-import.test.ts +0 -26
  147. package/tests/api/feedback-create.test.ts +0 -71
  148. package/tests/api/feedback-delete.test.ts +0 -160
  149. package/tests/api/feedback-filter.test.ts +0 -250
  150. package/tests/api/feedback-list.test.ts +0 -234
  151. package/tests/api/feedback-route-assignee-condition.test.ts +0 -32
  152. package/tests/api/feedback-similar.test.ts +0 -46
  153. package/tests/api/feedback-sort.test.ts +0 -261
  154. package/tests/api/feedback-status-enum.test.ts +0 -49
  155. package/tests/api/feedback-status-filter.test.ts +0 -117
  156. package/tests/api/feedback-submit-on-behalf.test.ts +0 -269
  157. package/tests/api/feedback.test.ts +0 -175
  158. package/tests/api/identify-jwt.test.ts +0 -25
  159. package/tests/api/invitation-accept.test.ts +0 -213
  160. package/tests/api/organization-invitations.test.ts +0 -186
  161. package/tests/api/organization-members-list.test.ts +0 -79
  162. package/tests/api/organization-members.test.ts +0 -340
  163. package/tests/api/organizations.test.ts +0 -149
  164. package/tests/api/register.test.ts +0 -112
  165. package/tests/api/upload.test.ts +0 -103
  166. package/tests/api/vote.test.ts +0 -82
  167. package/tests/app/admin-feedback-detail-page.test.tsx +0 -25
  168. package/tests/app/admin-feedback-list-page.test.tsx +0 -25
  169. package/tests/app/admin-feedback-new-page.test.tsx +0 -25
  170. package/tests/app/health-route-helpers.test.ts +0 -27
  171. package/tests/app/login-page.test.ts +0 -26
  172. package/tests/app/portal-page.test.ts +0 -29
  173. package/tests/app/project-portal-overview.test.tsx +0 -25
  174. package/tests/app/widget-page-import.test.ts +0 -25
  175. package/tests/components/create-post-dialog-defaults.test.ts +0 -43
  176. package/tests/components/feedback/duplicate-suggestions-inline.test.tsx +0 -27
  177. package/tests/components/feedback/embedded-feedback-form.test.tsx +0 -96
  178. package/tests/components/feedback/feedback-detail.test.tsx +0 -25
  179. package/tests/components/feedback/feedback-stats.test.tsx +0 -49
  180. package/tests/components/feedback-bulk-actions.test.tsx +0 -39
  181. package/tests/components/feedback-i18n-keys.test.ts +0 -70
  182. package/tests/components/feedback-list-controls-compile.test.ts +0 -25
  183. package/tests/components/feedback-list-controls.test.tsx +0 -204
  184. package/tests/components/feedback-list-item.test.tsx +0 -67
  185. package/tests/components/landing/hero.test.tsx +0 -46
  186. package/tests/components/layout/language-switcher.test.tsx +0 -25
  187. package/tests/components/layout/sidebar.test.tsx +0 -157
  188. package/tests/components/login-form.test.ts +0 -25
  189. package/tests/components/organization-form.test.ts +0 -32
  190. package/tests/components/organization-switcher.test.ts +0 -25
  191. package/tests/components/pagination.test.tsx +0 -43
  192. package/tests/components/portal-overview.test.tsx +0 -25
  193. package/tests/components/profile-form.test.tsx +0 -139
  194. package/tests/components/role-selector.test.ts +0 -31
  195. package/tests/components/status-chart.test.tsx +0 -90
  196. package/tests/e2e/auth.e2e.ts +0 -323
  197. package/tests/e2e/feedback-actions.e2e.ts +0 -471
  198. package/tests/e2e/feedback-attachment.e2e.ts +0 -168
  199. package/tests/e2e/feedback-customer.e2e.ts +0 -226
  200. package/tests/e2e/feedback-management.e2e.ts +0 -565
  201. package/tests/e2e/feedback-submit.e2e.ts +0 -133
  202. package/tests/e2e/feedback-view.e2e.ts +0 -297
  203. package/tests/e2e/fixtures/test-data.ts +0 -235
  204. package/tests/e2e/health-check.e2e.ts +0 -230
  205. package/tests/e2e/helpers/test-utils-helpers.test.ts +0 -43
  206. package/tests/e2e/helpers/test-utils.ts +0 -298
  207. package/tests/e2e/integration-placeholders.e2e.ts +0 -199
  208. package/tests/e2e/organization.e2e.ts +0 -292
  209. package/tests/e2e/permissions.e2e.ts +0 -424
  210. package/tests/e2e/project-widget.e2e.ts +0 -63
  211. package/tests/feedback/filters.test.ts +0 -29
  212. package/tests/hooks/use-permissions.test.ts +0 -52
  213. package/tests/lib/ai/classifier.test.ts +0 -104
  214. package/tests/lib/ai/duplicate-detector.test.ts +0 -234
  215. package/tests/lib/attachments-schema.test.ts +0 -30
  216. package/tests/lib/auth/session.test.ts +0 -49
  217. package/tests/lib/auth-client.test.ts +0 -37
  218. package/tests/lib/auth-config.test.ts +0 -26
  219. package/tests/lib/feedback-prefill.test.ts +0 -52
  220. package/tests/lib/feedback-processor.test.ts +0 -41
  221. package/tests/lib/feedback-schema.test.ts +0 -33
  222. package/tests/lib/file-validator.test.ts +0 -48
  223. package/tests/lib/get-feedback-by-id.test.ts +0 -37
  224. package/tests/lib/invitations.test.ts +0 -35
  225. package/tests/lib/login-schema.test.ts +0 -36
  226. package/tests/lib/org-context.test.ts +0 -95
  227. package/tests/lib/organization-access.test.ts +0 -44
  228. package/tests/lib/organization-member-role-schema.test.ts +0 -41
  229. package/tests/lib/permissions.test.ts +0 -88
  230. package/tests/lib/portal-analytics.test.ts +0 -25
  231. package/tests/lib/portal-contributors.test.ts +0 -25
  232. package/tests/lib/portal-copy.test.ts +0 -27
  233. package/tests/lib/portal-i18n.test.ts +0 -30
  234. package/tests/lib/portal-leaderboard-settings.test.ts +0 -25
  235. package/tests/lib/portal-modules.test.ts +0 -25
  236. package/tests/lib/portal-seo.test.ts +0 -25
  237. package/tests/lib/portal-sharing.test.ts +0 -25
  238. package/tests/lib/portal-sorting.test.ts +0 -25
  239. package/tests/lib/portal-theme.test.ts +0 -25
  240. package/tests/lib/rate-limit.test.ts +0 -142
  241. package/tests/lib/resolve-locale.test.ts +0 -34
  242. package/tests/lib/services/backup.test.ts +0 -145
  243. package/tests/lib/user-organizations.test.ts +0 -42
  244. package/tests/lib/user-role-schema.test.ts +0 -33
  245. package/tests/lib/user-schema.test.ts +0 -25
  246. package/tests/setup.ts +0 -74
  247. package/vercel.json +0 -4
@@ -1,293 +0,0 @@
1
- # Admin Feedback Filters & Sorting Implementation Plan
2
-
3
- > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
4
-
5
- **Goal:** Add URL-driven filters/sorting/pagination to /admin/feedback, including assignee/hasVotes/hasReplies, plus members API with client caching.
6
-
7
- **Architecture:** Server-side query parameters drive list data. A new members endpoint provides assignee candidates. Frontend controls update URL, triggering fetches. Data remains in existing feedback API.
8
-
9
- **Tech Stack:** Next.js App Router, React 19, TypeScript, Tailwind v4, Bun, Drizzle ORM.
10
-
11
- ---
12
-
13
- ### Task 1: Add organization members list endpoint
14
-
15
- **Files:**
16
- - Create: `app/api/organizations/[orgId]/members/route.ts`
17
- - Create: `app/api/organizations/[orgId]/members/handler.ts`
18
- - Test: `tests/api/organization-members-list.test.ts`
19
-
20
- **Step 1: Write the failing test**
21
-
22
- ```ts
23
- import { describe, expect, it, mock } from "bun:test";
24
- import { NextRequest } from "next/server";
25
-
26
- describe("GET /api/organizations/[orgId]/members", () => {
27
- it("returns members with displayName", async () => {
28
- const mockDb = {
29
- select: mock(() => ({
30
- from: mock(() => ({
31
- innerJoin: mock(() => ({
32
- where: mock(() => Promise.resolve([
33
- { userId: "user_1", displayName: "Ada" },
34
- ])),
35
- })),
36
- })),
37
- })),
38
- };
39
-
40
- mock.module("@/lib/auth/config", () => ({
41
- auth: { api: { getSession: mock(() => Promise.resolve({ user: { id: "user_1" } })) } },
42
- }));
43
-
44
- mock.module("@/lib/db", () => ({ db: mockDb }));
45
-
46
- const { GET } = await import("@/app/api/organizations/[orgId]/members/route");
47
- const req = new NextRequest("http://localhost:3000/api/organizations/org_1/members");
48
- const res = await GET(req, { params: Promise.resolve({ orgId: "org_1" }) });
49
-
50
- expect(res.status).toBe(200);
51
- const json = await res.json();
52
- expect(json.data[0]).toHaveProperty("userId");
53
- expect(json.data[0]).toHaveProperty("displayName");
54
- });
55
- });
56
- ```
57
-
58
- **Step 2: Run test to verify it fails**
59
-
60
- Run: `bun test tests/api/organization-members-list.test.ts`
61
- Expected: FAIL (module not found or handler missing)
62
-
63
- **Step 3: Write minimal implementation**
64
-
65
- ```ts
66
- // handler.ts
67
- import { NextResponse } from "next/server";
68
- import { assertOrganizationAccess } from "@/lib/auth/organization";
69
- import { organizationMembers, user } from "@/lib/db/schema";
70
- import { eq } from "drizzle-orm";
71
-
72
- export function buildListMembersHandler({ auth, db }: { auth: any; db: any }) {
73
- return async function GET(req: Request, context: { params: { orgId: string } | Promise<{ orgId: string }> }) {
74
- const session = await auth.api.getSession({ headers: req.headers });
75
- if (!session) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
76
-
77
- const { orgId } = await Promise.resolve(context.params);
78
- try {
79
- await assertOrganizationAccess(db, session.user.id, orgId);
80
- } catch {
81
- return NextResponse.json({ error: "Forbidden" }, { status: 403 });
82
- }
83
-
84
- const rows = await db
85
- .select({
86
- userId: organizationMembers.userId,
87
- displayName: user.name,
88
- email: user.email,
89
- })
90
- .from(organizationMembers)
91
- .innerJoin(user, eq(organizationMembers.userId, user.id))
92
- .where(eq(organizationMembers.organizationId, orgId));
93
-
94
- const data = rows.map((row: any) => ({
95
- userId: row.userId,
96
- displayName: row.displayName ?? row.email ?? "未知成员",
97
- }));
98
-
99
- return NextResponse.json({ data }, { status: 200 });
100
- };
101
- }
102
- ```
103
-
104
- **Step 4: Run test to verify it passes**
105
-
106
- Run: `bun test tests/api/organization-members-list.test.ts`
107
- Expected: PASS
108
-
109
- **Step 5: Commit**
110
-
111
- ```bash
112
- git add app/api/organizations/[orgId]/members/route.ts app/api/organizations/[orgId]/members/handler.ts tests/api/organization-members-list.test.ts
113
- git commit -m "feat: add organization members list endpoint"
114
- ```
115
-
116
- ---
117
-
118
- ### Task 2: Add query param parsing/serialization helpers
119
-
120
- **Files:**
121
- - Create: `lib/feedback/filters.ts`
122
- - Test: `tests/feedback/filters.test.ts`
123
-
124
- **Step 1: Write the failing test**
125
-
126
- ```ts
127
- import { describe, expect, it } from "bun:test";
128
- import { parseCsvParam, serializeCsvParam } from "@/lib/feedback/filters";
129
-
130
- describe("filters helpers", () => {
131
- it("parses csv into array", () => {
132
- expect(parseCsvParam("a,b")).toEqual(["a", "b"]);
133
- });
134
-
135
- it("serializes array into csv", () => {
136
- expect(serializeCsvParam(["a", "b"])).toBe("a,b");
137
- });
138
- });
139
- ```
140
-
141
- **Step 2: Run test to verify it fails**
142
-
143
- Run: `bun test tests/feedback/filters.test.ts`
144
- Expected: FAIL (module missing)
145
-
146
- **Step 3: Write minimal implementation**
147
-
148
- ```ts
149
- export function parseCsvParam(value?: string | null) {
150
- if (!value) return [];
151
- return value
152
- .split(",")
153
- .map((item) => item.trim())
154
- .filter(Boolean);
155
- }
156
-
157
- export function serializeCsvParam(values: string[]) {
158
- return values.filter(Boolean).join(",");
159
- }
160
- ```
161
-
162
- **Step 4: Run test to verify it passes**
163
-
164
- Run: `bun test tests/feedback/filters.test.ts`
165
- Expected: PASS
166
-
167
- **Step 5: Commit**
168
-
169
- ```bash
170
- git add lib/feedback/filters.ts tests/feedback/filters.test.ts
171
- git commit -m "chore: add feedback filter helpers"
172
- ```
173
-
174
- ---
175
-
176
- ### Task 3: Add Feedback list controls UI (filters + sorting)
177
-
178
- **Files:**
179
- - Create: `components/feedback/feedback-list-controls.tsx`
180
- - Modify: `components/feedback/feedback-list.tsx`
181
- - Modify: `components/shared/pagination.tsx`
182
-
183
- **Step 1: Write the failing test**
184
-
185
- ```ts
186
- import { describe, expect, it } from "bun:test";
187
- import { render } from "@testing-library/react";
188
- import { FeedbackListControls } from "@/components/feedback/feedback-list-controls";
189
-
190
- describe("FeedbackListControls", () => {
191
- it("renders filters and sort controls", () => {
192
- const { getByLabelText } = render(
193
- <FeedbackListControls
194
- organizationId="org_1"
195
- total={10}
196
- pageSize={20}
197
- onUpdate={() => {}}
198
- />
199
- );
200
- expect(getByLabelText("搜索反馈")).toBeTruthy();
201
- });
202
- });
203
- ```
204
-
205
- **Step 2: Run test to verify it fails**
206
-
207
- Run: `bun test tests/components/feedback-list-controls.test.tsx`
208
- Expected: FAIL (component missing)
209
-
210
- **Step 3: Write minimal implementation**
211
-
212
- - Add controls for search, status/type/priority/assignee/hasVotes/hasReplies, and sort
213
- - Read/write URL params via `useSearchParams` + `useRouter`
214
- - Reset page to 1 on change
215
- - Add cached assignee list loading
216
- - Update `FeedbackList` to pass current params and render controls
217
- - Add `aria-label` to pagination icon buttons and replace "..." with "…"
218
-
219
- **Step 4: Run test to verify it passes**
220
-
221
- Run: `bun test tests/components/feedback-list-controls.test.tsx`
222
- Expected: PASS
223
-
224
- **Step 5: Commit**
225
-
226
- ```bash
227
- git add components/feedback/feedback-list-controls.tsx components/feedback/feedback-list.tsx components/shared/pagination.tsx
228
- git commit -m "feat: add feedback list controls"
229
- ```
230
-
231
- ---
232
-
233
- ### Task 4: Extend /api/feedback filtering for new params
234
-
235
- **Files:**
236
- - Modify: `app/api/feedback/route.ts`
237
- - Modify: `app/api/feedback/handler.ts`
238
- - Test: `tests/api/feedback-filter.test.ts`
239
-
240
- **Step 1: Write the failing test**
241
-
242
- ```ts
243
- it("filters by assignee and hasVotes", async () => {
244
- const req = new NextRequest("http://localhost:3000/api/feedback?assignee=user_1&hasVotes=true&organizationId=org_1");
245
- const res = await GET(req);
246
- expect(res.status).toBe(200);
247
- });
248
- ```
249
-
250
- **Step 2: Run test to verify it fails**
251
-
252
- Run: `bun test tests/api/feedback-filter.test.ts`
253
- Expected: FAIL (missing behavior)
254
-
255
- **Step 3: Write minimal implementation**
256
-
257
- - Parse CSV params for `status/type/priority/assignee/hasVotes/hasReplies`
258
- - Apply `assignee` filter (includes `unassigned`)
259
- - Apply `hasVotes` filter (`voteCount > 0` or `= 0`)
260
- - Apply `hasReplies` filter (`replyCount > 0` or `= 0`)
261
-
262
- **Step 4: Run test to verify it passes**
263
-
264
- Run: `bun test tests/api/feedback-filter.test.ts`
265
- Expected: PASS
266
-
267
- **Step 5: Commit**
268
-
269
- ```bash
270
- git add app/api/feedback/route.ts app/api/feedback/handler.ts tests/api/feedback-filter.test.ts
271
- git commit -m "feat: add feedback filters for assignee and replies"
272
- ```
273
-
274
- ---
275
-
276
- ### Task 5: Full verification
277
-
278
- **Step 1: Run lint**
279
-
280
- Run: `bun run lint`
281
- Expected: 0 errors
282
-
283
- **Step 2: Run relevant tests**
284
-
285
- Run: `bun test tests/api/organization-members-list.test.ts tests/feedback/filters.test.ts tests/components/feedback-list-controls.test.tsx tests/api/feedback-filter.test.ts`
286
- Expected: PASS
287
-
288
- **Step 3: Commit any remaining fixes**
289
-
290
- ```bash
291
- git add -A
292
- git commit -m "chore: finalize feedback filters"
293
- ```
@@ -1,180 +0,0 @@
1
- # Admin Feedback Route Consolidation Implementation Plan
2
-
3
- > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
4
-
5
- **Goal:** Move all feedback management routes under `/admin`, removing legacy `/feedback` and `/feedback/new` dashboard paths.
6
-
7
- **Architecture:** Keep admin list and detail at `/admin/feedback` and `/admin/feedback/[id]`, add `/admin/feedback/new` by moving the submit-on-behalf page, and delete the old dashboard feedback list. Update all internal links and list defaults to use the `/admin` base. No redirects.
8
-
9
- **Tech Stack:** Next.js App Router, React, TypeScript, Tailwind CSS, Bun.
10
-
11
- ### Task 1: Remove legacy dashboard feedback list route
12
-
13
- **Files:**
14
- - Delete: `app/(dashboard)/feedback/page.tsx`
15
-
16
- **Step 1: Write the failing test**
17
-
18
- ```ts
19
- // tests/e2e/feedback-management.spec.ts (add a case asserting /feedback is 404)
20
- // Example (Playwright):
21
- // await page.goto("/feedback");
22
- // await expect(page.getByText("Not Found")).toBeVisible();
23
- ```
24
-
25
- **Step 2: Run test to verify it fails**
26
-
27
- Run: `bun run test tests/e2e/feedback-management.spec.ts`
28
- Expected: FAIL because `/feedback` still exists
29
-
30
- **Step 3: Remove the legacy route**
31
-
32
- ```ts
33
- // Delete file: app/(dashboard)/feedback/page.tsx
34
- ```
35
-
36
- **Step 4: Run test to verify it passes**
37
-
38
- Run: `bun run test tests/e2e/feedback-management.spec.ts`
39
- Expected: PASS
40
-
41
- **Step 5: Commit**
42
-
43
- ```bash
44
- git add app/(dashboard)/feedback/page.tsx tests/e2e/feedback-management.spec.ts
45
- git commit -m "refactor: remove legacy feedback list route"
46
- ```
47
-
48
- ### Task 2: Move submit-on-behalf route under /admin
49
-
50
- **Files:**
51
- - Move: `app/(dashboard)/feedback/new/page.tsx` → `app/(dashboard)/admin/feedback/new/page.tsx`
52
-
53
- **Step 1: Write the failing test**
54
-
55
- ```ts
56
- // tests/e2e/feedback-customer.spec.ts (update /feedback/new -> /admin/feedback/new and assert old path 404)
57
- ```
58
-
59
- **Step 2: Run test to verify it fails**
60
-
61
- Run: `bun run test tests/e2e/feedback-customer.spec.ts`
62
- Expected: FAIL with old URL
63
-
64
- **Step 3: Move the route file**
65
-
66
- ```bash
67
- mkdir -p app/(dashboard)/admin/feedback/new
68
- mv app/(dashboard)/feedback/new/page.tsx app/(dashboard)/admin/feedback/new/page.tsx
69
- ```
70
-
71
- **Step 4: Run test to verify it passes**
72
-
73
- Run: `bun run test tests/e2e/feedback-customer.spec.ts`
74
- Expected: PASS
75
-
76
- **Step 5: Commit**
77
-
78
- ```bash
79
- git add app/(dashboard)/admin/feedback/new/page.tsx app/(dashboard)/feedback/new/page.tsx tests/e2e/feedback-customer.spec.ts
80
- git commit -m "refactor: move submit-on-behalf route under admin"
81
- ```
82
-
83
- ### Task 3: Update navigation links to /admin
84
-
85
- **Files:**
86
- - Modify: `components/layout/sidebar.tsx`
87
- - Modify: `components/dashboard/quick-actions.tsx`
88
- - Modify: `components/dashboard/recent-feedback-list.tsx`
89
-
90
- **Step 1: Write the failing test**
91
-
92
- ```ts
93
- // tests/e2e/feedback-management.spec.ts or a unit test
94
- // Assert sidebar/quick-actions links resolve to /admin/feedback and /admin/feedback/new
95
- ```
96
-
97
- **Step 2: Run test to verify it fails**
98
-
99
- Run: `bun run test tests/e2e/feedback-management.spec.ts`
100
- Expected: FAIL (links still /feedback)
101
-
102
- **Step 3: Update links**
103
-
104
- ```ts
105
- // sidebar: /feedback -> /admin/feedback
106
- // quick-actions: /feedback -> /admin/feedback
107
- // recent-feedback-list: /feedback -> /admin/feedback, /feedback/new -> /admin/feedback/new
108
- ```
109
-
110
- **Step 4: Run test to verify it passes**
111
-
112
- Run: `bun run test tests/e2e/feedback-management.spec.ts`
113
- Expected: PASS
114
-
115
- **Step 5: Commit**
116
-
117
- ```bash
118
- git add components/layout/sidebar.tsx components/dashboard/quick-actions.tsx components/dashboard/recent-feedback-list.tsx tests/e2e/feedback-management.spec.ts
119
- git commit -m "refactor: point feedback navigation to admin routes"
120
- ```
121
-
122
- ### Task 4: Default feedback list base path to /admin
123
-
124
- **Files:**
125
- - Modify: `components/feedback/feedback-list.tsx`
126
- - Modify: `components/feedback/feedback-list-item.tsx`
127
-
128
- **Step 1: Write the failing test**
129
-
130
- ```ts
131
- // tests/components/feedback/feedback-list.test.tsx (new)
132
- // Render FeedbackList without basePath and assert item links are /admin/feedback/:id
133
- ```
134
-
135
- **Step 2: Run test to verify it fails**
136
-
137
- Run: `bun run test tests/components/feedback/feedback-list.test.tsx`
138
- Expected: FAIL because default basePath is /feedback
139
-
140
- **Step 3: Update defaults**
141
-
142
- ```ts
143
- // basePath default: "/feedback" -> "/admin/feedback"
144
- ```
145
-
146
- **Step 4: Run test to verify it passes**
147
-
148
- Run: `bun run test tests/components/feedback/feedback-list.test.tsx`
149
- Expected: PASS
150
-
151
- **Step 5: Commit**
152
-
153
- ```bash
154
- git add components/feedback/feedback-list.tsx components/feedback/feedback-list-item.tsx tests/components/feedback/feedback-list.test.tsx
155
- git commit -m "refactor: default feedback list links to admin"
156
- ```
157
-
158
- ### Task 5: Verification
159
-
160
- **Files:**
161
- - (No new files)
162
-
163
- **Step 1: Run lint**
164
-
165
- Run: `bun run lint`
166
- Expected: Warnings only; no new errors
167
-
168
- **Step 2: Smoke-check routes**
169
-
170
- - `/admin/feedback` loads list
171
- - `/admin/feedback/[id]` loads detail
172
- - `/admin/feedback/new` loads submit-on-behalf form
173
- - `/feedback` and `/feedback/new` 404
174
-
175
- **Step 3: Commit (if needed)**
176
-
177
- ```bash
178
- git add -A
179
- git commit -m "chore: verify admin feedback routes"
180
- ```
@@ -1,158 +0,0 @@
1
- # E2E Test Fixes Implementation Plan
2
-
3
- > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
4
-
5
- **Goal:** Run the requested Playwright E2E specs and fix any failures until they pass.
6
-
7
- **Architecture:** Use the existing Playwright specs as the failing tests, trace failures to the responsible UI/API layer, and apply minimal, targeted fixes. Re-run each spec after each fix to validate.
8
-
9
- **Tech Stack:** Next.js (App Router), React, TypeScript, Bun, Playwright.
10
-
11
- ---
12
-
13
- ### Task 1: Establish execution workspace
14
-
15
- **Files:**
16
- - Modify: `.gitignore` (only if `.worktrees/` is not ignored)
17
-
18
- **Step 1: Check preferred worktree directory**
19
- Run: `ls -d .worktrees 2>/dev/null || ls -d worktrees 2>/dev/null`
20
- Expected: one of the directories exists; otherwise proceed to CLAUDE.md preference.
21
-
22
- **Step 2: Check CLAUDE.md for worktree guidance**
23
- Run: `grep -i "worktree.*director" CLAUDE.md 2>/dev/null`
24
- Expected: guidance or no output.
25
-
26
- **Step 3: Verify ignore if using project-local directory**
27
- Run: `git check-ignore -q .worktrees 2>/dev/null || git check-ignore -q worktrees 2>/dev/null`
28
- Expected: zero exit code; if not ignored, add and commit `.gitignore` entry.
29
-
30
- **Step 4: Create worktree and install deps**
31
- Run:
32
- ```
33
- project=$(basename "$(git rev-parse --show-toplevel)")
34
- branch="fix/e2e-tests-2026-01-16"
35
- path=".worktrees/$branch"
36
-
37
- git worktree add "$path" -b "$branch"
38
- cd "$path"
39
- bun install
40
- ```
41
- Expected: worktree created and dependencies installed.
42
-
43
- **Step 5: Baseline test command (single spec)**
44
- Run: `bunx playwright test tests/e2e/health-check.spec.ts`
45
- Expected: If failing, stop and report; if passing, continue.
46
-
47
- ---
48
-
49
- ### Task 2: Fix `tests/e2e/feedback-management.spec.ts`
50
-
51
- **Files:**
52
- - Modify: `tests/e2e/feedback-management.spec.ts`
53
- - Modify: `app/**` (as indicated by failure)
54
-
55
- **Step 1: Run spec to capture failure**
56
- Run: `bunx playwright test tests/e2e/feedback-management.spec.ts`
57
- Expected: FAIL with specific error output.
58
-
59
- **Step 2: Root cause investigation**
60
- - Identify failing assertion, locator, or API response in the error output.
61
- - Trace to the source file indicated by stack/trace.
62
-
63
- **Step 3: Minimal fix**
64
- - Update the failing locator/expectation to match current UI OR fix the underlying UI/API issue.
65
- - Keep scope minimal; avoid refactors.
66
-
67
- **Step 4: Verify**
68
- Run: `bunx playwright test tests/e2e/feedback-management.spec.ts`
69
- Expected: PASS.
70
-
71
- ---
72
-
73
- ### Task 3: Fix `tests/e2e/feedback-submit.spec.ts`
74
-
75
- **Files:**
76
- - Modify: `tests/e2e/feedback-submit.spec.ts`
77
- - Modify: `app/**` (as indicated by failure)
78
-
79
- **Step 1: Run spec to capture failure**
80
- Run: `bunx playwright test tests/e2e/feedback-submit.spec.ts`
81
- Expected: FAIL with specific error output.
82
-
83
- **Step 2: Root cause investigation**
84
- - Identify failing step, response, or UI mismatch.
85
- - Trace to responsible route/component.
86
-
87
- **Step 3: Minimal fix**
88
- - Adjust test expectations or fix underlying behavior.
89
-
90
- **Step 4: Verify**
91
- Run: `bunx playwright test tests/e2e/feedback-submit.spec.ts`
92
- Expected: PASS.
93
-
94
- ---
95
-
96
- ### Task 4: Fix `tests/e2e/feedback-view.spec.ts`
97
-
98
- **Files:**
99
- - Modify: `tests/e2e/feedback-view.spec.ts`
100
- - Modify: `app/**` (as indicated by failure)
101
-
102
- **Step 1: Run spec to capture failure**
103
- Run: `bunx playwright test tests/e2e/feedback-view.spec.ts`
104
- Expected: FAIL with specific error output.
105
-
106
- **Step 2: Root cause investigation**
107
- - Identify failing expectations and any missing data/fixtures.
108
- - Trace to page/data-loading code.
109
-
110
- **Step 3: Minimal fix**
111
- - Adjust test to current UI or fix underlying page/data.
112
-
113
- **Step 4: Verify**
114
- Run: `bunx playwright test tests/e2e/feedback-view.spec.ts`
115
- Expected: PASS.
116
-
117
- ---
118
-
119
- ### Task 5: Fix `tests/e2e/health-check.spec.ts`
120
-
121
- **Files:**
122
- - Modify: `app/health/route.ts`
123
- - Modify: `tests/e2e/health-check.spec.ts` (only if test is outdated)
124
-
125
- **Step 1: Run spec to capture failure**
126
- Run: `bunx playwright test tests/e2e/health-check.spec.ts`
127
- Expected: FAIL with specific error output.
128
-
129
- **Step 2: Root cause investigation**
130
- - Verify health endpoint route exists and matches test expectation.
131
- - Validate response shape and status.
132
-
133
- **Step 3: Minimal fix**
134
- - Adjust endpoint or test to align expected contract.
135
-
136
- **Step 4: Verify**
137
- Run: `bunx playwright test tests/e2e/health-check.spec.ts`
138
- Expected: PASS.
139
-
140
- ---
141
-
142
- ### Task 6: Final verification (requested specs)
143
-
144
- **Files:**
145
- - None (test run)
146
-
147
- **Step 1: Run requested specs in order**
148
- Run:
149
- ```
150
- bunx playwright test tests/e2e/feedback-management.spec.ts
151
- bunx playwright test tests/e2e/feedback-submit.spec.ts
152
- bunx playwright test tests/e2e/feedback-view.spec.ts
153
- bunx playwright test tests/e2e/health-check.spec.ts
154
- ```
155
- Expected: All PASS.
156
-
157
- **Step 2: Report results**
158
- Summarize changes, test outcomes, and any follow-ups.