1
1
import React , { useMemo } from "react" ;
2
2
import styled , { useTheme } from "styled-components" ;
3
3
4
- import Skeleton from "react-loading-skeleton" ;
5
4
import { useParams } from "react-router-dom" ;
6
5
7
6
import { _TimelineItem1 , CustomTimeline } from "@kleros/ui-components-library" ;
8
7
9
- import CalendarIcon from "svgs/icons/calendar.svg" ;
10
8
import ClosedCaseIcon from "svgs/icons/check-circle-outline.svg" ;
11
9
import NewTabIcon from "svgs/icons/new-tab.svg" ;
10
+ import GavelExecutedIcon from "svgs/icons/gavel-executed.svg" ;
12
11
13
12
import { Periods } from "consts/periods" ;
14
13
import { usePopulatedDisputeData } from "hooks/queries/usePopulatedDisputeData" ;
@@ -21,8 +20,6 @@ import { useVotingHistory } from "queries/useVotingHistory";
21
20
import { ClassicRound } from "src/graphql/graphql" ;
22
21
import { getTxnExplorerLink } from "src/utils" ;
23
22
24
- import { responsiveSize } from "styles/responsiveSize" ;
25
-
26
23
import { StyledClosedCircle } from "components/StyledIcons/ClosedCircleIcon" ;
27
24
28
25
import { ExternalLink } from "../ExternalLink" ;
@@ -37,24 +34,6 @@ const StyledTimeline = styled(CustomTimeline)`
37
34
width: 100%;
38
35
` ;
39
36
40
- const EnforcementContainer = styled . div `
41
- display: flex;
42
- gap: 8px;
43
- margin-top: ${ responsiveSize ( 12 , 24 ) } ;
44
- fill: ${ ( { theme } ) => theme . secondaryText } ;
45
-
46
- small {
47
- font-weight: 400;
48
- line-height: 19px;
49
- color: ${ ( { theme } ) => theme . secondaryText } ;
50
- }
51
- ` ;
52
-
53
- const StyledCalendarIcon = styled ( CalendarIcon ) `
54
- width: 14px;
55
- height: 14px;
56
- ` ;
57
-
58
37
const StyledNewTabIcon = styled ( NewTabIcon ) `
59
38
margin-bottom: 2px;
60
39
path {
@@ -84,73 +63,95 @@ const useItems = (disputeDetails?: DisputeDetailsQuery, arbitrable?: `0x${string
84
63
const localRounds : ClassicRound [ ] = getLocalRounds ( votingHistory ?. dispute ?. disputeKitDispute ) as ClassicRound [ ] ;
85
64
const rounds = votingHistory ?. dispute ?. rounds ;
86
65
const theme = useTheme ( ) ;
87
- const txnExplorerLink = useMemo ( ( ) => {
66
+ const txnDisputeCreatedLink = useMemo ( ( ) => {
88
67
return getTxnExplorerLink ( votingHistory ?. dispute ?. transactionHash ?? "" ) ;
89
68
} , [ votingHistory ] ) ;
69
+ const txnEnforcementLink = useMemo ( ( ) => {
70
+ return getTxnExplorerLink ( disputeDetails ?. dispute ?. rulingTransactionHash ?? "" ) ;
71
+ } , [ disputeDetails ] ) ;
90
72
91
73
return useMemo < TimelineItems | undefined > ( ( ) => {
92
74
const dispute = disputeDetails ?. dispute ;
93
- if ( dispute ) {
94
- const rulingOverride = dispute . overridden ;
95
- const currentPeriodIndex = Periods [ dispute . period ] ;
96
-
97
- return localRounds ?. reduce < TimelineItems > (
98
- ( acc , { winningChoice } , index ) => {
99
- const isOngoing = index === localRounds . length - 1 && currentPeriodIndex < 3 ;
100
- const roundTimeline = rounds ?. [ index ] . timeline ;
101
-
102
- const icon = dispute . ruled && ! rulingOverride && index === localRounds . length - 1 ? ClosedCaseIcon : "" ;
103
- const answers = disputeData ?. answers ;
104
- acc . push ( {
105
- title : `Jury Decision - Round ${ index + 1 } ` ,
106
- party : isOngoing ? "Voting is ongoing" : getVoteChoice ( winningChoice , answers ) ,
107
- subtitle : isOngoing
108
- ? ""
109
- : `${ formatDate ( roundTimeline ?. [ Periods . vote ] ) } / ${
110
- votingHistory ?. dispute ?. rounds . at ( index ) ?. court . name
111
- } `,
112
- rightSided : true ,
113
- variant : theme . secondaryPurple ,
114
- Icon : icon !== "" ? icon : undefined ,
115
- } ) ;
116
-
117
- if ( index < localRounds . length - 1 ) {
118
- acc . push ( {
119
- title : "Appealed" ,
120
- party : "" ,
121
- subtitle : formatDate ( roundTimeline ?. [ Periods . appeal ] ) ,
122
- rightSided : true ,
123
- Icon : StyledClosedCircle ,
124
- } ) ;
125
- } else if ( rulingOverride && dispute . currentRuling !== winningChoice ) {
126
- acc . push ( {
127
- title : "Won by Appeal" ,
128
- party : getVoteChoice ( dispute . currentRuling , answers ) ,
129
- subtitle : formatDate ( roundTimeline ?. [ Periods . appeal ] ) ,
130
- rightSided : true ,
131
- Icon : ClosedCaseIcon ,
132
- } ) ;
133
- }
134
-
135
- return acc ;
136
- } ,
137
- [
138
- {
139
- title : "Dispute created" ,
140
- party : (
141
- < ExternalLink to = { txnExplorerLink } rel = "noopener noreferrer" target = "_blank" >
142
- < StyledNewTabIcon />
143
- </ ExternalLink >
144
- ) ,
145
- subtitle : formatDate ( votingHistory ?. dispute ?. createdAt ) ,
146
- rightSided : true ,
147
- variant : theme . secondaryPurple ,
148
- } ,
149
- ]
150
- ) ;
75
+ if ( ! dispute ) return ;
76
+
77
+ const rulingOverride = dispute . overridden ;
78
+ const currentPeriodIndex = Periods [ dispute . period ] ;
79
+
80
+ const base : TimelineItems = [
81
+ {
82
+ title : "Dispute created" ,
83
+ party : (
84
+ < ExternalLink to = { txnDisputeCreatedLink } rel = "noopener noreferrer" target = "_blank" >
85
+ < StyledNewTabIcon />
86
+ </ ExternalLink >
87
+ ) ,
88
+ subtitle : formatDate ( votingHistory ?. dispute ?. createdAt ) ,
89
+ rightSided : true ,
90
+ variant : theme . secondaryPurple ,
91
+ } ,
92
+ ] ;
93
+
94
+ const items = localRounds ?. reduce < _TimelineItem1 [ ] > ( ( acc , { winningChoice } , index ) => {
95
+ const isOngoing = index === localRounds . length - 1 && currentPeriodIndex < 3 ;
96
+ const roundTimeline = rounds ?. [ index ] . timeline ;
97
+ const icon = dispute . ruled && ! rulingOverride && index === localRounds . length - 1 ? ClosedCaseIcon : undefined ;
98
+ const answers = disputeData ?. answers ;
99
+
100
+ acc . push ( {
101
+ title : `Jury Decision - Round ${ index + 1 } ` ,
102
+ party : isOngoing ? "Voting is ongoing" : getVoteChoice ( winningChoice , answers ) ,
103
+ subtitle : isOngoing ? "" : `${ formatDate ( roundTimeline ?. [ Periods . vote ] ) } / ${ rounds ?. [ index ] ?. court . name } ` ,
104
+ rightSided : true ,
105
+ variant : theme . secondaryPurple ,
106
+ Icon : icon ,
107
+ } ) ;
108
+
109
+ if ( index < localRounds . length - 1 ) {
110
+ acc . push ( {
111
+ title : "Appealed" ,
112
+ party : "" ,
113
+ subtitle : formatDate ( roundTimeline ?. [ Periods . appeal ] ) ,
114
+ rightSided : true ,
115
+ Icon : StyledClosedCircle ,
116
+ } ) ;
117
+ } else if ( rulingOverride && dispute . currentRuling !== winningChoice ) {
118
+ acc . push ( {
119
+ title : "Won by Appeal" ,
120
+ party : getVoteChoice ( dispute . currentRuling , answers ) ,
121
+ subtitle : formatDate ( roundTimeline ?. [ Periods . appeal ] ) ,
122
+ rightSided : true ,
123
+ Icon : ClosedCaseIcon ,
124
+ } ) ;
125
+ }
126
+
127
+ return acc ;
128
+ } , [ ] ) ;
129
+
130
+ if ( dispute . ruled ) {
131
+ items . push ( {
132
+ title : "Enforcement" ,
133
+ party : (
134
+ < ExternalLink to = { txnEnforcementLink } rel = "noopener noreferrer" target = "_blank" >
135
+ < StyledNewTabIcon />
136
+ </ ExternalLink >
137
+ ) ,
138
+ subtitle : `${ formatDate ( dispute . rulingTimestamp ) } / ${ rounds ?. at ( - 1 ) ?. court . name } ` ,
139
+ rightSided : true ,
140
+ Icon : GavelExecutedIcon ,
141
+ } ) ;
151
142
}
152
- return ;
153
- } , [ disputeDetails , disputeData , localRounds , theme , rounds , votingHistory , txnExplorerLink ] ) ;
143
+
144
+ return [ ...base , ...items ] as TimelineItems ;
145
+ } , [
146
+ disputeDetails ,
147
+ disputeData ,
148
+ localRounds ,
149
+ theme ,
150
+ rounds ,
151
+ votingHistory ,
152
+ txnDisputeCreatedLink ,
153
+ txnEnforcementLink ,
154
+ ] ) ;
154
155
} ;
155
156
156
157
interface IDisputeTimeline {
@@ -160,33 +161,8 @@ interface IDisputeTimeline {
160
161
const DisputeTimeline : React . FC < IDisputeTimeline > = ( { arbitrable } ) => {
161
162
const { id } = useParams ( ) ;
162
163
const { data : disputeDetails } = useDisputeDetailsQuery ( id ) ;
163
- const { data : votingHistory } = useVotingHistory ( id ) ;
164
164
const items = useItems ( disputeDetails , arbitrable ) ;
165
165
166
- const transactionExplorerLink = useMemo ( ( ) => {
167
- return getTxnExplorerLink ( disputeDetails ?. dispute ?. rulingTransactionHash ?? "" ) ;
168
- } , [ disputeDetails ] ) ;
169
-
170
- return (
171
- < Container >
172
- { items && < StyledTimeline { ...{ items } } /> }
173
- { disputeDetails ?. dispute ?. ruled && (
174
- < EnforcementContainer >
175
- < StyledCalendarIcon />
176
- < small >
177
- Enforcement:{ " " }
178
- { disputeDetails . dispute . rulingTimestamp ? (
179
- < ExternalLink to = { transactionExplorerLink } rel = "noopener noreferrer" target = "_blank" >
180
- { formatDate ( disputeDetails . dispute . rulingTimestamp ) }
181
- </ ExternalLink >
182
- ) : (
183
- < Skeleton height = { 16 } width = { 56 } />
184
- ) } { " " }
185
- / { votingHistory ?. dispute ?. rounds . at ( - 1 ) ?. court . name }
186
- </ small >
187
- </ EnforcementContainer >
188
- ) }
189
- </ Container >
190
- ) ;
166
+ return < Container > { items && < StyledTimeline { ...{ items } } /> } </ Container > ;
191
167
} ;
192
168
export default DisputeTimeline ;
0 commit comments