@nexttylabs/echo 0.4.0 → 0.6.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 (262) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/app/(dashboard)/admin/feedback/[id]/edit/page.tsx +12 -6
  3. package/app/(dashboard)/admin/feedback/new/page.tsx +19 -17
  4. package/app/(dashboard)/admin/layout.tsx +16 -6
  5. package/app/(dashboard)/layout.tsx +4 -2
  6. package/app/(dashboard)/settings/api-keys/page.tsx +13 -3
  7. package/app/(dashboard)/settings/layout.tsx +25 -2
  8. package/app/(dashboard)/settings/organization/page.tsx +8 -9
  9. package/app/(public)/[organizationSlug]/roadmap/page.tsx +19 -1
  10. package/app/api/admin/backup/route.ts +22 -4
  11. package/app/api/auth/register/handler.ts +1 -2
  12. package/app/api/feedback/[id]/comments/[commentId]/route.ts +13 -4
  13. package/app/api/feedback/[id]/reclassify/route.ts +4 -4
  14. package/app/api/organizations/handler.ts +2 -4
  15. package/components/settings/settings-sidebar.tsx +4 -4
  16. package/hooks/use-organization.tsx +116 -0
  17. package/hooks/use-permissions.ts +24 -11
  18. package/lib/auth/config.ts +0 -7
  19. package/lib/auth/organization.ts +20 -0
  20. package/lib/auth/permissions.ts +10 -0
  21. package/lib/db/migrations/0000_needy_leech.sql +335 -0
  22. package/lib/db/migrations/meta/0000_snapshot.json +2186 -1
  23. package/lib/db/migrations/meta/_journal.json +2 -135
  24. package/lib/db/schema/auth.ts +0 -1
  25. package/lib/db/schema/index.ts +0 -1
  26. package/lib/portal/public-context.tsx +5 -0
  27. package/package.json +20 -1
  28. package/.changeset/README.md +0 -21
  29. package/.changeset/config.json +0 -11
  30. package/.changeset/cozy-ghosts-care.md +0 -5
  31. package/.changeset/sharp-lines-stand.md +0 -5
  32. package/.changeset/sour-doodles-eat.md +0 -5
  33. package/.changeset/tender-moose-shop.md +0 -5
  34. package/.github/pull_request_template.md +0 -13
  35. package/.github/workflows/ci.yml +0 -41
  36. package/.github/workflows/publish.yml +0 -44
  37. package/.github/workflows/release.yml +0 -73
  38. package/AGENTS.md +0 -92
  39. package/Dockerfile +0 -57
  40. package/Makefile +0 -77
  41. package/bun.lock +0 -2503
  42. package/components/portal/project-switcher.tsx +0 -20
  43. package/docker-compose.dev.yml +0 -26
  44. package/docker-compose.yml +0 -98
  45. package/docs/architecture.md +0 -259
  46. package/docs/component-inventory.md +0 -261
  47. package/docs/database-migrations.md +0 -76
  48. package/docs/development-guide.md +0 -209
  49. package/docs/e2e-user-flows.csv +0 -31
  50. package/docs/er-diagram-feedback.mmd +0 -138
  51. package/docs/er-diagram.mmd +0 -281
  52. package/docs/i18n-check-report.md +0 -296
  53. package/docs/index.md +0 -214
  54. package/docs/logic-chain.md +0 -94
  55. package/docs/plans/2026-01-02-database-migration-scripts.md +0 -496
  56. package/docs/plans/2026-01-02-user-login-design.md +0 -37
  57. package/docs/plans/2026-01-02-user-login.md +0 -437
  58. package/docs/plans/2026-01-02-user-registration-design.md +0 -47
  59. package/docs/plans/2026-01-02-user-registration.md +0 -628
  60. package/docs/plans/2026-01-03-roles-permissions-design.md +0 -20
  61. package/docs/plans/2026-01-03-roles-permissions.md +0 -266
  62. package/docs/plans/2026-01-05-authentication-middleware.md +0 -207
  63. package/docs/plans/2026-01-05-member-removal.md +0 -186
  64. package/docs/plans/2026-01-05-organization-creation.md +0 -374
  65. package/docs/plans/2026-01-05-rbac-middleware.md +0 -112
  66. package/docs/plans/2026-01-05-role-configuration.md +0 -441
  67. package/docs/plans/2026-01-06-file-upload-support.md +0 -804
  68. package/docs/plans/2026-01-06-permission-check-hook.md +0 -155
  69. package/docs/plans/2026-01-06-resource-ownership-check.md +0 -231
  70. package/docs/plans/2026-01-07-feedback-tracking-link.md +0 -459
  71. package/docs/plans/2026-01-09-logout-redirect-design.md +0 -52
  72. package/docs/plans/2026-01-09-phase2-3-plan.md +0 -654
  73. package/docs/plans/2026-01-09-portal-execution-plan.md +0 -408
  74. package/docs/plans/2026-01-09-project-delete-feature-design.md +0 -163
  75. package/docs/plans/2026-01-09-project-delete-implementation.md +0 -451
  76. package/docs/plans/2026-01-09-project-edit-delete-design.md +0 -52
  77. package/docs/plans/2026-01-09-settings-center-design.md +0 -114
  78. package/docs/plans/2026-01-09-settings-center.md +0 -948
  79. package/docs/plans/2026-01-10-organization-only-design.md +0 -66
  80. package/docs/plans/2026-01-10-organization-only-implementation.md +0 -433
  81. package/docs/plans/2026-01-10-portal-settings-restructure-plan.md +0 -18
  82. package/docs/plans/2026-01-10-project-settings-tabs-design-implementation.md +0 -296
  83. package/docs/plans/2026-01-14-e2e-playwright-feedback.md +0 -173
  84. package/docs/plans/2026-01-15-feedback-management-org-context-design.md +0 -82
  85. package/docs/plans/2026-01-15-feedback-management-org-context-implementation-plan.md +0 -521
  86. package/docs/plans/2026-01-16-admin-feedback-filters-design.md +0 -75
  87. package/docs/plans/2026-01-16-admin-feedback-filters-implementation.md +0 -293
  88. package/docs/plans/2026-01-16-admin-feedback-route-consolidation.md +0 -180
  89. package/docs/plans/2026-01-16-e2e-test-fixes.md +0 -158
  90. package/docs/plans/2026-01-17-admin-feedback-filters.md +0 -214
  91. package/docs/plans/2026-01-17-admin-feedback-improvements.md +0 -453
  92. package/docs/plans/2026-01-18-changesets-design.md +0 -40
  93. package/docs/product_changes.md +0 -37
  94. package/docs/project-overview.md +0 -159
  95. package/docs/project-scan-report.json +0 -104
  96. package/docs/route-role-visibility.md +0 -51
  97. package/docs/source-tree-analysis.md +0 -150
  98. package/docs/testing/delete-project-manual-tests.md +0 -18
  99. package/docs/user-story-tracking.md +0 -191
  100. package/eslint.config.mjs +0 -19
  101. package/lib/db/migrations/.gitkeep +0 -0
  102. package/lib/db/migrations/0000_cynical_gladiator.sql +0 -53
  103. package/lib/db/migrations/0001_wandering_sunfire.sql +0 -27
  104. package/lib/db/migrations/0002_shallow_speedball.sql +0 -1
  105. package/lib/db/migrations/0003_add_org_description.sql +0 -1
  106. package/lib/db/migrations/0003_boring_wild_pack.sql +0 -13
  107. package/lib/db/migrations/0004_windy_tyrannus.sql +0 -27
  108. package/lib/db/migrations/0005_perpetual_doorman.sql +0 -5
  109. package/lib/db/migrations/0006_aberrant_captain_midlands.sql +0 -13
  110. package/lib/db/migrations/0007_clever_captain_cross.sql +0 -14
  111. package/lib/db/migrations/0008_sparkling_pandemic.sql +0 -2
  112. package/lib/db/migrations/0009_happy_black_tom.sql +0 -29
  113. package/lib/db/migrations/0010_kind_junta.sql +0 -8
  114. package/lib/db/migrations/0011_mute_squadron_supreme.sql +0 -25
  115. package/lib/db/migrations/0012_giant_power_man.sql +0 -24
  116. package/lib/db/migrations/0013_damp_titanium_man.sql +0 -17
  117. package/lib/db/migrations/0014_blue_alice.sql +0 -18
  118. package/lib/db/migrations/0015_webhook_tables.sql +0 -41
  119. package/lib/db/migrations/0016_github_integration.sql +0 -30
  120. package/lib/db/migrations/0016_overjoyed_ghost_rider.sql +0 -22
  121. package/lib/db/migrations/0017_slimy_inhumans.sql +0 -6
  122. package/lib/db/migrations/0018_same_spitfire.sql +0 -1
  123. package/lib/db/migrations/0019_jittery_loners.sql +0 -16
  124. package/lib/db/migrations/0019_remove_projects_add_org_settings.sql +0 -14
  125. package/lib/db/migrations/meta/0001_snapshot.json +0 -553
  126. package/lib/db/migrations/meta/0002_snapshot.json +0 -560
  127. package/lib/db/migrations/meta/0003_snapshot.json +0 -650
  128. package/lib/db/migrations/meta/0004_snapshot.json +0 -852
  129. package/lib/db/migrations/meta/0005_snapshot.json +0 -900
  130. package/lib/db/migrations/meta/0006_snapshot.json +0 -1011
  131. package/lib/db/migrations/meta/0007_snapshot.json +0 -1125
  132. package/lib/db/migrations/meta/0008_snapshot.json +0 -1146
  133. package/lib/db/migrations/meta/0009_snapshot.json +0 -1386
  134. package/lib/db/migrations/meta/0010_snapshot.json +0 -1419
  135. package/lib/db/migrations/meta/0011_snapshot.json +0 -1615
  136. package/lib/db/migrations/meta/0012_snapshot.json +0 -1805
  137. package/lib/db/migrations/meta/0013_snapshot.json +0 -1948
  138. package/lib/db/migrations/meta/0014_snapshot.json +0 -2082
  139. package/lib/db/migrations/meta/0015_snapshot.json +0 -2476
  140. package/lib/db/migrations/meta/0016_snapshot.json +0 -2633
  141. package/lib/db/migrations/meta/0017_snapshot.json +0 -2680
  142. package/lib/db/migrations/meta/0018_snapshot.json +0 -2686
  143. package/lib/db/migrations/meta/0019_snapshot.json +0 -2741
  144. package/lib/db/schema/projects.ts +0 -145
  145. package/lib/db/schema/user-profiles.ts +0 -31
  146. package/lib/validations/projects.ts +0 -49
  147. package/next-env.d.ts +0 -6
  148. package/playwright.config.ts +0 -44
  149. package/proxy.test.ts +0 -131
  150. package/proxy.ts +0 -116
  151. package/scripts/backup-db.sh +0 -57
  152. package/scripts/backup-db.ts +0 -24
  153. package/scripts/generate-openapi.ts +0 -22
  154. package/scripts/migration-helper.ts +0 -39
  155. package/scripts/pre-deploy.ts +0 -75
  156. package/scripts/restore-db.sh +0 -60
  157. package/scripts/rollback.ts +0 -72
  158. package/scripts/seed-tags.ts +0 -48
  159. package/tests/api/feedback-bulk.test.ts +0 -47
  160. package/tests/api/feedback-by-id.test.ts +0 -67
  161. package/tests/api/feedback-comments-route-import.test.ts +0 -26
  162. package/tests/api/feedback-create.test.ts +0 -71
  163. package/tests/api/feedback-delete.test.ts +0 -160
  164. package/tests/api/feedback-filter.test.ts +0 -250
  165. package/tests/api/feedback-list.test.ts +0 -234
  166. package/tests/api/feedback-route-assignee-condition.test.ts +0 -32
  167. package/tests/api/feedback-similar.test.ts +0 -46
  168. package/tests/api/feedback-sort.test.ts +0 -261
  169. package/tests/api/feedback-status-enum.test.ts +0 -49
  170. package/tests/api/feedback-status-filter.test.ts +0 -117
  171. package/tests/api/feedback-submit-on-behalf.test.ts +0 -269
  172. package/tests/api/feedback.test.ts +0 -175
  173. package/tests/api/identify-jwt.test.ts +0 -25
  174. package/tests/api/invitation-accept.test.ts +0 -213
  175. package/tests/api/organization-invitations.test.ts +0 -186
  176. package/tests/api/organization-members-list.test.ts +0 -79
  177. package/tests/api/organization-members.test.ts +0 -340
  178. package/tests/api/organizations.test.ts +0 -149
  179. package/tests/api/register.test.ts +0 -112
  180. package/tests/api/upload.test.ts +0 -103
  181. package/tests/api/vote.test.ts +0 -82
  182. package/tests/app/admin-feedback-detail-page.test.tsx +0 -25
  183. package/tests/app/admin-feedback-list-page.test.tsx +0 -25
  184. package/tests/app/admin-feedback-new-page.test.tsx +0 -25
  185. package/tests/app/health-route-helpers.test.ts +0 -27
  186. package/tests/app/login-page.test.ts +0 -26
  187. package/tests/app/portal-page.test.ts +0 -29
  188. package/tests/app/project-portal-overview.test.tsx +0 -25
  189. package/tests/app/widget-page-import.test.ts +0 -25
  190. package/tests/components/create-post-dialog-defaults.test.ts +0 -43
  191. package/tests/components/feedback/duplicate-suggestions-inline.test.tsx +0 -27
  192. package/tests/components/feedback/embedded-feedback-form.test.tsx +0 -96
  193. package/tests/components/feedback/feedback-detail.test.tsx +0 -25
  194. package/tests/components/feedback/feedback-stats.test.tsx +0 -49
  195. package/tests/components/feedback-bulk-actions.test.tsx +0 -39
  196. package/tests/components/feedback-i18n-keys.test.ts +0 -70
  197. package/tests/components/feedback-list-controls-compile.test.ts +0 -25
  198. package/tests/components/feedback-list-controls.test.tsx +0 -204
  199. package/tests/components/feedback-list-item.test.tsx +0 -67
  200. package/tests/components/landing/hero.test.tsx +0 -46
  201. package/tests/components/layout/language-switcher.test.tsx +0 -25
  202. package/tests/components/layout/sidebar.test.tsx +0 -157
  203. package/tests/components/login-form.test.ts +0 -25
  204. package/tests/components/organization-form.test.ts +0 -32
  205. package/tests/components/organization-switcher.test.ts +0 -25
  206. package/tests/components/pagination.test.tsx +0 -43
  207. package/tests/components/portal-overview.test.tsx +0 -25
  208. package/tests/components/profile-form.test.tsx +0 -139
  209. package/tests/components/role-selector.test.ts +0 -31
  210. package/tests/components/status-chart.test.tsx +0 -90
  211. package/tests/e2e/auth.e2e.ts +0 -323
  212. package/tests/e2e/feedback-actions.e2e.ts +0 -471
  213. package/tests/e2e/feedback-attachment.e2e.ts +0 -168
  214. package/tests/e2e/feedback-customer.e2e.ts +0 -226
  215. package/tests/e2e/feedback-management.e2e.ts +0 -565
  216. package/tests/e2e/feedback-submit.e2e.ts +0 -133
  217. package/tests/e2e/feedback-view.e2e.ts +0 -297
  218. package/tests/e2e/fixtures/test-data.ts +0 -235
  219. package/tests/e2e/health-check.e2e.ts +0 -230
  220. package/tests/e2e/helpers/test-utils-helpers.test.ts +0 -43
  221. package/tests/e2e/helpers/test-utils.ts +0 -298
  222. package/tests/e2e/integration-placeholders.e2e.ts +0 -199
  223. package/tests/e2e/organization.e2e.ts +0 -292
  224. package/tests/e2e/permissions.e2e.ts +0 -424
  225. package/tests/e2e/project-widget.e2e.ts +0 -63
  226. package/tests/feedback/filters.test.ts +0 -29
  227. package/tests/hooks/use-permissions.test.ts +0 -52
  228. package/tests/lib/ai/classifier.test.ts +0 -104
  229. package/tests/lib/ai/duplicate-detector.test.ts +0 -234
  230. package/tests/lib/attachments-schema.test.ts +0 -30
  231. package/tests/lib/auth/session.test.ts +0 -49
  232. package/tests/lib/auth-client.test.ts +0 -37
  233. package/tests/lib/auth-config.test.ts +0 -26
  234. package/tests/lib/feedback-prefill.test.ts +0 -52
  235. package/tests/lib/feedback-processor.test.ts +0 -41
  236. package/tests/lib/feedback-schema.test.ts +0 -33
  237. package/tests/lib/file-validator.test.ts +0 -48
  238. package/tests/lib/get-feedback-by-id.test.ts +0 -37
  239. package/tests/lib/invitations.test.ts +0 -35
  240. package/tests/lib/login-schema.test.ts +0 -36
  241. package/tests/lib/org-context.test.ts +0 -95
  242. package/tests/lib/organization-access.test.ts +0 -44
  243. package/tests/lib/organization-member-role-schema.test.ts +0 -41
  244. package/tests/lib/permissions.test.ts +0 -88
  245. package/tests/lib/portal-analytics.test.ts +0 -25
  246. package/tests/lib/portal-contributors.test.ts +0 -25
  247. package/tests/lib/portal-copy.test.ts +0 -27
  248. package/tests/lib/portal-i18n.test.ts +0 -30
  249. package/tests/lib/portal-leaderboard-settings.test.ts +0 -25
  250. package/tests/lib/portal-modules.test.ts +0 -25
  251. package/tests/lib/portal-seo.test.ts +0 -25
  252. package/tests/lib/portal-sharing.test.ts +0 -25
  253. package/tests/lib/portal-sorting.test.ts +0 -25
  254. package/tests/lib/portal-theme.test.ts +0 -25
  255. package/tests/lib/rate-limit.test.ts +0 -142
  256. package/tests/lib/resolve-locale.test.ts +0 -34
  257. package/tests/lib/services/backup.test.ts +0 -145
  258. package/tests/lib/user-organizations.test.ts +0 -42
  259. package/tests/lib/user-role-schema.test.ts +0 -33
  260. package/tests/lib/user-schema.test.ts +0 -25
  261. package/tests/setup.ts +0 -74
  262. 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.