File size: 3,188 Bytes
d47b053
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import type { StudioWorkResult } from '../protocol/studio-agent-types'
import type { StudioReviewViewModel } from '../store/studio-selectors'
import { studioPanelClass } from '../theme'
import { StudioReviewFindingList } from './StudioReviewFindingList'
import { useI18n } from '../../i18n'

interface StudioReviewPanelProps {
  result: StudioWorkResult | null
  review: StudioReviewViewModel | null
}

export function StudioReviewPanel({ result, review }: StudioReviewPanelProps) {
  const { t } = useI18n()
  if (!result || !review) {
    return (
      <section className={studioPanelClass('p-4')}>
        <div className="text-xs uppercase tracking-[0.28em] text-text-secondary">{t('studio.review.title')}</div>
        <div className="mt-3 text-sm text-text-secondary">{t('studio.review.empty')}</div>
      </section>
    )
  }

  return (
    <section className={studioPanelClass('p-4')}>
      <div className="text-xs uppercase tracking-[0.28em] text-text-secondary">{t('studio.review.title')}</div>
      <h3 className="mt-2 text-lg font-semibold text-text-primary">{result.summary}</h3>
      {(review.sourceLabel || review.path) && (
        <div className="mt-2 text-xs text-text-secondary">
          {review.sourceLabel ?? review.path}
        </div>
      )}

      <div className="mt-4 grid gap-4 xl:grid-cols-[1.1fr_0.9fr]">
        <div>
          <div className="mb-2 text-sm font-medium text-text-primary">{t('studio.review.findings')}</div>
          <StudioReviewFindingList findings={review.findings} />
        </div>

        <div className="space-y-4">
          <div className="rounded-2xl border border-black/10 bg-black/5 p-3 dark:border-white/10 dark:bg-white/5">
            <div className="text-sm font-medium text-text-primary">{t('studio.review.summary')}</div>
            <div className="mt-2 text-sm text-text-secondary">{review.summary ?? t('studio.review.noSummary')}</div>
          </div>

          {review.changeSet && (
            <div className="rounded-2xl border border-black/10 bg-black/5 p-3 dark:border-white/10 dark:bg-white/5">
              <div className="text-sm font-medium text-text-primary">{t('studio.review.changeSet')}</div>
              <div className="mt-2 space-y-3 text-xs text-text-secondary">
                {review.changeSet.before && <CodeBlock title={t('studio.review.before')} content={review.changeSet.before} />}
                {review.changeSet.after && <CodeBlock title={t('studio.review.after')} content={review.changeSet.after} />}
                {review.changeSet.diff && <CodeBlock title={t('studio.review.diff')} content={review.changeSet.diff} />}
              </div>
            </div>
          )}

          {review.report && <CodeBlock title={t('studio.review.rawReport')} content={review.report} />}
        </div>
      </div>
    </section>
  )
}

function CodeBlock({ title, content }: { title: string; content: string }) {
  return (
    <div>
      <div className="mb-1 text-xs uppercase tracking-[0.2em] text-text-secondary">{title}</div>
      <pre className="overflow-auto rounded-2xl bg-white/70 p-3 text-xs leading-6 text-text-primary dark:bg-black/20">{content}</pre>
    </div>
  )
}