{
  "id": "mod_nbu_exchange",
  "type": "module",
  "version": "1.0",
  "context": {
    "title": "Курс валют НБУ",
    "icon": "💱",
    "layout": "phone"
  },
  "state": {
    "currency": "EUR",
    "selectedDate": 0,
    "rates": [],
    "isLoading": true,
    "error": ""
  },
  "dependencies": [
    {
      "repository": {
        "remote": {
          "id": "nbu_exchange_api",
          "config": {
            "endPoint": "https://bank.gov.ua/NBUStatService/v1/statdirectory/exchange"
          }
        }
      }
    },
    {
      "service": {
        "audio": {
          "id": "nbu_audio"
        }
      }
    }
  ],
  "children": [
    {
      "id": "nbu_root_scroll",
      "type": "scroll",
      "style": {
        "layout": {
          "maxWidth": "infinity",
          "maxHeight": "infinity"
        },
        "scroll": {
          "dismissesKeyboard": "interactively"
        },
        "common": {
          "background": {
            "gradient": {
              "linear": {
                "colors": [
                  "#0F172A",
                  "#172033",
                  "#1E293B"
                ],
                "startPoint": "top",
                "endPoint": "bottom"
              }
            }
          }
        }
      },
      "children": [
        {
          "id": "nbu_content_stack",
          "type": "vstack",
          "context": {
            "_spacing": 20,
            "_alignment": "leading"
          },
          "style": {
            "layout": {
              "maxWidth": "infinity",
              "padding": {
                "top": 18,
                "bottom": 28,
                "leading": 18,
                "trailing": 18
              }
            }
          },
          "children": [
            {
              "id": "nbu_intro_card",
              "type": "hstack",
              "context": {
                "_spacing": 12,
                "_alignment": "center"
              },
              "style": {
                "layout": {
                  "maxWidth": "infinity",
                  "padding": 18
                },
                "common": {
                  "background": {
                    "gradient": {
                      "linear": {
                        "colors": [
                          "#166534",
                          "#15803D"
                        ],
                        "startPoint": "topLeading",
                        "endPoint": "bottomTrailing"
                      }
                    }
                  },
                  "foreground": "white",
                  "cornerRadius": 20
                },
                "shadow": {
                  "color": {
                    "color": "black",
                    "opacity": 0.22
                  },
                  "radius": 12,
                  "y": 6
                }
              },
              "children": [
                {
                  "id": "nbu_intro_icon",
                  "type": "image",
                  "context": {
                    "_source": "sf://building.columns.fill"
                  },
                  "style": {
                    "layout": {
                      "width": 36,
                      "height": 36
                    },
                    "common": {
                      "foreground": "white"
                    }
                  }
                },
                {
                  "id": "nbu_intro_text_stack",
                  "type": "vstack",
                  "context": {
                    "_spacing": 4,
                    "_alignment": "leading"
                  },
                  "style": {
                    "layout": {
                      "maxWidth": "infinity"
                    }
                  },
                  "children": [
                    {
                      "id": "nbu_intro_heading",
                      "type": "text",
                      "context": {
                        "_text": "Офіційний курс"
                      },
                      "style": {
                        "common": {
                          "font": {
                            "kind": "headline",
                            "weight": "bold"
                          },
                          "foreground": "white"
                        }
                      }
                    },
                    {
                      "id": "nbu_intro_copy",
                      "type": "text",
                      "context": {
                        "_text": "Дані надходять безпосередньо з відкритого сервісу Національного банку України."
                      },
                      "style": {
                        "common": {
                          "font": "caption",
                          "foreground": {
                            "color": "white",
                            "opacity": 0.82
                          }
                        },
                        "text": {
                          "lineSpacing": 2
                        }
                      }
                    }
                  ]
                }
              ]
            },
            {
              "id": "nbu_filters_card",
              "type": "vstack",
              "context": {
                "_spacing": 16,
                "_alignment": "leading"
              },
              "style": {
                "layout": {
                  "maxWidth": "infinity",
                  "padding": 18
                },
                "common": {
                  "background": {
                    "material": "regular"
                  },
                  "foreground": "primary",
                  "cornerRadius": 20,
                  "glass": "regular"
                },
                "shadow": {
                  "color": {
                    "color": "black",
                    "opacity": 0.18
                  },
                  "radius": 12,
                  "y": 6
                }
              },
              "children": [
                {
                  "id": "nbu_filters_header",
                  "type": "hstack",
                  "context": {
                    "_spacing": 8,
                    "_alignment": "center"
                  },
                  "children": [
                    {
                      "id": "nbu_filters_icon",
                      "type": "image",
                      "context": {
                        "_source": "sf://slider.horizontal.3"
                      },
                      "style": {
                        "layout": {
                          "width": 20,
                          "height": 20
                        },
                        "common": {
                          "foreground": "green"
                        }
                      }
                    },
                    {
                      "id": "nbu_filters_title",
                      "type": "text",
                      "context": {
                        "_text": "Параметри запиту"
                      },
                      "style": {
                        "common": {
                          "font": "headline",
                          "foreground": "primary"
                        }
                      }
                    }
                  ]
                },
                {
                  "id": "nbu_currency_picker",
                  "type": "picker",
                  "context": {
                    "_label": "Валюта",
                    "_selection": "${currency}",
                    "_options": [
                      "USD",
                      "EUR",
                      "PLN",
                      "GBP",
                      "CHF",
                      "CZK",
                      "HUF",
                      "RON",
                      "BGN",
                      "CAD",
                      "AUD",
                      "JPY",
                      "CNY",
                      "TRY",
                      "SEK",
                      "NOK",
                      "DKK"
                    ]
                  },
                  "style": {
                    "picker": "menu"
                  }
                },
                {
                  "id": "nbu_date_picker",
                  "type": "datepicker",
                  "context": {
                    "_label": "Дата курсу",
                    "_date": "${selectedDate}",
                    "_max": "#{today}",
                    "_components": "date"
                  },
                  "style": {
                    "datePicker": "compact"
                  }
                },
                {
                  "id": "nbu_date_hint_row",
                  "type": "hstack",
                  "context": {
                    "_spacing": 6,
                    "_alignment": "center"
                  },
                  "children": [
                    {
                      "id": "nbu_date_hint_icon",
                      "type": "image",
                      "context": {
                        "_source": "sf://info.circle"
                      },
                      "style": {
                        "layout": {
                          "width": 14,
                          "height": 14
                        },
                        "common": {
                          "foreground": "secondary"
                        }
                      }
                    },
                    {
                      "id": "nbu_date_hint",
                      "type": "text",
                      "context": {
                        "_text": "Доступна сьогоднішня або минула дата. Для вихідних НБУ може повернути останній опублікований курс."
                      },
                      "style": {
                        "common": {
                          "font": "caption",
                          "foreground": "secondary"
                        }
                      }
                    }
                  ]
                },
                {
                  "id": "nbu_fetch_button",
                  "type": "button",
                  "context": {
                    "_label": "Показати курс",
                    "_image": "sf://arrow.clockwise"
                  },
                  "style": {
                    "button": {
                      "standard": {
                        "type": "borderedProminent",
                        "shape": "capsule"
                      }
                    },
                    "layout": {
                      "maxWidth": "infinity",
                      "minHeight": 48
                    },
                    "common": {
                      "disabled": "${isLoading}"
                    }
                  },
                  "events": {
                    "onTap": [
                      {
                        "state": {
                          "id": "act_nbu_start_manual_fetch",
                          "input": {
                            "isLoading": true,
                            "error": "",
                            "rates": []
                          },
                          "output": {
                            "success": [
                              {
                                "repo": {
                                  "id": "act_nbu_manual_request",
                                  "input": {
                                    "repositoryId": "nbu_exchange_api",
                                    "operation": "read",
                                    "params": {
                                      "body": {
                                        "valcode": "${currency}",
                                        "date": "{{ format(${selectedDate}, {'date': {'style': 'custom', 'pattern': 'yyyyMMdd'}}) }}",
                                        "json": ""
                                      }
                                    }
                                  },
                                  "output": {
                                    "success": [
                                      {
                                        "condition": {
                                          "id": "act_nbu_manual_has_data",
                                          "input": "{{ notEmpty(@{act_nbu_manual_request}) }}",
                                          "output": {
                                            "success": [
                                              {
                                                "state": {
                                                  "id": "act_nbu_apply_manual_result",
                                                  "input": {
                                                    "rates": "@{act_nbu_manual_request}",
                                                    "isLoading": false,
                                                    "error": ""
                                                  }
                                                }
                                              },
                                              {
                                                "service": {
                                                  "id": "act_nbu_manual_success_haptic",
                                                  "input": {
                                                    "serviceId": "nbu_audio",
                                                    "params": {
                                                      "sound": "none",
                                                      "haptic": "success"
                                                    }
                                                  },
                                                  "output": {
                                                    "failure": [
                                                      {
                                                        "state": {
                                                          "id": "act_nbu_manual_success_haptic_failed",
                                                          "input": {
                                                            "isLoading": false,
                                                            "error": "Курс отримано, але не вдалося відтворити тактильний відгук."
                                                          }
                                                        }
                                                      }
                                                    ]
                                                  }
                                                }
                                              }
                                            ],
                                            "failure": [
                                              {
                                                "state": {
                                                  "id": "act_nbu_manual_empty_result",
                                                  "input": {
                                                    "rates": [],
                                                    "isLoading": false,
                                                    "error": "НБУ не повернув курс для вибраної валюти та дати. Спробуйте іншу дату."
                                                  }
                                                }
                                              },
                                              {
                                                "service": {
                                                  "id": "act_nbu_manual_empty_haptic",
                                                  "input": {
                                                    "serviceId": "nbu_audio",
                                                    "params": {
                                                      "sound": "none",
                                                      "haptic": "warning"
                                                    }
                                                  },
                                                  "output": {
                                                    "failure": [
                                                      {
                                                        "state": {
                                                          "id": "act_nbu_manual_empty_haptic_failed",
                                                          "input": {
                                                            "isLoading": false,
                                                            "error": "{{ ${error} + ' Не вдалося відтворити тактильний відгук.' }}"
                                                          }
                                                        }
                                                      }
                                                    ]
                                                  }
                                                }
                                              }
                                            ]
                                          }
                                        }
                                      }
                                    ],
                                    "failure": [
                                      {
                                        "state": {
                                          "id": "act_nbu_manual_request_failed",
                                          "input": {
                                            "rates": [],
                                            "isLoading": false,
                                            "error": "{{ 'Не вдалося отримати курс' + (notEmpty(@{act_nbu_manual_request.message}) ? ': ' + @{act_nbu_manual_request.message} : '. Перевірте з’єднання з мережею та повторіть спробу.') }}"
                                          }
                                        }
                                      },
                                      {
                                        "service": {
                                          "id": "act_nbu_manual_error_haptic",
                                          "input": {
                                            "serviceId": "nbu_audio",
                                            "params": {
                                              "sound": "none",
                                              "haptic": "error"
                                            }
                                          },
                                          "output": {
                                            "failure": [
                                              {
                                                "state": {
                                                  "id": "act_nbu_manual_error_haptic_failed",
                                                  "input": {
                                                    "isLoading": false,
                                                    "error": "{{ ${error} + ' Не вдалося відтворити тактильний відгук.' }}"
                                                  }
                                                }
                                              }
                                            ]
                                          }
                                        }
                                      }
                                    ]
                                  }
                                }
                              }
                            ]
                          }
                        }
                      }
                    ]
                  }
                }
              ]
            },
            {
              "id": "nbu_result_area",
              "type": "conditional",
              "context": {
                "_condition": "${isLoading}",
                "_trueComponent": {
                  "id": "nbu_loading_card",
                  "type": "vstack",
                  "context": {
                    "_spacing": 12,
                    "_alignment": "center"
                  },
                  "style": {
                    "layout": {
                      "maxWidth": "infinity",
                      "padding": 24
                    },
                    "common": {
                      "background": {
                        "material": "regular"
                      },
                      "foreground": "primary",
                      "cornerRadius": 20
                    }
                  },
                  "children": [
                    {
                      "id": "nbu_loading_progress",
                      "type": "progress",
                      "context": {
                        "_value": 0,
                        "_total": 1
                      }
                    },
                    {
                      "id": "nbu_loading_text",
                      "type": "text",
                      "context": {
                        "_text": "Отримуємо офіційний курс…"
                      },
                      "style": {
                        "common": {
                          "font": "subheadline",
                          "foreground": "secondary"
                        }
                      }
                    }
                  ]
                },
                "_falseComponent": {
                  "id": "nbu_loaded_area",
                  "type": "conditional",
                  "context": {
                    "_condition": "{{ notEmpty(${error}) }}",
                    "_trueComponent": {
                      "id": "nbu_error_card",
                      "type": "vstack",
                      "context": {
                        "_spacing": 10,
                        "_alignment": "center"
                      },
                      "style": {
                        "layout": {
                          "maxWidth": "infinity",
                          "padding": 20
                        },
                        "common": {
                          "background": {
                            "color": "red",
                            "opacity": 0.14
                          },
                          "foreground": "primary",
                          "cornerRadius": 20
                        },
                        "shadow": {
                          "color": {
                            "color": "black",
                            "opacity": 0.12
                          },
                          "radius": 8,
                          "y": 4
                        }
                      },
                      "children": [
                        {
                          "id": "nbu_error_icon",
                          "type": "image",
                          "context": {
                            "_source": "sf://exclamationmark.triangle.fill"
                          },
                          "style": {
                            "layout": {
                              "width": 30,
                              "height": 30
                            },
                            "common": {
                              "foreground": "red"
                            }
                          }
                        },
                        {
                          "id": "nbu_error_text",
                          "type": "text",
                          "context": {
                            "_text": "${error}"
                          },
                          "style": {
                            "common": {
                              "font": "subheadline",
                              "foreground": "primary"
                            },
                            "text": {
                              "multilineTextAlignment": "center",
                              "lineSpacing": 2
                            }
                          }
                        }
                      ]
                    },
                    "_falseComponent": {
                      "id": "nbu_result_or_empty",
                      "type": "conditional",
                      "context": {
                        "_condition": "{{ notEmpty(${rates}) }}",
                        "_trueComponent": {
                          "id": "nbu_rate_card",
                          "type": "vstack",
                          "context": {
                            "_spacing": 14,
                            "_alignment": "leading",
                            "rateItem": "${rates[0]}"
                          },
                          "style": {
                            "layout": {
                              "maxWidth": "infinity",
                              "padding": 20
                            },
                            "common": {
                              "background": {
                                "gradient": {
                                  "linear": {
                                    "colors": [
                                      "#14532D",
                                      "#166534",
                                      "#0F766E"
                                    ],
                                    "startPoint": "topLeading",
                                    "endPoint": "bottomTrailing"
                                  }
                                }
                              },
                              "foreground": "white",
                              "cornerRadius": 22
                            },
                            "shadow": {
                              "color": {
                                "color": "black",
                                "opacity": 0.24
                              },
                              "radius": 14,
                              "y": 8
                            },
                            "animation": {
                              "kind": "spring",
                              "value": "${rates}",
                              "duration": 0.45,
                              "bounce": 0.25
                            }
                          },
                          "children": [
                            {
                              "id": "nbu_rate_header",
                              "type": "hstack",
                              "context": {
                                "_spacing": 10,
                                "_alignment": "center"
                              },
                              "children": [
                                {
                                  "id": "nbu_rate_icon",
                                  "type": "image",
                                  "context": {
                                    "_source": "sf://chart.line.uptrend.xyaxis"
                                  },
                                  "style": {
                                    "layout": {
                                      "width": 24,
                                      "height": 24
                                    },
                                    "common": {
                                      "foreground": "white"
                                    }
                                  }
                                },
                                {
                                  "id": "nbu_rate_currency_stack",
                                  "type": "vstack",
                                  "context": {
                                    "_spacing": 2,
                                    "_alignment": "leading"
                                  },
                                  "children": [
                                    {
                                      "id": "nbu_rate_code",
                                      "type": "text",
                                      "context": {
                                        "_text": "@{rateItem.cc}"
                                      },
                                      "style": {
                                        "common": {
                                          "font": {
                                            "kind": "title3",
                                            "weight": "bold"
                                          },
                                          "foreground": "white"
                                        }
                                      }
                                    },
                                    {
                                      "id": "nbu_rate_name",
                                      "type": "text",
                                      "context": {
                                        "_text": "@{rateItem.txt}"
                                      },
                                      "style": {
                                        "common": {
                                          "font": "caption",
                                          "foreground": {
                                            "color": "white",
                                            "opacity": 0.78
                                          }
                                        }
                                      }
                                    }
                                  ]
                                },
                                {
                                  "id": "nbu_rate_header_spacer",
                                  "type": "spacer"
                                },
                                {
                                  "id": "nbu_rate_date",
                                  "type": "text",
                                  "context": {
                                    "_text": "@{rateItem.exchangedate}"
                                  },
                                  "style": {
                                    "common": {
                                      "font": "caption",
                                      "foreground": {
                                        "color": "white",
                                        "opacity": 0.82
                                      }
                                    }
                                  }
                                }
                              ]
                            },
                            {
                              "id": "nbu_rate_divider",
                              "type": "divider"
                            },
                            {
                              "id": "nbu_rate_value_row",
                              "type": "hstack",
                              "context": {
                                "_spacing": 8,
                                "_alignment": "bottom"
                              },
                              "children": [
                                {
                                  "id": "nbu_rate_value",
                                  "type": "text",
                                  "context": {
                                    "_text": "@{rateItem.rate}",
                                    "_format": {
                                      "number": {
                                        "style": "decimal",
                                        "minimumFractionDigits": 2,
                                        "maximumFractionDigits": 4
                                      }
                                    }
                                  },
                                  "style": {
                                    "common": {
                                      "font": {
                                        "kind": "largeTitle",
                                        "weight": "bold"
                                      },
                                      "foreground": "white"
                                    },
                                    "text": {
                                      "lineLimit": 1,
                                      "minimumScaleFactor": 0.7
                                    }
                                  }
                                },
                                {
                                  "id": "nbu_rate_unit",
                                  "type": "text",
                                  "context": {
                                    "_text": "грн"
                                  },
                                  "style": {
                                    "common": {
                                      "font": "title2",
                                      "foreground": {
                                        "color": "white",
                                        "opacity": 0.78
                                      }
                                    }
                                  }
                                }
                              ]
                            },
                            {
                              "id": "nbu_rate_explanation",
                              "type": "text",
                              "context": {
                                "_text": "{{ '1 ' + @{rateItem.cc} + ' за офіційним курсом НБУ' }}"
                              },
                              "style": {
                                "common": {
                                  "font": "subheadline",
                                  "foreground": {
                                    "color": "white",
                                    "opacity": 0.82
                                  }
                                }
                              }
                            }
                          ]
                        },
                        "_falseComponent": {
                          "id": "nbu_empty_card",
                          "type": "vstack",
                          "context": {
                            "_spacing": 10,
                            "_alignment": "center"
                          },
                          "style": {
                            "layout": {
                              "maxWidth": "infinity",
                              "padding": 24
                            },
                            "common": {
                              "background": {
                                "material": "regular"
                              },
                              "foreground": "primary",
                              "cornerRadius": 20
                            }
                          },
                          "children": [
                            {
                              "id": "nbu_empty_icon",
                              "type": "image",
                              "context": {
                                "_source": "sf://calendar.badge.clock"
                              },
                              "style": {
                                "layout": {
                                  "width": 38,
                                  "height": 38
                                },
                                "common": {
                                  "foreground": "green"
                                }
                              }
                            },
                            {
                              "id": "nbu_empty_text",
                              "type": "text",
                              "context": {
                                "_text": "Виберіть валюту й дату, щоб переглянути офіційний курс."
                              },
                              "style": {
                                "common": {
                                  "font": "subheadline",
                                  "foreground": "secondary"
                                },
                                "text": {
                                  "multilineTextAlignment": "center"
                                }
                              }
                            }
                          ]
                        }
                      }
                    }
                  }
                }
              }
            },
            {
              "id": "nbu_source_note",
              "type": "hstack",
              "context": {
                "_spacing": 7,
                "_alignment": "center"
              },
              "style": {
                "layout": {
                  "maxWidth": "infinity",
                  "padding": {
                    "horizontal": 4
                  }
                }
              },
              "children": [
                {
                  "id": "nbu_source_icon",
                  "type": "image",
                  "context": {
                    "_source": "sf://checkmark.shield.fill"
                  },
                  "style": {
                    "layout": {
                      "width": 15,
                      "height": 15
                    },
                    "common": {
                      "foreground": "green"
                    }
                  }
                },
                {
                  "id": "nbu_source_text",
                  "type": "text",
                  "context": {
                    "_text": "Джерело: відкритий API НБУ. Перелік містить найуживаніші валюти; валюту можна змінити в меню вище."
                  },
                  "style": {
                    "common": {
                      "font": "caption",
                      "foreground": {
                        "color": "white",
                        "opacity": 0.66
                      }
                    },
                    "text": {
                      "lineSpacing": 2
                    }
                  }
                }
              ]
            }
          ]
        }
      ]
    }
  ],
  "events": {
    "onAppear": [
      {
        "state": {
          "id": "act_nbu_initialize_date",
          "input": {
            "selectedDate": "#{today}",
            "isLoading": true,
            "error": "",
            "rates": []
          },
          "output": {
            "success": [
              {
                "repo": {
                  "id": "act_nbu_initial_request",
                  "input": {
                    "repositoryId": "nbu_exchange_api",
                    "operation": "read",
                    "params": {
                      "body": {
                        "valcode": "${currency}",
                        "date": "{{ format(${selectedDate}, {'date': {'style': 'custom', 'pattern': 'yyyyMMdd'}}) }}",
                        "json": ""
                      }
                    }
                  },
                  "output": {
                    "success": [
                      {
                        "condition": {
                          "id": "act_nbu_initial_has_data",
                          "input": "{{ notEmpty(@{act_nbu_initial_request}) }}",
                          "output": {
                            "success": [
                              {
                                "state": {
                                  "id": "act_nbu_apply_initial_result",
                                  "input": {
                                    "rates": "@{act_nbu_initial_request}",
                                    "isLoading": false,
                                    "error": ""
                                  }
                                }
                              }
                            ],
                            "failure": [
                              {
                                "state": {
                                  "id": "act_nbu_initial_empty_result",
                                  "input": {
                                    "rates": [],
                                    "isLoading": false,
                                    "error": "НБУ не повернув курс на сьогодні. Виберіть попередню дату та повторіть запит."
                                  }
                                }
                              }
                            ]
                          }
                        }
                      }
                    ],
                    "failure": [
                      {
                        "state": {
                          "id": "act_nbu_initial_request_failed",
                          "input": {
                            "rates": [],
                            "isLoading": false,
                            "error": "{{ 'Не вдалося завантажити курс' + (notEmpty(@{act_nbu_initial_request.message}) ? ': ' + @{act_nbu_initial_request.message} : '. Перевірте з’єднання з мережею та повторіть спробу.') }}"
                          }
                        }
                      }
                    ]
                  }
                }
              }
            ]
          }
        }
      }
    ]
  }
}