@shepai/cli 1.48.0 → 1.49.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apis/json-schema/RejectionFeedbackEntry.yaml +4 -1
- package/dist/packages/core/src/application/use-cases/agents/reject-agent-run.use-case.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/agents/reject-agent-run.use-case.js +3 -0
- package/dist/packages/core/src/domain/generated/output.d.ts +5 -1
- package/dist/packages/core/src/domain/generated/output.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/di/container.js +3 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.js +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge.node.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge.node.js +65 -36
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/merge-prompts.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/merge-prompts.js +34 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/plan.prompt.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/plan.prompt.js +30 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/requirements.prompt.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/requirements.prompt.js +8 -4
- package/dist/src/presentation/cli/commands/feat/show.command.d.ts +6 -0
- package/dist/src/presentation/cli/commands/feat/show.command.d.ts.map +1 -1
- package/dist/src/presentation/cli/commands/feat/show.command.js +52 -14
- package/dist/src/presentation/web/app/actions/approve-feature.d.ts +2 -1
- package/dist/src/presentation/web/app/actions/approve-feature.d.ts.map +1 -1
- package/dist/src/presentation/web/app/actions/approve-feature.js +2 -2
- package/dist/src/presentation/web/app/actions/reject-feature.d.ts +7 -0
- package/dist/src/presentation/web/app/actions/reject-feature.d.ts.map +1 -0
- package/dist/src/presentation/web/app/actions/reject-feature.js +34 -0
- package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar-config.d.ts +24 -0
- package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar-config.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar-config.js +1 -0
- package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.d.ts +3 -0
- package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.js +12 -0
- package/dist/src/presentation/web/components/common/drawer-action-bar/index.d.ts +3 -0
- package/dist/src/presentation/web/components/common/drawer-action-bar/index.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/drawer-action-bar/index.js +1 -0
- package/dist/src/presentation/web/components/common/drawer-revision-input/drawer-revision-input-config.d.ts +11 -0
- package/dist/src/presentation/web/components/common/drawer-revision-input/drawer-revision-input-config.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/drawer-revision-input/drawer-revision-input-config.js +1 -0
- package/dist/src/presentation/web/components/common/drawer-revision-input/drawer-revision-input.d.ts +3 -0
- package/dist/src/presentation/web/components/common/drawer-revision-input/drawer-revision-input.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/drawer-revision-input/drawer-revision-input.js +18 -0
- package/dist/src/presentation/web/components/common/drawer-revision-input/index.d.ts +3 -0
- package/dist/src/presentation/web/components/common/drawer-revision-input/index.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/drawer-revision-input/index.js +1 -0
- package/dist/src/presentation/web/components/common/merge-review/merge-review-config.d.ts +4 -2
- package/dist/src/presentation/web/components/common/merge-review/merge-review-config.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/merge-review/merge-review.d.ts +1 -1
- package/dist/src/presentation/web/components/common/merge-review/merge-review.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/merge-review/merge-review.js +4 -15
- package/dist/src/presentation/web/components/common/merge-review/merge-review.stories.js +1 -1
- package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire-config.d.ts +4 -2
- package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire-config.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.d.ts +1 -1
- package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.js +6 -15
- package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.stories.d.ts +4 -0
- package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.stories.js +24 -3
- package/dist/src/presentation/web/components/common/reject-feedback-dialog/index.d.ts +3 -0
- package/dist/src/presentation/web/components/common/reject-feedback-dialog/index.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/reject-feedback-dialog/index.js +1 -0
- package/dist/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog-config.d.ts +9 -0
- package/dist/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog-config.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog-config.js +1 -0
- package/dist/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog.d.ts +3 -0
- package/dist/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog.js +19 -0
- package/dist/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog.stories.d.ts +14 -0
- package/dist/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog.stories.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog.stories.js +46 -0
- package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review-config.d.ts +4 -2
- package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review-config.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.d.ts +1 -1
- package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.js +4 -14
- package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.stories.d.ts +4 -0
- package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.stories.js +24 -6
- package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/control-center/control-center-inner.js +48 -33
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/build-manifest.json +2 -2
- package/web/.next/cache/.previewinfo +1 -1
- package/web/.next/cache/.rscinfo +1 -1
- package/web/.next/cache/.tsbuildinfo +1 -1
- package/web/.next/cache/config.json +3 -3
- package/web/.next/fallback-build-manifest.json +2 -2
- package/web/.next/prerender-manifest.json +3 -3
- package/web/.next/required-server-files.js +1 -1
- package/web/.next/required-server-files.json +1 -1
- package/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/page/server-reference-manifest.json +41 -26
- package/web/.next/server/app/page.js +2 -1
- package/web/.next/server/app/page.js.nft.json +1 -1
- package/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__03a0dba7._.js +4 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__03a0dba7._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__249c74f6._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__2d1a8e37._.js +9 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__2d1a8e37._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__d8fbe735._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__d8fbe735._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_1fafa9db._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_ed0934e5._.js.map +1 -1
- package/web/.next/server/pages/500.html +2 -2
- package/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/server/server-reference-manifest.json +42 -27
- package/web/.next/standalone/src/presentation/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/src/presentation/web/.next/build-manifest.json +2 -2
- package/web/.next/standalone/src/presentation/web/.next/prerender-manifest.json +3 -3
- package/web/.next/standalone/src/presentation/web/.next/required-server-files.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/page/server-reference-manifest.json +41 -26
- package/web/.next/standalone/src/presentation/web/.next/server/app/page.js +2 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__03a0dba7._.js +4 -4
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__249c74f6._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__2d1a8e37._.js +9 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__d8fbe735._.js +3 -0
- package/web/.next/standalone/src/presentation/web/.next/server/pages/500.html +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.json +42 -27
- package/web/.next/standalone/src/presentation/web/app/actions/approve-feature.ts +4 -2
- package/web/.next/standalone/src/presentation/web/app/actions/reject-feature.ts +52 -0
- package/web/.next/standalone/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar-config.ts +24 -0
- package/web/.next/standalone/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.tsx +64 -0
- package/web/.next/standalone/src/presentation/web/components/common/drawer-action-bar/index.ts +2 -0
- package/web/.next/standalone/src/presentation/web/components/common/drawer-revision-input/drawer-revision-input-config.ts +10 -0
- package/web/.next/standalone/src/presentation/web/components/common/drawer-revision-input/drawer-revision-input.tsx +41 -0
- package/web/.next/standalone/src/presentation/web/components/common/drawer-revision-input/index.ts +2 -0
- package/web/.next/standalone/src/presentation/web/components/common/merge-review/merge-review-config.ts +4 -2
- package/web/.next/standalone/src/presentation/web/components/common/merge-review/merge-review.stories.tsx +1 -1
- package/web/.next/standalone/src/presentation/web/components/common/merge-review/merge-review.tsx +24 -53
- package/web/.next/standalone/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire-config.ts +4 -2
- package/web/.next/standalone/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.stories.tsx +36 -8
- package/web/.next/standalone/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.tsx +16 -47
- package/web/.next/standalone/src/presentation/web/components/common/reject-feedback-dialog/index.ts +2 -0
- package/web/.next/standalone/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog-config.ts +8 -0
- package/web/.next/standalone/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog.stories.tsx +63 -0
- package/web/.next/standalone/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog.tsx +78 -0
- package/web/.next/standalone/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review-config.ts +4 -2
- package/web/.next/standalone/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.stories.tsx +27 -6
- package/web/.next/standalone/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.tsx +14 -42
- package/web/.next/standalone/src/presentation/web/components/features/control-center/control-center-inner.tsx +94 -49
- package/web/.next/standalone/src/presentation/web/server.js +1 -1
- package/web/.next/static/chunks/25cab79117866d51.js +10 -0
- package/web/.next/static/chunks/59b8bd47023e0249.css +2 -0
- package/web/.next/trace +1 -1
- package/web/.next/trace-build +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__19d52794._.js +0 -9
- package/web/.next/server/chunks/ssr/[root-of-the-server]__19d52794._.js.map +0 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__19d52794._.js +0 -9
- package/web/.next/static/chunks/66378a6c055c4e67.js +0 -10
- package/web/.next/static/chunks/8668962d3e682263.css +0 -2
- /package/web/.next/static/{1kZFDMQ0i-Y8dy1KkHlzv → y92RZZcCAiudDG54kYSQf}/_buildManifest.js +0 -0
- /package/web/.next/static/{1kZFDMQ0i-Y8dy1KkHlzv → y92RZZcCAiudDG54kYSQf}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{1kZFDMQ0i-Y8dy1KkHlzv → y92RZZcCAiudDG54kYSQf}/_ssgManifest.js +0 -0
package/web/.next/standalone/src/presentation/web/components/common/merge-review/merge-review.tsx
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { useState } from 'react';
|
|
4
3
|
import {
|
|
5
4
|
CheckCircle2,
|
|
6
5
|
ExternalLink,
|
|
@@ -13,12 +12,10 @@ import {
|
|
|
13
12
|
GitBranch,
|
|
14
13
|
ArrowRight,
|
|
15
14
|
Layers,
|
|
16
|
-
Send,
|
|
17
15
|
} from 'lucide-react';
|
|
18
16
|
import { CiStatus } from '@shepai/core/domain/generated/output';
|
|
19
17
|
import { Badge } from '@/components/ui/badge';
|
|
20
|
-
import {
|
|
21
|
-
import { Input } from '@/components/ui/input';
|
|
18
|
+
import { DrawerActionBar } from '@/components/common/drawer-action-bar';
|
|
22
19
|
import type { MergeReviewProps, MergeReviewPhase } from './merge-review-config';
|
|
23
20
|
|
|
24
21
|
function CiStatusBadge({ status }: { status: CiStatus }) {
|
|
@@ -77,17 +74,14 @@ function PhaseList({ phases }: { phases: MergeReviewPhase[] }) {
|
|
|
77
74
|
);
|
|
78
75
|
}
|
|
79
76
|
|
|
80
|
-
export function MergeReview({
|
|
77
|
+
export function MergeReview({
|
|
78
|
+
data,
|
|
79
|
+
onApprove,
|
|
80
|
+
onReject,
|
|
81
|
+
isProcessing = false,
|
|
82
|
+
isRejecting = false,
|
|
83
|
+
}: MergeReviewProps) {
|
|
81
84
|
const { pr, diffSummary, phases, branch, warning } = data;
|
|
82
|
-
const [chatInput, setChatInput] = useState('');
|
|
83
|
-
|
|
84
|
-
function handleSubmit(e: { preventDefault: () => void }) {
|
|
85
|
-
e.preventDefault();
|
|
86
|
-
const text = chatInput.trim();
|
|
87
|
-
if (!text) return;
|
|
88
|
-
onRefine(text);
|
|
89
|
-
setChatInput('');
|
|
90
|
-
}
|
|
91
85
|
|
|
92
86
|
return (
|
|
93
87
|
<div className="flex h-full flex-col">
|
|
@@ -208,45 +202,22 @@ export function MergeReview({ data, onApprove, onRefine, isProcessing = false }:
|
|
|
208
202
|
{phases && phases.length > 0 ? <PhaseList phases={phases} /> : null}
|
|
209
203
|
</div>
|
|
210
204
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
aria-label="Send"
|
|
228
|
-
disabled={isProcessing}
|
|
229
|
-
>
|
|
230
|
-
<Send />
|
|
231
|
-
</Button>
|
|
232
|
-
</form>
|
|
233
|
-
<div className="px-4 pt-2 pb-4">
|
|
234
|
-
<Button
|
|
235
|
-
type="button"
|
|
236
|
-
className="w-full"
|
|
237
|
-
disabled={isProcessing}
|
|
238
|
-
onClick={onApprove}
|
|
239
|
-
aria-label="Approve Merge"
|
|
240
|
-
>
|
|
241
|
-
{isProcessing ? (
|
|
242
|
-
<Loader2 className="mr-1.5 h-4 w-4 animate-spin" />
|
|
243
|
-
) : (
|
|
244
|
-
<GitMerge className="mr-1.5 h-4 w-4" />
|
|
245
|
-
)}
|
|
246
|
-
Approve Merge
|
|
247
|
-
</Button>
|
|
248
|
-
</div>
|
|
249
|
-
</div>
|
|
205
|
+
<DrawerActionBar
|
|
206
|
+
onReject={onReject}
|
|
207
|
+
onApprove={onApprove}
|
|
208
|
+
approveLabel="Approve Merge"
|
|
209
|
+
approveIcon={
|
|
210
|
+
isProcessing ? (
|
|
211
|
+
<Loader2 className="mr-1.5 h-4 w-4 animate-spin" />
|
|
212
|
+
) : (
|
|
213
|
+
<GitMerge className="mr-1.5 h-4 w-4" />
|
|
214
|
+
)
|
|
215
|
+
}
|
|
216
|
+
revisionPlaceholder="Ask AI to revise before merging..."
|
|
217
|
+
rejectDialogTitle="Reject Merge"
|
|
218
|
+
isProcessing={isProcessing}
|
|
219
|
+
isRejecting={isRejecting}
|
|
220
|
+
/>
|
|
250
221
|
</div>
|
|
251
222
|
);
|
|
252
223
|
}
|
|
@@ -14,12 +14,14 @@ export interface PrdQuestionnaireProps {
|
|
|
14
14
|
selections: Record<string, string>;
|
|
15
15
|
/** Selection change callback */
|
|
16
16
|
onSelect: (questionId: string, optionId: string) => void;
|
|
17
|
-
/** Chat refinement submit callback */
|
|
18
|
-
onRefine: (text: string) => void;
|
|
19
17
|
/** Finalize requirements callback */
|
|
20
18
|
onApprove: (actionId: string) => void;
|
|
19
|
+
/** Reject requirements callback — opens feedback dialog when provided; also used for inline text rejection */
|
|
20
|
+
onReject?: (feedback: string) => void;
|
|
21
21
|
/** Controls disabled/animated state during refinement */
|
|
22
22
|
isProcessing?: boolean;
|
|
23
|
+
/** Whether a reject operation is in flight */
|
|
24
|
+
isRejecting?: boolean;
|
|
23
25
|
/** Show the goal/context header (default: false) */
|
|
24
26
|
showHeader?: boolean;
|
|
25
27
|
}
|
|
@@ -146,10 +146,9 @@ const mockFinalAction = {
|
|
|
146
146
|
function InteractiveQuestionnaire({
|
|
147
147
|
selections: initialSelections = {},
|
|
148
148
|
...props
|
|
149
|
-
}: Omit<
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
> & { selections?: Record<string, string> }) {
|
|
149
|
+
}: Omit<React.ComponentProps<typeof PrdQuestionnaire>, 'onSelect' | 'onApprove' | 'selections'> & {
|
|
150
|
+
selections?: Record<string, string>;
|
|
151
|
+
}) {
|
|
153
152
|
const [selections, setSelections] = useState<Record<string, string>>(initialSelections);
|
|
154
153
|
|
|
155
154
|
return (
|
|
@@ -157,7 +156,6 @@ function InteractiveQuestionnaire({
|
|
|
157
156
|
{...props}
|
|
158
157
|
selections={selections}
|
|
159
158
|
onSelect={(qId, optId) => setSelections((prev) => ({ ...prev, [qId]: optId }))}
|
|
160
|
-
onRefine={fn().mockName('onRefine')}
|
|
161
159
|
onApprove={fn().mockName('onApprove')}
|
|
162
160
|
/>
|
|
163
161
|
);
|
|
@@ -174,7 +172,6 @@ const meta: Meta<typeof PrdQuestionnaire> = {
|
|
|
174
172
|
},
|
|
175
173
|
argTypes: {
|
|
176
174
|
onSelect: { action: 'onSelect' },
|
|
177
|
-
onRefine: { action: 'onRefine' },
|
|
178
175
|
onApprove: { action: 'onApprove' },
|
|
179
176
|
},
|
|
180
177
|
decorators: [
|
|
@@ -296,7 +293,7 @@ function DrawerTemplate({
|
|
|
296
293
|
...props
|
|
297
294
|
}: Omit<
|
|
298
295
|
React.ComponentProps<typeof PrdQuestionnaireDrawer>,
|
|
299
|
-
'open' | 'onClose' | 'onSelect' | '
|
|
296
|
+
'open' | 'onClose' | 'onSelect' | 'onApprove' | 'selections'
|
|
300
297
|
> & { selections?: Record<string, string> }) {
|
|
301
298
|
const [open, setOpen] = useState(true);
|
|
302
299
|
const [selections, setSelections] = useState<Record<string, string>>(initialSelections);
|
|
@@ -316,7 +313,6 @@ function DrawerTemplate({
|
|
|
316
313
|
onClose={() => setOpen(false)}
|
|
317
314
|
selections={selections}
|
|
318
315
|
onSelect={(qId, optId) => setSelections((prev) => ({ ...prev, [qId]: optId }))}
|
|
319
|
-
onRefine={fn().mockName('onRefine')}
|
|
320
316
|
onApprove={fn().mockName('onApprove')}
|
|
321
317
|
/>
|
|
322
318
|
</div>
|
|
@@ -383,3 +379,35 @@ export const DeletingState: DrawerStory = {
|
|
|
383
379
|
/>
|
|
384
380
|
),
|
|
385
381
|
};
|
|
382
|
+
|
|
383
|
+
/* ─── Reject Variants ─── */
|
|
384
|
+
|
|
385
|
+
const allAnsweredSelections = {
|
|
386
|
+
problem: 'user_pain',
|
|
387
|
+
priority: 'p1',
|
|
388
|
+
success: 'adoption',
|
|
389
|
+
timeline: 'sprint',
|
|
390
|
+
scope: 'mvp',
|
|
391
|
+
stakeholders: 'end_users',
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
/** All answered with reject button visible on last step. */
|
|
395
|
+
export const WithRejectButton: Story = {
|
|
396
|
+
render: () => (
|
|
397
|
+
<InteractiveQuestionnaire
|
|
398
|
+
data={mockData}
|
|
399
|
+
selections={allAnsweredSelections}
|
|
400
|
+
onReject={fn().mockName('onReject')}
|
|
401
|
+
/>
|
|
402
|
+
),
|
|
403
|
+
};
|
|
404
|
+
|
|
405
|
+
/** Rejecting state — reject button disabled with spinner while reject action is in flight. */
|
|
406
|
+
export const RejectingState: Story = {
|
|
407
|
+
args: {
|
|
408
|
+
data: mockData,
|
|
409
|
+
selections: allAnsweredSelections,
|
|
410
|
+
onReject: fn().mockName('onReject'),
|
|
411
|
+
isRejecting: true,
|
|
412
|
+
},
|
|
413
|
+
};
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { Check, ChevronLeft, ChevronRight } from 'lucide-react';
|
|
4
4
|
import { useCallback, useMemo, useState } from 'react';
|
|
5
5
|
import { cn } from '@/lib/utils';
|
|
6
6
|
import { Button } from '@/components/ui/button';
|
|
7
|
-
import { Input } from '@/components/ui/input';
|
|
8
7
|
import { Badge } from '@/components/ui/badge';
|
|
8
|
+
import { DrawerActionBar } from '@/components/common/drawer-action-bar';
|
|
9
9
|
import type { PrdQuestionnaireProps } from './prd-questionnaire-config';
|
|
10
10
|
|
|
11
11
|
export function PrdQuestionnaire({
|
|
12
12
|
data,
|
|
13
13
|
selections,
|
|
14
14
|
onSelect,
|
|
15
|
-
onRefine,
|
|
16
15
|
onApprove,
|
|
16
|
+
onReject,
|
|
17
17
|
isProcessing = false,
|
|
18
|
+
isRejecting = false,
|
|
18
19
|
showHeader = false,
|
|
19
20
|
}: PrdQuestionnaireProps) {
|
|
20
21
|
const { question, context, questions, finalAction } = data;
|
|
21
22
|
const [currentStep, setCurrentStep] = useState(0);
|
|
22
|
-
const [chatInput, setChatInput] = useState('');
|
|
23
23
|
|
|
24
24
|
const total = questions.length;
|
|
25
25
|
const isFirstStep = currentStep === 0;
|
|
@@ -39,14 +39,6 @@ export function PrdQuestionnaire({
|
|
|
39
39
|
[onSelect, isLastStep]
|
|
40
40
|
);
|
|
41
41
|
|
|
42
|
-
function handleSubmit(e: { preventDefault: () => void }) {
|
|
43
|
-
e.preventDefault();
|
|
44
|
-
const text = chatInput.trim();
|
|
45
|
-
if (!text) return;
|
|
46
|
-
onRefine(text);
|
|
47
|
-
setChatInput('');
|
|
48
|
-
}
|
|
49
|
-
|
|
50
42
|
if (total === 0) return null;
|
|
51
43
|
|
|
52
44
|
return (
|
|
@@ -143,17 +135,7 @@ export function PrdQuestionnaire({
|
|
|
143
135
|
Previous
|
|
144
136
|
</Button>
|
|
145
137
|
|
|
146
|
-
{isLastStep ? (
|
|
147
|
-
<Button
|
|
148
|
-
type="button"
|
|
149
|
-
size="sm"
|
|
150
|
-
disabled={isProcessing || answeredCount < total}
|
|
151
|
-
onClick={() => onApprove(finalAction.id)}
|
|
152
|
-
>
|
|
153
|
-
<Check className="mr-1 h-4 w-4" />
|
|
154
|
-
{finalAction.label}
|
|
155
|
-
</Button>
|
|
156
|
-
) : (
|
|
138
|
+
{!isLastStep ? (
|
|
157
139
|
<Button
|
|
158
140
|
type="button"
|
|
159
141
|
variant="ghost"
|
|
@@ -164,12 +146,19 @@ export function PrdQuestionnaire({
|
|
|
164
146
|
{selections[currentQuestion.id] ? 'Next' : 'Skip'}
|
|
165
147
|
<ChevronRight className="ml-1 h-4 w-4" />
|
|
166
148
|
</Button>
|
|
167
|
-
)}
|
|
149
|
+
) : null}
|
|
168
150
|
</div>
|
|
169
151
|
</div>
|
|
170
152
|
|
|
171
|
-
|
|
172
|
-
|
|
153
|
+
<DrawerActionBar
|
|
154
|
+
onReject={onReject}
|
|
155
|
+
onApprove={() => onApprove(finalAction.id)}
|
|
156
|
+
approveLabel={finalAction.label}
|
|
157
|
+
approveIcon={<Check className="mr-1.5 h-4 w-4" />}
|
|
158
|
+
revisionPlaceholder="Ask AI to refine requirements..."
|
|
159
|
+
isProcessing={isProcessing}
|
|
160
|
+
isRejecting={isRejecting}
|
|
161
|
+
>
|
|
173
162
|
<div
|
|
174
163
|
className={cn(
|
|
175
164
|
'bg-muted h-1.5 overflow-hidden',
|
|
@@ -190,27 +179,7 @@ export function PrdQuestionnaire({
|
|
|
190
179
|
/>
|
|
191
180
|
)}
|
|
192
181
|
</div>
|
|
193
|
-
|
|
194
|
-
<Input
|
|
195
|
-
type="text"
|
|
196
|
-
placeholder="Ask AI to refine requirements..."
|
|
197
|
-
aria-label="Ask AI to refine requirements"
|
|
198
|
-
disabled={isProcessing}
|
|
199
|
-
value={chatInput}
|
|
200
|
-
onChange={(e) => setChatInput(e.target.value)}
|
|
201
|
-
className="flex-1"
|
|
202
|
-
/>
|
|
203
|
-
<Button
|
|
204
|
-
type="submit"
|
|
205
|
-
variant="secondary"
|
|
206
|
-
size="icon"
|
|
207
|
-
aria-label="Send"
|
|
208
|
-
disabled={isProcessing}
|
|
209
|
-
>
|
|
210
|
-
<Send />
|
|
211
|
-
</Button>
|
|
212
|
-
</form>
|
|
213
|
-
</div>
|
|
182
|
+
</DrawerActionBar>
|
|
214
183
|
</div>
|
|
215
184
|
);
|
|
216
185
|
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { fn } from '@storybook/test';
|
|
3
|
+
import { RejectFeedbackDialog } from './reject-feedback-dialog';
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof RejectFeedbackDialog> = {
|
|
6
|
+
title: 'Composed/RejectFeedbackDialog',
|
|
7
|
+
component: RejectFeedbackDialog,
|
|
8
|
+
tags: ['autodocs'],
|
|
9
|
+
parameters: {
|
|
10
|
+
layout: 'centered',
|
|
11
|
+
},
|
|
12
|
+
args: {
|
|
13
|
+
open: true,
|
|
14
|
+
onOpenChange: fn().mockName('onOpenChange'),
|
|
15
|
+
onConfirm: fn().mockName('onConfirm'),
|
|
16
|
+
isSubmitting: false,
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default meta;
|
|
21
|
+
type Story = StoryObj<typeof RejectFeedbackDialog>;
|
|
22
|
+
|
|
23
|
+
/** Default — dialog open with empty feedback; confirm button disabled. */
|
|
24
|
+
export const Default: Story = {};
|
|
25
|
+
|
|
26
|
+
/** With feedback entered — confirm button enabled. */
|
|
27
|
+
export const WithFeedback: Story = {
|
|
28
|
+
play: async ({ canvasElement }) => {
|
|
29
|
+
// Type feedback into the textarea to show enabled state
|
|
30
|
+
const textarea = canvasElement.ownerDocument.querySelector(
|
|
31
|
+
'textarea[aria-label="Rejection feedback"]'
|
|
32
|
+
) as HTMLTextAreaElement | null;
|
|
33
|
+
if (textarea) {
|
|
34
|
+
// Simulate React-compatible input
|
|
35
|
+
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
|
|
36
|
+
window.HTMLTextAreaElement.prototype,
|
|
37
|
+
'value'
|
|
38
|
+
)?.set;
|
|
39
|
+
nativeInputValueSetter?.call(
|
|
40
|
+
textarea,
|
|
41
|
+
'The requirements are missing error handling for edge cases. Please add validation for empty inputs.'
|
|
42
|
+
);
|
|
43
|
+
textarea.dispatchEvent(new Event('input', { bubbles: true }));
|
|
44
|
+
textarea.dispatchEvent(new Event('change', { bubbles: true }));
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/** Submitting state — spinner shown, buttons disabled. */
|
|
50
|
+
export const Submitting: Story = {
|
|
51
|
+
args: {
|
|
52
|
+
isSubmitting: true,
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/** Custom title and description for tech decisions context. */
|
|
57
|
+
export const CustomTitle: Story = {
|
|
58
|
+
args: {
|
|
59
|
+
title: 'Reject Plan',
|
|
60
|
+
description:
|
|
61
|
+
'Provide feedback on the technical plan for the agent to revise. Be specific about which decisions need changes.',
|
|
62
|
+
},
|
|
63
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useEffect, useState } from 'react';
|
|
4
|
+
import { Loader2 } from 'lucide-react';
|
|
5
|
+
import {
|
|
6
|
+
AlertDialog,
|
|
7
|
+
AlertDialogAction,
|
|
8
|
+
AlertDialogCancel,
|
|
9
|
+
AlertDialogContent,
|
|
10
|
+
AlertDialogDescription,
|
|
11
|
+
AlertDialogFooter,
|
|
12
|
+
AlertDialogHeader,
|
|
13
|
+
AlertDialogTitle,
|
|
14
|
+
} from '@/components/ui/alert-dialog';
|
|
15
|
+
import { Textarea } from '@/components/ui/textarea';
|
|
16
|
+
import type { RejectFeedbackDialogProps } from './reject-feedback-dialog-config';
|
|
17
|
+
|
|
18
|
+
const DEFAULT_TITLE = 'Reject Requirements';
|
|
19
|
+
const DEFAULT_DESCRIPTION =
|
|
20
|
+
'Provide feedback for the agent to address in the next iteration. Feedback is required.';
|
|
21
|
+
|
|
22
|
+
export function RejectFeedbackDialog({
|
|
23
|
+
open,
|
|
24
|
+
onOpenChange,
|
|
25
|
+
onConfirm,
|
|
26
|
+
isSubmitting,
|
|
27
|
+
title = DEFAULT_TITLE,
|
|
28
|
+
description = DEFAULT_DESCRIPTION,
|
|
29
|
+
}: RejectFeedbackDialogProps) {
|
|
30
|
+
const [feedback, setFeedback] = useState('');
|
|
31
|
+
|
|
32
|
+
// Reset feedback when dialog opens
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (open) {
|
|
35
|
+
setFeedback('');
|
|
36
|
+
}
|
|
37
|
+
}, [open]);
|
|
38
|
+
|
|
39
|
+
const isFeedbackEmpty = feedback.trim().length === 0;
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<AlertDialog open={open} onOpenChange={onOpenChange}>
|
|
43
|
+
<AlertDialogContent>
|
|
44
|
+
<AlertDialogHeader>
|
|
45
|
+
<AlertDialogTitle>{title}</AlertDialogTitle>
|
|
46
|
+
<AlertDialogDescription>{description}</AlertDialogDescription>
|
|
47
|
+
</AlertDialogHeader>
|
|
48
|
+
<Textarea
|
|
49
|
+
aria-label="Rejection feedback"
|
|
50
|
+
placeholder="Describe what needs to change..."
|
|
51
|
+
value={feedback}
|
|
52
|
+
onChange={(e) => setFeedback(e.target.value)}
|
|
53
|
+
disabled={isSubmitting}
|
|
54
|
+
rows={4}
|
|
55
|
+
/>
|
|
56
|
+
<AlertDialogFooter>
|
|
57
|
+
<AlertDialogCancel disabled={isSubmitting} onClick={() => onOpenChange(false)}>
|
|
58
|
+
Cancel
|
|
59
|
+
</AlertDialogCancel>
|
|
60
|
+
<AlertDialogAction
|
|
61
|
+
variant="destructive"
|
|
62
|
+
disabled={isFeedbackEmpty || isSubmitting}
|
|
63
|
+
onClick={() => onConfirm(feedback.trim())}
|
|
64
|
+
>
|
|
65
|
+
{isSubmitting ? (
|
|
66
|
+
<>
|
|
67
|
+
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
|
68
|
+
Rejecting…
|
|
69
|
+
</>
|
|
70
|
+
) : (
|
|
71
|
+
'Confirm Reject'
|
|
72
|
+
)}
|
|
73
|
+
</AlertDialogAction>
|
|
74
|
+
</AlertDialogFooter>
|
|
75
|
+
</AlertDialogContent>
|
|
76
|
+
</AlertDialog>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
@@ -12,12 +12,14 @@ export interface TechDecisionsReviewData {
|
|
|
12
12
|
export interface TechDecisionsReviewProps {
|
|
13
13
|
/** Tech decisions data from the research artifact */
|
|
14
14
|
data: TechDecisionsReviewData;
|
|
15
|
-
/** Chat refinement callback — sends user feedback to the agent */
|
|
16
|
-
onRefine: (text: string) => void;
|
|
17
15
|
/** Approve plan callback */
|
|
18
16
|
onApprove: () => void;
|
|
17
|
+
/** Reject plan callback — opens feedback dialog when provided; also used for inline text rejection */
|
|
18
|
+
onReject?: (feedback: string) => void;
|
|
19
19
|
/** Controls disabled state during loading */
|
|
20
20
|
isProcessing?: boolean;
|
|
21
|
+
/** Whether a reject operation is in flight */
|
|
22
|
+
isRejecting?: boolean;
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
export interface TechDecisionsDrawerProps extends TechDecisionsReviewProps {
|
|
@@ -67,7 +67,7 @@ type Story = StoryObj<typeof TechDecisionsReview>;
|
|
|
67
67
|
export const Default: Story = {
|
|
68
68
|
args: {
|
|
69
69
|
data: mockData,
|
|
70
|
-
|
|
70
|
+
onReject: fn().mockName('onReject'),
|
|
71
71
|
onApprove: fn().mockName('onApprove'),
|
|
72
72
|
},
|
|
73
73
|
};
|
|
@@ -85,7 +85,7 @@ export const Processing: Story = {
|
|
|
85
85
|
export const SingleDecision: Story = {
|
|
86
86
|
args: {
|
|
87
87
|
data: { ...mockData, decisions: [mockData.decisions[0]] },
|
|
88
|
-
|
|
88
|
+
onReject: fn().mockName('onReject'),
|
|
89
89
|
onApprove: fn().mockName('onApprove'),
|
|
90
90
|
},
|
|
91
91
|
};
|
|
@@ -94,7 +94,7 @@ export const SingleDecision: Story = {
|
|
|
94
94
|
export const NoTechnologies: Story = {
|
|
95
95
|
args: {
|
|
96
96
|
data: { ...mockData, technologies: [] },
|
|
97
|
-
|
|
97
|
+
onReject: fn().mockName('onReject'),
|
|
98
98
|
onApprove: fn().mockName('onApprove'),
|
|
99
99
|
},
|
|
100
100
|
};
|
|
@@ -139,8 +139,8 @@ export const InDrawer: DrawerStory = {
|
|
|
139
139
|
featureName="Agent Executor Abstraction"
|
|
140
140
|
featureId="FEAT-099"
|
|
141
141
|
data={mockData}
|
|
142
|
-
onRefine={fn().mockName('onRefine')}
|
|
143
142
|
onApprove={fn().mockName('onApprove')}
|
|
143
|
+
onReject={fn().mockName('onReject')}
|
|
144
144
|
/>
|
|
145
145
|
),
|
|
146
146
|
};
|
|
@@ -153,8 +153,8 @@ export const WithDeleteButton: DrawerStory = {
|
|
|
153
153
|
featureName="Agent Executor Abstraction"
|
|
154
154
|
featureId="FEAT-099"
|
|
155
155
|
data={mockData}
|
|
156
|
-
onRefine={fn().mockName('onRefine')}
|
|
157
156
|
onApprove={fn().mockName('onApprove')}
|
|
157
|
+
onReject={fn().mockName('onReject')}
|
|
158
158
|
onDelete={fn().mockName('onDelete')}
|
|
159
159
|
/>
|
|
160
160
|
),
|
|
@@ -168,10 +168,31 @@ export const DeletingState: DrawerStory = {
|
|
|
168
168
|
featureName="Agent Executor Abstraction"
|
|
169
169
|
featureId="FEAT-099"
|
|
170
170
|
data={mockData}
|
|
171
|
-
onRefine={fn().mockName('onRefine')}
|
|
172
171
|
onApprove={fn().mockName('onApprove')}
|
|
172
|
+
onReject={fn().mockName('onReject')}
|
|
173
173
|
onDelete={fn().mockName('onDelete')}
|
|
174
174
|
isDeleting
|
|
175
175
|
/>
|
|
176
176
|
),
|
|
177
177
|
};
|
|
178
|
+
|
|
179
|
+
/* ─── Reject Variants ─── */
|
|
180
|
+
|
|
181
|
+
/** With reject button visible next to approve. */
|
|
182
|
+
export const WithRejectButton: Story = {
|
|
183
|
+
args: {
|
|
184
|
+
data: mockData,
|
|
185
|
+
onApprove: fn().mockName('onApprove'),
|
|
186
|
+
onReject: fn().mockName('onReject'),
|
|
187
|
+
},
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
/** Rejecting state — reject button disabled while reject action is in flight. */
|
|
191
|
+
export const RejectingState: Story = {
|
|
192
|
+
args: {
|
|
193
|
+
data: mockData,
|
|
194
|
+
onApprove: fn().mockName('onApprove'),
|
|
195
|
+
onReject: fn().mockName('onReject'),
|
|
196
|
+
isRejecting: true,
|
|
197
|
+
},
|
|
198
|
+
};
|
|
@@ -3,10 +3,9 @@
|
|
|
3
3
|
import { useState } from 'react';
|
|
4
4
|
import type { Components } from 'react-markdown';
|
|
5
5
|
import Markdown from 'react-markdown';
|
|
6
|
-
import { Check, ChevronRight, GitCompareArrows, Layers
|
|
6
|
+
import { Check, ChevronRight, GitCompareArrows, Layers } from 'lucide-react';
|
|
7
7
|
import { Badge } from '@/components/ui/badge';
|
|
8
|
-
import {
|
|
9
|
-
import { Input } from '@/components/ui/input';
|
|
8
|
+
import { DrawerActionBar } from '@/components/common/drawer-action-bar';
|
|
10
9
|
import type { TechDecisionsReviewProps, TechDecision } from './tech-decisions-review-config';
|
|
11
10
|
|
|
12
11
|
const markdownComponents: Components = {
|
|
@@ -109,20 +108,12 @@ function DecisionCard({ decision, index }: { decision: TechDecision; index: numb
|
|
|
109
108
|
|
|
110
109
|
export function TechDecisionsReview({
|
|
111
110
|
data,
|
|
112
|
-
onRefine,
|
|
113
111
|
onApprove,
|
|
112
|
+
onReject,
|
|
114
113
|
isProcessing = false,
|
|
114
|
+
isRejecting = false,
|
|
115
115
|
}: TechDecisionsReviewProps) {
|
|
116
116
|
const { summary, decisions } = data;
|
|
117
|
-
const [chatInput, setChatInput] = useState('');
|
|
118
|
-
|
|
119
|
-
function handleSubmit(e: { preventDefault: () => void }) {
|
|
120
|
-
e.preventDefault();
|
|
121
|
-
const text = chatInput.trim();
|
|
122
|
-
if (!text) return;
|
|
123
|
-
onRefine(text);
|
|
124
|
-
setChatInput('');
|
|
125
|
-
}
|
|
126
117
|
|
|
127
118
|
if (decisions.length === 0) return null;
|
|
128
119
|
|
|
@@ -154,35 +145,16 @@ export function TechDecisionsReview({
|
|
|
154
145
|
))}
|
|
155
146
|
</div>
|
|
156
147
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
className="flex-1"
|
|
168
|
-
/>
|
|
169
|
-
<Button
|
|
170
|
-
type="submit"
|
|
171
|
-
variant="secondary"
|
|
172
|
-
size="icon"
|
|
173
|
-
aria-label="Send"
|
|
174
|
-
disabled={isProcessing}
|
|
175
|
-
>
|
|
176
|
-
<Send />
|
|
177
|
-
</Button>
|
|
178
|
-
</form>
|
|
179
|
-
<div className="px-4 pt-2 pb-4">
|
|
180
|
-
<Button type="button" className="w-full" disabled={isProcessing} onClick={onApprove}>
|
|
181
|
-
<Check className="mr-1.5 h-4 w-4" />
|
|
182
|
-
Approve Plan
|
|
183
|
-
</Button>
|
|
184
|
-
</div>
|
|
185
|
-
</div>
|
|
148
|
+
<DrawerActionBar
|
|
149
|
+
onReject={onReject}
|
|
150
|
+
onApprove={onApprove}
|
|
151
|
+
approveLabel="Approve Plan"
|
|
152
|
+
approveIcon={<Check className="mr-1.5 h-4 w-4" />}
|
|
153
|
+
revisionPlaceholder="Ask AI to revise the plan..."
|
|
154
|
+
rejectDialogTitle="Reject Plan"
|
|
155
|
+
isProcessing={isProcessing}
|
|
156
|
+
isRejecting={isRejecting}
|
|
157
|
+
/>
|
|
186
158
|
</div>
|
|
187
159
|
);
|
|
188
160
|
}
|