File size: 7,236 Bytes
6a059d3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
import React, { useMemo } from "react"
import ReactDiffViewer, { DiffMethod } from "react-diff-viewer-continued"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Badge } from "@/components/ui/badge"
import { GitCompare, ArrowRight } from "lucide-react"
import { GithubDiff } from "./types"

interface LegalDiffViewerProps {
  diff: GithubDiff
  className?: string
}

export function LegalDiffViewer({ diff, className }: LegalDiffViewerProps) {
  // Calculate percentage/number change for the badge
  const changeBadge = useMemo(() => {
    try {
      // Extract numbers from old and new text
      const oldNumbers = diff.old_text.match(/(\d+(\.\d+)?)/g)?.map(Number) || []
      const newNumbers = diff.new_text.match(/(\d+(\.\d+)?)/g)?.map(Number) || []

      // Simple heuristic: if we find one number in each that changed
      if (oldNumbers.length === 1 && newNumbers.length === 1) {
        const oldVal = oldNumbers[0]
        const newVal = newNumbers[0]
        
        if (oldVal !== newVal) {
          const percentChange = ((newVal - oldVal) / oldVal) * 100
          const isIncrease = newVal > oldVal
          
          return {
            text: `${isIncrease ? "+" : ""}${percentChange.toFixed(1)}% ${isIncrease ? "Increase" : "Decrease"}`,
            variant: isIncrease ? "destructive" : "default" as "default" | "destructive" | "outline" | "secondary",
            color: isIncrease ? "bg-red-600" : "bg-green-600" // Higher taxes (increase) usually bad/red, lower good/green? Or just standard diff colors?
            // Let's stick to standard: Green = Increase, Red = Decrease for numbers usually, 
            // BUT for taxes: Increase = Bad (Red), Decrease = Good (Green).
            // Let's just use neutral or standard diff colors to avoid bias.
            // For the badge, let's just show the change.
          }
        }
      }
      
      // Check for specific keywords like "increased from X to Y"
      // This is handled by the diff view itself visually, but a badge is nice.
      return null
    } catch (e) {
      return null
    }
  }, [diff.old_text, diff.new_text])

  // Custom styles for react-diff-viewer-2 to match Kenyan flag theme
  // Red (#B91C1C) for deleted, Green (#16A34A) for added
  const newStyles = {
    variables: {
      light: {
        diffViewerBackground: "transparent",
        diffViewerColor: "currentColor",
        addedBackground: "rgba(22, 163, 74, 0.2)", // Green #16A34A
        addedColor: "currentColor",
        removedBackground: "rgba(185, 28, 28, 0.2)", // Red #B91C1C
        removedColor: "currentColor",
        wordAddedBackground: "rgba(22, 163, 74, 0.4)",
        wordRemovedBackground: "rgba(185, 28, 28, 0.4)",
        addedGutterBackground: "rgba(22, 163, 74, 0.1)",
        removedGutterBackground: "rgba(185, 28, 28, 0.1)",
        gutterBackground: "transparent",
        gutterBackgroundDark: "transparent",
        highlightBackground: "rgba(255, 255, 255, 0.1)",
        highlightGutterBackground: "rgba(255, 255, 255, 0.1)",
        codeFoldGutterBackground: "transparent",
        codeFoldBackground: "transparent",
        emptyLineBackground: "transparent",
        gutterColor: "currentColor",
        addedGutterColor: "currentColor",
        removedGutterColor: "currentColor",
        codeFoldContentColor: "currentColor",
        diffViewerTitleBackground: "transparent",
        diffViewerTitleColor: "currentColor",
        diffViewerTitleBorderColor: "transparent",
      },
      dark: {
        diffViewerBackground: "transparent",
        diffViewerColor: "currentColor",
        addedBackground: "rgba(22, 163, 74, 0.2)", // Green
        addedColor: "currentColor",
        removedBackground: "rgba(185, 28, 28, 0.2)", // Red
        removedColor: "currentColor",
        wordAddedBackground: "rgba(22, 163, 74, 0.4)",
        wordRemovedBackground: "rgba(185, 28, 28, 0.4)",
        addedGutterBackground: "rgba(22, 163, 74, 0.1)",
        removedGutterBackground: "rgba(185, 28, 28, 0.1)",
        gutterBackground: "transparent",
        gutterBackgroundDark: "transparent",
        highlightBackground: "rgba(255, 255, 255, 0.1)",
        highlightGutterBackground: "rgba(255, 255, 255, 0.1)",
        codeFoldGutterBackground: "transparent",
        codeFoldBackground: "transparent",
        emptyLineBackground: "transparent",
        gutterColor: "currentColor",
        addedGutterColor: "currentColor",
        removedGutterColor: "currentColor",
        codeFoldContentColor: "currentColor",
        diffViewerTitleBackground: "transparent",
        diffViewerTitleColor: "currentColor",
        diffViewerTitleBorderColor: "transparent",
      }
    },
    line: {
      padding: '10px 2px',
      '&:hover': {
        background: 'rgba(255, 255, 255, 0.05)',
      },
    },
    content: {
        fontFamily: 'inherit',
        fontSize: '0.9rem',
    }
  }

  return (
    <Card className={`w-full overflow-hidden border-primary/20 bg-card/50 backdrop-blur-sm ${className}`}>

      <CardHeader className="pb-2 border-b border-border/50 bg-muted/30">

        <div className="flex items-center justify-between">

          <div className="flex items-center gap-2">

            <div className="p-2 rounded-lg bg-primary/10 text-primary">

              <GitCompare className="w-5 h-5" />

            </div>

            <div>

              <CardTitle className="text-base font-bold text-primary flex items-center gap-2">

                {diff.title}

              </CardTitle>

            </div>

          </div>

          {changeBadge && (

            <Badge variant={changeBadge.variant} className={`${changeBadge.color} text-white border-0`}>

              {changeBadge.text}

            </Badge>

          )}

        </div>

      </CardHeader>

      <CardContent className="p-0 overflow-x-auto">

        <div className="min-w-[500px] text-sm">

            {/* We force dark mode styles if the app is in dark mode, but react-diff-viewer-2 

                uses a 'useDarkTheme' prop. We can try to detect or just pass true/false.

                For now, let's assume the app handles theme via class 'dark'. 

                Since we can't easily detect system preference here without hooks, 

                we'll rely on the parent passing a theme or default to light/dark based on CSS variables.

                Actually, react-diff-viewer-2 styles object handles both light and dark keys, 

                but we need to tell it which one to use.

            */}

            <ReactDiffViewer

              oldValue={diff.old_text}

              newValue={diff.new_text}

              splitView={diff.highlight_type === "side_by_side"}

              compareMethod={DiffMethod.WORDS}

              styles={newStyles}

              useDarkTheme={true} // Force dark theme styles for now as they look better in both modes with our transparent bg

              leftTitle="Original Text"

              rightTitle="Amended Text"

            />

        </div>

      </CardContent>

    </Card>
  )
}