@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,451 +0,0 @@
1
- # Project Delete Feature Implementation Plan
2
-
3
- > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
4
-
5
- **Goal:** Add ability for admin users to delete projects with a safe confirmation mechanism (typing project name to confirm).
6
-
7
- **Architecture:** Create a delete confirmation dialog component using shadcn AlertDialog. Add a "danger zone" section to the project settings page with a delete button. Call the existing DELETE API endpoint at `/api/projects/[projectId]`.
8
-
9
- **Tech Stack:**
10
- - React 19 (client components)
11
- - Next.js 16 App Router
12
- - Shadcn/ui (AlertDialog, Button, Card, Input)
13
- - Lucide React (icons)
14
- - TypeScript
15
-
16
- ---
17
-
18
- ## Task 1: Create Delete Project Dialog Component
19
-
20
- **Files:**
21
- - Create: `components/project/delete-project-dialog.tsx`
22
-
23
- **Step 1: Create the delete dialog component file**
24
-
25
- Create file `components/project/delete-project-dialog.tsx` with the following content:
26
-
27
- ```tsx
28
- "use client";
29
-
30
- import { useState } from "react";
31
- import { useRouter } from "next/navigation";
32
- import { AlertTriangle } from "lucide-react";
33
- import {
34
- AlertDialog,
35
- AlertDialogAction,
36
- AlertDialogCancel,
37
- AlertDialogContent,
38
- AlertDialogDescription,
39
- AlertDialogFooter,
40
- AlertDialogHeader,
41
- AlertDialogMedia,
42
- AlertDialogTitle,
43
- } from "@/components/ui/alert-dialog";
44
- import { Input } from "@/components/ui/input";
45
- import { Label } from "@/components/ui/label";
46
-
47
- interface DeleteProjectDialogProps {
48
- projectId: string;
49
- projectName: string;
50
- open: boolean;
51
- onOpenChange: (open: boolean) => void;
52
- }
53
-
54
- export function DeleteProjectDialog({
55
- projectId,
56
- projectName,
57
- open,
58
- onOpenChange,
59
- }: DeleteProjectDialogProps) {
60
- const router = useRouter();
61
- const [confirmText, setConfirmText] = useState("");
62
- const [isDeleting, setIsDeleting] = useState(false);
63
- const [error, setError] = useState<string | null>(null);
64
-
65
- const isConfirmMatch = confirmText === projectName;
66
-
67
- async function handleDelete() {
68
- if (!isConfirmMatch) return;
69
-
70
- setIsDeleting(true);
71
- setError(null);
72
-
73
- try {
74
- const response = await fetch(`/api/projects/${projectId}`, {
75
- method: "DELETE",
76
- });
77
-
78
- if (!response.ok) {
79
- const result = await response.json();
80
- throw new Error(result.error || "删除失败");
81
- }
82
-
83
- // Success - close dialog and redirect
84
- onOpenChange(false);
85
- router.push("/settings/projects");
86
- router.refresh();
87
- } catch (err) {
88
- setError(err instanceof Error ? err.message : "删除失败");
89
- setIsDeleting(false);
90
- }
91
- }
92
-
93
- function handleOpenChange(newOpen: boolean) {
94
- if (!isDeleting) {
95
- onOpenChange(newOpen);
96
- // Reset state when closing
97
- if (!newOpen) {
98
- setConfirmText("");
99
- setError(null);
100
- }
101
- }
102
- }
103
-
104
- return (
105
- <AlertDialog open={open} onOpenChange={handleOpenChange}>
106
- <AlertDialogContent>
107
- <AlertDialogHeader>
108
- <AlertDialogMedia>
109
- <AlertTriangle className="text-destructive" />
110
- </AlertDialogMedia>
111
- <AlertDialogTitle>删除项目</AlertDialogTitle>
112
- <AlertDialogDescription>
113
- <div className="space-y-3">
114
- <p>此操作不可撤销。删除项目将会:</p>
115
- <ul className="list-disc space-y-1 pl-5 text-left">
116
- <li>永久删除项目的所有配置</li>
117
- <li>删除所有相关的反馈数据</li>
118
- <li>删除所有相关的评论和附件</li>
119
- </ul>
120
- </div>
121
- </AlertDialogDescription>
122
- </AlertDialogHeader>
123
-
124
- <div className="space-y-2">
125
- <Label htmlFor="confirm-text">
126
- 请输入项目名称 <span className="font-semibold">{projectName}</span> 以确认删除
127
- </Label>
128
- <Input
129
- id="confirm-text"
130
- value={confirmText}
131
- onChange={(e) => setConfirmText(e.target.value)}
132
- placeholder={projectName}
133
- disabled={isDeleting}
134
- autoComplete="off"
135
- />
136
- {error && (
137
- <p className="text-sm text-destructive">{error}</p>
138
- )}
139
- </div>
140
-
141
- <AlertDialogFooter>
142
- <AlertDialogCancel disabled={isDeleting}>取消</AlertDialogCancel>
143
- <AlertDialogAction
144
- variant="destructive"
145
- disabled={!isConfirmMatch || isDeleting}
146
- onClick={(e) => {
147
- e.preventDefault();
148
- handleDelete();
149
- }}
150
- >
151
- {isDeleting ? "删除中..." : "删除项目"}
152
- </AlertDialogAction>
153
- </AlertDialogFooter>
154
- </AlertDialogContent>
155
- </AlertDialog>
156
- );
157
- }
158
- ```
159
-
160
- **Step 2: Verify the component compiles**
161
-
162
- Run TypeScript check:
163
- ```bash
164
- bun run build --dry-run
165
- ```
166
-
167
- Expected: No TypeScript errors in the new file.
168
-
169
- **Step 3: Commit the dialog component**
170
-
171
- ```bash
172
- git add components/project/delete-project-dialog.tsx
173
- git commit -m "feat: add delete project confirmation dialog component"
174
- ```
175
-
176
- ---
177
-
178
- ## Task 2: Add Danger Zone to Project Settings
179
-
180
- **Files:**
181
- - Modify: `components/project/project-settings.tsx`
182
-
183
- **Step 1: Import the delete dialog and required icons**
184
-
185
- At the top of `components/project/project-settings.tsx`, add these imports after the existing imports:
186
-
187
- ```tsx
188
- import { AlertTriangle } from "lucide-react";
189
- import { DeleteProjectDialog } from "./delete-project-dialog";
190
- ```
191
-
192
- **Step 2: Add state for delete dialog**
193
-
194
- Inside the `ProjectSettings` component, after the existing state declarations (around line 54), add:
195
-
196
- ```tsx
197
- const [showDeleteDialog, setShowDeleteDialog] = useState(false);
198
- ```
199
-
200
- Also add the useState import if not already present:
201
-
202
- ```tsx
203
- import { useState } from "react";
204
- ```
205
-
206
- **Step 3: Add danger zone card below the preview card**
207
-
208
- At the end of the return statement, after the closing `</Card>` for the preview (around line 321), add:
209
-
210
- ```tsx
211
- <Card className="border-destructive/50 lg:col-span-2">
212
- <CardHeader>
213
- <CardTitle className="text-destructive flex items-center gap-2">
214
- <AlertTriangle className="h-5 w-5" />
215
- 危险区域
216
- </CardTitle>
217
- <CardDescription>
218
- 这些操作不可逆,请谨慎操作
219
- </CardDescription>
220
- </CardHeader>
221
- <CardContent>
222
- <div className="flex items-start justify-between gap-4">
223
- <div className="flex-1">
224
- <h4 className="font-medium text-sm">删除项目</h4>
225
- <p className="text-sm text-muted-foreground mt-1">
226
- 永久删除此项目及其所有相关数据
227
- </p>
228
- </div>
229
- <Button
230
- variant="destructive"
231
- onClick={() => setShowDeleteDialog(true)}
232
- >
233
- 删除项目
234
- </Button>
235
- </div>
236
- </CardContent>
237
- </Card>
238
-
239
- <DeleteProjectDialog
240
- projectId={project.projectId}
241
- projectName={project.name}
242
- open={showDeleteDialog}
243
- onOpenChange={setShowDeleteDialog}
244
- />
245
- ```
246
-
247
- **Step 4: Verify the updated component compiles**
248
-
249
- Run TypeScript check:
250
- ```bash
251
- bun run build --dry-run
252
- ```
253
-
254
- Expected: No TypeScript errors.
255
-
256
- **Step 5: Test in development mode**
257
-
258
- Start the development server:
259
- ```bash
260
- bun dev
261
- ```
262
-
263
- Navigate to: `http://localhost:3000/settings/projects/[any-project-slug]`
264
-
265
- Expected behavior:
266
- - See "危险区域" card at the bottom with red border
267
- - See "删除项目" button in red
268
- - Clicking the button opens the confirmation dialog
269
- - Dialog shows warning icon and message
270
- - Input field requires exact project name
271
- - Delete button is disabled until text matches
272
- - Cancel button closes dialog
273
-
274
- **Step 6: Commit the changes**
275
-
276
- ```bash
277
- git add components/project/project-settings.tsx
278
- git commit -m "feat: add danger zone with delete button to project settings"
279
- ```
280
-
281
- ---
282
-
283
- ## Task 3: Test Delete Functionality
284
-
285
- **Step 1: Manual testing checklist**
286
-
287
- Test the following scenarios:
288
-
289
- 1. **Permission check**: Log in as non-admin user
290
- - Navigate to project settings
291
- - Verify delete button is visible (backend will reject)
292
-
293
- 2. **Dialog behavior**:
294
- - Click "删除项目" button
295
- - Verify dialog opens
296
- - Verify warning icon and message are displayed
297
- - Type incorrect project name
298
- - Verify "删除项目" button stays disabled
299
- - Type correct project name
300
- - Verify "删除项目" button becomes enabled
301
-
302
- 3. **Cancel flow**:
303
- - Open dialog
304
- - Type partial project name
305
- - Click "取消"
306
- - Verify dialog closes
307
- - Re-open dialog
308
- - Verify input field is empty (state reset)
309
-
310
- 4. **Successful delete**:
311
- - Open dialog
312
- - Type exact project name
313
- - Click "删除项目"
314
- - Verify button shows "删除中..." loading state
315
- - Verify redirect to `/settings/projects`
316
- - Verify project is removed from list
317
-
318
- 5. **Error handling**:
319
- - Simulate network error (disconnect internet)
320
- - Try to delete
321
- - Verify error message is displayed
322
- - Verify dialog stays open
323
- - Verify user can retry
324
-
325
- **Step 2: Document test results**
326
-
327
- Create a test results file:
328
-
329
- ```bash
330
- echo "# Delete Project Feature - Manual Test Results
331
-
332
- Date: $(date +%Y-%m-%d)
333
-
334
- ## Test Cases
335
-
336
- - [ ] Dialog opens when delete button clicked
337
- - [ ] Warning icon and message displayed
338
- - [ ] Input validation works (exact match required)
339
- - [ ] Cancel button closes dialog and resets state
340
- - [ ] Successful delete redirects to project list
341
- - [ ] Error messages displayed on failure
342
- - [ ] Loading state shown during delete
343
- - [ ] Backend permission check works
344
-
345
- ## Notes
346
-
347
- [Add any observations or issues found]
348
- " > docs/testing/delete-project-manual-tests.md
349
- ```
350
-
351
- **Step 3: Commit test documentation**
352
-
353
- ```bash
354
- git add docs/testing/delete-project-manual-tests.md
355
- git commit -m "docs: add manual test checklist for project delete feature"
356
- ```
357
-
358
- ---
359
-
360
- ## Task 4: Update Component Exports (Optional)
361
-
362
- **Files:**
363
- - Modify: `components/project/index.ts` (if it exists)
364
-
365
- **Step 1: Check if index file exists**
366
-
367
- ```bash
368
- ls components/project/index.ts
369
- ```
370
-
371
- **Step 2: If exists, add export**
372
-
373
- If the file exists, add:
374
-
375
- ```tsx
376
- export { DeleteProjectDialog } from "./delete-project-dialog";
377
- ```
378
-
379
- **Step 3: Commit if modified**
380
-
381
- ```bash
382
- git add components/project/index.ts
383
- git commit -m "chore: export DeleteProjectDialog component"
384
- ```
385
-
386
- If the file doesn't exist, skip this task.
387
-
388
- ---
389
-
390
- ## Task 5: Final Verification
391
-
392
- **Step 1: Run full build**
393
-
394
- ```bash
395
- bun run build
396
- ```
397
-
398
- Expected: Build succeeds with no errors.
399
-
400
- **Step 2: Run linter**
401
-
402
- ```bash
403
- bun run lint
404
- ```
405
-
406
- Expected: No new linting errors in modified/created files.
407
-
408
- **Step 3: Create final commit if needed**
409
-
410
- If there are any lint fixes:
411
-
412
- ```bash
413
- git add .
414
- git commit -m "style: fix lint issues in delete project feature"
415
- ```
416
-
417
- ---
418
-
419
- ## Completion Checklist
420
-
421
- - [x] DeleteProjectDialog component created
422
- - [x] Danger zone added to project settings
423
- - [x] Delete button triggers confirmation dialog
424
- - [x] Input validation requires exact project name match
425
- - [x] Successful delete redirects to project list
426
- - [x] Error handling displays user-friendly messages
427
- - [x] Loading states prevent duplicate actions
428
- - [x] All TypeScript checks pass
429
- - [x] Manual testing completed
430
- - [x] Code committed with clear commit messages
431
-
432
- ---
433
-
434
- ## Post-Implementation Notes
435
-
436
- **Future Enhancements:**
437
- 1. Add toast notification on successful delete
438
- 2. Show feedback count before deleting
439
- 3. Add soft delete capability (deletedAt field)
440
- 4. Allow data export before deletion
441
- 5. Add unit tests for DeleteProjectDialog component
442
-
443
- **Known Limitations:**
444
- - No undo functionality (permanent delete)
445
- - No batch delete capability
446
- - No feedback count preview in dialog
447
-
448
- **Related Files:**
449
- - Backend API: `app/api/projects/[projectId]/route.ts` (already implements DELETE)
450
- - Database schema: `lib/db/schema/projects.ts` (cascade delete configured)
451
- - Permissions: Admin-only enforced at API level
@@ -1,52 +0,0 @@
1
- # Design: Project Edit and Delete Features
2
-
3
- ## Overview
4
- Add functionality to edit project details (name, description) and delete projects within the Project Settings page. This completes the project management lifecycle.
5
-
6
- ## Components
7
-
8
- ### 1. `ProjectEditForm`
9
- A client component for editing basic project information.
10
- - **Location**: `components/project/project-edit-form.tsx`
11
- - **Props**: `project: Project`
12
- - **State**: Uses `react-hook-form` with `zodResolver` and `updateProjectSchema`.
13
- - **UI**:
14
- - Card with "Project Details" title.
15
- - Input for Name.
16
- - Textarea for Description.
17
- - Submit button.
18
- - **Action**: calls `PUT /api/projects/[projectId]`.
19
-
20
- ### 2. `ProjectDeleteSection`
21
- A client component for the "Danger Zone".
22
- - **Location**: `components/project/project-delete-section.tsx`
23
- - **Props**: `project: Project`
24
- - **UI**:
25
- - Card with red border/styling to indicate danger.
26
- - Title "Danger Zone".
27
- - "Delete Project" button (destructive variant).
28
- - Confirmation Dialog (`AlertDialog`) requiring user confirmation.
29
- - **Action**: calls `DELETE /api/projects/[projectId]`.
30
- - **Post-Action**: Redirects to `/settings/projects` (or dashboard).
31
-
32
- ### 3. `ProjectSettings` (Refactor)
33
- Update the existing `components/project/project-settings.tsx`.
34
- - Currently, it contains the entire Widget Config form logic.
35
- - **Refactoring**:
36
- - Extract the existing form logic into `components/project/project-widget-form.tsx`.
37
- - Update `ProjectSettings` to be a layout container that renders:
38
- 1. `<ProjectEditForm />`
39
- 2. `<ProjectWidgetForm />` (The extracted widget config)
40
- 3. `<ProjectDeleteSection />`
41
-
42
- ## API Interactions
43
- - **Update**: `PUT /api/projects/[projectId]` (Existing)
44
- - Supports partial updates of `name`, `description`, `widgetConfig`.
45
- - **Delete**: `DELETE /api/projects/[projectId]` (Existing)
46
- - Deletes project and cascades (handled by DB schema, verified in previous reads).
47
-
48
- ## Plan
49
- 1. Extract `ProjectWidgetForm` from `project-settings.tsx`.
50
- 2. Create `ProjectEditForm`.
51
- 3. Create `ProjectDeleteSection`.
52
- 4. Reassemble `ProjectSettings`.
@@ -1,114 +0,0 @@
1
- # Settings Center Design
2
-
3
- ## Overview
4
-
5
- Consolidate all settings-related features (notifications, profile, organization, etc.) into a unified Settings Center, accessible from the user dropdown menu in the sidebar.
6
-
7
- ## Current Problems
8
-
9
- 1. "Notifications Settings" appears in both navigation area and user section
10
- 2. Missing user Profile page entry
11
- 3. "Organization Settings" link points to `/settings/organizations/new` (create page instead of management page)
12
- 4. Settings features scattered across different locations
13
-
14
- ## Design Decisions
15
-
16
- - **Settings entry**: User dropdown menu only (not in main navigation)
17
- - **Layout**: Left-right split layout (sidebar menu + content area)
18
- - **Categories**: Profile, Notifications, Appearance, Organization (admin), API Keys (admin/pm)
19
-
20
- ## Sidebar Structure
21
-
22
- ```
23
- Navigation:
24
- ├── Dashboard /dashboard
25
- └── Feedback /feedback
26
-
27
- Projects:
28
- ├── + New Project
29
- └── Project list...
30
-
31
- User Area (bottom):
32
- └── [Avatar] Username ▼ ← Dropdown menu
33
- ├── Settings → /settings
34
- └── Sign Out
35
- ```
36
-
37
- ## Settings Center Routes
38
-
39
- ```
40
- /settings
41
- ├── /settings/profile Personal profile (default)
42
- ├── /settings/notifications Notification preferences
43
- ├── /settings/appearance Theme settings
44
- ├── /settings/organization Organization management (admin only)
45
- └── /settings/api-keys API key management (admin/pm only)
46
- ```
47
-
48
- ## Page Content
49
-
50
- ### Profile `/settings/profile`
51
- - Avatar upload/change
52
- - Name editing
53
- - Email display (read-only or editable)
54
- - Change password
55
-
56
- ### Notifications `/settings/notifications`
57
- - Email notification toggle
58
- - Notification type preferences (new feedback, status changes, comment replies, etc.)
59
-
60
- ### Appearance `/settings/appearance`
61
- - Theme toggle (light/dark/system)
62
- - Language selection (if needed)
63
-
64
- ### Organization `/settings/organization` (admin only)
65
- - Organization name, description editing
66
- - Member list and role management
67
- - Invite new members
68
-
69
- ### API Keys `/settings/api-keys` (admin/pm only)
70
- - Key list
71
- - Create/delete keys
72
-
73
- ## File Structure
74
-
75
- ```
76
- app/(dashboard)/settings/
77
- ├── layout.tsx ← Settings layout (left-right split)
78
- ├── page.tsx ← Redirect to /settings/profile
79
- ├── profile/page.tsx
80
- ├── notifications/page.tsx
81
- ├── appearance/page.tsx
82
- ├── organization/page.tsx
83
- └── api-keys/page.tsx
84
-
85
- components/settings/
86
- ├── settings-sidebar.tsx ← Left menu with role-based visibility
87
- └── index.ts
88
- ```
89
-
90
- ## Component Changes
91
-
92
- ### Sidebar (`components/layout/sidebar.tsx`)
93
- - Remove "Notifications Settings" and "Organization Settings" nav items
94
- - Replace user area with `DropdownMenu` component
95
- - Dropdown contains: Settings link, Sign Out button
96
-
97
- ### Settings Layout
98
- ```tsx
99
- // SettingsLayout
100
- <div className="flex">
101
- <aside> ← SettingsSidebar (left menu)
102
- <main> ← Content area {children}
103
- </div>
104
- ```
105
-
106
- ### Permission Control
107
- - `SettingsSidebar`: Conditionally render menu items based on `user.role`
108
- - Each page: Server-side permission check (prevent direct URL access)
109
-
110
- ## Implementation Notes
111
-
112
- - Use existing Radix UI `DropdownMenu` component
113
- - Reuse existing notification settings page content
114
- - Organization page should use existing organization/member management logic