edc_web_components/components/
contract_negotiation_status.rs1use crate::contexts::use_edc_connector_context;
2use edc_connector_client::types::contract_negotiation::{
3 ContractNegotiation, ContractNegotiationState,
4};
5use patternfly_yew::prelude::*;
6use std::time::Duration;
7use yew::platform::spawn_local;
8use yew::platform::time::sleep;
9use yew::prelude::*;
10
11const HAPPY_PATH_STATES: [(&str, ContractNegotiationState); 7] = [
12 ("Initial", ContractNegotiationState::Initial),
13 ("Requested", ContractNegotiationState::Requested),
14 ("Offered", ContractNegotiationState::Offered),
15 ("Accepted", ContractNegotiationState::Accepted),
16 ("Agreed", ContractNegotiationState::Agreed),
17 ("Verifier", ContractNegotiationState::Verified),
18 ("Finalized", ContractNegotiationState::Finalized),
19];
20
21#[derive(Clone, Debug, PartialEq, Properties)]
22pub struct ContractNegotiationStatusProps {
23 pub contract_negotiation_id: String,
24 pub on_finalized: Callback<()>,
25}
26
27#[component]
28pub fn ContractNegotiationStatus(props: &ContractNegotiationStatusProps) -> Html {
29 let edc_connector_client = use_edc_connector_context();
30
31 let contract_negotiation_state = use_state(|| None);
32
33 use_effect_with(
34 (
35 props.contract_negotiation_id.clone(),
36 edc_connector_client.clone(),
37 contract_negotiation_state.setter(),
38 props.on_finalized.clone(),
39 ),
40 |(
41 contract_negotiation_id,
42 edc_connector_client,
43 contract_negotiation_state_setter,
44 on_finalized,
45 )| {
46 let contract_negotiation_id = contract_negotiation_id.clone();
47 let edc_connector_client = edc_connector_client.clone();
48 let contract_negotiation_state_setter = contract_negotiation_state_setter.clone();
49 let on_finalized = on_finalized.clone();
50
51 spawn_local(async move {
52 loop {
53 let contract_negotiation = if let Some(client) = edc_connector_client.get_client() {
54 client
55 .contract_negotiations(edc_connector_client::EdcConnectorApiVersion::V4)
56 .get(&contract_negotiation_id)
57 .await
58 .ok()
59 } else {
60 None
61 };
62
63 let state = contract_negotiation
64 .as_ref()
65 .map(|contract_negotiation| contract_negotiation.state().clone());
66
67 contract_negotiation_state_setter.set(contract_negotiation);
68
69 if state == Some(ContractNegotiationState::Finalized) {
70 on_finalized.emit(());
71 break;
72 }
73
74 sleep(Duration::from_secs(1)).await;
75 }
76 });
77 },
78 );
79
80 if let Some(contract_negotiation) = (*contract_negotiation_state).clone() {
81 let contract_negotiation: ContractNegotiation = contract_negotiation;
82
83 let current_state_index = HAPPY_PATH_STATES
84 .iter()
85 .position(|(_, state)| state == contract_negotiation.state())
86 .unwrap_or_default();
87
88 let steps = HAPPY_PATH_STATES
89 .iter()
90 .enumerate()
91 .map(|(index, (state_label, _))| {
92 let status = if index < current_state_index {
93 ProgressStepperStepStatus::Success
94 } else if index == current_state_index {
95 if index == HAPPY_PATH_STATES.len() - 1 {
96 ProgressStepperStepStatus::Success
97 } else {
98 ProgressStepperStepStatus::Default
99 }
100 } else {
101 ProgressStepperStepStatus::Pending
102 };
103
104 html_nested!(
105 <ProgressStepperStep {status}>
106 <div>{ state_label.to_string() }</div>
107 </ProgressStepperStep>
108 )
109 });
110
111 html!(<ProgressStepper>{ for steps }</ProgressStepper>)
112 } else {
113 html!()
114 }
115}