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