feat(PBI-49): add debugProps to jobs/ + ideas/ components
This commit is contained in:
parent
6c004ffc74
commit
c9f0e65a3d
15 changed files with 45 additions and 22 deletions
|
|
@ -9,6 +9,7 @@ import { Download } from 'lucide-react'
|
|||
import { toast } from 'sonner'
|
||||
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { debugProps } from '@/lib/debug'
|
||||
import { downloadIdeaMdAction } from '@/actions/ideas'
|
||||
|
||||
interface Props {
|
||||
|
|
@ -47,6 +48,7 @@ export function DownloadMdButton({ ideaId, kind, hasContent }: Props) {
|
|||
onClick={handleClick}
|
||||
disabled={pending || !hasContent}
|
||||
title={hasContent ? `Download ${kind}_md` : 'Geen content'}
|
||||
{...debugProps('download-md-button', 'DownloadMdButton', 'components/ideas/download-md-button.tsx')}
|
||||
>
|
||||
<Download className="size-3.5 mr-1" />
|
||||
.md
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import { getIdeaStatusBadge } from '@/lib/idea-status-colors'
|
|||
import type { IdeaStatusApi } from '@/lib/idea-status'
|
||||
import { isIdeaEditable } from '@/lib/idea-status'
|
||||
import type { IdeaDto } from '@/lib/idea-dto'
|
||||
import { debugProps } from '@/lib/debug'
|
||||
import { updateIdeaAction, archiveIdeaAction, updateSecondaryProductsAction } from '@/actions/ideas'
|
||||
import { IdeaRowActions } from '@/components/ideas/idea-row-actions'
|
||||
import { IdeaMdEditor } from '@/components/ideas/idea-md-editor'
|
||||
|
|
@ -132,7 +133,7 @@ export function IdeaDetailLayout({
|
|||
const badge = getIdeaStatusBadge(API_TO_DB[idea.status])
|
||||
|
||||
return (
|
||||
<div className="p-6 max-w-5xl mx-auto w-full space-y-6">
|
||||
<div className="p-6 max-w-5xl mx-auto w-full space-y-6" {...debugProps('idea-detail-layout', 'IdeaDetailLayout', 'components/ideas/idea-detail-layout.tsx')}>
|
||||
{/* Breadcrumb / back-link */}
|
||||
<Link
|
||||
href="/ideas"
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import { DemoTooltip } from '@/components/shared/demo-tooltip'
|
|||
import { getIdeaStatusBadge } from '@/lib/idea-status-colors'
|
||||
import type { IdeaStatusApi } from '@/lib/idea-status'
|
||||
import type { IdeaDto } from '@/lib/idea-dto'
|
||||
import { debugProps } from '@/lib/debug'
|
||||
import { createIdeaAction, archiveIdeaAction } from '@/actions/ideas'
|
||||
import { IdeaRowActions } from '@/components/ideas/idea-row-actions'
|
||||
|
||||
|
|
@ -258,7 +259,7 @@ export function IdeaList({ ideas, products, isDemo }: IdeaListProps) {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-4" {...debugProps('idea-list', 'IdeaList', 'components/ideas/idea-list.tsx')}>
|
||||
{/* Top-bar: search + nieuw-knop */}
|
||||
<div className="flex flex-wrap items-center gap-3">
|
||||
<Input
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import { toast } from 'sonner'
|
|||
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Textarea } from '@/components/ui/textarea'
|
||||
import { debugProps } from '@/lib/debug'
|
||||
import { parsePlanMd, type PlanParseError } from '@/lib/idea-plan-parser'
|
||||
import { updateGrillMdAction, updatePlanMdAction } from '@/actions/ideas'
|
||||
|
||||
|
|
@ -112,7 +113,7 @@ export function IdeaMdEditor({ ideaId, kind, initialValue, onCancel }: Props) {
|
|||
const dirty = value !== initialValue
|
||||
|
||||
return (
|
||||
<div className="space-y-3">
|
||||
<div className="space-y-3" {...debugProps('idea-md-editor', 'IdeaMdEditor', 'components/ideas/idea-md-editor.tsx')}>
|
||||
{errors.length > 0 && (
|
||||
<div className="rounded-md border border-status-blocked/30 bg-status-blocked/10 p-3 space-y-1">
|
||||
<p className="text-xs font-medium text-status-blocked">
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { ExternalLink, Link2Off } from 'lucide-react'
|
|||
import { toast } from 'sonner'
|
||||
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { debugProps } from '@/lib/debug'
|
||||
import { relinkIdeaPlanAction } from '@/actions/ideas'
|
||||
import type { IdeaDto } from '@/lib/idea-dto'
|
||||
|
||||
|
|
@ -27,7 +28,7 @@ export function IdeaPbiLinkCard({ idea, isDemo }: Props) {
|
|||
|
||||
if (idea.pbi && idea.product_id) {
|
||||
return (
|
||||
<div className="rounded-md border border-status-done/30 bg-status-done/10 p-4 flex items-center gap-3">
|
||||
<div className="rounded-md border border-status-done/30 bg-status-done/10 p-4 flex items-center gap-3" {...debugProps('idea-pbi-link-card', 'IdeaPbiLinkCard', 'components/ideas/idea-pbi-link-card.tsx')}>
|
||||
<div className="flex-1">
|
||||
<p className="text-xs uppercase tracking-wide text-status-done font-medium">
|
||||
Gepland
|
||||
|
|
@ -62,7 +63,7 @@ export function IdeaPbiLinkCard({ idea, isDemo }: Props) {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="rounded-md border border-status-blocked/30 bg-status-blocked/10 p-4 space-y-2">
|
||||
<div className="rounded-md border border-status-blocked/30 bg-status-blocked/10 p-4 space-y-2" {...debugProps('idea-pbi-link-card', 'IdeaPbiLinkCard', 'components/ideas/idea-pbi-link-card.tsx')}>
|
||||
<div className="flex items-center gap-2">
|
||||
<Link2Off className="size-4 text-status-blocked" />
|
||||
<p className="text-sm font-medium text-status-blocked">
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import {
|
|||
} from '@/components/ui/tooltip'
|
||||
import { DemoTooltip } from '@/components/shared/demo-tooltip'
|
||||
import { useSoloStore } from '@/stores/solo-store'
|
||||
import { debugProps } from '@/lib/debug'
|
||||
import {
|
||||
startGrillJobAction,
|
||||
startMakePlanJobAction,
|
||||
|
|
@ -134,7 +135,7 @@ export function IdeaRowActions({ idea, isDemo, onArchive }: IdeaRowActionsProps)
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-1">
|
||||
<div className="flex items-center gap-1" {...debugProps('idea-row-actions', 'IdeaRowActions', 'components/ideas/idea-row-actions.tsx')}>
|
||||
{/* Bekijk PBI — alleen zichtbaar in PLANNED */}
|
||||
{status === 'planned' && idea.pbi && idea.product_id && (
|
||||
<Button
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import { Badge } from '@/components/ui/badge'
|
|||
import { StoryLog } from '@/components/shared/story-log'
|
||||
import { JOB_STATUS_LABELS, JOB_STATUS_COLORS } from '@/components/shared/job-status'
|
||||
import type { ClaudeJobStatusApi } from '@/lib/job-status'
|
||||
import { debugProps } from '@/lib/debug'
|
||||
import type { IdeaSyncData } from '@/app/(app)/ideas/[id]/sync-tab-server'
|
||||
|
||||
interface Props {
|
||||
|
|
@ -88,7 +89,7 @@ export function IdeaSyncTab({ data }: Props) {
|
|||
if (!pbi) return null
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-4" {...debugProps('idea-sync-tab', 'IdeaSyncTab', 'components/ideas/idea-sync-tab.tsx')}>
|
||||
{/* Header: PBI-link + PR-status */}
|
||||
<div className="flex flex-wrap items-center gap-3 rounded-md border border-border bg-surface-container p-3">
|
||||
<a
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import { toast } from 'sonner'
|
|||
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Textarea } from '@/components/ui/textarea'
|
||||
import { debugProps } from '@/lib/debug'
|
||||
import { answerQuestion } from '@/actions/questions'
|
||||
import { UserChatInput } from '@/components/ideas/user-chat-input'
|
||||
|
||||
|
|
@ -124,7 +125,7 @@ export function IdeaTimeline({
|
|||
const showChatInput = planMd !== null
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-4" {...debugProps('idea-timeline', 'IdeaTimeline', 'components/ideas/idea-timeline.tsx')}>
|
||||
{merged.length === 0 ? (
|
||||
<p className="text-sm text-muted-foreground py-8 text-center italic">
|
||||
Nog geen activiteit op dit idee.
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { toast } from 'sonner'
|
|||
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Textarea } from '@/components/ui/textarea'
|
||||
import { debugProps } from '@/lib/debug'
|
||||
import { createUserQuestionAction } from '@/actions/user-questions'
|
||||
|
||||
interface Props {
|
||||
|
|
@ -39,7 +40,7 @@ export function UserChatInput({ ideaId, isDemo = false }: Props) {
|
|||
|
||||
if (isDemo) {
|
||||
return (
|
||||
<div className="rounded-md border border-input bg-surface-container p-3">
|
||||
<div className="rounded-md border border-input bg-surface-container p-3" {...debugProps('user-chat-input', 'UserChatInput', 'components/ideas/user-chat-input.tsx')}>
|
||||
<p className="text-xs text-muted-foreground italic">
|
||||
Demo-modus: vragen stellen is niet beschikbaar.
|
||||
</p>
|
||||
|
|
@ -48,7 +49,7 @@ export function UserChatInput({ ideaId, isDemo = false }: Props) {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-2 rounded-md border border-input bg-surface-container p-3">
|
||||
<div className="space-y-2 rounded-md border border-input bg-surface-container p-3" {...debugProps('user-chat-input', 'UserChatInput', 'components/ideas/user-chat-input.tsx')}>
|
||||
<label className="text-xs font-medium text-muted-foreground">
|
||||
Stel een vraag over dit plan
|
||||
</label>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
'use client'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
import { debugProps } from '@/lib/debug'
|
||||
import { JOB_STATUS_LABELS, JOB_STATUS_COLORS } from '@/components/shared/job-status'
|
||||
import { jobStatusToApi } from '@/lib/job-status'
|
||||
import type { ClaudeJobKind, ClaudeJobStatus } from '@prisma/client'
|
||||
|
|
@ -61,6 +62,7 @@ export default function JobCard({
|
|||
'border rounded-lg p-3 cursor-pointer hover:bg-surface-container transition-colors text-sm',
|
||||
isSelected && 'ring-2 ring-primary',
|
||||
)}
|
||||
{...debugProps('job-card', 'JobCard', 'components/jobs/job-card.tsx')}
|
||||
>
|
||||
<div className="flex justify-between items-center gap-2">
|
||||
<span className="text-[10px] px-1.5 py-0.5 rounded border bg-muted text-muted-foreground font-mono">
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { JOB_STATUS_LABELS, JOB_STATUS_COLORS } from '@/components/shared/job-st
|
|||
import { jobStatusToApi } from '@/lib/job-status'
|
||||
import type { JobWithRelations } from '@/actions/jobs-page'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { debugProps } from '@/lib/debug'
|
||||
import { DemoTooltip } from '@/components/shared/demo-tooltip'
|
||||
import { restartClaudeJobAction } from '@/actions/claude-jobs'
|
||||
|
||||
|
|
@ -57,7 +58,7 @@ export default function JobDetailPane({ job, isDemo }: JobDetailPaneProps) {
|
|||
|
||||
if (!job) {
|
||||
return (
|
||||
<div className="flex items-center justify-center h-full text-sm text-muted-foreground">
|
||||
<div className="flex items-center justify-center h-full text-sm text-muted-foreground" {...debugProps('job-detail-pane', 'JobDetailPane', 'components/jobs/job-detail-pane.tsx')}>
|
||||
Selecteer een job om details te zien
|
||||
</div>
|
||||
)
|
||||
|
|
@ -75,7 +76,7 @@ export default function JobDetailPane({ job, isDemo }: JobDetailPaneProps) {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="overflow-y-auto h-full p-4">
|
||||
<div className="overflow-y-auto h-full p-4" {...debugProps('job-detail-pane', 'JobDetailPane', 'components/jobs/job-detail-pane.tsx')}>
|
||||
<FieldRow label="Status">
|
||||
<span className={cn('text-xs px-2 py-0.5 rounded-full border font-medium', JOB_STATUS_COLORS[apiStatus])}>
|
||||
{JOB_STATUS_LABELS[apiStatus]}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
'use client'
|
||||
|
||||
import { debugProps } from '@/lib/debug'
|
||||
import type { JobWithRelations } from '@/actions/jobs-page'
|
||||
|
||||
interface FieldRowProps {
|
||||
|
|
@ -42,7 +43,7 @@ interface JobUsagePaneProps {
|
|||
export default function JobUsagePane({ job }: JobUsagePaneProps) {
|
||||
if (!job) {
|
||||
return (
|
||||
<div className="flex items-center justify-center h-full text-sm text-muted-foreground">
|
||||
<div className="flex items-center justify-center h-full text-sm text-muted-foreground" {...debugProps('job-usage-pane', 'JobUsagePane', 'components/jobs/job-usage-pane.tsx')}>
|
||||
Selecteer een job om gebruik te zien
|
||||
</div>
|
||||
)
|
||||
|
|
@ -57,7 +58,7 @@ export default function JobUsagePane({ job }: JobUsagePaneProps) {
|
|||
const costLabel = job.costUsd != null ? `$${job.costUsd.toFixed(4)}` : '—'
|
||||
|
||||
return (
|
||||
<div className="overflow-y-auto h-full p-4">
|
||||
<div className="overflow-y-auto h-full p-4" {...debugProps('job-usage-pane', 'JobUsagePane', 'components/jobs/job-usage-pane.tsx')}>
|
||||
<FieldRow label="Model">{job.modelId ?? '—'}</FieldRow>
|
||||
<FieldRow label="Tokens invoer">{formatNumber(job.inputTokens)}</FieldRow>
|
||||
<FieldRow label="Tokens uitvoer">{formatNumber(job.outputTokens)}</FieldRow>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import JobsColumn from './jobs-column'
|
|||
import JobDetailPane from './job-detail-pane'
|
||||
import JobUsagePane from './job-usage-pane'
|
||||
import SprintSubTasksPane from './sprint-sub-tasks-pane'
|
||||
import { debugProps } from '@/lib/debug'
|
||||
import { useJobsStore } from '@/stores/jobs-store'
|
||||
import useJobsRealtime from '@/hooks/use-jobs-realtime'
|
||||
import type { ClaudeJobStatusApi } from '@/lib/job-status'
|
||||
|
|
@ -96,11 +97,13 @@ export default function JobsBoard({ initialActiveJobs, initialDoneJobs, isDemo }
|
|||
)
|
||||
|
||||
return (
|
||||
<SplitPane
|
||||
panes={[leftPane, middlePane, rightPane]}
|
||||
defaultSplit={[25, 50, 25]}
|
||||
cookieKey="jobs"
|
||||
tabLabels={['Actief', 'Details', 'Klaar']}
|
||||
/>
|
||||
<div className="h-full" {...debugProps('jobs-board', 'JobsBoard', 'components/jobs/jobs-board.tsx')}>
|
||||
<SplitPane
|
||||
panes={[leftPane, middlePane, rightPane]}
|
||||
defaultSplit={[25, 50, 25]}
|
||||
cookieKey="jobs"
|
||||
tabLabels={['Actief', 'Details', 'Klaar']}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import JobCard from './job-card'
|
|||
import { JOB_STATUS_LABELS } from '@/components/shared/job-status'
|
||||
import { jobStatusToApi, type ClaudeJobStatusApi } from '@/lib/job-status'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { debugProps } from '@/lib/debug'
|
||||
import type { JobWithRelations } from '@/actions/jobs-page'
|
||||
import type { ClaudeJobKind } from '@prisma/client'
|
||||
|
||||
|
|
@ -170,7 +171,7 @@ export default function JobsColumn({
|
|||
const activeFilterCount = filterKinds.size + filterStatuses.size
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-full">
|
||||
<div className="flex flex-col h-full" {...debugProps('jobs-column', 'JobsColumn', 'components/jobs/jobs-column.tsx')}>
|
||||
<div className="flex items-center justify-between gap-2 px-2 py-1.5 border-b border-border bg-surface-container-low shrink-0">
|
||||
<span className="text-xs font-medium text-muted-foreground px-1">{title}</span>
|
||||
<div className="flex items-center gap-1.5 flex-wrap justify-end">
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import { useEffect, useState } from 'react'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { debugProps } from '@/lib/debug'
|
||||
import { JOB_STATUS_LABELS, JOB_STATUS_COLORS } from '@/components/shared/job-status'
|
||||
import type { ClaudeJobStatusApi } from '@/lib/job-status'
|
||||
|
||||
|
|
@ -63,5 +64,9 @@ function SubTaskList({ jobId }: { jobId: string }) {
|
|||
|
||||
export default function SprintSubTasksPane({ jobId, isSprintJob }: SprintSubTasksPaneProps) {
|
||||
if (!isSprintJob || !jobId) return null
|
||||
return <SubTaskList key={jobId} jobId={jobId} />
|
||||
return (
|
||||
<div {...debugProps('sprint-sub-tasks-pane', 'SprintSubTasksPane', 'components/jobs/sprint-sub-tasks-pane.tsx')}>
|
||||
<SubTaskList key={jobId} jobId={jobId} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue