Skip to main content

edc_web_components/components/
contract_negotiation_status.rs

1use 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}