@@ -19,15 +19,43 @@ import { IncreaseOperatorFeeStatusBadge } from "@/components/operator/increase-o
1919import { OperatorValidatorsList } from "@/components/operator/operator-validators-list" ;
2020import { OperatorStatusBadge } from "@/components/operator/operator-status-badge" ;
2121import { useOperatorEarningsAndFees } from "@/hooks/operator/use-operator-earnings-and-fees" ;
22+ import { Skeleton } from "@/components/ui/skeleton" ;
23+
24+ const AmountSkeleton : FC < { "data-testid" ?: string } > = ( props ) => (
25+ < div className = "flex flex-col gap-2" { ...props } >
26+ < Skeleton className = "h-7 w-32" />
27+ < Skeleton className = "h-4 w-16" />
28+ </ div >
29+ ) ;
30+
31+ const AmountUnavailable : FC < { "data-testid" ?: string } > = ( props ) => (
32+ < div className = "flex flex-col items-start gap-2" { ...props } >
33+ < Text variant = "body-2-medium" className = "text-error-500" >
34+ Couldn't read this value from the network.
35+ </ Text >
36+ < Text variant = "body-3-medium" className = "text-gray-500" >
37+ It will appear once the connection recovers.
38+ </ Text >
39+ </ div >
40+ ) ;
2241
2342export const Operator : FC < ComponentPropsWithoutRef < "div" > > = ( { ...props } ) => {
2443 const params = useOperatorPageParams ( ) ;
2544 const operatorId = BigInt ( params . operatorId ! ) ;
2645 const operator = useOperator ( operatorId ! ) ;
27- const { feeEth, yearlyFeeEth, yearlyFeeSSV, balanceEth, balanceSSV } =
28- useOperatorEarningsAndFees ( operatorId ) ;
46+ const {
47+ feeEth,
48+ yearlyFeeEth,
49+ yearlyFeeSSV,
50+ balanceEth,
51+ balanceSSV,
52+ earningsStatus,
53+ feesStatus,
54+ } = useOperatorEarningsAndFees ( operatorId ) ;
2955
30- const hasBalance = balanceEth > 0n || balanceSSV > 0n ;
56+ const hasBalance =
57+ earningsStatus . isSuccess && ( balanceEth > 0n || balanceSSV > 0n ) ;
58+ const canUpdateFee = feesStatus . isSuccess && feeEth . data !== 0n ;
3159
3260 if ( ! operator . data ) return null ;
3361
@@ -111,31 +139,48 @@ export const Operator: FC<ComponentPropsWithoutRef<"div">> = ({ ...props }) => {
111139 </ div >
112140 < Container variant = "horizontal" size = "xl" { ...props } className = "h-full" >
113141 < div className = "flex items-stretch gap-6 flex-col flex-1" >
114- < Card data-testid = "dashboard-operator-balance-card" className = "w-full" >
142+ < Card
143+ data-testid = "dashboard-operator-balance-card"
144+ className = "w-full"
145+ >
115146 < Text
116147 data-testid = "dashboard-operator-balance-label"
117148 variant = "headline4"
118149 className = "text-gray-500"
119150 >
120151 Balance
121152 </ Text >
122- < div className = "flex flex-col gap-4" >
123- < BalanceDisplay
124- data-testid = "dashboard-operator-balance-eth"
125- amount = { balanceEth }
126- token = "ETH"
127- />
128- { yearlyFeeSSV !== 0n && ! operator . data . migrated && (
153+ { earningsStatus . isUnavailable ? (
154+ < AmountUnavailable data-testid = "dashboard-operator-balance-error" />
155+ ) : earningsStatus . isPending ? (
156+ < AmountSkeleton data-testid = "dashboard-operator-balance-loading" />
157+ ) : (
158+ < div className = "flex flex-col gap-4" >
129159 < BalanceDisplay
130- data-testid = "dashboard-operator-balance-ssv "
131- amount = { balanceSSV }
132- token = "SSV "
160+ data-testid = "dashboard-operator-balance-eth "
161+ amount = { balanceEth }
162+ token = "ETH "
133163 />
134- ) }
135- </ div >
164+ { yearlyFeeSSV !== 0n && ! operator . data . migrated && (
165+ < BalanceDisplay
166+ data-testid = "dashboard-operator-balance-ssv"
167+ amount = { balanceSSV }
168+ token = "SSV"
169+ />
170+ ) }
171+ </ div >
172+ ) }
136173 < Tooltip
137174 asChild
138- content = { ! hasBalance ? "No balance to withdraw" : undefined }
175+ content = {
176+ earningsStatus . isUnavailable
177+ ? "Balance unavailable"
178+ : earningsStatus . isPending
179+ ? "Loading balance"
180+ : ! hasBalance
181+ ? "No balance to withdraw"
182+ : undefined
183+ }
139184 >
140185 < Button
141186 data-testid = "dashboard-operator-withdraw-btn"
@@ -160,24 +205,34 @@ export const Operator: FC<ComponentPropsWithoutRef<"div">> = ({ ...props }) => {
160205 </ Text >
161206 < IncreaseOperatorFeeStatusBadge />
162207 </ div >
163- < div className = "flex flex-col gap-4" >
164- < BalanceDisplay
165- data-testid = "dashboard-operator-yearly-fee-eth"
166- amount = { yearlyFeeEth }
167- token = "ETH"
168- />
169- { yearlyFeeSSV > 0 && (
208+ { feesStatus . isUnavailable ? (
209+ < AmountUnavailable data-testid = "dashboard-operator-yearly-fee-error" />
210+ ) : feesStatus . isPending ? (
211+ < AmountSkeleton data-testid = "dashboard-operator-yearly-fee-loading" />
212+ ) : (
213+ < div className = "flex flex-col gap-4" >
170214 < BalanceDisplay
171- data-testid = "dashboard-operator-yearly-fee-ssv "
172- amount = { yearlyFeeSSV }
173- token = "SSV "
215+ data-testid = "dashboard-operator-yearly-fee-eth "
216+ amount = { yearlyFeeEth }
217+ token = "ETH "
174218 />
175- ) }
176- </ div >
219+ { yearlyFeeSSV > 0 && (
220+ < BalanceDisplay
221+ data-testid = "dashboard-operator-yearly-fee-ssv"
222+ amount = { yearlyFeeSSV }
223+ token = "SSV"
224+ />
225+ ) }
226+ </ div >
227+ ) }
177228 < Tooltip
178229 asChild
179230 content = {
180- feeEth . data === 0n ? (
231+ feesStatus . isUnavailable ? (
232+ "Fee unavailable"
233+ ) : feesStatus . isPending ? (
234+ "Loading fee"
235+ ) : feeEth . data === 0n ? (
181236 < >
182237 Operators with a fee of 0 cannot change their fee.{ " " }
183238 < Button
@@ -196,7 +251,7 @@ export const Operator: FC<ComponentPropsWithoutRef<"div">> = ({ ...props }) => {
196251 < Button
197252 data-testid = "dashboard-operator-update-fee-btn"
198253 as = { Link }
199- disabled = { feeEth . isLoading || feeEth . data === 0n }
254+ disabled = { ! canUpdateFee }
200255 to = "fee/update"
201256 variant = "secondary"
202257 size = "xl"
0 commit comments