/);
+```
+
+Your `p` element should come after your `hr` element.
+
+```js
+const htmlString = code.split(/output\s*\.\s*innerHTML\s*=\s*/)[1].split(/`/)[1];
+assert.isAbove(htmlString.indexOf('
\$\{budgetCalories\}\s*Calories\s*Budgeted<\/p>/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+ /g).length, 2);
+```
+
+Your second `p` element should be on a new line.
+
+```js
+const htmlString = code.split(/output\s*\.\s*innerHTML\s*=\s*/)[1].split(/`/)[1];
+assert.match(htmlString, /\n\s*
\$\{consumedCalories\}\s*Calories\s*Consumed<\/p>/));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+ 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...
-Let us list the factors of the first seven triangle numbers:
+Abaixo está a lista dos 7 primeiros números do triângulo:
37107287533902102798797998220837590246510135740250
@@ -115,19 +115,19 @@ Work out the first ten digits of the sum of the following one-hundred 50-digit n
# --hints--
-`largeSum(testNums)` should return a number.
+`largeSum(testNums)` deve retornar um número.
```js
assert(typeof largeSum(testNums) === 'number');
```
-`largeSum(testNums)` should return 8348422521.
+`largeSum(testNums)` deve retornar 8348422521.
```js
assert.strictEqual(largeSum(testNums), 8348422521);
```
-`largeSum(fiftyDigitNums)` should return 5537376230.
+`largeSum(fiftyDigitNums)` deve retornar 5537376230.
```js
assert.strictEqual(largeSum(fiftyDigitNums), 5537376230);
diff --git a/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-14-longest-collatz-sequence.md b/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-14-longest-collatz-sequence.md
index cac70d3bb29..add22b290c3 100644
--- a/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-14-longest-collatz-sequence.md
+++ b/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-14-longest-collatz-sequence.md
@@ -1,6 +1,6 @@
---
id: 5900f37a1000cf542c50fe8d
-title: 'Problem 14: Longest Collatz sequence'
+title: 'Problema 14: Maior conjectura de Collatz'
challengeType: 1
forumTopicId: 301768
dashedName: problem-14-longest-collatz-sequence
@@ -8,61 +8,61 @@ dashedName: problem-14-longest-collatz-sequence
# --description--
-The following iterative sequence is defined for the set of positive integers:
+A seguinte sequência iterativa é definida para o conjunto dos números inteiros positivos:
-
n → n /2 (n is even)
+
n → n /2 (use quando n for par)
-
n → 3n + 1 (n is odd)
+
n → 3n + 1 (use quando n for ímpar)
-Using the rule above and starting with 13, we generate the following sequence:
+Usando a regra acima e começando com 13, geramos a seguinte sequência:
13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1
-It can be seen that this sequence (starting at 13 and finishing at 1) contains 10 terms. Although it has not been proved yet (Collatz Problem), it is thought that all starting numbers finish at 1.
+Podemos ver que essa sequência (começando em 13 e terminando em 1) contém 10 termos. Embora ainda não tenha sido provado (conjectura de Collatz), acredita-se que qualquer número inicial termine em 1.
-Which starting number, under the given `limit`, produces the longest chain?
+Qual número inicial, sob o `limit` (limite) definido, produz a sequência mais longa?
-**Note:** Once the chain starts the terms are allowed to go above `limit`.
+**Observação:** uma vez iniciada, os termos na sequência podem passar acima do `limit`.
# --hints--
-`longestCollatzSequence(14)` should return a number.
+`longestCollatzSequence(14)` deve retornar um número.
```js
assert(typeof longestCollatzSequence(14) === 'number');
```
-`longestCollatzSequence(14)` should return 9.
+`longestCollatzSequence(14)` deve retornar 9.
```js
assert.strictEqual(longestCollatzSequence(14), 9);
```
-`longestCollatzSequence(5847)` should return 3711.
+`longestCollatzSequence(5847)` deve retornar 3711.
```js
assert.strictEqual(longestCollatzSequence(5847), 3711);
```
-`longestCollatzSequence(46500)` should return 35655.
+`longestCollatzSequence(46500)` deve retornar 35655.
```js
assert.strictEqual(longestCollatzSequence(46500), 35655);
```
-`longestCollatzSequence(54512)` should return 52527.
+`longestCollatzSequence(54512)` deve retornar 52527.
```js
assert.strictEqual(longestCollatzSequence(54512), 52527);
```
-`longestCollatzSequence(100000)` should return 77031.
+`longestCollatzSequence(100000)` deve retornar 77031.
```js
assert.strictEqual(longestCollatzSequence(100000), 77031);
```
-`longestCollatzSequence(1000000)` should return 837799.
+`longestCollatzSequence(1000000)` deve retornar 837799.
```js
assert.strictEqual(longestCollatzSequence(1000000), 837799);
diff --git a/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-15-lattice-paths.md b/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-15-lattice-paths.md
index 225eddd68e7..7490847b37d 100644
--- a/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-15-lattice-paths.md
+++ b/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-15-lattice-paths.md
@@ -1,6 +1,6 @@
---
id: 5900f37b1000cf542c50fe8e
-title: 'Problem 15: Lattice paths'
+title: 'Problema 15: Caminhos em uma grade'
challengeType: 1
forumTopicId: 301780
dashedName: problem-15-lattice-paths
@@ -8,33 +8,33 @@ dashedName: problem-15-lattice-paths
# --description--
-Starting in the top left corner of a 2×2 grid, and only being able to move to the right and down, there are exactly 6 routes to the bottom right corner.
+Começando no canto superior esquerdo de uma grade 2×2, e sendo capaz de se mover para a direita e para baixo, existem exatamente 6 caminhos até o canto inferior direito.
-
+
-How many such routes are there through a given `gridSize`?
+Quantas rotas existem que cruzam uma grade de tamanho `gridSize`?
# --hints--
-`latticePaths(4)` should return a number.
+`latticePaths(4)` deve retornar um número.
```js
assert(typeof latticePaths(4) === 'number');
```
-`latticePaths(4)` should return 70.
+`latticePaths(4)` deve retornar 70.
```js
assert.strictEqual(latticePaths(4), 70);
```
-`latticePaths(9)` should return 48620.
+`latticePaths(9)` deve retornar 48620.
```js
assert.strictEqual(latticePaths(9), 48620);
```
-`latticePaths(20)` should return 137846528820.
+`latticePaths(20)` deve retornar 137846528820.
```js
assert.strictEqual(latticePaths(20), 137846528820);
diff --git a/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-2-even-fibonacci-numbers.md b/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-2-even-fibonacci-numbers.md
index 4376672786b..11fed41bcf8 100644
--- a/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-2-even-fibonacci-numbers.md
+++ b/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-2-even-fibonacci-numbers.md
@@ -1,6 +1,6 @@
---
id: 5900f36e1000cf542c50fe81
-title: 'Problem 2: Even Fibonacci Numbers'
+title: 'Problema 2: Apenas números pares da sequência de Fibonacci'
challengeType: 1
forumTopicId: 301838
dashedName: problem-2-even-fibonacci-numbers
@@ -8,63 +8,63 @@ dashedName: problem-2-even-fibonacci-numbers
# --description--
-Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:
+Cada novo número na sequência de Fibonacci é gerado pela soma dos dois números anteriores. Ao começar com 1 e 2, os primeiros 10 números serão:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
-By considering the terms in the Fibonacci sequence whose values do not exceed `n`, find the sum of the even-valued terms.
+Considerando os números na sequência de Fibonacci cujos valores não excedem `n`, encontre a soma dos números pares.
# --hints--
-`fiboEvenSum(10)` should return a number.
+`fiboEvenSum(10)` deve retornar um número.
```js
assert(typeof fiboEvenSum(10) === 'number');
```
-Your function should return an even value.
+A função deve retornar um valor par (even).
```js
assert.equal(fiboEvenSum(10) % 2 === 0, true);
```
-Your function should sum the even-valued Fibonacci numbers: `fiboEvenSum(8)` should return 10.
+A função deve somar os números pares de Fibonacci: `fiboEvenSum(8)` deve retornar 10.
```js
assert.strictEqual(fiboEvenSum(8), 10);
```
-`fiboEvenSum(10)` should return 10.
+`fiboEvenSum(10)` deve retornar 10.
```js
assert.strictEqual(fiboEvenSum(10), 10);
```
-`fiboEvenSum(34)` should return 44.
+`fiboEvenSum(34)` deve retornar 44.
```js
assert.strictEqual(fiboEvenSum(34), 44);
```
-`fiboEvenSum(60)` should return 44.
+`fiboEvenSum(60)` deve retornar 44.
```js
assert.strictEqual(fiboEvenSum(60), 44);
```
-`fiboEvenSum(1000)` should return 798.
+`fiboEvenSum(1000)` deve retornar 798.
```js
assert.strictEqual(fiboEvenSum(1000), 798);
```
-`fiboEvenSum(100000)` should return 60696.
+`fiboEvenSum(100000)` deve retornar 60696.
```js
assert.strictEqual(fiboEvenSum(100000), 60696);
```
-`fiboEvenSum(4000000)` should return 4613732.
+`fiboEvenSum(4000000)` deve retornar 4613732.
```js
assert.strictEqual(fiboEvenSum(4000000), 4613732);
diff --git a/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-3-largest-prime-factor.md b/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-3-largest-prime-factor.md
index 2961ac6b9c0..424ca34aa26 100644
--- a/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-3-largest-prime-factor.md
+++ b/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-3-largest-prime-factor.md
@@ -1,6 +1,6 @@
---
id: 5900f36f1000cf542c50fe82
-title: 'Problem 3: Largest prime factor'
+title: 'Problema 3: Maior fator primo'
challengeType: 1
forumTopicId: 301952
dashedName: problem-3-largest-prime-factor
@@ -8,55 +8,55 @@ dashedName: problem-3-largest-prime-factor
# --description--
-The prime factors of 13195 are 5, 7, 13 and 29.
+Os fatores primos de 13195 são 5, 7, 13 e 29.
-What is the largest prime factor of the given `number`?
+Qual é o maior fator primo do parâmetro `number`?
# --hints--
-`largestPrimeFactor(2)` should return a number.
+`largestPrimeFactor(2)` deve retornar um número.
```js
assert(typeof largestPrimeFactor(2) === 'number');
```
-`largestPrimeFactor(2)` should return 2.
+`largestPrimeFactor(2)` deve retornar 2.
```js
assert.strictEqual(largestPrimeFactor(2), 2);
```
-`largestPrimeFactor(3)` should return 3.
+`largestPrimeFactor(3)` deve retornar 3.
```js
assert.strictEqual(largestPrimeFactor(3), 3);
```
-`largestPrimeFactor(5)` should return 5.
+`largestPrimeFactor(5)` deve retornar 5.
```js
assert.strictEqual(largestPrimeFactor(5), 5);
```
-`largestPrimeFactor(7)` should return 7.
+`largestPrimeFactor(7)` deve retornar 7.
```js
assert.strictEqual(largestPrimeFactor(7), 7);
```
-`largestPrimeFactor(8)` should return 2.
+`largestPrimeFactor(8)` deve retornar 2.
```js
assert.strictEqual(largestPrimeFactor(8), 2);
```
-`largestPrimeFactor(13195)` should return 29.
+`largestPrimeFactor(13195)` deve retornar 29.
```js
assert.strictEqual(largestPrimeFactor(13195), 29);
```
-`largestPrimeFactor(600851475143)` should return 6857.
+`largestPrimeFactor(600851475143)` deve retornar 6857.
```js
assert.strictEqual(largestPrimeFactor(600851475143), 6857);
diff --git a/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-4-largest-palindrome-product.md b/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-4-largest-palindrome-product.md
index 9e436255531..e85b4aee09c 100644
--- a/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-4-largest-palindrome-product.md
+++ b/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-4-largest-palindrome-product.md
@@ -1,6 +1,6 @@
---
id: 5900f3701000cf542c50fe83
-title: 'Problem 4: Largest palindrome product'
+title: 'Problema 4: Maior palíndromo de um produto'
challengeType: 1
forumTopicId: 302065
dashedName: problem-4-largest-palindrome-product
@@ -8,25 +8,25 @@ dashedName: problem-4-largest-palindrome-product
# --description--
-A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.
+Um número palíndromo é aquele que pode ser lido da esquerda para a direita e vice-versa. O maior palíndromo feito a partir do produto de dois algarismos é 9009 = 91 × 99.
-Find the largest palindrome made from the product of two `n`-digit numbers.
+Encontre o maior palíndromo feito a partir do produto de dois números de `n` algarismos.
# --hints--
-`largestPalindromeProduct(2)` should return a number.
+`largestPalindromeProduct(2)` deve retornar um número.
```js
assert(typeof largestPalindromeProduct(2) === 'number');
```
-`largestPalindromeProduct(2)` should return 9009.
+`largestPalindromeProduct(2)` deve retornar 9009.
```js
assert.strictEqual(largestPalindromeProduct(2), 9009);
```
-`largestPalindromeProduct(3)` should return 906609.
+`largestPalindromeProduct(3)` deve retornar 906609.
```js
assert.strictEqual(largestPalindromeProduct(3), 906609);
diff --git a/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-5-smallest-multiple.md b/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-5-smallest-multiple.md
index 2f20bceaadf..a98dc958095 100644
--- a/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-5-smallest-multiple.md
+++ b/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-5-smallest-multiple.md
@@ -1,6 +1,6 @@
---
id: 5900f3711000cf542c50fe84
-title: 'Problem 5: Smallest multiple'
+title: 'Problema 5: Menor múltiplo'
challengeType: 1
forumTopicId: 302160
dashedName: problem-5-smallest-multiple
@@ -8,43 +8,43 @@ dashedName: problem-5-smallest-multiple
# --description--
-2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.
+2520 é o menor número que pode ser dividido por cada um dos números entre 1 e 10, sem nenhum resto.
-What is the smallest positive number that is evenly divisible by all of the numbers from 1 to `n`?
+Qual é o menor número positivo que é igualmente divisível por todos os números de 1 a `n`?
# --hints--
-`smallestMult(5)` should return a number.
+`smallestMult(5)` deve retornar um número.
```js
assert(typeof smallestMult(5) === 'number');
```
-`smallestMult(5)` should return 60.
+`smallestMult(5)` deve retornar 60.
```js
assert.strictEqual(smallestMult(5), 60);
```
-`smallestMult(7)` should return 420.
+`smallestMult(7)` deve retornar 420.
```js
assert.strictEqual(smallestMult(7), 420);
```
-`smallestMult(10)` should return 2520.
+`smallestMult(10)` deve retornar 2520.
```js
assert.strictEqual(smallestMult(10), 2520);
```
-`smallestMult(13)` should return 360360.
+`smallestMult(13)` deve retornar 360360.
```js
assert.strictEqual(smallestMult(13), 360360);
```
-`smallestMult(20)` should return 232792560.
+`smallestMult(20)` deve retornar 232792560.
```js
assert.strictEqual(smallestMult(20), 232792560);
diff --git a/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-6-sum-square-difference.md b/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-6-sum-square-difference.md
index 65a460bd803..f82fded9a45 100644
--- a/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-6-sum-square-difference.md
+++ b/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-6-sum-square-difference.md
@@ -1,6 +1,6 @@
---
id: 5900f3721000cf542c50fe85
-title: 'Problem 6: Sum square difference'
+title: 'Problema 6: Diferença da soma dos quadrados'
challengeType: 1
forumTopicId: 302171
dashedName: problem-6-sum-square-difference
@@ -8,39 +8,39 @@ dashedName: problem-6-sum-square-difference
# --description--
-The sum of the squares of the first ten natural numbers is,
+A soma dos quadrados dos primeiros dez números naturais é,
12 + 22 + ... + 102 = 385
-The square of the sum of the first ten natural numbers is,
+O quadrado da soma dos primeiros dez números naturais é,
(1 + 2 + ... + 10)2 = 552 = 3025
-Hence the difference between the sum of the squares of the first ten natural numbers and the square of the sum is 3025 − 385 = 2640.
+Por isso, a diferença entre a soma dos quadrados dos primeiros dez números naturais e o quadrado da soma é 3025 – 385 = 2640.
-Find the difference between the sum of the squares of the first `n` natural numbers and the square of the sum.
+Calcule a diferença entre a soma dos quadrados dos primeiros `n` números naturais e o quadrado da soma.
# --hints--
-`sumSquareDifference(10)` should return a number.
+`sumSquareDifference(10)` deve retornar um número.
```js
assert(typeof sumSquareDifference(10) === 'number');
```
-`sumSquareDifference(10)` should return 2640.
+`sumSquareDifference(10)` deve retornar 2640.
```js
assert.strictEqual(sumSquareDifference(10), 2640);
```
-`sumSquareDifference(20)` should return 41230.
+`sumSquareDifference(20)` deve retornar 41230.
```js
assert.strictEqual(sumSquareDifference(20), 41230);
```
-`sumSquareDifference(100)` should return 25164150.
+`sumSquareDifference(100)` deve retornar 25164150.
```js
assert.strictEqual(sumSquareDifference(100), 25164150);
diff --git a/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-7-10001st-prime.md b/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-7-10001st-prime.md
index 6780c8fa2d1..e7a79856e45 100644
--- a/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-7-10001st-prime.md
+++ b/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-7-10001st-prime.md
@@ -1,6 +1,6 @@
---
id: 5900f3731000cf542c50fe86
-title: 'Problem 7: 10001st prime'
+title: 'Problema 7: 10001º número primo'
challengeType: 1
forumTopicId: 302182
dashedName: problem-7-10001st-prime
@@ -8,43 +8,43 @@ dashedName: problem-7-10001st-prime
# --description--
-By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.
+Ao listar os primeiros seis números primos: 2, 3, 5, 7, 11 e 13, podemos ver que o sexto número primo é 13.
-What is the `n`th prime number?
+Qual é o `n`-ésimo número primo?
# --hints--
-`nthPrime(6)` should return a number.
+`nthPrime(6)` deve retornar um número.
```js
assert(typeof nthPrime(6) === 'number');
```
-`nthPrime(6)` should return 13.
+`nthPrime(6)` deve retornar 13.
```js
assert.strictEqual(nthPrime(6), 13);
```
-`nthPrime(10)` should return 29.
+`nthPrime(10)` deve retornar 29.
```js
assert.strictEqual(nthPrime(10), 29);
```
-`nthPrime(100)` should return 541.
+`nthPrime(100)` deve retornar 541.
```js
assert.strictEqual(nthPrime(100), 541);
```
-`nthPrime(1000)` should return 7919.
+`nthPrime(1000)` deve retornar 7919.
```js
assert.strictEqual(nthPrime(1000), 7919);
```
-`nthPrime(10001)` should return 104743.
+`nthPrime(10001)` deve retornar 104743.
```js
assert.strictEqual(nthPrime(10001), 104743);
diff --git a/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-8-largest-product-in-a-series.md b/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-8-largest-product-in-a-series.md
index c84d410e207..8d8a048facf 100644
--- a/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-8-largest-product-in-a-series.md
+++ b/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-8-largest-product-in-a-series.md
@@ -1,6 +1,6 @@
---
id: 5900f3741000cf542c50fe87
-title: 'Problem 8: Largest product in a series'
+title: 'Problema 8: Maior produto em uma série'
challengeType: 1
forumTopicId: 302193
dashedName: problem-8-largest-product-in-a-series
@@ -8,7 +8,7 @@ dashedName: problem-8-largest-product-in-a-series
# --description--
-The four adjacent digits in the 1000-digit number that have the greatest product are 9 × 9 × 8 × 9 = 5832.
+O número abaixo possui 1000 algarismos. Se você pegar, em ordem, 4 algarismos quaisquer, o maior produto que você vai encontrar é 9 × 9 × 8 × 9 = 5832.
73167176531330624919225119674426574742355349194934
96983520312774506326239578318016984801869478851843
@@ -31,23 +31,23 @@ The four adjacent digits in the 1000-digit number that have the greatest product
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450
-Find the `n` adjacent digits in the 1000-digit number that have the greatest product. What is the value of this product?
+Encontre os `n` algarismos adjacentes no número de 1000 algarismos que têm o maior produto. Qual é o valor do produto?
# --hints--
-`largestProductinaSeries(4)` should return a number.
+`largestProductinaSeries(4)` deve retornar um número.
```js
assert(typeof largestProductinaSeries(4) === 'number');
```
-`largestProductinaSeries(4)` should return 5832.
+`largestProductinaSeries(4)` deve retornar 5832.
```js
assert.strictEqual(largestProductinaSeries(4), 5832);
```
-`largestProductinaSeries(13)` should return 23514624000.
+`largestProductinaSeries(13)` deve retornar 23514624000.
```js
assert.strictEqual(largestProductinaSeries(13), 23514624000);
diff --git a/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-9-special-pythagorean-triplet.md b/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-9-special-pythagorean-triplet.md
index a853dd4415e..5b5c1f2f7d2 100644
--- a/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-9-special-pythagorean-triplet.md
+++ b/curriculum/challenges/portuguese/18-project-euler/project-euler-problems-1-to-100/problem-9-special-pythagorean-triplet.md
@@ -1,6 +1,6 @@
---
id: 5900f3761000cf542c50fe88
-title: 'Problem 9: Special Pythagorean triplet'
+title: 'Problema 9: Terno pitagórico especial'
challengeType: 1
forumTopicId: 302205
dashedName: problem-9-special-pythagorean-triplet
@@ -8,35 +8,35 @@ dashedName: problem-9-special-pythagorean-triplet
# --description--
-A Pythagorean triplet is a set of three natural numbers, `a` < `b` < `c`, for which,
+Um terno pitagórico é um conjunto de três números naturais, `a` < `b` < `c` tal que
a 2 + b 2 = c 2
-For example, 3
2 + 4
2 = 9 + 16 = 25 = 5
2 .
+Por exemplo, 3
2 + 4
2 = 9 + 16 = 25 = 5
2 .
-There exists exactly one Pythagorean triplet for which `a` + `b` + `c` = 1000. Find the product `abc` such that `a` + `b` + `c` = `n`.
+Há exatamente um terno pitagórico para o qual `a` + `b` + `c` = 1000. Encontre o produto `abc` tal que `a` + `b` + `c` = `n`.
# --hints--
-`specialPythagoreanTriplet(24)` should return a number.
+`specialPythagoreanTriplet(24)` deve retornar um número.
```js
assert(typeof specialPythagoreanTriplet(24) === 'number');
```
-`specialPythagoreanTriplet(24)` should return 480.
+`specialPythagoreanTriplet(24)` deve retornar 480.
```js
assert.strictEqual(specialPythagoreanTriplet(24), 480);
```
-`specialPythagoreanTriplet(120)` should return 49920, 55080 or 60000.
+`specialPythagoreanTriplet(120)` deve retornar 49920, 55080 ou 60000.
```js
assert([49920, 55080, 60000].includes(specialPythagoreanTriplet(120)));
```
-`specialPythagoreanTriplet(1000)` should return 31875000.
+`specialPythagoreanTriplet(1000)` deve retornar 31875000.
```js
assert.strictEqual(specialPythagoreanTriplet(1000), 31875000);
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/basic-javascript/record-collection.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/basic-javascript/record-collection.md
index 6e872c248a9..eccc4361481 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/basic-javascript/record-collection.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/basic-javascript/record-collection.md
@@ -8,21 +8,28 @@ dashedName: record-collection
# --description--
-Вам надано літерал об'єкта, який представляє вашу колекцію музичних альбомів. Кожен альбом має унікальний id як свій ключ та декілька інших властивостей. Не всі альбоми мають повну інформацію.
+You are creating a function that aids in the maintenance of a musical album collection. The collection is organized as an object that contains multiple albums which are also objects. Each album is represented in the collection with a unique `id` as the property name. Within each album object, there are various properties describing information about the album. Not all albums have complete information.
-Ви починаєте з функції `updateRecords`, що приймає літерал об'єкта `records`, який містить колекцію музичних альбомів, `id`, `prop` (типу `artist` чи `tracks`) та `value`. Завершіть функцію, використовуючи правила нижче, щоб змінити об'єкт, переданий до функції.
+The `updateRecords` function takes 4 arguments represented by the following function parameters:
-- Ваша функція завжди повинна повертати весь об'єкт-колекцію.
-- Якщо `prop` не є `tracks`, а `value` не є пустим рядком, то оновіть або встановіть `prop` альбому на `value`.
-- Якщо `prop` є `tracks`, але альбом не має властивості `tracks`, то створіть пустий масив та додайте `value` до нього.
-- Якщо `prop` є `tracks` та `value` не є пустим рядком, то додайте `value` в кінець наявного масиву `tracks` в альбомі.
-- Якщо `value` є пустим рядком, видаліть дану властивість `prop` з альбому.
+- `records` - an object containing several individual albums
+- `id` - a number representing a specific album in the `records` object
+- `prop` - a string representing the name of the album’s property to update
+- `value` - a string containing the information used to update the album’s property
-**Примітка:** копія об'єкту `recordCollection` використовується для тестів.
+Complete the function using the rules below to modify the object passed to the function.
+
+- Your function must always return the entire `records` object.
+- If `value` is an empty string, delete the given `prop` property from the album.
+- If `prop` isn’t `"tracks"` and `value` isn't an empty string, assign the `value` to that album’s `prop`.
+- If `prop` is `"tracks"` and `value` isn’t an empty string, add the `value` to the end of the album’s existing `"tracks"` array.
+- If the album doesn’t have a `"tracks"` property, create a new array for the album's `"tracks"` property before adding the `value` to it.
+
+**Note:** A copy of the `recordCollection` object is used for the tests. You should not directly modify the `recordCollection` object.
# --hints--
-Після `updateRecords(recordCollection, 5439, "artist", "ABBA")`, `artist` повинен стати рядком `ABBA`
+After `updateRecords(recordCollection, 5439, "artist", "ABBA")`, `artist` should be the string `ABBA`
```js
assert(
@@ -31,7 +38,7 @@ assert(
);
```
-Після `updateRecords(recordCollection, 5439, "tracks", "Take a Chance on Me")`, `tracks` повинен мати рядок `Take a Chance on Me` як останній та єдиний елемент.
+After `updateRecords(recordCollection, 5439, "tracks", "Take a Chance on Me")`, `tracks` should have the string `Take a Chance on Me` as the last and only element.
```js
assert(
@@ -41,14 +48,14 @@ assert(
);
```
-Після `updateRecords(recordCollection, 2548, "artist", "")` не потрібно налаштовувати `artist`
+After `updateRecords(recordCollection, 2548, "artist", "")`, `artist` should not be set
```js
updateRecords(_recordCollection, 2548, 'artist', '');
assert(!_recordCollection[2548].hasOwnProperty('artist'));
```
-Після `updateRecords(recordCollection, 1245, "tracks", "Addicted to Love")`, `tracks` повинен мати рядок `Addicted to Love` як останній елемент.
+After `updateRecords(recordCollection, 1245, "tracks", "Addicted to Love")`, `tracks` should have the string `Addicted to Love` as the last element.
```js
assert(
@@ -58,7 +65,7 @@ assert(
);
```
-Після `updateRecords(recordCollection, 2468, "tracks", "Free")`, `tracks` повинен мати рядок `1999` як перший елемент.
+After `updateRecords(recordCollection, 2468, "tracks", "Free")`, `tracks` should have the string `1999` as the first element.
```js
assert(
@@ -68,14 +75,14 @@ assert(
);
```
-Після `updateRecords(recordCollection, 2548, "tracks", "")` не потрібно налаштовувати `tracks`
+After `updateRecords(recordCollection, 2548, "tracks", "")`, `tracks` should not be set
```js
updateRecords(_recordCollection, 2548, 'tracks', '');
assert(!_recordCollection[2548].hasOwnProperty('tracks'));
```
-Після `updateRecords(recordCollection, 1245, "albumTitle", "Riptide")`, `albumTitle` повинен стати рядком `Riptide`
+After `updateRecords(recordCollection, 1245, "albumTitle", "Riptide")`, `albumTitle` should be the string `Riptide`
```js
assert(
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/es6/compare-scopes-of-the-var-and-let-keywords.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/es6/compare-scopes-of-the-var-and-let-keywords.md
index b8c833ce28e..f77dd482469 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/es6/compare-scopes-of-the-var-and-let-keywords.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/es6/compare-scopes-of-the-var-and-let-keywords.md
@@ -27,7 +27,7 @@ console.log(i);
У такому разі консоль показуватиме значення `[0, 1, 2]` та `3`.
-Якщо ключовим словом є `var`, то `i` оголошується глобально. Тому коли виконується `i++`, оновлюється глобальна змінна. Цей код схожий до наступного:
+Якщо ключовим словом є `var`, то `i` оголошується глобально. Тому коли виконується `i++`, оновлюється глобальна змінна. Такий код схожий до наступного:
```js
var numArray = [];
@@ -80,11 +80,11 @@ console.log(i);
Виправте код так, щоб `i`, оголошена в інструкції `if`, була окремою змінною від `i`, оголошеною у першому рядку функції. Не використовуйте у своєму коді ключове слово `var`.
-Це завдання створене для того, щоб показати відмінність між тим, як ключові слова `var` і `let` присвоюють область видимості оголошеній змінній. При програмуванні схожої функції краще використовувати різні назви для змінних, щоб уникнути плутанини.
+Це завдання створене для того, щоб показати відмінність між тим, як ключові слова `var` та `let` присвоюють область видимості оголошеній змінній. При програмуванні схожої функції краще використовувати різні назви для змінних, щоб уникнути плутанини.
# --hints--
-`var` повинне бути відсутнім у коді.
+`var` має бути відсутнім у коді.
```js
assert(!code.match(/var/g));
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/es6/create-an-export-fallback-with-export-default.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/es6/create-an-export-fallback-with-export-default.md
index 9c8af4f2a2e..c473faf647c 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/es6/create-an-export-fallback-with-export-default.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/es6/create-an-export-fallback-with-export-default.md
@@ -24,7 +24,7 @@ export default function(x, y) {
}
```
-Першою є іменована функція, а другою – анонімна.
+Першою є іменована функція, а другою — анонімна.
Оскільки `export default` використовується для оголошення резервного значення для модуля або файлу, лише одне значення може бути експортоване за замовчуванням у кожному модулі або файлі. Крім того, ви не можете використати `export default` з `var`, `let` чи `const`
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/es6/handle-a-rejected-promise-with-catch.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/es6/handle-a-rejected-promise-with-catch.md
index b2470e8f490..935affe7ae5 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/es6/handle-a-rejected-promise-with-catch.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/es6/handle-a-rejected-promise-with-catch.md
@@ -8,7 +8,7 @@ dashedName: handle-a-rejected-promise-with-catch
# --description--
-`catch` – це метод, який використовують тоді, коли проміс було відхилено. Він виконується одразу після виклику методу `reject`. Ось синтаксис:
+`catch` — це метод, який використовують тоді, коли проміс було відхилено. Він виконується одразу після виклику методу `reject`. Ось синтаксис:
```js
myPromise.catch(error => {
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/es6/mutate-an-array-declared-with-const.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/es6/mutate-an-array-declared-with-const.md
index e2ca50a5610..36718b205dc 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/es6/mutate-an-array-declared-with-const.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/es6/mutate-an-array-declared-with-const.md
@@ -14,7 +14,7 @@ dashedName: mutate-an-array-declared-with-const
Деякі розробники надають перевагу присвоєнню усіх змінних за допомогою `const`, якщо їм не потрібно повторно присвоїти значення. Тоді вони використовують `let`.
-Однак варто розуміти, що об'єкти (включно з масивами та функціями), присвоєні змінній за допомогою `const`, всеодно можна змінити. Оголошення `const` всього лиш запобігає повторному присвоєнню ідентифікатора змінної.
+Однак варто розуміти, що об’єкти (включно з масивами та функціями), присвоєні змінній за допомогою `const`, всеодно можна змінити. Оголошення `const` всього лиш запобігає повторному присвоєнню ідентифікатора змінної.
```js
const s = [5, 6, 7];
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/apply-functional-programming-to-convert-strings-to-url-slugs.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/apply-functional-programming-to-convert-strings-to-url-slugs.md
index 3fe0d2ec857..e8307d4f092 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/apply-functional-programming-to-convert-strings-to-url-slugs.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/apply-functional-programming-to-convert-strings-to-url-slugs.md
@@ -12,7 +12,7 @@ dashedName: apply-functional-programming-to-convert-strings-to-url-slugs
Об’єднаємо вивчене, щоб розв’язати практичне завдання.
-Багато сайтів керування вмістом (CMS) додають заголовки дописів до частини URL в цілях соціальних закладок. Наприклад, якщо ви напишете середній допис під назвою `Stop Using Reduce`, ймовірно, URL міститиме заголовок (`.../stop-using-reduce`). Можливо, ви вже помітили це на сайті freeCodeCamp.
+Багато сайтів керування вмістом (CMS) додають заголовки дописів до частини URL в цілях закладок. Наприклад, якщо ви напишете середній допис під назвою `Stop Using Reduce`, ймовірно, URL міститиме заголовок (`.../stop-using-reduce`). Можливо, ви вже помітили це на сайті freeCodeCamp.
# --instructions--
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/avoid-mutations-and-side-effects-using-functional-programming.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/avoid-mutations-and-side-effects-using-functional-programming.md
index f0175127c03..d997163879d 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/avoid-mutations-and-side-effects-using-functional-programming.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/avoid-mutations-and-side-effects-using-functional-programming.md
@@ -12,13 +12,13 @@ dashedName: avoid-mutations-and-side-effects-using-functional-programming
Це малий приклад набагато більшого шаблону: ви викликаєте функцію на змінній, масиві чи об’єкті, а функція змінює змінну чи щось в об’єкті.
-Один з основних принципів функційного програмування – нічого не змінювати. Зміни призводять до помилок. Легше уникнути помилок, знаючи, що ваші функції нічого не змінюють, включно з аргументами функцій чи будь-якою глобальною змінною.
+Один з основних принципів функційного програмування — нічого не змінювати. Зміни призводять до помилок. Легше уникнути помилок, знаючи, що ваші функції нічого не змінюють, включно з аргументами функцій чи будь-якою глобальною змінною.
У попередньому прикладі не було складних операцій, але метод `splice` змінив вихідний масив і видав помилку.
Пригадаємо, що у функційному програмуванні зміну називають
мутацією , а наслідок називають
побічним ефектом . В ідеалі функція повинна бути
чистою , тобто не спричиняти жодних побічних ефектів.
-Спробуємо опанувати цю дисципліну і не будемо змінювати будь-які змінні чи об'єкти в нашому коді.
+Спробуємо опанувати цю дисципліну і не будемо змінювати будь-які змінні чи об’єкти в нашому коді.
# --instructions--
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/combine-an-array-into-a-string-using-the-join-method.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/combine-an-array-into-a-string-using-the-join-method.md
index 9e0712a112e..74cc8ba19cb 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/combine-an-array-into-a-string-using-the-join-method.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/combine-an-array-into-a-string-using-the-join-method.md
@@ -8,7 +8,7 @@ dashedName: combine-an-array-into-a-string-using-the-join-method
# --description--
-Метод `join` використовують, щоб об'єднати елементи масиву та створити з них рядок. Він приймає потрібний аргумент для розділювача, який використовується для відокремлення елементів масиву у рядку.
+Метод `join` використовують, щоб об’єднати елементи масиву та створити з них рядок. Він приймає потрібний аргумент для розділювача, який використовується для відокремлення елементів масиву у рядку.
Ось приклад:
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/combine-two-arrays-using-the-concat-method.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/combine-two-arrays-using-the-concat-method.md
index f95ff13e915..2a507e20cb6 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/combine-two-arrays-using-the-concat-method.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/combine-two-arrays-using-the-concat-method.md
@@ -8,7 +8,7 @@ dashedName: combine-two-arrays-using-the-concat-method
# --description--
-
Конкатенація – це склеювання елементів. JavaScript пропонує метод `concat` для рядків та масивів, який працює однаково для обох. Щодо масивів: метод викликається на масиві, потім інший масив надається як аргумент до `concat` та додається до кінця першого масиву. Він повертає новий масив та не змінює жодного з вихідних масивів. Ось приклад:
+
Конкатенація — це склеювання елементів. JavaScript пропонує метод `concat` для рядків та масивів, який працює однаково для обох. Щодо масивів: метод викликається на масиві, потім інший масив надається як аргумент до `concat` та додається до кінця першого масиву. Він повертає новий масив та не змінює жодного з вихідних масивів. Ось приклад:
```js
[1, 2, 3].concat([4, 5, 6]);
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/implement-map-on-a-prototype.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/implement-map-on-a-prototype.md
index be2d7eaabee..02edc50bf2b 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/implement-map-on-a-prototype.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/implement-map-on-a-prototype.md
@@ -10,7 +10,7 @@ dashedName: implement-map-on-a-prototype
Як ви бачили з використання `Array.prototype.map()`, або просто `map()`, метод `map` повертає масив тієї ж довжини, що і той, на якому був викликаний. Він також не змінює вихідний масив, оскільки функція зворотного виклику цього не робить.
-Іншими словами, `map` – це чиста функція, де вихідні дані залежать від вхідних. Крім того, вона приймає іншу функцію як аргумент.
+Іншими словами, `map` — це чиста функція, де вихідні дані залежать від вхідних. Крім того, вона приймає іншу функцію як аргумент.
Ви можете багато дізнатись про метод `map`, якщо реалізуєте власну версію. Рекомендовано використовувати цикл `for` або `Array.prototype.forEach()`.
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/introduction-to-currying-and-partial-application.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/introduction-to-currying-and-partial-application.md
index bce316f0a56..72aa9627d61 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/introduction-to-currying-and-partial-application.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/introduction-to-currying-and-partial-application.md
@@ -8,7 +8,7 @@ dashedName: introduction-to-currying-and-partial-application
# --description--
-
Арність функції – це кількість необхідних аргументів.
Каррінгом функції називають перетворення функції з n-ною арністю у n-ну кількість функцій з арністю 1.
+
Арність функції — це кількість необхідних аргументів.
Каррінгом функції називають перетворення функції з n-ною арністю у n-ну кількість функцій з арністю 1.
Іншими словами, структура функції змінюється так, що вона приймає один аргумент, потім повертається інша функція, яка приймає наступний аргумент і так далі.
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/learn-about-functional-programming.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/learn-about-functional-programming.md
index b88ffe0ef5c..c4e06aa6563 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/learn-about-functional-programming.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/learn-about-functional-programming.md
@@ -8,7 +8,7 @@ dashedName: learn-about-functional-programming
# --description--
-Функційне програмування – це стиль програмування, у якому рішення є простими ізольованими функціями без будь-яких побічних ефектів, які виходять за межі області дії функції: `INPUT -> PROCESS -> OUTPUT`
+Функційне програмування — це стиль програмування, у якому рішення є простими ізольованими функціями без будь-яких побічних ефектів, які виходять за межі області дії функції: `INPUT -> PROCESS -> OUTPUT`
Функційне програмування передбачає:
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/pass-arguments-to-avoid-external-dependence-in-a-function.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/pass-arguments-to-avoid-external-dependence-in-a-function.md
index 12c6b1143d9..81f3088891a 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/pass-arguments-to-avoid-external-dependence-in-a-function.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/pass-arguments-to-avoid-external-dependence-in-a-function.md
@@ -12,7 +12,7 @@ dashedName: pass-arguments-to-avoid-external-dependence-in-a-function
Ми не змінили значення глобальної змінної, але функція `incrementer` не буде працювати без глобальної змінної `fixedValue`.
-Інший принцип функційного програмування – завжди оголошувати свої залежності відкрито. Це означає, що якщо функція залежить від змінної чи об’єкта, тоді ця змінна чи об’єкт передаються прямо до функції як аргумент.
+Інший принцип функційного програмування — завжди оголошувати свої залежності відкрито. Це означає, що якщо функція залежить від змінної чи об’єкта, тоді ця змінна чи об’єкт передаються прямо до функції як аргумент.
З цього принципу випливає декілька хороших наслідків. Цю функцію легше протестувати, ви знаєте її вхідні дані і вона ні від чого не залежить у вашій програмі.
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/refactor-global-variables-out-of-functions.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/refactor-global-variables-out-of-functions.md
index 174ada67969..6bd58293ff3 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/refactor-global-variables-out-of-functions.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/refactor-global-variables-out-of-functions.md
@@ -10,9 +10,9 @@ dashedName: refactor-global-variables-out-of-functions
Наразі ми розглянули два окремих принципи функційного програмування:
-1) Не змінюйте змінну чи об’єкт – створюйте нові змінні та об’єкти і, якщо потрібно, повертайте їх з функції. Підказка: якщо використати щось схоже до `const newArr = arrVar` (де `arrVar` є масивом), ви просто створите посилання на наявну змінну, а не копію. Тому, змінивши значення в `newArr`, зміниться значення в `arrVar`.
+1) Не змінюйте змінну чи об’єкт — створюйте нові змінні та об’єкти і, якщо потрібно, повертайте їх з функції. Підказка: якщо використати щось схоже до `const newArr = arrVar` (де `arrVar` є масивом), ви просто створите посилання на наявну змінну, а не копію. Тому, змінивши значення в `newArr`, зміниться значення в `arrVar`.
-2) Оголошення параметрів функції – будь-яке обчислення всередині функції залежить лише від аргументів, переданих до функції, а не від глобального об’єкта чи змінної.
+2) Оголошення параметрів функції — будь-яке обчислення всередині функції залежить лише від аргументів, переданих до функції, а не від глобального об’єкта чи змінної.
Додавання одиниці до числа не дуже цікаве, але ми можемо застосувати ці принципи при роботі з масивами або складнішими об’єктами.
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/remove-elements-from-an-array-using-slice-instead-of-splice.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/remove-elements-from-an-array-using-slice-instead-of-splice.md
index 49fe05c5394..2af4898596d 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/remove-elements-from-an-array-using-slice-instead-of-splice.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/remove-elements-from-an-array-using-slice-instead-of-splice.md
@@ -8,7 +8,7 @@ dashedName: remove-elements-from-an-array-using-slice-instead-of-splice
# --description--
-Часто при роботі з масивами потрібно видалити деякі елементи, а решту масиву зберегти. JavaScript пропонує метод `splice`, який приймає аргументи для індексу (де саме почати видаляти елементи), а тоді – їх кількість. Якщо другий аргумент не надано, то елементи видаляються до кінця за замовчуванням. Однак метод `splice` змінює вихідний масив, у якому викликається. Ось приклад:
+Часто при роботі з масивами потрібно видалити деякі елементи, а решту масиву зберегти. JavaScript пропонує метод `splice`, який приймає аргументи для індексу (де саме почати видаляти елементи), а тоді — їх кількість. Якщо другий аргумент не надано, то елементи видаляються до кінця за замовчуванням. Однак метод `splice` змінює вихідний масив, у якому викликається. Ось приклад:
```js
const cities = ["Chicago", "Delhi", "Islamabad", "London", "Berlin"];
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/return-a-sorted-array-without-changing-the-original-array.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/return-a-sorted-array-without-changing-the-original-array.md
index c58092a93ca..323c371220c 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/return-a-sorted-array-without-changing-the-original-array.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/return-a-sorted-array-without-changing-the-original-array.md
@@ -8,11 +8,11 @@ dashedName: return-a-sorted-array-without-changing-the-original-array
# --description--
-Побічним ефектом методу `sort` є те, що він змінює порядок елементів у вихідному масиві. Іншими словами, він змінює масив. Один зі способів уникнути цього – спочатку об’єднати порожній масив із масивом, який потрібно відсортувати (пам’ятайте, що `slice` та `concat` повертають новий масив), а потім запустити метод `sort`.
+Побічним ефектом методу `sort` є те, що він змінює порядок елементів у вихідному масиві. Іншими словами, він змінює масив. Один зі способів уникнути цього — спочатку об’єднати порожній масив із масивом, який потрібно відсортувати (пам’ятайте, що `slice` та `concat` повертають новий масив), а потім запустити метод `sort`.
# --instructions--
-Використайте метод `sort` у функції `nonMutatingSort`, щоб відсортувати елементи масиву у висхідному порядку. Функція повинна повернути новий масив і не змінювати змінну `globalArray`.
+Використайте метод `sort` у функції `nonMutatingSort`, щоб відсортувати елементи масиву у порядку зростання. Функція повинна повернути новий масив і не змінювати змінну `globalArray`.
# --hints--
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/sort-an-array-alphabetically-using-the-sort-method.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/sort-an-array-alphabetically-using-the-sort-method.md
index 80d4fd5332e..4366b823b73 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/sort-an-array-alphabetically-using-the-sort-method.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/sort-an-array-alphabetically-using-the-sort-method.md
@@ -36,7 +36,7 @@ reverseAlpha(['l', 'h', 'z', 'b', 's']);
Поверненим значенням буде `['z', 's', 'l', 'h', 'b']`.
-Метод сортування JavaScript за замовчуванням – це значення Unicode, що може надати несподівані результати. Тому краще надавати функцію зворотного виклику, щоб визначити порядок сортування об’єктів масиву. Коли надається така функція зворотного виклику (зазвичай називається `compareFunction`), елементи масиву впорядковуються відповідно до її поверненого значення. Якщо `compareFunction(a,b)` повертає значення двох елементів (`a` та `b`) менше за 0, то `a` йтиме перед `b`. Якщо `compareFunction(a,b)` повертає значення двох елементів (`a` та `b`) більше за 0, то `b` йтиме перед `a`. Якщо `compareFunction(a,b)` повертає значення двох елементів (`a` та `b`) рівне 0, то `a` та `b` залишаться без змін.
+Типовий метод сортування JavaScript полягає в сортуванні рядкових точок Unicode, що може видавати неочікувані результати. Тому краще надавати функцію зворотного виклику, щоб визначити порядок сортування об’єктів масиву. Коли надається така функція зворотного виклику (зазвичай називається `compareFunction`), елементи масиву впорядковуються відповідно до її поверненого значення. Якщо `compareFunction(a,b)` повертає значення двох елементів (`a` та `b`) менше за 0, то `a` йтиме перед `b`. Якщо `compareFunction(a,b)` повертає значення двох елементів (`a` та `b`) більше за 0, то `b` йтиме перед `a`. Якщо `compareFunction(a,b)` повертає значення двох елементів (`a` та `b`) рівне 0, то `a` та `b` залишаться без змін.
# --instructions--
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/split-a-string-into-an-array-using-the-split-method.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/split-a-string-into-an-array-using-the-split-method.md
index 40025768e1c..5ebe85c1886 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/split-a-string-into-an-array-using-the-split-method.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/split-a-string-into-an-array-using-the-split-method.md
@@ -10,7 +10,7 @@ dashedName: split-a-string-into-an-array-using-the-split-method
Метод `split` розділяє рядок на масив рядків. Він приймає потрібний аргумент для розділювача, який може бути символом для розбиття рядка чи регулярного виразу. Наприклад, якщо розділювач є пробілом, ви отримаєте масив слів, а якщо розділювачем є пустий рядок, ви отримаєте масив окремих рядків із символом.
-Ось два приклади, які розділяють один рядок пробілами, а інший – цифрами, використовуючи регулярний вираз:
+Ось два приклади, які розділяють один рядок пробілами, а інший — цифрами, використовуючи регулярний вираз:
```js
const str = "Hello World";
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/understand-functional-programming-terminology.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/understand-functional-programming-terminology.md
index 409ff7a093c..fa3f628efdf 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/understand-functional-programming-terminology.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/understand-functional-programming-terminology.md
@@ -14,7 +14,7 @@ dashedName: understand-functional-programming-terminology
Але спочатку розглянемо трішки функційної термінології:
-
Функція зворотного виклику (callback) – це функції, які передаються іншим функціям, щоб вирішити, коли та як їх викликати. Можливо, ви бачили, як деякі передаються іншим методам. Наприклад, у `filter` функція зворотного виклику повідомляє JavaScript критерії для фільтрації масиву.
+
Функції зворотного виклику (callback) — це функції, які передаються іншим функціям, щоб вирішити, коли та як їх викликати. Можливо, ви бачили, як деякі передаються іншим методам. Наприклад, у `filter` функція зворотного виклику повідомляє JavaScript критерії для фільтрації масиву.
Функції, які можна присвоїти до змінної, передати до іншої функції або навпаки повернути з іншої функції, як інше звичайне значення, називають функціями
першого класу . У JavaScript всі функції є функціями першого класу.
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/use-the-reduce-method-to-analyze-data.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/use-the-reduce-method-to-analyze-data.md
index 9414ca6c064..5f7382f8910 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/use-the-reduce-method-to-analyze-data.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/functional-programming/use-the-reduce-method-to-analyze-data.md
@@ -8,11 +8,11 @@ dashedName: use-the-reduce-method-to-analyze-data
# --description--
-`Array.prototype.reduce()`, або просто `reduce()` – найпоширеніша операція із масивами у JavaScript. Ви можете вирішити практично будь-яку проблему обробки масиву, використовуючи метод `reduce`.
+`Array.prototype.reduce()`, або просто `reduce()` — найпоширеніша операція із масивами у JavaScript. Ви можете вирішити практично будь-яку проблему обробки масиву, використовуючи метод `reduce`.
Метод `reduce` дозволяє використовувати загальні форми обробки масивів і можна сказати, що `filter` та `map` є похідними від `reduce`. Метод `reduce` перебирає кожен елемент у масиві та повертає єдине значення (тобто рядок, число, об’єкт, масив). Це досягається за допомогою функції зворотного виклику, яка відбувається на кожній ітерації.
-Функція зворотного виклику приймає чотири аргументи. Перший аргумент відомий як акумулятор, якому призначається повернене значення функції зворотного виклику з попередньої ітерації. Другим є елемент, який наразі опрацьовується. Третім є індекс цього елемента. Четвертий – це масив, на якому було викликано `reduce`.
+Функція зворотного виклику приймає чотири аргументи. Перший аргумент відомий як акумулятор, якому призначається повернене значення функції зворотного виклику з попередньої ітерації. Другим є елемент, який наразі опрацьовується. Третім є індекс цього елемента. Четвертий — це масив, на якому було викликано `reduce`.
Крім того, `reduce` має додатковий параметр, який приймає початкове значення акумулятора. Якщо цей другий параметр не використовується, то перша ітерація пропускається, а друга передається першому елементу масиву як акумулятор.
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/dna-pairing.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/dna-pairing.md
index 28f0bd1e1e9..1d51650668a 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/dna-pairing.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/dna-pairing.md
@@ -14,7 +14,7 @@ dashedName: dna-pairing
Наприклад, при введенні `GCG` поверніть `[["G", "C"], ["C","G"], ["G", "C"]]`
-Символ та його пара об'єднуються в масив, і всі масиви згруповані в один інкапсульований масив.
+Символ та його пара об’єднуються в масив, і всі масиви згруповані в один інкапсульований масив.
# --hints--
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/everything-be-true.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/everything-be-true.md
index 3500452fbaf..9904bab22a4 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/everything-be-true.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/everything-be-true.md
@@ -10,11 +10,11 @@ dashedName: everything-be-true
Перевірте, чи предикат (другий аргумент) є
істинним для усіх елементів колекції (перший аргумент).
-Іншими словами, вам дано колекцію масивів об'єктів. Предикат `pre` буде властивістю об'єкта і вам потрібно повернути `true`, якщо його значення `truthy` (істинне). В іншому випадку поверніть `false`.
+Іншими словами, вам надано колекцію масивів об’єктів. Предикат `pre` буде властивістю об’єкта і вам потрібно повернути `true`, якщо його значення `truthy` (істинне). В іншому випадку поверніть `false`.
-Значення `truthy` у JavaScript – це значення, які перетворюються на `true` при оцінці в булевому контексті.
+Значення `truthy` у JavaScript — це значення, які перетворюються на `true` при оцінці в булевому контексті.
-Пам'ятайте, ви можете отримати доступ до властивостей об'єкта, використовуючи точкову нотацію або дужкову нотацію (`[]`).
+Пам’ятайте, ви можете отримати доступ до властивостей об’єкта, використовуючи точкову нотацію або дужкову нотацію (`[]`).
# --hints--
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/make-a-person.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/make-a-person.md
index 739a89a4f85..9a893236d46 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/make-a-person.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/make-a-person.md
@@ -19,7 +19,7 @@ setLastName(last)
setFullName(firstAndLast)
```
-Запустіть тести, щоб побачити очікуваний вивід для кожного методу. Методи, що приймають аргумент, повинні приймати лише один аргумент і це повинен бути рядок. Ці методи повинні бути єдиними доступними засобами для взаємодії з об'єктом.
+Запустіть тести, щоб побачити очікуваний вивід для кожного методу. Методи, що приймають аргумент, повинні приймати лише один аргумент і це повинен бути рядок. Ці методи повинні бути єдиними доступними засобами для взаємодії з об’єктом.
# --hints--
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/map-the-debris.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/map-the-debris.md
index dae99fd1b9e..ddeaff550ef 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/map-the-debris.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/map-the-debris.md
@@ -12,18 +12,18 @@ dashedName: map-the-debris
$$ T = 2 \pi \sqrt{\frac{a^{3}}{\mu}} $$
-- $a$ – велика піввісь орбіти
-- $μ = GM$ – стандартний гравітаційний параметр
-- $G$ – гравітаційна стала,
-- $M$ – маса масивнішого тіла.
+- $a$ — велика піввісь орбіти
+- $μ = GM$ — стандартний гравітаційний параметр
+- $G$ — гравітаційна стала,
+- $M$ — маса масивнішого тіла.
Поверніть новий масив, який трансформує середню висоту елементів у їхні орбітальні періоди (у секундах).
-Масив міститиме об'єкти у форматі `{name: 'name', avgAlt: avgAlt}`.
+Масив міститиме об’єкти у форматі `{name: 'name', avgAlt: avgAlt}`.
-Значення потрібно округлити до найближчого цілого числа. Тіло, навколо якого потрібно обертатися, – Земля.
+Значення потрібно округлити до найближчого цілого числа. Тіло, навколо якого потрібно обертатися, — Земля.
-Радіус Землі становить 6367.4447 кілометрів, а значення GM Землі – 398600.4418 км
3 с
-2 .
+Радіус Землі становить 6367.4447 кілометрів, а значення GM Землі — 398600.4418 км
3 с
-2 .
# --hints--
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/pig-latin.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/pig-latin.md
index aa9c0a22fd5..18cce1b01fe 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/pig-latin.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/pig-latin.md
@@ -8,7 +8,7 @@ dashedName: pig-latin
# --description--
-Поросяча латина – це спосіб шифрування англійських слів. Правила такі:
+Поросяча латина — це спосіб шифрування англійських слів. Правила такі:
\- Якщо слово починається з приголосного звуку, то перший приголосний або сполучення приголосних переміщуються в кінець слова і додається `ay`.
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/seek-and-destroy.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/seek-and-destroy.md
index 1f3e3034d29..41db2b8773e 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/seek-and-destroy.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/seek-and-destroy.md
@@ -10,7 +10,7 @@ dashedName: seek-and-destroy
Вам буде надано початковий масив (перший аргумент у функції `destroyer`), який супроводжується одним або більше аргументами. Видаліть всі елементи з початкового масиву, які мають таке ж значення, як ці аргументи.
-**Примітка:** потрібно використати об'єкт `arguments`.
+**Примітка:** потрібно використати об’єкт `arguments`.
# --hints--
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/smallest-common-multiple.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/smallest-common-multiple.md
index 7efe4bc65a5..3793e8af609 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/smallest-common-multiple.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/smallest-common-multiple.md
@@ -10,7 +10,7 @@ dashedName: smallest-common-multiple
Знайдіть найменше спільне кратне заданих параметрів, яке можна поділити на обидва з них, а також на всі послідовні числа в діапазоні між цими параметрами.
-Діапазоном буде масив з двох чисел, які необов'язково будуть у числовому порядку.
+Діапазоном буде масив з двох чисел, які необов’язково будуть у числовому порядку.
Наприклад, якщо дано 1 і 3, знайдіть найменше спільне кратне обох чисел (1 і 3), яке рівно ділиться на всі числа *між* 1 і 3. Тут відповіддю буде 6.
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/sum-all-odd-fibonacci-numbers.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/sum-all-odd-fibonacci-numbers.md
index 4bfa33ebf00..8993c7cfc0f 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/sum-all-odd-fibonacci-numbers.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/sum-all-odd-fibonacci-numbers.md
@@ -12,7 +12,7 @@ dashedName: sum-all-odd-fibonacci-numbers
Першими двома числами в послідовності Фібоначчі є 0 та 1. Кожне додаткове число у послідовності є сумою двох попередніх чисел. Першими сімома числами в послідовності Фібоначчі є 1, 1, 2, 3, 5 і 8.
-Наприклад, `sumFibs(10)` має повертати `10`, оскільки всі непарні числа Фібоначчі, які менші або дорівнюють `10` – це 1, 1, 3 і 5.
+Наприклад, `sumFibs(10)` має повертати `10`, оскільки всі непарні числа Фібоначчі, які менші або дорівнюють `10` — це 1, 1, 3 і 5.
# --hints--
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/sum-all-primes.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/sum-all-primes.md
index 9340b275c59..244b52ab450 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/sum-all-primes.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/sum-all-primes.md
@@ -8,7 +8,7 @@ dashedName: sum-all-primes
# --description--
-
Просте число – це ціле число, яке більше за 1 та має два дільники: 1 і саме число. Наприклад, 2 є простим числом, оскільки воно ділиться лише на 1 і 2. І навпаки, 4 не є простим числом, оскільки воно ділиться на 1, 2 і 4.
+
Просте число — це ціле число, яке більше за 1 та має два дільники: 1 і саме число. Наприклад, 2 є простим числом, оскільки воно ділиться лише на 1 і 2. І навпаки, 4 не є простим числом, оскільки воно ділиться на 1, 2 і 4.
Перепишіть `sumPrimes` таким чином, щоб поверталася сума всіх простих чисел, які менші або дорівнюють num.
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/wherefore-art-thou.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/wherefore-art-thou.md
index 17f32cae5b6..1204a366101 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/wherefore-art-thou.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/wherefore-art-thou.md
@@ -8,9 +8,9 @@ dashedName: wherefore-art-thou
# --description--
-Напишіть функцію, яка проглядає масив об'єктів (перший аргумент) і повертає масив усіх об'єктів, які мають однакові пари імен та значень (другий аргумент). Кожна пара імен та значень вихідного об'єкта повинна бути в об'єкті з колекції, якщо він необхідний у повернутому масиві.
+Напишіть функцію, яка проглядає масив об’єктів (перший аргумент) і повертає масив усіх об’єктів, які мають однакові пари імен та значень (другий аргумент). Кожна пара імен та значень вихідного об'єкта повинна бути в об’єкті з колекції, якщо він необхідний у повернутому масиві.
-Наприклад, якщо першим аргументом є `[{ first: "Romeo", last: "Montague" }, { first: "Mercutio", last: null }, { first: "Tybalt", last: "Capulet" }]` та другим аргументом є `{ last: "Capulet" }`, тоді потрібно повернути третій об'єкт з масиву (перший аргумент), оскільки він містить ім'я та його значення, яке було передане до другого аргументу.
+Наприклад, якщо першим аргументом є `[{ first: "Romeo", last: "Montague" }, { first: "Mercutio", last: null }, { first: "Tybalt", last: "Capulet" }]` та другим аргументом є `{ last: "Capulet" }`, тоді потрібно повернути третій об’єкт з масиву (перший аргумент), оскільки він містить ім’я та його значення, яке було передане до другого аргументу.
# --hints--
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/cash-register.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/cash-register.md
index 410cbb82015..fa040db227a 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/cash-register.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/cash-register.md
@@ -10,13 +10,13 @@ dashedName: cash-register
Розробіть функцію касового апарату `checkCashRegister()`, яка приймає ціну покупки як перший аргумент (`price`), оплату як другий аргумент (`cash`) та суму готівки в касі як третій аргумент (`cid`).
-`cid` – це 2D масив, який містить список доступного обігу.
+`cid` — це 2D масив, який містить список доступного обігу.
Функція `checkCashRegister()` завжди повинна повертати об’єкт з ключем `status` та ключем `change`.
Поверніть `{status: "INSUFFICIENT_FUNDS", change: []}`, якщо сума готівки в касі менша за здачу, або ви не можете віддати здачу.
-Поверніть `{status: "CLOSED", change: [...]}` з сумою в касі як значення ключа `change`, якщо вона дорівнює здачі.
+Поверніть `{status: "CLOSED", change: [...]}` з сумою в касі як значення ключа `change`, якщо воно дорівнює здачі.
В іншому випадку, поверніть `{status: "OPEN", change: [...]}` зі здачею в монетах і банкнотах, в порядку від найбільшої до найменшої, як значення ключа `change`.
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/palindrome-checker.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/palindrome-checker.md
index 25bde46ddba..bff90cb10c5 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/palindrome-checker.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/palindrome-checker.md
@@ -10,7 +10,7 @@ dashedName: palindrome-checker
Поверніть `true`, якщо заданий рядок є паліндромом. В іншому випадку, поверніть `false`.
-
Паліндром – це слово чи речення, що однаково пишеться в обох напрямках (зліва направо та справа наліво), незважаючи на розділові знаки, регістр чи пробіли.
+
Паліндром — це слово чи речення, що однаково пишеться в обох напрямках (зліва направо та справа наліво), незважаючи на розділові знаки, велику/малу літеру чи пробіли.
**Примітка:** вам потрібно прибрати **всі неалфавітні символи** (розділові знаки, пробіли та символи) і написати весь текст одинаково (великими або малими літерами) для перевірки паліндромів.
diff --git a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/telephone-number-validator.md b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/telephone-number-validator.md
index 068b22019e4..add4ce8c44f 100644
--- a/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/telephone-number-validator.md
+++ b/curriculum/challenges/ukrainian/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/telephone-number-validator.md
@@ -14,7 +14,7 @@ dashedName: telephone-number-validator
555-555-5555 (555)555-5555 (555) 555-5555 555 555 5555 5555555555 1 555 555 5555
-У цьому завданні вам буде надано рядок (наприклад, `800-692-7753` або `8oo-six427676;laskdjf`). Ваше завдання – підтвердити або відхилити мобільний номер США на основі будь-якої комбінації форматів, наданих вище. Код зони нумерації є обов’язковим. Якщо надано телефонний код країни, то ви повинні підтвердити, що телефонним кодом країни є `1`. Поверніть `true`, якщо рядок є дійсним мобільним номером США; в іншому випадку поверніть `false`.
+У цьому завданні вам буде надано рядок (наприклад, `800-692-7753` або `8oo-six427676;laskdjf`). Ваше завдання — підтвердити або відхилити мобільний номер США на основі будь-якої комбінації форматів, наданих вище. Код зони нумерації є обов’язковим. Якщо надано телефонний код країни, то ви повинні підтвердити, що телефонним кодом країни є `1`. Поверніть `true`, якщо рядок є дійсним мобільним номером США; в іншому випадку поверніть `false`.
# --hints--
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/data-visualization-page-rank.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/data-visualization-page-rank.md
index 8f6b8abb3c7..3d9f31b96c6 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/data-visualization-page-rank.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/data-visualization-page-rank.md
@@ -18,7 +18,7 @@ dashedName: data-visualization-page-rank
## --answers--
-Він визначає, які сторінки найбільш пов'язані.
+Він визначає, які сторінки найбільш пов’язані.
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/introduction-hardware-achitecture.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/introduction-hardware-achitecture.md
index 3102e51480c..d473f9825bb 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/introduction-hardware-achitecture.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/introduction-hardware-achitecture.md
@@ -22,7 +22,7 @@ dashedName: introduction-hardware-architecture
---
-Пам'ять.
+Пам’ять.
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/networking-using-urllib-in-python.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/networking-using-urllib-in-python.md
index ff448f1682e..7479f47bbc9 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/networking-using-urllib-in-python.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/networking-using-urllib-in-python.md
@@ -25,15 +25,15 @@ for line in fhand:
## --answers--
-Лише зміст "romeo.txt".
+Лише зміст «romeo.txt».
---
-Верхній колонтитул і зміст "romeo.txt".
+Верхній колонтитул і зміст «romeo.txt».
---
-Верхній та нижній колонтитули, зміст "romeo.txt".
+Верхній та нижній колонтитули, зміст «romeo.txt».
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/networking-write-a-web-browser.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/networking-write-a-web-browser.md
index ad447d801aa..36f0671de57 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/networking-write-a-web-browser.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/networking-write-a-web-browser.md
@@ -38,7 +38,7 @@ mysock.close()
---
-Простий e-mail клієнт.
+Простий клієнт пошти.
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/object-lifecycle.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/object-lifecycle.md
index 2cba78ae199..cee3a24d797 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/object-lifecycle.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/object-lifecycle.md
@@ -1,6 +1,6 @@
---
id: 5e7b9f170b6c005b0e76f087
-title: Життєвий цикл об'єкта
+title: Життєвий цикл об’єкта
challengeType: 11
videoId: p1r3h_AMMIM
bilibiliIds:
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/objects-a-sample-class.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/objects-a-sample-class.md
index db70a195a18..58d03c7cdb0 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/objects-a-sample-class.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/objects-a-sample-class.md
@@ -1,6 +1,6 @@
---
id: 5e7b9f160b6c005b0e76f086
-title: 'Об''єкти: приклад класу'
+title: 'Об’єкти: приклад класу'
challengeType: 11
videoId: FiABKEuaSJ8
bilibiliIds:
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/objects-inheritance.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/objects-inheritance.md
index fb86a476217..7219646054b 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/objects-inheritance.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/objects-inheritance.md
@@ -1,6 +1,6 @@
---
id: 5e7b9f170b6c005b0e76f088
-title: 'Об''єкти: успадкування'
+title: 'Об’єкти: успадкування'
challengeType: 11
videoId: FBL3alYrxRM
bilibiliIds:
@@ -14,7 +14,7 @@ dashedName: objects-inheritance
## --text--
-Що таке успадкування в об'єктно-орієнтованому програмуванні?
+Що таке успадкування в об’єктноорієнтованому програмуванні?
## --answers--
@@ -30,7 +30,7 @@ dashedName: objects-inheritance
---
-Метод, який викликається в момент, коли клас використано для побудови об'єкту.
+Метод, який викликається в момент, коли клас використано для побудови об’єкту.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/python-dictionaries.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/python-dictionaries.md
index 57af6b72568..05ddbb5707e 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/python-dictionaries.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/python-dictionaries.md
@@ -1,6 +1,6 @@
---
id: 5e7b9f090b6c005b0e76f067
-title: Словники Python
+title: Словники в Python
challengeType: 11
videoId: dnzvfimrRMg
bilibiliIds:
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/python-objects.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/python-objects.md
index e38aa46e6c9..a19dfe0f17d 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/python-objects.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/python-objects.md
@@ -1,6 +1,6 @@
---
id: 5e7b9f160b6c005b0e76f085
-title: Об'єкти в Python
+title: Об’єкти в Python
challengeType: 11
videoId: uJxGeTYy0us
bilibiliIds:
@@ -14,23 +14,23 @@ dashedName: python-objects
## --text--
-Яке з наведених тверджень НЕ є правильним для об'єктів у Python?
+Яке з наведених тверджень НЕ є правильним для об’єктів у Python?
## --answers--
-Об'єкти створюються та використовуються.
+Об’єкти створюються та використовуються.
---
-Об'єкти – це біти коду та дані.
+Об’єкти — це біти коду та дані.
---
-Об'єкти приховують деталі.
+Об’єкти приховують деталі.
---
-Об'єкти – це один з п'яти стандартних типів даних.
+Об‘єкти — це один з п’яти стандартних типів даних.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/relational-database-design.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/relational-database-design.md
index b24a7f39e43..84b0aab6855 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/relational-database-design.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/relational-database-design.md
@@ -1,6 +1,6 @@
---
id: 5e7b9f180b6c005b0e76f08c
-title: Проектування реляційних баз даних
+title: Проєктування реляційних баз даних
challengeType: 11
videoId: AqdfbrpkbHk
bilibiliIds:
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/relational-databases-join-operation.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/relational-databases-join-operation.md
index 31c15f599e0..d4c944a4d51 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/relational-databases-join-operation.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/relational-databases-join-operation.md
@@ -26,7 +26,7 @@ dashedName: relational-databases-join-operation
---
-Воно вказує на те, як саме таблиці мають бути об'єднані.
+Воно вказує на те, як саме таблиці мають бути об’єднані.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/representing-relationships-in-a-relational-database.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/representing-relationships-in-a-relational-database.md
index 3ff23a3280a..209164c626e 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/representing-relationships-in-a-relational-database.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/representing-relationships-in-a-relational-database.md
@@ -14,7 +14,7 @@ dashedName: representing-relationships-in-a-relational-database
## --text--
-Що таке foreign key?
+Що таке іноземний ключ?
## --answers--
@@ -26,7 +26,7 @@ dashedName: representing-relationships-in-a-relational-database
---
-Число, яке вказує на первинний ключ від пов'язаного рядка в іншій таблиці.
+Число, яке вказує на первинний ключ від пов’язаного рядка в іншій таблиці.
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/visualizing-data-with-python.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/visualizing-data-with-python.md
index b4a6bea4941..4f6b668046d 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/visualizing-data-with-python.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/visualizing-data-with-python.md
@@ -30,7 +30,7 @@ dashedName: visualizing-data-with-python
---
-запам'ятовані
+запам’ятовані
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/web-services-api-rate-limiting-and-security.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/web-services-api-rate-limiting-and-security.md
index 0630ca85ceb..c18e74b1e65 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/web-services-api-rate-limiting-and-security.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/web-services-api-rate-limiting-and-security.md
@@ -30,7 +30,7 @@ dashedName: web-services-api-rate-limiting-and-security
## --answers--
-ім'я користувача
+ім’я користувача
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/web-services-service-oriented-approach.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/web-services-service-oriented-approach.md
index 248542f491c..a3c6c233c06 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/web-services-service-oriented-approach.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/python-for-everybody/web-services-service-oriented-approach.md
@@ -18,7 +18,7 @@ dashedName: web-services-service-oriented-approach
## --answers--
-Розповсюджені між багатьма комп'ютерними системами, які поєднані між собою через інтернет або внутрішню мережу.
+Розповсюджені між багатьма комп’ютерними системами, які поєднані між собою через інтернет або внутрішню мережу.
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/scientific-computing-with-python-projects/budget-app.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/scientific-computing-with-python-projects/budget-app.md
index 6301e20bbe6..4d61c096ec9 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/scientific-computing-with-python-projects/budget-app.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/scientific-computing-with-python-projects/budget-app.md
@@ -17,15 +17,15 @@ dashedName: budget-app
# --instructions--
-Завершіть клас `Category` у `budget.py`. Він повинен опрацьовувати об'єкти, базуючись на різних категоріях, наприклад *їжа*, *одяг* та *розваги*. Коли об'єкти створені, вони передаються в назву категорії. Клас повинен мати поле класу під назвою `ledger`, яке є списком. Клас також повинен містити наступні методи:
+Завершіть клас `Category` у `budget.py`. Він повинен опрацьовувати об’єкти, базуючись на різних категоріях (наприклад, *їжа*, *одяг* та *розваги*). Коли об’єкти створені, вони передаються до назви категорії. Клас повинен мати поле класу під назвою `ledger`, яке є списком. Клас також повинен містити наступні методи:
-- Метод `deposit`, що приймає суму та опис. Якщо жодного опису не дано, то він автоматично стає порожнім рядком. Цей метод повинен додавати об'єкти до списку ledger у вигляді `{"amount": amount, "description": description}`.
-- Метод `withdraw` схожий до методу `deposit`, але сума, яку він передає, повинна зберігатися у списку як від'ємне число. Якщо недостатньо коштів, то нічого додавати не потрібно. Цей метод повинен повертати `True`, якщо зняття дійсне, а в іншому випадку повертати `False`.
+- Метод `deposit`, що приймає суму та опис. Якщо жодного опису не дано, то він автоматично стає порожнім рядком. Цей метод повинен додавати об’єкти до списку ledger у вигляді `{"amount": amount, "description": description}`.
+- Метод `withdraw` схожий до методу `deposit`, але сума, яку він передає, повинна зберігатися у списку як від’ємне число. Якщо недостатньо коштів, то нічого додавати не потрібно. Цей метод повинен повертати `True`, якщо зняття дійсне, а в іншому випадку повертати `False`.
- Метод `get_balance`, що повертає поточний баланс категорії бюджету на основі депозитів і зняття.
-- Метод `transfer`, що приймає суму або іншу бюджетну категорію як аргументи. Цей метод повинен додавати виведення суми та опис "Transfer to [Destination Budget Category]" (перенести до [категорія]). Потім він повинен додати депозит до іншої категорії, що містить суму та опис "Transfer from [Source Budget Category]" (передача з [категорія]). Якщо недостатньо коштів, то нічого додавати не потрібно. Цей метод повинен повертати `True`, якщо переказ дійсний, а в іншому випадку повертати `False`.
+- Метод `transfer`, що приймає суму або іншу бюджетну категорію як аргументи. Цей метод повинен додавати виведення суми та опис «Transfer to [Destination Budget Category]» (перенести до [категорія]). Потім він повинен додати депозит до іншої категорії, що містить суму та опис «Transfer from [Source Budget Category]» (перенести з [категорія]). Якщо недостатньо коштів, то нічого додавати не потрібно. Цей метод повинен повертати `True`, якщо переказ дійсний, а в іншому випадку повертати `False`.
- Метод `check_funds`, що приймає суму як аргумент. Він повертає `False`, якщо сума більша за баланс бюджетної категорії, а в іншому випадку повертає `True`. Цей метод варто використовувати обом методам `withdraw` та `transfer`.
-Якщо бюджетний об'єкт надрукований, він повинен відображатися:
+Якщо бюджет надрукований, то повинні відображатися:
- Рядок заголовка із 30 символів, де назва категорії знаходиться у центрі рядка символів `*`.
- Список елементів у записі. Кожен рядок повинен показувати опис і суму. Повинні зображатися перші 23 символи опису, а потім сума. Сума повинна бути вирівняною за правим краєм, містити два десяткові знаки та відображати максимум 7 символів.
@@ -44,7 +44,7 @@ Total: 923.96
Окрім класу `Category` створіть функцію під назвою `create_spend_chart` (за межами класу), яка приймає список категорій як аргумент. Вона повинна повертати рядок зі стовпчиковою діаграмою.
-Діаграма повинна показувати відсотки, витрачені в кожній категорії, переданій до функції. Відсоток витраченого повинен бути розрахований лише за рахунок зняття, але не з депозитів. Внизу лівої частини графіку повинні бути мітки 0 - 100. Стовпчики у стовпчиковій діаграмі повинні бути створені із символу «o». Висота кожного стовпчика повинна бути округлена до найближчого 10. Горизонтальна лінія під стовпчиками повинна розташовуватись в двох пробілах від кінцевого стовпчика. Назва кожної категорії повинна бути написана вертикально під стовпчиком. Вгорі повинен бути заголовок "Percentage spent by category" (відсоток, витрачений у категорії).
+Діаграма повинна показувати відсотки, витрачені в кожній категорії, переданій до функції. Відсоток витраченого повинен бути розрахований лише за рахунок зняття, але не з депозитів. Внизу лівої частини графіку повинні бути мітки 0 - 100. Стовпчики у стовпчиковій діаграмі повинні бути створені із символу «o». Висота кожного стовпчика повинна бути округлена до найближчого 10. Горизонтальна лінія під стовпчиками повинна розташовуватись в двох пробілах від кінцевого стовпчика. Назва кожної категорії повинна бути написана вертикально під стовпчиком. Вгорі повинен бути заголовок «Percentage spent by category» (відсоток, витрачений у категорії).
Ця функція буде тестуватися чотирма категоріями.
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/scientific-computing-with-python-projects/polygon-area-calculator.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/scientific-computing-with-python-projects/polygon-area-calculator.md
index 3e292385064..38ab47edf00 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/scientific-computing-with-python-projects/polygon-area-calculator.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/scientific-computing-with-python-projects/polygon-area-calculator.md
@@ -17,25 +17,25 @@ dashedName: polygon-area-calculator
# --instructions--
-У цьому проєкті ви будете використовувати об'єктно-орієнтоване програмування, щоб створити класи Rectangle (прямокутник) та Square (квадрат). Клас Square повинен бути підкласом до Rectangle і наслідувати його методи та атрибути.
+У цьому проєкті ви будете використовувати об’єктноорієнтоване програмування, щоб створити класи Rectangle (прямокутник) та Square (квадрат). Клас Square повинен бути підкласом до Rectangle і наслідувати його методи та атрибути.
## Клас Rectangle
-При створенні об'єкту Rectangle ви повинні ініціалізувати його, використовуючи атрибути `width` та `height`. Клас також повинен містити наступні методи:
+При створенні об’єкту Rectangle ви повинні ініціалізувати його, використовуючи атрибути `width` та `height`. Клас також повинен містити наступні методи:
- `set_width`
- `set_height`
- `get_area`: повертає площу (`width * height`)
- `get_perimeter`: повертає периметр (`2 * width + 2 * height`)
- `get_diagonal`: повертає діагональ (`(width ** 2 + height ** 2) ** .5`)
-- `get_picture`: повертає рядок, який представляє фігуру лініями "\*". Кількість ліній повинна дорівнювати висоті, а кількість "\*" у кожному рядку повинна дорівнювати ширині. Наприкінці кожного рядка має бути новий рядок (`\n`). Якщо ширина або висота більші за 50, то повинен повернутись рядок "Too big for picture." (завеликий для зображення).
+- `get_picture`: повертає рядок, який представляє фігуру лініями «\*». Кількість ліній повинна дорівнювати висоті, а кількість «\*» у кожному рядку повинна дорівнювати ширині. Наприкінці кожного рядка має бути новий рядок (`\n`). Якщо ширина або висота більші за 50, то повинен повернутись рядок «Too big for picture.» (завеликий для зображення).
- `get_amount_inside`: приймає іншу фігуру (квадрат чи трикутник) як аргумент. Повертає ту кількість разів, скільки передана фігура може поміститися у фігурі (без обертання). Наприклад, прямокутник з шириною 4 і висотою 8 може вмістити два квадрати зі сторонами 4.
Додатково, якщо екземпляр Rectangle представлений як рядок, він має виглядати так: `Rectangle(width=5, height=10)`
## Клас Square
-Клас Square має бути підкласом Rectangle. Коли ви створюєте об'єкт Square, передається довжина однієї сторони. Метод `__init__` має зберігати довжину сторони в атрибутах `width` та `height` з класу Rectangle.
+Клас Square має бути підкласом Rectangle. Коли ви створюєте об’єкт Square, передається довжина однієї сторони. Метод `__init__` має зберігати довжину сторони в атрибутах `width` та `height` з класу Rectangle.
Клас Square повинен мати доступ до методів класу Rectange, але також повинен містити метод `set_side`. Якщо екземпляр Square представлений у вигляді рядка, то це має виглядати так: `Square(side=9)`
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/scientific-computing-with-python-projects/probability-calculator.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/scientific-computing-with-python-projects/probability-calculator.md
index 99d244845b9..47b4b04f8fe 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/scientific-computing-with-python-projects/probability-calculator.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/scientific-computing-with-python-projects/probability-calculator.md
@@ -17,11 +17,11 @@ dashedName: probability-calculator
# --instructions--
-Уявімо, що у капелюсі лежить 5 синіх, 4 червоні та 2 зелені кульки. Яка ймовірність того, що з 4 кульок, які ви витягнете, принаймні 1 буде червоною та 2 зеленими? І хоча можливо прорахувати вірогідність за допомогою вищої математики, легше буде написати програму для виконання великої кількості експериментів для оцінки приблизної вірогідності.
+Уявімо, що у капелюсі лежить 5 синіх, 4 червоні та 2 зелені кульки. Яка вірогідність того, що з 4 кульок, які ви витягнете, принаймні 1 буде червоною та 2 зеленими? І хоча можливо прорахувати вірогідність за допомогою вищої математики, легше буде написати програму для виконання великої кількості експериментів для оцінки приблизної вірогідності.
У цьому проєкті напишіть програму, яка визначатиме вірогідність випадкового діставання певних кульок із капелюха.
-Спершу створіть клас `Hat` в `prob_calculator.py`. Клас має взяти змінну кількість аргументів, яка вточнюватиме кількість кульок усіх кольорів із капелюха. Наприклад, об'єкт класу можна створити такими способами:
+Спершу створіть клас `Hat` в `prob_calculator.py`. Клас має взяти змінну кількість аргументів, яка вточнюватиме кількість кульок усіх кольорів із капелюха. Наприклад, об’єкт класу можна створити такими способами:
```py
hat1 = Hat(yellow=3, blue=2, green=6)
@@ -29,20 +29,20 @@ hat2 = Hat(red=5, orange=4)
hat3 = Hat(red=5, orange=4, black=1, blue=0, pink=2, striped=9)
```
-Капелюх завжди створюється з принаймні однією кулькою. Аргументи, які передаються в об'єкт-капелюх, під час створення мають конвертуватися в поле класу `contents`. `contents` має бути списком рядків, де один елемент дорівнює кожній кульці у капелюсі. Кожний елемент списку має бути назвою кольору, яка позначає кульку певного кольору. Наприклад, якщо ваш капелюх `{"red": 2, "blue": 1}`, то `contents` має бути `["red", "red", "blue"]`.
+Капелюх завжди створюється з принаймні однією кулькою. Аргументи, які передаються в об’єкт-капелюх, під час створення мають конвертуватися в поле класу `contents`. `contents` має бути списком рядків, де один елемент дорівнює кожній кульці у капелюсі. Кожний елемент списку має бути назвою кольору, яка позначає кульку певного кольору. Наприклад, якщо ваш капелюх `{"red": 2, "blue": 1}`, то `contents` має бути `["red", "red", "blue"]`.
Клас `Hat` повинен мати метод `draw`, який приймає аргумент з позначенням кількості кульок, які можна витягти з капелюха. Цей метод має випадково витягати кульки з `contents` та повертати ці кульки списком рядків. Кульки не повинні повертатися до капелюха після того, як їх витягли (як в експерименті з урною без заміни). Якщо кількість кульок, яку треба витягти, перевищує доступну кількість, поверніть усі кульки.
Потім створіть функцію `experiment` в `prob_calculator.py` (не в класі `Hat`). Ця функція повинна приймати наступні аргументи:
-- `hat`: об'єкт-капелюх з кульками, який має бути скопійований у функцію.
-- `expected_balls`: об'єкт, який вказує на точну кількість кульок, котру треба вийняти з капелюха для експерименту. Наприклад, щоб визначити вірогідність того, що ви витягнете 2 сині та 1 червону кульки з капелюха, встановіть `expected_balls` на `{"blue":2, "red":1}`.
+- `hat`: об’єкт-капелюх з кульками, що потрібно скопіювати у функцію.
+- `expected_balls`: об’єкт, який вказує на точну кількість кульок, які треба вийняти з капелюха для експерименту. Наприклад, щоб визначити вірогідність того, що ви витягнете 2 сині та 1 червону кульки з капелюха, встановіть `expected_balls` на `{"blue":2, "red":1}`.
- `num_balls_drawn`: кількість кульок, які треба витягти з капелюха в кожному експерименті.
- `num_experiments`: кількість експериментів, які треба провести. (Чим більше експериментів було проведено, тим точнішою буде вірогідність.)
Функція `experiment` повинна повертати вірогідність.
-Допустимо, якщо ви хочете визначити вірогідність витягти щонайменше 2 червоні кульки та одну зелену, коли витягаєте п'ять кульок з капелюха, де лежить шість чорних, чотири червоні та три зелені кульки. Для цього вам треба виконати `N` експериментів, порахувати скільки `M` разів ви можете витягти принаймні дві червоні кульки та одну зелену кульку та вирахувати вірогідність як `M/N`. Кожен експеримент складається з капелюха (з певними кульками), витягування декількох кульок та перевірки, чи ви витягли необхідні кульки.
+Допустимо, якщо ви хочете визначити вірогідність витягти щонайменше 2 червоні кульки та одну зелену, коли витягаєте п’ять кульок з капелюха, де лежить шість чорних, чотири червоні та три зелені кульки. Для цього вам треба виконати `N` експериментів, порахувати скільки `M` разів ви можете витягти принаймні дві червоні кульки та одну зелену кульку та вирахувати вірогідність як `M/N`. Кожен експеримент складається з капелюха (з певними кульками), витягування декількох кульок та перевірки, чи ви витягли необхідні кульки.
Ось так ви можете викликати функцію `experiment`, базуючись на прикладі зверху з 2000 експериментами:
@@ -74,7 +74,7 @@ probability = experiment(hat=hat,
# --hints--
-Проєкт повинен правильно вираховувати ймовірність та пройти всі тести.
+Проєкт повинен правильно вираховувати вірогідність та пройти всі тести.
```js
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/scientific-computing-with-python-projects/time-calculator.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/scientific-computing-with-python-projects/time-calculator.md
index c41a55b5059..aefb5afaeab 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/scientific-computing-with-python-projects/time-calculator.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/scientific-computing-with-python-projects/time-calculator.md
@@ -16,15 +16,15 @@ dashedName: time-calculator
# --instructions--
-Напишіть функцію під назвою `add_time`, яка приймає два обов'язкових параметри та один необов'язковий параметр:
+Напишіть функцію під назвою `add_time`, яка приймає два обов’язкових параметри та один необов’язковий параметр:
- початковий час в 12-годинному форматі (закінчується на AM чи PM)
- проміжок часу, який позначає кількість годин та хвилин
-- (необов'язково) перший день тижня, байдуже на регістр
+- (необов’язково) перший день тижня, байдуже на регістр
Функція повинна додати проміжок часу до початкового часу та повернути результат.
-Якщо результатом буде наступний день, то повинне бути `(next day)` після часу. Якщо результат буде за декілька днів, то повинне бути `(n days later)` після часу, де n – це кількість днів.
+Якщо результатом буде наступний день, то повинне бути `(next day)` після часу. Якщо результат буде за декілька днів, то повинне бути `(n days later)` після часу, де n — це кількість днів.
Якщо функції задано довільний параметр першого дня тижня, то вивід має показувати день тижня у результаті. День тижня у виводі повинен бути після часу та перед кількістю днів.
diff --git a/curriculum/challenges/ukrainian/14-responsive-web-design-22/learn-html-forms-by-building-a-registration-form/60f805f813eaf2049bc2ceea.md b/curriculum/challenges/ukrainian/14-responsive-web-design-22/learn-html-forms-by-building-a-registration-form/60f805f813eaf2049bc2ceea.md
index efe73dc54a1..e8b489a81b6 100644
--- a/curriculum/challenges/ukrainian/14-responsive-web-design-22/learn-html-forms-by-building-a-registration-form/60f805f813eaf2049bc2ceea.md
+++ b/curriculum/challenges/ukrainian/14-responsive-web-design-22/learn-html-forms-by-building-a-registration-form/60f805f813eaf2049bc2ceea.md
@@ -26,25 +26,29 @@ assert.equal(document.querySelectorAll('label input')?.length, 4);
Ви повинні додати перший `input` після тексту `label` `Enter Your First Name:` та додати пробіл після двокрапки.
```js
-assert.equal(document.querySelectorAll('label')?.[0]?.innerHTML.trim(), 'Enter Your First Name:
');
+const query = /^Enter Your First Name:\s+
/
+assert.match(document.querySelectorAll('label')?.[0]?.innerHTML.trim(), query);
```
Ви повинні додати другий `input` після тексту `label` `Enter Your Last Name:` та додати пробіл після двокрапки.
```js
-assert.equal(document.querySelectorAll('label')?.[1]?.innerHTML.trim(), 'Enter Your Last Name:
');
+const query = /^Enter Your Last Name:\s+
/
+assert.match(document.querySelectorAll('label')?.[1]?.innerHTML.trim(), query);
```
Ви повинні додати третій `input` після тексту `label` `Enter Your Email:` та додати пробіл після двокрапки.
```js
-assert.equal(document.querySelectorAll('label')?.[2]?.innerHTML.trim(), 'Enter Your Email:
');
+const query = /^Enter Your Email:\s+
/
+assert.match(document.querySelectorAll('label')?.[2]?.innerHTML.trim(), query);
```
Ви повинні додати четвертий `input` після тексту `label` `Create a New Password:` та додати пробіл після двокрапки.
```js
-assert.equal(document.querySelectorAll('label')?.[3]?.innerHTML.trim(), 'Create a New Password:
');
+const query = /^Create a New Password:\s+
/
+assert.match(document.querySelectorAll('label')?.[3]?.innerHTML.trim(), query);
```
# --seed--
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/5ddb965c65d27e1512d44d9a.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/5ddb965c65d27e1512d44d9a.md
new file mode 100644
index 00000000000..c3def32154d
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/5ddb965c65d27e1512d44d9a.md
@@ -0,0 +1,122 @@
+---
+id: 5ddb965c65d27e1512d44d9a
+title: Step 1
+challengeType: 0
+dashedName: step-1
+---
+
+# --description--
+
+You have been provided with boilerplate CSS and HTML. However, you need to build your calorie counter form.
+
+Feel free to explore the HTML and CSS, then add a `form` element and give it an `id` set to `calorie-counter`.
+
+# --hints--
+
+You should have a `form` element.
+
+```js
+assert.exists(document.querySelector('form'));
+```
+
+Your `form` element should have an `id` attribute set to `calorie-counter`.
+
+```js
+assert.equal(document.querySelector('form')?.id, 'calorie-counter');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b606f09a14cc1781aea1fb.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b606f09a14cc1781aea1fb.md
new file mode 100644
index 00000000000..e938bc8c2e3
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b606f09a14cc1781aea1fb.md
@@ -0,0 +1,146 @@
+---
+id: 63b606f09a14cc1781aea1fb
+title: Step 2
+challengeType: 0
+dashedName: step-2
+---
+
+# --description--
+
+Create a `label` element, give it a `for` attribute set to `budget` and the text `Budget`, then create an `input` element with the `id` set to `budget`.
+
+# --hints--
+
+You should create a `label` element in your `form`.
+
+```js
+assert.exists(document.querySelector('form label'));
+```
+
+Your `label` element should have a `for` attribute set to `budget`.
+
+```js
+assert.equal(document.querySelector('form label')?.getAttribute('for'), 'budget');
+```
+
+Your `label` element should have the text `Budget`.
+
+```js
+assert.equal(document.querySelector('form label')?.innerText, 'Budget');
+```
+
+You should create an `input` element within your `form`.
+
+```js
+assert.exists(document.querySelector('form input'));
+```
+
+Your `input` element should come after your `label` element.
+
+```js
+assert.equal(document.querySelector('form input')?.previousElementSibling?.tagName, "LABEL");
+```
+
+Your `input` element should have an `id` set to `budget`.
+
+```js
+assert.equal(document.querySelector('form input')?.id, "budget");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b6075a62883218d282504c.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b6075a62883218d282504c.md
new file mode 100644
index 00000000000..fcabad47a30
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b6075a62883218d282504c.md
@@ -0,0 +1,131 @@
+---
+id: 63b6075a62883218d282504c
+title: Step 3
+challengeType: 0
+dashedName: step-3
+---
+
+# --description--
+
+Your `input` element needs some additional attributes. Give it a `type` set to `number` to only allow numeric inputs, a `min` attribute set to `0` to only allow positive numbers, and a `placeholder` set to `Daily calorie budget`.
+
+Finally, mark the `input` element as `required`.
+
+# --hints--
+
+Your `input` element should have a `type` attribute set to `number`.
+
+```js
+assert.equal(document.querySelector('form input').type, 'number');
+```
+
+Your `input` element should have a `min` attribute set to `0`.
+
+```js
+assert.equal(document.querySelector('form input').min, '0');
+```
+
+Your `input` element should have a `placeholder` attribute set to `Daily calorie budget`.
+
+```js
+assert.equal(document.querySelector('form input').placeholder, 'Daily calorie budget');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b607af6fcdb119aae9b16a.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b607af6fcdb119aae9b16a.md
new file mode 100644
index 00000000000..5079bde79a8
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b607af6fcdb119aae9b16a.md
@@ -0,0 +1,168 @@
+---
+id: 63b607af6fcdb119aae9b16a
+title: Step 4
+challengeType: 0
+dashedName: step-4
+---
+
+# --description--
+
+Create a `fieldset` element with the `id` set to `breakfast`.
+
+Within that element, create a `legend` with the text `Breakfast`, and an empty `div` with the `class` set to `input-container`.
+
+# --hints--
+
+You should create a `fieldset` element in your `form`.
+
+```js
+assert.exists(document.querySelector('form fieldset'));
+```
+
+Your `fieldset` element should come after your `input` element.
+
+```js
+assert.equal(document.querySelector('form fieldset')?.previousElementSibling?.tagName, "INPUT");
+```
+
+Your `fieldset` element should have an `id` set to `breakfast`.
+
+```js
+assert.equal(document.querySelector('form fieldset')?.id, "breakfast");
+```
+
+You should create a `legend` element within your `fieldset`.
+
+```js
+assert.exists(document.querySelector('form fieldset legend'));
+```
+
+Your `legend` element should have the text `Breakfast`.
+
+```js
+assert.equal(document.querySelector('form fieldset legend')?.innerText, "Breakfast");
+```
+
+You should create a `div` element within your `fieldset`.
+
+```js
+assert.exists(document.querySelector('form fieldset div'));
+```
+
+Your `div` element should come after your `legend` element.
+
+```js
+assert.equal(document.querySelector('form fieldset div')?.previousElementSibling?.tagName, "LEGEND");
+```
+
+Your `div` element should have a `class` set to `input-container`.
+
+```js
+assert.equal(document.querySelector('form fieldset div')?.className, "input-container");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60821c855d01b1eda3c0b.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60821c855d01b1eda3c0b.md
new file mode 100644
index 00000000000..7de68f5215c
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60821c855d01b1eda3c0b.md
@@ -0,0 +1,164 @@
+---
+id: 63b60821c855d01b1eda3c0b
+title: Step 5
+challengeType: 0
+dashedName: step-5
+---
+
+# --description--
+
+Now create a `fieldset` with an `id` set to `lunch`, and a corresponding `legend` and `div` element.
+
+# --hints--
+
+You should create a second `fieldset` element in your `form`.
+
+```js
+assert.exists(document.querySelectorAll('form fieldset')[1]);
+```
+
+Your second `fieldset` element should come after your first `fieldset` element.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[1]?.previousElementSibling?.tagName, "FIELDSET");
+```
+
+Your second `fieldset` element should have an `id` set to `lunch`.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[1]?.id, "lunch");
+```
+
+Your second `fieldset` element should contain a `legend` element.
+
+```js
+assert.exists(document.querySelectorAll('form fieldset')[1]?.querySelector('legend'));
+```
+
+Your new `legend` element should have the text `Lunch`.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[1]?.querySelector('legend')?.innerText, "Lunch");
+```
+
+Your second `fieldset` element should contain a `div` element.
+
+```js
+assert.exists(document.querySelectorAll('form fieldset')[1]?.querySelector('div'));
+```
+
+Your new `div` element should have a `class` set to `input-container`.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[1]?.querySelector('div')?.className, "input-container");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b6088bb56e2d1cac364043.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b6088bb56e2d1cac364043.md
new file mode 100644
index 00000000000..f7c617f998e
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b6088bb56e2d1cac364043.md
@@ -0,0 +1,168 @@
+---
+id: 63b6088bb56e2d1cac364043
+title: Step 6
+challengeType: 0
+dashedName: step-6
+---
+
+# --description--
+
+Continuing the pattern, create a `fieldset` for `dinner` with the same nested elements.
+
+# --hints--
+
+You should create a third `fieldset` element in your `form`.
+
+```js
+assert.exists(document.querySelectorAll('form fieldset')[2]);
+```
+
+Your third `fieldset` element should come after your second `fieldset` element.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[2]?.previousElementSibling?.tagName, "FIELDSET");
+```
+
+Your third `fieldset` element should have an `id` set to `dinner`.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[2]?.id, "dinner");
+```
+
+Your third `fieldset` element should contain a `legend` element.
+
+```js
+assert.exists(document.querySelectorAll('form fieldset')[2]?.querySelector('legend'));
+```
+
+Your new `legend` element should have the text `Dinner`.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[2]?.querySelector('legend')?.innerText, "Dinner");
+```
+
+Your third `fieldset` element should contain a `div` element.
+
+```js
+assert.exists(document.querySelectorAll('form fieldset')[2]?.querySelector('div'));
+```
+
+Your new `div` element should have a `class` set to `input-container`.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[2]?.querySelector('div')?.className, "input-container");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b608ebf40c871d960fc004.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b608ebf40c871d960fc004.md
new file mode 100644
index 00000000000..911126b33e4
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b608ebf40c871d960fc004.md
@@ -0,0 +1,214 @@
+---
+id: 63b608ebf40c871d960fc004
+title: Step 7
+challengeType: 0
+dashedName: step-7
+---
+
+# --description--
+
+You need two more of these `fieldset` code blocks – one for `snacks` and one for `exercise`.
+
+# --hints--
+
+You should create a fourth `fieldset` element in your `form`.
+
+```js
+assert.exists(document.querySelectorAll('form fieldset')[3]);
+```
+
+Your fourth `fieldset` element should come after your third `fieldset` element.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[3]?.previousElementSibling?.tagName, "FIELDSET");
+```
+
+Your fourth `fieldset` element should have an `id` set to `snacks`.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[3]?.id, "snacks");
+```
+
+Your fourth `fieldset` element should contain a `legend` element.
+
+```js
+assert.exists(document.querySelectorAll('form fieldset')[3]?.querySelector('legend'));
+```
+
+Your fourth `legend` element should have the text `Snacks`.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[3]?.querySelector('legend')?.innerText, "Snacks");
+```
+
+Your fourth `fieldset` element should contain a `div` element.
+
+```js
+assert.exists(document.querySelectorAll('form fieldset')[3]?.querySelector('div'));
+```
+
+Your fifth `div` element should have a `class` set to `input-container`.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[3]?.querySelector('div')?.className, "input-container");
+```
+
+You should create a fifth `fieldset` element in your `form`.
+
+```js
+assert.exists(document.querySelectorAll('form fieldset')[4]);
+```
+
+Your fifth `fieldset` element should come after your fourth `fieldset` element.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[4]?.previousElementSibling?.tagName, "FIELDSET");
+```
+
+Your fifth `fieldset` element should have an `id` set to `exercise`.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[4]?.id, "exercise");
+```
+
+Your fifth `fieldset` element should contain a `legend` element.
+
+```js
+assert.exists(document.querySelectorAll('form fieldset')[4]?.querySelector('legend'));
+```
+
+Your fifth `legend` element should have the text `Exercise`.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[4]?.querySelector('legend')?.innerText, "Exercise");
+```
+
+Your fifth `fieldset` element should contain a `div` element.
+
+```js
+assert.exists(document.querySelectorAll('form fieldset')[4]?.querySelector('div'));
+```
+
+Your fifth `div` element should have a `class` set to `input-container`.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[4]?.querySelector('div')?.className, "input-container");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60a140bf5a321d50a7315.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60a140bf5a321d50a7315.md
new file mode 100644
index 00000000000..068bea72dfc
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60a140bf5a321d50a7315.md
@@ -0,0 +1,163 @@
+---
+id: 63b60a140bf5a321d50a7315
+title: Step 8
+challengeType: 0
+dashedName: step-8
+---
+
+# --description--
+
+Create a `div` and give it a `class` set to `controls`. Nest a `span` element within that `div`.
+
+# --hints--
+
+You should create a new `div` element in your `form`.
+
+```js
+assert.exists(document.querySelector('form > div'));
+```
+
+Your `div` element should come after your `fieldset` elements.
+
+```js
+assert.equal(document.querySelector('form > div')?.previousElementSibling?.tagName, "FIELDSET");
+assert.notExists(document.querySelector('form > div')?.nextElementSibling);
+```
+
+Your `div` element should have a `class` attribute set to `controls`.
+
+```js
+assert.equal(document.querySelector('form > div')?.className, "controls");
+```
+
+You should nest a `span` element within your `div`.
+
+```js
+assert.exists(document.querySelector('form > div > span'));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60aaaa65f8922bfce6b7e.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60aaaa65f8922bfce6b7e.md
new file mode 100644
index 00000000000..c9723d26fcb
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60aaaa65f8922bfce6b7e.md
@@ -0,0 +1,210 @@
+---
+id: 63b60aaaa65f8922bfce6b7e
+title: Step 9
+challengeType: 0
+dashedName: step-9
+---
+
+# --description--
+
+In your `span` element, create a `label` element for an `entry-dropdown` and give it the text `Add food or exercise:`. Then create a `select` element with the `id` set to `entry-dropdown` and a `name` set to `options`. Below that, add a `button` element with the `id` set to `add-entry` and the text `Add Entry`.
+
+Give your `button` element a `type` attribute set to `button` to prevent automatic form submission.
+
+# --hints--
+
+You should add a `label` element to your `span` element.
+
+```js
+assert.exists(document.querySelector('.controls > span > label'));
+```
+
+Your new `label` element should have a `for` attribute set to `entry-dropdown`.
+
+```js
+assert.equal(document.querySelector('.controls > span > label')?.getAttribute('for'), 'entry-dropdown');
+```
+
+Your new `label` element should have the text `Add food or exercise:`.
+
+```js
+assert.equal(document.querySelector('.controls > span > label')?.innerText, 'Add food or exercise:');
+```
+
+You should add a `select` element to your `span` element.
+
+```js
+assert.exists(document.querySelector('.controls > span > select'));
+```
+
+Your `select` element should come after your `label` element.
+
+```js
+assert(document.querySelector('.controls > span > select')?.previousElementSibling?.tagName === 'LABEL');
+```
+
+Your new `select` element should have an `id` attribute set to `entry-dropdown`.
+
+```js
+assert.equal(document.querySelector('.controls > span > select')?.getAttribute('id'), 'entry-dropdown');
+```
+
+Your new `select` element should have a `name` attribute set to `options`.
+
+```js
+assert.equal(document.querySelector('.controls > span > select')?.getAttribute('name'), 'options');
+```
+
+You should add a `button` element to your `span` element.
+
+```js
+assert.exists(document.querySelector('.controls > span > button'));
+```
+
+Your `button` element should come after your `select` element.
+
+```js
+assert(document.querySelector('.controls > span > button')?.previousElementSibling?.tagName === 'SELECT');
+```
+
+Your new `button` element should have an `id` attribute set to `add-entry`.
+
+```js
+assert.equal(document.querySelector('.controls > span > button')?.getAttribute('id'), 'add-entry');
+```
+
+Your new `button` element should have the text `Add Entry`.
+
+```js
+assert.equal(document.querySelector('.controls > span > button')?.innerText, 'Add Entry');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60af1a0b9f7238a9dd294.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60af1a0b9f7238a9dd294.md
new file mode 100644
index 00000000000..27f69a473d9
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60af1a0b9f7238a9dd294.md
@@ -0,0 +1,220 @@
+---
+id: 63b60af1a0b9f7238a9dd294
+title: Step 10
+challengeType: 0
+dashedName: step-10
+---
+
+# --description--
+
+Your select menu needs options for each of the food and exercise `fieldset` elements you created in the previous steps. Use the `option` element to create a new option for each `fieldset`. The `value` attribute of each option should be the `id` of the `fieldset`, and the text of each option should be the text of the `legend`.
+
+Set the `Breakfast` option as the `selected` option.
+
+# --hints--
+
+You should create five `option` elements within your `select` element.
+
+```js
+assert.equal(document.querySelectorAll('.controls select option')?.length, 5);
+```
+
+Your first `option` should have the text `Breakfast`.
+
+```js
+assert.equal(document.querySelectorAll('.controls select option')?.[0]?.textContent, 'Breakfast');
+```
+
+Your first `option` should have the `value` attribute set to `breakfast`.
+
+```js
+assert.equal(document.querySelectorAll('.controls select option')?.[0]?.value, 'breakfast');
+```
+
+Your second `option` should have the text `Lunch`.
+
+```js
+assert.equal(document.querySelectorAll('.controls select option')?.[1]?.textContent, 'Lunch');
+```
+
+Your second `option` should have the `value` attribute set to `lunch`.
+
+```js
+assert.equal(document.querySelectorAll('.controls select option')?.[1]?.value, 'lunch');
+```
+
+Your third `option` should have the text `Dinner`.
+
+```js
+assert.equal(document.querySelectorAll('.controls select option')?.[2]?.textContent, 'Dinner');
+```
+
+Your third `option` should have the `value` attribute set to `dinner`.
+
+```js
+assert.equal(document.querySelectorAll('.controls select option')?.[2]?.value, 'dinner');
+```
+
+Your fourth `option` should have the text `Snacks`.
+
+```js
+assert.equal(document.querySelectorAll('.controls select option')?.[3]?.textContent, 'Snacks');
+```
+
+Your fourth `option` should have the `value` attribute set to `snacks`.
+
+```js
+assert.equal(document.querySelectorAll('.controls select option')?.[3]?.value, 'snacks');
+```
+
+Your fifth `option` should have the text `Exercise`.
+
+```js
+assert.equal(document.querySelectorAll('.controls select option')?.[4]?.textContent, 'Exercise');
+```
+
+Your fifth `option` should have the `value` attribute set to `exercise`.
+
+```js
+assert.equal(document.querySelectorAll('.controls select option')?.[4]?.value, 'exercise');
+```
+
+Your first `option` should be selected by default.
+
+```js
+assert.isTrue(document.querySelectorAll('.controls select option')?.[0]?.getAttributeNames()?.includes('selected'));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60c09c5039f25a3b2dda9.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60c09c5039f25a3b2dda9.md
new file mode 100644
index 00000000000..4e28d650816
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60c09c5039f25a3b2dda9.md
@@ -0,0 +1,207 @@
+---
+id: 63b60c09c5039f25a3b2dda9
+title: Step 11
+challengeType: 0
+dashedName: step-11
+---
+
+# --description--
+
+Create another `div` element. Within it, nest a `button` to `submit` the form, with an `id` set to `calculate-calories`. This button should have the text `Calculate Remaining Calories`.
+
+Then add a `button` with the `id` set to `clear` to clear the form (don't forget to give it a `type` attribute that prevents it from submitting the form). This button needs the text `Clear`.
+
+# --hints--
+
+You should create a second `div` element.
+
+```js
+assert.equal(document.querySelectorAll('form > div')?.length, 2);
+```
+
+Your new `div` element should have a `button` element.
+
+```js
+assert.exists(document.querySelectorAll('form > div')?.[1]?.querySelector('button'));
+```
+
+Your `button` element should have a `type` attribute set to `submit`.
+
+```js
+assert.equal(document.querySelectorAll('form > div')?.[1]?.querySelector('button')?.getAttribute('type'), 'submit');
+```
+
+Your `button` element should have an `id` attribute set to `calculate-calories`.
+
+```js
+assert.equal(document.querySelectorAll('form > div')?.[1]?.querySelector('button')?.getAttribute('id'), 'calculate-calories');
+```
+
+Your `button` element should have the text `Calculate Remaining Calories`.
+
+```js
+assert.equal(document.querySelectorAll('form > div')?.[1]?.querySelector('button')?.innerText, 'Calculate Remaining Calories');
+```
+
+Your `div` element should have a second `button` element.
+
+```js
+assert.exists(document.querySelectorAll('form > div')?.[1]?.querySelectorAll('button')?.[1]);
+```
+
+Your second `button` element should have a `type` attribute set to `button`.
+
+```js
+assert.equal(document.querySelectorAll('form > div')?.[1]?.querySelectorAll('button')?.[1]?.getAttribute('type'), 'button');
+```
+
+Your second `button` element should have an `id` attribute set to `clear`.
+
+```js
+assert.equal(document.querySelectorAll('form > div')?.[1]?.querySelectorAll('button')?.[1]?.getAttribute('id'), 'clear');
+```
+
+Your second `button` element should have the text `Clear`.
+
+```js
+assert.equal(document.querySelectorAll('form > div')?.[1]?.querySelectorAll('button')?.[1]?.innerText, 'Clear');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60ca38c897f2721b27959.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60ca38c897f2721b27959.md
new file mode 100644
index 00000000000..aaf24c8d8cb
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60ca38c897f2721b27959.md
@@ -0,0 +1,182 @@
+---
+id: 63b60ca38c897f2721b27959
+title: Step 12
+challengeType: 0
+dashedName: step-12
+---
+
+# --description--
+
+Your form needs somewhere to display the results. Add an empty `div` element and give it an `id` of `output` and the `class` values of `output` and `hide`.
+
+# --hints--
+
+You should add a `div` element after your `form`.
+
+```js
+assert.exists(document.querySelector('.container > div'));
+```
+
+Your new `div` element should have an `id` set to `output`.
+
+```js
+assert.equal(document.querySelector('.container > div')?.id, 'output');
+```
+
+Your new `div` element should have the `class` values of `output` and `hide`.
+
+```js
+assert.include(document.querySelector('.container > div')?.className.split(/\s+/), 'output');
+assert.include(document.querySelector('.container > div')?.className.split(/\s+/), 'hide');
+```
+
+Your new `div` should be empty.
+
+```js
+assert.equal(document.querySelector('.container > div')?.innerHTML, '');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60cfaca25bb27edd40f62.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60cfaca25bb27edd40f62.md
new file mode 100644
index 00000000000..17934b0039d
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60cfaca25bb27edd40f62.md
@@ -0,0 +1,170 @@
+---
+id: 63b60cfaca25bb27edd40f62
+title: Step 13
+challengeType: 0
+dashedName: step-13
+---
+
+# --description--
+
+Finally, you need to link your JavaScript file to your HTML. Create a `script` element to do so.
+
+# --hints--
+
+You should have a `script` element.
+
+```js
+assert.isAtLeast(document.querySelectorAll('script')?.length, 1);
+```
+
+Your `script` element should have the `src` set to `./script.js`.
+
+```js
+assert.match(code, /script\s*?src\s*?=\s*?('|")(\.\/)?script\.js\1/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60d3c5048302906962231.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60d3c5048302906962231.md
new file mode 100644
index 00000000000..de3870b44ad
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60d3c5048302906962231.md
@@ -0,0 +1,176 @@
+---
+id: 63b60d3c5048302906962231
+title: Step 14
+challengeType: 0
+dashedName: step-14
+---
+
+# --description--
+
+It is time to start writing the script that makes your form work. Begin by getting the `form` element (using the `id`) and storing it in a variable called `calorieCounter`.
+
+# --hints--
+
+You should create a variable called `calorieCounter`.
+
+```js
+assert.isDefined(calorieCounter);
+```
+
+You should use `document.getElementById()` to get the `#calorie-counter` element.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|")calorie-counter\1\s*\)/g);
+```
+
+You should store the `#calorie-counter` element in a variable called `calorieCounter`.
+
+```js
+assert.equal(calorieCounter, document.getElementById('calorie-counter'));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b613f367584d2a5d041b7d.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b613f367584d2a5d041b7d.md
new file mode 100644
index 00000000000..44e1c274573
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b613f367584d2a5d041b7d.md
@@ -0,0 +1,195 @@
+---
+id: 63b613f367584d2a5d041b7d
+title: Step 15
+challengeType: 0
+dashedName: step-15
+---
+
+# --description--
+
+Get your `#budget` element and assign it to `budgetNumberInput`, and your `#entry-dropdown` element and assign it to `entryDropdown`.
+
+# --hints--
+
+You should declare a variable called `budgetNumberInput`.
+
+```js
+assert.isDefined(budgetNumberInput);
+```
+
+You should use `document.getElementById()` to get the `#budget` element.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|")budget\1\s*\)/g);
+```
+
+You should store the `#budget` element in a variable called `budgetNumberInput`.
+
+```js
+assert.equal(budgetNumberInput, document.getElementById('budget'));
+```
+
+You should declare a variable called `entryDropdown`.
+
+```js
+assert.isDefined(entryDropdown);
+```
+
+You should use `document.getElementById()` to get the `#entry-dropdown` element.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|")entry-dropdown\1\s*\)/g);
+```
+
+You should store the `#entry-dropdown` element in a variable called `entryDropdown`.
+
+```js
+assert.equal(entryDropdown, document.getElementById('entry-dropdown'));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+--fcc-editable-region--
+const calorieCounter = document.getElementById('calorie-counter');
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b61490e633a22b4593e62f.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b61490e633a22b4593e62f.md
new file mode 100644
index 00000000000..6cbbeb5ab4a
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b61490e633a22b4593e62f.md
@@ -0,0 +1,215 @@
+---
+id: 63b61490e633a22b4593e62f
+title: Step 16
+challengeType: 0
+dashedName: step-16
+---
+
+# --description--
+
+Following the same pattern, assign your `#add-entry` element to `addEntryButton`, your `#clear` element to `clearButton`, and your `#output` element to `output`.
+
+# --hints--
+
+You should declare a variable called `addEntryButton`.
+
+```js
+assert.isDefined(addEntryButton);
+```
+
+You should use `document.getElementById()` to get the `#add-entry` element.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|")add-entry\1\s*\)/g);
+```
+
+You should assign the `#add-entry` element to `addEntryButton`.
+
+```js
+assert.equal(addEntryButton, document.getElementById('add-entry'));
+```
+
+You should declare a variable called `clearButton`.
+
+```js
+assert.isDefined(clearButton);
+```
+
+You should use `document.getElementById()` to get the `#clear` element.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|")clear\1\s*\)/g);
+```
+
+You should assign the `#clear` element to `clearButton`.
+
+```js
+assert.equal(clearButton, document.getElementById('clear'));
+```
+
+You should declare a variable called `output`.
+
+```js
+assert.isDefined(output);
+```
+
+You should use `document.getElementById()` to get the `#output` element.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|")output\1\s*\)/g);
+```
+
+You should assign the `#output` element to `output`.
+
+```js
+assert.equal(output, document.getElementById("output"));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+--fcc-editable-region--
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b614e6a1f7fe2cef6312dc.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b614e6a1f7fe2cef6312dc.md
new file mode 100644
index 00000000000..99c1985862c
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b614e6a1f7fe2cef6312dc.md
@@ -0,0 +1,182 @@
+---
+id: 63b614e6a1f7fe2cef6312dc
+title: Step 17
+challengeType: 0
+dashedName: step-17
+---
+
+# --description--
+
+Declare an `isError` variable and set it to `false`, but use `let` so you can reassign it later.
+
+# --hints--
+
+You should declare an `isError` variable.
+
+```js
+assert.isDefined(isError);
+```
+
+Your `isError` variable should be set to `false`.
+
+```js
+assert.isFalse(isError);
+```
+
+You should use `let` to declare your `isError` variable.
+
+```js
+assert.match(code, /let\s+isError\s*=\s*false/g);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+--fcc-editable-region--
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b6152e6aff882db819fc1e.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b6152e6aff882db819fc1e.md
new file mode 100644
index 00000000000..436b65b80d6
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b6152e6aff882db819fc1e.md
@@ -0,0 +1,192 @@
+---
+id: 63b6152e6aff882db819fc1e
+title: Step 18
+challengeType: 0
+dashedName: step-18
+---
+
+# --description--
+
+Even though you set an `input` element to be a number, JavaScript receives a string value. You need to write a function to clean the string value and ensure you have a number.
+
+Start by declaring a `cleanInputString` function that takes a `str` argument.
+
+# --hints--
+
+You should declare a `cleanInputString` variable.
+
+```js
+assert.isDefined(cleanInputString);
+```
+
+Your `cleanInputString` variable should be a function.
+
+```js
+assert.isFunction(cleanInputString);
+```
+
+Your `cleanInputString` function should take a `str` argument.
+
+```js
+assert.match(cleanInputString?.toString(), /\(str\)/);
+```
+
+`cleanInputString` should be an empty function.
+
+```js
+assert.match(cleanInputString?.toString(), /\{\s*\}/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b61584def8fa2ebcc259e0.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b61584def8fa2ebcc259e0.md
new file mode 100644
index 00000000000..b7de4018e24
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b61584def8fa2ebcc259e0.md
@@ -0,0 +1,182 @@
+---
+id: 63b61584def8fa2ebcc259e0
+title: Step 19
+challengeType: 0
+dashedName: step-19
+---
+
+# --description--
+
+You need to split your `str` into individual characters. Remember that strings have a `.split()` method, and if you pass an empty string it will split on every character.
+
+Declare a `strArray` variable and assign it that split value.
+
+# --hints--
+
+Your `cleanInputString` function should declare a `strArray` variable.
+
+```js
+assert.match(cleanInputString.toString(), /strArray\s*=/);
+```
+
+Your `strArray` variable should be assigned the value of `str.split('')`.
+
+```js
+assert.match(cleanInputString.toString(), /strArray\s*=\s*str\.split\(\s*('|")\1\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+--fcc-editable-region--
+function cleanInputString(str) {
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf43be3f969d24d4ed233c.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf43be3f969d24d4ed233c.md
new file mode 100644
index 00000000000..a0eaf81fd4e
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf43be3f969d24d4ed233c.md
@@ -0,0 +1,181 @@
+---
+id: 63bf43be3f969d24d4ed233c
+title: Step 20
+challengeType: 0
+dashedName: step-20
+---
+
+# --description--
+
+Declare a `cleanStrArray` variable and assign it an empty array. You will use this to store your valid number characters.
+
+# --hints--
+
+Your `cleanInputString` should declare a variable called `cleanStrArray`.
+
+```js
+assert.match(cleanInputString.toString(), /cleanStrArray\s*/g);
+```
+
+Your `cleanStrArray` variable should be assigned an empty array.
+
+```js
+assert.match(cleanInputString.toString(), /cleanStrArray\s*=\s*\[\s*\]/g);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+--fcc-editable-region--
+function cleanInputString(str) {
+ const strArray = str.split('');
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf446945d34d25e6db6e4f.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf446945d34d25e6db6e4f.md
new file mode 100644
index 00000000000..db275c224c1
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf446945d34d25e6db6e4f.md
@@ -0,0 +1,195 @@
+---
+id: 63bf446945d34d25e6db6e4f
+title: Step 21
+challengeType: 0
+dashedName: step-21
+---
+
+# --description--
+
+Use a `for` loop to iterate through each character in your `strArray` array.
+
+# --hints--
+
+Your `cleanInputString` function should have a `for` loop.
+
+```js
+assert.match(cleanInputString.toString(), /for\s*\(/g);
+```
+
+Your `for` loop should initialize a variable called `i` to `0`.
+
+```js
+assert.match(cleanInputString.toString(), /for\s*\(\s*(let|var)\s+i\s*=\s*0\s*;/g);
+```
+
+Your `for` loop should have a condition that checks if `i` is less than the length of `strArray`.
+
+```js
+assert.match(cleanInputString.toString(), /for\s*\(\s*(let|var)\s+i\s*=\s*0\s*;\s*i\s*<\s*strArray\.length\s*;/g);
+```
+
+Your `for` loop should increment `i` by `1` each time it runs. Use the increment operator for this.
+
+```js
+assert.match(cleanInputString.toString(), /for\s*\(\s*(let|var)\s+i\s*=\s*0\s*;\s*i\s*<\s*strArray\.length\s*;\s*i\s*\+\+\s*\)/g);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+--fcc-editable-region--
+function cleanInputString(str) {
+ const strArray = str.split('');
+ const cleanStrArray = [];
+
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf45ce0dc8d4270760c6d0.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf45ce0dc8d4270760c6d0.md
new file mode 100644
index 00000000000..a432c6687d5
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf45ce0dc8d4270760c6d0.md
@@ -0,0 +1,200 @@
+---
+id: 63bf45ce0dc8d4270760c6d0
+title: Step 22
+challengeType: 0
+dashedName: step-22
+---
+
+# --description--
+
+Within your loop, you need to check if the character in `strArray` at index `i` is not `+`, `-`, or a space. If it is not, `push` it to the `cleanStrArray`.
+
+To check your character, see if the array `["+", "-", " "]` includes the character – you can use the `.includes()` method on the array to do this.
+
+# --hints--
+
+Your `for` loop should have an `if` statement.
+
+```js
+assert.match(cleanInputString.toString(), /for\s*\(\s*(let|var)\s+i\s*=\s*0\s*;\s*i\s*<\s*strArray\.length\s*;\s*i\s*\+\+\s*\)\s*\{\s*if\s*\(/);
+```
+
+Your `for` loop should use `!["+", "-", " "].includes()`.
+
+```js
+// the loop protection injects code so we have to look at the raw code directly
+assert.match(code, /for\s*\(\s*(let|var)\s+i\s*=\s*0\s*;\s*i\s*<\s*strArray\.length\s*;\s*i\s*\+\+\s*\)\s*\{\s*if\s*\(!\[("|')\+\2\s*,\s*("|')-\3\s*,\s*("|')\s\4\s*\]\.includes\(/);
+```
+
+Your `for` loop should see if `strArray[i]` is found in `["+", "-", " "]`.
+
+```js
+assert.match(code, /for\s*\(\s*(let|var)\s+i\s*=\s*0\s*;\s*i\s*<\s*strArray\.length\s*;\s*i\s*\+\+\s*\)\s*\{\s*if\s*\(!\[("|')\+\2\s*,\s*("|')-\3\s*,\s*("|')\s\4\s*\]\.includes\(\s*strArray\[i\]\s*\)\)\s*\{/);
+```
+
+Your `for` loop should `push` `strArray[i]` to `cleanStrArray`.
+
+```js
+assert.match(code, /for\s*\(\s*(let|var)\s+i\s*=\s*0\s*;\s*i\s*<\s*strArray\.length\s*;\s*i\s*\+\+\s*\)\s*\{\s*if\s*\(!\[("|')\+\2\s*,\s*("|')-\3\s*,\s*("|')\s\4\s*\]\.includes\(\s*strArray\[i\]\s*\)\)\s*\{\s*cleanStrArray\.push\(\s*strArray\[i\]\s*\)\s*\}/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+--fcc-editable-region--
+function cleanInputString(str) {
+ const strArray = str.split('');
+ const cleanStrArray = [];
+
+ for (let i = 0; i < strArray.length; i++) {
+
+ }
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf461011fca327d3b60fa8.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf461011fca327d3b60fa8.md
new file mode 100644
index 00000000000..f74ff636c5b
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf461011fca327d3b60fa8.md
@@ -0,0 +1,213 @@
+---
+id: 63bf461011fca327d3b60fa8
+title: Step 23
+challengeType: 0
+dashedName: step-23
+---
+
+# --description--
+
+While looping through the string works, creating a new array is inefficient for memory and runtime performance. Instead, you can use Regular Expressions (referred to as "regex") to match specific characters.
+
+Regex in JavaScript is indicated by a pattern wrapped in forward slashes – for example:
+
+```js
+const regex = /hello/;
+```
+
+Remove your existing code within the `cleanInputString` function. Declare a `regex` variable and assign it the value from the example above.
+
+# --hints--
+
+You should remove the `cleanStrArray` variable.
+
+```js
+assert.notMatch(cleanInputString.toString(), /cleanStrArray/);
+```
+
+You should remove the `strArray` variable.
+
+```js
+assert.notMatch(cleanInputString.toString(), /strArray/);
+```
+
+You should not have a `for` loop.
+
+```js
+assert.notMatch(cleanInputString.toString(), /for/);
+```
+
+You should declare a `regex` variable.
+
+```js
+assert.match(cleanInputString.toString(), /regex\s*=/);
+```
+
+Your `regex` variable should be set to the regular expression `/hello/`.
+
+```js
+assert.match(cleanInputString.toString(), /regex\s*=\s*\/hello\//);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+--fcc-editable-region--
+function cleanInputString(str) {
+ const strArray = str.split('');
+ const cleanStrArray = [];
+
+ for (let i = 0; i < strArray.length; i++) {
+ if (!["+", "-", " "].includes(strArray[i])) {
+ cleanStrArray.push(strArray[i])
+ }
+ }
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf47fd40599f29827f484d.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf47fd40599f29827f484d.md
new file mode 100644
index 00000000000..0f781eb61cf
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf47fd40599f29827f484d.md
@@ -0,0 +1,176 @@
+---
+id: 63bf47fd40599f29827f484d
+title: Step 24
+challengeType: 0
+dashedName: step-24
+---
+
+# --description--
+
+The pattern you currently have will match the exact text `hello`, which is not what you want to match. You want to look for `+`, `-`, or spaces. Replace the pattern in your `regex` variable with `\+-` to look for plus and minus characters.
+
+Note that you need to use the `\` to
escape the `+`, because a `+` has a special meaning in regular expressions.
+
+# --hints--
+
+Your `regex` variable should be set to the regular expression `/\+-/`.
+
+```js
+assert.match(cleanInputString.toString(), /regex\s*=\s*\/\\\+-\//);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+--fcc-editable-region--
+function cleanInputString(str) {
+ const regex = /hello/;
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf492b6dfb292a79f0e675.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf492b6dfb292a79f0e675.md
new file mode 100644
index 00000000000..25d6d2447fb
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf492b6dfb292a79f0e675.md
@@ -0,0 +1,174 @@
+---
+id: 63bf492b6dfb292a79f0e675
+title: Step 25
+challengeType: 0
+dashedName: step-25
+---
+
+# --description--
+
+In regex, shorthand character classes allow you to match specific characters without having to write those characters in your pattern. Shorthand character classes are preceded with a backslash (`\`). The character class `\s` will match any whitespace character. Add this to your regex pattern.
+
+# --hints--
+
+Your `regex` variable should be set to the regular expression `/\+-\s/`.
+
+```js
+assert.match(cleanInputString.toString(), /regex\s*=\s*\/\\\+-\\s\//)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+--fcc-editable-region--
+function cleanInputString(str) {
+ const regex = /\+-/;
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf4bfe9de3852be51c8f86.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf4bfe9de3852be51c8f86.md
new file mode 100644
index 00000000000..3b18f0aac60
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf4bfe9de3852be51c8f86.md
@@ -0,0 +1,188 @@
+---
+id: 63bf4bfe9de3852be51c8f86
+title: Step 26
+challengeType: 0
+dashedName: step-26
+---
+
+# --description--
+
+Your current pattern won't work just yet. `/+-\s/` looks for `+`, `-`, and a space *in order*. This would match `+- hello` but would not match `+hello`.
+
+To tell the pattern to match each of these characters individually, you need to turn them into a character class. This is done by wrapping the characters you want to match in brackets. For example, this pattern will match the characters `h`, `e`, `l`, or `o`:
+
+```js
+const regex = /[helo]/;
+```
+
+Turn your `+-\s` pattern into a character class. Note that you no longer need to escape the `+` character, because you are using a character class.
+
+# --hints--
+
+Your `regex` variable should be set to the regular expression `[+-\s]`.
+
+```js
+assert.match(cleanInputString.toString(), /regex\s*=\s*\/\[\\?\+-\\s\]\//)
+```
+
+You should not escape the `+` character in your regular expression.
+
+```js
+assert.match(cleanInputString.toString(), /regex\s*=\s*\/\[\+-\\s\]\//);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+--fcc-editable-region--
+function cleanInputString(str) {
+ const regex = /\+-\s/;
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf4d351e06432ce9bf3627.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf4d351e06432ce9bf3627.md
new file mode 100644
index 00000000000..30baf30ed58
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf4d351e06432ce9bf3627.md
@@ -0,0 +1,180 @@
+---
+id: 63bf4d351e06432ce9bf3627
+title: Step 27
+challengeType: 0
+dashedName: step-27
+---
+
+# --description--
+
+Regex can also take specific flags to alter the pattern matching behavior. Flags are added after the closing `/`. The `g` flag, which stands for "global", will tell the pattern to continue looking after it has found a match. Here is an example:
+
+```js
+const helloRegex = /hello/g;
+```
+
+Add the `g` flag to your regex pattern.
+
+# --hints--
+
+You should add the `g` flag to your `regex` value.
+
+```js
+assert.match(cleanInputString.toString(), /regex\s*=\s*\/\[\+-\\s\]\/g/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+--fcc-editable-region--
+function cleanInputString(str) {
+ const regex = /[+-\s]/;
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf511b85b6082e54dc1573.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf511b85b6082e54dc1573.md
new file mode 100644
index 00000000000..4b35b49f7b9
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf511b85b6082e54dc1573.md
@@ -0,0 +1,199 @@
+---
+id: 63bf511b85b6082e54dc1573
+title: Step 28
+challengeType: 0
+dashedName: step-28
+---
+
+# --description--
+
+Strings have a `.replace()` method which allows you to replace characters in the string with another string. `.replace` takes two arguments. The first is the character sequence to replace – this can either be a string or a regex pattern. The second is the string to replace that sequence with. For example, this would replace all instances of `l` with `1`:
+
+```js
+"hello".replace(/l/g, "1");
+```
+
+Use your `regex` to replace all instances of `+`, `-`, and a space in `str` with an empty string. Return this value.
+
+# --hints--
+
+Your `cleanInputString` should call the `replace` method of `str`.
+
+```js
+assert.match(cleanInputString.toString(), /str\.replace\(/);
+```
+
+You should pass `regex` as the first argument to `replace`.
+
+```js
+assert.match(cleanInputString.toString(), /str\.replace\(\s*regex\s*/);
+```
+
+You should pass `""` as the second argument to `replace`.
+
+```js
+assert.match(cleanInputString.toString(), /str\.replace\(\s*regex\s*,\s*("|')\1\s*\)/);
+```
+
+Your `cleanInputString` function should directly return the result of your `replace` method.
+
+```js
+assert.match(cleanInputString.toString(), /return\s*str\.replace\(\s*regex\s*,\s*("|')\1\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+--fcc-editable-region--
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5230bccd1c2f5c13e1ce.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5230bccd1c2f5c13e1ce.md
new file mode 100644
index 00000000000..b6eef00a30b
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5230bccd1c2f5c13e1ce.md
@@ -0,0 +1,191 @@
+---
+id: 63bf5230bccd1c2f5c13e1ce
+title: Step 29
+challengeType: 0
+dashedName: step-29
+---
+
+# --description--
+
+In HTML, number inputs allow for exponential notation (such as `1e10`). You need to filter those out.
+
+Start by creating a function called `isInvalidInput` – it should take a single `str` parameter.
+
+# --hints--
+
+You should declare an `isInvalidInput` variable.
+
+```js
+assert.isDefined(isInvalidInput)
+```
+
+`isInvalidInput` should be a function.
+
+```js
+assert.isFunction(isInvalidInput)
+```
+
+`isInvalidInput` should take a single `str` parameter.
+
+```js
+assert.match(isInvalidInput?.toString(), /\(\s*str\s*\)/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf598a4c807930a13a1a27.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf598a4c807930a13a1a27.md
new file mode 100644
index 00000000000..778a809571e
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf598a4c807930a13a1a27.md
@@ -0,0 +1,185 @@
+---
+id: 63bf598a4c807930a13a1a27
+title: Step 30
+challengeType: 0
+dashedName: step-30
+---
+
+# --description--
+
+Declare a `regex` variable, and assign it a regex that matches the character `e`.
+
+# --hints--
+
+Your `isInvalidInput` function should have a `regex` variable.
+
+```js
+assert.match(isInvalidInput.toString(), /regex\s*=/);
+```
+
+Your `regex` variable should be set to `/e/`.
+
+```js
+assert.match(isInvalidInput.toString(), /regex\s*=\s*\/e\//);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+--fcc-editable-region--
+function isInvalidInput(str) {
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5a518d54f63181ab639a.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5a518d54f63181ab639a.md
new file mode 100644
index 00000000000..2bf1aa0f9a3
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5a518d54f63181ab639a.md
@@ -0,0 +1,179 @@
+---
+id: 63bf5a518d54f63181ab639a
+title: Step 31
+challengeType: 0
+dashedName: step-31
+---
+
+# --description--
+
+The `e` in a number input can also be an uppercase `E`. Regex has a flag for this, however – the `i` flag, which stands for "insensitive". This flag makes your pattern case-insensitive. Add the `i` flag to your regex pattern.
+
+# --hints--
+
+Your `regex` value should have the `i` flag.
+
+```js
+assert.match(isInvalidInput.toString(), /regex\s*=\s*\/e\/i/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+--fcc-editable-region--
+function isInvalidInput(str) {
+ const regex = /e/;
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5a92fd148d3264d5322b.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5a92fd148d3264d5322b.md
new file mode 100644
index 00000000000..19873a84492
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5a92fd148d3264d5322b.md
@@ -0,0 +1,187 @@
+---
+id: 63bf5a92fd148d3264d5322b
+title: Step 32
+challengeType: 0
+dashedName: step-32
+---
+
+# --description--
+
+Number inputs only allow the `e` to occur between two digits. To match any number, you can use the character class `[0-9]`. This will match any digit between `0` and `9`.
+
+Add this character class before and after `e` in your pattern.
+
+# --hints--
+
+You should add the `[0-9]` character class before `e` in your regular expression.
+
+```js
+assert.match(isInvalidInput.toString(), /regex\s*=\s*\/\[0-9\]e/);
+```
+
+You should add the `[0-9]` character class after `e` in your regular expression.
+
+```js
+assert.match(isInvalidInput.toString(), /regex\s*=\s*\/\[0-9\]e\[0-9\]\//);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+--fcc-editable-region--
+function isInvalidInput(str) {
+ const regex = /e/i;
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5adfe2981b332eb007b6.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5adfe2981b332eb007b6.md
new file mode 100644
index 00000000000..75477ddd763
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5adfe2981b332eb007b6.md
@@ -0,0 +1,185 @@
+---
+id: 63bf5adfe2981b332eb007b6
+title: Step 33
+challengeType: 0
+dashedName: step-33
+---
+
+# --description--
+
+The `+` modifier in a regex allows you to match a pattern that occurs one or more times. To match your digit pattern one or more times, add a plus after each of the digit character classes. For example: `[0-9]+`.
+
+# --hints--
+
+You should add the `+` modifier to the character class before `e` in your regular expression.
+
+```js
+assert.match(isInvalidInput.toString(), /regex\s*=\s*\/\[0-9\]\+e/);
+```
+
+You should add the `+` modifier to the character class after `e` in your regular expression.
+
+```js
+assert.match(isInvalidInput.toString(), /regex\s*=\s*\/\[0-9\]\+e\[0-9\]\+\//);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+--fcc-editable-region--
+function isInvalidInput(str) {
+ const regex = /[0-9]e[0-9]/i;
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5bcfebff0734593fad19.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5bcfebff0734593fad19.md
new file mode 100644
index 00000000000..95686b3c3a0
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5bcfebff0734593fad19.md
@@ -0,0 +1,185 @@
+---
+id: 63bf5bcfebff0734593fad19
+title: Step 34
+challengeType: 0
+dashedName: step-34
+---
+
+# --description--
+
+There is a shorthand character class to match any digit: `\d`. Replace your `[0-9]` character classes with this shorthand.
+
+# --hints--
+
+You should replace the `[0-9]` character class before `e` with `\d` in your regular expression.
+
+```js
+assert.match(isInvalidInput.toString(), /regex\s*=\s*\/\\d\+e/);
+```
+
+You should replace the `[0-9]` character class after `e` with `\d` in your regular expression.
+
+```js
+assert.match(isInvalidInput.toString(), /regex\s*=\s*\/\\d\+e\\d\+\//);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+--fcc-editable-region--
+function isInvalidInput(str) {
+ const regex = /[0-9]+e[0-9]+/i;
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5c438f523a359769106c.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5c438f523a359769106c.md
new file mode 100644
index 00000000000..f6f61282ce9
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5c438f523a359769106c.md
@@ -0,0 +1,194 @@
+---
+id: 63bf5c438f523a359769106c
+title: Step 35
+challengeType: 0
+dashedName: step-35
+---
+
+# --description--
+
+Strings have a `.match()` method, which takes a regex argument. `.match()` will return an array of match results – containing either the first match, or all matches if the global flag is used.
+
+Return the result of calling the `.match()` method on `str` and passing your `regex` variable as the argument. You'll use this match result later on.
+
+# --hints--
+
+Your `isInvalidInput` function should call the `.match()` method on `str`.
+
+```js
+assert.match(isInvalidInput.toString(), /str\.match\(/);
+```
+
+You should pass `regex` as the argument to the `.match()` method.
+
+```js
+assert.match(isInvalidInput.toString(), /str\.match\(\s*regex\s*\)/);
+```
+
+Your `isInvalidInput` function should directly return the result of the `.match()` call.
+
+```js
+assert.match(isInvalidInput.toString(), /return\s+str\.match\(\s*regex\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+--fcc-editable-region--
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5cf03b50bf36cfbe94ea.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5cf03b50bf36cfbe94ea.md
new file mode 100644
index 00000000000..228f3503303
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5cf03b50bf36cfbe94ea.md
@@ -0,0 +1,194 @@
+---
+id: 63bf5cf03b50bf36cfbe94ea
+title: Step 36
+challengeType: 0
+dashedName: step-36
+---
+
+# --description--
+
+Your next step is to allow users to add entries to the calorie counter. Declare an empty function `addEntry`. This function should not take any parameters.
+
+# --hints--
+
+You should declare an `addEntry` variable.
+
+```js
+assert.isDefined(addEntry);
+```
+
+Your `addEntry` variable should be a function.
+
+```js
+assert.isFunction(addEntry);
+```
+
+Your `addEntry` function should not take any parameters.
+
+```js
+assert.match(addEntry?.toString(), /\(\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c1dfbd56c71e278800010c.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c1dfbd56c71e278800010c.md
new file mode 100644
index 00000000000..1bc417c8bbb
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c1dfbd56c71e278800010c.md
@@ -0,0 +1,198 @@
+---
+id: 63c1dfbd56c71e278800010c
+title: Step 37
+challengeType: 0
+dashedName: step-37
+---
+
+# --description--
+
+You'll need to know which category the entry goes in. Thankfully, you added a dropdown for the user to select a category.
+
+Remember that you queried that dropdown earlier in your JavaScript and assigned it to the `entryDropdown` button. Use concatenation to add `#` to the beginning of the `value` property of `entryDropdown`, and assign that result to a `targetId` variable.
+
+# --hints--
+
+Your `addEntry` function should have a `targetId` variable.
+
+```js
+assert.match(addEntry.toString(), /targetId\s*=/);
+```
+
+Your `targetId` variable should start with the string `#`.
+
+```js
+assert.match(addEntry.toString(), /targetId\s*=\s*('|")#\1/);
+```
+
+You should use concatenation to add `entryDropdown.value` after your `#` string.
+
+```js
+assert.match(addEntry.toString(), /targetId\s*=\s*('|")#\1\s*\+\s*entryDropdown\.value/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c1e0af28078f2dfad9eb3e.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c1e0af28078f2dfad9eb3e.md
new file mode 100644
index 00000000000..413b5f76d84
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c1e0af28078f2dfad9eb3e.md
@@ -0,0 +1,203 @@
+---
+id: 63c1e0af28078f2dfad9eb3e
+title: Step 38
+challengeType: 0
+dashedName: step-38
+---
+
+# --description--
+
+Now you need to target the `.input-container` element within the element that has your `targetId`. Declare a new `targetInputContainer` variable, and assign it the value of `document.querySelector()`. Use concatenation to separate `targetId` and `'.input-container'` with a space, and pass that string to `querySelector()`.
+
+# --hints--
+
+Your `addEntry` function should have a `targetInputContainer` variable.
+
+```js
+assert.match(addEntry.toString(), /targetInputContainer\s*=/);
+```
+
+Your `targetInputContainer` variable should be set to `document.querySelector()`.
+
+```js
+assert.match(addEntry.toString(), /targetInputContainer\s*=\s*document\.querySelector\(/);
+```
+
+You should pass `targetId` to your `querySelector()` method.
+
+```js
+assert.match(addEntry.toString(), /targetInputContainer\s*=\s*document\.querySelector\(\s*targetId\s*/);
+```
+
+You should concatenate `' .input-container'` to `targetId`. Remember to include the space at the beginning of `.input-container`.
+
+```js
+assert.match(addEntry.toString(), /targetInputContainer\s*=\s*document\.querySelector\(\s*targetId\s*\s*\+\s*('|")\s\.input-container\1\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+ const targetId = '#' + entryDropdown.value;
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c1e1965a898d302e0af4e3.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c1e1965a898d302e0af4e3.md
new file mode 100644
index 00000000000..06e5ac50cec
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c1e1965a898d302e0af4e3.md
@@ -0,0 +1,203 @@
+---
+id: 63c1e1965a898d302e0af4e3
+title: Step 39
+challengeType: 0
+dashedName: step-39
+---
+
+# --description--
+
+JavaScript has a feature called
template literals , which allow you to interpolate variables directly within a string. Template literals are denoted with backticks ` `` `, as opposed to single or double quotes. Variables can be passed in to a template literal by surrounding the variable with `${}` – the value of the variable will be inserted into the string.
+
+For example:
+
+```js
+const name = "Naomi";
+const templateLiteral = `Hello, my name is ${name}~!`;
+console.log(templateLiteral);
+```
+
+The console will show the string "Hello, my name is Naomi~!".
+
+Replace your concatenated string in the `querySelector` with a template literal – be sure to keep the space between your `targetId` variable and `.input-container`.
+
+# --hints--
+
+You should use a template literal in your `querySelector` method.
+
+```js
+assert.match(code, /const\s+targetInputContainer\s*=\s*document\.querySelector\(`.*`\)/);
+```
+
+Your template literal should have the value `{targetId} .input-container`.
+
+```js
+assert.match(code, /const\s+targetInputContainer\s*=\s*document\.querySelector\(`\$\{targetId\}\s\.input-container`\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+ const targetId = '#' + entryDropdown.value;
+ const targetInputContainer = document.querySelector(targetId + ' .input-container');
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c1e5b4b3c8a031def3bd65.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c1e5b4b3c8a031def3bd65.md
new file mode 100644
index 00000000000..6aeab26c100
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c1e5b4b3c8a031def3bd65.md
@@ -0,0 +1,197 @@
+---
+id: 63c1e5b4b3c8a031def3bd65
+title: Step 40
+challengeType: 0
+dashedName: step-40
+---
+
+# --description--
+
+Thanks to template literals, you actually don't need the `targetId` variable at all. Remove that variable, and update your template literal to replace `targetId` with `entryDropdown.value` – remember to add `#` before that, in the string.
+
+# --hints--
+
+You should remove the `targetId` variable.
+
+```js
+assert.notMatch(addEntry.toString(), /targetId\s*=/);
+```
+
+You should replace the `targetId` reference in your template literal with `entryDropdown.value`.
+
+```js
+assert.match(code, /const\s+targetInputContainer\s*=\s*document\.querySelector\(`#?\$\{entryDropdown\.value\}\s\.input-container`\s*\)/);
+```
+
+You should add `#` at the beginning of your template literal.
+
+```js
+assert.match(code, /const\s+targetInputContainer\s*=\s*document\.querySelector\(`#\$\{entryDropdown\.value\}\s\.input-container`\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+ const targetId = '#' + entryDropdown.value;
+ const targetInputContainer = document.querySelector(`${targetId} .input-container`);
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c1e704ee12703347625900.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c1e704ee12703347625900.md
new file mode 100644
index 00000000000..b658496aeee
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c1e704ee12703347625900.md
@@ -0,0 +1,197 @@
+---
+id: 63c1e704ee12703347625900
+title: Step 41
+challengeType: 0
+dashedName: step-41
+---
+
+# --description--
+
+You will want to number the entries a user adds. Declare an `entryNumber` variable and give it the value of `targetInputContainer.querySelectorAll()`. You do not need to pass an argument to the query selector yet.
+
+# --hints--
+
+You should have an `entryNumber` variable.
+
+```js
+assert.match(addEntry.toString(), /entryNumber\s*=/);
+```
+
+Your `entryNumber` variable should have the value of `targetInputContainer.querySelectorAll()`.
+
+```js
+assert.match(addEntry.toString(), /entryNumber\s*=\s*targetInputContainer\.querySelectorAll\(/);
+```
+
+You should not pass an argument to `querySelectorAll()`.
+
+```js
+assert.match(addEntry.toString(), /entryNumber\s*=\s*targetInputContainer\.querySelectorAll\(\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c2164c0df38a382062c4af.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c2164c0df38a382062c4af.md
new file mode 100644
index 00000000000..15622f17e14
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c2164c0df38a382062c4af.md
@@ -0,0 +1,201 @@
+---
+id: 63c2164c0df38a382062c4af
+title: Step 42
+challengeType: 0
+dashedName: step-42
+---
+
+# --description--
+
+Each entry will have a text input for the entry's name, and a number input for the calories. To get a count of the number of entries, you can query by text inputs. Note that you cannot query by number inputs, as you have an extra number input for the user's calorie budget.
+
+Pass the string `input[type="text"]` to the `querySelectorAll()` method. Remember that you will need to use single quotes for your string, so that you can use double quotes within.
+
+This will return a `NodeList` of all the text inputs in the form. You can then access the `length` property of the `NodeList` to get the number of entries. Do this on the same line.
+
+# --hints--
+
+You should pass the string `input[type="text"]` to the `querySelectorAll()` method.
+
+```js
+assert.match(addEntry.toString(), /entryNumber\s*=\s*targetInputContainer\.querySelectorAll\(\s*'input\[type="text"]'\)/)
+```
+
+You should access the `length` property of your `querySelectorAll()`.
+
+```js
+assert.match(addEntry.toString(), /\.querySelectorAll\(\s*'input\[type="text"]'\)\.length/)
+```
+
+Your `entryNumber` variable should be the `length` of the `querySelectorAll`.
+
+```js
+assert.match(addEntry.toString(), /entryNumber\s*=\s*targetInputContainer\.querySelectorAll\(\s*'input\[type="text"]'\)\.length/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll();
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c216da562fbb3957b9cb2c.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c216da562fbb3957b9cb2c.md
new file mode 100644
index 00000000000..a7c1e1d3e7b
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c216da562fbb3957b9cb2c.md
@@ -0,0 +1,192 @@
+---
+id: 63c216da562fbb3957b9cb2c
+title: Step 43
+challengeType: 0
+dashedName: step-43
+---
+
+# --description--
+
+Now you need to build your dynamic HTML string to add to the webpage. Declare a new `HTMLString` variable, and assign it an empty template literal string.
+
+# --hints--
+
+Your `addEntry` function should have an `HTMLString` variable.
+
+```js
+assert.match(addEntry.toString(), /HTMLString\s*=/)
+```
+
+Your `HTMLString` should be an empty template literal.
+
+```js
+assert.match(code, /HTMLString\s*=\s*``/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length;
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c2171c1e5b6e3aa51768d0.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c2171c1e5b6e3aa51768d0.md
new file mode 100644
index 00000000000..e8ced7f3436
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c2171c1e5b6e3aa51768d0.md
@@ -0,0 +1,198 @@
+---
+id: 63c2171c1e5b6e3aa51768d0
+title: Step 44
+challengeType: 0
+dashedName: step-44
+---
+
+# --description--
+
+Start your `HTMLString` with a new line, then create a `label` element. Give that element the text `Entry # Name`, using your template literal syntax to replace `#` with the value of `entryNumber`.
+
+# --hints--
+
+Your `HTMLString` variable should start with a new line.
+
+```js
+assert.match(code, /HTMLString\s*=\s*`\n/);
+```
+
+You should add a `label` element on the new line.
+
+```js
+assert.match(code, /HTMLString\s*=\s*`\n\s*
.*<\/label>/);
+```
+
+Your `label` element should have the text `Entry ${entryNumber} Name`.
+
+```js
+assert.match(code, /HTMLString\s*=\s*`\n\s*Entry\s\$\{entryNumber\}\sName<\/label>/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length;
+ const HTMLString = ``;
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21774193de43bbc6a769f.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21774193de43bbc6a769f.md
new file mode 100644
index 00000000000..f78a3d0252c
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21774193de43bbc6a769f.md
@@ -0,0 +1,193 @@
+---
+id: 63c21774193de43bbc6a769f
+title: Step 45
+challengeType: 0
+dashedName: step-45
+---
+
+# --description--
+
+Give your `label` element a `for` attribute with the value `X-#-name`, where `X` is the `value` of the `entryDropdown` element and `#` is the value of `entryNumber`. Remember that HTML attributes should be wrapped in double quotes.
+
+# --hints--
+
+Your `label` element should have a `for` attribute set to `${entryDropdown.value}-${entryNumber}-name`.
+
+```js
+assert.match(code, /HTMLString\s*=\s*`\n\s*/)
+```
+
+Your `label` element should have the same text as before.
+
+```js
+assert.match(code, /HTMLString\s*=\s*`\n\s*Entry\s\$\{entryNumber\}\sName<\/label>/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length;
+ const HTMLString = `
+ Entry ${entryNumber} Name `;
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c217ccd939053ce4fa16d6.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c217ccd939053ce4fa16d6.md
new file mode 100644
index 00000000000..42ee9b19109
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c217ccd939053ce4fa16d6.md
@@ -0,0 +1,217 @@
+---
+id: 63c217ccd939053ce4fa16d6
+title: Step 46
+challengeType: 0
+dashedName: step-46
+---
+
+# --description--
+
+After your `label` element, and on a new line in your template string, create an `input` element. Give it a `type` attribute set to `text`, a `placeholder` attribute set to `Name`, and an `id` attribute that matches the `for` attribute of your `label` element.
+
+# --hints--
+
+You should not modify your `label` element.
+
+```js
+assert.match(code, /HTMLString\s*=\s*`\n\s*Entry\s\$\{entryNumber\}\sName<\/label>/);
+```
+
+You should add an `input` element on a new line.
+
+```js
+assert.match(code, /HTMLString\s*=\s*`\n\s*Entry\s\$\{entryNumber\}\sName<\/label>\n\s* /)[0];
+assert.include(inputAttributes, 'type="text"');
+```
+
+Your `input` element should have a `placeholder` attribute set to `Name`.
+
+```js
+const HTMLstring = code.split("HTMLString =")[1];
+const inputAttributes = HTMLstring.match(/ /)[0];
+assert.include(inputAttributes, 'placeholder="Name"');
+```
+
+Your `input` element should have an `id` attribute set to `${entryDropdown.value}-${entryNumber}-name`.
+
+```js
+const HTMLstring = code.split("HTMLString =")[1];
+const inputAttributes = HTMLstring.match(/ /)[0];
+assert.include(inputAttributes, 'id="${entryDropdown.value}-${entryNumber}-name"');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length;
+ const HTMLString = `
+ Entry ${entryNumber} Name `;
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21839f56eaf3ef4e027c4.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21839f56eaf3ef4e027c4.md
new file mode 100644
index 00000000000..cfeec0927c4
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21839f56eaf3ef4e027c4.md
@@ -0,0 +1,228 @@
+---
+id: 63c21839f56eaf3ef4e027c4
+title: Step 47
+challengeType: 0
+dashedName: step-47
+---
+
+# --description--
+
+Create another `label` element (on a new line) at the end of your `HTMLString`. This `label` should have the text `Entry # Calories`, using your template literal syntax to replace `#` with the value of `entryNumber`, and the `for` attribute set to `X-#-calories`, where `X` is the `value` of `entryDropdown` and `#` is the value of `entryNumber`.
+
+# --hints--
+
+You should have two `label` elements in your `HTMLString`.
+
+```js
+const HTMLstring = code.split("HTMLString =")[1];
+assert.equal(HTMLstring.match(/.*<\/label>/g)[1];
+assert.match(label, //)
+```
+
+Your new `label` element should have the text `Entry ${entryNumber} Calories`.
+
+```js
+const HTMLstring = code.split("HTMLString =")[1];
+const label = HTMLstring.match(/.*<\/label>/g)[1];
+assert.match(label, /Entry\s\$\{entryNumber\}\sCalories<\/label>/);
+```
+
+You should not modify your existing elements.
+
+```js
+const HTMLstring = code.split("HTMLString =")[1];
+assert.match(HTMLstring, /`\n\s*Entry\s\$\{entryNumber\}\sName<\/label>\n\s* \n\s*Entry\s\$\{entryNumber\}\sCalories<\/label>/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+ `;
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c2187f55eb0f400269568f.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c2187f55eb0f400269568f.md
new file mode 100644
index 00000000000..f0fa5f37c19
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c2187f55eb0f400269568f.md
@@ -0,0 +1,238 @@
+---
+id: 63c2187f55eb0f400269568f
+title: Step 48
+challengeType: 0
+dashedName: step-48
+---
+
+# --description--
+
+Finally, on a new line after your second `label`, create another `input` element. Give this one a `type` attribute set to `number`, a `min` attribute set to `0` (to ensure negative calories cannot be added), a `placeholder` attribute set to `Calories`, and an `id` attribute that matches the `for` attribute of your second `label` element.
+
+# --hints--
+
+You should have two `input` elements in your `HTMLString`.
+
+```js
+const HTMLstring = code.split("HTMLString =")[1];
+assert.equal(HTMLstring.match(/ ]*>/g)[1];
+assert.include(inputAttributes, 'type="number"');
+```
+
+Your `input` element should have a `placeholder` attribute set to `Calories`.
+
+```js
+const HTMLstring = code.split("HTMLString =")[1];
+const inputAttributes = HTMLstring.match(/ ]*>/g)[1];
+assert.include(inputAttributes, 'placeholder="Calories"');
+```
+
+Your `input` element should have an `id` attribute set to `${entryDropdown.value}-${entryNumber}-name`.
+
+```js
+const HTMLstring = code.split("HTMLString =")[1];
+const inputAttributes = HTMLstring.match(/ ]*>/g)[1];
+assert.include(inputAttributes, 'id="${entryDropdown.value}-${entryNumber}-calories"');
+```
+
+Your `input` element should have a `min` attribute set to `0`.
+
+```js
+const HTMLstring = code.split("HTMLString =")[1];
+const inputAttributes = HTMLstring.match(/ ]*>/g)[1];
+assert.include(inputAttributes, 'min="0"');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories `;
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c218c028c56a411b2a379a.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c218c028c56a411b2a379a.md
new file mode 100644
index 00000000000..36835a69413
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c218c028c56a411b2a379a.md
@@ -0,0 +1,208 @@
+---
+id: 63c218c028c56a411b2a379a
+title: Step 49
+challengeType: 0
+dashedName: step-49
+---
+
+# --description--
+
+Finally, add your new `HTMLString` to the `targetInputContainer` by using the `innerHTML` property. Remember to use the `+=` operator to add to the existing HTML instead of replacing it.
+
+# --hints--
+
+Your `addEntry` function should access the `innerHTML` property of `targetInputContainer`.
+
+```js
+assert.match(addEntry.toString(), /targetInputContainer\.innerHTML/);
+```
+
+You should use the `+=` operator on `targetInputContainer.innerHTML`.
+
+```js
+assert.match(addEntry.toString(), /targetInputContainer\.innerHTML\s*\+=/);
+```
+
+You should add your `HTMLString` to the `innerHTML` of the `targetInputContainer` element.
+
+```js
+assert.match(addEntry.toString(), /targetInputContainer\.innerHTML\s*\+=\s*HTMLString/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c2194dce265f429300c8b1.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c2194dce265f429300c8b1.md
new file mode 100644
index 00000000000..ebb6b922e2b
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c2194dce265f429300c8b1.md
@@ -0,0 +1,200 @@
+---
+id: 63c2194dce265f429300c8b1
+title: Step 51
+challengeType: 0
+dashedName: step-51
+---
+
+# --description--
+
+Try adding a couple of entries to the `Breakfast` category, and you may notice some bugs! The first thing we need to fix is the entry counts – the first entry should have a count of `1`, not `0`.
+
+This bug occurs because you are querying for `input[type="text"]` elements *before* adding the new entry to the page. To fix this, update your `entryNumber` variable to be the value of the `length` of the query plus `1`. Add this on your declaration line, not in your template strings.
+
+# --hints--
+
+You should add `1` to the `.length` of your `querySelectorAll()` method.
+
+```js
+assert.match(addEntry.toString(), /entryNumber\s*=\s*targetInputContainer\.querySelectorAll\(\s*'input\[type="text"]'\)\.length\s*\+\s*1/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.innerHTML += HTMLString;
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21c17fa8fd6447ff0389d.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21c17fa8fd6447ff0389d.md
new file mode 100644
index 00000000000..2d0ccd9e339
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21c17fa8fd6447ff0389d.md
@@ -0,0 +1,212 @@
+---
+id: 63c21c17fa8fd6447ff0389d
+title: Step 52
+challengeType: 0
+dashedName: step-52
+---
+
+# --description--
+
+Your other bug occurs if you add a `Breakfast` entry, fill it in, then add a second `Breakfast` entry. You'll see that the values you added disappeared.
+
+This is because you are updating `innerHTML` directly, which does not preserve your input content. Change your `innerHTML` assignment to use the `insertAdjacentHTML()` method of `targetInputContainer` instead. Do not pass any arguments yet.
+
+# --hints--
+
+You should not access the `innerHTML` property of `targetInputContainer`.
+
+```js
+assert.notMatch(addEntry.toString(), /targetInputContainer\.innerHTML/);
+```
+
+You should call the `insertAdjacentHTML()` method of `targetInputContainer`.
+
+```js
+assert.match(addEntry.toString(), /targetInputContainer\.insertAdjacentHTML\(/);
+```
+
+You should not pass any arguments to `insertAdjacentHTML()`.
+
+```js
+assert.match(addEntry.toString(), /targetInputContainer\.insertAdjacentHTML\(\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.innerHTML += HTMLString;
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21cd2c34541469f5700a9.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21cd2c34541469f5700a9.md
new file mode 100644
index 00000000000..78b1d7d6116
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21cd2c34541469f5700a9.md
@@ -0,0 +1,208 @@
+---
+id: 63c21cd2c34541469f5700a9
+title: Step 53
+challengeType: 0
+dashedName: step-53
+---
+
+# --description--
+
+The `insertAdjacentHtml` method takes two arguments. The first argument is a string that specifies the position of the inserted element. The second argument is a string containing the HTML to be inserted.
+
+For the first argument, pass the string `beforeend` to insert the new element as the last child of `targetInputContainer`.
+
+For the second argument, pass your `HTMLString` variable.
+
+# --hints--
+
+You should pass the string `beforeend` as the first argument to `insertAdjacentHTML`.
+
+```js
+assert.match(addEntry.toString(), /insertAdjacentHTML\(\s*('|")beforeend\1/);
+```
+
+You should pass your `HTMLString` variable as the second argument to `insertAdjacentHTML`.
+
+```js
+assert.match(addEntry.toString(), /insertAdjacentHTML\(\s*('|")beforeend\1\s*,\s*HTMLString\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML();
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21d4f48267a47c2946788.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21d4f48267a47c2946788.md
new file mode 100644
index 00000000000..501371edf5e
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21d4f48267a47c2946788.md
@@ -0,0 +1,216 @@
+---
+id: 63c21d4f48267a47c2946788
+title: Step 54
+challengeType: 0
+dashedName: step-54
+---
+
+# --description--
+
+Great! Now you can add entries without losing your previous inputs.
+
+Your next step is to write a function that will get the calorie counts from the user's entries.
+
+Declare a `getCaloriesFromInputs` function, and give it a parameter called `list`.
+
+# --hints--
+
+You should declare a `getCaloriesFromInputs` variable.
+
+```js
+assert.isDefined(getCaloriesFromInputs);
+```
+
+Your `getCaloriesFromInputs` variable should be a function.
+
+```js
+assert.isFunction(getCaloriesFromInputs);
+```
+
+Your `getCaloriesFromInputs` function should take a parameter called `list`.
+
+```js
+assert.match(getCaloriesFromInputs?.toString(), /\(\s*list\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21dea919c8e4adb0df8e8.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21dea919c8e4adb0df8e8.md
new file mode 100644
index 00000000000..b4f31e92cea
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21dea919c8e4adb0df8e8.md
@@ -0,0 +1,212 @@
+---
+id: 63c21dea919c8e4adb0df8e8
+title: Step 50
+challengeType: 0
+dashedName: step-50
+---
+
+# --description--
+
+In the Role Playing Game project, you learned how to set a button's behavior by editing its `onclick` property. You can also edit an element's behavior by adding an event listener.
+
+Call the `.addEventListener()` method of the `addEntryButton`. This takes two arguments. The first is the event to listen to – you should pass the string `click`. The second is the callback function, or the function that runs when the event is triggered. Pass the `addEntry` function as the second argument. Note that you should not *call* `addEntry`, but pass the variable (or function reference ) directly.
+
+# --hints--
+
+You should call the `.addEventListener()` method of the `addEntryButton`.
+
+```js
+assert.match(code, /addEntryButton\.addEventListener\(/);
+```
+
+You should pass `click` as the first argument to the `.addEventListener()` method.
+
+```js
+assert.match(code, /addEntryButton\.addEventListener\(\s*('|")click\1\s*/);
+```
+
+You should pass `addEntry` as the second argument to the `.addEventListener()` method.
+
+```js
+assert.match(code, /addEntryButton\.addEventListener\(\s*('|")click\1\s*,\s*addEntry\s*/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.innerHTML += HTMLString;
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8ab51214c8c1f1b9a49f7.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8ab51214c8c1f1b9a49f7.md
new file mode 100644
index 00000000000..8d47f896df1
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8ab51214c8c1f1b9a49f7.md
@@ -0,0 +1,216 @@
+---
+id: 63c8ab51214c8c1f1b9a49f7
+title: Step 55
+challengeType: 0
+dashedName: step-55
+---
+
+# --description--
+
+In your new function, declare a `calories` variable and assign it the value `0`. Use `let` to declare it, since you will be reassigning it later.
+
+# --hints--
+
+You should declare a `calories` variable.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /calories\s*=/);
+```
+
+Your `calories` variable should be assigned the value `0`.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /calories\s*=\s*0/);
+```
+
+You should declare your `calories` variable with `let`.
+
+```js
+// babel transforms the code, so we gotta do a hack here
+const getCaloriesFromInputsString = code.split('function getCaloriesFromInputs')[1];
+assert.match(getCaloriesFromInputsString, /let\s+calories\s*=\s*0/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function getCaloriesFromInputs(list) {
+
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8ad0cd8f1e5201c4ef2e4.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8ad0cd8f1e5201c4ef2e4.md
new file mode 100644
index 00000000000..4da040ed199
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8ad0cd8f1e5201c4ef2e4.md
@@ -0,0 +1,224 @@
+---
+id: 63c8ad0cd8f1e5201c4ef2e4
+title: Step 56
+challengeType: 0
+dashedName: step-56
+---
+
+# --description--
+
+The `list` parameter is going to be the result of a query selector, which will return a `NodeList`. A `NodeList` is an array-like which contains the elements that match the query selector.
+
+You'll need to loop through these elements, so start by creating a `for` loop. Your iterator `i` should start at `0`, continue while it is less than the length of the list, and increment by `1` each iteration.
+
+# --hints--
+
+Your `getCaloriesFromInputs` function should have a `for` loop.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /for\s*\(/g);
+```
+
+Your `for` loop should initialize a variable called `i` to `0`.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /for\s*\(\s*(let|var)\s+i\s*=\s*0\s*;/g);
+```
+
+Your `for` loop should have a condition that checks if `i` is less than the length of `list`.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /for\s*\(\s*(let|var)\s+i\s*=\s*0\s*;\s*i\s*<\s*list\.length\s*;/g);
+```
+
+Your `for` loop should increment `i` by `1` each time it runs. Use the increment operator for this.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /for\s*\(\s*(let|var)\s+i\s*=\s*0\s*;\s*i\s*<\s*list\.length\s*;\s*i\s*\+\+\s*\)/g);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8b0187cceff21c8389543.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8b0187cceff21c8389543.md
new file mode 100644
index 00000000000..645fcaa4d24
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8b0187cceff21c8389543.md
@@ -0,0 +1,234 @@
+---
+id: 63c8b0187cceff21c8389543
+title: Step 57
+challengeType: 0
+dashedName: step-57
+---
+
+# --description--
+
+The `NodeList` values you will pass to `list` will consist of `input` elements. So you will want to look at the `value` attribute of each element.
+
+Assign the `value` of the element in `list` at index `i` to a variable called `currVal`.
+
+# --hints--
+
+You should have a `currVal` variable.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /currVal\s*=/);
+```
+
+You should access the element in `list` at index `i` using bracket notation.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /list\[i\]/);
+```
+
+You should access the `value` attribute of the element in `list` at index `i`.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /list\[i\]\.value/);
+```
+
+You should assign the `value` of the element in `list` at index `i` to a variable called `currVal`.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /currVal\s*=\s*list\[i\]\.value/);
+```
+
+Your `currVal` assignment should be in your `for` loop.
+
+```js
+// another hack, because the loop protection injects stuff
+const getCaloriesString = code.split("function getCaloriesFromInputs")[1];
+assert.match(getCaloriesString, /for\s*\(\s*let\s+i\s*=\s*0\s*;\s*i\s*<\s*list\.length\s*;\s*i\s*\+\+\s*\)\s*\{\s*const|let\s*currVal\s*=\s*list\[i\]\.value/g);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+
+ }
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8be904ffff922f3c6f8d0.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8be904ffff922f3c6f8d0.md
new file mode 100644
index 00000000000..ae8ef40dd20
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8be904ffff922f3c6f8d0.md
@@ -0,0 +1,221 @@
+---
+id: 63c8be904ffff922f3c6f8d0
+title: Step 58
+challengeType: 0
+dashedName: step-58
+---
+
+# --description--
+
+Remember that you wrote a function earlier to clean the user's input? You'll need to use that function here.
+
+Update your `currVal` declaration to be the result of calling `cleanInputString` with `list[i].value`.
+
+# --hints--
+
+Your `getCaloriesFromInputs` function should call your `cleanInputString` function.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /cleanInputString\(/);
+```
+
+You should pass `list[i].value` as the parameter for `cleanInputString`.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /cleanInputString\(\s*list\[i\]\.value\)/);
+```
+
+You should assign the result of your `cleanInputString` call to your `currVal` variable.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /currVal\s*=\s*cleanInputString\(\s*list\[i\]\.value\)/);
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = list[i].value;
+ }
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8c00bfb671b23f9de4159.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8c00bfb671b23f9de4159.md
new file mode 100644
index 00000000000..a994632ff24
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8c00bfb671b23f9de4159.md
@@ -0,0 +1,219 @@
+---
+id: 63c8c00bfb671b23f9de4159
+title: Step 59
+challengeType: 0
+dashedName: step-59
+---
+
+# --description--
+
+You also need to confirm the input is valid. Declare an `invalidInputMatch` variable, and assign it the result of calling your `isInvalidInput` function with `currVal` as the argument.
+
+# --hints--
+
+You should declare an `invalidInputMatch` variable.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /invalidInputMatch\s*=/);
+```
+
+You should assign the result of calling `isInvalidInput` to your `invalidInputMatch` variable.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /invalidInputMatch\s*=\s*isInvalidInput\(/);
+```
+
+You should pass `currVal` as the parameter to `isInvalidInput`.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /invalidInputMatch\s*=\s*isInvalidInput\(\s*currVal\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+
+ }
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8c15fd337ad24b9b68049.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8c15fd337ad24b9b68049.md
new file mode 100644
index 00000000000..57c63d650b8
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8c15fd337ad24b9b68049.md
@@ -0,0 +1,233 @@
+---
+id: 63c8c15fd337ad24b9b68049
+title: Step 60
+challengeType: 0
+dashedName: step-60
+---
+
+# --description--
+
+Remember that your `isInvalidInput` function returns `String.match`, which is an array of matches or `null` if no matches are found.
+
+In JavaScript, values can either be truthy or falsy . A value is truthy if it evaluates to `true` when converted to a Boolean. A value is falsy if it evaluates to `false` when converted to a Boolean. `null` is an example of a falsy value.
+
+You need to check if `invalidInputMatch` is truthy – you can do this by passing the variable directly to your `if` condition (without a comparison operator). Here's an example of checking the truthiness of `helloWorld`.
+
+```js
+if (helloWorld) {
+
+}
+```
+
+Add an `if` statement that checks if `invalidInputMatch` is truthy.
+
+# --hints--
+
+You should add an `if` statement to your `getCaloriesFromInputs` function.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /if\s*\(/);
+```
+
+You should check the truthiness of `invalidInputMatch` in your `if` condition.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /if\s*\(\s*invalidInputMatch\s*\)/);
+```
+
+Your `if` statement should be inside your `for` loop.
+
+```js
+assert.isBelow(getCaloriesFromInputs.toString().indexOf("for"), getCaloriesFromInputs.toString().indexOf("if"));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+
+ }
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bc53735149084390e5d0.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bc53735149084390e5d0.md
new file mode 100644
index 00000000000..c5beb8876e8
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bc53735149084390e5d0.md
@@ -0,0 +1,226 @@
+---
+id: 63c9bc53735149084390e5d0
+title: Step 61
+challengeType: 0
+dashedName: step-61
+---
+
+# --description--
+
+Browsers have a built in `alert()` function, which you can use to display a pop-up message to the user. The message to display is passed as the argument to the `alert()` function.
+
+Using a template literal, in your `if` block, call the `alert()` function to tell the user `Invalid Input:`, followed by the first value in the `invalidInputMatch` array.
+
+# --hints--
+
+You should call the `alert()` function in your `if` block.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /if\s*\(\s*invalidInputMatch\s*\)\s*\{\s*alert\(/);
+```
+
+You should use a template literal to pass the `Invalid Input:` message to the `alert()` function.
+
+```js
+// because it transforms template literals...
+assert.match(code.split("function getCaloriesFromInputs")[1], /alert\(`Invalid Input: /);
+```
+
+You should use template literal syntax to display the first value in the `invalidInputMatch` array after the `Invalid Input:` text.
+
+```js
+assert.match(code.split("function getCaloriesFromInputs")[1], /alert\(`Invalid Input: \${invalidInputMatch\[0\]}`\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+
+ }
+ }
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bcc26219e7090da0f549.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bcc26219e7090da0f549.md
new file mode 100644
index 00000000000..8857c49a4af
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bcc26219e7090da0f549.md
@@ -0,0 +1,218 @@
+---
+id: 63c9bcc26219e7090da0f549
+title: Step 62
+challengeType: 0
+dashedName: step-62
+---
+
+# --description--
+
+Still within your `if` block, set `isError` to `true` and return `null`.
+
+# --hints--
+
+After your `alert`, you should set `isError` to `true`.
+
+```js
+assert.match(code.split("function getCaloriesFromInputs")[1], /alert\(`Invalid Input: \${invalidInputMatch\[0\]}`\s*\);\s*isError\s*=\s*true/);
+```
+
+After you modify `isError`, you should `return` the value `null`.
+
+```js
+assert.match(code.split("function getCaloriesFromInputs")[1], /alert\(`Invalid Input: \${invalidInputMatch\[0\]}`\s*\);\s*isError\s*=\s*true;?\s*return\s+null;?\s*\}/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+
+ }
+ }
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bce376ca4f09c15a3768.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bce376ca4f09c15a3768.md
new file mode 100644
index 00000000000..9e327dd56a4
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bce376ca4f09c15a3768.md
@@ -0,0 +1,234 @@
+---
+id: 63c9bce376ca4f09c15a3768
+title: Step 63
+challengeType: 0
+dashedName: step-63
+---
+
+# --description--
+
+Remember that `return` ends the execution of a function. After your `if` block, you need to handle the logic for when the input is valid. Because your `if` statement returns a value, you do not need an `else` statement.
+
+Use the addition assignment operator to add `currVal` to your `calories` total. You'll need to use the `Number` constructor to convert `currVal` to a number.
+
+# --hints--
+
+You should not add an `else` statement.
+
+```js
+assert.notMatch(getCaloriesFromInputs.toString(), /else/);
+```
+
+After your `if` statement, you should use the addition assignment operator on `calories`.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /if.*}\s*calories\s*\+=/s);
+```
+
+You should pass `currVal` to the `Number()` constructor.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /Number\(\s*currVal\s*\)/);
+```
+
+You should add the value of `Number(currVal)` to `calories`.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /calories\s*\+=\s*Number\(\s*currVal\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+
+ }
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bdd916e0c10af01ed8d7.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bdd916e0c10af01ed8d7.md
new file mode 100644
index 00000000000..ba37342ef6c
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bdd916e0c10af01ed8d7.md
@@ -0,0 +1,221 @@
+---
+id: 63c9bdd916e0c10af01ed8d7
+title: Step 64
+challengeType: 0
+dashedName: step-64
+---
+
+# --description--
+
+After your `for` loop has completed, return the `calories` value.
+
+# --hints--
+
+You should `return` the `calories` value.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /return\s+calories/);
+```
+
+Your new `return` statement should come after your `for` loop.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /calories\s*\+=\sNumber\(currVal\);\n\s*}\n\s*return\s+calories/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9be334f4a050c0b94bc93.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9be334f4a050c0b94bc93.md
new file mode 100644
index 00000000000..2a4f6d26012
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9be334f4a050c0b94bc93.md
@@ -0,0 +1,229 @@
+---
+id: 63c9be334f4a050c0b94bc93
+title: Step 65
+challengeType: 0
+dashedName: step-65
+---
+
+# --description--
+
+Now it's time to start putting it all together. Declare an empty `calculateCalories` function, which takes a parameter named `e`. This function will be another event listener, so the first argument passed will be the browser event – `e` is a common name for this parameter.
+
+# --hints--
+
+You should declare a `calculateCalories` variable.
+
+```js
+assert.isDefined(calculateCalories);
+```
+
+Your `calculateCalories` variable should be a function.
+
+```js
+assert.isFunction(calculateCalories);
+```
+
+Your `calculateCalories` function should take an `e` argument.
+
+```js
+assert.match(calculateCalories?.toString(), /\(e\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bef7fec05c0d38853828.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bef7fec05c0d38853828.md
new file mode 100644
index 00000000000..13d558d532c
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bef7fec05c0d38853828.md
@@ -0,0 +1,227 @@
+---
+id: 63c9bef7fec05c0d38853828
+title: Step 66
+challengeType: 0
+dashedName: step-66
+---
+
+# --description--
+
+You will be attaching this function to the `submit` event of the form. The `submit` event is triggered when the form is submitted. The default action of the `submit` event is to reload the page. You need to prevent this default action using the `preventDefault()` method of your `e` parameter.
+
+Add a line to your `calculateCalories` function that calls the `preventDefault()` method on the `e` parameter. Then, reset your global error flag to `false`.
+
+# --hints--
+
+Your `calculateCalories` function should call `e.preventDefault()`.
+
+```js
+assert.match(calculateCalories.toString(), /e\.preventDefault\(\)/);
+```
+
+Your `calculateCalories` function should reset the global error flag to `false`.
+
+```js
+assert.match(calculateCalories.toString(), /isError\s*=\s*false/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bf80558d780e848b2987.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bf80558d780e848b2987.md
new file mode 100644
index 00000000000..4e4da977f9e
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bf80558d780e848b2987.md
@@ -0,0 +1,236 @@
+---
+id: 63c9bf80558d780e848b2987
+title: Step 67
+challengeType: 0
+dashedName: step-67
+---
+
+# --description--
+
+Your function needs to get the values from the entries the user has added.
+
+Declare a `breakfastNumberInputs` variable, and give it the value of calling `document.querySelectorAll()` with the selector `#breakfast input[type=number]`. This will return any `number` inputs that are in the `#breakfast` element.
+
+# --hints--
+
+You should declare a `breakfastNumberInputs` variable.
+
+```js
+assert.match(calculateCalories.toString(), /breakfastNumberInputs\s*=/);
+```
+
+You should call `document.querySelectorAll()` with `#breakfast input[type=number]`.
+
+```js
+assert.match(calculateCalories.toString(), /document\.querySelectorAll\(('|")#breakfast input\[type=number\]\1\)/);
+```
+
+You should assign the result of your `odocument.querySelectorAll()` call to `breakfastNumberInputs`.
+
+```js
+assert.match(calculateCalories.toString(), /breakfastNumberInputs\s*=\s*document\.querySelectorAll\(('|")#breakfast input\[type=number\]\1\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9c09a7daa4f0ff92c4023.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9c09a7daa4f0ff92c4023.md
new file mode 100644
index 00000000000..84fd6422b00
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9c09a7daa4f0ff92c4023.md
@@ -0,0 +1,235 @@
+---
+id: 63c9c09a7daa4f0ff92c4023
+title: Step 68
+challengeType: 0
+dashedName: step-68
+---
+
+# --description--
+
+Using that same syntax, query your `number` inputs in the `#lunch` element and assign them to `lunchNumberInputs`.
+
+# --hints--
+
+You should declare a `lunchNumberInputs` variable.
+
+```js
+assert.match(calculateCalories.toString(), /lunchNumberInputs\s*=/);
+```
+
+You should call `document.querySelectorAll()` with `#lunch input[type=number]`.
+
+```js
+assert.match(calculateCalories.toString(), /document\.querySelectorAll\(('|")#lunch input\[type=number\]\1\)/);
+```
+
+You should assign the result of your `document.querySelectorAll()` call to `lunchNumberInputs`.
+
+```js
+assert.match(calculateCalories.toString(), /lunchNumberInputs\s*=\s*document\.querySelectorAll\(('|")#lunch input\[type=number\]\1\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9c0d0857f0a10a57af936.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9c0d0857f0a10a57af936.md
new file mode 100644
index 00000000000..8868dc1350c
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9c0d0857f0a10a57af936.md
@@ -0,0 +1,272 @@
+---
+id: 63c9c0d0857f0a10a57af936
+title: Step 69
+challengeType: 0
+dashedName: step-69
+---
+
+# --description--
+
+Following the same pattern, query for your `number` inputs in the `#dinner`, `#snacks`, and `#exercise` elements. Assign them to variables following the naming scheme of the previous two.
+
+# --hints--
+
+You should declare a `dinnerNumberInputs` variable.
+
+```js
+assert.match(calculateCalories.toString(), /dinnerNumberInputs\s*=/);
+```
+
+You should call `document.querySelectorAll()` with `#dinner input[type=number]`.
+
+```js
+assert.match(calculateCalories.toString(), /document\.querySelectorAll\(('|")#dinner input\[type=number\]\1\)/);
+```
+
+You should assign the result of your `document.querySelectorAll()` call to `dinnerNumberInputs`.
+
+```js
+assert.match(calculateCalories.toString(), /dinnerNumberInputs\s*=\s*document\.querySelectorAll\(('|")#dinner input\[type=number\]\1\)/);
+```
+
+You should declare a `snacksNumberInputs` variable.
+
+```js
+assert.match(calculateCalories.toString(), /snacksNumberInputs\s*=/);
+```
+
+You should call `document.querySelectorAll()` with `#snacks input[type=number]`.
+
+```js
+assert.match(calculateCalories.toString(), /document\.querySelectorAll\(('|")#snacks input\[type=number\]\1\)/);
+```
+
+You should assign the result of your `document.querySelectorAll()` call to `snacksNumberInputs`.
+
+```js
+assert.match(calculateCalories.toString(), /snacksNumberInputs\s*=\s*document\.querySelectorAll\(('|")#snacks input\[type=number\]\1\)/);
+```
+
+You should declare a `exerciseNumberInputs` variable.
+
+```js
+assert.match(calculateCalories.toString(), /exerciseNumberInputs\s*=/);
+```
+
+You should call `document.querySelectorAll()` with `#exercise input[type=number]`.
+
+```js
+assert.match(calculateCalories.toString(), /document\.querySelectorAll\(('|")#exercise input\[type=number\]\1\)/);
+```
+
+You should assign the result of your `document.querySelectorAll()` call to `exerciseNumberInputs`.
+
+```js
+assert.match(calculateCalories.toString(), /exerciseNumberInputs\s*=\s*document\.querySelectorAll\(('|")#exercise input\[type=number\]\1\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9c11a0a090311dff55564.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9c11a0a090311dff55564.md
new file mode 100644
index 00000000000..dd2be81cbc5
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9c11a0a090311dff55564.md
@@ -0,0 +1,242 @@
+---
+id: 63c9c11a0a090311dff55564
+title: Step 70
+challengeType: 0
+dashedName: step-70
+---
+
+# --description--
+
+Now that you have your lists of elements, you can pass them to your `getCaloriesFromInputs` function to extract the calorie total.
+
+Declare a `breakfastCalories` variable, and assign it the result of calling `getCaloriesFromInputs` with `breakfastNumberInputs` as the argument.
+
+# --hints--
+
+Your `calculateCalories` function should have a `breakfastCalories` variable.
+
+```js
+assert.match(calculateCalories.toString(), /breakfastCalories\s*=/);
+```
+
+You should call `getCaloriesFromInputs` with `breakfastNumberInputs` as the argument.
+
+```js
+assert.match(calculateCalories.toString(), /getCaloriesFromInputs\s*\(\s*breakfastNumberInputs\s*\)/);
+```
+
+You should assign the result of `getCaloriesFromInputs` to `breakfastCalories`.
+
+```js
+assert.match(calculateCalories.toString(), /breakfastCalories\s*=\s*getCaloriesFromInputs\s*\(\s*breakfastNumberInputs\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9c16dd75dd212dc12363c.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9c16dd75dd212dc12363c.md
new file mode 100644
index 00000000000..779bb1a2aed
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9c16dd75dd212dc12363c.md
@@ -0,0 +1,241 @@
+---
+id: 63c9c16dd75dd212dc12363c
+title: Step 71
+challengeType: 0
+dashedName: step-71
+---
+
+# --description--
+
+Now declare a `lunchCalories` variable, and give it the value of calling `getCaloriesFromInputs` with your `lunchNumberInputs`.
+
+# --hints--
+
+Your `calculateCalories` function should have a `lunchCalories` variable.
+
+```js
+assert.match(calculateCalories.toString(), /lunchCalories\s*=/);
+```
+
+You should call `getCaloriesFromInputs` with `lunchNumberInputs` as the argument.
+
+```js
+assert.match(calculateCalories.toString(), /getCaloriesFromInputs\s*\(\s*lunchNumberInputs\s*\)/);
+```
+
+You should assign the result of `getCaloriesFromInputs` to `lunchCalories`.
+
+```js
+assert.match(calculateCalories.toString(), /lunchCalories\s*=\s*getCaloriesFromInputs\s*\(\s*lunchNumberInputs\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9c1ef134f3513e751c975.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9c1ef134f3513e751c975.md
new file mode 100644
index 00000000000..4bd18bc353f
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9c1ef134f3513e751c975.md
@@ -0,0 +1,278 @@
+---
+id: 63c9c1ef134f3513e751c975
+title: Step 72
+challengeType: 0
+dashedName: step-72
+---
+
+# --description--
+
+Following this same pattern, declare variables for the `number` inputs in the `#dinner`, `#snacks`, and `#exercise` elements. Assign them the appropriate `getCaloriesFromInputs` calls.
+
+# --hints--
+
+Your `calculateCalories` function should have a `dinnerCalories` variable.
+
+```js
+assert.match(calculateCalories.toString(), /dinnerCalories\s*=/);
+```
+
+You should call `getCaloriesFromInputs` with `dinnerNumberInputs` as the argument.
+
+```js
+assert.match(calculateCalories.toString(), /getCaloriesFromInputs\s*\(\s*dinnerNumberInputs\s*\)/);
+```
+
+You should assign the result of `getCaloriesFromInputs` to `dinnerCalories`.
+
+```js
+assert.match(calculateCalories.toString(), /dinnerCalories\s*=\s*getCaloriesFromInputs\s*\(\s*dinnerNumberInputs\s*\)/);
+```
+
+Your `calculateCalories` function should have a `snacksCalories` variable.
+
+```js
+assert.match(calculateCalories.toString(), /snacksCalories\s*=/);
+```
+
+You should call `getCaloriesFromInputs` with `snacksNumberInputs` as the argument.
+
+```js
+assert.match(calculateCalories.toString(), /getCaloriesFromInputs\s*\(\s*snacksNumberInputs\s*\)/);
+```
+
+You should assign the result of `getCaloriesFromInputs` to `snacksCalories`.
+
+```js
+assert.match(calculateCalories.toString(), /snacksCalories\s*=\s*getCaloriesFromInputs\s*\(\s*snacksNumberInputs\s*\)/);
+```
+
+Your `calculateCalories` function should have a `exerciseCalories` variable.
+
+```js
+assert.match(calculateCalories.toString(), /exerciseCalories\s*=/);
+```
+
+You should call `getCaloriesFromInputs` with `exerciseNumberInputs` as the argument.
+
+```js
+assert.match(calculateCalories.toString(), /getCaloriesFromInputs\s*\(\s*exerciseNumberInputs\s*\)/);
+```
+
+You should assign the result of `getCaloriesFromInputs` to `exerciseCalories`.
+
+```js
+assert.match(calculateCalories.toString(), /exerciseCalories\s*=\s*getCaloriesFromInputs\s*\(\s*exerciseNumberInputs\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e3a83bb3e61a80eea564.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e3a83bb3e61a80eea564.md
new file mode 100644
index 00000000000..3df7e192a70
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e3a83bb3e61a80eea564.md
@@ -0,0 +1,249 @@
+---
+id: 63c9e3a83bb3e61a80eea564
+title: Step 73
+challengeType: 0
+dashedName: step-73
+---
+
+# --description--
+
+You also need to get the value of your `#budget` input. You already queried this at the top of your code, and set it to the `budgetNumberInput` variable. However, you used `getElementById`, which returns an `Element`, not a `NodeList`.
+
+A `NodeList` is an array-like, which means you can iterate through it and it shares some common methods with an array. For your `getCaloriesFromInputs` function, an array will work for the argument just as well as a `NodeList` does.
+
+Declare a `budgetCalories` variable and set it to the result of calling `getCaloriesFromInputs` – pass an array containing your `budgetNumberInput` as the argument.
+
+# --hints--
+
+Your `calculateCalories` function should have a `budgetCalories` variable.
+
+```js
+assert.match(calculateCalories.toString(), /budgetCalories\s*=/);
+```
+
+You should call `getCaloriesFromInputs` with `[budgetNumberInput]` as the argument.
+
+```js
+assert.match(calculateCalories.toString(), /getCaloriesFromInputs\s*\(\s*\[\s*budgetNumberInput\s*\]\s*\)/);
+```
+
+You should assign the result of `getCaloriesFromInputs` to `budgetCalories`.
+
+```js
+assert.match(calculateCalories.toString(), /budgetCalories\s*=\s*getCaloriesFromInputs\s*\(\s*\[\s*budgetNumberInput\s*\]\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e45519caf31b987fbb5f.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e45519caf31b987fbb5f.md
new file mode 100644
index 00000000000..c49004bbebb
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e45519caf31b987fbb5f.md
@@ -0,0 +1,247 @@
+---
+id: 63c9e45519caf31b987fbb5f
+title: Step 74
+challengeType: 0
+dashedName: step-74
+---
+
+# --description--
+
+Your `getCaloriesFromInputs` function will set the global error flag to `true` if an invalid input is detected. Add an `if` statement to your `calculateCalories` function that checks the truthiness of your global error flag, and if it is truthy then use `return` to end the function execution.
+
+# --hints--
+
+Your `calculateCalories` function should have an `if` statement.
+
+```js
+assert.match(calculateCalories.toString(), /if\s*\(/);
+```
+
+Your `if` statement should check the truthiness of the `isError` variable.
+
+```js
+assert.match(calculateCalories.toString(), /if\s*\(\s*isError\s*\)/);
+```
+
+Your `if` statement should use `return` to end the function execution.
+
+```js
+assert.match(calculateCalories.toString(), /if\s*\(\s*isError\s*\)\s*\{?\s*return;?\s*\}?\s*/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e4d2ff41811dd640504f.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e4d2ff41811dd640504f.md
new file mode 100644
index 00000000000..4f917ca49a0
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e4d2ff41811dd640504f.md
@@ -0,0 +1,257 @@
+---
+id: 63c9e4d2ff41811dd640504f
+title: Step 75
+challengeType: 0
+dashedName: step-75
+---
+
+# --description--
+
+It is time to start preparing your calculations. Start by declaring a `consumedCalories` variable, and assign it the sum of `breakfastCalories`, `lunchCalories`, `dinnerCalories`, and `snacksCalories` (note that order matters for the tests). Be sure to do this after your `if` statement.
+
+# --hints--
+
+Your function should have a `consumedCalories` variable.
+
+```js
+assert.match(calculateCalories.toString(), /consumedCalories\s*=/);
+```
+
+Your `consumedCalories` variable should come after your `if` statement.
+
+```js
+assert.isAbove(calculateCalories.toString().indexOf('consumedCalories'), calculateCalories.toString().indexOf('if'));
+```
+
+You should calculate the sum of `breakfastCalories`, `lunchCalories`, `dinnerCalories`, and `snacksCalories`, in order.
+
+```js
+assert.match(calculateCalories.toString(), /breakfastCalories\s*\+\s*lunchCalories\s*\+\s*dinnerCalories\s*\+\s*snacksCalories/);
+```
+
+You should assign the sum of `breakfastCalories`, `lunchCalories`, `dinnerCalories`, and `snacksCalories` to `consumedCalories`.
+
+```js
+assert.match(calculateCalories.toString(), /consumedCalories\s*=\s*breakfastCalories\s*\+\s*lunchCalories\s*\+\s*dinnerCalories\s*\+\s*snacksCalories/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e51b3a007a1eba1cd0f6.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e51b3a007a1eba1cd0f6.md
new file mode 100644
index 00000000000..81b19870fd2
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e51b3a007a1eba1cd0f6.md
@@ -0,0 +1,252 @@
+---
+id: 63c9e51b3a007a1eba1cd0f6
+title: Step 76
+challengeType: 0
+dashedName: step-76
+---
+
+# --description--
+
+Now declare a `remainingCalories` variable, and give it the value of subtracting `consumedCalories` from `budgetCalories` and adding `exerciseCalories`.
+
+# --hints--
+
+Your `calculateCalories` function should have a `remainingCalories` variable.
+
+```js
+assert.match(calculateCalories.toString(), /remainingCalories\s*=/);
+```
+
+You should find the value of `budgetCalories - consumedCalories + exerciseCalories`.
+
+```js
+assert.match(calculateCalories.toString(), /budgetCalories\s*-\s*consumedCalories\s*\+\s*exerciseCalories/);
+```
+
+You should assign the value of `budgetCalories - consumedCalories + exerciseCalories` to `remainingCalories`.
+
+```js
+assert.match(calculateCalories.toString(), /remainingCalories\s*=\s*budgetCalories\s*-\s*consumedCalories\s*\+\s*exerciseCalories/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e55b4b06c11fff555c64.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e55b4b06c11fff555c64.md
new file mode 100644
index 00000000000..bc911d3b831
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e55b4b06c11fff555c64.md
@@ -0,0 +1,267 @@
+---
+id: 63c9e55b4b06c11fff555c64
+title: Step 77
+challengeType: 0
+dashedName: step-77
+---
+
+# --description--
+
+You need to know if the user's calories are a surplus or a deficit. Declare a `surplusOrDeficit` variable.
+
+Use a ternary operator to set `surplusOrDeficit` to the string `Surplus` or `Deficit` depending on whether `remainingCalories` is greater than or equal to `0`. If it is greater than or equal to `0`, then `surplusOrDeficit` should be `Surplus`. Otherwise, it should be `Deficit`.
+
+# --hints--
+
+Your `calculateCalories` function should have a `surplusOrDeficit` variable.
+
+```js
+assert.match(calculateCalories.toString(), /surplusOrDeficit\s*=/g);
+```
+
+You should have a ternary operator that checks if `remainingCalories` is greater than or equal to `0`.
+
+```js
+assert.match(calculateCalories.toString(), /remainingCalories\s*>=\s*0\s*\?/g);
+```
+
+Your ternary operator return the string `Surplus` if `remainingCalories` is greater than or equal to `0`.
+
+```js
+assert.match(calculateCalories.toString(), /remainingCalories\s*>=\s*0\s*\?\s*('|")Surplus\1\s*:/g);
+```
+
+Your ternary operator return the string `Deficit` if `remainingCalories` is not greater than or equal to `0`.
+
+```js
+assert.match(calculateCalories.toString(), /remainingCalories\s*>=\s*0\s*\?\s*('|")Surplus\1\s*:\s*('|")Deficit\2/g);
+```
+
+You should assign the result of your ternary operator to `surplusOrDeficit`.
+
+```js
+assert.match(calculateCalories.toString(), /surplusOrDeficit\s*=\s*remainingCalories\s*>=\s*0\s*\?\s*('|")Surplus\1\s*:\s*('|")Deficit\2/g);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e5eea8261d22856ead1c.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e5eea8261d22856ead1c.md
new file mode 100644
index 00000000000..01ebba201d2
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e5eea8261d22856ead1c.md
@@ -0,0 +1,250 @@
+---
+id: 63c9e5eea8261d22856ead1c
+title: Step 78
+challengeType: 0
+dashedName: step-78
+---
+
+# --description--
+
+You need to construct the HTML string that will be displayed in the `output` element. Start by assigning an empty template literal to the `innerHTML` property of the `output` element.
+
+# --hints--
+
+You should access the `innerHTML` property of the `output` element.
+
+```js
+assert.match(calculateCalories.toString(), /output\s*\.\s*innerHTML/);
+```
+
+You should assign an empty template literal to the `innerHTML` property of the `output` element.
+
+```js
+// again, template literals don't play well with the parser so we have to look at the raw code.
+const htmlString = code.split(/output\s*\.\s*innerHTML\s*=\s*/)[1].split(/;?\s*\}/)[0];
+assert.equal(htmlString, '``');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e63bb1e32d23b6adbe44.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e63bb1e32d23b6adbe44.md
new file mode 100644
index 00000000000..5711b833a42
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e63bb1e32d23b6adbe44.md
@@ -0,0 +1,266 @@
+---
+id: 63c9e63bb1e32d23b6adbe44
+title: Step 79
+challengeType: 0
+dashedName: step-79
+---
+
+# --description--
+
+Your `output.innerHTML` string will need a `span` element. Create that, and give it a `class` attribute set to the `surplusOrDeficit` variable, but lowercased.
+
+Strings have a `.toLowerCase()` method that can help you with this. Do not give your `span` any text yet.
+
+# --hints--
+
+You should create a `span` element in your template literal.
+
+```js
+const htmlString = code.split(/output\s*\.\s*innerHTML\s*=\s*/)[1].split(/`/)[1];
+assert.match(htmlString, //);
+```
+
+Your `span` should not have any text.
+
+```js
+const htmlString = code.split(/output\s*\.\s*innerHTML\s*=\s*/)[1].split(/`/)[1];
+assert.match(htmlString, /<\/span>/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = ``;
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e6b7c0303524af2d0bc2.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e6b7c0303524af2d0bc2.md
new file mode 100644
index 00000000000..ee4568c97d6
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e6b7c0303524af2d0bc2.md
@@ -0,0 +1,245 @@
+---
+id: 63c9e6b7c0303524af2d0bc2
+title: Step 80
+challengeType: 0
+dashedName: step-80
+---
+
+# --description--
+
+Give your span the text `remainingCalories Calorie surplusOrDeficit`, using interpolation to replace `remainingCalories` and `surplusOrDeficit` with the appropriate variables.
+
+# --hints--
+
+Your `span` should have the text `${remainingCalories} Calorie ${surplusOrDeficit}`.
+
+```js
+const htmlString = code.split(/output\s*\.\s*innerHTML\s*=\s*/)[1].split(/`/)[1];
+assert.match(htmlString, /\$\{remainingCalories\} Calorie \$\{surplusOrDeficit\}<\/span>/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+
+ `;
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e769df38c92635c158ba.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e769df38c92635c158ba.md
new file mode 100644
index 00000000000..cec54f93795
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e769df38c92635c158ba.md
@@ -0,0 +1,254 @@
+---
+id: 63c9e769df38c92635c158ba
+title: Step 81
+challengeType: 0
+dashedName: step-81
+---
+
+# --description--
+
+When the user has a calorie deficit, the `remainingCalories` value will be negative. You don't want to display a negative number in the result string.
+
+`Math.abs()` is a built-in JavaScript method that will return the absolute value of a number. In your `span` text, wrap your `remainingCalories` reference in `Math.abs()` to ensure that the value is positive.
+
+# --hints--
+
+You should wrap the `remainingCalories` variable in `Math.abs()`.
+
+```js
+const htmlString = code.split(/output\s*\.\s*innerHTML\s*=\s*/)[1].split(/`/)[1];
+assert.match(htmlString, /Math\.abs\(\s*remainingCalories\s*\)/);
+```
+
+Your `span` should have the text `${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}`.
+
+```js
+const htmlString = code.split(/output\s*\.\s*innerHTML\s*=\s*/)[1].split(/`/)[1];
+assert.match(htmlString, /\$\{Math\.abs\(remainingCalories\)\} Calorie \$\{surplusOrDeficit\}<\/span>/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+ ${remainingCalories} Calorie ${surplusOrDeficit}
+ `;
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e7d5b21eee2776ecc226.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e7d5b21eee2776ecc226.md
new file mode 100644
index 00000000000..d341d5e62bf
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e7d5b21eee2776ecc226.md
@@ -0,0 +1,262 @@
+---
+id: 63c9e7d5b21eee2776ecc226
+title: Step 82
+challengeType: 0
+dashedName: step-82
+---
+
+# --description--
+
+After your `span` element, add an `hr` element to create a horizontal line.
+
+To keep your code clean and readable, you should add this on a new line in the template literal.
+
+# --hints--
+
+You should add an `hr` element to your `output.innerHTML` string.
+
+```js
+const htmlString = code.split(/output\s*\.\s*innerHTML\s*=\s*/)[1].split(/`/)[1];
+assert.match(htmlString, / /);
+```
+
+Your `hr` element should come after your `span` element.
+
+```js
+const htmlString = code.split(/output\s*\.\s*innerHTML\s*=\s*/)[1].split(/`/)[1];
+assert.isAbove(htmlString.indexOf(' /);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+ ${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}
+
+ `;
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e84c9fe8ca28c4101189.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e84c9fe8ca28c4101189.md
new file mode 100644
index 00000000000..ba1da012290
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e84c9fe8ca28c4101189.md
@@ -0,0 +1,270 @@
+---
+id: 63c9e84c9fe8ca28c4101189
+title: Step 83
+challengeType: 0
+dashedName: step-83
+---
+
+# --description--
+
+Now create a `p` element with the text `budgetCalories Calories Budgeted`, using interpolation to replace `budgetCalories` with the appropriate variable.
+
+This should come after your `hr` element.
+
+# --hints--
+
+You should create a `p` element.
+
+```js
+const htmlString = code.split(/output\s*\.\s*innerHTML\s*=\s*/)[1].split(/`/)[1];
+assert.match(htmlString, //);
+```
+
+Your `p` element should come after your `hr` element.
+
+```js
+const htmlString = code.split(/output\s*\.\s*innerHTML\s*=\s*/)[1].split(/`/)[1];
+assert.isAbove(htmlString.indexOf('
\$\{budgetCalories\}\s*Calories\s*Budgeted<\/p>/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+ ${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}
+
+
+ `;
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e8fe3a6f022a05a04675.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e8fe3a6f022a05a04675.md
new file mode 100644
index 00000000000..6b28d6282ad
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e8fe3a6f022a05a04675.md
@@ -0,0 +1,269 @@
+---
+id: 63c9e8fe3a6f022a05a04675
+title: Step 84
+challengeType: 0
+dashedName: step-84
+---
+
+# --description--
+
+Using the same interpolation syntax, add a second `p` element with the text `consumedCalories Calories Consumed` and a third with the text `exerciseCalories Calories Burned`. Remember to replace your `consumedCalories` and `exerciseCalories` variables with the appropriate values.
+
+# --hints--
+
+You should add a second `p` element to your template literal.
+
+```js
+const htmlString = code.split(/output\s*\.\s*innerHTML\s*=\s*/)[1].split(/`/)[1];
+assert.isAtLeast(htmlString.match(//g).length, 2);
+```
+
+Your second `p` element should be on a new line.
+
+```js
+const htmlString = code.split(/output\s*\.\s*innerHTML\s*=\s*/)[1].split(/`/)[1];
+assert.match(htmlString, /\n\s*
\$\{budgetCalories\}\s*Calories\s*Budgeted<\/p>\n\s*
\$\{consumedCalories\}\s*Calories\s*Consumed<\/p>/));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+ ${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}
+
+ ${budgetCalories} Calories Budgeted
+
+ `;
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e94e9df7d72aed1c24bd.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e94e9df7d72aed1c24bd.md
new file mode 100644
index 00000000000..f57827b6348
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e94e9df7d72aed1c24bd.md
@@ -0,0 +1,264 @@
+---
+id: 63c9e94e9df7d72aed1c24bd
+title: Step 85
+challengeType: 0
+dashedName: step-85
+---
+
+# --description--
+
+Finally, you need to make the `#output` element visible so the user can see your text. Your `output` variable is an Element, which has a `classList` property. This property has a `.remove()` method, which accepts a string representing the class to remove from the element.
+
+Use the `.remove()` method of the `output` variable's `classList` property to remove the `hide` class. Don't forget to place the word `hide` inside quotes.
+
+# --hints--
+
+You should access the `classList` property of the `output` element.
+
+```js
+assert.match(calculateCalories.toString(), /output\.classList/);
+```
+
+You should call the `.remove()` method of the `classList` property.
+
+```js
+assert.match(calculateCalories.toString(), /output\.classList\.remove\(/);
+```
+
+You should pass `hide` as the argument to the `.remove()` method.
+
+```js
+assert.match(calculateCalories.toString(), /output\.classList\.remove\(\s*('|")hide\1\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+ ${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}
+
+ ${budgetCalories} Calories Budgeted
+ ${consumedCalories} Calories Consumed
+ ${exerciseCalories} Calories Burned
+ `;
+
+
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9ea23dbadbf2c2764e3f5.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9ea23dbadbf2c2764e3f5.md
new file mode 100644
index 00000000000..18e5f04d27a
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9ea23dbadbf2c2764e3f5.md
@@ -0,0 +1,265 @@
+---
+id: 63c9ea23dbadbf2c2764e3f5
+title: Step 86
+challengeType: 0
+dashedName: step-86
+---
+
+# --description--
+
+If you click on your `Calculate Remaining Calories` button, you'll see that nothing happens. You still need to mount the event listener.
+
+Add an event listener to your `calorieCounter` element. The event type should be `submit`, and the callback function should be `calculateCalories`.
+
+# --hints--
+
+You should use the `.addEventListener()` method of your `calorieCounter` element.
+
+```js
+assert.match(code, /calorieCounter\.addEventListener\(/);
+```
+
+You should pass `submit` as the first argument to `.addEventListener()`.
+
+```js
+assert.match(code, /calorieCounter\.addEventListener\(\s*('|")submit\1\s*/);
+```
+
+You should pass `calculateCalories` as the second argument to `.addEventListener()`.
+
+```js
+assert.match(code, /calorieCounter\.addEventListener\(\s*('|")submit\1\s*,\s*calculateCalories\s*/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+ ${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}
+
+ ${budgetCalories} Calories Budgeted
+ ${consumedCalories} Calories Consumed
+ ${exerciseCalories} Calories Burned
+ `;
+
+ output.classList.remove('hide');
+}
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9ea9b16430f2d54522464.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9ea9b16430f2d54522464.md
new file mode 100644
index 00000000000..6c09fd6f149
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9ea9b16430f2d54522464.md
@@ -0,0 +1,265 @@
+---
+id: 63c9ea9b16430f2d54522464
+title: Step 87
+challengeType: 0
+dashedName: step-87
+---
+
+# --description--
+
+Your final feature to add is the ability for a user to clear the form. Start by declaring an empty function called `clearForm` – it should not take any arguments.
+
+# --hints--
+
+You should declare a `clearForm` variable.
+
+```js
+assert.isDefined(clearForm);
+```
+
+Your `clearForm` variable should be a function.
+
+```js
+assert.isFunction(clearForm);
+```
+
+Your `clearForm` function should not take any arguments.
+
+```js
+assert.match(clearForm?.toString(), /\(\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+ ${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}
+
+ ${budgetCalories} Calories Budgeted
+ ${consumedCalories} Calories Consumed
+ ${exerciseCalories} Calories Burned
+ `;
+
+ output.classList.remove('hide');
+}
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+calorieCounter.addEventListener("submit", calculateCalories);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9eb09bcfaa72e3da820a1.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9eb09bcfaa72e3da820a1.md
new file mode 100644
index 00000000000..7810095dcce
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9eb09bcfaa72e3da820a1.md
@@ -0,0 +1,267 @@
+---
+id: 63c9eb09bcfaa72e3da820a1
+title: Step 88
+challengeType: 0
+dashedName: step-88
+---
+
+# --description--
+
+You need to get all of the input containers. Declare an `inputContainers` variable, and assign it to the value of querying the document for all elements with the class `input-container`.
+
+# --hints--
+
+You should declare an `inputContainers` variable in your `clearForm` function.
+
+```js
+assert.match(clearForm.toString(), /inputContainers\s*=/);
+```
+
+You should use the `querySelectorAll` method to get all of the elements with the class `input-container`.
+
+```js
+assert.match(clearForm.toString(), /document\.querySelectorAll\(\s*('|")\.input-container\1\s*\)/);
+```
+
+You should assign the value of the `querySelectorAll` method to the `inputContainers` variable.
+
+```js
+assert.match(clearForm.toString(), /inputContainers\s*=\s*document\.querySelectorAll\(\s*('|")\.input-container\1\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+ ${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}
+
+ ${budgetCalories} Calories Budgeted
+ ${consumedCalories} Calories Consumed
+ ${exerciseCalories} Calories Burned
+ `;
+
+ output.classList.remove('hide');
+}
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+--fcc-editable-region--
+function clearForm() {
+
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+calorieCounter.addEventListener("submit", calculateCalories);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9eb4a5d68f12f32d9b440.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9eb4a5d68f12f32d9b440.md
new file mode 100644
index 00000000000..73d20bba696
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9eb4a5d68f12f32d9b440.md
@@ -0,0 +1,263 @@
+---
+id: 63c9eb4a5d68f12f32d9b440
+title: Step 89
+challengeType: 0
+dashedName: step-89
+---
+
+# --description--
+
+Remember that `document.querySelectorAll` returns a `NodeList`, which is array-like but is not an array. However, the `Array` object has a `.from()` method that accepts an array-like and returns an array. This is helpful when you want access to more robust array methods, which you will learn about in a future project.
+
+Wrap your `inputContainers` query selector in `Array.from()`. Do this on the same line as your declaration.
+
+# --hints--
+
+You should wrap your `querySelectorAll` in `Array.from()`.
+
+```js
+assert.match(clearForm, /Array\.from\(\s*document\.querySelectorAll\(\s*('|")\.input-container*\1\s*\)\s*\)/);
+```
+
+You should assign the result of `Array.from()` to your `inputContainers` variable.
+
+```js
+assert.match(clearForm, /inputContainers\s*=\s*Array\.from\(\s*document\.querySelectorAll\(\s*('|")\.input-container*\1\s*\)\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+ ${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}
+
+ ${budgetCalories} Calories Budgeted
+ ${consumedCalories} Calories Consumed
+ ${exerciseCalories} Calories Burned
+ `;
+
+ output.classList.remove('hide');
+}
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+--fcc-editable-region--
+function clearForm() {
+ const inputContainers = document.querySelectorAll('.input-container');
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+calorieCounter.addEventListener("submit", calculateCalories);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9ebb7b12bca3025b0a935.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9ebb7b12bca3025b0a935.md
new file mode 100644
index 00000000000..f6655dc9175
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9ebb7b12bca3025b0a935.md
@@ -0,0 +1,276 @@
+---
+id: 63c9ebb7b12bca3025b0a935
+title: Step 90
+challengeType: 0
+dashedName: step-90
+---
+
+# --description--
+
+It is time for another loop. Use a `for` loop to iterate through the `inputContainers` array.
+
+Inside the loop, set the `innerHTML` property of the element at the current index to an empty string. This will clear all of the contents of that input container.
+
+# --hints--
+
+Your `clearForm` function should have a `for` loop.
+
+```js
+// loop protect injects stuff, so let's look at the raw code again
+const clearForm = code.split("function clearForm()")[1];
+assert.match(clearForm, /for\s*\(/);
+```
+
+Your `for` loop should iterate through the `inputContainers` array. Remember to use `i` as your iterator.
+
+```js
+const clearForm = code.split("function clearForm()")[1];
+assert.match(clearForm, /for\s*\(\s*let\s+i\s*=\s*0\s*;\s*i\s*<\s*inputContainers\.length\s*;\s*i\s*\+\+\s*\)/);
+```
+
+Your `for` loop should set the `innerHTML` property of `inputContainers[i]` to an empty string.
+
+```js
+const clearForm = code.split("function clearForm()")[1];
+const forLoop = clearForm.split("for")[1];
+assert.match(forLoop, /inputContainers\[\s*i\s*\]\s*\.innerHTML\s*=\s*(`|'|")\1\s*/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+ ${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}
+
+ ${budgetCalories} Calories Budgeted
+ ${consumedCalories} Calories Consumed
+ ${exerciseCalories} Calories Burned
+ `;
+
+ output.classList.remove('hide');
+}
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+--fcc-editable-region--
+function clearForm() {
+ const inputContainers = Array.from(document.querySelectorAll('.input-container'));
+
+
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+calorieCounter.addEventListener("submit", calculateCalories);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9ec044acedf312c4974ff.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9ec044acedf312c4974ff.md
new file mode 100644
index 00000000000..5ef4abce954
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9ec044acedf312c4974ff.md
@@ -0,0 +1,275 @@
+---
+id: 63c9ec044acedf312c4974ff
+title: Step 91
+challengeType: 0
+dashedName: step-91
+---
+
+# --description--
+
+After your loop completes, you need to clear the `budgetNumberInput`. Set the `value` property of `budgetNumberInput` to an empty string.
+
+# --hints--
+
+Your `clearForm` function should access the `value` property of the `budgetNumberInput` element.
+
+```js
+assert.match(clearForm.toString(), /budgetNumberInput\.value/);
+```
+
+Your `clearForm` function should set the `value` property of the `budgetNumberInput` element to an empty string.
+
+```js
+assert.match(clearForm.toString(), /budgetNumberInput\.value\s*=\s*('|"|`)\1/);
+```
+
+You should modify the `budgetNumberInput` after your `for` loop.
+
+```js
+const clearForm = code.split("function clearForm()")[1];
+const afterLoop = clearForm.split("}")[1];
+assert.match(afterLoop, /budgetNumberInput\.value/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+ ${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}
+
+ ${budgetCalories} Calories Budgeted
+ ${consumedCalories} Calories Consumed
+ ${exerciseCalories} Calories Burned
+ `;
+
+ output.classList.remove('hide');
+}
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+--fcc-editable-region--
+function clearForm() {
+ const inputContainers = Array.from(document.querySelectorAll('.input-container'));
+
+ for (let i = 0; i < inputContainers.length; i++) {
+ inputContainers[i].innerHTML = '';
+ }
+
+
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+calorieCounter.addEventListener("submit", calculateCalories);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9f24afbc9cf324dcaa9a4.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9f24afbc9cf324dcaa9a4.md
new file mode 100644
index 00000000000..3dab9bed7e5
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9f24afbc9cf324dcaa9a4.md
@@ -0,0 +1,276 @@
+---
+id: 63c9f24afbc9cf324dcaa9a4
+title: Step 92
+challengeType: 0
+dashedName: step-92
+---
+
+# --description--
+
+You also need to clear the `output` element's text. You can do this by setting the `innerText` property to an empty string.
+
+The difference between `innerText` and `innerHTML` is that `innerText` will not render HTML elements, but will display the tags and content as raw text.
+
+# --hints--
+
+Your `clearForm` function should access the `innerText` property of the `output` element.
+
+```js
+assert.match(clearForm.toString(), /output\.innerText/);
+```
+
+Your `clearForm` function should set the `innerText` property of the `output` element to an empty string.
+
+```js
+assert.match(clearForm.toString(), /output\.innerText\s*=\s*('|"|`)\1/);
+```
+
+You should modify `output` after modifying `budgetNumberInput`.
+
+```js
+assert.isAbove(clearForm.toString().indexOf('output'), clearForm.toString().indexOf('budgetNumberInput'));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+ ${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}
+
+ ${budgetCalories} Calories Budgeted
+ ${consumedCalories} Calories Consumed
+ ${exerciseCalories} Calories Burned
+ `;
+
+ output.classList.remove('hide');
+}
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+--fcc-editable-region--
+function clearForm() {
+ const inputContainers = Array.from(document.querySelectorAll('.input-container'));
+
+ for (let i = 0; i < inputContainers.length; i++) {
+ inputContainers[i].innerHTML = '';
+ }
+
+ budgetNumberInput.value = '';
+
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+calorieCounter.addEventListener("submit", calculateCalories);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9f28bda3e3f336e21b6b4.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9f28bda3e3f336e21b6b4.md
new file mode 100644
index 00000000000..b2e9d536a15
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9f28bda3e3f336e21b6b4.md
@@ -0,0 +1,277 @@
+---
+id: 63c9f28bda3e3f336e21b6b4
+title: Step 93
+challengeType: 0
+dashedName: step-93
+---
+
+# --description--
+
+To finish off this function, you need to restore the `hide` class to the `output` element. The `classList` property has an `.add()` method which is the opposite of the `.remove()` method. It accepts a string representing the class to add to the element.
+
+Add the `hide` class to your `output`.
+
+# --hints--
+
+You should access the `classList` property of the `output` element.
+
+```js
+assert.match(clearForm.toString(), /output\.classList/);
+```
+
+You should call the `.add()` method on the `classList` property of the `output` element.
+
+```js
+assert.match(clearForm.toString(), /output\.classList\.add/);
+```
+
+You should pass `hide` as the argument to the `.add()` method.
+
+```js
+assert.match(clearForm.toString(), /output\.classList\.add\(\s*('|")hide\1\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+ ${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}
+
+ ${budgetCalories} Calories Budgeted
+ ${consumedCalories} Calories Consumed
+ ${exerciseCalories} Calories Burned
+ `;
+
+ output.classList.remove('hide');
+}
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+--fcc-editable-region--
+function clearForm() {
+ const inputContainers = Array.from(document.querySelectorAll('.input-container'));
+
+ for (let i = 0; i < inputContainers.length; i++) {
+ inputContainers[i].innerHTML = '';
+ }
+
+ budgetNumberInput.value = '';
+ output.innerText = '';
+
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+calorieCounter.addEventListener("submit", calculateCalories);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9f2bff625af342023512c.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9f2bff625af342023512c.md
new file mode 100644
index 00000000000..d29b3f2ac72
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9f2bff625af342023512c.md
@@ -0,0 +1,520 @@
+---
+id: 63c9f2bff625af342023512c
+title: Step 94
+challengeType: 0
+dashedName: step-94
+---
+
+# --description--
+
+To complete this project, add an event listener to the `clearButton` button. When the button is clicked, it should call the `clearForm` function.
+
+Congratulations! Your project is complete.
+
+# --hints--
+
+You should add an event listener to the `clearButton` button.
+
+```js
+assert.match(code, /clearButton\s*\.addEventListener\s*\(/);
+```
+
+You should pass `click` as the first argument to `.addEventListener()`.
+
+```js
+assert.match(code, /clearButton\s*\.addEventListener\s*\(\s*('|"|`)click\1\s*/);
+```
+
+You should pass `clearForm` as the second argument to `.addEventListener()`.
+
+```js
+assert.match(code, /clearButton\s*\.addEventListener\s*\(\s*('|"|`)click\1\s*,\s*clearForm\s*/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+ ${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}
+
+ ${budgetCalories} Calories Budgeted
+ ${consumedCalories} Calories Consumed
+ ${exerciseCalories} Calories Burned
+ `;
+
+ output.classList.remove('hide');
+}
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+function clearForm() {
+ const inputContainers = Array.from(document.querySelectorAll('.input-container'));
+
+ for (let i = 0; i < inputContainers.length; i++) {
+ inputContainers[i].innerHTML = '';
+ }
+
+ budgetNumberInput.value = '';
+ output.innerText = '';
+ output.classList.add('hide');
+}
+
+addEntryButton.addEventListener("click", addEntry);
+calorieCounter.addEventListener("submit", calculateCalories);
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
+
+# --solutions--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+ ${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}
+
+ ${budgetCalories} Calories Budgeted
+ ${consumedCalories} Calories Consumed
+ ${exerciseCalories} Calories Burned
+ `;
+
+ output.classList.remove('hide');
+}
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+function clearForm() {
+ const inputContainers = Array.from(document.querySelectorAll('.input-container'));
+
+ for (let i = 0; i < inputContainers.length; i++) {
+ inputContainers[i].innerHTML = '';
+ }
+
+ budgetNumberInput.value = '';
+ output.innerText = '';
+ output.classList.add('hide');
+}
+
+addEntryButton.addEventListener('click', addEntry);
+calorieCounter.addEventListener('submit', calculateCalories);
+clearButton.addEventListener('click', clearForm);
+```
diff --git a/curriculum/challenges/ukrainian/17-college-algebra-with-python/build-a-data-graph-explorer-project/build-a-data-graph-explorer.md b/curriculum/challenges/ukrainian/17-college-algebra-with-python/build-a-data-graph-explorer-project/build-a-data-graph-explorer.md
old mode 100755
new mode 100644
diff --git a/curriculum/challenges/ukrainian/17-college-algebra-with-python/build-a-financial-calculator-project/build-a-financial-calculator.md b/curriculum/challenges/ukrainian/17-college-algebra-with-python/build-a-financial-calculator-project/build-a-financial-calculator.md
old mode 100755
new mode 100644
diff --git a/curriculum/challenges/ukrainian/17-college-algebra-with-python/build-a-graphing-calculator-project/build-a-graphing-calculator.md b/curriculum/challenges/ukrainian/17-college-algebra-with-python/build-a-graphing-calculator-project/build-a-graphing-calculator.md
old mode 100755
new mode 100644
diff --git a/curriculum/challenges/ukrainian/17-college-algebra-with-python/build-a-multi-function-calculator-project/build-a-multi-function-calculator.md b/curriculum/challenges/ukrainian/17-college-algebra-with-python/build-a-multi-function-calculator-project/build-a-multi-function-calculator.md
old mode 100755
new mode 100644
diff --git a/curriculum/challenges/ukrainian/17-college-algebra-with-python/build-three-math-games-project/build-three-math-games.md b/curriculum/challenges/ukrainian/17-college-algebra-with-python/build-three-math-games-project/build-three-math-games.md
old mode 100755
new mode 100644