Share
diff --git a/curriculum/challenges/ukrainian/01-responsive-web-design/css-flexbox/use-the-order-property-to-rearrange-items.md b/curriculum/challenges/ukrainian/01-responsive-web-design/css-flexbox/use-the-order-property-to-rearrange-items.md
index cbad1ad34d..cb88edd917 100644
--- a/curriculum/challenges/ukrainian/01-responsive-web-design/css-flexbox/use-the-order-property-to-rearrange-items.md
+++ b/curriculum/challenges/ukrainian/01-responsive-web-design/css-flexbox/use-the-order-property-to-rearrange-items.md
@@ -20,13 +20,17 @@ The `order` property is used to tell CSS the order of how flex items appear in t
Елемент `#box-1` повинен мати властивість `order` зі значенням `2`.
```js
-assert($('#box-1').css('order') == '2');
+const boxOne = document.querySelector('#box-1');
+const order = window.getComputedStyle(boxOne)['order'];
+assert.strictEqual(order, '2');
```
Елемент `#box-2` повинен мати властивість `order` зі значенням `1`.
```js
-assert($('#box-2').css('order') == '1');
+const boxTwo = document.querySelector('#box-2');
+const order = window.getComputedStyle(boxTwo)['order'];
+assert.strictEqual(order, '1');
```
# --seed--
diff --git a/curriculum/challenges/ukrainian/03-front-end-development-libraries/front-end-development-libraries-projects/build-a-25-5-clock.md b/curriculum/challenges/ukrainian/03-front-end-development-libraries/front-end-development-libraries-projects/build-a-25-5-clock.md
index 1c67144639..e30689154e 100644
--- a/curriculum/challenges/ukrainian/03-front-end-development-libraries/front-end-development-libraries-projects/build-a-25-5-clock.md
+++ b/curriculum/challenges/ukrainian/03-front-end-development-libraries/front-end-development-libraries-projects/build-a-25-5-clock.md
@@ -72,7 +72,7 @@ dashedName: build-a-25--5-clock
**Історія користувача №28:** аудіоелемент з id зі значенням `beep` має зупинитись та перемотатись напочаток, якщо натиснути елемент з id зі значенням `reset`.
-Ви можете створити свій проєкт,
використавши цей шаблон CodePen та натиснувши `Save`. Або ж ви можете скористатися цим посиланням CDN, щоб виконати тести в будь-якому середовищі: `https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js`
+Ви можете створити свій проєкт,
використавши цей шаблон CodePen та натиснувши `Save`. If you prefer to use another environment, then put this ``
Як тільки закінчите, надайте посилання на свій проєкт з усіма пройденими тестами.
diff --git a/curriculum/challenges/ukrainian/03-front-end-development-libraries/front-end-development-libraries-projects/build-a-drum-machine.md b/curriculum/challenges/ukrainian/03-front-end-development-libraries/front-end-development-libraries-projects/build-a-drum-machine.md
index 23777d4cf9..dfbd03f099 100644
--- a/curriculum/challenges/ukrainian/03-front-end-development-libraries/front-end-development-libraries-projects/build-a-drum-machine.md
+++ b/curriculum/challenges/ukrainian/03-front-end-development-libraries/front-end-development-libraries-projects/build-a-drum-machine.md
@@ -41,7 +41,7 @@ dashedName: build-a-drum-machine
- [Kick](https://cdn.freecodecamp.org/testable-projects-fcc/audio/RP4_KICK_1.mp3)
- [Closed-HH](https://cdn.freecodecamp.org/testable-projects-fcc/audio/Cev_H2.mp3)
-Ви можете створити свій проєкт,
використавши цей шаблон CodePen та натиснувши `Save`. Або ж ви можете скористатися цим посиланням CDN, щоб виконати тести в будь-якому середовищі: `https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js`
+Ви можете створити свій проєкт,
використавши цей шаблон CodePen та натиснувши `Save`. If you prefer to use another environment, then put this ``
Як тільки закінчите, надайте посилання на свій проєкт з усіма пройденими тестами.
diff --git a/curriculum/challenges/ukrainian/03-front-end-development-libraries/front-end-development-libraries-projects/build-a-javascript-calculator.md b/curriculum/challenges/ukrainian/03-front-end-development-libraries/front-end-development-libraries-projects/build-a-javascript-calculator.md
index 1d09e9d13f..9b788b4216 100644
--- a/curriculum/challenges/ukrainian/03-front-end-development-libraries/front-end-development-libraries-projects/build-a-javascript-calculator.md
+++ b/curriculum/challenges/ukrainian/03-front-end-development-libraries/front-end-development-libraries-projects/build-a-javascript-calculator.md
@@ -52,7 +52,7 @@ dashedName: build-a-javascript-calculator
- **Immediate Execution Logic:** `11.5`
- **Логіка формул/виразів:** `32.5`
-Ви можете створити свій проєкт,
використавши цей шаблон CodePen та натиснувши `Save`. Або ж ви можете скористатися цим посиланням CDN, щоб виконати тести в будь-якому середовищі: `https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js`
+You can build your project by
using this CodePen template and clicking `Save` to create your own pen. If you prefer to use another environment, then put this ``
Як тільки закінчите, надайте посилання на свій проєкт з усіма пройденими тестами.
diff --git a/curriculum/challenges/ukrainian/03-front-end-development-libraries/front-end-development-libraries-projects/build-a-markdown-previewer.md b/curriculum/challenges/ukrainian/03-front-end-development-libraries/front-end-development-libraries-projects/build-a-markdown-previewer.md
index de1b454fef..3fdba28e80 100644
--- a/curriculum/challenges/ukrainian/03-front-end-development-libraries/front-end-development-libraries-projects/build-a-markdown-previewer.md
+++ b/curriculum/challenges/ukrainian/03-front-end-development-libraries/front-end-development-libraries-projects/build-a-markdown-previewer.md
@@ -29,7 +29,7 @@ dashedName: build-a-markdown-previewer
**Додатково (вам непотрібно робити цього, щоб пройти тест):** попередній перегляд розмітки інтерпретує повернення каретки та відтворює їх як елементи `br` (розрив рядка).
-Ви можете створити свій проєкт,
використавши цей шаблон CodePen та натиснувши `Save`. Або ж ви можете скористатися цим посиланням CDN, щоб виконати тести в будь-якому середовищі: `https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js`
+You can build your project by
using this CodePen template and clicking `Save` to create your own pen. If you prefer to use another environment, then put this ``
Як тільки закінчите, надайте посилання на свій проєкт з усіма пройденими тестами.
diff --git a/curriculum/challenges/ukrainian/03-front-end-development-libraries/front-end-development-libraries-projects/build-a-random-quote-machine.md b/curriculum/challenges/ukrainian/03-front-end-development-libraries/front-end-development-libraries-projects/build-a-random-quote-machine.md
index f289516c31..0809ac5b46 100644
--- a/curriculum/challenges/ukrainian/03-front-end-development-libraries/front-end-development-libraries-projects/build-a-random-quote-machine.md
+++ b/curriculum/challenges/ukrainian/03-front-end-development-libraries/front-end-development-libraries-projects/build-a-random-quote-machine.md
@@ -37,7 +37,7 @@ dashedName: build-a-random-quote-machine
**Історія користувача №11:** обгортковий елемент `#quote-box` має бути горизонтально відцентрованим. Виконайте тести зі збільшенням браузера до 100% і розгорнутою сторінкою.
-Ви можете створити свій проєкт,
використавши цей шаблон CodePen та натиснувши `Save`. Або ж ви можете скористатися цим CDN-посиланням, щоб провести тести на будь-якому середовищі: `https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js`
+You can build your project by
using this CodePen template and clicking `Save` to create your own pen. If you prefer to use another environment, then put this ``
Щойно впораєтеся, прикріпіть URL-адресу із пройденими тестами до проєкту, над яким працюєте.
diff --git a/curriculum/challenges/ukrainian/04-data-visualization/json-apis-and-ajax/get-json-with-the-javascript-fetch-method.md b/curriculum/challenges/ukrainian/04-data-visualization/json-apis-and-ajax/get-json-with-the-javascript-fetch-method.md
index 941de65e09..1336fdfb2b 100644
--- a/curriculum/challenges/ukrainian/04-data-visualization/json-apis-and-ajax/get-json-with-the-javascript-fetch-method.md
+++ b/curriculum/challenges/ukrainian/04-data-visualization/json-apis-and-ajax/get-json-with-the-javascript-fetch-method.md
@@ -22,6 +22,8 @@ fetch('/json/cats.json')
```
+Note: The `fetch()` method uses `GET` as the default `HTTP` method. This means you don’t need to specify it explicitly for basic data retrieval.
+
Зверніть увагу на кожен фрагмент коду.
Перший рядок здійснює запит. Таким чином `fetch(URL)` робить запит `GET` до конкретної URL-адреси. Метод повертає проміс.
diff --git a/curriculum/challenges/ukrainian/05-back-end-development-and-apis/back-end-development-and-apis-projects/exercise-tracker.md b/curriculum/challenges/ukrainian/05-back-end-development-and-apis/back-end-development-and-apis-projects/exercise-tracker.md
index 71d4fea5ac..a849d24070 100644
--- a/curriculum/challenges/ukrainian/05-back-end-development-and-apis/back-end-development-and-apis-projects/exercise-tracker.md
+++ b/curriculum/challenges/ukrainian/05-back-end-development-and-apis/back-end-development-and-apis-projects/exercise-tracker.md
@@ -212,15 +212,29 @@ async (getUserInput) => {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `description=${expected.description}&duration=${expected.duration}&date=1990-01-01`
});
- if (addRes.ok) {
- const actual = await addRes.json();
- assert.deepEqual(actual, expected);
- assert.isString(actual.description);
- assert.isNumber(actual.duration);
- assert.isString(actual.date);
- } else {
+ assert.isTrue(addRes.ok);
+ if (!addRes.ok) {
throw new Error(`${addRes.status} ${addRes.statusText}`);
}
+ const responseBody = await addRes.json();
+ assert.isString(responseBody.description);
+ assert.isNumber(responseBody.duration);
+ assert.isString(responseBody.date);
+ assert.equal(responseBody._id, expected._id);
+ assert.equal(responseBody.username, expected.username);
+ assert.equal(responseBody.description, expected.description);
+ assert.equal(responseBody.duration, expected.duration);
+ const receivedDate = new Date(responseBody.date);
+ const expectedDate = new Date(expected.date); // Jan 1, 1990
+ const allowedPreviousDate = new Date(expectedDate);
+ allowedPreviousDate.setDate(expectedDate.getDate() - 1); // Dec 31, 1989
+ const isValidDate =
+ receivedDate.toDateString() === expectedDate.toDateString() ||
+ receivedDate.toDateString() === allowedPreviousDate.toDateString();
+ assert.isTrue(
+ isValidDate,
+ `Expected date to be ${expectedDate.toDateString()} or ${allowedPreviousDate.toDateString()}, but got ${receivedDate.toDateString()}`
+ );
} else {
throw new Error(`${res.status} ${res.statusText}`);
}
@@ -495,26 +509,38 @@ async(getUserInput) => {
Властивість `date` будь-якого об’єкту в масиві `log`, що повернувся з `GET /api/users/:_id/logs`, має бути рядком. Використайте формат `dateString` від `Date` API.
```js
-async(getUserInput) => {
+async (getUserInput) => {
const url = getUserInput('url');
const res = await fetch(url + '/api/users', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
- body: `username=fcc_test_${Date.now()}`.substring(0,29)
+ body: `username=fcc_test_${Date.now()}`.substring(0, 29)
});
- if(res.ok) {
- const {_id, username} = await res.json();
+
+ if (res.ok) {
+ const { _id, username } = await res.json();
+ const currentDate = new Date();
+ const expectedDates = [
+ new Date(currentDate.setDate(currentDate.getDate() - 1)).toLocaleDateString("en-US", {
+ timeZone: "UTC", weekday: "short", month: "short",
+ day: "2-digit", year: "numeric"
+ }).replaceAll(',', ''),
+ new Date().toLocaleDateString("en-US", {
+ timeZone: "UTC", weekday: "short", month: "short",
+ day: "2-digit", year: "numeric"
+ }).replaceAll(',', ''),
+ new Date(currentDate.setDate(currentDate.getDate() + 1)).toLocaleDateString("en-US", {
+ timeZone: "UTC", weekday: "short", month: "short",
+ day: "2-digit", year: "numeric"
+ }).replaceAll(',', '')
+ ];
const expected = {
username,
description: 'test',
duration: 60,
_id,
- date: new Date().toLocaleDateString("en-US", {
- timeZone: "UTC", weekday: "short", month: "short",
- day: "2-digit", year: "numeric"
- }).replaceAll(',', '')
};
const addRes = await fetch(url + `/api/users/${_id}/exercises`, {
method: 'POST',
@@ -523,13 +549,13 @@ async(getUserInput) => {
},
body: `description=${expected.description}&duration=${expected.duration}`
});
- if(addRes.ok) {
+ if (addRes.ok) {
const logRes = await fetch(url + `/api/users/${_id}/logs`);
- if(logRes.ok){
- const {log} = await logRes.json();
+ if (logRes.ok) {
+ const { log } = await logRes.json();
const exercise = log[0];
assert.isString(exercise.date);
- assert.equal(exercise.date, expected.date);
+ assert.include(expectedDates, exercise.date); // Check if date matches any valid dates
} else {
throw new Error(`${logRes.status} ${logRes.statusText}`);
}
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/build-a-budget-app-project/budget-app.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/build-a-budget-app-project/budget-app.md
index 773c70aae8..f787c30d30 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/build-a-budget-app-project/budget-app.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/build-a-budget-app-project/budget-app.md
@@ -711,6 +711,358 @@ t.result.wasSuccessful()
})
```
+Title at the top of `create_spend_chart` chart should say `Percentage spent by category`.
+
+```js
+({
+ test: () => {
+ pyodide.FS.writeFile('/home/pyodide/budget.py', code);
+ pyodide.FS.writeFile('/home/pyodide/test_module.py',`
+import unittest
+import budget
+from importlib import reload
+
+reload(budget)
+class UnitTests(unittest.TestCase):
+ maxDiff = None
+ def setUp(self):
+ self.food = budget.Category("Food")
+
+ def test_create_spend_chart(self):
+ self.food.deposit(900, "deposit")
+ self.food.withdraw(105.55)
+ chart = budget.create_spend_chart([self.food])
+ expected = "Percentage spent by category"
+ self.assertEqual(chart.split("\\n")[0], expected, "Chart should have correct title.")
+`);
+
+ const testCode = `
+from unittest import main
+from importlib import reload
+import test_module
+reload(test_module)
+t = main(module='test_module', exit=False)
+t.result.wasSuccessful()
+`;
+ const out = runPython(testCode);
+ assert(out);
+ }
+})
+```
+
+`create_spend_chart` chart should have correct percentages down the left side.
+
+```js
+({
+ test: () => {
+ pyodide.FS.writeFile('/home/pyodide/budget.py', code);
+ pyodide.FS.writeFile('/home/pyodide/test_module.py',`
+import unittest
+import budget
+from importlib import reload
+
+reload(budget)
+class UnitTests(unittest.TestCase):
+ maxDiff = None
+ def setUp(self):
+ self.food = budget.Category("Food")
+
+ def test_create_spend_chart(self):
+ self.food.deposit(900, "deposit")
+ self.food.withdraw(105.55)
+ chart = budget.create_spend_chart([self.food])
+ percentages = ["100|", " 90|", " 80|", " 70|", " 60|", " 50|", " 40|", " 30|", " 20|", " 10|", " 0|"]
+ for line, percent in zip(chart.split("\\n")[1:], percentages):
+ self.assertTrue(line.startswith(percent), "Chart correct percentages in the vertical axis.")
+`);
+
+ const testCode = `
+from unittest import main
+from importlib import reload
+import test_module
+reload(test_module)
+t = main(module='test_module', exit=False)
+t.result.wasSuccessful()
+`;
+ const out = runPython(testCode);
+ assert(out);
+ }
+})
+```
+
+The height of each bar on the `create_spend_chart` chart should be rounded down to the nearest 10.
+
+```js
+({
+ test: () => {
+ pyodide.FS.writeFile('/home/pyodide/budget.py', code);
+ pyodide.FS.writeFile('/home/pyodide/test_module.py',`
+import unittest
+import budget
+from importlib import reload
+
+reload(budget)
+class UnitTests(unittest.TestCase):
+ maxDiff = None
+ def setUp(self):
+ self.food = budget.Category("Food")
+ self.entertainment = budget.Category("Entertainment")
+ self.business = budget.Category("Business")
+ self.food.deposit(900, "deposit")
+ self.entertainment.deposit(900, "deposit")
+ self.business.deposit(900, "deposit")
+ self.food.withdraw(78)
+ self.entertainment.withdraw(22)
+ self.business.withdraw(8)
+
+ def test_create_spend_chart_rounding_close_to_upper_and_lower_ten(self):
+ chart_lines = budget.create_spend_chart([self.food, self.entertainment]).split("\\n")[1:12]
+ result_lines = '''100|
+ 90|
+ 80|
+ 70| o
+ 60| o
+ 50| o
+ 40| o
+ 30| o
+ 20| o o
+ 10| o o
+ 0| o o'''.split("\\n")
+
+ self.assertEqual(len(chart_lines), len(result_lines), "Lines missing in chart.")
+ for actual, expected in zip(chart_lines, result_lines):
+ self.assertTrue(actual.startswith(expected), "Expected different rounding of bars.")
+
+
+ def test_create_spend_chart_rounding_single_digit(self):
+ chart_lines = budget.create_spend_chart([self.business, self.food, self.entertainment]).split("\\n")[1:12]
+ result_lines = '''100|
+ 90|
+ 80|
+ 70| o
+ 60| o
+ 50| o
+ 40| o
+ 30| o
+ 20| o o
+ 10| o o
+ 0| o o o'''.split("\\n")
+
+ self.assertEqual(len(chart_lines), len(result_lines), "Lines missing in chart.")
+ for actual, expected in zip(chart_lines, result_lines):
+ self.assertTrue(actual.startswith(expected), "Expected different rounding of bars.")
+`);
+
+ const testCode = `
+from unittest import main
+from importlib import reload
+import test_module
+reload(test_module)
+t = main(module='test_module', exit=False)
+t.result.wasSuccessful()
+`;
+ const out = runPython(testCode);
+ assert(out);
+ }
+})
+```
+
+Each line in `create_spend_chart` chart should have the same length. Bars for different categories should be separated by two spaces, with additional two spaces after the final bar.
+
+```js
+({
+ test: () => {
+ pyodide.FS.writeFile('/home/pyodide/budget.py', code);
+ pyodide.FS.writeFile('/home/pyodide/test_module.py',`
+import unittest
+import budget
+from importlib import reload
+
+reload(budget)
+class UnitTests(unittest.TestCase):
+ maxDiff = None
+ def setUp(self):
+ self.food = budget.Category("Food")
+ self.entertainment = budget.Category("Entertainment")
+ self.business = budget.Category("Business")
+ self.food.deposit(900, "deposit")
+ self.entertainment.deposit(900, "deposit")
+ self.business.deposit(900, "deposit")
+ self.food.withdraw(78)
+ self.entertainment.withdraw(22)
+ self.business.withdraw(8)
+
+
+ def test_create_spend_chart_chart_lines_have_expected_length(self):
+ chart_categories = [[self.food, self.entertainment], [self.business, self.food, self.entertainment]]
+
+ expected_lengths = [len(line) for line in [" 0| o o ", " 0| o o o "]]
+ expected_chart_lines = 11
+
+ for categories, expected_length in zip(chart_categories, expected_lengths):
+ chart_lines = budget.create_spend_chart(categories).split("\\n")[1:12]
+
+ self.assertEqual(len(chart_lines), expected_chart_lines, "Lines missing in chart.")
+ for actual in chart_lines:
+ self.assertEqual(len(actual), expected_length, "Expected different length of the chart line. Check that all spacing is exact.")
+`);
+ const testCode = `
+from unittest import main
+from importlib import reload
+import test_module
+reload(test_module)
+t = main(module='test_module', exit=False)
+t.result.wasSuccessful()
+`;
+ const out = runPython(testCode);
+ assert(out);
+ }
+})
+```
+
+`create_spend_chart` should correctly show horizontal line below the bars. Using three `-` characters for each category, and in total going two characters past the final bar.
+
+```js
+({
+ test: () => {
+ pyodide.FS.writeFile('/home/pyodide/budget.py', code);
+ pyodide.FS.writeFile('/home/pyodide/test_module.py',`
+import unittest
+import budget
+from importlib import reload
+
+reload(budget)
+class UnitTests(unittest.TestCase):
+ maxDiff = None
+ def setUp(self):
+ self.food = budget.Category("Food")
+ self.entertainment = budget.Category("Entertainment")
+ self.business = budget.Category("Business")
+ self.food.deposit(900, "deposit")
+ self.entertainment.deposit(900, "deposit")
+ self.business.deposit(900, "deposit")
+ self.food.withdraw(105.55)
+ self.entertainment.withdraw(33.40)
+ self.business.withdraw(10.99)
+
+ def test_create_spend_chart_horizontal_bar(self):
+ chart_categories = [[self.business], [self.business, self.food], [self.business, self.food, self.entertainment]]
+ horizontal_lines = [" ----", " -------", " ----------"]
+ for categories, expected in zip(chart_categories, horizontal_lines):
+ actual = budget.create_spend_chart(categories).split("\\n")[12]
+ self.assertEqual(actual, expected, "Expected different horizontal bar. Check that all spacing is exact.")
+`);
+
+ const testCode = `
+from unittest import main
+from importlib import reload
+import test_module
+reload(test_module)
+t = main(module='test_module', exit=False)
+t.result.wasSuccessful()
+`;
+ const out = runPython(testCode);
+ assert(out);
+ }
+})
+```
+
+`create_spend_chart` chart should not have new line character at the end.
+
+```js
+({
+ test: () => {
+ pyodide.FS.writeFile('/home/pyodide/budget.py', code);
+ pyodide.FS.writeFile('/home/pyodide/test_module.py',`
+import unittest
+import budget
+from importlib import reload
+
+reload(budget)
+class UnitTests(unittest.TestCase):
+ maxDiff = None
+ def setUp(self):
+ self.food = budget.Category("Food")
+ self.entertainment = budget.Category("Entertainment")
+ self.business = budget.Category("Business")
+
+ def test_create_spend_chart_no_ending_new_line(self):
+ self.food.deposit(900, "deposit")
+ self.entertainment.deposit(900, "deposit")
+ self.business.deposit(900, "deposit")
+ self.food.withdraw(105.55)
+ self.entertainment.withdraw(33.40)
+ self.business.withdraw(10.99)
+ actual = budget.create_spend_chart([self.business, self.food, self.entertainment])
+ self.assertFalse(actual.endswith("\\n"), "Expected chart to not have new line at the end.")
+`);
+
+ const testCode = `
+from unittest import main
+from importlib import reload
+import test_module
+reload(test_module)
+t = main(module='test_module', exit=False)
+t.result.wasSuccessful()
+`;
+ const out = runPython(testCode);
+ assert(out);
+ }
+})
+```
+
+`create_spend_chart` chart should have each category name written vertically below the bar. Each line should have the same length, each category should be separated by two spaces, with additional two spaces after the final category.
+
+```js
+({
+ test: () => {
+ pyodide.FS.writeFile('/home/pyodide/budget.py', code);
+ pyodide.FS.writeFile('/home/pyodide/test_module.py',`
+import unittest
+import budget
+from importlib import reload
+
+reload(budget)
+class UnitTests(unittest.TestCase):
+ maxDiff = None
+ def setUp(self):
+ self.food = budget.Category("Food")
+ self.entertainment = budget.Category("Entertainment")
+ self.business = budget.Category("Business")
+ self.food.deposit(900, "deposit")
+ self.entertainment.deposit(900, "deposit")
+ self.business.deposit(900, "deposit")
+ self.food.withdraw(105.55)
+ self.entertainment.withdraw(33.40)
+ self.business.withdraw(10.99)
+
+ def test_create_spend_chart_names_two_categories(self):
+ chart = budget.create_spend_chart([self.food, self.entertainment])
+ actual = "\\n".join(chart.split("\\n")[13:]).rstrip("\\n")
+ expected = " F E \\n o n \\n o t \\n d e \\n r \\n t \\n a \\n i \\n n \\n m \\n e \\n n \\n t "
+ self.assertEqual(actual, expected, "Expected different category names written vertically below the bar. Check that all spacing is exact.")
+
+ def test_create_spend_chart_names_three_categories(self):
+ chart = budget.create_spend_chart([self.business, self.food, self.entertainment])
+ actual = "\\n".join(chart.split("\\n")[13:]).rstrip("\\n")
+ expected = " B F E \\n u o n \\n s o t \\n i d e \\n n r \\n e t \\n s a \\n s i \\n n \\n m \\n e \\n n \\n t "
+ self.assertEqual(actual, expected, "Expected different category names written vertically below the bar. Check that all spacing is exact.")
+`);
+
+ const testCode = `
+from unittest import main
+from importlib import reload
+import test_module
+reload(test_module)
+t = main(module='test_module', exit=False)
+t.result.wasSuccessful()
+`;
+ const out = runPython(testCode);
+ assert(out);
+ }
+})
+```
+
`create_spend_chart` should print a different chart representation. Check that all spacing is exact. Open your browser console with F12 for more details.
```js
diff --git a/curriculum/challenges/ukrainian/14-responsive-web-design-22/build-a-survey-form-project/build-a-survey-form.md b/curriculum/challenges/ukrainian/14-responsive-web-design-22/build-a-survey-form-project/build-a-survey-form.md
index 3ca57c0110..db4ed84b18 100644
--- a/curriculum/challenges/ukrainian/14-responsive-web-design-22/build-a-survey-form-project/build-a-survey-form.md
+++ b/curriculum/challenges/ukrainian/14-responsive-web-design-22/build-a-survey-form-project/build-a-survey-form.md
@@ -38,327 +38,368 @@ dashedName: build-a-survey-form
Ви повинні мати елемент `h1` з `id` зі значенням `title`.
```js
-const el = document.getElementById('title')
-assert(!!el && el.tagName === 'H1')
+const el = document.getElementById('title');
+assert.isNotNull(el);
+assert.strictEqual(el.tagName, 'H1');
```
Ваш `#title` не повинен бути порожнім.
```js
-const el = document.getElementById('title')
-assert(!!el && el.innerText.length > 0)
+const el = document.getElementById('title');
+assert.isNotNull(el);
+assert.isAbove(el.innerText.length, 0);
```
Ви повинні мати елемент `p` з `id` зі значенням `description`.
```js
-const el = document.getElementById('description')
-assert(!!el && el.tagName === 'P')
+const el = document.getElementById('description');
+assert.isNotNull(el);
+assert.strictEqual(el.tagName, 'P');
```
Ваш `#description` не повинен бути порожнім.
```js
-const el = document.getElementById('description')
-assert(!!el && el.innerText.length > 0)
+const el = document.getElementById('description');
+assert.isNotNull(el);
+assert.isAbove(el.innerText.length, 0);
```
Ви повинні мати елемент `form` з `id` зі значенням `survey-form`.
```js
-const el = document.getElementById('survey-form')
-assert(!!el && el.tagName === 'FORM')
+const el = document.getElementById('survey-form');
+assert.isNotNull(el);
+assert.strictEqual(el.tagName, 'FORM');
```
Ви повинні мати елемент `input` з `id` зі значенням `name`.
```js
-const el = document.getElementById('name')
-assert(!!el && el.tagName === 'INPUT')
+const el = document.getElementById('name');
+assert.isNotNull(el);
+assert.strictEqual(el.tagName, 'INPUT');
```
Ваш `#name` повинен мати `type` зі значенням `text`.
```js
-const el = document.getElementById('name')
-assert(!!el && el.type === 'text')
+const el = document.getElementById('name');
+assert.isNotNull(el);
+assert.strictEqual(el.type, 'text');
```
Ваш `#name` повинен вимагати введення.
```js
-const el = document.getElementById('name')
-assert(!!el && el.required)
+const el = document.getElementById('name');
+assert.isNotNull(el);
+assert.isTrue(el.required);
```
Ваш `#name` повинен бути нащадком `#survey-form`.
```js
-const el = document.querySelector('#survey-form #name')
-assert(!!el)
+const el = document.querySelector('#survey-form #name');
+assert.isNotNull(el);
```
Ви повинні мати елемент `input` з `id` зі значенням `email`.
```js
-const el = document.getElementById('email')
-assert(!!el && el.tagName === 'INPUT')
+const el = document.getElementById('email');
+assert.isNotNull(el);
+assert.strictEqual(el.tagName, 'INPUT');
```
Ваш `#email` повинен мати `type` зі значенням `email`.
```js
-const el = document.getElementById('email')
-assert(!!el && el.type === 'email')
+const el = document.getElementById('email');
+assert.isNotNull(el);
+assert.strictEqual(el.type, 'email');
```
Ваш `#email` повинен вимагати введення.
```js
-const el = document.getElementById('email')
-assert(!!el && el.required)
+const el = document.getElementById('email');
+assert.isNotNull(el);
+assert.isTrue(el.required);
```
Ваш `#email` повинен бути нащадком `#survey-form`.
```js
-const el = document.querySelector('#survey-form #email')
-assert(!!el)
+const el = document.querySelector('#survey-form #email');
+assert.isNotNull(el);
```
Ви повинні мати елемент `input` з `id` зі значенням `number`.
```js
-const el = document.getElementById('number')
-assert(!!el && el.tagName === 'INPUT')
+const el = document.getElementById('number');
+assert.isNotNull(el);
+assert.strictEqual(el.tagName, 'INPUT');
```
Ваш `#number` повинен бути нащадком `#survey-form`.
```js
-const el = document.querySelector('#survey-form #number')
-assert(!!el)
+const el = document.querySelector('#survey-form #number');
+assert.isNotNull(el);
```
Ваш `#number` повинен мати `type` зі значенням `number`.
```js
-const el = document.getElementById('number')
-assert(!!el && el.type === 'number')
+const el = document.getElementById('number');
+assert.isNotNull(el);
+assert.strictEqual(el.type, 'number');
```
Ваш `#number` повинен мати атрибут `min` з числовим значенням.
```js
-const el = document.getElementById('number')
-assert(!!el && el.min && isFinite(el.min))
+const el = document.getElementById('number');
+assert.isNotNull(el);
+assert.isNotEmpty(el.min);
+assert.isTrue(isFinite(el.min));
```
Ваш `#number` повинен мати атрибут `max` з числовим значенням.
```js
-const el = document.getElementById('number')
-assert(!!el && el.max && isFinite(el.max))
+const el = document.getElementById('number');
+assert.isNotNull(el);
+assert.isNotEmpty(el.max);
+assert.isTrue(isFinite(el.max));
```
Ви повинні мати елемент `label` з `id` зі значенням `name-label`.
```js
-const el = document.getElementById('name-label')
-assert(!!el && el.tagName === 'LABEL')
+const el = document.getElementById('name-label');
+assert.isNotNull(el);
+assert.strictEqual(el.tagName, 'LABEL');
```
Ви повинні мати елемент `label` з `id` зі значенням `email-label`.
```js
-const el = document.getElementById('email-label')
-assert(!!el && el.tagName === 'LABEL')
+const el = document.getElementById('email-label');
+assert.isNotNull(el);
+assert.strictEqual(el.tagName, 'LABEL');
```
Ви повинні мати елемент `label` з `id` зі значенням `number-label`.
```js
-const el = document.getElementById('number-label')
-assert(!!el && el.tagName === 'LABEL')
+const el = document.getElementById('number-label');
+assert.isNotNull(el);
+assert.strictEqual(el.tagName, 'LABEL');
```
Ваш `#name-label` повинен містити текст, який описує введені дані.
```js
-const el = document.getElementById('name-label')
-assert(!!el && el.innerText.length > 0)
+const el = document.getElementById('name-label');
+assert.isNotNull(el);
+assert.isAbove(el.innerText.length, 0);
```
Ваш `#email-label` повинен містити текст, який описує введені дані.
```js
-const el = document.getElementById('email-label')
-assert(!!el && el.innerText.length > 0)
+const el = document.getElementById('email-label');
+assert.isNotNull(el);
+assert.isAbove(el.innerText.length, 0);
```
Ваш `#number-label` повинен містити текст, який описує введені дані.
```js
-const el = document.getElementById('number-label')
-assert(!!el && el.innerText.length > 0)
+const el = document.getElementById('number-label');
+assert.isNotNull(el);
+assert.isAbove(el.innerText.length, 0);
```
Ваш `#name-label` повинен бути нащадком `#survey-form`.
```js
-const el = document.querySelector('#survey-form #name-label')
-assert(!!el)
+const el = document.querySelector('#survey-form #name-label');
+assert.isNotNull(el);
```
Ваш `#email-label` повинен бути нащадком `#survey-form`.
```js
-const el = document.querySelector('#survey-form #email-label')
-assert(!!el)
+const el = document.querySelector('#survey-form #email-label');
+assert.isNotNull(el);
```
Ваш `#number-label` повинен бути нащадком `#survey-form`.
```js
-const el = document.querySelector('#survey-form #number-label')
-assert(!!el)
+const el = document.querySelector('#survey-form #number-label');
+assert.isNotNull(el);
```
Ваш `#name` повинен мати атрибут `placeholder` та значення.
```js
-const el = document.getElementById('name')
-assert(!!el && !!el.placeholder && el.placeholder.length > 0)
+const el = document.getElementById('name');
+assert.isNotNull(el);
+assert.isNotNull(el.placeholder);
+assert.isAbove(el.placeholder.length, 0);
```
Ваш `#email` повинен мати атрибут `placeholder` та значення.
```js
-const el = document.getElementById('email')
-assert(!!el && !!el.placeholder && el.placeholder.length > 0)
+const el = document.getElementById('email');
+assert.isNotNull(el);
+assert.isNotNull(el.placeholder);
+assert.isAbove(el.placeholder.length, 0);
```
Ваш `#number` повинен мати атрибут `placeholder` та значення.
```js
-const el = document.getElementById('number')
-assert(!!el && !!el.placeholder && el.placeholder.length > 0)
+const el = document.getElementById('number');
+assert.isNotNull(el);
+assert.isNotNull(el.placeholder);
+assert.isAbove(el.placeholder.length, 0);
```
Ви повинні мати поле `select` з `id` зі значенням `dropdown`.
```js
-const el = document.getElementById('dropdown')
-assert(!!el && el.tagName === 'SELECT')
+const el = document.getElementById('dropdown');
+assert.isNotNull(el);
+assert.strictEqual(el.tagName, 'SELECT');
```
Ваш `#dropdown` повинен мати щонайменше два елементи `option` з можливістю вибору (не відключені).
```js
-const els = document.querySelectorAll('#dropdown option:not([disabled])')
-assert(els.length >= 2)
+const els = document.querySelectorAll('#dropdown option:not([disabled])');
+assert.isAtLeast(els.length, 2);
```
Ваш `#dropdown` повинен бути нащадком `#survey-form`.
```js
-const el = document.querySelector('#survey-form #dropdown')
-assert(!!el)
+const el = document.querySelector('#survey-form #dropdown');
+assert.isNotNull(el);
```
Ви повинні мати щонайменше два елементи `input` з `type` зі значенням `radio` (радіокнопки).
```js
-const els = document.querySelectorAll('input[type="radio"]')
-assert(els.length >= 2)
+const els = document.querySelectorAll('input[type="radio"]');
+assert.isAtLeast(els.length, 2);
```
Ви повинні мати щонайменше дві радіокнопки, які є нащадками `#survey-form`.
```js
-const els = document.querySelectorAll('#survey-form input[type="radio"]')
-assert(els.length >= 2)
+const els = document.querySelectorAll('#survey-form input[type="radio"]');
+assert.isAtLeast(els.length, 2);
```
Всі радіокнопки повинні мати атрибут `value` та значення.
```js
-const els1 = document.querySelectorAll('input[type="radio"]')
-const els2 = document.querySelectorAll('input[type="radio"][value=""], input[type="radio"]:not([value])')
-assert(els1.length > 0 && els2.length === 0)
+const els1 = document.querySelectorAll('input[type="radio"]');
+const els2 = document.querySelectorAll(
+ 'input[type="radio"][value=""], input[type="radio"]:not([value])'
+);
+assert.isAbove(els1.length, 0);
+assert.lengthOf(els2, 0);
```
Всі радіокнопки повинні мати атрибут `name` та значення.
```js
-const els1 = document.querySelectorAll('input[type="radio"]')
-const els2 = document.querySelectorAll('input[type="radio"][name=""], input[type="radio"]:not([name])')
-assert(els1.length > 0 && els2.length === 0)
+const els1 = document.querySelectorAll('input[type="radio"]');
+const els2 = document.querySelectorAll(
+ 'input[type="radio"][name=""], input[type="radio"]:not([name])'
+);
+assert.isAbove(els1.length, 0);
+assert.lengthOf(els2, 0);
```
В кожній групі радіокнопок повинно бути щонайменше 2 радіокнопки.
```js
const radioButtons = document.querySelectorAll('input[type="radio"]');
-const groups = {}
+const groups = {};
if (radioButtons) {
radioButtons.forEach(el => {
- if (!groups[el.name]) groups[el.name] = []
- groups[el.name].push(el)
- })
+ if (!groups[el.name]) groups[el.name] = [];
+ groups[el.name].push(el);
+ });
}
-const groupKeys = Object.keys(groups)
+const groupKeys = Object.keys(groups);
groupKeys.forEach(key => {
- if (groups[key].length < 2) assert(false)
-})
+ if (groups[key].length < 2) assert(false);
+});
-assert(groupKeys.length > 0)
+assert.isAbove(groupKeys.length, 0);
```
Ви повинні мати щонайменше два елементи `input` з `type` зі значенням `checkbox` (прапорцями), що є нащадками `#survey-form`.
```js
const els = document.querySelectorAll('#survey-form input[type="checkbox"]');
-assert(els.length >= 2)
+assert.isAtLeast(els.length, 2);
```
Всі прапорці всередині `#survey-form` повинні мати атрибут `value` та значення.
```js
-const els1 = document.querySelectorAll('#survey-form input[type="checkbox"]')
-const els2 = document.querySelectorAll('#survey-form input[type="checkbox"][value=""], #survey-form input[type="checkbox"]:not([value])')
-assert(els1.length > 0 && els2.length === 0)
+const els1 = document.querySelectorAll('#survey-form input[type="checkbox"]');
+const els2 = document.querySelectorAll(
+ '#survey-form input[type="checkbox"][value=""], #survey-form input[type="checkbox"]:not([value])'
+);
+assert.isAbove(els1.length, 0);
+assert.lengthOf(els2, 0);
```
Ви повинні мати щонайменше один елемент `textarea`, що є нащадком `#survey-form`.
```js
-const el = document.querySelector('#survey-form textarea')
-assert(!!el)
+const el = document.querySelector('#survey-form textarea');
+assert.isNotNull(el);
```
Ви повинні мати елемент `input` або `button` з `id` зі значенням `submit`.
```js
-const el = document.getElementById('submit')
-assert(!!el && (el.tagName === 'INPUT' || el.tagName === 'BUTTON'))
+const el = document.getElementById('submit');
+assert.isNotNull(el);
+assert.isTrue(el.tagName === 'INPUT' || el.tagName === 'BUTTON');
```
Ваш `#submit` повинен мати `type` зі значенням `submit`.
```js
-const el = document.getElementById('submit')
-assert(!!el && el.type === 'submit')
+const el = document.getElementById('submit');
+assert.isNotNull(el);
+assert.strictEqual(el.type, 'submit');
```
Ваш `#submit` повинен бути нащадком `#survey-form`.
```js
-const el = document.querySelector('#survey-form #submit')
-assert(!!el)
+const el = document.querySelector('#survey-form #submit');
+assert.isNotNull(el);
```
# --seed--
@@ -508,7 +549,10 @@ body {
background: #3a3240;
color: white;
}
-input, textarea, select, button {
+input,
+textarea,
+select,
+button {
background: #3a3240;
color: white;
}
diff --git a/curriculum/challenges/ukrainian/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc174fcf86c76b9248c6eb2.md b/curriculum/challenges/ukrainian/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc174fcf86c76b9248c6eb2.md
index 41b565959a..53dfc1d236 100644
--- a/curriculum/challenges/ukrainian/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc174fcf86c76b9248c6eb2.md
+++ b/curriculum/challenges/ukrainian/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc174fcf86c76b9248c6eb2.md
@@ -49,9 +49,11 @@ assert(document.querySelector('h1').innerText.toLowerCase() === 'catphotoapp');
You appear to be using a browser extension that is modifying the page. Be sure to turn off all browser extensions.
```js
-assert.isAtMost(document.querySelectorAll('script').length, 2);
-assert.equal(document.querySelectorAll('style').length, 1);
-assert.equal(document.querySelectorAll('link').length, 0);
+if(__checkForBrowserExtensions){
+ assert.isAtMost(document.querySelectorAll('script').length, 2);
+ assert.equal(document.querySelectorAll('style').length, 1);
+ assert.equal(document.querySelectorAll('link').length, 0);
+}
```
# --seed--
diff --git a/curriculum/challenges/ukrainian/14-responsive-web-design-22/learn-intermediate-css-by-building-a-cat-painting/646ceb843412c74edee27a79.md b/curriculum/challenges/ukrainian/14-responsive-web-design-22/learn-intermediate-css-by-building-a-cat-painting/646ceb843412c74edee27a79.md
index 903f49778b..ece1ef4840 100644
--- a/curriculum/challenges/ukrainian/14-responsive-web-design-22/learn-intermediate-css-by-building-a-cat-painting/646ceb843412c74edee27a79.md
+++ b/curriculum/challenges/ukrainian/14-responsive-web-design-22/learn-intermediate-css-by-building-a-cat-painting/646ceb843412c74edee27a79.md
@@ -18,49 +18,49 @@ dashedName: step-22
Ви повинні мати селектор `.cat-right-ear`.
```js
-assert(new __helpers.CSSHelp(document)?.getStyle('.cat-head'))
+assert.exists(new __helpers.CSSHelp(document)?.getStyle('.cat-right-ear'))
```
Селектор `.cat-right-ear` повинен мати властивість `height` зі значенням `100px`. Не забудьте про крапку з комою.
```js
-assert(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.height === '100px')
+assert.strictEqual(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.height, '100px')
```
Селектор `.cat-right-ear` повинен мати властивість `width` зі значенням `100px`. Не забудьте про крапку з комою.
```js
-assert(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.width === '100px')
+assert.strictEqual(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.width, '100px')
```
Селектор `.cat-right-ear` повинен мати властивість `background-color` зі значенням `white`. Не забудьте про крапку з комою.
```js
-assert(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.backgroundColor === 'white')
+assert.strictEqual(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.backgroundColor, 'white')
```
Селектор `.cat-right-ear` повинен мати властивість `border-left` зі значенням `35px solid blue`. Не забудьте про крапку з комою.
```js
-assert(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.borderLeft === '35px solid blue')
+assert.strictEqual(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.borderLeft, '35px solid blue')
```
Селектор `.cat-right-ear` повинен мати властивість `border-right` зі значенням `35px solid blue`. Не забудьте про крапку з комою.
```js
-assert(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.borderRight === '35px solid blue')
+assert.strictEqual(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.borderRight, '35px solid blue')
```
Селектор `.cat-right-ear` повинен мати властивість `border-top` зі значенням `35px solid red`. Не забудьте про крапку з комою.
```js
-assert(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.borderTop === '35px solid red')
+assert.strictEqual(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.borderTop, '35px solid red')
```
Селектор `.cat-right-ear` повинен мати властивість `border-bottom` зі значенням `35px solid red`. Не забудьте про крапку з комою.
```js
-assert(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.borderBottom === '35px solid red')
+assert.strictEqual(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.borderBottom, '35px solid red')
```
# --seed--
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/build-a-palindrome-checker-project/build-a-palindrome-checker.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/build-a-palindrome-checker-project/build-a-palindrome-checker.md
index 0f11c8da61..e82dc309ec 100644
--- a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/build-a-palindrome-checker-project/build-a-palindrome-checker.md
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/build-a-palindrome-checker-project/build-a-palindrome-checker.md
@@ -25,12 +25,12 @@ dashedName: build-a-palindrome-checker
1. Якщо елемент `#text-input` містить текст `_eye` та натиснути на елемент `#check-btn`, то елемент `#result` повинен містити текст `"_eye is a palindrome"`.
1. Якщо елемент `#text-input` містить текст `race car` та натиснути на елемент `#check-btn`, то елемент `#result` повинен містити текст `"race car is a palindrome"`.
1. Якщо елемент `#text-input` містить текст `not a palindrome` та натиснути на елемент `#check-btn`, то елемент `#result` повинен містити текст `"not a palindrome is not a palindrome"`.
-1. Якщо елемент `#text-input` містить текст `A man, a plan, a canal. Panama` та натиснути на елемент `#check-btn`, то елемент `#result` повинен містити текст `"A man, a plan, a canal. Panama is a palindrome"`.
+1. When the `#text-input` element contains the text `A man, a plan, a canal. Panama` and the `#check-btn` element is clicked, the `#result` element should contain the text `"A man, a plan, a canal. Panama is a palindrome"`.
1. Якщо елемент `#text-input` містить текст `never odd or even` та натиснути на елемент `#check-btn`, то елемент `#result` повинен містити текст `"never odd or even is a palindrome"`.
1. Якщо елемент `#text-input` містить текст `nope` та натиснути на елемент `#check-btn`, то елемент `#result` повинен містити текст `"nope is not a palindrome"`.
1. Якщо елемент `#text-input` містить текст `almostomla` та натиснути на елемент `#check-btn`, то елемент `#result` повинен містити текст `"almostomla is not a palindrome"`.
1. Якщо елемент `#text-input` містить текст `My age is 0, 0 si ega ym.` та натиснути на елемент `#check-btn`, то елемент `#result` повинен містити текст `"My age is 0, 0 si ega ym. is a palindrome"`.
-1. Якщо елемент `#text-input` містить текст `1 eye for of 1 eye.` та натиснути на елемент `#check-btn`, то елемент `#result` повинен містити текст `"1 eye for of 1 eye. is not a palindrome"`.
+1. When the `#text-input` element contains the text `1 eye for of 1 eye.` and the `#check-btn` element is clicked, the `#result` element should contain the text `"1 eye for of 1 eye. is not a palindrome"`.
1. Якщо елемент `#text-input` містить текст `0_0 (: /-\ :) 0-0` та натиснути на елемент `#check-btn`, то елемент `#result` повинен містити текст `"0_0 (: /-\ :) 0-0 is a palindrome"`.
1. Якщо елемент `#text-input` містить текст `five|\_/|four` та натиснути на елемент `#check-btn`, то елемент `#result` повинен містити текст `"five|\_/|four is not a palindrome"`.
@@ -138,7 +138,7 @@ checkBtn.click();
assert.strictEqual(resultEl.innerText.trim().replace(/[.,?!]+$/g, '').toLowerCase(), 'not a palindrome is not a palindrome');
```
-Якщо елемент `#text-input` містить текст `A man, a plan, a canal. Panama` та натиснути на елемент `#check-btn`, то елемент `#result` повинен містити текст `"A man, a plan, a canal. Panama is a palindrome"`.
+When the `#text-input` element contains the text `A man, a plan, a canal. Panama` and the `#check-btn` element is clicked, the `#result` element should contain the text `"A man, a plan, a canal. Panama is a palindrome"`.
```js
const inputEl = document.getElementById('text-input');
@@ -203,7 +203,7 @@ checkBtn.click();
assert.strictEqual(resultEl.innerText.trim().replace(/[.,?!]+$/g, '').toLowerCase(), 'my age is 0, 0 si ega ym. is a palindrome');
```
-Якщо елемент `#text-input` містить текст `1 eye for of 1 eye.` та натиснути на елемент `#check-btn`, то елемент `#result` повинен містити текст `"1 eye for of 1 eye. is not a palindrome"`.
+When the `#text-input` element contains the text `1 eye for of 1 eye.` and the `#check-btn` element is clicked, the `#result` element should contain the text `"1 eye for of 1 eye. is not a palindrome"`.
```js
const inputEl = document.getElementById('text-input');
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
index ec9c1d8780..9be4f75630 100644
--- 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
@@ -14,65 +14,162 @@ dashedName: step-87
Додайте другий елемент `p` до шаблонного літерала.
```js
-assert.isAtLeast(getTemplateContents(code)?.match(/
[^<]*<\/p>/g)?.length, 2);
-```
-Ваш другий елемент `p` має бути на новому рядку.
+const entryDropdownElement = document.getElementById('entry-dropdown');
+budgetNumberInput.value = 2000;
+addEntry();
-```js
-assert.match(getTemplateContents(code), /
\s*
[^<]*<\/p>\n\s*
[^<]*<\/p>/);
-```
+const breakfastValueElement = document.getElementById("breakfast-1-calories");
+breakfastValueElement.value = 300;
+entryDropdownElement.value = "lunch";
+addEntry();
-Другий елемент `p` повинен йти після наявного елемента `p`.
+const lunchValueElement = document.getElementById("lunch-1-calories");
+lunchValueElement.value = 600;
+entryDropdownElement.value = "dinner";
+addEntry();
-```js
-assert.match(getTemplateContents(code), /
\$\{budgetCalories\}\s*Calories\s*Budgeted<\/p>\s*
/);
+const dinnerValueElement = document.getElementById("dinner-1-calories");
+dinnerValueElement.value = 700;
+entryDropdownElement.value = "snacks";
+addEntry();
+
+const snacksValueElement = document.getElementById("snacks-1-calories");
+snacksValueElement.value = 200;
+entryDropdownElement.value = "exercise";
+addEntry();
+
+const exerciseValueElement = document.getElementById("exercise-1-calories");
+exerciseValueElement.value = 300;
+const fakeEvent = { preventDefault: () => {} };
+calculateCalories(fakeEvent);
+
+
+const output = document.getElementById('output');
+assert.isAtLeast(output.children.length, 4);
```
Другий елемент `p` повинен мати текст `${consumedCalories} Calories Consumed`.
```js
-const secondP = getTemplateContents(code)?.split(/
/)?.[2];
-assert.match(secondP, /\$\{consumedCalories\}\s*Calories\s*Consumed<\/p>/);
+
+const entryDropdownElement = document.getElementById('entry-dropdown');
+budgetNumberInput.value = 2000;
+addEntry();
+
+const breakfastValueElement = document.getElementById("breakfast-1-calories");
+breakfastValueElement.value = 300;
+entryDropdownElement.value = "lunch";
+addEntry();
+
+const lunchValueElement = document.getElementById("lunch-1-calories");
+lunchValueElement.value = 600;
+entryDropdownElement.value = "dinner";
+addEntry();
+
+const dinnerValueElement = document.getElementById("dinner-1-calories");
+dinnerValueElement.value = 700;
+entryDropdownElement.value = "snacks";
+addEntry();
+
+const snacksValueElement = document.getElementById("snacks-1-calories");
+snacksValueElement.value = 200;
+entryDropdownElement.value = "exercise";
+addEntry();
+
+const exerciseValueElement = document.getElementById("exercise-1-calories");
+exerciseValueElement.value = 300;
+const fakeEvent = { preventDefault: () => {} };
+calculateCalories(fakeEvent);
+
+assert.strictEqual(output.children[3].innerText,"1800 Calories Consumed");
+
+dinnerValueElement.value = 300;
+calculateCalories(fakeEvent);
+assert.strictEqual(output.children[3].innerText,"1400 Calories Consumed");
+
```
Додайте третій елемент `p` до шаблонного літерала.
```js
-assert.lengthOf(getTemplateContents(code)?.match(/
[^<]*<\/p>/g), 3);
-```
-Третій елемент `p` має бути на новому рядку.
+const entryDropdownElement = document.getElementById('entry-dropdown');
+budgetNumberInput.value = 2000;
+addEntry();
-```js
-assert.match(getTemplateContents(code), /
\s*
[^<]*<\/p>\s*
[^<]*<\/p>\n\s*
[^<]*<\/p>/);
-```
+const breakfastValueElement = document.getElementById("breakfast-1-calories");
+breakfastValueElement.value = 300;
+entryDropdownElement.value = "lunch";
+addEntry();
-Третій елемент `p` має йти після другого наявного елемента `p`.
+const lunchValueElement = document.getElementById("lunch-1-calories");
+lunchValueElement.value = 600;
+entryDropdownElement.value = "dinner";
+addEntry();
-```js
-assert.match(getTemplateContents(code), /
\$\{consumedCalories\}\s*Calories\s*Consumed<\/p>\s*
/);
+const dinnerValueElement = document.getElementById("dinner-1-calories");
+dinnerValueElement.value = 700;
+entryDropdownElement.value = "snacks";
+addEntry();
+
+const snacksValueElement = document.getElementById("snacks-1-calories");
+snacksValueElement.value = 200;
+entryDropdownElement.value = "exercise";
+addEntry();
+
+const exerciseValueElement = document.getElementById("exercise-1-calories");
+exerciseValueElement.value = 300;
+const fakeEvent = { preventDefault: () => {} };
+calculateCalories(fakeEvent);
+
+assert.lengthOf(output.children,5);
```
Третій елемент `p` повинен містити текст `${exerciseCalories} Calories Burned`.
```js
-const thirdP = getTemplateContents(code)?.split(/
/)?.[3];
-assert.match(thirdP, /\$\{exerciseCalories\}\s*Calories\s*Burned<\/p>/);
-```
-# --seed--
+const entryDropdownElement = document.getElementById('entry-dropdown');
+budgetNumberInput.value = 2000;
+addEntry();
-## --after-user-code--
+const breakfastValueElement = document.getElementById("breakfast-1-calories");
+breakfastValueElement.value = 300;
+entryDropdownElement.value = "lunch";
+addEntry();
+
+const lunchValueElement = document.getElementById("lunch-1-calories");
+lunchValueElement.value = 600;
+entryDropdownElement.value = "dinner";
+addEntry();
+
+const dinnerValueElement = document.getElementById("dinner-1-calories");
+dinnerValueElement.value = 700;
+entryDropdownElement.value = "snacks";
+addEntry();
+
+const snacksValueElement = document.getElementById("snacks-1-calories");
+snacksValueElement.value = 200;
+entryDropdownElement.value = "exercise";
+addEntry();
+
+const exerciseValueElement = document.getElementById("exercise-1-calories");
+exerciseValueElement.value = 300;
+const fakeEvent = { preventDefault: () => {} };
+calculateCalories(fakeEvent);
+
+assert.strictEqual(output.children[4].innerText,"300 Calories Burned");
+
+exerciseValueElement.value = Math.floor(Math.random() * 500);
+
+calculateCalories(fakeEvent);
+assert.strictEqual(output.children[4].innerText, exerciseValueElement.value.toString() + " Calories Burned");
-```js
-function getTemplateContents(code) {
- return code
- .split(/output\s*\.\s*innerHTML\s*=\s*/)?.[1]
- ?.split(/`/)?.[1];
-}
```
+# --seed--
+
## --seed-contents--
```html
@@ -270,7 +367,7 @@ function addEntry() {
targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
}
---fcc-editable-region--
+
function calculateCalories(e) {
e.preventDefault();
isError = false;
@@ -292,6 +389,7 @@ function calculateCalories(e) {
return;
}
+--fcc-editable-region--
const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
const surplusOrDeficit = remainingCalories < 0 ? 'Surplus' : 'Deficit';
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-functional-programming-by-building-a-spreadsheet/64496d80bc174a158c973080.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-functional-programming-by-building-a-spreadsheet/64496d80bc174a158c973080.md
index 42bfdca309..e27875ccfa 100644
--- a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-functional-programming-by-building-a-spreadsheet/64496d80bc174a158c973080.md
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-functional-programming-by-building-a-spreadsheet/64496d80bc174a158c973080.md
@@ -7,62 +7,29 @@ dashedName: step-25
# --description--
-Використовуючи тернарний синтаксис, перевірте, чи `length` парне використовуючи функцію `isEven`. Якщо так, поверніть середнє числа в `middle` індексі та числа після нього. Якщо воно непарне, поверніть число за індексом `middle` – вам потрібно буде округлити значення `middle` у більшу сторону.
+Check if `length` is even using your `isEven` function. Якщо так, поверніть середнє числа в `middle` індексі та числа після нього. Якщо воно непарне, поверніть число за індексом `middle` – вам потрібно буде округлити значення `middle` у більшу сторону.
# --hints--
-Використайте ключове слово `return`.
+You should return a value from the `median` function.
```js
-assert.match(code, /const\s+median\s*=\s*nums\s*=>\s*\{\s*const\s+sorted\s*=\s*nums\.slice\(\s*\)\.sort\(\s*\(\s*a\s*,\s*b\s*\)\s*=>\s*a\s*-\s*b\s*\)\s*\s*;?\s*const\s+length\s*=\s*sorted\.length\s*;?\s*const\s+middle\s*=\s*length\s*\/\s*2\s*-\s*1\s*;?\s*return/);
+assert.exists(median([2,4,6,8]));
```
-Викличте функцію `isEven()` після ключового слова `return`.
+If `length` is even, you should return the average of the number at the `middle` index and the number after it.
```js
-assert.match(code, /const\s+median\s*=\s*nums\s*=>\s*\{\s*const\s+sorted\s*=\s*nums\.slice\(\s*\)\.sort\(\s*\(\s*a\s*,\s*b\s*\)\s*=>\s*a\s*-\s*b\s*\)\s*\s*;?\s*const\s+length\s*=\s*sorted\.length\s*;?\s*const\s+middle\s*=\s*length\s*\/\s*2\s*-\s*1\s*;?\s*return\s+isEven\(/);
+assert.strictEqual(median([2,4,6,8]),5);
+assert.strictEqual(median([6,12,18,24]),15);
```
-Передайте змінну `length` до виклику `isEven()`.
-```js
-assert.match(code, /const\s+median\s*=\s*nums\s*=>\s*\{\s*const\s+sorted\s*=\s*nums\.slice\(\s*\)\.sort\(\s*\(\s*a\s*,\s*b\s*\)\s*=>\s*a\s*-\s*b\s*\)\s*\s*;?\s*const\s+length\s*=\s*sorted\.length\s*;?\s*const\s+middle\s*=\s*length\s*\/\s*2\s*-\s*1\s*;?\s*return\s+isEven\(\s*length\s*\)/);
-```
-
-Щоб перевірити правильність виклику `isEven()`, використайте тернарний синтаксис.
-
-```js
-assert.match(code, /const\s+median\s*=\s*nums\s*=>\s*\{\s*const\s+sorted\s*=\s*nums\.slice\(\s*\)\.sort\(\s*\(\s*a\s*,\s*b\s*\)\s*=>\s*a\s*-\s*b\s*\)\s*\s*;?\s*const\s+length\s*=\s*sorted\.length\s*;?\s*const\s+middle\s*=\s*length\s*\/\s*2\s*-\s*1\s*;?\s*return\s+isEven\(\s*length\s*\)\s*\?/);
-```
-
-Якщо потрійний є правдивим, викличте функцію `average()`.
-
-```js
-assert.match(code, /const\s+median\s*=\s*nums\s*=>\s*\{\s*const\s+sorted\s*=\s*nums\.slice\(\s*\)\.sort\(\s*\(\s*a\s*,\s*b\s*\)\s*=>\s*a\s*-\s*b\s*\)\s*\s*;?\s*const\s+length\s*=\s*sorted\.length\s*;?\s*const\s+middle\s*=\s*length\s*\/\s*2\s*-\s*1\s*;?\s*return\s+isEven\(\s*length\s*\)\s*\?\s*average\(/);
-```
-
-Передайте масив у функцію `average()`.
-
-```js
-assert.match(code, /const\s+median\s*=\s*nums\s*=>\s*\{\s*const\s+sorted\s*=\s*nums\.slice\(\s*\)\.sort\(\s*\(\s*a\s*,\s*b\s*\)\s*=>\s*a\s*-\s*b\s*\)\s*\s*;?\s*const\s+length\s*=\s*sorted\.length\s*;?\s*const\s+middle\s*=\s*length\s*\/\s*2\s*-\s*1\s*;?\s*return\s+isEven\(\s*length\s*\)\s*\?\s*average\(\s*\[/);
-```
-
-Першим елементом масиву, який передається в `average()`, має бути елемент із індексом `middle` масиву `sorted`.
-
-```js
-assert.match(code, /const\s+median\s*=\s*nums\s*=>\s*\{\s*const\s+sorted\s*=\s*nums\.slice\(\s*\)\.sort\(\s*\(\s*a\s*,\s*b\s*\)\s*=>\s*a\s*-\s*b\s*\)\s*\s*;?\s*const\s+length\s*=\s*sorted\.length\s*;?\s*const\s+middle\s*=\s*length\s*\/\s*2\s*-\s*1\s*;?\s*return\s+isEven\(\s*length\s*\)\s*\?\s*average\(\s*\[\s*sorted\s*\[\s*middle\s*\]/);
-```
-
-Першим елементом масиву, який передається в `average()`, має бути елемент із індексом `middle + 1` масиву `sorted`.
-
-```js
-assert.match(code, /const\s+median\s*=\s*nums\s*=>\s*\{\s*const\s+sorted\s*=\s*nums\.slice\(\s*\)\.sort\(\s*\(\s*a\s*,\s*b\s*\)\s*=>\s*a\s*-\s*b\s*\)\s*\s*;?\s*const\s+length\s*=\s*sorted\.length\s*;?\s*const\s+middle\s*=\s*length\s*\/\s*2\s*-\s*1\s*;?\s*return\s+isEven\(\s*length\s*\)\s*\?\s*average\(\s*\[\s*sorted\s*\[\s*middle\s*\]\s*,\s*sorted\s*\[\s*middle\s*\+\s*1\s*\]\s*\]\s*\)/);
-```
-
-Якщо потрійний є хибним, поверніть значення з `sorted` за індексом `middle`. Використайте `Math.ceil()`, щоб округлити значення `middle` в більшу сторону.
+If `length` is odd, you should return the value at the `middle` index.
```js
-assert.match(code, /const\s+median\s*=\s*nums\s*=>\s*\{\s*const\s+sorted\s*=\s*nums\.slice\(\s*\)\.sort\(\s*\(\s*a\s*,\s*b\s*\)\s*=>\s*a\s*-\s*b\s*\)\s*\s*;?\s*const\s+length\s*=\s*sorted\.length\s*;?\s*const\s+middle\s*=\s*length\s*\/\s*2\s*-\s*1\s*;?\s*return\s+isEven\(\s*length\s*\)\s*\?\s*average\(\s*\[\s*sorted\s*\[\s*middle\s*\]\s*,\s*sorted\s*\[\s*middle\s*\+\s*1\s*\]\s*\]\s*\)\s*:\s*sorted\s*\[\s*Math\.ceil\(\s*middle\s*\)\s*\]\s*;?/);
+assert.strictEqual(median([2,4,6,8,10]),6);
+assert.strictEqual(median([3,6,9,12,15]),9);
```
# --seed--
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/review-algorithmic-thinking-by-building-a-dice-game/657e230500602983e01fff6e.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/review-algorithmic-thinking-by-building-a-dice-game/657e230500602983e01fff6e.md
index 5f0507b3b5..ceb13c6e1f 100644
--- a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/review-algorithmic-thinking-by-building-a-dice-game/657e230500602983e01fff6e.md
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/review-algorithmic-thinking-by-building-a-dice-game/657e230500602983e01fff6e.md
@@ -55,14 +55,44 @@ assert.strictEqual(scoreSpans[3].innerText, ", score = 30");
Якщо черга не випадає, функція `checkForStraights` має ввімкнути останній перемикач, встановити значення на `0` та оновити відображуваний текст на `, score = 0`.
+```js
+const assertNoStraight = (_diceValuesArr) => {
+ resetRadioOptions();
+ checkForStraights(_diceValuesArr);
+ assert.isTrue(scoreInputs[3].disabled);
+ assert.isTrue(scoreInputs[4].disabled);
+ assert.isFalse(scoreInputs[5].disabled);
+ assert.strictEqual(scoreInputs[5].value, "0");
+ assert.strictEqual(scoreSpans[5].innerText, ", score = 0");
+}
+
+assertNoStraight([1,1,1,1,1]);
+assertNoStraight([1,1,4,4,4]);
+```
+
+You should call the `checkForStraights` function when the `rollDiceBtn` is clicked.
+
```js
resetRadioOptions();
-checkForStraights([1,1,1,1,1]);
-assert.isTrue(scoreInputs[3].disabled);
-assert.isTrue(scoreInputs[4].disabled);
-assert.isFalse(scoreInputs[5].disabled);
-assert.strictEqual(scoreInputs[5].value, "0");
-assert.strictEqual(scoreSpans[5].innerText, ", score = 0");
+const origMathRandom = Math.random;
+// Temporarily modifies Math.random to guarantee a straight.
+const myMathRandom = (() => {
+ let i = 0;
+ const values = [4/6,2/6,5/6,3/6,1/6];
+ return () => values[i++ % 5];
+})();
+
+Math.random = myMathRandom;
+
+try {
+ rollDiceBtn.click();
+} finally {
+ Math.random = origMathRandom;
+}
+
+assert.isFalse(scoreInputs[4].disabled);
+assert.strictEqual(scoreInputs[4].value, "40");
+assert.strictEqual(scoreSpans[4].innerText, ", score = 40");
```
# --seed--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b068e28a3bd135ced0042.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b068e28a3bd135ced0042.md
index 0dacaabd2f..edba99d2fc 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b068e28a3bd135ced0042.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b068e28a3bd135ced0042.md
@@ -21,7 +21,7 @@ dashedName: task-2
## --answers--
-Запитується про загальну думку Тома щодо його роботи.
+It asks for Tom's complete opinion about the workplace.
### --feedback--
@@ -37,15 +37,15 @@ dashedName: task-2
---
-Запитується про почуття Тома з першого дня до сьогодення.
+It asks about Tom's feelings from his first day to the present time.
---
-Запитується тільки про перший день Тома на роботі.
+It asks only about Tom's first day at the workplace.
### --feedback--
-Запитується про досвід Тома до моменту самого запитання.
+It is about Tom's experience until the time he is asked.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b190c4e736f5c4005b132.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b190c4e736f5c4005b132.md
index c3f082d207..eb624f1bb6 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b190c4e736f5c4005b132.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b190c4e736f5c4005b132.md
@@ -24,7 +24,7 @@ Sarah: Yes, we go out with the team sometimes. Are you into these activities? --
## --answers--
-`Yes, it’s great!`
+`Yes, it's great!`
### --feedback--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b1ae0c2fb4c64071ade7a.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b1ae0c2fb4c64071ade7a.md
index ec47c676cc..a166451f23 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b1ae0c2fb4c64071ade7a.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b1ae0c2fb4c64071ade7a.md
@@ -19,7 +19,7 @@ dashedName: task-10
Оберіть правильне запитання Тома до Сари:
-`Absolutely! They are really fun. What is the team’s favorite?`
+`Absolutely! They are really fun. What is the team's favorite?`
## --answers--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b23ad0df43588a6eadfa4.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b23ad0df43588a6eadfa4.md
index e877c08558..f0e32a02f9 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b23ad0df43588a6eadfa4.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b23ad0df43588a6eadfa4.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-12
---
-
---
-`What is the team’s favorite?` та `Many of us enjoy the monthly game night.`
+`What is the team's favorite?` and `Many of us enjoy the monthly game night.`
### --feedback--
@@ -47,7 +47,7 @@ The first sentence is correct. В другому прикладі ствердж
---
-`What is the team’s favorite?` та `Are you into playing board games?`
+`What is the team's favorite?` and `Are you into playing board games?`
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b24e5edd7708e93549565.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b24e5edd7708e93549565.md
index 0bc9569d61..cfe0ab9830 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b24e5edd7708e93549565.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b24e5edd7708e93549565.md
@@ -18,7 +18,7 @@ Tom: Yes, I've played both before. Great choices. -->
`I have played this game before.` — Приклад речення в теперішньому доконаному часі. Дія відбулась у невизначений час в минулому.
-`I’ve played this game before.` — Ще один приклад речення в теперішньому доконаному часі, але з використанням скорочення `I've` для `I have`. Дія відбулась у невизначений час в минулому, як і в попередньому прикладі.
+`I've played this game before.` - This sentence is also in the present perfect tense, using the contraction `I've` for `I have`. Дія відбулась у невизначений час в минулому, як і в попередньому прикладі.
# --questions--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b69e10d6606a0185d4d4f.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b69e10d6606a0185d4d4f.md
index 302860af33..adf1d125bf 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b69e10d6606a0185d4d4f.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b69e10d6606a0185d4d4f.md
@@ -13,7 +13,7 @@ So far you have learned how to create questions with the verb `to be`. Щоб у
`You are a developer` -> `Are you a developer?`
-Але не у всіх реченнях можна поміняти місцями іменник з дієсловом. В деяких реченнях потрібно додати допоміжне дієслово, щоб утворити запитання. Одним з найбільш поширених допоміжних дієслів є `do`.
+Changing the order of the noun and the verb doesn't work in every situation. В деяких реченнях потрібно додати допоміжне дієслово, щоб утворити запитання. Одним з найбільш поширених допоміжних дієслів є `do`.
Ви можете використовувати дієслово `do` як допоміжне до більшості дієслів. В теперішньому часі воно набуває форми `do` (I, you, we, they) та `does` (he, she, it). Це як маркер, який ви додаєте на початку речення і всі розуміють, що це запитання. Наприклад:
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b6f641e5c3ab1afc6efc1.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b6f641e5c3ab1afc6efc1.md
index 9ef42a84a2..078df04b27 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b6f641e5c3ab1afc6efc1.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b6f641e5c3ab1afc6efc1.md
@@ -13,7 +13,7 @@ Before you learned to ask questions using `do`, you can also use it to create ne
`It does not function` - (Subject + `does` + `not` + main verb)
-Often, to be more practical people abbreviate `do not` to `don't` and `does not` to `doesn’t`.
+Often, to be more practical people abbreviate `do not` to `don't` and `does not` to `doesn't`.
Just like with questions, when you use `don't`, the main verb that comes after it will always be in its base form, no matter who you're talking about.
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b70cc934e0ab83cab4dbe.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b70cc934e0ab83cab4dbe.md
index 5bcd636d00..9506ff1e4b 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b70cc934e0ab83cab4dbe.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b70cc934e0ab83cab4dbe.md
@@ -29,7 +29,7 @@ dashedName: task-27
### --feedback--
-В першому пропуску Том запитує про хобі Софі. Потрібно використати `do`.
+In the first blank, Tom is asking a question about Sophie's hobbies, which requires `do.`
---
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b92b25858f24caf6894aa.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b92b25858f24caf6894aa.md
index 0525d76531..f661975fff 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b92b25858f24caf6894aa.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657b92b25858f24caf6894aa.md
@@ -11,7 +11,7 @@ Tom: It's a deal! -->
# --description--
-Вираз `only if` використовують як умову для того, щоб щось сталося. Це те ж саме, що й `this will happen if that happens`. Тобто це домовленість, в якій одна дія залежить від іншої.
+Вираз `only if` використовують як умову для того, щоб щось сталося. It's like saying `this will happen if that happens.` It's a way of making an agreement where one action depends on another.
Наприклад, якщо ваш друг каже `I'll go out only if it doesn't rain`, це означає, що він піде гуляти, якщо перестане йти дощ.
@@ -20,7 +20,7 @@ Tom: It's a deal! -->
## --text--
-Яка умова Софі?
+What is Sophie's condition?
## --answers--
@@ -44,7 +44,7 @@ Tom: It's a deal! -->
---
-Вона не хоче чути, як грає Том.
+She doesn't want to hear Tom play.
### --feedback--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657cb68bf15f349a744b5fba.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657cb68bf15f349a744b5fba.md
index 2669b1cf07..13918e1f59 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657cb68bf15f349a744b5fba.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657cb68bf15f349a744b5fba.md
@@ -7,11 +7,11 @@ dashedName: task-43
# --description--
-Якщо ви хочете дізнатися про характер чи особистість людини, не вказуючи стать, можна використати `they` як займенник однини та запитати `What are they like?`.
+When you want to learn about a person's character or personality without specifying their gender, you can use `they` as a singular pronoun and ask, `What are they like?`.
Це ввічливий та інклюзивний спосіб поставити запитання. `They` означає, що ви не робите припущень щодо статі людей. Наприклад:
-Уявіть, що хтось приєднався до вашого проєкту з програмування, але ви ще не знайомі. Замість того, щоб вгадувати стать, ви можете запитати керівника: `What are they like?`
+Imagine there is a new team member joining your programming project, but you haven't met them yet. Замість того, щоб вгадувати стать, ви можете запитати керівника: `What are they like?`
Таким чином ви зможете дізнатися про риси нового члена команди (наприклад, організованість, творчість або уважність до деталей).
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657cdc5a8e30191d1abec8b7.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657cdc5a8e30191d1abec8b7.md
index bdf57871d8..6b1dc32bde 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657cdc5a8e30191d1abec8b7.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657cdc5a8e30191d1abec8b7.md
@@ -9,7 +9,7 @@ dashedName: task-58
# --description--
-Послухайте як відмінюються дієслова в третій особі.
+Let's practice listening to verbs conjugated in the third person.
# --fillInTheBlank--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657ce061cda4a42a99c65d89.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657ce061cda4a42a99c65d89.md
index c4a07b6a3e..84c6b380ec 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657ce061cda4a42a99c65d89.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657ce061cda4a42a99c65d89.md
@@ -13,7 +13,7 @@ dashedName: task-60
## --text--
-Виберіть правильне запитання про звичне місце роботи.
+Choose the correct question for asking about someone's usual work location.
## --answers--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657cfeeeabb34d946d437dc7.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657cfeeeabb34d946d437dc7.md
index f206982476..7b9b413d19 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657cfeeeabb34d946d437dc7.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657cfeeeabb34d946d437dc7.md
@@ -11,7 +11,7 @@ dashedName: task-75
The expression `to be in good hands` means that someone is being taken care of by a competent or capable person.
-It’s like saying you can relax because you trust the person helping or looking after you.
+It's like saying you can relax because you trust the person helping or looking after you.
# --questions--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657cff86dd812f98672e2649.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657cff86dd812f98672e2649.md
index aa301dd7d8..ded7ee20df 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657cff86dd812f98672e2649.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657cff86dd812f98672e2649.md
@@ -35,7 +35,7 @@ Sophie's words are very positive, more than just average.
---
-She is unsure about Maria’s leadership skills.
+She is unsure about Maria's leadership skills.
### --feedback--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657dc1d18a0a6f25302badba.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657dc1d18a0a6f25302badba.md
index a6504cbaf0..6729f470b2 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657dc1d18a0a6f25302badba.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657dc1d18a0a6f25302badba.md
@@ -13,7 +13,7 @@ The word `reasonable` means something is fair, makes sense, or is acceptable in
## --text--
-What does `that’s reasonable` mean?
+What does `that's reasonable` mean?
## --answers--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657dc50830f9be380105f1ee.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657dc50830f9be380105f1ee.md
index 52aa0007a4..b5b7de27fd 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657dc50830f9be380105f1ee.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657dc50830f9be380105f1ee.md
@@ -9,7 +9,7 @@ dashedName: task-94
In English, the verb `know` is conjugated to `knows` when the subject is singular and in third person.
-`Everyone` refers to a group but it is treated as a singular noun, that’s why in English the correct form is `everyone knows`.
+`Everyone` refers to a group but it is treated as a singular noun, that's why in English the correct form is `everyone knows`.
# --questions--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657dc568fe84e53acc962fc3.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657dc568fe84e53acc962fc3.md
index ae8e2fd60c..6a6c75cb0a 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657dc568fe84e53acc962fc3.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657dc568fe84e53acc962fc3.md
@@ -10,7 +10,7 @@ Tom: Good to know! Do they involve everyone on the team? -->
# --description--
-Listen carefully to Tom’s question about the team meetings.
+Listen carefully to Tom's question about the team meetings.
# --questions--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657dc9946a177a5938ad3854.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657dc9946a177a5938ad3854.md
index 709b0368c8..1a3323ef9c 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657dc9946a177a5938ad3854.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657dc9946a177a5938ad3854.md
@@ -13,7 +13,7 @@ dashedName: task-104
How long it takes to make a website depends on how big or small the job is. Choosing the coding language depends on the computer or system we use.
-Notice that after `depends` there’s always the preposition `on`.
+Notice that after `depends` there's always the preposition `on`.
# --instructions--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657dca763bc23c5fc3398d95.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657dca763bc23c5fc3398d95.md
index 39cc84d0ea..68e2ef1b0c 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657dca763bc23c5fc3398d95.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657dca763bc23c5fc3398d95.md
@@ -26,7 +26,7 @@ Definitely next Monday.
### --feedback--
-`Definitely` is too certain compared to `probably.`
+Sophie says `probably`, which does not imply anything definite.
---
@@ -34,7 +34,7 @@ Maybe in two weeks.
### --feedback--
-`Maybe in two weeks` suggests less certainty and a longer timeframe than indicated by `probably.`
+Sophie uses `probably`, which suggests a greater level of certainty than maybe.
---
@@ -46,7 +46,7 @@ On Friday.
### --feedback--
-`On Friday` is not mentioned and does not align with `probably next Monday.`
+Friday was not mentioned in the dialog. It has to do with another day of the week.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657dce8ff35869721311a5e3.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657dce8ff35869721311a5e3.md
index ea09c5aac0..f1224e3dde 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657dce8ff35869721311a5e3.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657dce8ff35869721311a5e3.md
@@ -21,7 +21,7 @@ Which sentence is correct for describing one place near you?
### --feedback--
-`There are` is used for plural nouns, and `bank` is singular. You’ll learn about `there are` in the next few lessons.
+`There are` is used for plural nouns, and `bank` is singular. You'll learn about `there are` in the next few lessons.
---
@@ -29,7 +29,7 @@ Which sentence is correct for describing one place near you?
### --feedback--
-This option is a question form, not a statement. You’ll learn about questions later.
+This option is a question form, not a statement. You'll learn about questions later.
---
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657dd047e755e37d58f5084f.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657dd047e755e37d58f5084f.md
index 11907b4c84..15c73ff336 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657dd047e755e37d58f5084f.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657dd047e755e37d58f5084f.md
@@ -31,7 +31,7 @@ Absence of parks.
### --feedback--
-`Absence` suggests that there are no parks.
+`A couple of` suggests that there are some parks.
---
@@ -43,7 +43,7 @@ Many parks.
### --feedback--
-`Many` indicates a larger quantity, which doesn't match the context.
+`A couple of` indicates a small quantity, which doesn't match this answer.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657ddaaf8d89b4a56e3fdf78.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657ddaaf8d89b4a56e3fdf78.md
index 9d43fff47c..11f7436b40 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657ddaaf8d89b4a56e3fdf78.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657ddaaf8d89b4a56e3fdf78.md
@@ -11,9 +11,9 @@ dashedName: task-123
Maria mentions that she doesn't know of any theater in the area. When you want to express that something does not exist or is not present somewhere, you use `there isn't` for singular nouns or `there aren't` for plural nouns.
-`There isn’t` is an abbreviation of `there is not`.
+`There isn't` is an abbreviation of `there is not`.
-`There aren’t` is an abbreviation of `there are not`.
+`There aren't` is an abbreviation of `there are not`.
# --instructions--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657ddd7d4fc512b03741d9a3.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657ddd7d4fc512b03741d9a3.md
index 76db0319c5..1f2b06ed59 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657ddd7d4fc512b03741d9a3.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-conversation-starters-in-the-break-room/657ddd7d4fc512b03741d9a3.md
@@ -21,11 +21,11 @@ There are closed malls.
### --feedback--
-They don’t discuss the opening hours of malls.
+They don't discuss the opening hours of malls.
---
-There aren’t any malls.
+There aren't any malls.
### --feedback--
@@ -33,7 +33,7 @@ Malls are easy to locate.
---
-Malls aren’t very common in this area.
+Malls aren't very common in this area.
### --feedback--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-greetings-in-your-first-day-at-the-office/656cd6a37495961c5f242c5d.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-greetings-in-your-first-day-at-the-office/656cd6a37495961c5f242c5d.md
index fe945fc7d8..d0923655f0 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-greetings-in-your-first-day-at-the-office/656cd6a37495961c5f242c5d.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-greetings-in-your-first-day-at-the-office/656cd6a37495961c5f242c5d.md
@@ -46,7 +46,7 @@ There are some questions you can start a friendly conversation with. Софі в
### --feedback--
-Софі не запитує про причини. Спробуйте ще раз.
+She doesn't ask for reasons. Спробуйте ще раз.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-ask-and-share-about-educational-and-professional-background/657b30e1b9f035e7e656fd01.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-ask-and-share-about-educational-and-professional-background/657b30e1b9f035e7e656fd01.md
index 2690f68ae7..ae81dda38d 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-ask-and-share-about-educational-and-professional-background/657b30e1b9f035e7e656fd01.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-ask-and-share-about-educational-and-professional-background/657b30e1b9f035e7e656fd01.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-91
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-ask-and-share-about-educational-and-professional-background/65f3a5111de04c216a38d998.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-ask-and-share-about-educational-and-professional-background/65f3a5111de04c216a38d998.md
index f8523c7800..faf27f8fbc 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-ask-and-share-about-educational-and-professional-background/65f3a5111de04c216a38d998.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-ask-and-share-about-educational-and-professional-background/65f3a5111de04c216a38d998.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-61
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-ask-and-share-about-educational-and-professional-background/65f3a5733a199c21ca589173.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-ask-and-share-about-educational-and-professional-background/65f3a5733a199c21ca589173.md
index b09c0a7281..7dcbceae4e 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-ask-and-share-about-educational-and-professional-background/65f3a5733a199c21ca589173.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-ask-and-share-about-educational-and-professional-background/65f3a5733a199c21ca589173.md
@@ -6,7 +6,7 @@ dashedName: task-62
---
+Brian: They weren't exactly big projects. Most of them were smaller scale. But it was a great learning experience. -->
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-ask-for-clarification-on-code-understanding/65f52f761f23715bce60f9ce.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-ask-for-clarification-on-code-understanding/65f52f761f23715bce60f9ce.md
index 1be4e2282b..dacf7632b8 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-ask-for-clarification-on-code-understanding/65f52f761f23715bce60f9ce.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-ask-for-clarification-on-code-understanding/65f52f761f23715bce60f9ce.md
@@ -15,7 +15,7 @@ dashedName: task-20
## --text--
-What part of Sarah’s answer suggests a course of action?
+What part of Sarah's answer suggests a course of action?
## --answers--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-clarify-information-in-different-interactions/66415d2fc70cf753ed0723a4.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-clarify-information-in-different-interactions/66415d2fc70cf753ed0723a4.md
index 57b9aca791..93211e77fd 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-clarify-information-in-different-interactions/66415d2fc70cf753ed0723a4.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-clarify-information-in-different-interactions/66415d2fc70cf753ed0723a4.md
@@ -11,7 +11,7 @@ dashedName: task-76
`That's strange` means you think something is unusual or unexpected. For example, if you see it snowing in the summer, you might say, `That's strange.` It means you did not expect that to happen.
-`I'm sure` means you are confident that something is true. For example, if you know your friend’s birthday is tomorrow, you can say, `I'm sure it's tomorrow.` It means you believe it without doubt.
+`I'm sure` means you are confident that something is true. For example, if you know your friend's birthday is tomorrow, you can say, `I'm sure it's tomorrow.` It means you believe it without doubt.
Listen and fill in the blanks.
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-clarify-information-in-different-interactions/664274a516894a70a9111cb6.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-clarify-information-in-different-interactions/664274a516894a70a9111cb6.md
index b853f26347..c387a71689 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-clarify-information-in-different-interactions/664274a516894a70a9111cb6.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-clarify-information-in-different-interactions/664274a516894a70a9111cb6.md
@@ -11,7 +11,7 @@ dashedName: task-78
`Now that I think about it` means you have remembered or realized something after thinking more. For example, if you forgot where you put your keys but then remember, you might say, `Now that I think about it, they are on the table.` It means you have thought again and found new information.
-`To confuse something with something else` means to mix up two things and think one is the other. For example, if you see someone’s twin and think it is your friend, you can say `Sorry. I confused your twin with you`. It means you mistake one thing for another.
+`To confuse something with something else` means to mix up two things and think one is the other. For example, if you see someone's twin and think it is your friend, you can say `Sorry. I confused your twin with you`. It means you mistake one thing for another.
# --questions--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-clarify-information-in-different-interactions/6642914bd5def3734c59b763.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-clarify-information-in-different-interactions/6642914bd5def3734c59b763.md
index 3a04d24636..a2976c13c2 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-clarify-information-in-different-interactions/6642914bd5def3734c59b763.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-clarify-information-in-different-interactions/6642914bd5def3734c59b763.md
@@ -11,7 +11,7 @@ dashedName: task-79
A `tray` is a flat, shallow container used to carry or hold things. For example, you use a `tray` to bring food or drinks from the kitchen to the table.
-`Enough` means having as much as you need. For example, if you have `enough water`, it means you have all the water you need to drink and you don’t need more. It can be used to talk about quantity, like having `enough food`, or to talk about quality, like when something is `good enough`.
+`Enough` means having as much as you need. For example, if you have `enough water`, it means you have all the water you need to drink and you don't need more. It can be used to talk about quantity, like having `enough food`, or to talk about quality, like when something is `good enough`.
Послухайте діалог та доповніть речення.
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/655b76340ecb8285060ab6d5.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/655b76340ecb8285060ab6d5.md
index 3f13a0b5ab..3262c8e2ef 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/655b76340ecb8285060ab6d5.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/655b76340ecb8285060ab6d5.md
@@ -23,7 +23,7 @@ Sophie helps her team and James checked cybersecurity
### --feedback--
-У цьому реченні неправильно використано простий теперішній час щодо Софі та простий минулий час щодо Джеймса. Ці часи не виражають тривалу дію їхньої поточної діяльності.
+У цьому реченні неправильно використано простий теперішній час щодо Софі та простий минулий час щодо Джеймса. They don't reflect the continuous, ongoing nature of their current activities.
---
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/655bdc7e9c4116509df13f34.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/655bdc7e9c4116509df13f34.md
index b016a9e143..5e20a5bbfc 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/655bdc7e9c4116509df13f34.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/655bdc7e9c4116509df13f34.md
@@ -9,13 +9,13 @@ dashedName: task-19
# --description--
-`Use` означає використовувати щось з певною метою.
+To `use` means to put something to a particular purpose.
`Tool` — це те, що допомагає виконувати роботу. Зазвичай інструментами на роботі є програмне забезпечення та все інше на комп’ютері. For example:
-`Using tools can make hard jobs easier`
+- `Using tools can make hard jobs easier`
-`She uses tools to organize her work`
+- `She uses tools to organize her work`
# --fillInTheBlank--
@@ -29,7 +29,7 @@ dashedName: task-19
### --feedback--
-Стосується використання чогось з певною метою. Використайте закінчення `-ing`.
+Refers to the act of utilizing something for a purpose. Use `-ing`
---
@@ -37,7 +37,7 @@ dashedName: task-19
### --feedback--
-Те, що допомагає виконувати роботу. Використайте форму множини.
+Something that helps you do a job. Use the plural form.
# --scene--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/655c9a89818e18606c18ca4b.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/655c9a89818e18606c18ca4b.md
index 5df17748b7..1fe06956ea 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/655c9a89818e18606c18ca4b.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/655c9a89818e18606c18ca4b.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-22
---
-
+
# --description--
@@ -15,7 +15,7 @@ dashedName: task-22
## --sentence--
-`Hi Maria! I'm BLANK a new software to BLANK problems. It’s a nice experience so far, but we're BLANK more tests to BLANK sure everything BLANK`
+`Hi Maria! I'm BLANK a new software to BLANK problems. It's a nice experience so far, but we're BLANK more tests to BLANK sure everything BLANK`
## --blanks--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/655c9bcb5bedb4620acb6f18.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/655c9bcb5bedb4620acb6f18.md
index c80bc35f9f..7fee6929ec 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/655c9bcb5bedb4620acb6f18.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/655c9bcb5bedb4620acb6f18.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-24
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/656a44b06bea9443b8ff45bd.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/656a44b06bea9443b8ff45bd.md
index ed1f8177d0..0858c40f94 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/656a44b06bea9443b8ff45bd.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/656a44b06bea9443b8ff45bd.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-34
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/656a456b46b4b04437f2d3e9.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/656a456b46b4b04437f2d3e9.md
index 052b67e6be..85eaf33c85 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/656a456b46b4b04437f2d3e9.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/656a456b46b4b04437f2d3e9.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-35
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/656a4ac4529e0f49ab900c3b.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/656a4ac4529e0f49ab900c3b.md
index bacfa88b73..8d51326af0 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/656a4ac4529e0f49ab900c3b.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/656a4ac4529e0f49ab900c3b.md
@@ -23,7 +23,7 @@ She is learning about project management
### --feedback--
-Sarah doesn’t mention project management.
+Sarah doesn't mention project management.
---
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/656a4d1943d8f24c030ded74.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/656a4d1943d8f24c030ded74.md
index 1000026d9d..fa31c3a78b 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/656a4d1943d8f24c030ded74.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-describe-your-current-project/656a4d1943d8f24c030ded74.md
@@ -13,7 +13,7 @@ dashedName: task-53
`I don't like carrots. My sister doesn't like them, either.`
-Тут`either` — означає чи співрозмовник та його сестра не люблять моркву.
+Here, `either` means both the speaker and their sister don't like carrots.
# --questions--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-popular-trends-in-technology/65fe10ef733aebd257f0677d.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-popular-trends-in-technology/65fe10ef733aebd257f0677d.md
index d42f143233..d8f69f155f 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-popular-trends-in-technology/65fe10ef733aebd257f0677d.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-popular-trends-in-technology/65fe10ef733aebd257f0677d.md
@@ -9,7 +9,7 @@ dashedName: task-2
# --description--
-`AI` stands for Artificial Intelligence. It’s an abbreviation of Artificial Intelligence.
+`AI` stands for Artificial Intelligence. It's an abbreviation of Artificial Intelligence.
# --questions--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-popular-trends-in-technology/65ff086669d84512c7d132f1.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-popular-trends-in-technology/65ff086669d84512c7d132f1.md
index 4ff82ad7f9..458f53df8c 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-popular-trends-in-technology/65ff086669d84512c7d132f1.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-popular-trends-in-technology/65ff086669d84512c7d132f1.md
@@ -9,7 +9,7 @@ dashedName: task-4
# --description--
-`like` is a preposition used to describe the similarity between two things, people, or concepts. It indicates that there are shared qualities or characteristics between the compared elements. It’s commonly used in comparisons to highlight similarities. Example: `Her eyes are blue like the sky.`
+`like` is a preposition used to describe the similarity between two things, people, or concepts. It indicates that there are shared qualities or characteristics between the compared elements. It's commonly used in comparisons to highlight similarities. Example: `Her eyes are blue like the sky.`
Fill in the blank with proper word.
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-popular-trends-in-technology/6617e75a204e044552675f58.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-popular-trends-in-technology/6617e75a204e044552675f58.md
index 941b92981c..c04949226c 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-popular-trends-in-technology/6617e75a204e044552675f58.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-popular-trends-in-technology/6617e75a204e044552675f58.md
@@ -9,7 +9,7 @@ dashedName: task-5
# --description--
-In this challenge, you’ll practice what you learned in previous challenges. Listen to the dialogue and choose the correct answer.
+In this challenge, you'll practice what you learned in previous challenges. Listen to the dialogue and choose the correct answer.
# --questions--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-popular-trends-in-technology/661ed01f09114567cc8fa939.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-popular-trends-in-technology/661ed01f09114567cc8fa939.md
index 683ce65442..5da21f8933 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-popular-trends-in-technology/661ed01f09114567cc8fa939.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-popular-trends-in-technology/661ed01f09114567cc8fa939.md
@@ -9,7 +9,7 @@ dashedName: task-88
# --description--
-You learned how to talk about an unspecified thing or information with a broad term that didn’t point to a specific item. Let’s review it in this challenge.
+You learned how to talk about an unspecified thing or information with a broad term that didn't point to a specific item. Let's review it in this challenge.
Listen and fill in the blank.
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-popular-trends-in-technology/661edda6df434c6f2161bea5.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-popular-trends-in-technology/661edda6df434c6f2161bea5.md
index 4ae3ee8f65..734db8f115 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-popular-trends-in-technology/661edda6df434c6f2161bea5.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-popular-trends-in-technology/661edda6df434c6f2161bea5.md
@@ -39,7 +39,7 @@ This answer limits `AR` to one aspect, which is not what `it is a mix` suggests.
### --feedback--
-`It is a mix` doesn’t mean `AR` is separate from reality.
+`It is a mix` doesn't mean `AR` is separate from reality.
---
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-popular-trends-in-technology/661ee1436ecb9271c66be82c.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-popular-trends-in-technology/661ee1436ecb9271c66be82c.md
index 1ba10ebe82..906795f8d4 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-popular-trends-in-technology/661ee1436ecb9271c66be82c.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-popular-trends-in-technology/661ee1436ecb9271c66be82c.md
@@ -9,7 +9,7 @@ dashedName: task-92
# --description--
-Let’s review what Sophie and Tom talk about.
+Let's review what Sophie and Tom talk about.
Listen and fill in the blanks to complete the dialogue.
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-popular-trends-in-technology/661eea69ca8a5177320d5e90.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-popular-trends-in-technology/661eea69ca8a5177320d5e90.md
index 6510d035ad..bc0f0e6d71 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-popular-trends-in-technology/661eea69ca8a5177320d5e90.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-popular-trends-in-technology/661eea69ca8a5177320d5e90.md
@@ -9,7 +9,7 @@ dashedName: task-97
# --description--
-Let’s review what Sophie and Tom talk about, to understand how AR works.
+Let's review what Sophie and Tom talk about, to understand how AR works.
# --fillInTheBlank--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65b22d1aeb5ecf1d590d30bf.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65b22d1aeb5ecf1d590d30bf.md
index 2d2a7363ff..b0ce443908 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65b22d1aeb5ecf1d590d30bf.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65b22d1aeb5ecf1d590d30bf.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-6
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65b22e5388370c209a6b0b73.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65b22e5388370c209a6b0b73.md
index 139ac35da9..f28dced324 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65b22e5388370c209a6b0b73.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65b22e5388370c209a6b0b73.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-7
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65b25b541262654062a21e74.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65b25b541262654062a21e74.md
index 0226baa52b..16e5be04c4 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65b25b541262654062a21e74.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65b25b541262654062a21e74.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-13
---
-
+
# --description--
@@ -17,7 +17,7 @@ The phrase `right away` means quickly or very soon. For instance, `If you find a
## --sentence--
-`You’ll BLANK her BLANK BLANK.`
+`You'll BLANK her BLANK BLANK.`
## --blanks--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65b25bcc98b00d41d06d2a2b.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65b25bcc98b00d41d06d2a2b.md
index 19470ec85a..e0ebbff85a 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65b25bcc98b00d41d06d2a2b.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65b25bcc98b00d41d06d2a2b.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-14
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65d86e08994c4a0436d92766.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65d86e08994c4a0436d92766.md
index 34102b08c2..e2dbf56525 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65d86e08994c4a0436d92766.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65d86e08994c4a0436d92766.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-71
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65d89562dff69551e7683df3.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65d89562dff69551e7683df3.md
index a6729560d0..6b8df040de 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65d89562dff69551e7683df3.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65d89562dff69551e7683df3.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-82
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65daa8143ae77767ad914ba4.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65daa8143ae77767ad914ba4.md
index 693c5e9d72..b420fd22f0 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65daa8143ae77767ad914ba4.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65daa8143ae77767ad914ba4.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-94
---
-
+
# --description--
@@ -17,7 +17,7 @@ For example, if you don't eat healthy food or exercise, you might be `neglecting
## --sentence--
-`I also don’t want to BLANK BLANK BLANK, so two months ago I started jogging regularly.`
+`I also don't want to BLANK BLANK BLANK, so two months ago I started jogging regularly.`
## --blanks--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65daa8cce1b9206995e4aec3.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65daa8cce1b9206995e4aec3.md
index ee3f2a8786..a54cbbf0ef 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65daa8cce1b9206995e4aec3.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65daa8cce1b9206995e4aec3.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-95
---
-
+
# --description--
@@ -17,7 +17,7 @@ For example, if you say `I moved here a year ago`, it means that one year has pa
## --sentence--
-`I also don’t want to neglect my health, so two months BLANK I started jogging regularly.`
+`I also don't want to neglect my health, so two months BLANK I started jogging regularly.`
## --blanks--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65daab9b713d3e6e6272c8bf.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65daab9b713d3e6e6272c8bf.md
index db8ad34e22..43cae0abe5 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65daab9b713d3e6e6272c8bf.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65daab9b713d3e6e6272c8bf.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-97
---
-
+
# --description--
@@ -21,7 +21,7 @@ Adverbs describe how actions are done. They are often formed by adding `-ly` to
## --sentence--
-`I also don’t want to neglect my health, so two months ago I started BLANK BLANK.`
+`I also don't want to neglect my health, so two months ago I started BLANK BLANK.`
## --blanks--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65dab1186529467ee5e463a7.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65dab1186529467ee5e463a7.md
index b0110df059..9caec3eca4 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65dab1186529467ee5e463a7.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65dab1186529467ee5e463a7.md
@@ -6,7 +6,7 @@ dashedName: task-99
---
+Sophie: Well, I have to make time for my family – that's really important to me. I also don't want to neglect my health, so two months ago I started jogging regularly. It helps me relax and stay fit. -->
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65dad153fd675cb51e8423b0.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65dad153fd675cb51e8423b0.md
index 634d120a7c..27d163814b 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65dad153fd675cb51e8423b0.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-roles-and-responsibilies/65dad153fd675cb51e8423b0.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-106
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-tech-trends-and-updates/6636f834a7b32443a43fa4e0.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-tech-trends-and-updates/6636f834a7b32443a43fa4e0.md
index 5fa4210df8..2783ff78b1 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-tech-trends-and-updates/6636f834a7b32443a43fa4e0.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-tech-trends-and-updates/6636f834a7b32443a43fa4e0.md
@@ -43,7 +43,7 @@ It disconnects applications from the internet, focusing on internal networks.
### --feedback--
-Serverless computing still uses the internet as part of cloud services; it doesn’t focus on internal networks.
+Serverless computing still uses the internet as part of cloud services; it doesn't focus on internal networks.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-tech-trends-and-updates/663855865f5d53510f9cd9a5.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-tech-trends-and-updates/663855865f5d53510f9cd9a5.md
index 97750727a7..db2bd25203 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-tech-trends-and-updates/663855865f5d53510f9cd9a5.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-tech-trends-and-updates/663855865f5d53510f9cd9a5.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-38
---
-
+
# --description--
@@ -17,7 +17,7 @@ For example, `He is hearing different opinions on the topic.` It shows he is cur
## --sentence--
-`Sarah, I’m BLANK a lot BLANK AI in programming these days, but I don't know how to use it. Any ideas?`
+`Sarah, I'm BLANK a lot BLANK AI in programming these days, but I don't know how to use it. Any ideas?`
## --blanks--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-tech-trends-and-updates/6638994f7dbcb3548e458202.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-tech-trends-and-updates/6638994f7dbcb3548e458202.md
index df877af430..67d0b616d6 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-tech-trends-and-updates/6638994f7dbcb3548e458202.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-tech-trends-and-updates/6638994f7dbcb3548e458202.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-41
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-tech-trends-and-updates/66389a37bc8a4b5539eab451.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-tech-trends-and-updates/66389a37bc8a4b5539eab451.md
index 518f522e95..8f3b4221ab 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-tech-trends-and-updates/66389a37bc8a4b5539eab451.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-tech-trends-and-updates/66389a37bc8a4b5539eab451.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-42
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-tech-trends-and-updates/66389e09cec2fa569567b15a.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-tech-trends-and-updates/66389e09cec2fa569567b15a.md
index 57fa71f0e8..3a3a533476 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-tech-trends-and-updates/66389e09cec2fa569567b15a.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-tech-trends-and-updates/66389e09cec2fa569567b15a.md
@@ -23,7 +23,7 @@ Using a program that automatically improves code efficiency
### --feedback--
-This is an example of AI, as it involves using technology to improve code, aligning with Sarah’s description.
+This is an example of AI, as it involves using technology to improve code, aligning with Sarah's description.
---
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6556bc95e6ce5d850d37dd07.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6556bc95e6ce5d850d37dd07.md
index b4291308ca..14bce3107c 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6556bc95e6ce5d850d37dd07.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6556bc95e6ce5d850d37dd07.md
@@ -17,41 +17,42 @@ dashedName: task-3
Ось ще декілька прикладів:
-`She wakes up early every day`: `early` позначає час, коли вона прокидається. `He has a quick shower in the morning`: `quick` вказує на коротку тривалість прийняття душу.
+* `She wakes up early every day` - `Early` describes the time of her waking up.
+* `He has a quick shower in the morning` - `Quick` describes the short duration of the shower.
# --questions--
## --text--
-На що вказує прикметник `energetic` щодо когось?
+What does the adjective `energetic` imply about someone?
## --answers--
-Ця людина нездужає.
+That the person is feeling unwell.
### --feedback--
-`Energetic` зазвичай вживається для вираження позитивного відношення до людини, а не того, що вона погано себе почуває.
+`Energetic` is generally used to express a positive feeling about a person, not that they are feeling unwell..
---
-Ця людина виглядає сповненою енергії.
+That the person seems like they have a lot of energy.
---
-Ця людина відчуває дискомфорт.
+That the person is uncomfortable.
### --feedback--
-Як правило, `energetic` вживається для підкреслення того, наскільки енергійною виглядає людина, а не того, наскільки комфортно вона себе почуває.
+`Energetic` is generally used to express how dynamic the person looks, not how comfortable they are.
---
-Ця людина запізнюється.
+That the person is late.
### --feedback--
-Прикметник `energetic` не стосується часу чи пунктуальності.
+The adjective `energetic` does not relate to time or punctuality.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6556be93f9fcb88ac9e88b0d.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6556be93f9fcb88ac9e88b0d.md
index 485e77251c..84eefaa9ee 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6556be93f9fcb88ac9e88b0d.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6556be93f9fcb88ac9e88b0d.md
@@ -13,9 +13,12 @@ dashedName: task-4
`A ton of energy` — це ідіоматичний вираз, що означає «мати багато енергії», подібно до виразу `loads of energy`.
-Ще один вираз `I slept like a rock` означає «спати дуже глибоким сном». Ось ще кілька прикладів ідіоматичних виразів:
+Ще один вираз `I slept like a rock` означає «спати дуже глибоким сном». Here are some more examples of idiomatic expressions:
-`She's feeling blue today.` (сумувати) `This math problem is a piece of cake.` (досить легко) `He's in hot water now.` (в халепі) `They see eye to eye.` (погоджуватися одне з одним)
+* `She's feeling blue today.` (feeling sad)
+* `This math problem is a piece of cake.` (very easy)
+* `He's in hot water now.` (in trouble)
+* `They see eye to eye.` (agree with each other)
# --fillInTheBlank--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655792631f21afaa40c611e1.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655792631f21afaa40c611e1.md
index 1c22ffe53c..36b6163359 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655792631f21afaa40c611e1.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655792631f21afaa40c611e1.md
@@ -13,9 +13,8 @@ dashedName: task-13
`Before` вживається для того, щоб підкреслити те, що відбувається раніше, аніж інша подія, тоді як `after` — те, що відбувається пізніше. Наприклад:
-` I brush my teeth before I have breakfast` (Спершу потрібно почистити зуби)
-
-`I go to work after I have breakfast` (Опісля йдемо на роботу)
+* `I brush my teeth before I have breakfast` (Brushing teeth happens first)
+* `I go to work after I have breakfast` (Going to work happens later)
# --fillInTheBlank--
@@ -29,7 +28,7 @@ dashedName: task-13
### --feedback--
-Це слово використовується для позначення наступного кроку в послідовності подій. Відбувається `that`.
+This word is used to talk about the next step in a sequence of events. It comes `that`.
# --scene--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557985a95ab6db1c4a31b6c.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557985a95ab6db1c4a31b6c.md
index cec3c16cf3..e4f581e824 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557985a95ab6db1c4a31b6c.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557985a95ab6db1c4a31b6c.md
@@ -9,15 +9,18 @@ dashedName: task-14
Дієслово `take` використовується в багатьох поширених англійських виразах. При використанні `take` з різними іменниками він може мати відмінні значення. Наприклад:
-`Take a shower` означає приймати душ. `Take a walk` означає піти на прогулянку. `Take a nap` означає трохи поспати. `Take a chance` означає спробувати щось, що може бути ризикованим.
+* `Take a shower` means to shower.
+* `Take a walk` means to go for a walk.
+* `Take a nap` means to sleep for a little while.
+* `Take a chance` means to try something that might be risky.
-Ці вирази нагадують незмінні рецепти в англійській мові: коли слова разом означають щось конкретне.
+These phrases are like fixed recipes in English; the words go together to mean something specific.
# --questions--
## --text--
-Який вираз означає швидко помитися у воді?
+Which phrase means to quickly clean yourself under water?
## --answers--
@@ -29,7 +32,7 @@ dashedName: task-14
### --feedback--
-`Take a walk` означає прогулятися на свіжому повітрі. Суть полягає не в прибиранні.
+`Take a walk` means to go for a walk outside. It is not about cleaning.
---
@@ -37,7 +40,7 @@ dashedName: task-14
### --feedback--
-`Take a chance` означає спробувати щось, що може бути ризикованим. Суть полягає не в прибиранні.
+`Take a chance` means to try something that might be risky. It's not about cleaning.
---
@@ -45,7 +48,7 @@ dashedName: task-14
### --feedback--
-`Take a nap` означає трохи поспати. Це не означає помитися.
+`Take a nap` means to sleep for a short time. It does not mean to clean yourself.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557995f0d97e1b2837a3081.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557995f0d97e1b2837a3081.md
index 53ef95e918..52557ee4e6 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557995f0d97e1b2837a3081.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557995f0d97e1b2837a3081.md
@@ -9,13 +9,15 @@ dashedName: task-15
Пам'ятайте, що прикметники - це слова, які описують або надають додаткову інформацію про іменники. Вони можуть описати вам, як щось виглядає, відчувається чи діє. Наприклад:
-`Quick` описує щось, зроблене за короткий час. `Relaxed` описує щось або когось спокійним та не суворим. `Alert` описує максимальну обізнаність та уважність.
+* `Quick` describes something done in a short time.
+* `Relaxed` describes something or someone calm and not strict.
+* `Alert` describes being fully aware and paying attention.
# --questions--
## --text--
-Яке слово ви б використали, щоб описати людину, яка повністю сконцентрована й готова до дій?
+Which word would you use to describe someone who is paying full attention and is ready to act?
## --answers--
@@ -23,7 +25,7 @@ dashedName: task-15
### --feedback--
-`Relaxed` використовується для опису когось спокійного або ситуації, яка не є напруженою.
+`Relaxed` is used to describe someone calm or a situation that is not strict.
---
@@ -31,7 +33,7 @@ dashedName: task-15
### --feedback--
-`Quick` описує щось зроблене за короткий час, а не те, наскільки швидко хтось звертає увагу.
+`Quick` describes something done in a short time, not how someone is paying attention.
---
@@ -39,7 +41,7 @@ dashedName: task-15
### --feedback--
-`Tall` описує зріст когось або чогось, а не те, як вони звертають увагу.
+`Tall` is used to describe the height of someone or something, not how they are paying attention.
---
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/65579a0e1613d5b31a034ee5.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/65579a0e1613d5b31a034ee5.md
index f3c36ac443..46ad14c75c 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/65579a0e1613d5b31a034ee5.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/65579a0e1613d5b31a034ee5.md
@@ -9,45 +9,47 @@ dashedName: task-16
Дієслово `get` широко вживане в англійській мові і має багато значень. Це може означати отримати, ставати або досягати певного стану. Наприклад:
-`Get dressed` означає одягатися. `Get ready` означає готуватися до чогось. `Get tired` означає втомлюватися.
+* `Get dressed` means to put on clothes.
+* `Get ready` means to prepare for something.
+* `Get tired` means to start feeling tired.
-Розуміння того, в яких випадках використовувати `get`, допоможе вам виражати різні дії та стани англійською мовою.
+Understanding how `get` is used will help you express different actions and states in English.
-Примітка: Нехай вас не лякає багатозначність `get`. Вивчайте по одному значенню за раз і намагайтеся отримувати задоволення, розкриваючи його кілька значень.
+Note: Don't let the many meanings of `get` scare you. Learn one usage at a time and try to have fun discovering its several meanings.
# --questions--
## --text--
-Що означає `get dressed`?
+What does `get dressed` mean?
## --answers--
-Одягнутися
+Put on clothes
---
-Купувати новий одяг
+Buy new clothes
### --feedback--
-`Buy new clothes` означає купити одяг, а не вдягати його.
+`Buy new clothes` means to purchase clothes, not to put them on.
---
-Випрати одяг
+Wash clothes
### --feedback--
-`Wash clothes` означає випрати одяг, а не вдягати його.
+`Wash clothes` means to clean clothes, not to put them on.
---
-Складати одяг
+Fold clothes
### --feedback--
-`Fold clothes` означає акуратно складати одяг, а не вдягати його.
+`Fold clothes` means to arrange clothes neatly, not to put them on.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557aee56ed7dcb5506a66d6.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557aee56ed7dcb5506a66d6.md
index 42d33d816f..322ad81068 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557aee56ed7dcb5506a66d6.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557aee56ed7dcb5506a66d6.md
@@ -9,43 +9,44 @@ dashedName: task-19
Словосполучення `dress code` - це комплекс правил щодо того, що слід одягати в певному місці чи на певному заході. Кожен заклад має свій дрес-код. Наприклад:
-Словосполучення `relaxed dress code` — невимушений й зручний дрес-код, який ви можете носити щоденно. Словосполучення `formal dress code` навпаки передбачає більш офіційний та елегантний одяг.
+* A `relaxed dress code` means you can wear casual, comfortable clothes.
+* A `formal dress code` requires more official and elegant clothes.
-Примітка: Пам'ятайте, що дрес-код може відрізнятися в залежності від культури і конкретного місця.
+Note: Remember, dress codes can vary depending on the culture and the specific place.
# --questions--
## --text--
-Який `relaxed dress code` зазвичай допускається на роботу?
+What does a `relaxed dress code` at work usually allow you to wear?
## --answers--
-Костюми й краватки
+Suits and ties
### --feedback--
-Як правило, костюми та краватки є частиною формального дрес-коду, а не повсякденного.
+Suits and ties are usually part of a formal dress code, not a relaxed one.
---
-Повсякденний одяг, як-от джинси та футболки
+Casual clothes like jeans and T-shirts
---
-Уніформи
+Uniforms
### --feedback--
-Уніформа - це особливий тип одягу, необхідний на деяких робочих місцях, який зазвичай не асоціюється з повсякденним дрес-кодом.
+Uniforms are specific types of clothes required by some workplaces, not typically associated with a relaxed dress code.
---
-Вечірні сукні
+Evening gowns
### --feedback--
-Вечірні сукні досить урочисті. Їх не заведено одягати на робочі місця з неформальним дрес-кодом.
+Evening gowns are very formal and are not usually worn in workplaces with a relaxed dress code.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557d6a229e541bfde2c560d.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557d6a229e541bfde2c560d.md
index 41f7fd27df..33e01a1697 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557d6a229e541bfde2c560d.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557d6a229e541bfde2c560d.md
@@ -13,7 +13,8 @@ dashedName: task-26
`Late` означає зробити щось після запланованого або звичного часу, наприклад, запізнитися на зустріч. Ось декілька прикладів:
-`She likes to start her day early with a jog.` `He often works late at the office.`
+* `She likes to start her day early with a jog.`
+* `He often works late at the office.`
# --questions--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557d782bc7613c06aa7dafd.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557d782bc7613c06aa7dafd.md
index 23170ee47a..4923c24849 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557d782bc7613c06aa7dafd.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557d782bc7613c06aa7dafd.md
@@ -11,7 +11,8 @@ dashedName: task-27
The word `never` is an adverb used to mean `not at any time` or `not ever`. It's often used to talk about things that someone doesn't do or hasn't done. For example:
-`I have never been to Australia.` (this means the person has not visited Australia at any time) `She never eats fast food.` (this means she does not eat fast food at any time)
+* `I have never been to Australia.` (this means the person has not visited Australia at any time)
+* `She never eats fast food.` (this means she does not eat fast food at any time)
The word `thought` is the past tense of `think`. `Thought of that` means to have considered or come up with an idea in the past. Наприклад:
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557db51366bf6c15a966fb0.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557db51366bf6c15a966fb0.md
index ab690e7746..5e9daa1da7 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557db51366bf6c15a966fb0.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557db51366bf6c15a966fb0.md
@@ -11,18 +11,16 @@ dashedName: task-28
Коли дієслово стоїть після прийменника, зазвичай воно набуває форми герундія із закінченням `-ing`. Герундій - це дієслова, що виражають дію чи процес у вигляді іменника. Це правило є поширеним у більшості англійських виразів. Наприклад:
-`After eating dinner, we watched a movie.` (`eating` стоїть після прийменника `after`)
-
-`She is interested in learning Spanish.` (`learning` стоїть після прийменника `in`)
-
-`Before going to bed, I like to read.` (`going` стоїть після прийменника `before`)
+* `After eating dinner, we watched a movie.` (`eating` follows the preposition `after`)
+* `She is interested in learning Spanish.` (`learning` follows the preposition `in`)
+* `Before going to bed, I like to read.` (`going` follows the preposition `before`)
# --questions--
## --text--
-Яке дієслово використовує Сара після прийменника `before`?
+What is the verb Sarah uses after the preposition `before`?
## --answers--
@@ -30,7 +28,7 @@ dashedName: task-28
### --feedback--
-`Morning` - це іменник і не вживається після `before` в значенні дії, пов'язаної з від'їздом.
+`Morning` is a noun and doesn't fit after `before` in the context of an action related to leaving.
---
@@ -38,7 +36,7 @@ dashedName: task-28
### --feedback--
-`Leave` - це початкова форма дієслова, але після прийменника до дієслова додається закінчення `-ing`.
+`Leave` is the base form of the verb, but after a preposition, the verb should be in the `-ing` form.
---
@@ -50,7 +48,7 @@ dashedName: task-28
### --feedback--
-`Left` - це минулий час від дієслова `leave`, що не вживається після прийменника для опису дії, що триває.
+`Left` is the past tense of `leave` and isn't used after a preposition to describe an ongoing action.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557dc1aa6be93c1eb4e9efb.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557dc1aa6be93c1eb4e9efb.md
index ded17bef3d..17db85fb9d 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557dc1aa6be93c1eb4e9efb.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557dc1aa6be93c1eb4e9efb.md
@@ -11,43 +11,42 @@ dashedName: task-29
Слово `if` часто використовується в умовних реченнях для опису можливої ситуації та її наслідків. Наприклад:
-`If it rains, I will bring an umbrella.` (Рішення взяти з собою парасольку залежить від ймовірності дощу.)
-
-`If you need help, just ask.` (Пропозиція допомоги можлива лише за умови, що її потребує інша людина.)
+* `If it rains, I will bring an umbrella.` (The action of bringing an umbrella depends on the possibility of rain.)
+* `If you need help, just ask.` (The offer to help is conditional on the other person needing it.)
# --questions--
## --text--
-Що має на увазі Сара, використовуючи `if` у своєму реченні про перевірку електронних листів та повідомлень?
+What does Sarah imply by using `if` in her statement about checking emails and messages?
## --answers--
-Вона завжди отримує невідкладні повідомлення від своєї команди
+She always finds urgent updates from her team
### --feedback--
-`If` вказує на те, що ви ймовірно отримаєте невідкладні повідомлення.
+`If` doesn't suggest certainty of finding urgent updates.
---
-Інколи бувають невідкладні повідомлення, інколи - ні
+Sometimes there are urgent updates, sometimes not
---
-Вона ніколи не перевіряє свою електронну пошту та повідомлення
+She never checks her emails and messages
### --feedback--
-Сара стверджує, що вона перевіряє свою електронну пошту та повідомлення.
+Sarah actually states that she does check her emails and messages.
---
-Перевірка електронної пошти не входить у її рутину
+Checking emails is not part of her routine
### --feedback--
-Сара зазначає, що перевірка електронної пошти та повідомлень є частиною її повсякденного життя.
+Sarah mentions that checking emails and messages is part of her routine.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557dea8c258c1c2a767deb7.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557dea8c258c1c2a767deb7.md
index c372d30302..5f65bcc743 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557dea8c258c1c2a767deb7.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557dea8c258c1c2a767deb7.md
@@ -13,9 +13,8 @@ The word `even` is used to add emphasis to a statement, often highlighting somet
When combined with `before` in the phrase `even before`, it emphasizes that an action or event occurs earlier than usual or expected, adding a sense of surprise or admiration. Наприклад:
-`Even before the sun rises, she starts her workout.` (emphasizes that her workout begins unusually early)
-
-`He finished the project even before the deadline.` (implies that finishing before the deadline is surprisingly early)
+* `Even before the sun rises, she starts her workout.` (emphasizes that her workout begins unusually early)
+* `He finished the project even before the deadline.` (implies that finishing before the deadline is surprisingly early)
In conversation, using `even` can express that something is more than what might be considered normal or usual. It makes the statement stronger.
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557e0adbee371c3ac455a01.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557e0adbee371c3ac455a01.md
index 9fe748d15b..3d5bd82970 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557e0adbee371c3ac455a01.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557e0adbee371c3ac455a01.md
@@ -11,7 +11,8 @@ dashedName: task-32
You probably remember that `I'll` is the contracted form of `I will`, a modal verb used to express future intentions, decisions, or plans made at the moment of speaking. Наприклад:
-`I'll call you tomorrow.` (future intention to call) `I'll take the bus to work.` (decision made about taking the bus)
+* `I'll call you tomorrow.` (future intention to call)
+* `I'll take the bus to work.` (decision made about taking the bus)
# --questions--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557e5c6a854bfcad48808c4.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557e5c6a854bfcad48808c4.md
index 03d5bac431..c02d2bc026 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557e5c6a854bfcad48808c4.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/6557e5c6a854bfcad48808c4.md
@@ -15,7 +15,7 @@ This challenge is designed to summarize and reinforce the understanding of James
## --sentence--
-`Sarah has a consistent morning routine. She BLANK up around 7 AM and starts her day by BLANK a bit. After making a cup of BLANK, she takes a BLANK shower and goes to the kitchen to BLANK a balanced breakfast. This helps her stay BLANK during the morning. She checks her BLANK and messages before BLANK to work. She likes to stay BLANK about the day’s tasks. James thinks her productivity BLANK coming to work is impressive and says he BLANK try some of her habits to become more BLANK in the morning as well.`
+`Sarah has a consistent morning routine. She BLANK up around 7 AM and starts her day by BLANK a bit. After making a cup of BLANK, she takes a BLANK shower and goes to the kitchen to BLANK a balanced breakfast. This helps her stay BLANK during the morning. She checks her BLANK and messages before BLANK to work. She likes to stay BLANK about the day's tasks. James thinks her productivity BLANK coming to work is impressive and says he BLANK try some of her habits to become more BLANK in the morning as well.`
## --blanks--
@@ -87,7 +87,7 @@ Going away from a place, in this case, her home. Try finishing the word with `in
### --feedback--
-Having knowledge or being aware of the day's tasks after acessing her email.
+Having knowledge or being aware of the day's tasks after accessing her email.
---
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a235215bab7fa2a2e4bb7.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a235215bab7fa2a2e4bb7.md
index 405d488c65..6ea8867829 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a235215bab7fa2a2e4bb7.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a235215bab7fa2a2e4bb7.md
@@ -11,7 +11,8 @@ The `y` ending can also turn nouns into adjectives that describe a characteristi
`Healthy` comes from the noun `health` and means having or showing good health. Like `sleepy`, the `y` changes the noun into an adjective. Other examples:
-`Wealthy` (having a lot of wealth), `Cloudy` (full of or covered with clouds)
+* `Wealthy` (having a lot of wealth)
+* `Cloudy` (full of or covered with clouds)
# --questions--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a33bb8f2009ff7a7abfaa.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a33bb8f2009ff7a7abfaa.md
index d6062a3db3..a5a8d89fbb 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a33bb8f2009ff7a7abfaa.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a33bb8f2009ff7a7abfaa.md
@@ -15,7 +15,9 @@ There's a difference between `may be` and `maybe`. Let's take a closer look.
`Maybe` is an adverb indicating uncertainty or possibility. Наприклад:
-`It may be raining outside.` (suggests a possibility of rain) `Maybe I will go out later.` (expresses uncertainty about going out) `May I ask a question?` (Asks for the permission to speak)
+* `It may be raining outside.` (suggests a possibility of rain)
+* `Maybe I will go out later.` (expresses uncertainty about going out)
+* `May I ask a question?` (Asks for the permission to speak)
# --fillInTheBlank--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a367638e3f401eb0235ea.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a367638e3f401eb0235ea.md
index 0726c4c2de..736944e2c0 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a367638e3f401eb0235ea.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a367638e3f401eb0235ea.md
@@ -11,7 +11,7 @@ dashedName: task-45
`I feel groggy if I don't get enough sleep` (describes feeling tired due to lack of sleep)
-`Sluggish` is an adjective that describes a feeling of low energy, slow movement, or a lack of alertness. It's often used when someone feels tired, lethargic, or not able to think or move quickly. This term can apply to both physical and mental states. Ось декілька прикладів:
+`Sluggish` is an adjective that describes a feeling of low energy, slow movement, or a lack of alertness. It's often used when someone feels tired, lethargic, or not able to think or move quickly. This term can apply to both physical and mental states. Here is an example:
`The computer was running sluggishly, taking a long time to respond` (describes slow performance, used metaphorically for an inanimate object)
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a3789069fc902eb2aaa4b.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a3789069fc902eb2aaa4b.md
index 5bb008add9..c30052edd3 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a3789069fc902eb2aaa4b.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a3789069fc902eb2aaa4b.md
@@ -11,9 +11,8 @@ dashedName: task-46
The verb `to ring` refers to the action of making a sound, particularly a clear resonant sound. It's commonly used to describe the sound made by bells, telephones, or alarms. Наприклад:
-`The phone will ring at 9 AM to remind me of the meeting.` (indicates the phone making a sound)
-
-`I wake up when my alarm clock rings.` (describes the alarm making a sound to wake someone up)
+* `The phone will ring at 9 AM to remind me of the meeting.` (indicates the phone making a sound)
+* `I wake up when my alarm clock rings.` (describes the alarm making a sound to wake someone up)
# --fillInTheBlank--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a39242197c9040ddedef2.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a39242197c9040ddedef2.md
index b8e5cf4acf..b7cc61ef7e 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a39242197c9040ddedef2.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a39242197c9040ddedef2.md
@@ -11,9 +11,8 @@ dashedName: task-47
The imperative form is used to give orders, instructions, or advice. It often starts with a verb in the base form for positive commands, or with `don't`/`do not` for negative commands. Understanding this form is important for following or giving instructions. Наприклад:
-`Drink plenty of water` (positive command)
-
-`Don't stay up too late` (negative command)
+* `Drink plenty of water` (positive command)
+* `Don't stay up too late` (negative command)
# --fillInTheBlank--
@@ -27,7 +26,7 @@ The imperative form is used to give orders, instructions, or advice. It often st
### --feedback--
-Base form of the verb used for giving a positive command. Напишіть це слово з великої літери.
+Base form of the verb used for giving a positive command. This word is capitalized.
---
@@ -35,7 +34,7 @@ Base form of the verb used for giving a positive command. Напишіть це
### --feedback--
-Another base form used for giving a positive command. Не пишіть це слово з великої літери.
+Another base form used for giving a positive command. This word is not capitalized.
# --scene--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a3cc030fb970687d6444d.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a3cc030fb970687d6444d.md
index 77aaf69217..61625f3ede 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a3cc030fb970687d6444d.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a3cc030fb970687d6444d.md
@@ -9,15 +9,14 @@ dashedName: task-50
The word `later` is the comparative form of `late`, used to indicate a time or event that is after the expected, usual, or planned time. Comparatives are used to compare two things. Наприклад:
-`We will leave later than planned.` (means leaving after the planned time)
-
-`She arrived later than me.` (indicates she arrived after the speaker)
+* `We will leave later than planned.` (means leaving after the planned time)
+* `She arrived later than me.` (indicates she arrived after the speaker)
# --questions--
## --text--
-Що означає `compensate later`?
+What does `compensate later` imply?
## --answers--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a4a5af997350c187bd779.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a4a5af997350c187bd779.md
index ed8aef9bdd..aebf2b16a8 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a4a5af997350c187bd779.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a4a5af997350c187bd779.md
@@ -11,9 +11,8 @@ dashedName: task-52
`Who` can be used as a relative pronoun to introduce a clause that gives more information about a person or people. It links a description or action specifically to a person. Наприклад:
-`She is someone who always knows what to do.` (links the knowing what to do to the person)
-
-`He's the data analyst who helped me a lot.` (describes the data analyst with the action of helping)
+* `She is someone who always knows what to do.` (links the knowing what to do to the person)
+* `He's the data analyst who helped me a lot.` (describes the data analyst with the action of helping)
# --fillInTheBlank--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a4fc35818d90f73f63ba0.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a4fc35818d90f73f63ba0.md
index f840cac817..7072909e61 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a4fc35818d90f73f63ba0.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a4fc35818d90f73f63ba0.md
@@ -11,9 +11,8 @@ dashedName: task-54
The verb `to rush` means to do something or move quickly or in a hurry, often due to time pressure. It's used to describe actions done with urgency. Наприклад:
-`I had to rush to catch the train.` (means moving quickly to not miss the train)
-
-`Don't rush your decision.` (suggests taking time to decide)
+* `I had to rush to catch the train.` (means moving quickly to not miss the train)
+* `Don't rush your decision.` (suggests taking time to decide)
# --fillInTheBlank--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a51cff12fb7117aa611f9.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a51cff12fb7117aa611f9.md
index a3e5f328c3..a354ef2aa4 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a51cff12fb7117aa611f9.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a51cff12fb7117aa611f9.md
@@ -11,9 +11,8 @@ dashedName: task-56
`Breathing exercises` are practices where you consciously control your breathing pattern. They are often used for relaxation, stress management, and to `clear your mind` – which means to free your mind from stress or worry. Наприклад:
-`Deep breathing helps to calm your nerves.` (uses controlled breathing for relaxation)
-
-`Clear your mind before the test to focus better.` (freeing the mind from distractions)
+* `Deep breathing helps to calm your nerves.` (uses controlled breathing for relaxation)
+* `Clear your mind before the test to focus better.` (freeing the mind from distractions)
# --fillInTheBlank--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a54506b259313b2d59577.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a54506b259313b2d59577.md
index 68912a95b0..99bc0a1af1 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a54506b259313b2d59577.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a54506b259313b2d59577.md
@@ -17,7 +17,7 @@ Conditional sentences often use `if` to describe a situation (cause) that will l
## --text--
-What is the cause and consequence of the expert’s advice?
+What is the cause and consequence of the expert's advice?
## --answers--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a5bfadf47e1199f9b65eb.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a5bfadf47e1199f9b65eb.md
index b1d65fdde6..4701e829dd 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a5bfadf47e1199f9b65eb.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a5bfadf47e1199f9b65eb.md
@@ -11,11 +11,13 @@ dashedName: task-62
Past tense verbs are used to talk about actions that happened in the past. Some verbs change their form in the past tense, like `say` to `said`. Наприклад:
-`Yesterday, she said she would join us` (Past tense of `say`) `He said the meeting was at noon` (Describes a past statement about the meeting time)
+* `Yesterday, she said she would join us` (Past tense of `say`)
+* `He said the meeting was at noon` (Describes a past statement about the meeting time)
-Another example of irregular verb is `tell`, which becomes `told` in the past tense. Наприклад:
+Another example of an irregular verb is `tell`, which becomes `told` in the past tense. Наприклад:
-`He told me about the plan last week` (Past tense of `tell`) `Last night, they told stories about our last project` (Using `told` to describe a past action)
+* `He told me about the plan last week` (Past tense of `tell`)
+* `Last night, they told stories about our last project` (Using `told` to describe a past action)
Don't worry if irregular verbs seem tricky; with practice, you'll get the hang of them!
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a5e76ca6f8d1b1a88e0f1.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a5e76ca6f8d1b1a88e0f1.md
index 0e1bc16b19..e384f57140 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a5e76ca6f8d1b1a88e0f1.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a5e76ca6f8d1b1a88e0f1.md
@@ -11,15 +11,13 @@ dashedName: task-63
Regular verbs usually add `-ed` to form the past tense. This can also result in some adjectives as in the dialogue.
-`Complicated` is the past tense form of the regular verb `complicate`, as well as the adjective that means something is not simple or easy to do. One example of it as a verb can be: `The problems on the road complicated our trip.`
-
-`I walked to the store` (Past tense of `walk`)
-
-`She cleaned her room yesterday` (Past tense of `clean`)
+* `Complicated` is the past tense form of the regular verb `complicate`, as well as the adjective that means something is not simple or easy to do. One example of it as a verb can be: `The problems on the road complicated our trip.`
+* `I walked to the store` (Past tense of `walk`)
+* `She cleaned her room yesterday` (Past tense of `clean`)
Extra note to help with the audio:
-`Running around` means moving about in a hurried or energetic way, often chaotically. Наприклад:
+`Running around` means moving about in a hurried or energetic way, often chaotically. For example:
`The kids are running around the playground`
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a78fdfac0e22b0c400e72.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a78fdfac0e22b0c400e72.md
index 37ba1b2a97..1e859b80d6 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a78fdfac0e22b0c400e72.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a78fdfac0e22b0c400e72.md
@@ -9,7 +9,7 @@ dashedName: task-64
# --description--
-Послухайте аудіо та доповніть речення нижче.
+Listen to the audio and complete the sentence below.
# --fillInTheBlank--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a79e595bd202b4cd5e2d2.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a79e595bd202b4cd5e2d2.md
index 57a8bbf905..eeccb6c635 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a79e595bd202b4cd5e2d2.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a79e595bd202b4cd5e2d2.md
@@ -11,7 +11,8 @@ dashedName: task-65
The modal verb `could` is often used to politely ask for help or suggestions. Наприклад:
-`Could you show me how to do this?` (asking for help in a polite way) `What could I do to improve my skills?` (asking for suggestions)
+* `Could you show me how to do this?` (asking for help in a polite way)
+* `What could I do to improve my skills?` (asking for suggestions)
Understanding how to use `could` is important to create polite requests or questions.
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a7c5211e5252cf8a4ed01.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a7c5211e5252cf8a4ed01.md
index ab05effbc1..cdca2e286f 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a7c5211e5252cf8a4ed01.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a7c5211e5252cf8a4ed01.md
@@ -11,15 +11,13 @@ dashedName: task-67
The modal verb `can` is used to express ability, possibility, or to ask permission. It's a versatile verb that's commonly used in everyday conversation. Наприклад:
-`I can speak three languages` (ability)
+* `I can speak three languages` (ability)
+* `Can I borrow your pen?` (asking permission)
-`Can I borrow your pen?` (asking permission)
+The word `tough` means difficult or challenging. It's often used to describe situations that require a lot of effort or endurance. For example:
-The word `tough` means difficult or challenging. It's often used to describe situations that require a lot of effort or endurance. Наприклад:
-
-`The API test was really tough` (indicates the test was challenging)
-
-`They'are going through a tough time right now` (implies a period of difficulty)
+* `The API test was really tough` (indicates the test was challenging)
+* `They're going through a tough time right now` (implies a period of difficulty)
# --fillInTheBlank--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a7d752ffc542e5874af0b.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a7d752ffc542e5874af0b.md
index 59d4465afa..4d1275e3d5 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a7d752ffc542e5874af0b.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a7d752ffc542e5874af0b.md
@@ -15,9 +15,10 @@ Understanding the difference between `can` and `could` is crucial in English.
`Could` is often used for polite requests, suggestions, or to talk about ability in the past. Наприклад:
-`I can code very well` (present ability) `Can I leave early today?` (asking for permission)
-
-`Could you pass me that tool, please?` (polite request) `When I first learned programming, I could spend hours debugging without getting tired` (past ability)
+* `I can code very well` (present ability)
+* `Can I leave early today?` (asking for permission)
+* `Could you pass me that tool, please?` (polite request)
+* `When I first learned programming, I could spend hours debugging without getting tired` (past ability)
# --questions--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a896f31ca6a32913d1106.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a896f31ca6a32913d1106.md
index 98cc3f1f88..bc8000d6c0 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a896f31ca6a32913d1106.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a896f31ca6a32913d1106.md
@@ -11,7 +11,7 @@ dashedName: task-69
The words you use in a sentence can make a big difference in modulating the message it delivers. Let's look at some examples to understand this better.
-Prepositions like `by` affect the verb that comes after, When you use `by`, it often needs the verb to end with `-ing`. Ось приклад:
+Prepositions like `by` affect the verb that comes after. When you use `by`, it often needs the verb to end with `-ing`. Ось приклад:
`I improved by practicing daily` (This means I got better at something because I practiced every day. You use the preposition `by` to show how something is done)
@@ -21,7 +21,8 @@ Adjectives can also change the meaning of the following word by adding details t
Even words like `family` and `outdoor` can be used as adjectives, they describe the noun that follows them. Наприклад:
-`Family activities bring everyone together.` (`family` describes the type of activities) `Outdoor sports are enjoyable in good weather.` (`outdoor` describes where the sports happen)
+* `Family activities bring everyone together.` (`family` describes the type of activities)
+* `Outdoor sports are enjoyable in good weather.` (`outdoor` describes where the sports happen)
# --fillInTheBlank--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a8c9d2a0ea136a0fd3631.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a8c9d2a0ea136a0fd3631.md
index 0881683e13..429dd3097e 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a8c9d2a0ea136a0fd3631.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655a8c9d2a0ea136a0fd3631.md
@@ -12,9 +12,8 @@ dashedName: task-72
`While` is used in sentences to indicate that two actions or events are happening at the same time. It often sets the scene for one action that occurs during the time another action is taking place. Наприклад:
-`While I cook, I listen to music` (I listen to music at the same time as I am cooking)
-
-`She reads while waiting for the bus` (She reads during the time she is waiting)
+* `While I cook, I listen to music` (I listen to music at the same time as I am cooking)
+* `She reads while waiting for the bus` (She reads during the time she is waiting)
# --questions--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655b266c2ea5495f43b97ea5.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655b266c2ea5495f43b97ea5.md
index 6deb0e3222..e6e7272f93 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655b266c2ea5495f43b97ea5.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655b266c2ea5495f43b97ea5.md
@@ -39,7 +39,7 @@ That is the wrong time.
### --feedback--
-That’s the wrong time of the day.
+That's the wrong time of the day.
---
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655b2b5cc4ea3062f9811dec.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655b2b5cc4ea3062f9811dec.md
index 20ea02c825..f414467027 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655b2b5cc4ea3062f9811dec.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655b2b5cc4ea3062f9811dec.md
@@ -14,9 +14,8 @@ A `night owl` is someone who stays up late. For example: `He's a night owl, ofte
`Be back` means to return, and `tops` is used informally to indicate the maximum amount or time. Наприклад:
-`I'll be back by dinner` (returning before a specific time)
-
-`The meeting will last one hour, tops` (no longer than one hour)
+* `I'll be back by dinner` (returning before a specific time)
+* `The meeting will last one hour, tops` (no longer than one hour)
# --fillInTheBlank--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655b3197bb31ca670081f6d7.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655b3197bb31ca670081f6d7.md
index a08fb8a1bf..4a32676228 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655b3197bb31ca670081f6d7.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-discuss-your-morning-or-evening-routine/655b3197bb31ca670081f6d7.md
@@ -19,7 +19,7 @@ Long adjectives: Just add `the most` before the adjective.
`This is the most interesting book I've read.` (`the most` + `interesting`)
-This is an introduction to these adjectives. You’ll learn more in the future.
+This is an introduction to these adjectives. You'll learn more in the future.
# --fillInTheBlank--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-document-code-for-a-project/65e46524078f872c3a871f9f.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-document-code-for-a-project/65e46524078f872c3a871f9f.md
index 72fc278ad4..bbf2171f1e 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-document-code-for-a-project/65e46524078f872c3a871f9f.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-document-code-for-a-project/65e46524078f872c3a871f9f.md
@@ -41,7 +41,7 @@ dashedName: task-5
### --feedback--
-Це ще одне значення `clear`, яке стосується чогось, що пропускає світло, причому об’єкти позаду видно чітко. `Clear` у документації стосується розуміння, а не прозорості.
+It's another meaning of `clear`, referring to something allowing light to pass through so that objects behind can be distinctly seen. `Clear` у документації стосується розуміння, а не прозорості.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/661757150c7a75961a574a39.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/661757150c7a75961a574a39.md
index e8bbc42411..6cdf351555 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/661757150c7a75961a574a39.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/661757150c7a75961a574a39.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-7
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/66175792ec93b19771c55c62.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/66175792ec93b19771c55c62.md
index 93978578b5..013a616207 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/66175792ec93b19771c55c62.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/66175792ec93b19771c55c62.md
@@ -29,7 +29,7 @@ She thinks the design is perfect and doesn't need any changes.
---
-She doesn’t know and needs more time to form an opinion.
+She doesn't know and needs more time to form an opinion.
### --feedback--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/661772551b64ddd40c834b1e.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/661772551b64ddd40c834b1e.md
index 07dc802470..3a62c77760 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/661772551b64ddd40c834b1e.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/661772551b64ddd40c834b1e.md
@@ -35,7 +35,7 @@ Yes, she completely agrees with Brian and suggests additional features for the m
### --feedback--
-Sarah's statement indicates disagreement with Brian’s focus on the mobile app, as she believes the web app requires more attention.
+Sarah's statement indicates disagreement with Brian's focus on the mobile app, as she believes the web app requires more attention.
---
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/661796e4635cd3eb1c8c78a4.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/661796e4635cd3eb1c8c78a4.md
index 2ac0cabf02..34d809f45e 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/661796e4635cd3eb1c8c78a4.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/661796e4635cd3eb1c8c78a4.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-14
---
-
+
# --description--
@@ -19,7 +19,7 @@ To `allocate` means to distribute or assign resources or responsibilities to dif
## --sentence--
-`Well, here’s what I think we could do. Why don’t we BLANK resources to both platforms BLANK? We could give equal priority to BLANK the web app and the mobile app.`
+`Well, here's what I think we could do. Why don't we BLANK resources to both platforms BLANK? We could give equal priority to BLANK the web app and the mobile app.`
## --blanks--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/661797b505f2d3ed4b170d74.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/661797b505f2d3ed4b170d74.md
index be9b53d6c0..5e9637adab 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/661797b505f2d3ed4b170d74.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/661797b505f2d3ed4b170d74.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-15
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/66179829f664e3ee9b42ce5f.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/66179829f664e3ee9b42ce5f.md
index f6fb42112a..bb399843a1 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/66179829f664e3ee9b42ce5f.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/66179829f664e3ee9b42ce5f.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-16
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/6617994636fa13f16060b12b.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/6617994636fa13f16060b12b.md
index e990ab159c..843aa6c4c1 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/6617994636fa13f16060b12b.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/6617994636fa13f16060b12b.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-17
---
-
+
# --description--
@@ -23,7 +23,7 @@ Understanding these terms is key for discussing work plans and responsibilities.
## --sentence--
-`I BLANK think we should BLANK more time to the web app, but I see where you’re coming from, Brian. I think we can try giving equal BLANK for a while.`
+`I BLANK think we should BLANK more time to the web app, but I see where you're coming from, Brian. I think we can try giving equal BLANK for a while.`
## --blanks--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/6617aea9ccdd68f7088368d1.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/6617aea9ccdd68f7088368d1.md
index c688fef9ae..138a0d98b3 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/6617aea9ccdd68f7088368d1.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/6617aea9ccdd68f7088368d1.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-18
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/6617af3ab73475f87b53a59d.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/6617af3ab73475f87b53a59d.md
index cc09db577f..37d9f5ef44 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/6617af3ab73475f87b53a59d.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/6617af3ab73475f87b53a59d.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-19
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/6617b500a7049808f3a2a593.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/6617b500a7049808f3a2a593.md
index 5c8b168946..7ea4aedde8 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/6617b500a7049808f3a2a593.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/6617b500a7049808f3a2a593.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-29
---
-
+
# --description--
@@ -15,7 +15,7 @@ Focus on the word `greater`. `Greater` is used to describe something that is mor
## --sentence--
-`I see what you mean. I strongly feel that Agile aligns with our team's strengths, though. I think we’ll have a BLANK chance of success with it.`
+`I see what you mean. I strongly feel that Agile aligns with our team's strengths, though. I think we'll have a BLANK chance of success with it.`
## --blanks--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/6617b53e5eda8e09c6c67d28.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/6617b53e5eda8e09c6c67d28.md
index b68208ff37..a3272c305f 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/6617b53e5eda8e09c6c67d28.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/6617b53e5eda8e09c6c67d28.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-30
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/6617b674eb480b0c8d3d6031.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/6617b674eb480b0c8d3d6031.md
index 5431406a25..8f173b1e5d 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/6617b674eb480b0c8d3d6031.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/6617b674eb480b0c8d3d6031.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-31
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/6617b81046e7b11287a7bef8.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/6617b81046e7b11287a7bef8.md
index 780105ecb4..f21fc2329e 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/6617b81046e7b11287a7bef8.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-express-agreement-or-disagreement/6617b81046e7b11287a7bef8.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-32
---
-
+
# --description--
@@ -27,7 +27,7 @@ Sarah expresses a strong belief in Agile's alignment with the team's strengths.
---
-She disagrees with using Agile and thinks it won’t be successful.
+She disagrees with using Agile and thinks it won't be successful.
### --feedback--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-have-a-conversation-about-preferences-and-motivations/658157d104bbc92a95147e45.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-have-a-conversation-about-preferences-and-motivations/658157d104bbc92a95147e45.md
index 9bcd1d60ef..5814744158 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-have-a-conversation-about-preferences-and-motivations/658157d104bbc92a95147e45.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-have-a-conversation-about-preferences-and-motivations/658157d104bbc92a95147e45.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-32
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-have-a-conversation-about-preferences-and-motivations/65fc9a04edb4d56c8390bc3a.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-have-a-conversation-about-preferences-and-motivations/65fc9a04edb4d56c8390bc3a.md
index 7d1939a0ba..43738f3a27 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-have-a-conversation-about-preferences-and-motivations/65fc9a04edb4d56c8390bc3a.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-have-a-conversation-about-preferences-and-motivations/65fc9a04edb4d56c8390bc3a.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-31
---
-
+
# --description--
@@ -15,7 +15,7 @@ A `glitch` is a small problem that stops something from working right. Like when
## --sentence--
-`Yeah, technical BLANK are complicated and there’s not much we can do other than BLANK to solve them.`
+`Yeah, technical BLANK are complicated and there's not much we can do other than BLANK to solve them.`
## --blanks--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-have-a-conversation-about-preferences-and-motivations/65fc9ab3635ebc6d167f86e6.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-have-a-conversation-about-preferences-and-motivations/65fc9ab3635ebc6d167f86e6.md
index 568982dd60..39f7a3629c 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-have-a-conversation-about-preferences-and-motivations/65fc9ab3635ebc6d167f86e6.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-have-a-conversation-about-preferences-and-motivations/65fc9ab3635ebc6d167f86e6.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-33
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/656bd968e52c34220164de8d.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/656bd968e52c34220164de8d.md
index d9fadb3d43..70f2d19b0f 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/656bd968e52c34220164de8d.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/656bd968e52c34220164de8d.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-32
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65a84dad1595bbbc2e9cd895.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65a84dad1595bbbc2e9cd895.md
index b9f428a8bc..6ef7083f85 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65a84dad1595bbbc2e9cd895.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65a84dad1595bbbc2e9cd895.md
@@ -5,11 +5,11 @@ challengeType: 22
dashedName: task-34
---
-
+
# --description--
-People often use `have already` to talk about something they have done before now, and `have never` to talk about something they have not done at any time in the past. Let’s practice using these phrases.
+People often use `have already` to talk about something they have done before now, and `have never` to talk about something they have not done at any time in the past. Let's practice using these phrases.
# --fillInTheBlank--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65a84e922382a7bd112057ad.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65a84e922382a7bd112057ad.md
index a8db1240e9..17626b938d 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65a84e922382a7bd112057ad.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65a84e922382a7bd112057ad.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-35
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65a85090914872be8ca97793.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65a85090914872be8ca97793.md
index c2fa1f52ca..36966b5f79 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65a85090914872be8ca97793.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65a85090914872be8ca97793.md
@@ -19,7 +19,7 @@ What is Tom asking Sarah about?
## --answers--
-Why she didn’t solve the issue
+Why she didn't solve the issue
### --feedback--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65a9457392dfd7d564bc940e.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65a9457392dfd7d564bc940e.md
index 74f5b12b3d..fb559fde22 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65a9457392dfd7d564bc940e.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65a9457392dfd7d564bc940e.md
@@ -27,7 +27,7 @@ It caused more problems, showing the current version is the issue.
### --feedback--
-Sarah said that going back didn’t solve the issue, not that it caused more problems.
+Sarah said that going back didn't solve the issue, not that it caused more problems.
---
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65b28bbe803df52c4e76dd15.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65b28bbe803df52c4e76dd15.md
index 1bf7b96837..304c432462 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65b28bbe803df52c4e76dd15.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65b28bbe803df52c4e76dd15.md
@@ -13,7 +13,7 @@ Modal verbs like `might` and `can` are used to express possibility and ability.
`Might` is used for something that could happen or be true, like saying, `It might rain today`.
-`Can` is used to talk about someone's ability to do something, like, `She can speak three languages`. Let’s practice using these words in sentences.
+`Can` is used to talk about someone's ability to do something, like, `She can speak three languages`. Let's practice using these words in sentences.
# --fillInTheBlank--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65b28f840a0d962f2240e800.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65b28f840a0d962f2240e800.md
index 53cec8fc3c..e91defe0e1 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65b28f840a0d962f2240e800.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65b28f840a0d962f2240e800.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-47
---
-
+
# --description--
@@ -15,7 +15,7 @@ In this task, you'll practice filling in key verbs and adjectives used in techni
## --sentence--
-`Agreed. I’ll BLANK a PR with the rollback and some BLANK logs for BLANK. That may help us find what the problem is.`
+`Agreed. I'll BLANK a PR with the rollback and some BLANK logs for BLANK. That may help us find what the problem is.`
## --blanks--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65b2af1545e34334b7573de9.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65b2af1545e34334b7573de9.md
index 86b4c75190..9152edf7d3 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65b2af1545e34334b7573de9.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65b2af1545e34334b7573de9.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-48
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65b2b2781c59e837a5e0beb2.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65b2b2781c59e837a5e0beb2.md
index 15cc09f91a..66bb5fa6a9 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65b2b2781c59e837a5e0beb2.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65b2b2781c59e837a5e0beb2.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-51
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65b2bb073ac8d03dfe507810.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65b2bb073ac8d03dfe507810.md
index 0516c1c957..34f2f39036 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65b2bb073ac8d03dfe507810.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-help-a-coworker-troubleshoot-on-github/65b2bb073ac8d03dfe507810.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-60
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-offer-technical-support-and-guidance/6620e51c36d18c137b887081.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-offer-technical-support-and-guidance/6620e51c36d18c137b887081.md
index 88c12ea077..5523bc92e0 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-offer-technical-support-and-guidance/6620e51c36d18c137b887081.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-offer-technical-support-and-guidance/6620e51c36d18c137b887081.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-29
---
-
+
# --description--
@@ -27,7 +27,7 @@ Writing complex code without comments
### --feedback--
-Tom’s focus is on explaining complex code with comments, not writing it without comments.
+Tom's focus is on explaining complex code with comments, not writing it without comments.
---
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-offer-technical-support-and-guidance/6622346c798d906ee4d31846.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-offer-technical-support-and-guidance/6622346c798d906ee4d31846.md
index b095faa885..4f5facb39f 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-offer-technical-support-and-guidance/6622346c798d906ee4d31846.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-offer-technical-support-and-guidance/6622346c798d906ee4d31846.md
@@ -37,7 +37,7 @@ In this context, it refers to the final point Maria wants to make.
### --feedback--
-It describes the team’s nature of working together and helping each other.
+It describes the team's nature of working together and helping each other.
---
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-read-and-understand-code-documentation/65fd5f2abfdbc510942d76f8.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-read-and-understand-code-documentation/65fd5f2abfdbc510942d76f8.md
index 51c43ff795..9c37c88af0 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-read-and-understand-code-documentation/65fd5f2abfdbc510942d76f8.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-read-and-understand-code-documentation/65fd5f2abfdbc510942d76f8.md
@@ -35,7 +35,7 @@ dashedName: task-6
### --feedback--
-Порада Сари стосується не читання всього підряд, а ефективного пошуку конкретної інформації.
+The suggestion isn't about reading everything in order but about finding specific information efficiently.
---
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-progress-and-accomplishments/661005bbe1801e14c303a57a.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-progress-and-accomplishments/661005bbe1801e14c303a57a.md
index b7de149d03..362b66a43c 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-progress-and-accomplishments/661005bbe1801e14c303a57a.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-progress-and-accomplishments/661005bbe1801e14c303a57a.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-4
---
-
+
# --description--
@@ -17,7 +17,7 @@ dashedName: task-4
## --sentence--
-`That's great, Sarah! I’ve also been BLANK busy this week. I tested the new BLANK we added last week. It BLANK to be working well. And I found a few BLANK issues that we need to fix.`
+`That's great, Sarah! I've also been BLANK busy this week. I tested the new BLANK we added last week. It BLANK to be working well. And I found a few BLANK issues that we need to fix.`
## --blanks--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-progress-and-accomplishments/66100646290700150caff732.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-progress-and-accomplishments/66100646290700150caff732.md
index 0b5456e45e..b29db484fd 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-progress-and-accomplishments/66100646290700150caff732.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-progress-and-accomplishments/66100646290700150caff732.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-5
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-progress-and-accomplishments/661216bbf6d9a51b409172a8.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-progress-and-accomplishments/661216bbf6d9a51b409172a8.md
index 47bfb38ad2..afec377391 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-progress-and-accomplishments/661216bbf6d9a51b409172a8.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-progress-and-accomplishments/661216bbf6d9a51b409172a8.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-7
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-progress-and-accomplishments/661256fe823f142fb9858beb.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-progress-and-accomplishments/661256fe823f142fb9858beb.md
index 5510ef725e..3994684a45 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-progress-and-accomplishments/661256fe823f142fb9858beb.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-progress-and-accomplishments/661256fe823f142fb9858beb.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-22
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-progress-and-accomplishments/66126744e24b0a31255718a7.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-progress-and-accomplishments/66126744e24b0a31255718a7.md
index fd7eb8ca19..6c9731d406 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-progress-and-accomplishments/66126744e24b0a31255718a7.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-progress-and-accomplishments/66126744e24b0a31255718a7.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-23
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579cf81a9cec6d21f872959.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579cf81a9cec6d21f872959.md
index a186aaf148..6f08804fde 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579cf81a9cec6d21f872959.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579cf81a9cec6d21f872959.md
@@ -9,7 +9,7 @@ dashedName: task-6
# --description--
-The phrase `a fresh pair of eyes` is an idiomatic expression meaning to have someone new look at something to offer a different perspective. It’s often used when someone has been working on a problem for a long time and needs an outside opinion. The modal verb `may` suggests possibility or likelihood but not certainty.
+The phrase `a fresh pair of eyes` is an idiomatic expression meaning to have someone new look at something to offer a different perspective. It's often used when someone has been working on a problem for a long time and needs an outside opinion. The modal verb `may` suggests possibility or likelihood but not certainty.
# --fillInTheBlank--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579d002683211d5c7d13ef3.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579d002683211d5c7d13ef3.md
index 41febce4ba..699b277150 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579d002683211d5c7d13ef3.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579d002683211d5c7d13ef3.md
@@ -9,7 +9,7 @@ dashedName: task-8
# --description--
-Sophie implies, or suggests without directly stating, that she needs help with her coding problem. To 'imply' something means to suggest it in an indirect way. For example, saying 'It’s getting late' can imply that it's time to leave, without saying it directly.
+Sophie implies, or suggests without directly stating, that she needs help with her coding problem. To 'imply' something means to suggest it in an indirect way. For example, saying 'It's getting late' can imply that it's time to leave, without saying it directly.
# --questions--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579d4ca0578b4e95f1df60e.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579d4ca0578b4e95f1df60e.md
index e44f99e60c..38ed3b2caa 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579d4ca0578b4e95f1df60e.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579d4ca0578b4e95f1df60e.md
@@ -35,7 +35,7 @@ She should wait until the next meeting
### --feedback--
-Bob’s offer to help is immediate, contingent on Sophie sharing the code, not waiting until the next meeting.
+Bob's offer to help is immediate, contingent on Sophie sharing the code, not waiting until the next meeting.
---
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579d539b1e5c2ec64484e49.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579d539b1e5c2ec64484e49.md
index 8e587d5379..8d771bc597 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579d539b1e5c2ec64484e49.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579d539b1e5c2ec64484e49.md
@@ -43,7 +43,7 @@ He doesn't think the problem can be solved
### --feedback--
-Bob’s statement implies he believes there are possible solutions, not that it's unsolvable.
+Bob's statement implies he believes there are possible solutions, not that it's unsolvable.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579d827ebd50afcacb829fe.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579d827ebd50afcacb829fe.md
index 9ccaae5eb1..a2f66708b1 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579d827ebd50afcacb829fe.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579d827ebd50afcacb829fe.md
@@ -44,7 +44,7 @@ He is asking for a break from the meeting
### --feedback--
-Bob’s statement is about making a suggestion, not about taking a break from the meeting.
+Bob's statement is about making a suggestion, not about taking a break from the meeting.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579dbf6a3e8a5161a592169.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579dbf6a3e8a5161a592169.md
index d588a4d271..e533837b10 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579dbf6a3e8a5161a592169.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579dbf6a3e8a5161a592169.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-31
---
-
+
# --description--
@@ -43,7 +43,7 @@ He is unsure about the usefulness of the discussion
### --feedback--
-Bob’s statement `I'm sure` shows confidence in the usefulness of the discussion.
+Bob's statement `I'm sure` shows confidence in the usefulness of the discussion.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579ddc94db61d2463022da3.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579ddc94db61d2463022da3.md
index d5a2672aa3..3a4d1eb9d8 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579ddc94db61d2463022da3.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579ddc94db61d2463022da3.md
@@ -35,7 +35,7 @@ Sophie specifically mentions a coding issue she's been working on, not a differe
---
-She requests Bob’s help on a coding issue she's struggling with
+She requests Bob's help on a coding issue she's struggling with
---
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579de040244fb274179f001.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579de040244fb274179f001.md
index 14cb1927c0..9f9d7d7081 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579de040244fb274179f001.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579de040244fb274179f001.md
@@ -31,7 +31,7 @@ It means to give someone access to something, here referring to the code.
### --feedback--
-It suggests starting something with enthusiasm, indicating Bob’s readiness to examine the code closely.
+It suggests starting something with enthusiasm, indicating Bob's readiness to examine the code closely.
# --scene--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579e17ff05c5d451c2e4f35.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579e17ff05c5d451c2e4f35.md
index b9731dc590..f31ba1d95d 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579e17ff05c5d451c2e4f35.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-share-your-progress-in-weekly-stand-up-meetings/6579e17ff05c5d451c2e4f35.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-56
---
-
+
# --description--
@@ -23,7 +23,7 @@ To wait for further instructions about coding standards
### --feedback--
-Sophie’s statement shows she is ready to start working on the standards, not waiting for instructions.
+Sophie's statement shows she is ready to start working on the standards, not waiting for instructions.
---
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e0868da73165e32763679.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e0868da73165e32763679.md
index 118d044f3a..01b0a280c3 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e0868da73165e32763679.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e0868da73165e32763679.md
@@ -38,7 +38,7 @@ dashedName: task-8
### --feedback--
-У цьому реченні не використано `most`.
+This sentence doesn't use `most`
---
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e15f175ecdf90b583ed01.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e15f175ecdf90b583ed01.md
index 138082652e..ec335f366b 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e15f175ecdf90b583ed01.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e15f175ecdf90b583ed01.md
@@ -19,7 +19,7 @@ dashedName: task-17
## --answers--
-Про думку щодо роботи.
+Sophie's opinion on work.
### --feedback--
@@ -39,7 +39,7 @@ dashedName: task-17
---
-Яка улюблена кава Софі.
+Sophie's favorite coffee.
### --feedback--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e1c10bc3f2ea8e1c1d7f7.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e1c10bc3f2ea8e1c1d7f7.md
index fb45b3a648..31f9557d50 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e1c10bc3f2ea8e1c1d7f7.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e1c10bc3f2ea8e1c1d7f7.md
@@ -7,7 +7,7 @@ dashedName: task-22
# --description--
-Розуміння чийогось розпорядку дня, як-от обідніх звичок, передбачає звернення уваги на конкретні деталі в розмові.
+Understanding someone's routine, like their lunch habits, involves paying attention to specific details in the conversation.
# --questions--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e31b82090130535456f65.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e31b82090130535456f65.md
index 6f68dc270f..2c71ad0e3a 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e31b82090130535456f65.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e31b82090130535456f65.md
@@ -33,7 +33,7 @@ Anna: You're welcome, Tom. -->
### --feedback--
-Допомога з проєктом у цьому контексті не згадується.
+Helping with a project isn't mentioned in this context.
---
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e358a40dd95143df6fe26.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e358a40dd95143df6fe26.md
index 64608efce7..abe7e09217 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e358a40dd95143df6fe26.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e358a40dd95143df6fe26.md
@@ -41,7 +41,7 @@ His favorite security equipment.
### --feedback--
-Equipment isn’t mentioned in Sophie's question.
+Equipment isn't mentioned in Sophie's question.
---
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e3dfda31b534042d06e39.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e3dfda31b534042d06e39.md
index f1fca95238..f4e88ad9e6 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e3dfda31b534042d06e39.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e3dfda31b534042d06e39.md
@@ -27,7 +27,7 @@ dashedName: task-54
---
-`I have to make sure the security cameras work because I believe it’s crucial.`
+`I have to make sure the security cameras work because I believe it's crucial.`
### --feedback--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e4a245cc71782126b3316.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e4a245cc71782126b3316.md
index c0ca1e8925..da6684670f 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e4a245cc71782126b3316.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e4a245cc71782126b3316.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-68
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e4e482e3a38992b212c6f.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e4e482e3a38992b212c6f.md
index f80a82845c..bec42a2ac9 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e4e482e3a38992b212c6f.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e4e482e3a38992b212c6f.md
@@ -9,7 +9,7 @@ dashedName: task-77
A `policy` (у множині, `policies`) це принцип або правило, щоб керувати рішеннями та досягати раціональних результатів. Організація часто приймає положення, щоб керувати співробітниками.
-Наприклад, `The company’s privacy policy protects client information.`
+For instance, `The company's privacy policy protects client information.`
# --questions--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e50576597e0a65cd97e24.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e50576597e0a65cd97e24.md
index 63ac186b10..68d8a4af9c 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e50576597e0a65cd97e24.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e50576597e0a65cd97e24.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-75
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e50dd1f6ff2a9873f9ff0.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e50dd1f6ff2a9873f9ff0.md
index 76bad63ca6..8f556e8ebd 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e50dd1f6ff2a9873f9ff0.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e50dd1f6ff2a9873f9ff0.md
@@ -44,7 +44,7 @@ dashedName: task-72
### --feedback--
-Йдеться про виконання поставлених завдань, а не про особистий вибір.
+It's about following set tasks, not personal choice.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e5c296bdba2ea26c67ca0.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e5c296bdba2ea26c67ca0.md
index 4d158f04d8..4190a30f98 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e5c296bdba2ea26c67ca0.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e5c296bdba2ea26c67ca0.md
@@ -15,7 +15,7 @@ dashedName: task-97
## --text--
-У чому сенс питання Лінди?
+What is the meaning of Linda's question?
## --answers--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e5d8f7f2274f2b1a8efcc.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e5d8f7f2274f2b1a8efcc.md
index 9319ea7b03..8511037610 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e5d8f7f2274f2b1a8efcc.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-a-typical-workday-and-tasks/657e5d8f7f2274f2b1a8efcc.md
@@ -25,7 +25,7 @@ What is the difference between `every` and `any`?
### --feedback--
-`Every` is for all items, not just in questions.
+`Every` is for all items, not just in questions; `any` is for one, some, or all.
---
@@ -41,7 +41,7 @@ What is the difference between `every` and `any`?
### --feedback--
-`Every` означає всі, а не жоден.
+`Every` means all, not none; `any` means one, some, or all.
---
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-hobbies-and-interests/657e76356b6af6c07fe338c1.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-hobbies-and-interests/657e76356b6af6c07fe338c1.md
index 41192f0ba0..d97f42bc80 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-hobbies-and-interests/657e76356b6af6c07fe338c1.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-hobbies-and-interests/657e76356b6af6c07fe338c1.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-28
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-hobbies-and-interests/657e786b51f7eac240e92bcc.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-hobbies-and-interests/657e786b51f7eac240e92bcc.md
index 234888dde3..b9a56828d6 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-hobbies-and-interests/657e786b51f7eac240e92bcc.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-hobbies-and-interests/657e786b51f7eac240e92bcc.md
@@ -39,7 +39,7 @@ This sentence is not correct. A correct usage would be `Would you like me to mak
### --feedback--
-In this context, `like` doesn’t require the ending `-s` The correct form is `Would you like a glass of water?`
+In this context, `like` doesn't require the ending `-s` The correct form is `Would you like a glass of water?`
---
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-hobbies-and-interests/657fff7dabba2ff23993b08c.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-hobbies-and-interests/657fff7dabba2ff23993b08c.md
index 6fbb3fd72e..f0453925d3 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-hobbies-and-interests/657fff7dabba2ff23993b08c.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-hobbies-and-interests/657fff7dabba2ff23993b08c.md
@@ -31,7 +31,7 @@ Partial acceptance
### --feedback--
-It suggests agreeing partially, which doesn’t fit the intention of the phrase.
+It suggests agreeing partially, which doesn't fit the intention of the phrase.
---
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-hobbies-and-interests/658010478daa16fe79d8113a.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-hobbies-and-interests/658010478daa16fe79d8113a.md
index d6ae27bd74..ac0a35826c 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-hobbies-and-interests/658010478daa16fe79d8113a.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-hobbies-and-interests/658010478daa16fe79d8113a.md
@@ -35,7 +35,7 @@ She's hesitant to include Brian.
### --feedback--
-Sophie's tone doesn’t suggest hesitation, but rather openness and enthusiasm for his participation.
+Sophie's tone doesn't suggest hesitation, but rather openness and enthusiasm for his participation.
---
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6613d3fe6615374be0d10008.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6613d3fe6615374be0d10008.md
index db0e15fc56..e587ab16d8 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6613d3fe6615374be0d10008.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6613d3fe6615374be0d10008.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-5
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6613d46936e9374c24cfaaab.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6613d46936e9374c24cfaaab.md
index 4fc9f8ac26..c2da6004a4 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6613d46936e9374c24cfaaab.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6613d46936e9374c24cfaaab.md
@@ -11,7 +11,7 @@ dashedName: task-6
`Going to` can also be used when you have some evidence in the present that something will happen in the future.
-For example, `Look at those numbers! It's going to be a hard day.` or `They are going to feel upset if we don’t invite them to the meeting.`
+For example, `Look at those numbers! It's going to be a hard day.` or `They are going to feel upset if we don't invite them to the meeting.`
# --fillInTheBlank--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6613d550a08c194cd27607ec.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6613d550a08c194cd27607ec.md
index 133205c30f..c837e2a30b 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6613d550a08c194cd27607ec.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6613d550a08c194cd27607ec.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-8
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6613d6c3e74a984d6fcbd013.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6613d6c3e74a984d6fcbd013.md
index fb2bd9b052..222ba14381 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6613d6c3e74a984d6fcbd013.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6613d6c3e74a984d6fcbd013.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-10
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6614ad58c102e15df06c96d5.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6614ad58c102e15df06c96d5.md
index 4fd5018af9..2a8b1f0d73 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6614ad58c102e15df06c96d5.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6614ad58c102e15df06c96d5.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-15
---
-
+
# --description--
@@ -21,7 +21,7 @@ An `audience` refers to the group of people who watch, read, or listen to someth
## --sentence--
-`I think we’re going to focus on social media marketing. It's BLANK, and it will BLANK a BLANK audience.`
+`I think we're going to focus on social media marketing. It's BLANK, and it will BLANK a BLANK audience.`
## --blanks--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6614ae3e02cc465ebee68851.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6614ae3e02cc465ebee68851.md
index 6d89d3cb0a..11783666da 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6614ae3e02cc465ebee68851.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6614ae3e02cc465ebee68851.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-16
---
-
+
# --description--
@@ -19,7 +19,7 @@ Which part of Sophie's sentence indicates that she is considering focusing on so
## --answers--
-`I think we’re going to focus on social media marketing.`
+`I think we're going to focus on social media marketing.`
---
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6614b1f8ee220c5f79df89b8.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6614b1f8ee220c5f79df89b8.md
index 227afa1c26..fc3e9ca53c 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6614b1f8ee220c5f79df89b8.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6614b1f8ee220c5f79df89b8.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-17
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6614b3e52a6aca60bc3417fb.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6614b3e52a6aca60bc3417fb.md
index c2908e52d5..7b09a9f810 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6614b3e52a6aca60bc3417fb.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-talk-about-updates-and-plans-for-tasks-and-projects/6614b3e52a6aca60bc3417fb.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-20
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/6629ce1a4f6581a7266d6ca9.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/6629ce1a4f6581a7266d6ca9.md
index 2eb4f1d6eb..cf2ee0dcd1 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/6629ce1a4f6581a7266d6ca9.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/6629ce1a4f6581a7266d6ca9.md
@@ -11,7 +11,7 @@ dashedName: task-3
The **Present Perfect Continuous tense** is used talk about actions or situations that started in the past and are still happening now. It is very useful when you want to emphasize the duration of an activity or that it is an ongoing process.
-Here’s how to form the **Present Perfect Continuous**: Subject + `has/have been` + `-ing` form of the verb. This tense is often used with expressions of time such as `for` and `since`. `For` is used with a period of time like two years or six months, while `since` is used with a specific point in time, like 2018 or this morning.
+Here's how to form the **Present Perfect Continuous**: Subject + `has/have been` + `-ing` form of the verb. This tense is often used with expressions of time such as `for` and `since`. `For` is used with a period of time like two years or six months, while `since` is used with a specific point in time, like 2018 or this morning.
Приклади:
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662a2779b2aeb80c10508bf2.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662a2779b2aeb80c10508bf2.md
index 7eaffd598d..d08321c008 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662a2779b2aeb80c10508bf2.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662a2779b2aeb80c10508bf2.md
@@ -23,7 +23,7 @@ She complains about the difficulty of learning them.
### --feedback--
-Sophie doesn’t mention any difficulty; she only expresses surprise at the number of programming languages.
+Sophie doesn't mention any difficulty; she only expresses surprise at the number of programming languages.
---
@@ -43,7 +43,7 @@ She ignores the comment and changes the subject.
### --feedback--
-Sophie directly responds to Brian’s observation by pointing out an interesting fact about programming languages.
+Sophie directly responds to Brian's observation by pointing out an interesting fact about programming languages.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662a2b1f0c9314142ae87955.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662a2b1f0c9314142ae87955.md
index 0833853c06..f0dbb7ee07 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662a2b1f0c9314142ae87955.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662a2b1f0c9314142ae87955.md
@@ -43,7 +43,7 @@ Who she was with when she spent the time
### --feedback--
-Brian’s question is specifically about the amount of time, not about who was with her.
+Brian's question is specifically about the amount of time, not about who was with her.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662a304552f2631d63aa7cab.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662a304552f2631d63aa7cab.md
index 258be83d21..84958a2ec1 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662a304552f2631d63aa7cab.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662a304552f2631d63aa7cab.md
@@ -35,7 +35,7 @@ Sophie actually indicates she has free time and chooses to spend much of it on a
---
-She doesn’t enjoy what she does in her free time.
+She doesn't enjoy what she does in her free time.
### --feedback--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662b74055c06e60af4f9b976.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662b74055c06e60af4f9b976.md
index 57b58ec1d0..a487f5b178 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662b74055c06e60af4f9b976.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662b74055c06e60af4f9b976.md
@@ -23,7 +23,7 @@ Brian needs help finding Python, the snake.
### --feedback--
-Brian’s question is about Python the programming language, not a snake.
+Brian's question is about Python the programming language, not a snake.
---
@@ -35,7 +35,7 @@ Brian is looking for someone to teach him Python next week.
### --feedback--
-Brian’s request implies an immediate need for clarification on a specific question, not seeking a teacher for future lessons.
+Brian's request implies an immediate need for clarification on a specific question, not seeking a teacher for future lessons.
---
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662b8975b11107146a49ec58.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662b8975b11107146a49ec58.md
index f9e8fd16d6..dc5f3dc416 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662b8975b11107146a49ec58.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662b8975b11107146a49ec58.md
@@ -35,7 +35,7 @@ Sarah needs help installing her code.
### --feedback--
-The audio does not mention installation issues; it focuses on trouble with existing code and understanding what’s wrong.
+The audio does not mention installation issues; it focuses on trouble with existing code and understanding what's wrong.
---
@@ -43,7 +43,7 @@ Sarah is confident about fixing the code herself.
### --feedback--
-Sarah’s description of not being able to figure out the issue suggests she is not confident about resolving it on her own.
+Sarah's description of not being able to figure out the issue suggests she is not confident about resolving it on her own.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662f074021418e2b24937af7.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662f074021418e2b24937af7.md
index ae5a2a3522..3b4d056908 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662f074021418e2b24937af7.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662f074021418e2b24937af7.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-53
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662f0d350c37f42de48847fe.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662f0d350c37f42de48847fe.md
index 12d25fca96..1fd8f0afa2 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662f0d350c37f42de48847fe.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662f0d350c37f42de48847fe.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-57
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662f2e4b96f60636d44eb7db.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662f2e4b96f60636d44eb7db.md
index 994f004cd8..530029377b 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662f2e4b96f60636d44eb7db.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662f2e4b96f60636d44eb7db.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-66
---
-
+
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662f31024608f337c0bf53a9.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662f31024608f337c0bf53a9.md
index 0cd2d90516..61f9cf7529 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662f31024608f337c0bf53a9.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662f31024608f337c0bf53a9.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-67
---
-
+
# --description--
@@ -31,11 +31,11 @@ Tom knows some things but hasn't tried them yet.
---
-Tom knows a lot about it but hasn’t used it.
+Tom knows a lot about it but hasn't used it.
### --feedback--
-Tom mentions understanding basic ideas like classes and methods, but he hasn’t used them, showing he knows a bit but not a lot.
+Tom mentions understanding basic ideas like classes and methods, but he hasn't used them, showing he knows a bit but not a lot.
---
@@ -43,7 +43,7 @@ Tom doesn't know anything about it.
### --feedback--
-Tom does know something because he talks about classes and methods, so he isn’t completely unfamiliar.
+Tom does know something because he talks about classes and methods, so he isn't completely unfamiliar.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662f3450de7c2139809fb72b.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662f3450de7c2139809fb72b.md
index 753ba2e66b..7ba2a7aca8 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662f3450de7c2139809fb72b.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-how-to-use-basic-programming-vocabulary-in-conversations/662f3450de7c2139809fb72b.md
@@ -33,7 +33,7 @@ A coworker asks for a report urgently and you reply, `No worries`, without provi
### --feedback--
-This use might imply indifference or dismissal without addressing the coworker’s urgent need, which is not appropriate.
+This use might imply indifference or dismissal without addressing the coworker's urgent need, which is not appropriate.
---
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657b400653813a1caa228aca.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657b400653813a1caa228aca.md
index 4ccf902c93..36f1978231 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657b400653813a1caa228aca.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657b400653813a1caa228aca.md
@@ -20,7 +20,7 @@ My name is Alice, and I'm happy to be part of the team.
## --text--
-Що означає вислів I’m happy у теперішньому простому часі?
+What does the expression `I'm happy` indicate in the present simple tense?
## --answers--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657b68caf6debb2975503948.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657b68caf6debb2975503948.md
index 0aee8e1743..6e155eaccb 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657b68caf6debb2975503948.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657b68caf6debb2975503948.md
@@ -13,7 +13,7 @@ It's nice to have you here, Alice.
# --description--
-`It’s nice to` використовується для вираження позитивних настроїв або почуттів щодо чогось або когось.
+`It's nice to` is used to express a positive sentiment or feeling about something or someone.
# --questions--
@@ -23,7 +23,7 @@ It's nice to have you here, Alice.
## --answers--
-Негативну думку про присутність Аліси
+A negative opinion about Alice's presence
### --feedback--
@@ -31,7 +31,7 @@ It's nice to have you here, Alice.
---
-Нейтральне твердження про присутність Аліси
+A neutral statement about Alice's presence
### --feedback--
@@ -39,7 +39,7 @@ It's nice to have you here, Alice.
---
-Вибачення за присутність Аліси
+An apology for Alice's presence
### --feedback--
@@ -47,7 +47,7 @@ It's nice to have you here, Alice.
---
-Позитивне та доброзичливе відчуття присутності Аліси
+A positive and welcoming sentiment about Alice's presence
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657ca50a95d1c3828ee5a991.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657ca50a95d1c3828ee5a991.md
index 71944af416..1fe4b5e67a 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657ca50a95d1c3828ee5a991.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657ca50a95d1c3828ee5a991.md
@@ -34,7 +34,7 @@ Bob: Well, I'm Bob, your project manager. I'm really happy to see new faces join
### --feedback--
-Хоча це може бути правдою, це не має прямого відношення до фрази про нових учасників.
+While this might be true, it doesn't directly relate to the phrase about new members.
---
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657caa4012f1cf846dcaa619.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657caa4012f1cf846dcaa619.md
index f7b97bfb26..7bb8164efe 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657caa4012f1cf846dcaa619.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657caa4012f1cf846dcaa619.md
@@ -7,7 +7,7 @@ dashedName: task-33
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657cad90d6745e85569cdc06.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657cad90d6745e85569cdc06.md
index 4551da167c..f82e736782 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657cad90d6745e85569cdc06.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657cad90d6745e85569cdc06.md
@@ -7,7 +7,7 @@ dashedName: task-34
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657caec5163c6c85e5b31284.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657caec5163c6c85e5b31284.md
index 29d7f1163a..295858c477 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657caec5163c6c85e5b31284.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657caec5163c6c85e5b31284.md
@@ -7,7 +7,7 @@ dashedName: task-35
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657cafc142a867006734c3ed.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657cafc142a867006734c3ed.md
index dfe0bb0497..0410348e65 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657cafc142a867006734c3ed.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657cafc142a867006734c3ed.md
@@ -7,7 +7,7 @@ dashedName: task-36
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657ccfa7eeb47305177d4a45.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657ccfa7eeb47305177d4a45.md
index 88ee651596..6ebd341592 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657ccfa7eeb47305177d4a45.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657ccfa7eeb47305177d4a45.md
@@ -7,7 +7,7 @@ dashedName: task-42
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657cd816f3caf509f85e4d4a.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657cd816f3caf509f85e4d4a.md
index 0cbad2afaa..68089835ce 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657cd816f3caf509f85e4d4a.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657cd816f3caf509f85e4d4a.md
@@ -7,7 +7,7 @@ dashedName: task-50
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657ce387f809d60eb54f06d6.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657ce387f809d60eb54f06d6.md
index c812a86ac4..513cd9c36b 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657ce387f809d60eb54f06d6.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657ce387f809d60eb54f06d6.md
@@ -7,7 +7,7 @@ dashedName: task-58
# --description--
@@ -20,7 +20,7 @@ Bob: Is there any specific area of design or development you're interested in? H
## --sentence--
-`Is there any BLANK area of design or development you're interested in? He’s your BLANK-to BLANK for that.`
+`Is there any BLANK area of design or development you're interested in? He's your BLANK-to BLANK for that.`
## --blanks--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657ce691d6c57c107e650c5e.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657ce691d6c57c107e650c5e.md
index 950050780d..0b507ff183 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657ce691d6c57c107e650c5e.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657ce691d6c57c107e650c5e.md
@@ -7,7 +7,7 @@ dashedName: task-61
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657daa5ab8505427a5b99cd2.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657daa5ab8505427a5b99cd2.md
index 571e892312..62da9ac0f5 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657daa5ab8505427a5b99cd2.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657daa5ab8505427a5b99cd2.md
@@ -7,7 +7,7 @@ dashedName: task-64
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657dab674b9de728828aa020.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657dab674b9de728828aa020.md
index 9de5c8e9af..8cbe8bf7fa 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657dab674b9de728828aa020.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657dab674b9de728828aa020.md
@@ -7,7 +7,7 @@ dashedName: task-66
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657dadfc7d21eb294c9f057e.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657dadfc7d21eb294c9f057e.md
index fa6384613b..1bade0dd9d 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657dadfc7d21eb294c9f057e.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657dadfc7d21eb294c9f057e.md
@@ -7,7 +7,7 @@ dashedName: task-67
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657daf702ed04a29ee42de69.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657daf702ed04a29ee42de69.md
index 0bab8f1c47..de03f42ce0 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657daf702ed04a29ee42de69.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657daf702ed04a29ee42de69.md
@@ -7,7 +7,7 @@ dashedName: task-68
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657df21cc45b1f66112fb8fc.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657df21cc45b1f66112fb8fc.md
index dac7e366d5..8d9c613139 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657df21cc45b1f66112fb8fc.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657df21cc45b1f66112fb8fc.md
@@ -7,7 +7,7 @@ dashedName: task-69
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657df2b22d7649667734d71e.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657df2b22d7649667734d71e.md
index a9724a31cd..7c6c673cc4 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657df2b22d7649667734d71e.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657df2b22d7649667734d71e.md
@@ -7,7 +7,7 @@ dashedName: task-70
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657df5d14291b56887825276.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657df5d14291b56887825276.md
index 33edec0f34..527ac02447 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657df5d14291b56887825276.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657df5d14291b56887825276.md
@@ -7,7 +7,7 @@ dashedName: task-74
# --description--
@@ -18,7 +18,7 @@ James: Good morning. I’m James and I’m here to help you with your training.
## --sentence--
-`I’m James and I’m BLANK to BLANK you with your BLANK.`
+`I'm James and I'm BLANK to BLANK you with your BLANK.`
## --blanks--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657df6018a70e468f5dc016a.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657df6018a70e468f5dc016a.md
index dd7c16f805..bfa0c8df21 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657df6018a70e468f5dc016a.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657df6018a70e468f5dc016a.md
@@ -7,7 +7,7 @@ dashedName: task-75
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e4b7d381d567e8d97967c.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e4b7d381d567e8d97967c.md
index 960272adc1..bd0587b348 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e4b7d381d567e8d97967c.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e4b7d381d567e8d97967c.md
@@ -7,7 +7,7 @@ dashedName: task-88
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e4c1f0bd3e97ef2d46644.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e4c1f0bd3e97ef2d46644.md
index 60afc9b497..73d43bd19a 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e4c1f0bd3e97ef2d46644.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e4c1f0bd3e97ef2d46644.md
@@ -7,7 +7,7 @@ dashedName: task-89
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e4cd7f87d4f7f6954446d.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e4cd7f87d4f7f6954446d.md
index e20608d607..282d7fd922 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e4cd7f87d4f7f6954446d.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e4cd7f87d4f7f6954446d.md
@@ -7,7 +7,7 @@ dashedName: task-90
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e4db2e3fc8d7fb41b8b85.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e4db2e3fc8d7fb41b8b85.md
index 049d11fafa..2990a17f52 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e4db2e3fc8d7fb41b8b85.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e4db2e3fc8d7fb41b8b85.md
@@ -7,7 +7,7 @@ dashedName: task-91
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e4fd2ecf31280ef673f0d.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e4fd2ecf31280ef673f0d.md
index c1b97e8755..f8886089e4 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e4fd2ecf31280ef673f0d.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e4fd2ecf31280ef673f0d.md
@@ -7,7 +7,7 @@ dashedName: task-94
# --description--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e539471b4aa82c7402c15.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e539471b4aa82c7402c15.md
index 357caad275..2755c0e762 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e539471b4aa82c7402c15.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e539471b4aa82c7402c15.md
@@ -8,7 +8,7 @@ dashedName: task-97
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e5477269b94834908826f.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e5477269b94834908826f.md
index f649718ca9..7bc5784d4d 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e5477269b94834908826f.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e5477269b94834908826f.md
@@ -8,7 +8,7 @@ dashedName: task-98
@@ -20,7 +20,7 @@ David: I’ll be your point of contact and I’ll help make sure our collaborati
## --sentence--
-`I'll be your BLANK of contact and I’ll help make sure our BLANK is great.`
+`I'll be your BLANK of contact and I'll help make sure our BLANK is great.`
## --blanks--
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e54f51fe1c983d840cb70.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e54f51fe1c983d840cb70.md
index 0862e41f8b..f2574f6c24 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e54f51fe1c983d840cb70.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e54f51fe1c983d840cb70.md
@@ -8,7 +8,7 @@ dashedName: task-99
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e55e612fac9847dc7ce03.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e55e612fac9847dc7ce03.md
index f74e513c3b..5e0dbde561 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e55e612fac9847dc7ce03.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e55e612fac9847dc7ce03.md
@@ -8,7 +8,7 @@ dashedName: task-100
diff --git a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e56e7034d2d858b6e9e00.md b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e56e7034d2d858b6e9e00.md
index 6aa25e6eef..d9e136e452 100644
--- a/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e56e7034d2d858b6e9e00.md
+++ b/curriculum/challenges/ukrainian/21-a2-english-for-developers/learn-introductions-in-an-online-team-meeting/657e56e7034d2d858b6e9e00.md
@@ -8,7 +8,7 @@ dashedName: task-101
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66a91783d34e873290e9f5ec.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66a91783d34e873290e9f5ec.md
index d354f8b2f7..0508452f04 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66a91783d34e873290e9f5ec.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66a91783d34e873290e9f5ec.md
@@ -58,7 +58,7 @@ If she is going to a Hackathon this weekend.
To find out what Bob wants to know, listen to the second question he asks. Pay attention what comes after `I hear you're going to...` which show what Bob is trying to find out.
-He uses a question to confirm what he heard, specifically mentioning the event he thinks she’s attending.
+He uses a question to confirm what he heard, specifically mentioning the event he thinks she's attending.
# --scene--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66a95606a32d5747dae3bfba.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66a95606a32d5747dae3bfba.md
index 06c1cee959..25869b37cf 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66a95606a32d5747dae3bfba.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66a95606a32d5747dae3bfba.md
@@ -8,7 +8,7 @@ dashedName: task-14
# --instructions--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66a958bb3ac85c4a75e5fe88.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66a958bb3ac85c4a75e5fe88.md
index ca36ed3e23..6bc8abd325 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66a958bb3ac85c4a75e5fe88.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66a958bb3ac85c4a75e5fe88.md
@@ -7,7 +7,7 @@ dashedName: task-18
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66a9599790c94a4ba0e5dbd9.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66a9599790c94a4ba0e5dbd9.md
index 4ac4454391..1d204157a4 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66a9599790c94a4ba0e5dbd9.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66a9599790c94a4ba0e5dbd9.md
@@ -54,7 +54,7 @@ Lisa is asking about similar projects happening soon, not about moving to a diff
# --explanation--
-Lisa asks about what’s coming up, specifically looking for information on projects that are similar to the one she is currently working on.
+Lisa asks about what's coming up, specifically looking for information on projects that are similar to the one she is currently working on.
Pay attention to the phrase `similar projects coming up here` to understand what Lisa is asking about.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66a95ab699d0064d16bdf469.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66a95ab699d0064d16bdf469.md
index 0a3bcdfe0c..e547ded4d5 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66a95ab699d0064d16bdf469.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66a95ab699d0064d16bdf469.md
@@ -56,7 +56,7 @@ Bob is not asking about development status.
Bob uses the word `yet`, which signals that he is asking if something expected has already happened.
-Pay attention to the words `potential name` and `yet` in Bob’s question, as these indicate that he is asking about the status of the app's name.
+Pay attention to the words `potential name` and `yet` in Bob's question, as these indicate that he is asking about the status of the app's name.
# --scene--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66a961222115ad5437ddf4fb.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66a961222115ad5437ddf4fb.md
index 89ea86edbd..ca9bfe0a46 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66a961222115ad5437ddf4fb.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66a961222115ad5437ddf4fb.md
@@ -55,9 +55,9 @@ Bob has not decided yet. He says `Maybe`.
# --explanation--
-People sometimes express uncertainty before making a decision. Bob hasn’t fully decided if he'll join the event. You can notice that because he says `Maybe`, which shows he is still thinking about it.
+People sometimes express uncertainty before making a decision. Bob hasn't fully decided if he'll join the event. You can notice that because he says `Maybe`, which shows he is still thinking about it.
-Pay attention to Bob’s follow-up question where he asks, `Where can I find...?` This reveals that he needs more details before deciding whether to join the event.
+Pay attention to Bob's follow-up question where he asks, `Where can I find...?` This reveals that he needs more details before deciding whether to join the event.
# --scene--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b13f2f0c5a415ccd41335e.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b13f2f0c5a415ccd41335e.md
index 7d67182960..8775026bec 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b13f2f0c5a415ccd41335e.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b13f2f0c5a415ccd41335e.md
@@ -45,4 +45,4 @@ False
# --explanation--
-To answer this question, focus on the part of the text that describes Lisa’s team. Look for the sentence that mentions `Her team includes...`. This will help you determine if there are developers from Seattle on her team.
+To answer this question, focus on the part of the text that describes Lisa's team. Look for the sentence that mentions `Her team includes...`. This will help you determine if there are developers from Seattle on her team.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b4f8f6c1af973bdfdc0228.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b4f8f6c1af973bdfdc0228.md
index b82062ba59..ea088d0df4 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b4f8f6c1af973bdfdc0228.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b4f8f6c1af973bdfdc0228.md
@@ -41,7 +41,7 @@ When someone asks if you have a moment, they want to talk to you about something
When someone asks if you have a moment, they want to discuss something important.
-The correct response will show that you’re ready to listen or talk about the topic they want to discuss. Pay attention to options that focus on being open to a conversation.
+The correct response will show that you're ready to listen or talk about the topic they want to discuss. Pay attention to options that focus on being open to a conversation.
# --scene--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b56c0432933515821a4eeb.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b56c0432933515821a4eeb.md
index 4a83860096..ba994c9200 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b56c0432933515821a4eeb.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b56c0432933515821a4eeb.md
@@ -20,7 +20,7 @@ Listen to the audio and answer the question below.
## --text--
-Does Anna support Brian’s idea of using real-life scenarios?
+Does Anna support Brian's idea of using real-life scenarios?
## --answers--
@@ -44,7 +44,7 @@ She mentions that using real-life scenarios improves the training. This indicate
---
-She ignores Brian’s suggestion completely. This indicates she doesn't understands his idea.
+She ignores Brian's suggestion completely. This indicates she doesn't understands his idea.
### --feedback--
@@ -56,7 +56,7 @@ She didn't ignore Brian. Pay attention to the words she uses after `Using real-l
# --explanation--
-People sometimes show support indirectly without explicitly saying they agree. To understand if Anna supports Brian’s idea, focus on her comment about the training.
+People sometimes show support indirectly without explicitly saying they agree. To understand if Anna supports Brian's idea, focus on her comment about the training.
Instead of directly saying she likes the idea, she mentions that using real-life scenarios `makes the training more relevant`. This shows she agrees with Brian because she highlights a positive result of using his suggestion.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b572bd3d3e122e9a8ff9df.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b572bd3d3e122e9a8ff9df.md
index 8a8cccc7bb..c61a585c09 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b572bd3d3e122e9a8ff9df.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b572bd3d3e122e9a8ff9df.md
@@ -37,9 +37,9 @@ Consider what phrase you would use to suggest connecting with someone to discuss
`Touch base` means to make contact or to check in with someone, usually to discuss progress or updates. For example:
-- `Let’s touch base next week to see how the project is going.` - We'll talk again next week to discuss the project's progress.
+- `Let's touch base next week to see how the project is going.` - We'll talk again next week to discuss the project's progress.
-- `I’ll touch base with you later about the meeting.` - you'll contact this person later to talk about the meeting.
+- `I'll touch base with you later about the meeting.` - you'll contact this person later to talk about the meeting.
# --scene--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b57e127321d8524c7ddda7.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b57e127321d8524c7ddda7.md
index fb318c8bbf..1cb3999e59 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b57e127321d8524c7ddda7.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b57e127321d8524c7ddda7.md
@@ -35,11 +35,11 @@ A couple of days after the conversation with Anna, Brian sent this email to the
`Why Attend?`
-`As you know, our company has recently faced some security threats. We’re adding a section on phishing, using real-life scenarios to ensure everyone uses strong passwords and protects our data.`
+`As you know, our company has recently faced some security threats. We're adding a section on phishing, using real-life scenarios to ensure everyone uses strong passwords and protects our data.`
`Attendance:`
-`Attendance is mandatory. If you can’t attend, please inform your manager.`
+`Attendance is mandatory. If you can't attend, please inform your manager.`
`Looking forward to seeing you all.`
@@ -83,4 +83,4 @@ Brian doesn't mention a party.
# --explanation--
-Look at the email subject `Cybersecurity Training Session` and the first line `I want to update you on our next cybersecurity training session`. These show that Brian is informing the team about the upcoming session. There’s no mention of rescheduling, so the correct answer focuses on providing information about the training.
+Look at the email subject `Cybersecurity Training Session` and the first line `I want to update you on our next cybersecurity training session`. These show that Brian is informing the team about the upcoming session. There's no mention of rescheduling, so the correct answer focuses on providing information about the training.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b580cb9307d46113a8a637.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b580cb9307d46113a8a637.md
index fba928ee12..9865cdf2ce 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b580cb9307d46113a8a637.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b580cb9307d46113a8a637.md
@@ -35,11 +35,11 @@ A couple of days after the conversation with Anna, Brian sent this email to the
`Why Attend?`
-`As you know, our company has recently faced some security threats. We’re adding a section on phishing, using real-life scenarios to ensure everyone uses strong passwords and protects our data.`
+`As you know, our company has recently faced some security threats. We're adding a section on phishing, using real-life scenarios to ensure everyone uses strong passwords and protects our data.`
`Attendance:`
-`Attendance is mandatory. If you can’t attend, please inform your manager.`
+`Attendance is mandatory. If you can't attend, please inform your manager.`
`Looking forward to seeing you all.`
@@ -55,7 +55,7 @@ To know why the training session is important.
### --feedback--
-Although understanding the importance is useful, it doesn’t help you attend the meeting.
+Although understanding the importance is useful, it doesn't help you attend the meeting.
---
@@ -63,7 +63,7 @@ To bring a laptop to take notes during the session.
### --feedback--
-Bringing a laptop might be helpful, but it’s not essential information for attending the meeting.
+Bringing a laptop might be helpful, but it's not essential information for attending the meeting.
---
@@ -83,4 +83,4 @@ This is an important information, but it won't help you to attend the meeting. Q
# --explanation--
-To answer correctly, focus on the details needed to attend the meeting: the `date`, `time`, `topic`, and `location`. These are listed under `Details` in the email. While informing a manager is important if you can’t attend, it doesn't help you participate in the session itself.
+To answer correctly, focus on the details needed to attend the meeting: the `date`, `time`, `topic`, and `location`. These are listed under `Details` in the email. While informing a manager is important if you can't attend, it doesn't help you participate in the session itself.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b58252cb001966f564c19e.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b58252cb001966f564c19e.md
index f3937b181d..0f98762db2 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b58252cb001966f564c19e.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b58252cb001966f564c19e.md
@@ -35,11 +35,11 @@ A couple of days after the conversation with Anna, Brian sent this email to the
`Why Attend?`
-`As you know, our company has recently faced some security threats. We’re adding a section on phishing, using real-life scenarios to ensure everyone uses strong passwords and protects our data.`
+`As you know, our company has recently faced some security threats. We're adding a section on phishing, using real-life scenarios to ensure everyone uses strong passwords and protects our data.`
`Attendance:`
-`Attendance is mandatory. If you can’t attend, please inform your manager.`
+`Attendance is mandatory. If you can't attend, please inform your manager.`
`Looking forward to seeing you all.`
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b582d6978cff693c7b9455.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b582d6978cff693c7b9455.md
index a7ca1ea7ce..a2778d1e14 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b582d6978cff693c7b9455.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b582d6978cff693c7b9455.md
@@ -35,11 +35,11 @@ A couple of days after the conversation with Anna, Brian sent this email to the
`Why Attend?`
-`As you know, our company has recently faced some security threats. We’re adding a section on phishing, using real-life scenarios to ensure everyone uses strong passwords and protects our data.`
+`As you know, our company has recently faced some security threats. We're adding a section on phishing, using real-life scenarios to ensure everyone uses strong passwords and protects our data.`
`Attendance:`
-`Attendance is mandatory. If you can’t attend, please inform your manager.`
+`Attendance is mandatory. If you can't attend, please inform your manager.`
`Looking forward to seeing you all.`
@@ -83,4 +83,4 @@ Think about whether the email mentions anything about meetings or focuses on cyb
# --explanation--
-The email states, `We’re adding a section on phishing, using real-life scenarios.` This shows that the new section is focused on identifying phishing attempts, not scheduling meetings.
+The email states, `We're adding a section on phishing, using real-life scenarios.` This shows that the new section is focused on identifying phishing attempts, not scheduling meetings.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b583275950846a87e88de8.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b583275950846a87e88de8.md
index cff9863927..b9b8acba45 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b583275950846a87e88de8.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66b583275950846a87e88de8.md
@@ -35,11 +35,11 @@ A couple of days after the conversation with Anna, Brian sent this email to the
`Why Attend?`
-`As you know, our company has recently faced some security threats. We’re adding a section on phishing, using real-life scenarios to ensure everyone uses strong passwords and protects our data.`
+`As you know, our company has recently faced some security threats. We're adding a section on phishing, using real-life scenarios to ensure everyone uses strong passwords and protects our data.`
`Attendance:`
-`Attendance is mandatory. If you can’t attend, please inform your manager.`
+`Attendance is mandatory. If you can't attend, please inform your manager.`
`Looking forward to seeing you all.`
@@ -47,7 +47,7 @@ A couple of days after the conversation with Anna, Brian sent this email to the
`Brian`
-What should you do if you can’t attend the meeting?
+What should you do if you can't attend the meeting?
## --answers--
@@ -84,4 +84,4 @@ Reflect on whether the email mentions this as an option or gives different instr
# --explanation--
-The email says, `If you can’t attend, please inform your manager.` This clearly shows that the correct action is to inform your manager, not reschedule the meeting yourself.
+The email says, `If you can't attend, please inform your manager.` This clearly shows that the correct action is to inform your manager, not reschedule the meeting yourself.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66bbba46fff0ef451b701bcd.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66bbba46fff0ef451b701bcd.md
index 865b9759a4..d29fa0f85c 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66bbba46fff0ef451b701bcd.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66bbba46fff0ef451b701bcd.md
@@ -45,7 +45,7 @@ Yes, but only for a moment because she has her own problems.
### --feedback--
-Sarah doesn’t limit the time; she simply states that she is not busy.
+Sarah doesn't limit the time; she simply states that she is not busy.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66bbc147bc59c25e60e18aec.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66bbc147bc59c25e60e18aec.md
index ee9241e31c..f2f4e253a6 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66bbc147bc59c25e60e18aec.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66bbc147bc59c25e60e18aec.md
@@ -44,7 +44,7 @@ The live preview is working correctly.
### --feedback--
-If it were working correctly, Tom wouldn’t say that it isn’t showing.
+If it were working correctly, Tom wouldn't say that it isn't showing.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66bbf183427671a86f5ac25e.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66bbf183427671a86f5ac25e.md
index 24bb29a532..94a6c7425e 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66bbf183427671a86f5ac25e.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66bbf183427671a86f5ac25e.md
@@ -44,7 +44,7 @@ Not have this feature.
### --feedback--
-Pay attention to how Tom’s initial statement about the problem connects with his question, showing his surprise that the feature isn’t working as expected.
+Pay attention to how Tom's initial statement about the problem connects with his question, showing his surprise that the feature isn't working as expected.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4e019a6cbfa3210603aef.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4e019a6cbfa3210603aef.md
index 2cca4413cc..c675a49eb5 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4e019a6cbfa3210603aef.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4e019a6cbfa3210603aef.md
@@ -29,7 +29,7 @@ Place the following phrases in the correct spot:
`Lisa: We plan to develop a new app for real-time project collaboration. BLANK sound to you?`
-`Bob: Interesting! Who’s on your team?`
+`Bob: Interesting! Who's on your team?`
`Lisa: A couple of developers from our branch in Seattle, and a UX designer I've collaborated with before. BLANK we have any similar projects coming up here?`
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4ec1a03bb27643063f262.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4ec1a03bb27643063f262.md
index 4809d4e625..d1ad2f49cc 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4ec1a03bb27643063f262.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4ec1a03bb27643063f262.md
@@ -32,7 +32,7 @@ This is a contraction for `it is`, indicating who or what is involved in the act
### --feedback--
-This word is used to make the sentence negative, showing that the action isn’t happening.
+This word is used to make the sentence negative, showing that the action isn't happening.
# --explanation--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4efaa80afd0729ae471d1.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4efaa80afd0729ae471d1.md
index cf06529d4b..c55863c153 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4efaa80afd0729ae471d1.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4efaa80afd0729ae471d1.md
@@ -44,11 +44,11 @@ Remember the verb `to be`.
# --explanation--
-`Might` is used to express possibility. When Sarah says, `might not be running`, she’s suggesting that it’s possible the live server extension isn’t currently active or working. For example:
+`Might` is used to express possibility. When Sarah says, `might not be running`, she's suggesting that it's possible the live server extension isn't currently active or working. For example:
-- `The server might be down.` - It’s possible the server isn’t working.
+- `The server might be down.` - It's possible the server isn't working.
-- `She might not be available today.` - It’s possible she’s not free today.
+- `She might not be available today.` - It's possible she's not free today.
# --scene--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4f19f86b5f07a71ac7642.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4f19f86b5f07a71ac7642.md
index 7d795fbb9b..6ac0a66232 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4f19f86b5f07a71ac7642.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4f19f86b5f07a71ac7642.md
@@ -16,11 +16,11 @@ Listen to the audio and answer the question below.
## --text--
-What is the probable reason the live preview isn’t working?
+What is the probable reason the live preview isn't working?
## --answers--
-The live preview isn’t supported in Visual Studio Code.
+The live preview isn't supported in Visual Studio Code.
### --feedback--
@@ -40,7 +40,7 @@ Consider why Sarah would mention an issue if everything was working properly.
---
-Sarah doesn’t know what the problem is.
+Sarah doesn't know what the problem is.
### --feedback--
@@ -54,7 +54,7 @@ Think about whether Sarah suggested a possible cause for the issue.
Sarah mentions three things that will help you to help identify the issue.
-First, she says, `It should,` showing that the live preview is expected to work. Next, she states that it’s `not displaying,` which indicates a problem. Finally, she suggests a reason: `the live server extension might not be running.`
+First, she says, `It should,` showing that the live preview is expected to work. Next, she states that it's `not displaying,` which indicates a problem. Finally, she suggests a reason: `the live server extension might not be running.`
By connecting these clues, you can determine the probable reason Sarah provides for the issue.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4f338d6b658809576ae77.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4f338d6b658809576ae77.md
index 7c6b1aa2df..f13a7f41ff 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4f338d6b658809576ae77.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4f338d6b658809576ae77.md
@@ -26,7 +26,7 @@ Which option is the best answer to Sarah's question?
### --feedback--
-This response doesn’t address whether Tom is using the extension Sarah mentioned.
+This response doesn't address whether Tom is using the extension Sarah mentioned.
---
@@ -38,7 +38,7 @@ This response doesn’t address whether Tom is using the extension Sarah mention
# --explanation--
-Sarah is asking Tom if he’s using the live server extension, which is necessary for real-time previews in Visual Studio Code. Tom’s answer will help identify if this might be the cause of the problem. Select the option that answers Sarah's question.
+Sarah is asking Tom if he's using the live server extension, which is necessary for real-time previews in Visual Studio Code. Tom's answer will help identify if this might be the cause of the problem. Select the option that answers Sarah's question.
# --scene--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4f45289436884e6afc059.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4f45289436884e6afc059.md
index c03d740306..3a9346f3bc 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4f45289436884e6afc059.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4f45289436884e6afc059.md
@@ -28,9 +28,9 @@ These two words together mean to configure something so it works correctly.
# --explanation--
-`Set up right` means to configure something correctly so that it works as expected. If something isn’t `set up right`, it might not function properly. For example:
+`Set up right` means to configure something correctly so that it works as expected. If something isn't `set up right`, it might not function properly. For example:
-- `The printer isn’t working because it’s not set up right.` - The printer isn’t configured correctly.
+- `The printer isn't working because it's not set up right.` - The printer isn't configured correctly.
- `Make sure the software is set up right before you start using it.` - You need to configure the software correctly to ensure it works.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4f90997120794595abd5c.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4f90997120794595abd5c.md
index 2ed0f408a8..39e59c36ba 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4f90997120794595abd5c.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4f90997120794595abd5c.md
@@ -21,7 +21,7 @@ Which sentence correctly uses `pop up`?
### --feedback--
-Think about whether `pop up` describes something that happens automatically, or if it’s something you actively do.
+Think about whether `pop up` describes something that happens automatically, or if it's something you actively do.
---
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4fd010695b5a316201d03.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4fd010695b5a316201d03.md
index f564cf3f65..12bab43332 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4fd010695b5a316201d03.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4fd010695b5a316201d03.md
@@ -46,7 +46,7 @@ These two words together mean something suddenly appearing on the screen. The fi
`IntelliJ IDEA` is a popular Integrated Development Environment (IDE) used by developers to write, test, and debug code. It is known for its powerful features, including `auto-completion`, which helps you code faster by suggesting possible completions as you type.
-When Tom says that `auto-completion isn’t popping up`, he means that the feature, which normally suggests code as you type, isn’t appearing on the screen like it should.
+When Tom says that `auto-completion isn't popping up`, he means that the feature, which normally suggests code as you type, isn't appearing on the screen like it should.
# --scene--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4ffe51866ecadb48304b9.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4ffe51866ecadb48304b9.md
index ed6d30065a..223088f40a 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4ffe51866ecadb48304b9.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c4ffe51866ecadb48304b9.md
@@ -6,7 +6,7 @@ dashedName: task-122
---
+Tom: Also, in IntelliJ IDEA, the code auto-completion isn't popping up. Isn't it automatic? -->
# --instructions--
@@ -20,7 +20,7 @@ Listen to the audio and complete the sentence below.
## --blanks--
-`Isn’t it`
+`Isn't it`
### --feedback--
@@ -30,11 +30,11 @@ A tag question using the contraction of `is not` followed by a pronoun. The firs
A `tag question` is a short question added to the end of a sentence to confirm or check something. It's often used when the speaker expects the listener to agree with them. For example:
-- `It’s a nice day, isn’t it?` - The speaker expects that the listener will agree that it’s a nice day.
+- `It's a nice day, isn't it?` - The speaker expects that the listener will agree that it's a nice day.
-- `They are coming to the meeting, aren’t they?` - The speaker expects that the listener will agree that they are coming to the meeting.
+- `They are coming to the meeting, aren't they?` - The speaker expects that the listener will agree that they are coming to the meeting.
-When Tom says, `Isn’t it automatic?`, he is asking for confirmation that the auto-completion should happen automatically.
+When Tom says, `Isn't it automatic?`, he is asking for confirmation that the auto-completion should happen automatically.
# --scene--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c5012e6643c2b32b3af0be.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c5012e6643c2b32b3af0be.md
index e64bc75442..620bea5497 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c5012e6643c2b32b3af0be.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c5012e6643c2b32b3af0be.md
@@ -6,7 +6,7 @@ dashedName: task-123
---
+Tom: Also, in IntelliJ IDEA, the code auto-completion isn't popping up. Isn't it automatic? -->
# --instructions--
@@ -16,7 +16,7 @@ Listen to the audio and answer the question below.
## --text--
-Why does Tom ask `Isn’t it automatic?`
+Why does Tom ask `Isn't it automatic?`
## --answers--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c507bef7c69ac73fbc82cc.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c507bef7c69ac73fbc82cc.md
index 5d377d7ee1..b9da55a2cf 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c507bef7c69ac73fbc82cc.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c507bef7c69ac73fbc82cc.md
@@ -6,7 +6,7 @@ dashedName: task-124
---
+Tom: The code auto-completion isn't popping up. Isn't it automatic? -->
@@ -30,9 +30,9 @@ Which option is the best answer to Tom's question?
### --feedback--
-This options is wrong because it contradicts itself. It starts saying `It is`, confirming Tom’s question, but then it adds that auto-completion needs to be enabled manually every time.
+This options is wrong because it contradicts itself. It starts saying `It is`, confirming Tom's question, but then it adds that auto-completion needs to be enabled manually every time.
-This doesn’t make sense — if something is automatic, you wouldn’t need to enable it manually.
+This doesn't make sense — if something is automatic, you wouldn't need to enable it manually.
## --video-solution--
@@ -40,7 +40,7 @@ This doesn’t make sense — if something is automatic, you wouldn’t need to
# --explanation--
-Tom says, `The code auto-completion isn't popping up. Isn’t it automatic?` This means he expects auto-completion to work automatically.
+Tom says, `The code auto-completion isn't popping up. Isn't it automatic?` This means he expects auto-completion to work automatically.
A good response would either confirm that auto-completion should be automatic or explain why it might not be working.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c611f2d1e400c2f41ad5d9.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c611f2d1e400c2f41ad5d9.md
index fd842b9866..3f35eea8a3 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c611f2d1e400c2f41ad5d9.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c611f2d1e400c2f41ad5d9.md
@@ -42,7 +42,7 @@ In the `Present Simple` tense, the negative form is created using `doesn't` or `
- Use `isn't` with forms of `to be` to show that something is not true, like `isn't set up.`
-In this sentence, you’ll need both `doesn't` and `isn't` to correctly describe why the feature isn’t working as expected.
+In this sentence, you'll need both `doesn't` and `isn't` to correctly describe why the feature isn't working as expected.
# --scene--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c613a4d11b69cdd746b5ed.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c613a4d11b69cdd746b5ed.md
index 46f8651fd9..075b4fed84 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c613a4d11b69cdd746b5ed.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c613a4d11b69cdd746b5ed.md
@@ -54,13 +54,13 @@ Pay attention to what Sarah says after `it doesn't work if...`.
# --explanation--
-When Listening to Sarah’s, pay attention to the word `if`. This word often introduces the cause of a problem, explaining what needs to happen for something else to occur.
+When Listening to Sarah's, pay attention to the word `if`. This word often introduces the cause of a problem, explaining what needs to happen for something else to occur.
-After finding `if`, identify the part of the sentence that describes what happens when that condition isn’t met (the effect). In Sarah’s sentence:
+After finding `if`, identify the part of the sentence that describes what happens when that condition isn't met (the effect). In Sarah's sentence:
-- **Effect:** `The auto-completion doesn’t work`.
+- **Effect:** `The auto-completion doesn't work`.
-- **Cause** introduced by `if`: `If the project isn’t set up correctly`.
+- **Cause** introduced by `if`: `If the project isn't set up correctly`.
Understanding this relationship helps you explain problems and solutions clearly.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c616d281199cda967c144d.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c616d281199cda967c144d.md
index 0d8514e8ec..1c6799b09d 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c616d281199cda967c144d.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c616d281199cda967c144d.md
@@ -22,11 +22,11 @@ Tom is not sure he checked the settings and wants to check it again. How can he
## --answers--
-`I don’t think the settings matter.`
+`I don't think the settings matter.`
### --feedback--
-The correct answer would say that he isn’t sure if he has checked the settings, so he needs to check them again.
+The correct answer would say that he isn't sure if he has checked the settings, so he needs to check them again.
---
@@ -38,11 +38,11 @@ The correct answer would say that he isn’t sure if he has checked the settings
# --explanation--
-Sometimes, when you’re not sure if you’ve done something, it’s important to say that you’re unsure. For example:
+Sometimes, when you're not sure if you've done something, it's important to say that you're unsure. For example:
- `I'm not sure this is the correct settings.` - You are unsure whether the settings are according to what is expected or not.
-The correct answer will reflect Tom’s uncertainty and his plan to check the settings again.
+The correct answer will reflect Tom's uncertainty and his plan to check the settings again.
# --scene--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c6184eda8a8be150b1a0b4.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c6184eda8a8be150b1a0b4.md
index 9d0529ccb8..bcdb2dece2 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c6184eda8a8be150b1a0b4.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c6184eda8a8be150b1a0b4.md
@@ -32,7 +32,7 @@ These two words together mean that something is necessary or required.
### --feedback--
-This verb means to look at something carefully to find out if it’s correct or working properly.
+This verb means to look at something carefully to find out if it's correct or working properly.
---
@@ -46,7 +46,7 @@ This word means to do something one more time.
`Have to` is used to express that something is necessary or required. It indicates that there is no choice but to do something. For example:
-- `You have to save your changes before closing the program.` - This means it’s necessary to save changes before closing the program.
+- `You have to save your changes before closing the program.` - This means it's necessary to save changes before closing the program.
When Tom says, `I'll have to check again`, he is stating that it's necessary for him to check the settings one more time, suggesting he's not sure about it.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c6193e7546c4e51cbf64c9.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c6193e7546c4e51cbf64c9.md
index 5193a4b374..c9f5737a33 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c6193e7546c4e51cbf64c9.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c6193e7546c4e51cbf64c9.md
@@ -6,7 +6,7 @@ dashedName: task-130
---
+Tom: And in Eclipse, it's not showing the Git tools. -->
# --instructions--
@@ -36,9 +36,9 @@ This word means that something is supposed to be visible. It ends with `-ing`.
# --explanation--
-`It’s not showing` is used to explain that something expected to appear on the screen isn’t visible. For example:
+`It's not showing` is used to explain that something expected to appear on the screen isn't visible. For example:
-- `The image isn’t showing on the screen.` - The image is supposed to be there, but it’s not visible.
+- `The image isn't showing on the screen.` - The image is supposed to be there, but it's not visible.
# --scene--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c61a0197d7e7e87191e033.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c61a0197d7e7e87191e033.md
index 508b0dc14f..9b343d92f3 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c61a0197d7e7e87191e033.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c61a0197d7e7e87191e033.md
@@ -6,7 +6,7 @@ dashedName: task-131
---
+Tom: And in Eclipse, it's not showing the Git tools. -->
# --instructions--
@@ -20,7 +20,7 @@ What problem is Tom facing now?
## --answers--
-He doesn’t know how to use Git tools.
+He doesn't know how to use Git tools.
### --feedback--
@@ -28,11 +28,11 @@ Pay attention to the part where Tom talks about something that should be visible
---
-He can’t see the Git tools in Eclipse.
+He can't see the Git tools in Eclipse.
---
-He can’t open the Eclipse software.
+He can't open the Eclipse software.
### --feedback--
@@ -40,7 +40,7 @@ Pay attention to the part where Tom talks about something that should be visible
---
-He doesn’t have Git installed.
+He doesn't have Git installed.
### --feedback--
@@ -52,7 +52,7 @@ Pay attention to the part where Tom talks about something that should be visible
# --explanation--
-Tom says, `it’s not showing the Git tools,` which gives important clues to identify his problem.
+Tom says, `it's not showing the Git tools,` which gives important clues to identify his problem.
The key phrase is `not showing`, which points to a visibility issue rather than a problem with knowledge or installation.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c61a57f6eca6e9fb0f61d7.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c61a57f6eca6e9fb0f61d7.md
index 54cccc567f..106c722948 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c61a57f6eca6e9fb0f61d7.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c61a57f6eca6e9fb0f61d7.md
@@ -6,7 +6,7 @@ dashedName: task-132
---
+Tom: And in Eclipse, it's not showing the Git tools. Are they built-in? -->
# --instructions--
@@ -16,7 +16,7 @@ Listen to the audio and complete the sentence below.
## --sentence--
-`And in Eclipse, it’s not showing the Git tools. Are they BLANK?`
+`And in Eclipse, it's not showing the Git tools. Are they BLANK?`
## --blanks--
@@ -30,7 +30,7 @@ Something has been included as part of a larger system or structure from the sta
`Built-in` refers to features or tools that are included as part of a software program or device from the start, without needing to be added or installed separately.
-When something is `built-in`, it’s already there and ready to use. For example:
+When something is `built-in`, it's already there and ready to use. For example:
- `This laptop has a built-in camera.` - The camera is included as part of the laptop.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c61dee09da09f603fa3dbc.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c61dee09da09f603fa3dbc.md
index 9aa50e0fc9..6ed79263c4 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c61dee09da09f603fa3dbc.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c61dee09da09f603fa3dbc.md
@@ -6,7 +6,7 @@ dashedName: task-133
---
+Tom: It's not showing the Git tools. Are they built-in? -->
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c62046cf3df2fe7cf92230.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c62046cf3df2fe7cf92230.md
index 93318ded00..813f4789c4 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c62046cf3df2fe7cf92230.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c62046cf3df2fe7cf92230.md
@@ -20,7 +20,7 @@ According to Sarah, in which case won't the Git tools be visible?
## --answers--
-If the project isn’t saved correctly.
+If the project isn't saved correctly.
### --feedback--
@@ -28,7 +28,7 @@ Pay attention to what Sarah says after `but they're not visible if...`.
---
-If Eclipse isn’t updated to the latest version.
+If Eclipse isn't updated to the latest version.
### --feedback--
@@ -36,11 +36,11 @@ Pay attention to what Sarah says after `but they're not visible if...`.
---
-If the project isn’t linked to Git.
+If the project isn't linked to Git.
---
-If the Git tools aren’t installed manually.
+If the Git tools aren't installed manually.
### --feedback--
@@ -58,7 +58,7 @@ After `but`, Sarah mentions `they're not visible`, followed by the condition `if
This tells you that the tools are hidden unless the project is connected to Git.
-The phrase `if the project isn't` is a key marker that introduces the condition under which the Git tools won’t appear.
+The phrase `if the project isn't` is a key marker that introduces the condition under which the Git tools won't appear.
In Sarah's sentence, she uses `they're not` to explain that the Git tools are not visible, and `isn't` to say that the project is not linked to Git.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c6213241b74d023adcf637.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c6213241b74d023adcf637.md
index 6eebd117d0..4350295d82 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c6213241b74d023adcf637.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c6213241b74d023adcf637.md
@@ -34,7 +34,7 @@ When forming questions with the verb `to be`, the usual word order of the subjec
- `Is your project connected to Git?` (Question)
-In Sarah’s sentence, she uses this inversion to ask Tom if his project is connected to Git in Eclipse.
+In Sarah's sentence, she uses this inversion to ask Tom if his project is connected to Git in Eclipse.
# --scene--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c62515cf6ae70e34eb361d.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c62515cf6ae70e34eb361d.md
index a62104b0ec..666757cb56 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c62515cf6ae70e34eb361d.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c62515cf6ae70e34eb361d.md
@@ -16,11 +16,11 @@ Listen to the audio and answer the question below.
## --text--
-Tom believes his project should be connected to Git, but he isn’t completely sure. What should he answer Sarah?
+Tom believes his project should be connected to Git, but he isn't completely sure. What should he answer Sarah?
## --answers--
-`It’s supposed to be.`
+`It's supposed to be.`
---
@@ -36,11 +36,11 @@ Think about whether Tom is completely sure about the connection.
# --explanation--
-Sometimes, when you're not completely sure about something, but you believe it should be true, you can use the phrase `It’s supposed to` + verb.
+Sometimes, when you're not completely sure about something, but you believe it should be true, you can use the phrase `It's supposed to` + verb.
-This will express that something is expected to be a certain way, even if you haven’t confirmed it yet. For example:
+This will express that something is expected to be a certain way, even if you haven't confirmed it yet. For example:
-- `The update is supposed to fix the bug.` - This means you expect the update to fix the bug, but you haven’t confirmed it yet.
+- `The update is supposed to fix the bug.` - This means you expect the update to fix the bug, but you haven't confirmed it yet.
# --scene--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c625e03abcb711ca38ba5f.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c625e03abcb711ca38ba5f.md
index e6ae198ef7..6ecd32ea6a 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c625e03abcb711ca38ba5f.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c625e03abcb711ca38ba5f.md
@@ -32,13 +32,13 @@ These two words start the sentence and are used to describe something that is ha
### --feedback--
-An adjective that describes the feeling of being upset or annoyed because something isn’t working as expected. It ends with `-ing`.
+An adjective that describes the feeling of being upset or annoyed because something isn't working as expected. It ends with `-ing`.
# --explanation--
`This is` is a simple way to start a sentence when describing something.
-`Frustrating` is an adjective that describes a feeling of being upset or annoyed because something isn’t working as expected. For example:
+`Frustrating` is an adjective that describes a feeling of being upset or annoyed because something isn't working as expected. For example:
- `This is confusing.` - The situation is hard to understand.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c62747744dc4178785207d.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c62747744dc4178785207d.md
index 5c1cb4919d..dc90df92b0 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c62747744dc4178785207d.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c62747744dc4178785207d.md
@@ -20,7 +20,7 @@ Why is Tom frustrated?
## --answers--
-Because he doesn’t know how to code.
+Because he doesn't know how to code.
### --feedback--
@@ -28,7 +28,7 @@ Tom's frustration is not related to his coding skills.
---
-Because he didn’t save his project.
+Because he didn't save his project.
### --feedback--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c628215739f51ac74cb5cc.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c628215739f51ac74cb5cc.md
index f182ad1168..9b4afa7617 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c628215739f51ac74cb5cc.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c628215739f51ac74cb5cc.md
@@ -30,11 +30,11 @@ This word introduces the condition or situation that causes something to happen.
`when` is used here to describe a specific condition or situation that causes something to happen.
-In Sarah’s sentence, `when` introduces the condition where the IDEs become tricky: `if they’re not set up properly`. For example:
+In Sarah's sentence, `when` introduces the condition where the IDEs become tricky: `if they're not set up properly`. For example:
- `The program crashes when it runs out of memory.` - The condition of running out of memory causes the program to crash.
-- `The printer only works when it’s plugged in.` - The condition of being plugged in allows the printer to work.
+- `The printer only works when it's plugged in.` - The condition of being plugged in allows the printer to work.
In both cases, `when` is used to explain the situation in which something occurs.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c6293f674a0a1e960027c3.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c6293f674a0a1e960027c3.md
index cf4c22aa7c..c9a8a3d164 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c6293f674a0a1e960027c3.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c6293f674a0a1e960027c3.md
@@ -41,7 +41,7 @@ The IDEs are tricky because they lack built-in tools.
### --feedback--
-Reflect on whether Sarah’s explanation was about built-in tools or the setup of the IDEs.
+Reflect on whether Sarah's explanation was about built-in tools or the setup of the IDEs.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c62b0c65018625985a897d.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c62b0c65018625985a897d.md
index 60dd081e30..6fe398be0c 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c62b0c65018625985a897d.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c62b0c65018625985a897d.md
@@ -26,7 +26,7 @@ Tom wants to accept Sarah's offer. How could he reply to her?
---
-`I’m not sure if that will help.`
+`I'm not sure if that will help.`
### --feedback--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c637ce17705151c64f9059.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c637ce17705151c64f9059.md
index e0451e2128..643e541962 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c637ce17705151c64f9059.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c637ce17705151c64f9059.md
@@ -29,11 +29,11 @@ Place the following phrases in the correct spot:
`Sarah: It should, but BLANK because the live server extension might not be running. Are you using that extension for real-time previews?`
-`Tom: I think we are, but maybe BLANK right. Also, in IntelliJ IDEA, the code auto-completion isn't popping up. Isn’t it automatic?`
+`Tom: I think we are, but maybe BLANK right. Also, in IntelliJ IDEA, the code auto-completion isn't popping up. Isn't it automatic?`
`Sarah: It usually is, but it doesn't work if the project isn't set up right. Have you checked the settings?`
-`Tom: I'll have to check again. And in Eclipse, it’s not showing the Git tools. BLANK built in?`
+`Tom: I'll have to check again. And in Eclipse, it's not showing the Git tools. BLANK built in?`
`Sarah: Yes, they are, but BLANK if the project isn't linked to Git. Is your project connected to Git in Eclipse?`
@@ -57,7 +57,7 @@ This phrase is used when checking if something should be working automatically.
### --feedback--
-This phrase indicates that something expected to be visible on the screen isn’t appearing.
+This phrase indicates that something expected to be visible on the screen isn't appearing.
---
@@ -65,7 +65,7 @@ This phrase indicates that something expected to be visible on the screen isn’
### --feedback--
-This phrase explains that something isn’t arranged or configured correctly.
+This phrase explains that something isn't arranged or configured correctly.
---
@@ -81,7 +81,7 @@ This phrase is used to ask if something, like the Git tools, is included or buil
### --feedback--
-This phrase indicates that something, like the Git tools, can’t be seen on the screen.
+This phrase indicates that something, like the Git tools, can't be seen on the screen.
---
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c63db09b73ad6539eeee61.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c63db09b73ad6539eeee61.md
index 7078fc94a0..4bb912d098 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c63db09b73ad6539eeee61.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c63db09b73ad6539eeee61.md
@@ -27,17 +27,17 @@ Sarah decided to e-mail and document their conversation:
`2. IntelliJ IDEA - Auto-Completion:`
-`Double-check your project settings. If auto-completion isn’t working, the project might not be set up right. Go to your project settings and verify that all necessary plugins are enabled.`
+`Double-check your project settings. If auto-completion isn't working, the project might not be set up right. Go to your project settings and verify that all necessary plugins are enabled.`
`3. Eclipse - Git Tools:`
-`The Git tools are built-in, but they won’t be visible unless your project is linked to Git. Make sure your project is connected to the Git repository.`
+`The Git tools are built-in, but they won't be visible unless your project is linked to Git. Make sure your project is connected to the Git repository.`
`Let me know if you need any more help, or if you'd like to go through a detailed walkthrough together.`
`Best, Sarah`
-What should Tom do if the Live Preview isn’t displaying in Visual Studio Code?
+What should Tom do if the Live Preview isn't displaying in Visual Studio Code?
## --answers--
@@ -45,7 +45,7 @@ Restart Visual Studio Code and check the project settings.
### --feedback--
-Consider whether restarting the program is Sarah’s suggested solution or if she focuses more on project settings.
+Consider whether restarting the program is Sarah's suggested solution or if she focuses more on project settings.
---
@@ -65,7 +65,7 @@ Switch to a different IDE to see if the issue persists. She prefers Eclipse.
### --feedback--
-Reflect on whether Sarah’s advice is about changing IDEs or troubleshooting within Visual Studio Code.
+Reflect on whether Sarah's advice is about changing IDEs or troubleshooting within Visual Studio Code.
## --video-solution--
@@ -73,8 +73,8 @@ Reflect on whether Sarah’s advice is about changing IDEs or troubleshooting wi
# --explanation--
-To find the answer, focus on the section of Sarah’s email labeled `1. Visual Studio Code - Live preview.`
+To find the answer, focus on the section of Sarah's email labeled `1. Visual Studio Code - Live preview.`
-In this part, she explains that if the Live Preview isn’t displaying, Tom should first make sure the live server extension is installed and running.
+In this part, she explains that if the Live Preview isn't displaying, Tom should first make sure the live server extension is installed and running.
-Then, if it’s still not working, she advises checking the project settings to ensure everything is correctly set up for real-time previews.
+Then, if it's still not working, she advises checking the project settings to ensure everything is correctly set up for real-time previews.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c63fda0e11806e78090f36.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c63fda0e11806e78090f36.md
index cd6ca7c8a9..b010db7d26 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c63fda0e11806e78090f36.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c63fda0e11806e78090f36.md
@@ -27,11 +27,11 @@ Sarah decided to e-mail and document their conversation:
`2. IntelliJ IDEA - Auto-Completion:`
-`Double-check your project settings. If auto-completion isn’t working, the project might not be set up right. Go to your project settings and verify that all necessary plugins are enabled.`
+`Double-check your project settings. If auto-completion isn't working, the project might not be set up right. Go to your project settings and verify that all necessary plugins are enabled.`
`3. Eclipse - Git Tools:`
-`The Git tools are built-in, but they won’t be visible unless your project is linked to Git. Make sure your project is connected to the Git repository.`
+`The Git tools are built-in, but they won't be visible unless your project is linked to Git. Make sure your project is connected to the Git repository.`
`Let me know if you need any more help, or if you'd like to go through a detailed walkthrough together.`
@@ -41,7 +41,7 @@ Why might auto-completion not work in IntelliJ IDEA, according to Sarah's email?
## --answers--
-The live server extension isn’t installed.
+The live server extension isn't installed.
### --feedback--
@@ -53,7 +53,7 @@ The Git tools are not visible.
### --feedback--
-Consider whether the visibility of Git tools affects auto-completion, or if it’s more about the project setup.
+Consider whether the visibility of Git tools affects auto-completion, or if it's more about the project setup.
---
@@ -75,4 +75,4 @@ Reflect on whether Sarah mentioned file corruption as a reason for auto-completi
Pay close attention to the section labeled `2. IntelliJ IDEA - Auto-Completion.`
-In this part, Sarah mentions that if auto-completion isn’t working, the problem is likely due to the project not being set up correctly. She suggests checking the project settings and verifying that all necessary plugins are enabled.
+In this part, Sarah mentions that if auto-completion isn't working, the problem is likely due to the project not being set up correctly. She suggests checking the project settings and verifying that all necessary plugins are enabled.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c6409f492e5e71621d06b8.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c6409f492e5e71621d06b8.md
index e4b2db4d62..d46dd94d8d 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c6409f492e5e71621d06b8.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c6409f492e5e71621d06b8.md
@@ -27,11 +27,11 @@ Sarah decided to e-mail and document their conversation:
`2. IntelliJ IDEA - Auto-Completion:`
-`Double-check your project settings. If auto-completion isn’t working, the project might not be set up right. Go to your project settings and verify that all necessary plugins are enabled.`
+`Double-check your project settings. If auto-completion isn't working, the project might not be set up right. Go to your project settings and verify that all necessary plugins are enabled.`
`3. Eclipse - Git Tools:`
-`The Git tools are built-in, but they won’t be visible unless your project is linked to Git. Make sure your project is connected to the Git repository.`
+`The Git tools are built-in, but they won't be visible unless your project is linked to Git. Make sure your project is connected to the Git repository.`
`Let me know if you need any more help, or if you'd like to go through a detailed walkthrough together.`
@@ -41,7 +41,7 @@ What does Sarah say about the Git tools in Eclipse?
## --answers--
-They are built-in but won’t be visible unless your project is linked to Git.
+They are built-in but won't be visible unless your project is linked to Git.
---
@@ -61,7 +61,7 @@ Consider if Sarah said the tools are automatically visible or if she mentioned a
---
-They only work if you’re using IntelliJ IDEA.
+They only work if you're using IntelliJ IDEA.
### --feedback--
@@ -75,4 +75,4 @@ Reflect on whether Sarah was talking about Eclipse or if this applies to a diffe
Sarah provides instructions specifically about the Git tools in Eclipse under the section `3. Eclipse - Git Tools.`
-She mentions that the tools are built-in, but they won’t be visible unless the project is linked to Git.
+She mentions that the tools are built-in, but they won't be visible unless the project is linked to Git.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c640e2f81416727a42fd4c.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c640e2f81416727a42fd4c.md
index 6f49f93d04..c77c188650 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c640e2f81416727a42fd4c.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-describe-places-and-events/66c640e2f81416727a42fd4c.md
@@ -27,11 +27,11 @@ Sarah decided to e-mail and document their conversation:
`2. IntelliJ IDEA - Auto-Completion:`
-`Double-check your project settings. If auto-completion isn’t working, the project might not be set up right. Go to your project settings and verify that all necessary plugins are enabled.`
+`Double-check your project settings. If auto-completion isn't working, the project might not be set up right. Go to your project settings and verify that all necessary plugins are enabled.`
`3. Eclipse - Git Tools:`
-`The Git tools are built-in, but they won’t be visible unless your project is linked to Git. Make sure your project is connected to the Git repository.`
+`The Git tools are built-in, but they won't be visible unless your project is linked to Git. Make sure your project is connected to the Git repository.`
`Let me know if you need any more help, or if you'd like to go through a detailed walkthrough together.`
@@ -53,7 +53,7 @@ She suggests that Tom should hire someone else to fix the issues.
### --feedback--
-Consider if Sarah’s tone is more supportive or if she is suggesting an alternative solution.
+Consider if Sarah's tone is more supportive or if she is suggesting an alternative solution.
---
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-activities/67325a5443667173c717856f.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-activities/67325a5443667173c717856f.md
index b1682fdb15..b0bcc66654 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-activities/67325a5443667173c717856f.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-activities/67325a5443667173c717856f.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-111
---
-
+
# --instructions--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-activities/67325bae5d23157c74091944.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-activities/67325bae5d23157c74091944.md
index ce180fe911..f51c60f446 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-activities/67325bae5d23157c74091944.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-activities/67325bae5d23157c74091944.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-112
---
-
+
# --instructions--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-activities/67326cb0e9a72b69d6efd417.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-activities/67326cb0e9a72b69d6efd417.md
index 949d86af71..d4b8bda063 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-activities/67326cb0e9a72b69d6efd417.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-activities/67326cb0e9a72b69d6efd417.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-123
---
-
+
# --instructions--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-activities/67326fb4b198b97e4bcf4a69.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-activities/67326fb4b198b97e4bcf4a69.md
index 027f1acbbf..4acd87ae3e 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-activities/67326fb4b198b97e4bcf4a69.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-activities/67326fb4b198b97e4bcf4a69.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-125
---
-
+
# --instructions--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-activities/6732800300eff4f49912e30f.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-activities/6732800300eff4f49912e30f.md
index 6b57edd965..305ba737ce 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-activities/6732800300eff4f49912e30f.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-activities/6732800300eff4f49912e30f.md
@@ -17,7 +17,7 @@ Read the text and answer the question below.
Linda posted an update about her team's development process:
-`Over the past year, we've been focusing on user feedback more than ever, and it's really changed our approach to development. Instead of just tackling technical issues, we're now looking at everything from the user’s perspective.`
+`Over the past year, we've been focusing on user feedback more than ever, and it's really changed our approach to development. Instead of just tackling technical issues, we're now looking at everything from the user's perspective.`
`Last month, we rolled out a major update inspired by user feedback, and the response has been amazing. Now, rather than just reacting to issues, we're proactively making improvements based on what our users tell us.`
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/66609a1199ddd03548c45423.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/66609a1199ddd03548c45423.md
index 80fe5ba69d..ae1618326d 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/66609a1199ddd03548c45423.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/66609a1199ddd03548c45423.md
@@ -1,8 +1,8 @@
---
id: 66609a1199ddd03548c45423
-title: "Діалог 1: я Том"
+title: "Dialogue 1: A Debugging Session Recap"
challengeType: 21
-dashedName: dialogue-1-im-tom
+dashedName: dialogue-1-a-debugging-session-recap
---
# --description--
@@ -17,42 +17,198 @@ dashedName: dialogue-1-im-tom
```json
{
- "setup": {
- "background": "chaos.png",
- "characters": [
- {
- "character": "David",
- "position": {"x":50,"y":80,"z":8},
- "opacity": 0
- }
- ],
- "audio": {
- "filename": "1.1-1.mp3",
- "startTime": 1,
- "startTimestamp": 5.7,
- "finishTimestamp": 6.48
- }
- },
- "commands": [
- {
- "character": "David",
- "opacity": 1,
- "startTime": 0
- },
- {
- "character": "David",
- "startTime": 1,
- "finishTime": 0.78,
- "dialogue": {
- "text": "I'm Tom.",
- "align": "center"
- }
- },
- {
- "character": "Tom",
- "opacity": 0,
- "startTime": 1.28
- }
- ]
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "Lisa",
+ "position": { "x": -25, "y": 0, "z": 1 }
+ },
+ {
+ "character": "James",
+ "position": { "x": 125, "y": 0, "z": 1 }
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1
+ },
+ "alwaysShowDialogue": true
+ },
+ "commands": [
+ {
+ "character": "Lisa",
+ "position": { "x": 25, "y": 0, "z": 1 },
+ "startTime": 0
+ },
+ {
+ "character": "James",
+ "position": { "x": 70, "y": 0, "z": 1 },
+ "startTime": 0.5
+ },
+ {
+ "character": "Lisa",
+ "startTime": 1,
+ "finishTime": 4.04,
+ "dialogue": {
+ "text": "Hey, James. Did you find that bug we were stuck on yesterday?",
+ "align": "left"
+ }
+ },
+ {
+ "character": "James",
+ "startTime": 4.46,
+ "finishTime": 9.52,
+ "dialogue": {
+ "text": "Yes, I did. It was quite a hunt. First, I checked the recent changes we made to the code.",
+ "align": "right"
+ }
+ },
+ {
+ "character": "Lisa",
+ "startTime": 9.86,
+ "finishTime": 10.86,
+ "dialogue": {
+ "text": "What did you find there?",
+ "align": "left"
+ }
+ },
+ {
+ "character": "James",
+ "startTime": 11.14,
+ "finishTime": 14.86,
+ "dialogue": {
+ "text": "Nothing at first. Then I reviewed the error logs more carefully.",
+ "align": "right"
+ }
+ },
+ {
+ "character": "James",
+ "startTime": 15.24,
+ "finishTime": 17.12,
+ "dialogue": {
+ "text": "That's when I noticed something odd.",
+ "align": "right"
+ }
+ },
+ {
+ "character": "Lisa",
+ "startTime": 17.42,
+ "finishTime": 17.96,
+ "dialogue": {
+ "text": "What was it?",
+ "align": "left"
+ }
+ },
+ {
+ "character": "James",
+ "startTime": 18.3,
+ "finishTime": 20.78,
+ "dialogue": {
+ "text": "The system wasn't connecting to the database properly.",
+ "align": "right"
+ }
+ },
+ {
+ "character": "James",
+ "startTime": 21.16,
+ "finishTime": 26.36,
+ "dialogue": {
+ "text": "After that, I realized we didn't update the database credentials after the last security patch.",
+ "align": "right"
+ }
+ },
+ {
+ "character": "Lisa",
+ "startTime": 26.86,
+ "finishTime": 29.48,
+ "dialogue": {
+ "text": "Ah, so the credentials were the issue. Did you fix them?",
+ "align": "left"
+ }
+ },
+ {
+ "character": "James",
+ "startTime": 29.48,
+ "finishTime": 33.78,
+ "dialogue": {
+ "text": "Yes, I updated the credentials and the connection was finally successful.",
+ "align": "right"
+ }
+ },
+ {
+ "character": "James",
+ "startTime": 34.1,
+ "finishTime": 35.58,
+ "dialogue": {
+ "text": "The app started working again.",
+ "align": "right"
+ }
+ },
+ {
+ "character": "Lisa",
+ "startTime": 35.96,
+ "finishTime": 37.94,
+ "dialogue": {
+ "text": "Great job. Wasn't it stressful though?",
+ "align": "left"
+ }
+ },
+ {
+ "character": "James",
+ "startTime": 38.38,
+ "finishTime": 42.66,
+ "dialogue": {
+ "text": "A bit, but solving problems like these is what makes our job interesting, right?",
+ "align": "right"
+ }
+ },
+ {
+ "character": "Lisa",
+ "startTime": 43.22,
+ "finishTime": 45.58,
+ "dialogue": {
+ "text": "Absolutely. Thanks for handling it, James.",
+ "align": "left"
+ }
+ },
+ {
+ "character": "Lisa",
+ "startTime": 46.12,
+ "finishTime": 47.82,
+ "dialogue": {
+ "text": "Did anything else come up while you were debugging?",
+ "align": "left"
+ }
+ },
+ {
+ "character": "James",
+ "startTime": 48.3,
+ "finishTime": 52.6,
+ "dialogue": {
+ "text": "Not really. Everything else was running smoothly once the database issue was fixed.",
+ "align": "right"
+ }
+ },
+ {
+ "character": "Lisa",
+ "startTime": 53.12,
+ "finishTime": 57,
+ "dialogue": {
+ "text": "Perfect. Let's make sure we double check credentials after security updates in the future.",
+ "align": "left"
+ }
+ },
+ {
+ "character": "James",
+ "position": { "x": 125, "y": 0, "z": 1 },
+ "startTime": 57.5
+ },
+ {
+ "character": "Lisa",
+ "position": { "x": -25, "y": 0, "z": 1 },
+ "startTime": 58
+ }
+ ]
}
```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6704f438e6e9120d5a1274c6.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6704f438e6e9120d5a1274c6.md
new file mode 100644
index 0000000000..e6326dbc47
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6704f438e6e9120d5a1274c6.md
@@ -0,0 +1,106 @@
+---
+id: 6704f438e6e9120d5a1274c6
+title: Task 1
+challengeType: 19
+dashedName: task-1
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What does the word `bug` mean in Lisa's question?
+
+## --answers--
+
+A small insect
+
+### --feedback--
+
+In the context of programming, a `bug` refers to an issue, not an insect.
+
+---
+
+A piece of hardware
+
+### --feedback--
+
+A `bug` refers to a software issue, not a physical component.
+
+---
+
+An error or flaw in the code
+
+---
+
+A new feature in the software
+
+### --feedback--
+
+A `bug` is not a feature; it's an unintended issue that needs to be fixed.
+
+## --video-solution--
+
+3
+
+# --explanation--
+
+A `bug` is an error, flaw, or fault in a computer program that causes it to produce incorrect or unexpected results. For example:
+
+- `I found a bug in the code.` - You discovered an error in the code.
+
+- `I am fixing a bug.` - You are working on solving a problem in the code.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "Lisa",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 0,
+ "finishTimestamp": 3.04
+ }
+ },
+ "commands": [
+ {
+ "character": "Lisa",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Lisa",
+ "startTime": 1,
+ "finishTime": 4.04,
+ "dialogue": {
+ "text": "Hey, James. Did you find that bug we were stuck on yesterday?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Lisa",
+ "opacity": 0,
+ "startTime": 4.54
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6704fbd43885300e4aa221e9.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6704fbd43885300e4aa221e9.md
new file mode 100644
index 0000000000..1ec4342486
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6704fbd43885300e4aa221e9.md
@@ -0,0 +1,92 @@
+---
+id: 6704fbd43885300e4aa221e9
+title: Task 2
+challengeType: 22
+dashedName: task-2
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`Hey, James. BLANK you BLANK that bug we were stuck on yesterday?`
+
+## --blanks--
+
+`Did`
+
+### --feedback--
+
+This word is used to form a question in the past tense. It's placed before the subject (`you`). Don't forget to capitalize it.
+
+---
+
+`find`
+
+### --feedback--
+
+This word means to locate or discover something, in its base form after `did` in questions.
+
+# --explanation--
+
+The `Simple Past` structure for forming questions starts with `did` + subject + base form of the verb. You use `did` to show the action happened in the past, but keep the main verb (e.g., `find`) in its base form. For example:
+
+- `Did they finish the report on time?` - You want to know if the report was concluded before it was due.
+
+- `Did she call you yesterday?` - You want to know if the person received a call the day before.
+
+In Lisa's question, `did you find` is the question form to ask if James located or identified the `bug` they were working on the day before.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "Lisa",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 0,
+ "finishTimestamp": 3.04
+ }
+ },
+ "commands": [
+ {
+ "character": "Lisa",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Lisa",
+ "startTime": 1,
+ "finishTime": 4.04,
+ "dialogue": {
+ "text": "Hey, James. Did you find that bug we were stuck on yesterday?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Lisa",
+ "opacity": 0,
+ "startTime": 4.54
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6704fd952ad2560e9a7ca070.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6704fd952ad2560e9a7ca070.md
new file mode 100644
index 0000000000..81fe3a3153
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6704fd952ad2560e9a7ca070.md
@@ -0,0 +1,108 @@
+---
+id: 6704fd952ad2560e9a7ca070
+title: Task 3
+challengeType: 19
+dashedName: task-3
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What does the expression `stuck on` mean in this sentence?
+
+## --answers--
+
+To continuously work on something without any issues.
+
+### --feedback--
+
+While `stuck on` involves working on something, it specifically refers to being unable to make progress.
+
+---
+
+To be unable to solve or make progress on something.
+
+---
+
+To quickly solve a problem.
+
+### --feedback--
+
+`Stuck on` does not mean solving a problem quickly. It refers to facing difficulties or being unable to progress.
+
+---
+
+To ignore a problem.
+
+### --feedback--
+
+`Stuck on` means trying to solve something but being unable to move forward, not ignoring it.
+
+## --video-solution--
+
+2
+
+# --explanation--
+
+The expression `stuck on` is used when someone is unable to move forward with a task or solve a problem. It suggests being trapped or unable to progress. For example:
+
+- `We were stuck on this code error for hours.` - We could not proceed until that error in the code was found.
+
+- `She got stuck on the final question of the exam.` - She spent a long time on the final question.
+
+In the dialogue, Lisa uses `stuck on` to describe how they were unable to make progress in solving a bug in their work.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "Lisa",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 0,
+ "finishTimestamp": 3.04
+ }
+ },
+ "commands": [
+ {
+ "character": "Lisa",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Lisa",
+ "startTime": 1,
+ "finishTime": 4.04,
+ "dialogue": {
+ "text": "Hey, James. Did you find that bug we were stuck on yesterday?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Lisa",
+ "opacity": 0,
+ "startTime": 4.54
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6705055b28e3c20fce27a15c.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6705055b28e3c20fce27a15c.md
new file mode 100644
index 0000000000..f091e7300b
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6705055b28e3c20fce27a15c.md
@@ -0,0 +1,92 @@
+---
+id: 6705055b28e3c20fce27a15c
+title: Task 4
+challengeType: 22
+dashedName: task-4
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`Hey, James. Did you find that bug we were BLANK BLANK yesterday?`
+
+## --blanks--
+
+`stuck`
+
+### --feedback--
+
+This word means unable to move forward or solve a problem.
+
+---
+
+`on`
+
+### --feedback--
+
+This word shows the connection to the problem or task that was causing difficulty.
+
+# --explanation--
+
+The expression `stuck on` is used to describe a situation where someone is unable to make progress or solve an issue. It emphasizes being trapped or halted in a task. For example:
+
+- `I was stuck on that tricky math problem for hours.` - The problem made me waste a long time.
+
+- `We got stuck on deciding the best solution to the project's issues.` - We did not know the best solution and it took us a long time to find it.
+
+In this sentence, Lisa is referring to a bug they couldn't solve or fix the day before.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "Lisa",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 0,
+ "finishTimestamp": 3.04
+ }
+ },
+ "commands": [
+ {
+ "character": "Lisa",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Lisa",
+ "startTime": 1,
+ "finishTime": 4.04,
+ "dialogue": {
+ "text": "Hey, James. Did you find that bug we were stuck on yesterday?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Lisa",
+ "opacity": 0,
+ "startTime": 4.54
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67050a8becee6d10619fa5ff.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67050a8becee6d10619fa5ff.md
new file mode 100644
index 0000000000..4aade2cd2a
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67050a8becee6d10619fa5ff.md
@@ -0,0 +1,92 @@
+---
+id: 67050a8becee6d10619fa5ff
+title: Task 5
+challengeType: 19
+dashedName: task-5
+---
+
+
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+How could James tell Lisa that he found the bug using a very short answer to say it?
+
+## --answers--
+
+`Yes, I found it.`
+
+### --feedback--
+
+Short answers to questions that involve the `Simple Past` normally are `Yes,` + person + `did.` for affirmatives or `No,` + person + `didn't.` for negatives.
+
+---
+
+`Yes, I did.`
+
+## --video-solution--
+
+2
+
+# --explanation--
+
+When giving short answers to a question directed to you about something you did or did not do in the past, use `Yes, I did.` or `No, I didn't` to answer to them briefly. For example:
+
+- `Did you buy that car you wanted? No, I didn't.` - This means you did not buy the car.
+
+- `Did you pass the English test? Yes, I did` - This means you passed the test.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "Lisa",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 0,
+ "finishTimestamp": 3.04
+ }
+ },
+ "commands": [
+ {
+ "character": "Lisa",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Lisa",
+ "startTime": 1,
+ "finishTime": 4.04,
+ "dialogue": {
+ "text": "Hey, James. Did you find that bug we were stuck on yesterday?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Lisa",
+ "opacity": 0,
+ "startTime": 4.54
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67050fd29a37de112051064b.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67050fd29a37de112051064b.md
new file mode 100644
index 0000000000..0cebfd16c3
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67050fd29a37de112051064b.md
@@ -0,0 +1,84 @@
+---
+id: 67050fd29a37de112051064b
+title: Task 6
+challengeType: 22
+dashedName: task-6
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`Yes, I BLANK. It was quite a hunt.`
+
+## --blanks--
+
+`did`
+
+### --feedback--
+
+This word is used in short answers to confirm or emphasize an action in the past.
+
+# --explanation--
+
+Short answers in the `Simple Past` often use the auxiliary verb `did` to confirm or deny an action. This structure avoids repeating the full sentence while maintaining clarity. For example:
+
+Question: `Did you finish the project?` Short answer: `Yes, I did.`
+
+Question: `Did they call you back?` Short answer: `No, they didn't.`
+
+In the dialogue, James uses `Yes, I did` to confirm that he found the bug Lisa asked about.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "James",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 3.26,
+ "finishTimestamp": 5.34
+ }
+ },
+ "commands": [
+ {
+ "character": "James",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "James",
+ "startTime": 1,
+ "finishTime": 3.08,
+ "dialogue": {
+ "text": "Yes, I did. It was quite a hunt.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "James",
+ "opacity": 0,
+ "startTime": 3.58
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670515561e620a11f2d7308c.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670515561e620a11f2d7308c.md
new file mode 100644
index 0000000000..c561e52141
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670515561e620a11f2d7308c.md
@@ -0,0 +1,113 @@
+---
+id: 670515561e620a11f2d7308c
+title: Task 7
+challengeType: 19
+dashedName: task-7
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What is the meaning of `quite a hunt` in James's answer?
+
+## --answers--
+
+It means a fast and easy search for something.
+
+### --feedback--
+
+`Quite a hunt` suggests difficulty, not an easy search.
+
+---
+
+It refers to an actual hunting activity, like searching for animals.
+
+### --feedback--
+
+The word `hunt` is used figuratively here, meaning a search for something.
+
+---
+
+It refers to a challenging or difficult search for something.
+
+---
+
+It means the bug was already fixed without any effort.
+
+### --feedback--
+
+`Quite a hunt` emphasizes that finding the bug required significant effort.
+
+## --video-solution--
+
+3
+
+# --explanation--
+
+In this context, the word `hunt` is used figuratively to describe a focused search for something difficult to find. For example:
+
+- `It was a real hunt to track down that missing file.` - Finding the missing file was difficult.
+
+- `Finding the right apartment in the city was quite a hunt.` - We looked everywhere until we found the right apartment for us in this city.
+
+The expression `quite a/an` + noun is used to emphasize something as impressive, intense, or remarkable. For example:
+
+- `That was quite a show!` - This sentence emphasizes how impressive the show was.
+- `She gave quite an explanation.` - This sentence emphasizes that the explanation was thorough or detailed.
+
+Here, `quite a hunt` highlights that the search for the bug was challenging, intense, and significant.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "James",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 3.26,
+ "finishTimestamp": 5.34
+ }
+ },
+ "commands": [
+ {
+ "character": "James",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "James",
+ "startTime": 1,
+ "finishTime": 3.08,
+ "dialogue": {
+ "text": "Yes, I did. It was quite a hunt.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "James",
+ "opacity": 0,
+ "startTime": 3.58
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6705177d1d3dbb124955a397.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6705177d1d3dbb124955a397.md
new file mode 100644
index 0000000000..146f720231
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6705177d1d3dbb124955a397.md
@@ -0,0 +1,94 @@
+---
+id: 6705177d1d3dbb124955a397
+title: Task 8
+challengeType: 22
+dashedName: task-8
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`BLANK, I checked the BLANK changes we made to the code.`
+
+## --blanks--
+
+`First`
+
+### --feedback--
+
+This word is used to indicate the initial step or action in a sequence. As it is the first word in a sentence, do not forget to capitalize it.
+
+---
+
+`recent`
+
+### --feedback--
+
+This word describes something that happened or was made not long ago.
+
+# --explanation--
+
+In this sentence, `first` is used to show the initial action James took to debug the code. It indicates the start of a sequence of steps. Other examples of this usage include:
+
+- `First, we need to set up the database.` - This means setting up the database is the initial step.
+
+- `First, I turned on the computer.` - This means that before working on the computer, the initial thing I did was to turn it on.
+
+The word `recent` refers to something that happened or was made not long ago. It describes changes to the code that were made shortly before the bug was discovered. Another example:
+
+`The team discussed the most recent updates to the project.` - The updates that were talked about by the team were only the ones made in the last few days.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "James",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 5.5,
+ "finishTimestamp": 8.52
+ }
+ },
+ "commands": [
+ {
+ "character": "James",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "James",
+ "startTime": 1,
+ "finishTime": 4.02,
+ "dialogue": {
+ "text": "First, I checked the recent changes we made to the code.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "James",
+ "opacity": 0,
+ "startTime": 4.52
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670518bd8ec6f012af235433.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670518bd8ec6f012af235433.md
new file mode 100644
index 0000000000..283565a56e
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670518bd8ec6f012af235433.md
@@ -0,0 +1,96 @@
+---
+id: 670518bd8ec6f012af235433
+title: Task 9
+challengeType: 22
+dashedName: task-9
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`First, I BLANK the recent changes we BLANK to the code.`
+
+## --blanks--
+
+`checked`
+
+### --feedback--
+
+This is the `Simple Past` form of the regular verb `check`, formed by adding `-ed` to the base verb.
+
+---
+
+`made`
+
+### --feedback--
+
+This is the `Simple Past` form of the irregular verb `make`, which does not follow the regular `-ed` pattern.
+
+# --explanation--
+
+You use the `Simple Past` tense in affirmative sentences when you want to talk about completed actions at a moment in the past.
+
+In the `Simple Past`, regular verbs like `check` are formed by adding `-ed` to the base verb. Irregular verbs, such as `make`, have unique forms that do not follow this rule. In James's sentence:
+
+`Checked` is the past form of the regular verb `check`, indicating an action that was completed in the past. For example:
+
+`He checked his email before the meeting.` - He looked at the e-mails at a moment in the past prior to the meeting.
+
+`Made` is the past form of the irregular verb `make`, indicating something that was created or done in the past. For example:
+
+`She made a list of items to buy.` - She created a list of what she wanted to buy before going to the store.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "James",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 5.5,
+ "finishTimestamp": 8.52
+ }
+ },
+ "commands": [
+ {
+ "character": "James",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "James",
+ "startTime": 1,
+ "finishTime": 4.02,
+ "dialogue": {
+ "text": "First, I checked the recent changes we made to the code.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "James",
+ "opacity": 0,
+ "startTime": 4.52
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67051b185149b6130426a9ad.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67051b185149b6130426a9ad.md
new file mode 100644
index 0000000000..6b3c747577
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67051b185149b6130426a9ad.md
@@ -0,0 +1,114 @@
+---
+id: 67051b185149b6130426a9ad
+title: Task 10
+challengeType: 19
+dashedName: task-10
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What does Lisa want to know?
+
+## --answers--
+
+Why James found the bug.
+
+### --feedback--
+
+Lisa's question focuses on what James discovered, not on the reason for that.
+
+---
+
+When James found the bug.
+
+### --feedback--
+
+Lisa's question is not related to time. It's about what James found.
+
+---
+
+How James fixed the bug.
+
+### --feedback--
+
+Lisa isn't asking about the method or solution. She's asking for the result of James's search.
+
+---
+
+What James discovered.
+
+## --video-solution--
+
+4
+
+# --explanation--
+
+In the `Simple Past`, questions may start with a question word (e.g., `what`, `where`, `how`, `who`) using the following structure:
+
+**Question word + `did` + subject + base verb.**
+
+Lisa's question, `What did you find there?`, uses `what` to ask for specific information about the result of James's actions. Other examples include:
+
+- `Where did you go yesterday?` - You are asking about a location.
+
+- `How did they solve the problem?` - You are asking about a method.
+
+- `Who did you call last night?` - You are asking about a person.
+
+In the dialog, Lisa is asking about James's discovery while searching for the bug.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "Lisa",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 8.86,
+ "finishTimestamp": 9.96
+ }
+ },
+ "commands": [
+ {
+ "character": "Lisa",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Lisa",
+ "startTime": 1,
+ "finishTime": 2.1,
+ "dialogue": {
+ "text": "What did you find there?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Lisa",
+ "opacity": 0,
+ "startTime": 2.6
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67053619dd65bd1459449bf0.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67053619dd65bd1459449bf0.md
new file mode 100644
index 0000000000..9019a032fa
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67053619dd65bd1459449bf0.md
@@ -0,0 +1,148 @@
+---
+id: 67053619dd65bd1459449bf0
+title: Task 11
+challengeType: 19
+dashedName: task-11
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What did James discover initially?
+
+## --answers--
+
+He discovered nothing.
+
+---
+
+He discovered something.
+
+### --feedback--
+
+The expression James says doesn't say that he found something.
+
+---
+
+He found everything immediately.
+
+### --feedback--
+
+What James says contradicts the idea that he found everything.
+
+---
+
+He didn't look for anything.
+
+### --feedback--
+
+He was actually searching for something.
+
+## --video-solution--
+
+1
+
+# --explanation--
+
+James uses the word `nothing`, which indicates the absence of any discovery. For example:
+
+- `She found nothing unusual in the report.` -The report had the usual characteristics.
+
+- `We saw nothing strange during the test.` - It was a pretty common test.
+
+In contrast, in negative sentences, you'll use `anything` instead of `nothing`. For example:
+
+- Affirmative: `He found nothing.` - There were no discoveries.
+
+- Negative: `He didn't find anything.` - There were no discoveries.
+
+Notice that, in negative sentences and in questions with `did`, the main verb (in this case, `find`) is in its base form. The auxiliary verb `did` is what shows that this sentence is in the past tense. For example:
+
+- `They didn't find anything wrong with the program.` - Not finding anything was in the past.
+
+- `I didn't see anything unusual during the presentation.` - Nothing unusual was seen in the presentation that happened in the past.
+
+This structure helps avoid double negatives. James's answer, `Nothing at first`, reflects an affirmative sentence emphasizing that he couldn't find anything when he began his search.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "Lisa",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ },
+ {
+ "character": "James",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 8.86,
+ "finishTimestamp": 11.04
+ }
+ },
+ "commands": [
+ {
+ "character": "Lisa",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Lisa",
+ "startTime": 1,
+ "finishTime": 2,
+ "dialogue": {
+ "text": "What did you find there?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Lisa",
+ "opacity": 0,
+ "startTime": 2.14
+ },
+ {
+ "character": "James",
+ "opacity": 1,
+ "startTime": 2.14
+ },
+ {
+ "character": "James",
+ "startTime": 2.28,
+ "finishTime": 3.18,
+ "dialogue": {
+ "text": "Nothing at first.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "James",
+ "opacity": 0,
+ "startTime": 3.68
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670538f8565fb514ddf24b85.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670538f8565fb514ddf24b85.md
new file mode 100644
index 0000000000..55fb293609
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670538f8565fb514ddf24b85.md
@@ -0,0 +1,92 @@
+---
+id: 670538f8565fb514ddf24b85
+title: Task 12
+challengeType: 22
+dashedName: task-12
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`BLANK I reviewed the error logs more carefully.`
+
+## --blanks--
+
+`Then`
+
+### --feedback--
+
+This word is used to show the next step in a sequence of actions. It's in the beginning of the sentence, so don't forget to capitalize it.
+
+# --explanation--
+
+`Then` is used to indicate the next action in a sequence of events. It shows what happens after something else. For example:
+
+- `I turned on the computer, and then I opened my email.` - You only opened the email after turning on the computer.
+
+- `We fixed the bug, then we tested the application again.` - They only tested the application again after fixing the bug.
+
+In James's sentence, he uses `then` to explain the next action he took after checking the recent changes made to the code.
+
+Other words and phrases that can be used with the same meaning as `then` in this context are `after that` and `next`. For example:
+
+- `I checked the updates. After that, I started debugging.`
+
+- `I reviewed the requirements. Next, I shared my thoughts with the team.`.
+
+These words help structure descriptions of actions in chronological order.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "James",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 11.3,
+ "finishTimestamp": 13.86
+ }
+ },
+ "commands": [
+ {
+ "character": "James",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "James",
+ "startTime": 1,
+ "finishTime": 3.56,
+ "dialogue": {
+ "text": "Then I reviewed the error logs more carefully.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "James",
+ "opacity": 0,
+ "startTime": 4.06
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67053b9fe0a27715979bee1b.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67053b9fe0a27715979bee1b.md
new file mode 100644
index 0000000000..c0c28e490c
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67053b9fe0a27715979bee1b.md
@@ -0,0 +1,94 @@
+---
+id: 67053b9fe0a27715979bee1b
+title: Task 13
+challengeType: 22
+dashedName: task-13
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`Then I reviewed the BLANK BLANK more carefully.`
+
+## --blanks--
+
+`error`
+
+### --feedback--
+
+This word refers to mistakes or problems in a system or program.
+
+---
+
+`logs`
+
+### --feedback--
+
+This word refers to records or detailed reports of events or actions in a system.
+
+# --explanation--
+
+`Logs` generally means records or reports that document events, actions, or data over time. `Logs` are often used in technical contexts to track system activity. For example:
+
+`The server logs showed multiple login attempts.` - There is a record in the server of attempts of logging into it.
+
+`Error logs` specifically refer to records of system or application errors. These logs help identify issues by providing detailed information about what went wrong and when. For example:
+
+`The error logs revealed that the application crashed due to a missing file.` - In the record of issues or problems, you can see a missing file was the cause for the crash.
+
+In James's sentence, he refers to checking the `error logs` carefully to identify the source of a problem. These logs are essential for troubleshooting in programming.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "James",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 11.3,
+ "finishTimestamp": 13.86
+ }
+ },
+ "commands": [
+ {
+ "character": "James",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "James",
+ "startTime": 1,
+ "finishTime": 3.56,
+ "dialogue": {
+ "text": "Then I reviewed the error logs more carefully.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "James",
+ "opacity": 0,
+ "startTime": 4.06
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67053ea535fe23160e6b29c1.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67053ea535fe23160e6b29c1.md
new file mode 100644
index 0000000000..921e911605
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67053ea535fe23160e6b29c1.md
@@ -0,0 +1,96 @@
+---
+id: 67053ea535fe23160e6b29c1
+title: Task 14
+challengeType: 22
+dashedName: task-14
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`Then I reviewed the error logs BLANK BLANK.`
+
+## --blanks--
+
+`more`
+
+### --feedback--
+
+This word is used to indicate a higher degree or intensity.
+
+---
+
+`carefully`
+
+### --feedback--
+
+This word is an adverb that describes how the action was performed, with care.
+
+# --explanation--
+
+`More carefully` uses `more` to intensify the adverb `carefully`, which describes the way James reviewed the error logs. Adverbs like `carefully` modify verbs, showing how an action is performed.
+
+If you compare `more careful` and `more carefully`, the difference is in the fact that `more careful` is an adjective phrase describing a noun (person, place, or thing). For example:
+
+`She was more careful with her calculations.` - Here, `more careful` describes the subject/person, `she`.
+
+`More carefully` is an adverb phrase, which describes how the action is performed. For example:
+
+`She checked her calculations more carefully.` - It describes how the calculations were `checked` - in other words, it describes the action of `checking`, not the person who `checks`.
+
+In James's sentence, `more carefully` explains that James increased the level of attention or detail in the reviewing of the logs. It describes the review, not James.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "James",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 11.3,
+ "finishTimestamp": 13.86
+ }
+ },
+ "commands": [
+ {
+ "character": "James",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "James",
+ "startTime": 1,
+ "finishTime": 3.56,
+ "dialogue": {
+ "text": "Then I reviewed the error logs more carefully.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "James",
+ "opacity": 0,
+ "startTime": 4.06
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67053faa1471c916446ad615.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67053faa1471c916446ad615.md
new file mode 100644
index 0000000000..af24cbccb4
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67053faa1471c916446ad615.md
@@ -0,0 +1,116 @@
+---
+id: 67053faa1471c916446ad615
+title: Task 15
+challengeType: 19
+dashedName: task-15
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What did James discover when reviewing the error logs?
+
+## --answers--
+
+He didn't discover anything.
+
+### --feedback--
+
+James explicitly states that he noticed `something`, meaning he found something.
+
+---
+
+He discovered something.
+
+---
+
+He discovered a common mistake.
+
+### --feedback--
+
+James mentions finding `something odd`. `Odd` is different from `common`.
+
+---
+
+He didn't look for anything.
+
+### --feedback--
+
+James was actively investigating and found something during his review.
+
+## --video-solution--
+
+2
+
+# --explanation--
+
+`Something` is used in affirmative sentences to indicate that a thing exists or happened. For example:
+
+- `He found something unusual in the logs.` - He discovered that the logs had a different thing from the usual.
+
+- `She noticed something during the meeting.` - One particular thing drew her attention during the meeting.
+
+In contrast, `anything` is used in negative sentences or questions. For example:
+
+- Negative: `He didn't find anything in the logs.` - The logs did not help him understand the problem.
+
+- Question: `Did she notice anything during the meeting?` - You are asking if she was able to see something during the meeting.
+
+In negative sentences with `did not` or `didn't`, the main verb remains in its base form (`find`, `notice` etc.), and `anything` is used instead of `something`.
+
+Here, James says, `That's when I noticed something odd`, meaning he found something during his review process.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "James",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 14.24,
+ "finishTimestamp": 16.12
+ }
+ },
+ "commands": [
+ {
+ "character": "James",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "James",
+ "startTime": 1,
+ "finishTime": 2.88,
+ "dialogue": {
+ "text": "That's when I noticed something odd.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "James",
+ "opacity": 0,
+ "startTime": 3.38
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670541bdd115c71686a398c3.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670541bdd115c71686a398c3.md
new file mode 100644
index 0000000000..467d8d263f
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670541bdd115c71686a398c3.md
@@ -0,0 +1,84 @@
+---
+id: 670541bdd115c71686a398c3
+title: Task 16
+challengeType: 22
+dashedName: task-16
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`That's when I noticed something BLANK.`
+
+## --blanks--
+
+`odd`
+
+### --feedback--
+
+This word means strange or unusual.
+
+# --explanation--
+
+`Odd` is used to describe something that is unusual, strange, or unexpected. It often refers to something that does not fit the norm or is out of the ordinary. For example:
+
+- `The system showed an odd behavior during the test.` - Meaning the system acted different from the normal.
+
+- `I saw an odd pattern in the data.` - Meaning the pattern in the data was different.
+
+In James's sentence, he uses `odd` to describe something he noticed that seemed strange or unexpected while reviewing the logs.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "James",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 14.24,
+ "finishTimestamp": 16.12
+ }
+ },
+ "commands": [
+ {
+ "character": "James",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "James",
+ "startTime": 1,
+ "finishTime": 2.88,
+ "dialogue": {
+ "text": "That's when I noticed something odd.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "James",
+ "opacity": 0,
+ "startTime": 3.38
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6705425a4b3df216cb6de9a7.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6705425a4b3df216cb6de9a7.md
new file mode 100644
index 0000000000..0dee3f856f
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6705425a4b3df216cb6de9a7.md
@@ -0,0 +1,94 @@
+---
+id: 6705425a4b3df216cb6de9a7
+title: Task 17
+challengeType: 19
+dashedName: task-17
+---
+
+
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+How could Lisa ask **in a short way** about James's discovery in the error logs?
+
+## --answers--
+
+`What was the odd thing that you found when you were reviewing the error logs?`
+
+### --feedback--
+
+Even though this is exactly what she wants to know, it is not a short question.
+
+---
+
+`What was it?`
+
+## --video-solution--
+
+2
+
+# --explanation--
+
+James talks about `something odd`. Lisa asks him to identify what this odd thing (`it`) was by asking `What was it?`. `Was` is used because it is a singular thing (`something odd`) and it was found in the past, when James reviewed the error logs.
+
+Remember that, in questions, you normally invert verb and subject, so `it was` becomes `was it`. For example:
+
+- `It was fun!` - You're saying you liked an activity.
+
+- `Was it fun?` - You're asking the other person if they liked it.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "James",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 14.24,
+ "finishTimestamp": 16.12
+ }
+ },
+ "commands": [
+ {
+ "character": "James",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "James",
+ "startTime": 1,
+ "finishTime": 2.88,
+ "dialogue": {
+ "text": "That's when I noticed something odd.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "James",
+ "opacity": 0,
+ "startTime": 3.38
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6705442e6a6ebf1725bc8e1f.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6705442e6a6ebf1725bc8e1f.md
new file mode 100644
index 0000000000..a2124d76af
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6705442e6a6ebf1725bc8e1f.md
@@ -0,0 +1,142 @@
+---
+id: 6705442e6a6ebf1725bc8e1f
+title: Task 18
+challengeType: 19
+dashedName: task-18
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What does Lisa want to know?
+
+## --answers--
+
+She wants to know where it was.
+
+### --feedback--
+
+Lisa's question is not about the location of the problem, but about what James noticed.
+
+---
+
+She wants to know what it was.
+
+---
+
+She wants to know when it happened.
+
+### --feedback--
+
+Lisa's question is not about time. It's about identifying the odd thing.
+
+---
+
+She wants to know why it was odd.
+
+### --feedback--
+
+Lisa's question focuses on what the odd thing was, not about why James thought it was odd.
+
+## --video-solution--
+
+2
+
+# --explanation--
+
+The verb `to be` in the `Simple Past` is used to describe or ask about states or characteristics in the past. The forms are `was` (singular) and `were` (plural). For example:
+
+- Affirmative: `The meeting was productive.` - You had a good opinion about the meeting
+
+- Negative: `The meeting wasn't productive.` - Your opinion about the meeting was that it was a waste of time.
+
+In questions, the verb `to be` and the subject are inverted. For example:
+
+- Affirmative sentence: `It was a bug.` - You're confirming the presence of a bug in the code.
+
+- Question: `Was it a bug?` - You want to know if it was a bug. Notice `was` goes before `it` here.
+
+In this dialogue, Lisa asks `What was it?` to ask James to identify what the `something odd` that he noticed was.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "James",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ },
+ {
+ "character": "Lisa",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 14.24,
+ "finishTimestamp": 16.96
+ }
+ },
+ "commands": [
+ {
+ "character": "James",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "James",
+ "startTime": 1,
+ "finishTime": 2.88,
+ "dialogue": {
+ "text": "That's when I noticed something odd.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "James",
+ "opacity": 0,
+ "startTime": 3.03
+ },
+ {
+ "character": "Lisa",
+ "opacity": 1,
+ "startTime": 3.03
+ },
+ {
+ "character": "Lisa",
+ "startTime": 3.18,
+ "finishTime": 3.72,
+ "dialogue": {
+ "text": "What was it?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Lisa",
+ "opacity": 0,
+ "startTime": 4.22
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6705573e13b1211820a3ac67.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6705573e13b1211820a3ac67.md
new file mode 100644
index 0000000000..771ccd9100
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6705573e13b1211820a3ac67.md
@@ -0,0 +1,108 @@
+---
+id: 6705573e13b1211820a3ac67
+title: Task 19
+challengeType: 19
+dashedName: task-19
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What did James find in the error logs?
+
+## --answers--
+
+The system was connecting to many databases at the same time.
+
+### --feedback--
+
+James states that the system wasn't connecting properly to the database. There is no mention of more than one database in the sentence.
+
+---
+
+The system was turned off.
+
+### --feedback--
+
+James didn't mention that the system was off. The issue was with its connection to the database.
+
+---
+
+The system wasn't connecting to the database properly.
+
+---
+
+There were no errors in the system.
+
+### --feedback--
+
+James found an error: the system wasn't connecting to the database.
+
+## --video-solution--
+
+3
+
+# --explanation--
+
+The negative form of the verb `to be` in the `Simple Past` tense is `was not` or `wasn't` for singular subjects, and `were not` or `weren't` for plural subjects. It is used to describe something that did not happen or was not true. For example:
+
+- Singular: `The code wasn't running as expected.` - An issue was happening with the code.
+
+- Plural: `The changes weren't implemented correctly.` - Errors in the implementation caused the bugs.
+
+In James's sentence, he uses `wasn't` to explain that the system was failing to connect to the database. Negative sentences with `wasn't` or `weren't` indicate what did not occur or work as you might expect.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "James",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 17.3,
+ "finishTimestamp": 19.78
+ }
+ },
+ "commands": [
+ {
+ "character": "James",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "James",
+ "startTime": 1,
+ "finishTime": 3.48,
+ "dialogue": {
+ "text": "The system wasn't connecting to the database properly.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "James",
+ "opacity": 0,
+ "startTime": 3.98
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67055872382df21871200427.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67055872382df21871200427.md
new file mode 100644
index 0000000000..d3012ef7e2
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67055872382df21871200427.md
@@ -0,0 +1,84 @@
+---
+id: 67055872382df21871200427
+title: Task 20
+challengeType: 22
+dashedName: task-20
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`The system wasn't connecting to the database BLANK.`
+
+## --blanks--
+
+`properly`
+
+### --feedback--
+
+This word means in the correct or appropriate way.
+
+# --explanation--
+
+`Properly` is the adverb form of the adjective `proper`. Both words can express doing something in the correct or suitable manner, but their usage differs depending on the sentence structure. For example:
+
+- `The application didn't function properly after the update.` - This means the updates brought errors to the code. The adverb `properly` modifies the verb `function`.
+
+- `This wasn't a proper configuration of the database.` - The adjective `proper` describes the noun `configuration`.
+
+Here, James uses `properly` to describe that the system wasn't connecting to the database in the correct way.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "James",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 17.3,
+ "finishTimestamp": 19.78
+ }
+ },
+ "commands": [
+ {
+ "character": "James",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "James",
+ "startTime": 1,
+ "finishTime": 3.48,
+ "dialogue": {
+ "text": "The system wasn't connecting to the database properly.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "James",
+ "opacity": 0,
+ "startTime": 3.98
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67055c02b6774a18f8f7186f.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67055c02b6774a18f8f7186f.md
new file mode 100644
index 0000000000..2a544ee3ca
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67055c02b6774a18f8f7186f.md
@@ -0,0 +1,98 @@
+---
+id: 67055c02b6774a18f8f7186f
+title: Task 21
+challengeType: 22
+dashedName: task-21
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`After that, I realized we didn't update the database BLANK after the last security BLANK.`
+
+## --blanks--
+
+`credentials`
+
+### --feedback--
+
+This word refers to the username, password, or other information required to access a system.
+
+---
+
+`patch`
+
+### --feedback--
+
+This word refers to an update or fix applied to software or a system, often for security purposes.
+
+# --explanation--
+
+`Credentials` refers to information such as usernames, passwords, or keys that allow a user or system to access another system or resource. For example:
+
+- `Please enter your credentials to log in to the server.` - meaning you should insert your information to access the server.
+
+- `The credentials were incorrect, so the login failed.` - meaning the information you inserted is different from the one the system has in its database.
+
+A `patch` is an update or fix applied to software or systems to correct issues, improve functionality, or enhance security. For example:
+
+- `The developers released a patch to fix the bug.` - meaning they fixed the bug through an update to the system.
+
+- `Make sure to apply the latest security patch to protect your system.` - meaning the last security update will be able to protect your system better.
+
+Here, James explains that the issue was caused by forgetting to update the database `credentials` after applying a security `patch`.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "James",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 20.16,
+ "finishTimestamp": 25.36
+ }
+ },
+ "commands": [
+ {
+ "character": "James",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "James",
+ "startTime": 1,
+ "finishTime": 6.2,
+ "dialogue": {
+ "text": "After that, I realized we didn't update the database credentials after the last security patch.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "James",
+ "opacity": 0,
+ "startTime": 6.7
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67055d274231051940d0c8ea.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67055d274231051940d0c8ea.md
new file mode 100644
index 0000000000..0bad385235
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67055d274231051940d0c8ea.md
@@ -0,0 +1,94 @@
+---
+id: 67055d274231051940d0c8ea
+title: Task 22
+challengeType: 22
+dashedName: task-22
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`BLANK BLANK, I realized we didn't update the database credentials after the last security patch.`
+
+## --blanks--
+
+`After`
+
+### --feedback--
+
+The opposite of `before`. Capitalize it as it is in the beginning of a sentence.
+
+---
+
+`that`
+
+### --feedback--
+
+Demonstrative pronoun used when something is more distant from the speaker. When something is close to the speaker, you can use `this`.
+
+# --explanation--
+
+`After that` is used to show the order of events, meaning the next action or event followed something that happened previously. It helps organize actions in chronological order. For example:
+
+- `We finished the code review. After that, we started debugging.` - First, they reviewed the code. Then, they debugged it.
+
+- `He submitted the report. After that, he took a short break.` - First, he submitted the report. Then, he rested.
+
+`After that` is similar in meaning to expressions like `then` or `next`, but it specifically emphasizes that one action follows another in time.
+
+Here, James uses `after that` to indicate that realizing what the credentials issue was came after another action in the debugging process.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "James",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 20.16,
+ "finishTimestamp": 25.36
+ }
+ },
+ "commands": [
+ {
+ "character": "James",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "James",
+ "startTime": 1,
+ "finishTime": 6.2,
+ "dialogue": {
+ "text": "After that, I realized we didn't update the database credentials after the last security patch.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "James",
+ "opacity": 0,
+ "startTime": 6.7
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67055f5c9bdb8e1999102827.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67055f5c9bdb8e1999102827.md
new file mode 100644
index 0000000000..271d3441ce
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67055f5c9bdb8e1999102827.md
@@ -0,0 +1,120 @@
+---
+id: 67055f5c9bdb8e1999102827
+title: Task 23
+challengeType: 19
+dashedName: task-23
+---
+
+
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+After these lines, Lisa then asks James if he solved the problem. How could she ask that **in a brief way**?
+
+## --answers--
+
+`Did you fix the credentials that were causing the issue?`
+
+### --feedback--
+
+That is indeed what she wants to know, but she asks a much shorter question than this one.
+
+---
+
+`Did you fix them?`
+
+## --video-solution--
+
+2
+
+# --explanation--
+
+When talking about something you already mentioned before, you can use `it` to replace it if it is a singular noun or `them` if it is a plural noun to avoid repetition. For example:
+
+- `You were looking for a car to buy. Did you buy it?` - `It` is used instead of `the car` in the question.
+
+- `How were your tests last week? Did you do well on all of them?` - `Them` replaces `your tests` here.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "James",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ },
+ {
+ "character": "Lisa",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 20.88,
+ "finishTimestamp": 27.62
+ }
+ },
+ "commands": [
+ {
+ "character": "James",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "James",
+ "startTime": 1,
+ "finishTime": 5.48,
+ "dialogue": {
+ "text": "I realized we didn't update the database credentials after the last security patch.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "James",
+ "opacity": 0,
+ "startTime": 5.73
+ },
+ {
+ "character": "Lisa",
+ "opacity": 1,
+ "startTime": 5.73
+ },
+ {
+ "character": "Lisa",
+ "startTime": 5.98,
+ "finishTime": 7.74,
+ "dialogue": {
+ "text": "Ah, so the credentials were the issue.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Lisa",
+ "opacity": 0,
+ "startTime": 8.24
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6705605c7fb8f619e0068634.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6705605c7fb8f619e0068634.md
new file mode 100644
index 0000000000..30101291fb
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6705605c7fb8f619e0068634.md
@@ -0,0 +1,114 @@
+---
+id: 6705605c7fb8f619e0068634
+title: Task 24
+challengeType: 19
+dashedName: task-24
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What is Lisa asking James about?
+
+## --answers--
+
+She is asking if James fixed the credentials.
+
+---
+
+She is asking if the credentials caused the issue.
+
+### --feedback--
+
+Lisa already understands that the credentials were the problem. She is asking if James fixed them.
+
+---
+
+She is asking if James fixed the database.
+
+### --feedback--
+
+Lisa's question specifically refers to the credentials, not to the database as a whole.
+
+---
+
+She is asking if there are more issues.
+
+### --feedback--
+
+Lisa's question focuses on whether James fixed the credentials.
+
+## --video-solution--
+
+1
+
+# --explanation--
+
+`Issue` in this context means a problem or difficulty that needs to be solved. In the sentence, it refers to the database credentials being incorrect. For example:
+
+- `There was an issue with the system configuration.` - The problem was related to the configuration of the system.
+
+- `The main issue was a missing file.` - The problem was caused by a file not being where it should be.
+
+`Them` is a pronoun used to replace plural nouns already mentioned. In Lisa's question, `them` refers to the `credentials`. For example:
+
+- `The files were corrupted. Did you fix them?` - `them` refers to the files.
+
+- `The permissions were incorrect. I updated them this morning.` - `them` refers to the permissions.
+
+Lisa's question asks if James fixed the credentials.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "Lisa",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 25.86,
+ "finishTimestamp": 28.48
+ }
+ },
+ "commands": [
+ {
+ "character": "Lisa",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Lisa",
+ "startTime": 1,
+ "finishTime": 3.62,
+ "dialogue": {
+ "text": "Ah, so the credentials were the issue. Did you fix them?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Lisa",
+ "opacity": 0,
+ "startTime": 4.12
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670561a8af3d901a431549fe.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670561a8af3d901a431549fe.md
new file mode 100644
index 0000000000..3c649d9faf
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670561a8af3d901a431549fe.md
@@ -0,0 +1,117 @@
+---
+id: 670561a8af3d901a431549fe
+title: Task 25
+challengeType: 19
+dashedName: task-25
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What was necessary to make the app work again?
+
+## --answers--
+
+Restarting the app.
+
+### --feedback--
+
+James doesn't mention restarting the app as the solution. He says updating the credentials was necessary.
+
+---
+
+Fixing the database server.
+
+### --feedback--
+
+James mentions updating the credentials, not fixing the server, as the key to solving the issue.
+
+---
+
+Updating the credentials.
+
+---
+
+Reinstalling the app.
+
+### --feedback--
+
+James says updating the credentials solved the issue, not reinstalling the app.
+
+## --video-solution--
+
+3
+
+# --explanation--
+
+`Successful` means achieving the desired result or goal. In this context, James says the connection was `successful`, meaning the database connection worked correctly after updating the credentials. For example:
+
+- `The team completed a successful deployment yesterday.` - meaning the deployment finished with good results.
+
+- `Her solution to the problem was successful and saved a lot of time.` - meaning she found a good solution to the problem.
+
+In James's case, updating the credentials to make a successful connection to the database was necessary for the app to start working again.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "James",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 28.48,
+ "finishTimestamp": 34.58
+ }
+ },
+ "commands": [
+ {
+ "character": "James",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "James",
+ "startTime": 1,
+ "finishTime": 5.3,
+ "dialogue": {
+ "text": "Yes, I updated the credentials and the connection was finally successful.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "James",
+ "startTime": 5.62,
+ "finishTime": 7.1,
+ "dialogue": {
+ "text": "The app started working again.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "James",
+ "opacity": 0,
+ "startTime": 7.6
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670562a2aa92081a89ba77f6.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670562a2aa92081a89ba77f6.md
new file mode 100644
index 0000000000..f9c2b9d940
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670562a2aa92081a89ba77f6.md
@@ -0,0 +1,113 @@
+---
+id: 670562a2aa92081a89ba77f6
+title: Task 26
+challengeType: 22
+dashedName: task-26
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`Yes, I BLANK the credentials and the connection BLANK finally successful. The app BLANK working again.`
+
+## --blanks--
+
+`updated`
+
+### --feedback--
+
+This is the `Simple Past` form of the regular verb `update`, created by adding `-ed` to the base verb.
+
+---
+
+`was`
+
+### --feedback--
+
+This is the `Simple Past` form of the verb `to be`, used here to describe the state of the connection.
+
+---
+
+`started`
+
+### --feedback--
+
+This is the `Simple Past` form of the regular verb `start`, created by adding `-ed` to the base verb.
+
+# --explanation--
+
+Affirmative sentences in the `Simple Past` follow specific rules:
+
+For the verb `to be`, the forms are `was` (singular) and `were` (plural). These forms are used without auxiliary verbs. For example:
+
+- `The project was successful.` - This means the project brought good results.
+
+- `They were happy with the results.` - this represents how `they` felt about the results of the project.
+
+Regular verbs in the Simple Past are formed by adding `-ed` to the base verb. For example:
+
+- `I worked on the project yesterday.` - You add `-ed` to the base form of the verb `work` to say that the action happened in a moment in the past.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "James",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 28.48,
+ "finishTimestamp": 34.58
+ }
+ },
+ "commands": [
+ {
+ "character": "James",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "James",
+ "startTime": 1,
+ "finishTime": 5.3,
+ "dialogue": {
+ "text": "Yes, I updated the credentials and the connection was finally successful.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "James",
+ "startTime": 5.62,
+ "finishTime": 7.1,
+ "dialogue": {
+ "text": "The app started working again.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "James",
+ "opacity": 0,
+ "startTime": 7.6
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6705638c3791881aed186e9d.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6705638c3791881aed186e9d.md
new file mode 100644
index 0000000000..a9c803c3d8
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6705638c3791881aed186e9d.md
@@ -0,0 +1,90 @@
+---
+id: 6705638c3791881aed186e9d
+title: Task 27
+challengeType: 19
+dashedName: task-27
+---
+
+
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+How can Lisa congratulate James **in a brief way** to make him know she is happy with the results?
+
+## --answers--
+
+`Congratulations on a job well done. I'm really happy to know you solved this issue.`
+
+### --feedback--
+
+That is the idea. However, Lisa could say that in a much shorter form.
+
+---
+
+`Great job.`
+
+## --video-solution--
+
+2
+
+# --explanation--
+
+`Great job` can be used to tell someone you are satisfied with their effort or achievement. It expresses appreciation and acknowledgment of their success. For example:
+
+Kid: `Mom, I finished all my homework!` Mother: `Great job.`
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "James",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 32.9,
+ "finishTimestamp": 34.58
+ }
+ },
+ "commands": [
+ {
+ "character": "James",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "James",
+ "startTime": 1,
+ "finishTime": 2.68,
+ "dialogue": {
+ "text": "The app started working again.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "James",
+ "opacity": 0,
+ "startTime": 3.18
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670564e883b7911b4ec31e29.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670564e883b7911b4ec31e29.md
new file mode 100644
index 0000000000..5b08edcaf8
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670564e883b7911b4ec31e29.md
@@ -0,0 +1,134 @@
+---
+id: 670564e883b7911b4ec31e29
+title: Task 28
+challengeType: 19
+dashedName: task-28
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What can you conclude based on Lisa's comment?
+
+## --answers--
+
+She is telling James the app is broken.
+
+### --feedback--
+
+Lisa's comment intends to praise James for fixing the app, not to criticize him.
+
+---
+
+She is praising James for his effort.
+
+---
+
+She is asking James to work faster.
+
+### --feedback--
+
+Lisa's comment is about appreciating James's work, not asking for speed.
+
+---
+
+She is unsure if the app is working.
+
+### --feedback--
+
+Lisa's comment shows that she is confident in James's success and appreciates his work.
+
+## --video-solution--
+
+2
+
+# --explanation--
+
+The phrase `Great job` is used to praise or compliment someone for their effort or achievement. It expresses appreciation and acknowledgment of their success. For example:
+
+`You fixed the bug in record time. Great job!` - meaning you think it is great that the other person fixed the bug so fast.
+
+Lisa's use of `Great job` in the dialogue reflects her recognition of James's effort in solving the problem and getting the app working again.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "James",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ },
+ {
+ "character": "Lisa",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 32.9,
+ "finishTimestamp": 35.52
+ }
+ },
+ "commands": [
+ {
+ "character": "James",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "James",
+ "startTime": 1,
+ "finishTime": 2.68,
+ "dialogue": {
+ "text": "The app started working again.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "James",
+ "opacity": 0,
+ "startTime": 2.87
+ },
+ {
+ "character": "Lisa",
+ "opacity": 1,
+ "startTime": 2.87
+ },
+ {
+ "character": "Lisa",
+ "startTime": 3.06,
+ "finishTime": 3.62,
+ "dialogue": {
+ "text": "Great job.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Lisa",
+ "opacity": 0,
+ "startTime": 4.12
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67056697de96ba1ba012eb44.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67056697de96ba1ba012eb44.md
new file mode 100644
index 0000000000..60e30e466f
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67056697de96ba1ba012eb44.md
@@ -0,0 +1,60 @@
+---
+id: 67056697de96ba1ba012eb44
+title: Task 42
+challengeType: 22
+dashedName: task-42
+---
+
+# --instructions--
+
+Fill each blank with one of the following words to add the correct sequential linkers to the text below: `After`, `Finally`, `First`, or `Then`.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`BLANK, James checked the code for recent changes. BLANK, he reviewed the error logs more carefully. BLANK that, he found the bug in the database credentials. BLANK, he updated the credentials, and the app worked again.`
+
+## --blanks--
+
+`First`
+
+### --feedback--
+
+James' initial action was checking the code. The first letter is capitalized.
+
+---
+
+`Then`
+
+### --feedback--
+
+This linker indicates the immediate next action, which was reviewing the error logs. The first letter is capitalized.
+
+---
+
+`After`
+
+### --feedback--
+
+This word combined with the following makes a linker that correctly introduces a step with more separation, when James found the bug in the credentials. The first letter is capitalized.
+
+---
+
+`Finally`
+
+### --feedback--
+
+This linker indicates that updating the credentials was the last step in solving the issue. The first letter is capitalized.
+
+# --explanation--
+
+Sequential linkers like `first`, `then`, `after that`, and `finally` are used to describe the order of actions or events.
+
+- `First` is used to describe the initial action.
+
+- `Then` refers to the next immediate step.
+
+- `After that` is used to introduce a step following another action with some distinction between them.
+
+- `Finally` marks the last step in a sequence.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67056b4950144e1cf10c53a6.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67056b4950144e1cf10c53a6.md
new file mode 100644
index 0000000000..42892a829e
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67056b4950144e1cf10c53a6.md
@@ -0,0 +1,64 @@
+---
+id: 67056b4950144e1cf10c53a6
+title: Task 43
+challengeType: 19
+dashedName: task-43
+---
+
+
+
+# --instructions--
+
+Read the following text and answer the question below.
+
+# --questions--
+
+## --text--
+
+This is James' email to his team.
+
+`To: Team`
+
+`Hey team,`
+
+`I found the bug from yesterday. First, I checked the recent code changes but didn't see anything. Then, I looked at the error logs and realized the system wasn't connecting to the database properly. We hadn't updated the credentials after the last security patch. I fixed the credentials, and the app is now running smoothly!`
+
+`Best regards,` `James`
+
+What would be the most appropriate subject for James' email to the team?
+
+## --answers--
+
+`Update on the system connection issue`
+
+### --feedback--
+
+This subject is relevant but a bit too vague about the exact problem James fixed.
+
+---
+
+`Bug fixed. Database credentials updated`
+
+---
+
+`Security patch problems`
+
+### --feedback--
+
+This subject is misleading because the security patch wasn't the problem, it was the credentials not being updated after the patch.
+
+---
+
+`Error logs reviewed. No issues found`
+
+### --feedback--
+
+This subject is incorrect because James did find an issue while reviewing the error logs.
+
+## --video-solution--
+
+2
+
+# --explanation--
+
+To find the most appropriate subject take into consideration the whole email and think about the main issue discussed.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670570ad97d26e1d6bad572d.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670570ad97d26e1d6bad572d.md
new file mode 100644
index 0000000000..6c62c01113
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670570ad97d26e1d6bad572d.md
@@ -0,0 +1,66 @@
+---
+id: 670570ad97d26e1d6bad572d
+title: Task 44
+challengeType: 19
+dashedName: task-44
+---
+
+
+
+# --instructions--
+
+Read the following text and answer the question below.
+
+# --questions--
+
+## --text--
+
+This is James' email to his team.
+
+`To: Team`
+
+`Subject: Bug fixed. Database credentials updated`
+
+`Hey team,`
+
+`I found the bug from yesterday. First, I checked the recent code changes but didn't see anything. Then, I looked at the error logs and realized the system wasn't connecting to the database properly. We hadn't updated the credentials after the last security patch. I fixed the credentials, and the app is now running smoothly!`
+
+`Best regards,` `James`
+
+What was the first thing James did to investigate the bug?
+
+## --answers--
+
+He checked the recent code changes.
+
+---
+
+He updated the credentials.
+
+### --feedback--
+
+This is incorrect because James updated the credentials later.
+
+---
+
+He reviewed the error logs.
+
+### --feedback--
+
+James reviewed the error logs after checking the recent code changes.
+
+---
+
+He restarted the system.
+
+### --feedback--
+
+This action wasn't mentioned in the dialogue.
+
+## --video-solution--
+
+1
+
+# --explanation--
+
+To find out what was the first thing James did, focus on the sentence that starts with `First I...`.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6705725e2814c91dd738e8f4.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6705725e2814c91dd738e8f4.md
new file mode 100644
index 0000000000..eca1d02afd
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6705725e2814c91dd738e8f4.md
@@ -0,0 +1,66 @@
+---
+id: 6705725e2814c91dd738e8f4
+title: Task 45
+challengeType: 19
+dashedName: task-45
+---
+
+
+
+# --instructions--
+
+Read the following text and answer the question below.
+
+# --questions--
+
+## --text--
+
+This is James' email to his team.
+
+`To: Team`
+
+`Subject: Bug fixed. Database credentials updated`
+
+`Hey team,`
+
+`I found the bug from yesterday. First, I checked the recent code changes but didn't see anything. Then, I looked at the error logs and realized the system wasn't connecting to the database properly. We hadn't updated the credentials after the last security patch. I fixed the credentials, and the app is now running smoothly!`
+
+`Best regards,` `James`
+
+What was the main cause of the bug James found?
+
+## --answers--
+
+The error logs were not updated.
+
+### --feedback--
+
+This is incorrect because the issue wasn't related to the logs.
+
+---
+
+The system wasn't connecting to the database properly.
+
+---
+
+The code changes introduced a new error.
+
+### --feedback--
+
+The bug wasn't directly caused by the code changes.
+
+---
+
+The internet connection was unstable.
+
+### --feedback--
+
+James doesn't mention this.
+
+## --video-solution--
+
+2
+
+# --explanation--
+
+To find out the main cause of the bug, look for the part of the text that talks about the system's connection. Focus on the sentence that starts with `Then, I...`.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6705742b9616e01e275e5c08.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6705742b9616e01e275e5c08.md
new file mode 100644
index 0000000000..9fb48db944
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6705742b9616e01e275e5c08.md
@@ -0,0 +1,66 @@
+---
+id: 6705742b9616e01e275e5c08
+title: Task 46
+challengeType: 19
+dashedName: task-46
+---
+
+
+
+# --instructions--
+
+Read the following text and answer the question below.
+
+# --questions--
+
+## --text--
+
+This is James' email to his team.
+
+`To: Team`
+
+`Subject: Bug fixed. Database credentials updated`
+
+`Hey team,`
+
+`I found the bug from yesterday. First, I checked the recent code changes but didn't see anything. Then, I looked at the error logs and realized the system wasn't connecting to the database properly. We hadn't updated the credentials after the last security patch. I fixed the credentials, and the app is now running smoothly!`
+
+`Best regards,` `James`
+
+How did James fix the problem?
+
+## --answers--
+
+He reviewed the error logs again.
+
+### --feedback--
+
+Reviewing the logs helped James find the issue but didn't directly fix it.
+
+---
+
+He updated the credentials.
+
+---
+
+He made changes to the code.
+
+### --feedback--
+
+The issue wasn't fixed by changing the code, but by updating the credentials.
+
+---
+
+He restarted the app.
+
+### --feedback--
+
+Restarting the app wasn't mentioned as part of the solution.
+
+## --video-solution--
+
+2
+
+# --explanation--
+
+To find out how James fixed the problem, look for the part of the text that talks about updating the credentials. Focus on the sentence that starts with `We hadn't...`.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67057604ca099f1e7df78e77.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67057604ca099f1e7df78e77.md
new file mode 100644
index 0000000000..201b595e5b
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67057604ca099f1e7df78e77.md
@@ -0,0 +1,66 @@
+---
+id: 67057604ca099f1e7df78e77
+title: Task 47
+challengeType: 19
+dashedName: task-47
+---
+
+
+
+# --instructions--
+
+Read the following text and answer the question below.
+
+# --questions--
+
+## --text--
+
+This is James' email to his team.
+
+`To: Team`
+
+`Subject: Bug fixed. Database credentials updated`
+
+`Hey team,`
+
+`I found the bug from yesterday. First, I checked the recent code changes but didn't see anything. Then, I looked at the error logs and realized the system wasn't connecting to the database properly. We hadn't updated the credentials after the last security patch. I fixed the credentials, and the app is now running smoothly!`
+
+`Best regards,` `James`
+
+When were the credentials updated last time?
+
+## --answers--
+
+Before the bug was found.
+
+### --feedback--
+
+The credentials weren't updated before the bug was found, which was actually the cause of the issue.
+
+---
+
+After the last security patch.
+
+---
+
+When the error logs were cleared.
+
+### --feedback--
+
+The error logs revealed the issue, but the credentials weren't updated when the logs were cleared.
+
+---
+
+During the last system backup.
+
+### --feedback--
+
+No mention of a system backup was made, so this doesn't apply to the situation.
+
+## --video-solution--
+
+2
+
+# --explanation--
+
+To find out when the credentials were updated, check the part where James explains why the app wasn't working. Focus on the sentence starting with, `We hadn't updated...`.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67057e02da44871f492f6f35.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67057e02da44871f492f6f35.md
new file mode 100644
index 0000000000..cdff5a1471
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67057e02da44871f492f6f35.md
@@ -0,0 +1,66 @@
+---
+id: 67057e02da44871f492f6f35
+title: Task 48
+challengeType: 19
+dashedName: task-48
+---
+
+
+
+# --instructions--
+
+Read the following text and answer the question below.
+
+# --questions--
+
+## --text--
+
+This is James' email to his team.
+
+`To: Team`
+
+`Subject: Bug fixed. Database credentials updated`
+
+`Hey team,`
+
+`I found the bug from yesterday. First, I checked the recent code changes but didn't see anything. Then, I looked at the error logs and realized the system wasn't connecting to the database properly. We hadn't updated the credentials after the last security patch. I fixed the credentials, and the app is now running smoothly!`
+
+`Best regards,` `James`
+
+Is the app working now?
+
+## --answers--
+
+No, the app still has bugs.
+
+### --feedback--
+
+The bug was fixed after updating the credentials, so the app no longer has issues.
+
+---
+
+Yes, it's running smoothly.
+
+---
+
+No, the database is still down.
+
+### --feedback--
+
+The database connection issue was resolved, so it's not down anymore.
+
+---
+
+Yes, but only partially.
+
+### --feedback--
+
+The app is fully operational, not partially working.
+
+## --video-solution--
+
+2
+
+# --explanation--
+
+To figure out if the app is working now, look at the last part of James' explanation where he says, `I fixed...`.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670f6ca334a541048d0e9a76.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670f6ca334a541048d0e9a76.md
new file mode 100644
index 0000000000..83bb86d2ce
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670f6ca334a541048d0e9a76.md
@@ -0,0 +1,223 @@
+---
+id: 670f6ca334a541048d0e9a76
+title: "Dialogue 2: Project Post-Mortem"
+challengeType: 21
+dashedName: dialogue-2-project-post-mortem
+---
+
+# --description--
+
+Watch the video below to understand the context of the upcoming lessons.
+
+# --assignment--
+
+Watch the video
+
+# --scene--
+
+```json
+{
+"setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Linda",
+ "position": { "x": -25, "y": 0, "z": 1 }
+ },
+ {
+ "character": "Jake",
+ "position": { "x": 125, "y": 0, "z": 1 }
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1
+ },
+ "alwaysShowDialogue": true
+},
+"commands": [
+ {
+ "character": "Linda",
+ "position": { "x": 25, "y": 0, "z": 1 },
+ "startTime": 0
+ },
+ {
+ "character": "Jake",
+ "position": { "x": 70, "y": 0, "z": 1 },
+ "startTime": 0.5
+ },
+ {
+ "character": "Linda",
+ "startTime": 1,
+ "finishTime": 4.88,
+ "dialogue": {
+ "text": "I was thinking we could do a quick post-mortem of the design project.",
+ "align": "left"
+ }
+ },
+ {
+ "character": "Jake",
+ "startTime": 5.42,
+ "finishTime": 10.42,
+ "dialogue": {
+ "text": "Sure. I was reviewing our security protocols for the project just yesterday. What's on your mind?",
+ "align": "right"
+ }
+ },
+ {
+ "character": "Linda",
+ "startTime": 11.08,
+ "finishTime": 14.44,
+ "dialogue": {
+ "text": "Well, during the project, I was working closely with the development team,",
+ "align": "left"
+ }
+ },
+ {
+ "character": "Linda",
+ "startTime": 14.58,
+ "finishTime": 17.94,
+ "dialogue": {
+ "text": "and we were constantly updating the user interface based on user feedback.",
+ "align": "left"
+ }
+ },
+ {
+ "character": "Jake",
+ "startTime": 18.58,
+ "finishTime": 20.78,
+ "dialogue": {
+ "text": "I noticed that. But there was a time",
+ "align": "right"
+ }
+ },
+ {
+ "character": "Jake",
+ "startTime": 20.78,
+ "finishTime": 24.26,
+ "dialogue": {
+ "text": "when we weren't considering security implications during those updates, right?",
+ "align": "right"
+ }
+ },
+ {
+ "character": "Linda",
+ "startTime": 24.66,
+ "finishTime": 29.14,
+ "dialogue": {
+ "text": "Yes, that's true. We used to focus solely on design aspects and user experience.",
+ "align": "left"
+ }
+ },
+ {
+ "character": "Linda",
+ "startTime": 29.14,
+ "finishTime": 32.18,
+ "dialogue": {
+ "text": "Did you use to check the updates for security vulnerabilities?",
+ "align": "left"
+ }
+ },
+ {
+ "character": "Jake",
+ "startTime": 32.9,
+ "finishTime": 35.5,
+ "dialogue": {
+ "text": "I did, but not always in real time.",
+ "align": "right"
+ }
+ },
+ {
+ "character": "Jake",
+ "startTime": 35.78,
+ "finishTime": 39.12,
+ "dialogue": {
+ "text": "Sometimes I was checking them a day later, which wasn't ideal.",
+ "align": "right"
+ }
+ },
+ {
+ "character": "Linda",
+ "startTime": 39.68,
+ "finishTime": 42.66,
+ "dialogue": {
+ "text": "I remember there was a week when we were all working overtime.",
+ "align": "left"
+ }
+ },
+ {
+ "character": "Linda",
+ "startTime": 43,
+ "finishTime": 45.1,
+ "dialogue": {
+ "text": "You were fixing a security issue, weren't you?",
+ "align": "left"
+ }
+ },
+ {
+ "character": "Jake",
+ "startTime": 45.88,
+ "finishTime": 49.48,
+ "dialogue": {
+ "text": "Exactly. There was a major vulnerability that needed immediate action.",
+ "align": "right"
+ }
+ },
+ {
+ "character": "Jake",
+ "startTime": 49.68,
+ "finishTime": 53.2,
+ "dialogue": {
+ "text": "While I was addressing that, the team was waiting for my green light to proceed.",
+ "align": "right"
+ }
+ },
+ {
+ "character": "Linda",
+ "startTime": 53.72,
+ "finishTime": 55.56,
+ "dialogue": {
+ "text": "It was quite a learning curve for us.",
+ "align": "left"
+ }
+ },
+ {
+ "character": "Linda",
+ "startTime": 55.74,
+ "finishTime": 58.92,
+ "dialogue": {
+ "text": "We didn't use to integrate security and design as much as we should.",
+ "align": "left"
+ }
+ },
+ {
+ "character": "Jake",
+ "startTime": 59.7,
+ "finishTime": 65.94,
+ "dialogue": {
+ "text": "Agreed. Moving forward, we should ensure that security checks are happening while the design updates are being made.",
+ "align": "right"
+ }
+ },
+ {
+ "character": "Jake",
+ "startTime": 66.06,
+ "finishTime": 68.64,
+ "dialogue": {
+ "text": "We can't afford to overlook this aspect again.",
+ "align": "right"
+ }
+ },
+ {
+ "character": "Jake",
+ "position": { "x": 125, "y": 0, "z": 1 },
+ "startTime": 69.14
+ },
+ {
+ "character": "Linda",
+ "position": { "x": -25, "y": 0, "z": 1 },
+ "startTime": 69.64
+ }
+]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670f71de33e0be053934a9c3.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670f71de33e0be053934a9c3.md
new file mode 100644
index 0000000000..24008becf5
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670f71de33e0be053934a9c3.md
@@ -0,0 +1,106 @@
+---
+id: 670f71de33e0be053934a9c3
+title: Task 49
+challengeType: 19
+dashedName: task-49
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What does Linda mean by `postmortem`?
+
+## --answers--
+
+She means a review of the design project after its completion to analyze what went well and what didn't.
+
+---
+
+She means creating a new design for the project.
+
+### --feedback--
+
+A `postmortem` is not about designing something new but about reviewing what happened after a project.
+
+---
+
+She means canceling the design project.
+
+### --feedback--
+
+A `postmortem` is done after a project is completed, not about canceling it.
+
+---
+
+She means reviewing the project before starting it.
+
+### --feedback--
+
+A `postmortem` happens after the project is finished, not before.
+
+## --video-solution--
+
+1
+
+# --explanation--
+
+The term `postmortem` comes from Latin, meaning *after death*, but in a business context, it refers to a meeting or review conducted after the completion of a project to analyze its successes and problems.
+
+This meeting helps organizations learn from their experiences and improve future projects. For example:
+
+`The team conducted a postmortem to discuss the challenges faced during the product launch.` - This means the team met after product launch to discuss the challenges they encountered in the process.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Linda",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 0.5,
+ "finishTimestamp": 4.68
+ }
+ },
+ "commands": [
+ {
+ "character": "Linda",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Linda",
+ "startTime": 0,
+ "finishTime": 4.18,
+ "dialogue": {
+ "text": "I was thinking we could do a quick postmortem of the design project.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Linda",
+ "opacity": 0,
+ "startTime": 4.68
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670f74145be4b907a1b9c915.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670f74145be4b907a1b9c915.md
new file mode 100644
index 0000000000..017e62394f
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/670f74145be4b907a1b9c915.md
@@ -0,0 +1,92 @@
+---
+id: 670f74145be4b907a1b9c915
+title: Task 50
+challengeType: 22
+dashedName: task-50
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`I BLANK BLANK we could do a quick postmortem of the design project.`
+
+## --blanks--
+
+`was`
+
+### --feedback--
+
+This is the auxiliary verb used to form the `Past Continuous` in the singular first-person form.
+
+---
+
+`thinking`
+
+### --feedback--
+
+This is the main verb in the `Past Continuous`. It is used to talk about a process that happens on your mind.
+
+# --explanation--
+
+The `Past Continuous` tense is used to describe actions or thoughts that were in progress at a specific time in the past.
+
+This tense is often used to describe background actions or ongoing processes in the past. The structure is **`was`/`were` + verb ending in `-ing`**.
+
+In this sentence, `I was thinking` shows that Linda's thought about doing a postmortem was in progress at a specific time. Another example:
+
+`He was reviewing the report when the meeting started.` - Meaning that the action of reviewing the report was in progress and another situation interrupted it.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Linda",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 0.5,
+ "finishTimestamp": 4.68
+ }
+ },
+ "commands": [
+ {
+ "character": "Linda",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Linda",
+ "startTime": 0,
+ "finishTime": 4.18,
+ "dialogue": {
+ "text": "I was thinking we could do a quick postmortem of the design project.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Linda",
+ "opacity": 0,
+ "startTime": 4.68
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6710bc2f9f242e03ebeccbe9.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6710bc2f9f242e03ebeccbe9.md
new file mode 100644
index 0000000000..cdee09e739
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6710bc2f9f242e03ebeccbe9.md
@@ -0,0 +1,92 @@
+---
+id: 6710bc2f9f242e03ebeccbe9
+title: Task 51
+challengeType: 19
+dashedName: task-51
+---
+
+
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+How could Jake very briefly tell Linda that he agrees with the idea of having a quick `postmortem`?
+
+## --answers--
+
+`Oh, absolutely. I think doing a postmortem would be a great idea.`
+
+### --feedback--
+
+Even though this is correct, it is not brief. There's a simple, 4-letter word you can use to say exactly the same.
+
+---
+
+`Sure.`
+
+## --video-solution--
+
+2
+
+# --explanation--
+
+When agreeing with someone's idea you can briefly tell a person that by saying `Sure`. For example:
+
+- `Would you like to visit another country some day? Sure.` - This means you want to do it.
+
+- `How about going to the movies this week? Sure.` - This means you accept the invitation.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Linda",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 0.5,
+ "finishTimestamp": 4.68
+ }
+ },
+ "commands": [
+ {
+ "character": "Linda",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Linda",
+ "startTime": 0,
+ "finishTime": 4.18,
+ "dialogue": {
+ "text": "I was thinking we could do a quick postmortem of the design project.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Linda",
+ "opacity": 0,
+ "startTime": 4.68
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6710bf5df20df90498c991a2.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6710bf5df20df90498c991a2.md
new file mode 100644
index 0000000000..6834c3899c
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6710bf5df20df90498c991a2.md
@@ -0,0 +1,106 @@
+---
+id: 6710bf5df20df90498c991a2
+title: Task 52
+challengeType: 19
+dashedName: task-52
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What was Jake doing yesterday?
+
+## --answers--
+
+He was updating the security protocols.
+
+### --feedback--
+
+Jake says he was reviewing the protocols, not updating them.
+
+---
+
+He was designing a new security system.
+
+### --feedback--
+
+Jake was reviewing existing protocols, not designing a new system.
+
+---
+
+He was reviewing the security protocols for the project.
+
+---
+
+He was fixing a bug in the project.
+
+### --feedback--
+
+Jake's focus was on reviewing the security protocols, not fixing a bug.
+
+## --video-solution--
+
+3
+
+# --explanation--
+
+The `Past Continuous` tense often emphasizes the duration or background of an action in the past. It is used to describe an action that was ongoing at a specific time in the past. The structure is: **`was`/`were` + verb ending in `-ing`**.
+
+In Jake's sentence, `I was reviewing` shows that the action of reviewing was in progress yesterday. Another example:
+
+`She was testing the new feature when the system crashed.` - Here, the crashing of the system happened in the middle of her action of testing the new feature - the test was a longer ongoing action.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Jake",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 4.42,
+ "finishTimestamp": 8.7
+ }
+ },
+ "commands": [
+ {
+ "character": "Jake",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Jake",
+ "startTime": 1,
+ "finishTime": 5.28,
+ "dialogue": {
+ "text": "Sure. I was reviewing our security protocols for the project just yesterday.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Jake",
+ "opacity": 0,
+ "startTime": 5.78
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6710c59075616806206fcf44.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6710c59075616806206fcf44.md
new file mode 100644
index 0000000000..efca669837
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6710c59075616806206fcf44.md
@@ -0,0 +1,90 @@
+---
+id: 6710c59075616806206fcf44
+title: Task 53
+challengeType: 22
+dashedName: task-53
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`Sure. I was reviewing our BLANK BLANK for the project just yesterday.`
+
+## --blanks--
+
+`security`
+
+### --feedback--
+
+This word refers to measures or procedures taken to protect systems or data.
+
+---
+
+`protocols`
+
+### --feedback--
+
+This word refers to rules or procedures that need to be followed in specific situations.
+
+# --explanation--
+
+A `protocol` is a set of rules or procedures designed to guide behavior or processes. A `security protocol` refers to specific procedures designed to protect systems, networks, or data from unauthorized access or threats. For example:
+
+`Our security protocols require two-factor authentication for all logins.` - This means that the use of two-factor authentication for logging in is a part of the procedures related to protecting the system.
+
+In this sentence, Jake is referring to reviewing the rules and procedures (the `protocols`) designed to ensure the project's security.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Jake",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 4.42,
+ "finishTimestamp": 8.7
+ }
+ },
+ "commands": [
+ {
+ "character": "Jake",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Jake",
+ "startTime": 1,
+ "finishTime": 5.28,
+ "dialogue": {
+ "text": "Sure. I was reviewing our security protocols for the project just yesterday.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Jake",
+ "opacity": 0,
+ "startTime": 5.78
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6710c7bd388290075f19552c.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6710c7bd388290075f19552c.md
new file mode 100644
index 0000000000..d5af040376
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6710c7bd388290075f19552c.md
@@ -0,0 +1,106 @@
+---
+id: 6710c7bd388290075f19552c
+title: Task 54
+challengeType: 19
+dashedName: task-54
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What is Jake asking Linda?
+
+## --answers--
+
+He is asking what Linda is working on.
+
+### --feedback--
+
+Jake is asking about her thoughts, not her current task.
+
+---
+
+He is asking what Linda is thinking about.
+
+---
+
+He is asking if Linda is busy.
+
+### --feedback--
+
+Jake's question is about her thoughts, not her availability.
+
+---
+
+He is asking if Linda is worried about something.
+
+### --feedback--
+
+While the question could refer to concerns, it is more general, asking about what she is thinking.
+
+## --video-solution--
+
+2
+
+# --explanation--
+
+`What's on your mind?` is used to ask someone what they are thinking about or if they have any concerns or thoughts they want to share.
+
+It's often used in both personal and professional settings to encourage open communication. It is a conversational way to invite someone to express their thoughts. For example:
+
+`You seem quiet today. What's on your mind?` - You are asking the other person what they are thinking about.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Jake",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 8.72,
+ "finishTimestamp": 9.62
+ }
+ },
+ "commands": [
+ {
+ "character": "Jake",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Jake",
+ "startTime": 1,
+ "finishTime": 1.9,
+ "dialogue": {
+ "text": "What's on your mind?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Jake",
+ "opacity": 0,
+ "startTime": 2.4
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6710e0e2cafeeb09e6cb2d8f.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6710e0e2cafeeb09e6cb2d8f.md
new file mode 100644
index 0000000000..267bc8ff84
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6710e0e2cafeeb09e6cb2d8f.md
@@ -0,0 +1,115 @@
+---
+id: 6710e0e2cafeeb09e6cb2d8f
+title: Task 55
+challengeType: 22
+dashedName: task-55
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`Well, during the project, I BLANK BLANK closely with the development team, and we BLANK constantly BLANK the user interface based on user feedback.`
+
+## --blanks--
+
+`was`
+
+### --feedback--
+
+This is the auxiliary verb used to form the `Past Continuous` in the singular first-person form.
+
+---
+
+`working`
+
+### --feedback--
+
+This is the main verb in the `Past Continuous`, describing the act of laboring.
+
+---
+
+`were`
+
+### --feedback--
+
+This is the auxiliary verb used to form the `Past Continuous` in the plural first-person form.
+
+---
+
+`updating`
+
+### --feedback--
+
+This is the main verb in the `Past Continuous`, describing an ongoing action of improving or modernizing something.
+
+# --explanation--
+
+The `Past Continuous` tense is used to describe actions that were ongoing at a specific time in the past. When two `Past Continuous` sentences are used together, they often describe simultaneous actions or actions happening alongside each other.
+
+In this sentence, Linda is describing how she and her team were both working and updating the user interface continuously throughout the project. This shows two actions happening at the same time in the past, providing context or background for each other. For example:
+
+`While I was preparing the report, they were testing the new features.` - This means the action of my preparing the report and the testing of the new features happened at the same time.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Linda",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 10.08,
+ "finishTimestamp": 17.34
+ }
+ },
+ "commands": [
+ {
+ "character": "Linda",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Linda",
+ "startTime": 1,
+ "finishTime": 4.36,
+ "dialogue": {
+ "text": "Well, during the project, I was working closely with the development team,",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Linda",
+ "startTime": 4.5,
+ "finishTime": 8.26,
+ "dialogue": {
+ "text": "and we were constantly updating the user interface based on user feedback.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Linda",
+ "opacity": 0,
+ "startTime": 8.76
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6710e614f70bd10afb6ca7f7.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6710e614f70bd10afb6ca7f7.md
new file mode 100644
index 0000000000..9b7e8768f3
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6710e614f70bd10afb6ca7f7.md
@@ -0,0 +1,107 @@
+---
+id: 6710e614f70bd10afb6ca7f7
+title: Task 56
+challengeType: 22
+dashedName: task-56
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`Well, during the project, I was working BLANK with the development team, and we were BLANK updating the user interface based on user feedback.`
+
+## --blanks--
+
+`closely`
+
+### --feedback--
+
+This word is an adverb describing how someone works in a careful, detailed, or collaborative way.
+
+---
+
+`constantly`
+
+### --feedback--
+
+This word is an adverb describing an action that happens continuously or very frequently.
+
+# --explanation--
+
+`Closely` is an adverb that means working in a careful, detailed, or collaborative way. It is related to the adjective `close`, which refers to a short distance or a strong relationship. For example:
+
+- `The manager worked closely with the design team.` - This sentence uses the adverb, which describes how they worked.
+
+- `They have a close relationship.` - This sentence uses the adjective, which describes the relationship.
+
+`Constantly` is an adverb that describes something that happens continuously or very frequently. It is related to the adjective `constant`, which refers to something that does not change or stops. For example:
+
+- `She constantly checks her emails throughout the day.` - This sentence uses the adverb, which describes the frequency of the action of checking.
+
+- `There was a constant need for updates.` - This sentence uses the adjective, which describes the need as being frequent.
+
+In the sentence, Linda uses `closely` to describe how her collaboration with the team was and `constantly` to show how frequently they updated the user interface.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Linda",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 10.08,
+ "finishTimestamp": 17.34
+ }
+ },
+ "commands": [
+ {
+ "character": "Linda",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Linda",
+ "startTime": 1,
+ "finishTime": 4.36,
+ "dialogue": {
+ "text": "Well, during the project, I was working closely with the development team,",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Linda",
+ "startTime": 4.5,
+ "finishTime": 8.26,
+ "dialogue": {
+ "text": "and we were constantly updating the user interface based on user feedback.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Linda",
+ "opacity": 0,
+ "startTime": 8.76
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6710ef64fecf900ca5296978.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6710ef64fecf900ca5296978.md
new file mode 100644
index 0000000000..187e9c47d5
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6710ef64fecf900ca5296978.md
@@ -0,0 +1,119 @@
+---
+id: 6710ef64fecf900ca5296978
+title: Task 57
+challengeType: 19
+dashedName: task-57
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What did the development team use to constantly update the user interface?
+
+## --answers--
+
+They used user feedback.
+
+---
+
+They used new features.
+
+### --feedback--
+
+Linda says they updated the user interface based on user feedback, not new features.
+
+---
+
+They used system logs.
+
+### --feedback--
+
+Linda specifically mentions user feedback, not system logs, as the source for updates.
+
+---
+
+They used bug reports.
+
+### --feedback--
+
+While bug reports are important, Linda refers to user feedback for updating the user interface.
+
+## --video-solution--
+
+1
+
+# --explanation--
+
+The `user interface` (UI) refers to the part of a system or software that users interact with directly, such as buttons, menus, and screens. For example:
+
+`The user interface was redesigned to be more intuitive.` - Meaning the part of the software the user interacts with was improved.
+
+`User feedback` refers to opinions, suggestions, or issues reported by users about their experience with a product or service. For example:
+
+`The company improved the app based on user feedback.` - Meaning the comments and suggestions coming from the users were read and used to make the app better.
+
+In this context, Linda explains that the team relied on user feedback to make constant improvements to the user interface, ensuring it met the needs of users.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Linda",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 10.08,
+ "finishTimestamp": 17.34
+ }
+ },
+ "commands": [
+ {
+ "character": "Linda",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Linda",
+ "startTime": 1,
+ "finishTime": 4.36,
+ "dialogue": {
+ "text": "Well, during the project, I was working closely with the development team,",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Linda",
+ "startTime": 4.5,
+ "finishTime": 8.26,
+ "dialogue": {
+ "text": "and we were constantly updating the user interface based on user feedback.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Linda",
+ "opacity": 0,
+ "startTime": 8.76
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67121364e79da2047818b743.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67121364e79da2047818b743.md
new file mode 100644
index 0000000000..685bdc81e8
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67121364e79da2047818b743.md
@@ -0,0 +1,107 @@
+---
+id: 67121364e79da2047818b743
+title: Task 58
+challengeType: 19
+dashedName: task-58
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What does Jake mean when he says `I noticed that`?
+
+## --answers--
+
+
+He means he ignored it.
+
+### --feedback--
+
+`Notice` refers to observing or becoming aware of something, not ignoring it.
+
+---
+
+He means he forgot about it.
+
+### --feedback--
+
+`Notice` refers to paying attention, not forgetting.
+
+---
+
+He means he became aware of it or observed it.
+
+---
+
+He means he created it.
+
+### --feedback--
+
+`Notice` refers to observing something, not creating it.
+
+## --video-solution--
+
+3
+
+# --explanation--
+
+`Notice` means to become aware of something by seeing, hearing, or sensing it. It often implies paying attention to details. For example:
+
+`I noticed the error in the report before the meeting.` - This means you saw there was an error.
+
+It can refer to becoming aware of both physical things and situations. In this sentence, Jake means that he observed or became aware that the team was using user feedback to improve the user interface.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Jake",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 17.58,
+ "finishTimestamp": 18.7
+ }
+ },
+ "commands": [
+ {
+ "character": "Jake",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Jake",
+ "startTime": 1,
+ "finishTime": 2.12,
+ "dialogue": {
+ "text": "I noticed that.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Jake",
+ "opacity": 0,
+ "startTime": 2.62
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67121be3d5093805dfdbaa71.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67121be3d5093805dfdbaa71.md
new file mode 100644
index 0000000000..d5f941c9ca
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67121be3d5093805dfdbaa71.md
@@ -0,0 +1,108 @@
+---
+id: 67121be3d5093805dfdbaa71
+title: Task 59
+challengeType: 22
+dashedName: task-59
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`I noticed that. But there was a time when we BLANK BLANK security implications during those updates, right?`
+
+## --blanks--
+
+`weren't`
+
+### --feedback--
+
+This is the negative form of the auxiliary verb `to be` in the `Past Continuous`, used for **plural** subjects.
+
+---
+
+`considering`
+
+### --feedback--
+
+This is the main verb in the `Past Continuous`. It has to do with thinking carefully about something.
+
+# --explanation--
+
+The `Past Continuous` in its negative form is used to describe actions that were not happening at a specific time in the past. The structure is:
+**`wasn't` / `weren't` + verb ending in `-ing`**. For example:
+
+- `He wasn't listening during the meeting.` - This sentence uses the singular form `was`
+
+- `They weren't following the instructions carefully.` - This sentence uses the plural form `were`.
+
+In this context, `weren't considering` means that, at a certain point in the past, the team was not taking security implications into account while performing updates.
+
+The verb `consider` means to think carefully about something before making a decision or taking action. For example:
+
+`We need to consider all options before finalizing the project plan.` - Meaning it's necessary to think about the options.
+
+In Jake's sentence, `considering` refers to the team evaluating or thinking about security implications.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Jake",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 17.58,
+ "finishTimestamp": 23.46
+ }
+ },
+ "commands": [
+ {
+ "character": "Jake",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Jake",
+ "startTime": 1,
+ "finishTime": 3.2,
+ "dialogue": {
+ "text": "I noticed that. But there was a time",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Jake",
+ "startTime": 3.2,
+ "finishTime": 6.88,
+ "dialogue": {
+ "text": "when we weren't considering security implications during those updates, right?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Jake",
+ "opacity": 0,
+ "startTime": 7.38
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67121d26052fb606bd59705c.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67121d26052fb606bd59705c.md
new file mode 100644
index 0000000000..83de71ed0c
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67121d26052fb606bd59705c.md
@@ -0,0 +1,115 @@
+---
+id: 67121d26052fb606bd59705c
+title: Task 60
+challengeType: 19
+dashedName: task-60
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What does Jake mean with his question?
+
+## --answers--
+
+He is asking if the team always considered security implications.
+
+### --feedback--
+
+Jake's question suggests there might have been a time when security was overlooked.
+
+---
+
+He is asking if security was never important.
+
+### --feedback--
+
+Jake's question focuses on whether there was a specific time when security wasn't considered, not on its overall importance.
+
+---
+
+He is asking if the updates were unnecessary.
+
+### --feedback--
+
+Jake is asking about the consideration of security implications, not the necessity of the updates.
+
+---
+
+He is asking if there was a time when security concerns were not taken into account during the updates.
+
+## --video-solution--
+
+4
+
+# --explanation--
+
+`Implications` refers to the possible results or effects of an action or decision, especially those that are not immediately obvious. In this context, `security implications` are the potential consequences of not considering security during updates. For example:
+
+`Before launching the new feature, the team discussed the implications for user privacy.` - Meaning they discussed the possible consequences to user privacy that this new feature could bring.
+
+In Jake's question, he is referring to the potential negative outcomes of not considering security during past updates.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Jake",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 17.58,
+ "finishTimestamp": 23.46
+ }
+ },
+ "commands": [
+ {
+ "character": "Jake",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Jake",
+ "startTime": 1,
+ "finishTime": 3.2,
+ "dialogue": {
+ "text": "I noticed that. But there was a time",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Jake",
+ "startTime": 3.2,
+ "finishTime": 6.88,
+ "dialogue": {
+ "text": "when we weren't considering security implications during those updates, right?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Jake",
+ "opacity": 0,
+ "startTime": 7.38
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67122e8300d8e90843b04967.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67122e8300d8e90843b04967.md
new file mode 100644
index 0000000000..f6a79172da
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67122e8300d8e90843b04967.md
@@ -0,0 +1,110 @@
+---
+id: 67122e8300d8e90843b04967
+title: Task 61
+challengeType: 19
+dashedName: task-61
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What did the team normally pay attention to exclusively in the past?
+
+## --answers--
+
+They focused solely on design aspects and user experience.
+
+---
+
+They focused on security protocols.
+
+### --feedback--
+
+Linda specifically says they focused on design aspects and user experience, not security.
+
+---
+
+They paid attention to marketing strategies.
+
+### --feedback--
+
+Linda refers to focusing on design and user experience, not marketing.
+
+---
+
+They worked only on backend development.
+
+### --feedback--
+
+Linda says the team concentrated on design aspects and user experience, not backend development.
+
+## --video-solution--
+
+1
+
+# --explanation--
+
+`Used to` refers to actions or situations that were habitual or true in the past but are no longer the case. For example:
+
+`We used to have weekly team meetings, but now we meet monthly.` - This means it was the team's habit to meet more frequently in the past - once a week instead of once a month, as they do now.
+
+`Solely` means exclusively or only. It emphasizes that something was the only focus or priority. For example:
+
+`The company is solely focused on developing new technology.` - Meaning this is the **only** thing the company wants to concentrate its efforts on.
+
+In this sentence, Linda explains that the team previously focused only on design and user experience, with no consideration for other aspects like security.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Linda",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 23.66,
+ "finishTimestamp": 28.54
+ }
+ },
+ "commands": [
+ {
+ "character": "Linda",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Linda",
+ "startTime": 1,
+ "finishTime": 5.88,
+ "dialogue": {
+ "text": "Yes, that's true. We used to focus solely on design aspects and user experience.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Linda",
+ "opacity": 0,
+ "startTime": 6.38
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67176c867303f30476f3d126.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67176c867303f30476f3d126.md
new file mode 100644
index 0000000000..ef0eec257a
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67176c867303f30476f3d126.md
@@ -0,0 +1,90 @@
+---
+id: 67176c867303f30476f3d126
+title: Task 62
+challengeType: 22
+dashedName: task-62
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`Yes, that's true. We used to focus solely on design aspects and BLANK BLANK.`
+
+## --blanks--
+
+`user`
+
+### --feedback--
+
+This word refers to the person who interacts with a product or system.
+
+---
+
+`experience`
+
+### --feedback--
+
+This word refers to how a person feels when using a product or system.
+
+# --explanation--
+
+`User experience` (UX) refers to the overall experience a person has when interacting with a product, system, or service, including ease of use, satisfaction, and efficiency. For example:
+
+`Improving the user experience on our website increased customer satisfaction.` - This means that the look and feel of the site and how the user interacts to it was changed and this generated positive results.
+
+In this sentence, Linda mentions that the team used to focus on how users interacted with and felt about the design of their product.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Linda",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 23.66,
+ "finishTimestamp": 28.54
+ }
+ },
+ "commands": [
+ {
+ "character": "Linda",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Linda",
+ "startTime": 1,
+ "finishTime": 5.88,
+ "dialogue": {
+ "text": "Yes, that's true. We used to focus solely on design aspects and user experience.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Linda",
+ "opacity": 0,
+ "startTime": 6.38
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717756d3483e6060d2cd800.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717756d3483e6060d2cd800.md
new file mode 100644
index 0000000000..c48c4f5ffa
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717756d3483e6060d2cd800.md
@@ -0,0 +1,110 @@
+---
+id: 6717756d3483e6060d2cd800
+title: Task 63
+challengeType: 19
+dashedName: task-63
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What is Linda asking in this question?
+
+## --answers--
+
+She is asking if security updates are currently being checked.
+
+### --feedback--
+
+Linda's question is about a past habit, not about the current practice.
+
+---
+
+She is asking if checking for security vulnerabilities was a regular practice in the past.
+
+---
+
+She is asking if security vulnerabilities are easy to fix.
+
+### --feedback--
+
+Linda's question is about whether they used to check for vulnerabilities, not their ease of fixing.
+
+---
+
+She is asking if vulnerabilities were ignored.
+
+### --feedback--
+
+Linda is asking if they regularly checked for vulnerabilities, not if they were ignored.
+
+## --video-solution--
+
+2
+
+# --explanation--
+
+In the interrogative form, `used to` asks about past habits or routines that may no longer be true. The structure is: `Did` + subject + `use to` + base verb`?` For example:
+
+`Did you use to attend weekly meetings?` - You are asking if the other person normally attended the meetings.
+
+A `vulnerability` is a weakness or flaw that can be exploited, especially in the context of security. For example:
+
+`The team identified a vulnerability in the system that needed immediate attention.` - There was a weak spot in the system that had to be dealt with.
+
+In this sentence, Linda is asking if checking updates for security weaknesses was a regular part of their past process.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Linda",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 28.54,
+ "finishTimestamp": 31.78
+ }
+ },
+ "commands": [
+ {
+ "character": "Linda",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Linda",
+ "startTime": 1,
+ "finishTime": 4.24,
+ "dialogue": {
+ "text": "Did you use to check the updates for security vulnerabilities?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Linda",
+ "opacity": 0,
+ "startTime": 4.74
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671775877ee558061e6eebf8.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671775877ee558061e6eebf8.md
new file mode 100644
index 0000000000..206292eda3
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671775877ee558061e6eebf8.md
@@ -0,0 +1,90 @@
+---
+id: 671775877ee558061e6eebf8
+title: Task 64
+challengeType: 22
+dashedName: task-64
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`I did, but not always in BLANK BLANK.`
+
+## --blanks--
+
+`real`
+
+### --feedback--
+
+This word refers to something happening in the actual moment it occurs.
+
+---
+
+`time`
+
+### --feedback--
+
+This word refers to the ongoing or current moment in which events happen.
+
+# --explanation--
+
+The phrase `in real time` refers to something happening immediately as events occur, without delay. It is often used in the context of monitoring, communication, or data processing. For example:
+
+`The system updates the dashboard in real time, so you can see changes instantly.` - Meaning the dashboard changes immediately after the updates after the updates are applied.
+
+In Jake's sentence, he means that while he checked for security vulnerabilities, it wasn't always done immediately as the updates happened.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Jake",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 31.9,
+ "finishTimestamp": 34.7
+ }
+ },
+ "commands": [
+ {
+ "character": "Jake",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Jake",
+ "startTime": 1,
+ "finishTime": 3.8,
+ "dialogue": {
+ "text": "I did, but not always in real time.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Jake",
+ "opacity": 0,
+ "startTime": 4.3
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671775a360c128062f906b24.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671775a360c128062f906b24.md
new file mode 100644
index 0000000000..10f827b127
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671775a360c128062f906b24.md
@@ -0,0 +1,106 @@
+---
+id: 671775a360c128062f906b24
+title: Task 65
+challengeType: 19
+dashedName: task-65
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What did Jake think about checking the updates a day later?
+
+## --answers--
+
+He thought it wasn't ideal.
+
+---
+
+He thought it was the best solution.
+
+### --feedback--
+
+Jake explicitly says it wasn't ideal.
+
+---
+
+He didn't think it was a problem.
+
+### --feedback--
+
+Jake's comment shows that he recognized it wasn't an ideal approach.
+
+---
+
+He thought it was impossible.
+
+### --feedback--
+
+Jake mentions that he did check them a day later, but it wasn't ideal.
+
+## --video-solution--
+
+1
+
+# --explanation--
+
+`Which` is a relative pronoun used to provide additional information about something mentioned earlier in the sentence. In this case, `which` refers to the entire idea of checking the updates a day later and clarifies that it wasn't ideal. For example:
+
+`She missed the deadline, which caused a delay in the project.` - Here, `which` refers to `missing the deadline` and explains the resulting delay.
+
+Similarly, Jake uses `which` to express that checking updates a day later wasn't the best practice.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Jake",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 34.78,
+ "finishTimestamp": 38.52
+ }
+ },
+ "commands": [
+ {
+ "character": "Jake",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Jake",
+ "startTime": 1,
+ "finishTime": 4.74,
+ "dialogue": {
+ "text": "Sometimes I was checking them a day later, which wasn't ideal.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Jake",
+ "opacity": 0,
+ "startTime": 5.24
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671775bb104def063ffbdaab.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671775bb104def063ffbdaab.md
new file mode 100644
index 0000000000..6e0e6ecb27
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671775bb104def063ffbdaab.md
@@ -0,0 +1,82 @@
+---
+id: 671775bb104def063ffbdaab
+title: Task 66
+challengeType: 22
+dashedName: task-66
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`I remember there was a week when we were all working BLANK.`
+
+## --blanks--
+
+`overtime`
+
+### --feedback--
+
+This word refers to working beyond the regular hours.
+
+# --explanation--
+
+`To work overtime` means to work extra hours beyond the standard schedule, often to meet deadlines or complete urgent tasks. For example:
+
+`The team had to work overtime to finish the project before the deadline.` - Meaning you had to work extra hours to complete the project in order to meet the deadline.
+
+In this sentence, Linda is recalling a specific week when everyone had to put in extra hours to meet the demands of their work.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Linda",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 38.78,
+ "finishTimestamp": 42.16
+ }
+ },
+ "commands": [
+ {
+ "character": "Linda",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Linda",
+ "startTime": 1,
+ "finishTime": 4.38,
+ "dialogue": {
+ "text": "I remember there was a week when we were all working overtime.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Linda",
+ "opacity": 0,
+ "startTime": 4.58
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671775db2ecd44064fdb1f04.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671775db2ecd44064fdb1f04.md
new file mode 100644
index 0000000000..aa3b704542
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671775db2ecd44064fdb1f04.md
@@ -0,0 +1,94 @@
+---
+id: 671775db2ecd44064fdb1f04
+title: Task 67
+challengeType: 22
+dashedName: task-67
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`You were fixing a security issue, BLANK you?`
+
+## --blanks--
+
+`weren't`
+
+### --feedback--
+
+This word is part of a tag question using the auxiliary verb for the `Past Continuous`. It is used to confirm or seek agreement about something.
+
+# --explanation--
+
+`Tag questions` are short questions added to the end of a statement to confirm information or seek agreement. The structure depends on the main sentence:
+
+If the main sentence is positive, the tag is negative. For example:
+
+`You were working late, weren't you?` - You want to confirm if the other person was working late - you believe they were.
+
+If the main sentence is negative, the tag is positive. For Example:
+
+`You weren't at the meeting, were you?` - You want to confirm if the person did not attend the meeting - you believe they didn't.
+
+In this sentence, Linda uses the tag question `weren't you?` to confirm if Jake was fixing a security issue, because she thinks he was.
+
+A `security issue` refers to a problem or vulnerability that could compromise the safety or protection of a system, data, or user. For example:
+
+`The team addressed a security issue that allowed unauthorized access.` - meaning the team had to deal with a problem in security that was giving access to people without the proper authorization.
+
+In this context, Linda is asking about Jake's work on a specific problem related to security because she vividly remembers that was what was happening at the time.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Linda",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 42.2,
+ "finishTimestamp": 44.3
+ }
+ },
+ "commands": [
+ {
+ "character": "Linda",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Linda",
+ "startTime": 1,
+ "finishTime": 3.1,
+ "dialogue": {
+ "text": "You were fixing a security issue, weren't you?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Linda",
+ "opacity": 0,
+ "startTime": 3.6
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671775f2f55c4c066193a1c1.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671775f2f55c4c066193a1c1.md
new file mode 100644
index 0000000000..22334a1aa5
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671775f2f55c4c066193a1c1.md
@@ -0,0 +1,94 @@
+---
+id: 671775f2f55c4c066193a1c1
+title: Task 68
+challengeType: 19
+dashedName: task-68
+---
+
+
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+How could Jake tell Linda that was precisely what was happening at that time?
+
+## --answers--
+
+`Exactly.`
+
+---
+
+`I think so.`
+
+### --feedback--
+
+This answer means you agree with the other person, you believe they are right, but you are not sure of it.
+
+## --video-solution--
+
+1
+
+# --explanation--
+
+`Exactly` is used to confirm or strongly agree with something someone else has said. It indicates that the statement is fully correct. For example:
+
+Person 1: `Did you mean we should start testing today?`
+
+Person 2: `Exactly.` - meaning you are sure the tests should start today.
+
+In this context, Jake could say `Exactly` to confirm that he was indeed fixing a security issue back then as Linda mentioned.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Linda",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 42.2,
+ "finishTimestamp": 44.3
+ }
+ },
+ "commands": [
+ {
+ "character": "Linda",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Linda",
+ "startTime": 1,
+ "finishTime": 3.1,
+ "dialogue": {
+ "text": "You were fixing a security issue, weren't you?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Linda",
+ "opacity": 0,
+ "startTime": 3.6
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717760c06f5e10671ef0268.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717760c06f5e10671ef0268.md
new file mode 100644
index 0000000000..357f3e67bc
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717760c06f5e10671ef0268.md
@@ -0,0 +1,94 @@
+---
+id: 6717760c06f5e10671ef0268
+title: Task 69
+challengeType: 22
+dashedName: task-69
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`Exactly. There was a major BLANK that needed BLANK action.`
+
+## --blanks--
+
+`vulnerability`
+
+### --feedback--
+
+This word refers to a weakness or flaw in a system that could be exploited.
+
+---
+
+`immediate`
+
+### --feedback--
+
+This word refers to something happening right away.
+
+# --explanation--
+
+A `major vulnerability` is a significant weakness or flaw in a system that could lead to serious consequences if exploited. It usually requires urgent attention to protect the system or data. For example:
+
+`The team discovered a major vulnerability in the software that could allow unauthorized access.` - This means the weakness was a serious one.
+
+`Immediate action` refers to steps that must be taken right away to address a pressing issue or problem. For example:
+
+`When the server crashed, the team took immediate action to restore functionality.` - This means the team acted as fast as they could to restore the server's functionality.
+
+In this dialogue, Jake explains that the vulnerability was serious enough to require urgent measures to prevent potential risks.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Jake",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 44.68,
+ "finishTimestamp": 48.68
+ }
+ },
+ "commands": [
+ {
+ "character": "Jake",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Jake",
+ "startTime": 1,
+ "finishTime": 5,
+ "dialogue": {
+ "text": "Exactly. There was a major vulnerability that needed immediate action.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Jake",
+ "opacity": 0,
+ "startTime": 5.5
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717b543037e030fc7008aa7.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717b543037e030fc7008aa7.md
new file mode 100644
index 0000000000..e3aa46bac9
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717b543037e030fc7008aa7.md
@@ -0,0 +1,106 @@
+---
+id: 6717b543037e030fc7008aa7
+title: Task 70
+challengeType: 22
+dashedName: task-70
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`While I BLANK BLANK that, the team BLANK BLANK for my green light to proceed.`
+
+## --blanks--
+
+`was`
+
+### --feedback--
+
+This is the auxiliary verb used to form the `Past Continuous` in the singular first-person form.
+
+---
+
+`addressing`
+
+### --feedback--
+
+This is the main verb in the `Past Continuous`. It means to deal with or resolve something.
+
+---
+
+`was`
+
+### --feedback--
+
+This is the auxiliary verb used to form the `Past Continuous` in the singular third-person form.
+
+---
+
+`waiting`
+
+### --feedback--
+
+This is the main verb in the `Past Continuous`. It means to remain ready or expect something.
+
+# --explanation--
+
+The verb `address` in this context means to deal with or resolve an issue or problem. Jake was focusing on resolving the matter while the team waited for his approval. For example:
+
+`The manager addressed the client's concerns during the meeting.` - Here, `addressed` refers to taking action to deal with the client's concerns.
+
+In the sentence, Jake uses the `Past Continuous` (`was addressing`) to describe the ongoing action of resolving the issue while another ongoing action (`the team was waiting`) happened simultaneously.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Jake",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 48.78,
+ "finishTimestamp": 52.5
+ }
+ },
+ "commands": [
+ {
+ "character": "Jake",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Jake",
+ "startTime": 1,
+ "finishTime": 4.72,
+ "dialogue": {
+ "text": "While I was addressing that, the team was waiting for my green light to proceed.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Jake",
+ "opacity": 0,
+ "startTime": 5.22
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717b55fb3b4160fd757b7af.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717b55fb3b4160fd757b7af.md
new file mode 100644
index 0000000000..eb1a5ee7c8
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717b55fb3b4160fd757b7af.md
@@ -0,0 +1,106 @@
+---
+id: 6717b55fb3b4160fd757b7af
+title: Task 71
+challengeType: 19
+dashedName: task-71
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What was the team waiting for in order to resume their work?
+
+## --answers--
+
+They were waiting for Jake to fix everything.
+
+### --feedback--
+
+While Jake was resolving an issue, the team was specifically waiting for his green light, or permission, to continue.
+
+---
+
+They were waiting for new instructions.
+
+### --feedback--
+
+Jake's sentence focuses on the team waiting for his approval, not new instructions.
+
+---
+
+They were waiting for the system to restart.
+
+### --feedback--
+
+Jake doesn't mention the system restarting. The team was waiting for his permission.
+
+---
+
+They were waiting for Jake's permission or authorization.
+
+## --video-solution--
+
+4
+
+# --explanation--
+
+`Green light` in this context means approval or permission to start or continue an activity. It is often used figuratively to represent a signal to proceed. For example:
+
+`The manager gave the green light to launch the new product.` - Meaning the manager authorized the launch.
+
+In this sentence, Jake explains that the team was waiting for his permission to resume their work while he was resolving an issue.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Jake",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 48.78,
+ "finishTimestamp": 52.5
+ }
+ },
+ "commands": [
+ {
+ "character": "Jake",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Jake",
+ "startTime": 1,
+ "finishTime": 4.72,
+ "dialogue": {
+ "text": "While I was addressing that, the team was waiting for my green light to proceed.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Jake",
+ "opacity": 0,
+ "startTime": 5.22
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717b5754dcaae0fe7bb179b.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717b5754dcaae0fe7bb179b.md
new file mode 100644
index 0000000000..e1147fd638
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717b5754dcaae0fe7bb179b.md
@@ -0,0 +1,82 @@
+---
+id: 6717b5754dcaae0fe7bb179b
+title: Task 72
+challengeType: 22
+dashedName: task-72
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`It was BLANK a learning curve for us.`
+
+## --blanks--
+
+`quite`
+
+### --feedback--
+
+This word is used to emphasize the degree or extent of something.
+
+# --explanation--
+
+`Quite` is used in this context to emphasize the significant degree or extent of the learning curve. It adds intensity, suggesting that the learning experience was challenging or noteworthy. For example:
+
+`The project was quite a success, exceeding all expectations.` - Here, `quite` highlights the extent of the project's success.
+
+In Linda's sentence, it emphasizes that the learning curve was substantial for the team.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Linda",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 52.72,
+ "finishTimestamp": 54.76
+ }
+ },
+ "commands": [
+ {
+ "character": "Linda",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Linda",
+ "startTime": 1,
+ "finishTime": 3.04,
+ "dialogue": {
+ "text": "It was quite a learning curve for us.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Linda",
+ "opacity": 0,
+ "startTime": 3.54
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717b59830cdb50ff9f67623.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717b59830cdb50ff9f67623.md
new file mode 100644
index 0000000000..0fd27a8fee
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717b59830cdb50ff9f67623.md
@@ -0,0 +1,106 @@
+---
+id: 6717b59830cdb50ff9f67623
+title: Task 73
+challengeType: 19
+dashedName: task-73
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What did Linda think about working with the security aspects of the project?
+
+## --answers--
+
+She thought it was easy and required no learning.
+
+### --feedback--
+
+A `learning curve` implies there were challenges and a need to learn new things, not ease.
+
+---
+
+She thought it was unnecessary to work on security aspects.
+
+### --feedback--
+
+Linda's comment suggests that working on security aspects was a valuable learning experience, not unnecessary.
+
+---
+
+She thought it was a challenging but educational experience.
+
+---
+
+She thought it was unrelated to the project.
+
+### --feedback--
+
+Linda's comment directly relates to the team's work on security aspects, describing it as a significant learning experience.
+
+## --video-solution--
+
+3
+
+# --explanation--
+
+`Learning curve` refers to the time, effort, and challenges involved in gaining knowledge or mastering a new skill. For example:
+
+`Switching to the new software was a steep learning curve for the employees.` - This implies the employees had a lot of difficulty learning how to operate the new software.
+
+In this context, Linda is describing how working with security aspects required the team to learn and adapt, and that they possibly faced some difficulties along the way.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Linda",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 52.72,
+ "finishTimestamp": 54.76
+ }
+ },
+ "commands": [
+ {
+ "character": "Linda",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Linda",
+ "startTime": 1,
+ "finishTime": 3.04,
+ "dialogue": {
+ "text": "It was quite a learning curve for us.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Linda",
+ "opacity": 0,
+ "startTime": 3.54
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717b5b2b0c1d21009b2b0fd.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717b5b2b0c1d21009b2b0fd.md
new file mode 100644
index 0000000000..9f42eb53c5
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717b5b2b0c1d21009b2b0fd.md
@@ -0,0 +1,94 @@
+---
+id: 6717b5b2b0c1d21009b2b0fd
+title: Task 74
+challengeType: 22
+dashedName: task-74
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`We BLANK BLANK to integrate security and design as much as we should.`
+
+## --blanks--
+
+`didn't`
+
+### --feedback--
+
+This is the auxiliary verb of the simple tenses in the negative form. It shows that the action this was not a habit in the past.
+
+---
+
+`use`
+
+### --feedback--
+
+This is the base form of the verb used for past habits, not conjugated in its past form here, because the auxiliary verb `didn't` carries the past tense.
+
+# --explanation--
+
+In negative sentences with `used to`, the auxiliary verb `didn't` is used to indicate the past, and the main verb `use` remains in its base form (not conjugated).
+
+This structure emphasizes that an action was not habitual or common in the past.
+
+**Important:** The auxiliary verb `didn't` makes the sentence negative. The verb `use` stays in its base form because the past tense is already conveyed by `didn't`. For example:
+
+`We didn't use to have weekly meetings, but now we do.` - This means weekly meetings were not common back then.
+
+In Linda's sentence, she is saying that integrating security and design was not a regular practice in the past.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Linda",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 55.04,
+ "finishTimestamp": 58.22
+ }
+ },
+ "commands": [
+ {
+ "character": "Linda",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Linda",
+ "startTime": 1,
+ "finishTime": 4.18,
+ "dialogue": {
+ "text": "We didn't use to integrate security and design as much as we should.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Linda",
+ "opacity": 0,
+ "startTime": 4.68
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717b5c73e81e8101bed0ea2.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717b5c73e81e8101bed0ea2.md
new file mode 100644
index 0000000000..54d37c3598
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717b5c73e81e8101bed0ea2.md
@@ -0,0 +1,96 @@
+---
+id: 6717b5c73e81e8101bed0ea2
+title: Task 75
+challengeType: 19
+dashedName: task-75
+---
+
+
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+How could Jake tell Linda he agrees with what she is saying?
+
+## --answers--
+
+`Nonsense.`
+
+### --feedback--
+
+When you use `nonsense` to reply to a comment, it is because you do not believe it is true or deserves credit.
+
+---
+
+`Agreed.`
+
+## --video-solution--
+
+2
+
+# --explanation--
+
+`Agreed` is a concise way to express strong agreement with someone's statement. It is the opposite of the expression `Nonsense.`
+
+`Agreed` is often used in professional or conversational contexts to show alignment with what has been said. For Example:
+
+Person 1: `We should prioritize user feedback in our next update.`
+
+Person 2: `Agreed.` - This answer implies you strongly agree with prioritizing used feedback on the next update.
+
+In this context, Jake could use `Agreed` to acknowledge that he fully supports Linda's statement about the lack of integration between security and design in the past.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Linda",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 55.04,
+ "finishTimestamp": 58.22
+ }
+ },
+ "commands": [
+ {
+ "character": "Linda",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Linda",
+ "startTime": 1,
+ "finishTime": 4.18,
+ "dialogue": {
+ "text": "We didn't use to integrate security and design as much as we should.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Linda",
+ "opacity": 0,
+ "startTime": 4.68
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717b5dc5fd2c0102b2aacec.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717b5dc5fd2c0102b2aacec.md
new file mode 100644
index 0000000000..499bfc59aa
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717b5dc5fd2c0102b2aacec.md
@@ -0,0 +1,103 @@
+---
+id: 6717b5dc5fd2c0102b2aacec
+title: Task 76
+challengeType: 22
+dashedName: task-76
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`Agreed. Moving BLANK, we should BLANK that security checks are happening while the design updates are being made.`
+
+## --blanks--
+
+`forward`
+
+### --feedback--
+
+This phrase refers to looking or planning ahead into the future.
+
+---
+
+`ensure`
+
+### --feedback--
+
+This word means to make certain or guarantee that something happens.
+
+# --explanation--
+
+`Moving forward` means looking ahead or planning for the future. It emphasizes taking steps or making changes from this point onward. For example:
+
+`Moving forward, the team will prioritize communication to avoid delays.` - This means that prioritizing communication is something that will start being done from now on.
+
+`Ensure` means to make certain or guarantee that something happens as intended. It is often used when setting priorities or responsibilities. For example:
+
+`We need to ensure that all employees are aware of the new guidelines.` - This means we should pay attention to the fact the employees know what the new guidelines are.
+
+In this context, Jake is emphasizing the importance of planning for the future by guaranteeing that security checks align with design updates.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Jake",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 58.6,
+ "finishTimestamp": 65.24
+ }
+ },
+ "commands": [
+ {
+ "character": "Jake",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Jake",
+ "startTime": 1,
+ "finishTime": 5.5,
+ "dialogue": {
+ "text": "Agreed. Moving forward, we should ensure that security checks are happening",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Jake",
+ "startTime": 5.4,
+ "finishTime": 7.64,
+ "dialogue": {
+ "text": "while the design updates are being made.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Jake",
+ "opacity": 0,
+ "startTime": 8.14
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717b5f5be4456103b8ff767.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717b5f5be4456103b8ff767.md
new file mode 100644
index 0000000000..6fe4927f8b
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717b5f5be4456103b8ff767.md
@@ -0,0 +1,115 @@
+---
+id: 6717b5f5be4456103b8ff767
+title: Task 77
+challengeType: 19
+dashedName: task-77
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+When does Jake think security checks should happen?
+
+## --answers--
+
+They should happen before the design updates are made.
+
+### --feedback--
+
+Jake specifically mentions that security checks should occur simultaneously with the design updates.
+
+---
+
+They should happen after the design updates are complete.
+
+### --feedback--
+
+Jake's statement indicates the checks should happen during, not after, the updates.
+
+---
+
+They don't need to happen at all.
+
+### --feedback--
+
+Jake is stressing the importance of security checks during the design updates.
+
+---
+
+They should happen while the design updates are being made.
+
+## --video-solution--
+
+4
+
+# --explanation--
+
+The `Present Continuous` tense is used here to describe two ongoing actions happening at the same time: `security checks are happening` and `design updates are being made`. This emphasizes simultaneous activities. For example:
+
+`The team is testing the new feature while the developers are fixing bugs.` - This means the tests and the process of bug fixing are happening at the same time.
+
+This tense is often used to indicate that two events are occurring at the same time, creating a sense of coordination or overlap in actions. In Jake's statement, he stresses the importance of ensuring that both actions occur simultaneously.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Jake",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 58.6,
+ "finishTimestamp": 65.24
+ }
+ },
+ "commands": [
+ {
+ "character": "Jake",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Jake",
+ "startTime": 1,
+ "finishTime": 5.5,
+ "dialogue": {
+ "text": "Agreed. Moving forward, we should ensure that security checks are happening",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Jake",
+ "startTime": 5.4,
+ "finishTime": 7.64,
+ "dialogue": {
+ "text": "while the design updates are being made.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Jake",
+ "opacity": 0,
+ "startTime": 8.14
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717b611f1230c104cbf5d38.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717b611f1230c104cbf5d38.md
new file mode 100644
index 0000000000..202142b8fe
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717b611f1230c104cbf5d38.md
@@ -0,0 +1,90 @@
+---
+id: 6717b611f1230c104cbf5d38
+title: Task 78
+challengeType: 22
+dashedName: task-78
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`We BLANK BLANK to overlook this aspect again.`
+
+## --blanks--
+
+`can't`
+
+### --feedback--
+
+This word indicates inability or prohibition.
+
+---
+
+`afford`
+
+### --feedback--
+
+This word means to have the resources, time, or capacity to do something.
+
+# --explanation--
+
+`Can't afford` means that something is not feasible or permissible, often due to resource, time, or risk constraints. It emphasizes the necessity of avoiding a specific action or making a particular choice. For example:
+
+`We can't afford to miss the deadline for this project.` - This means that missing the deadline is not something we can do.
+
+In this context, Jake is emphasizing the critical importance of not ignoring this aspect in the future.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Jake",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 65.16,
+ "finishTimestamp": 67.94
+ }
+ },
+ "commands": [
+ {
+ "character": "Jake",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Jake",
+ "startTime": 1,
+ "finishTime": 3.78,
+ "dialogue": {
+ "text": "We can't afford to overlook this aspect again.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Jake",
+ "opacity": 0,
+ "startTime": 4.28
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717b6a5308335105c51cfe6.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717b6a5308335105c51cfe6.md
new file mode 100644
index 0000000000..9158491d15
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6717b6a5308335105c51cfe6.md
@@ -0,0 +1,106 @@
+---
+id: 6717b6a5308335105c51cfe6
+title: Task 79
+challengeType: 19
+dashedName: task-79
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What, in Jake's opinion, can't they afford to do anymore?
+
+## --answers--
+
+They can't afford to prioritize this aspect.
+
+### --feedback--
+
+Jake's concern is about not ignoring the aspect, not about prioritizing it.
+
+---
+
+They can't afford to overlook this aspect again.
+
+---
+
+They can't afford to discuss this aspect.
+
+### --feedback--
+
+Jake is emphasizing the need to address this aspect, not avoid discussing it.
+
+---
+
+They can't afford to remember this aspect.
+
+### --feedback--
+
+Jake is referring to the danger of overlooking or ignoring this aspect, not about remembering it.
+
+## --video-solution--
+
+2
+
+# --explanation--
+
+The verb `overlook` means to fail to notice or consider something important, often unintentionally. For example:
+
+`The team overlooked a critical error in the report, causing delays.` - Here, `overlooked` refers to failing to notice an error that had significant consequences.
+
+In this context, Jake is stressing that ignoring or neglecting this aspect would be a mistake.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "company2-center.png",
+ "characters": [
+ {
+ "character": "Jake",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.4
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-2.mp3",
+ "startTime": 1,
+ "startTimestamp": 65.16,
+ "finishTimestamp": 67.94
+ }
+ },
+ "commands": [
+ {
+ "character": "Jake",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Jake",
+ "startTime": 1,
+ "finishTime": 3.78,
+ "dialogue": {
+ "text": "We can't afford to overlook this aspect again.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Jake",
+ "opacity": 0,
+ "startTime": 4.28
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671d19c62da85c0982472a57.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671d19c62da85c0982472a57.md
new file mode 100644
index 0000000000..a42f03be45
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671d19c62da85c0982472a57.md
@@ -0,0 +1,68 @@
+---
+id: 671d19c62da85c0982472a57
+title: Task 80
+challengeType: 22
+dashedName: task-80
+---
+
+# --instructions--
+
+This is a review of the entire dialogue you just studied.
+
+Place the following phrases in the correct spot: `major vulnerability`, `security vulnerabilities`, `real time`, `learning curve`, `working overtime`, and `quick post-mortem`.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`Linda and Jake discuss their design project experience. First, Linda suggests they do a BLANK to review what went well and what didn't. Jake admits to reviewing BLANK, though not always in BLANK.`
+
+`Linda recalls a time when the whole team was BLANK, and Jake was addressing a BLANK that required immediate attention. Both agree that the project was a BLANK, teaching them the importance of integrating security into the design process.`
+
+## --blanks--
+
+`quick post-mortem`
+
+### --feedback--
+
+It's a review done after a project to reflect on successes and challenges.
+
+---
+
+`security vulnerabilities`
+
+### --feedback--
+
+Those are weaknesses that could expose the system to threats.
+
+---
+
+`real time`
+
+### --feedback--
+
+It means checking things as they happen, without delay.
+
+---
+
+`working overtime`
+
+### --feedback--
+
+It refers to putting in extra hours to meet project needs.
+
+---
+
+`major vulnerability`
+
+### --feedback--
+
+It's a critical issue that requires immediate attention to avoid risks.
+
+---
+
+`learning curve`
+
+### --feedback--
+
+It represents the time and effort needed to master something new.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671d1f358f62320b707af87f.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671d1f358f62320b707af87f.md
new file mode 100644
index 0000000000..4cddc1fac3
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671d1f358f62320b707af87f.md
@@ -0,0 +1,62 @@
+---
+id: 671d1f358f62320b707af87f
+title: Task 81
+challengeType: 19
+dashedName: task-81
+---
+
+
+
+# --instructions--
+
+Read the text and answer the question below.
+
+# --questions--
+
+## --text--
+
+This is Linda's blog post based on dialogue with Jake.
+
+`Lessons Learned from a Security Challenge` `By Linda` `October 26, 2024`
+
+`Last week, our team had to work overtime. We found a serious security problem in our design project. Jake, who handles security, worked late to fix it while the rest of the team waited to continue. It wasn't easy, but we learned a lot.`
+
+`We now know that we need to check for security issues while working on design updates, not after. This experience taught us how important it is to stay on top of things and not fall behind.`
+
+What is the main point of the blog post?
+
+## --answers--
+
+The team learned the importance of addressing security issues during design updates.
+
+---
+
+The team completed their project ahead of time.
+
+### --feedback--
+
+The text mentions that the team faced delays and challenges, not early completion.
+
+---
+
+The team avoided overtime by planning well.
+
+### --feedback--
+
+The text clearly states that the team had to work overtime to address a security problem.
+
+---
+
+The team decided to postpone security checks until after the project.
+
+### --feedback--
+
+The lesson learned was to check for security issues during design, not afterward.
+
+## --video-solution--
+
+1
+
+# --explanation--
+
+Focus on the entire text. The main idea of the post is learning from mistakes and improving processes.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671d1f5590e7110b82940771.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671d1f5590e7110b82940771.md
new file mode 100644
index 0000000000..7c0d24843a
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671d1f5590e7110b82940771.md
@@ -0,0 +1,62 @@
+---
+id: 671d1f5590e7110b82940771
+title: Task 82
+challengeType: 19
+dashedName: task-82
+---
+
+
+
+# --instructions--
+
+Read the text and answer the question below.
+
+# --questions--
+
+## --text--
+
+This is Linda's blog post based on dialogue with Jake.
+
+`Lessons Learned from a Security Challenge` `By Linda` `October 26, 2024`
+
+`Last week, our team had to work overtime. We found a serious security problem in our design project. Jake, who handles security, worked late to fix it while the rest of the team waited to continue. It wasn't easy, but we learned a lot.`
+
+`We now know that we need to check for security issues while working on design updates, not after. This experience taught us how important it is to stay on top of things and not fall behind.`
+
+Why did the team work overtime?
+
+## --answers--
+
+They wanted to impress the client by finishing early.
+
+### --feedback--
+
+The overtime was due to a security issue, not to finish early.
+
+---
+
+They needed more time to improve user feedback.
+
+### --feedback--
+
+The text does not mention overtime related to user feedback.
+
+---
+
+They found a serious security problem that needed to be fixed immediately.
+
+---
+
+They worked late to complete documentation.
+
+### --feedback--
+
+The text focuses on fixing security issues, not documentation.
+
+## --video-solution--
+
+3
+
+# --explanation--
+
+Focus on the paragraph that starts with `Last week, our team had to…`. This explains why the team worked late.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671d1f7ca5f2aa0bb63b9e22.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671d1f7ca5f2aa0bb63b9e22.md
new file mode 100644
index 0000000000..773c16a6b0
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671d1f7ca5f2aa0bb63b9e22.md
@@ -0,0 +1,62 @@
+---
+id: 671d1f7ca5f2aa0bb63b9e22
+title: Task 83
+challengeType: 19
+dashedName: task-83
+---
+
+
+
+# --instructions--
+
+Read the text and answer the question below.
+
+# --questions--
+
+## --text--
+
+This is Linda's blog post based on dialogue with Jake.
+
+`Lessons Learned from a Security Challenge` `By Linda` `October 26, 2024`
+
+`Last week, our team had to work overtime. We found a serious security problem in our design project. Jake, who handles security, worked late to fix it while the rest of the team waited to continue. It wasn't easy, but we learned a lot.`
+
+`We now know that we need to check for security issues while working on design updates, not after. This experience taught us how important it is to stay on top of things and not fall behind.`
+
+What did the team learn from working overtime?
+
+## --answers--
+
+They learned to ignore minor bugs until the end of the project.
+
+### --feedback--
+
+The lesson was about addressing security issues promptly, not ignoring problems.
+
+---
+
+They learned to address security issues during design updates.
+
+---
+
+They found that working late is the best way to solve issues.
+
+### --feedback--
+
+The text emphasizes learning better practices, not relying on overtime work.
+
+---
+
+They realized that delays in security checks are acceptable.
+
+### --feedback--
+
+The text teaches the opposite: to stay on top of things and not fall behind.
+
+## --video-solution--
+
+2
+
+# --explanation--
+
+Focus on the sentence that starts with `We now know that we need to…`. This teaches the main lesson: integrating security checks during design updates.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671d1f94461c820bc68e3694.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671d1f94461c820bc68e3694.md
new file mode 100644
index 0000000000..823679eb59
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671d1f94461c820bc68e3694.md
@@ -0,0 +1,62 @@
+---
+id: 671d1f94461c820bc68e3694
+title: Task 84
+challengeType: 19
+dashedName: task-84
+---
+
+
+
+# --instructions--
+
+Read the text and answer the question below.
+
+# --questions--
+
+## --text--
+
+This is Linda's blog post based on dialogue with Jake.
+
+`Lessons Learned from a Security Challenge` `By Linda` `October 26, 2024`
+
+`Last week, our team had to work overtime. We found a serious security problem in our design project. Jake, who handles security, worked late to fix it while the rest of the team waited to continue. It wasn't easy, but we learned a lot.`
+
+`We now know that we need to check for security issues while working on design updates, not after. This experience taught us how important it is to stay on top of things and not fall behind.`
+
+Who was responsible for security?
+
+## --answers--
+
+Linda
+
+### --feedback--
+
+Linda is mentioned in the dialogue but isn't responsible for security.
+
+---
+
+Jake
+
+---
+
+The entire team
+
+### --feedback--
+
+The text specifically mentions that someone handles security.
+
+---
+
+A third-party consultant
+
+### --feedback--
+
+There is no mention of a consultant handling security in the text.
+
+## --video-solution--
+
+2
+
+# --explanation--
+
+Focus on the sentence that starts with `Jake, who handles…`. This identifies him as the person responsible for security.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671d1fab38a4710bd7a6b9c0.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671d1fab38a4710bd7a6b9c0.md
new file mode 100644
index 0000000000..a3c58c5cc3
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671d1fab38a4710bd7a6b9c0.md
@@ -0,0 +1,62 @@
+---
+id: 671d1fab38a4710bd7a6b9c0
+title: Task 85
+challengeType: 19
+dashedName: task-85
+---
+
+
+
+# --instructions--
+
+Read the text and answer the question below.
+
+# --questions--
+
+## --text--
+
+This is Linda's blog post based on dialogue with Jake.
+
+`Lessons Learned from a Security Challenge` `By Linda` `October 26, 2024`
+
+`Last week, our team had to work overtime. We found a serious security problem in our design project. Jake, who handles security, worked late to fix it while the rest of the team waited to continue. It wasn't easy, but we learned a lot.`
+
+`We now know that we need to check for security issues while working on design updates, not after. This experience taught us how important it is to stay on top of things and not fall behind.`
+
+What lesson did the team take from the experience?
+
+## --answers--
+
+They decided to delay updates to reduce workload.
+
+### --feedback--
+
+The text emphasizes staying on top of things, not postponing updates.
+
+---
+
+They found that security issues aren't very important.
+
+### --feedback--
+
+The text highlights the importance of security, not downplaying it.
+
+---
+
+They decided to avoid security checks in future projects.
+
+### --feedback--
+
+The lesson was to integrate security checks into the design process, not avoid them.
+
+---
+
+They learned to stay on top of things and not fall behind.
+
+## --video-solution--
+
+4
+
+# --explanation--
+
+Focus on the sentence that starts with `This experience taught us…`. This highlights the overall takeaway about staying on top of tasks.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671d292ef6180210164c33e8.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671d292ef6180210164c33e8.md
new file mode 100644
index 0000000000..9c0c877d80
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671d292ef6180210164c33e8.md
@@ -0,0 +1,196 @@
+---
+id: 671d292ef6180210164c33e8
+title: "Dialogue 3: Tech Conference Experience"
+challengeType: 21
+dashedName: dialogue-3-tech-conference-experience
+---
+
+# --description--
+
+Watch the video below to understand the context of the upcoming lessons.
+
+# --assignment--
+
+Watch the video
+
+# --scene--
+
+```json
+{
+"setup": {
+ "background": "cafe.png",
+ "characters": [
+ {
+ "character": "Maria",
+ "position": { "x": -25, "y": 0, "z": 1 }
+ },
+ {
+ "character": "Brian",
+ "position": { "x": 125, "y": 0, "z": 1 }
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-3.mp3",
+ "startTime": 1
+ },
+ "alwaysShowDialogue": true
+},
+"commands": [
+ {
+ "character": "Maria",
+ "position": { "x": 25, "y": 0, "z": 1 },
+ "startTime": 0
+ },
+ {
+ "character": "Brian",
+ "position": { "x": 70, "y": 0, "z": 1 },
+ "startTime": 0.5
+ },
+ {
+ "character": "Maria",
+ "startTime": 1,
+ "finishTime": 4.38,
+ "dialogue": {
+ "text": "Brian, is that you? What a surprise to see you here at PyCon.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Brian",
+ "startTime": 4.64,
+ "finishTime": 7.68,
+ "dialogue": {
+ "text": "Wow, Maria. So nice to see you. Let's catch up.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Brian",
+ "startTime": 7.74,
+ "finishTime": 10.86,
+ "dialogue": {
+ "text": "I attended some really interesting sessions these last few days.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Maria",
+ "startTime": 11.28,
+ "finishTime": 14.56,
+ "dialogue": {
+ "text": "Yeah, me too. I checked out the latest in Python development.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Maria",
+ "startTime": 14.9,
+ "finishTime": 18.1,
+ "dialogue": {
+ "text": "Do you remember how we used to get excited about new tech back at work?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Brian",
+ "startTime": 18.74,
+ "finishTime": 23.24,
+ "dialogue": {
+ "text": "Absolutely. We used to spend our lunch breaks chatting about the newest trends in programming.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Brian",
+ "startTime": 23.84,
+ "finishTime": 25.74,
+ "dialogue": {
+ "text": "Did you go to the AI workshop yesterday?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Maria",
+ "startTime": 25.74,
+ "finishTime": 31.16,
+ "dialogue": {
+ "text": "Yes, I did. While the speaker was going through neural networks, I thought about our project last year.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Maria",
+ "startTime": 31.62,
+ "finishTime": 35.4,
+ "dialogue": {
+ "text": "I remember you would often stay late, fine-tuning the code until it was just right.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Brian",
+ "startTime": 36.72,
+ "finishTime": 40.24,
+ "dialogue": {
+ "text": "Now I take care of the training so that others can do the same.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Brian",
+ "startTime": 40.74,
+ "finishTime": 44.66,
+ "dialogue": {
+ "text": "Speaking of which, did you manage to catch the cyber security talk this morning?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Maria",
+ "startTime": 45.16,
+ "finishTime": 47.6,
+ "dialogue": {
+ "text": "I missed it. I was in a design sprint workshop.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Maria",
+ "startTime": 48.04,
+ "finishTime": 50.66,
+ "dialogue": {
+ "text": "We brainstormed for two hours straight. How was it?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Brian",
+ "startTime": 50.66,
+ "finishTime": 54.2,
+ "dialogue": {
+ "text": "It was eye-opening, especially the parts about protecting data.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Brian",
+ "startTime": 54.54,
+ "finishTime": 58.28,
+ "dialogue": {
+ "text": "It made me think of how we handled security in our earlier projects.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Brian",
+ "position": { "x": 125, "y": 0, "z": 1 },
+ "startTime": 58.78
+ },
+ {
+ "character": "Maria",
+ "position": { "x": -25, "y": 0, "z": 1 },
+ "startTime": 59.28
+ }
+]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f7579f5e0000560fcce55.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f7579f5e0000560fcce55.md
new file mode 100644
index 0000000000..b449610707
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f7579f5e0000560fcce55.md
@@ -0,0 +1,94 @@
+---
+id: 671f7579f5e0000560fcce55
+title: Task 86
+challengeType: 22
+dashedName: task-86
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`Brian, is that you? BLANK BLANK surprise to see you here at PyCon.`
+
+## --blanks--
+
+`What`
+
+### --feedback--
+
+This word is used as an intensifier to express strong emotion or emphasis.
+
+---
+
+`a`
+
+### --feedback--
+
+This is the indefinite article used with singular, countable nouns following `what` to enhance the expression.
+
+# --explanation--
+
+The structure `what` + an indefinite article is used to emphasize strong feelings or reactions about something. It often expresses surprise, admiration, or emotion. For example:
+
+`What a beautiful day it is!` - Here, the structure highlights the speaker's admiration for the day.
+
+Similarly, in Maria's sentence, `What a surprise` emphasizes her astonishment at seeing Brian at PyCon.
+
+`PyCon` is a well-known conference for Python programming enthusiasts, developers, and professionals. It provides a platform for learning, networking, and sharing Python-related knowledge. For example:
+
+`I attended PyCon last year and learned about the latest Python frameworks.` - This means the person was at PyCon last year and learned a lot.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "cafe.png",
+ "characters": [
+ {
+ "character": "Maria",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.5
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-3.mp3",
+ "startTime": 1,
+ "startTimestamp": 0.56,
+ "finishTimestamp": 3.94
+ }
+ },
+ "commands": [
+ {
+ "character": "Maria",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Maria",
+ "startTime": 1,
+ "finishTime": 4.38,
+ "dialogue": {
+ "text": "Brian, is that you? What a surprise to see you here at PyCon.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Maria",
+ "opacity": 0,
+ "startTime": 4.88
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f7592e571ad05716b2c67.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f7592e571ad05716b2c67.md
new file mode 100644
index 0000000000..3b03739af2
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f7592e571ad05716b2c67.md
@@ -0,0 +1,90 @@
+---
+id: 671f7592e571ad05716b2c67
+title: Task 87
+challengeType: 19
+dashedName: task-87
+---
+
+
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+Brian wants to keep the conversation flowing. What should he say next?
+
+## --answers--
+
+`Sorry Maria, I'm running late for my talk. Let's meet later.`
+
+### --feedback--
+
+While it suggests politeness, it doesn't match the friendly and enthusiastic tone of the original answer.
+
+---
+
+`Wow Maria! So nice to see you. Let's catch up.`
+
+## --video-solution--
+
+2
+
+# --explanation--
+
+In the dialogue, Brian responds with excitement and friendliness.
+
+The correct answer reflects his positive attitude with phrases like `So nice to see you` and `Let's catch up`, which align with the original conversation's tone.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "cafe.png",
+ "characters": [
+ {
+ "character": "Maria",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.5
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-3.mp3",
+ "startTime": 1,
+ "startTimestamp": 0.56,
+ "finishTimestamp": 3.94
+ }
+ },
+ "commands": [
+ {
+ "character": "Maria",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Maria",
+ "startTime": 1,
+ "finishTime": 4.38,
+ "dialogue": {
+ "text": "Brian, is that you? What a surprise to see you here at PyCon.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Maria",
+ "opacity": 0,
+ "startTime": 4.88
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f75ab41a1520581f5923a.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f75ab41a1520581f5923a.md
new file mode 100644
index 0000000000..c3ebc93249
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f75ab41a1520581f5923a.md
@@ -0,0 +1,84 @@
+---
+id: 671f75ab41a1520581f5923a
+title: Task 88
+challengeType: 22
+dashedName: task-88
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`Wow Maria! So nice to see you. Let's BLANK up.`
+
+## --blanks--
+
+`catch`
+
+### --feedback--
+
+Combined with the following word, it's a phrase that Brian uses to suggest talking with Maria about what they've both been up to recently.
+
+# --explanation--
+
+`Catch up` means to meet and update each other on recent events or activities after some time apart. For examples:
+
+- `She stayed late to catch up on her tasks.` - Meaning she worked longer to finish tasks she was behind on.
+
+- `Let's catch up during the meeting tomorrow.` - Meaning you and the other person can talk and update each other at the meeting.
+
+In this context, Brian is telling Maria that they should talk to each other to know what they've been doing.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "cafe.png",
+ "characters": [
+ {
+ "character": "Brian",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-3.mp3",
+ "startTime": 1,
+ "startTimestamp": 4.2,
+ "finishTimestamp": 7.24
+ }
+ },
+ "commands": [
+ {
+ "character": "Brian",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Brian",
+ "startTime": 1,
+ "finishTime": 4.04,
+ "dialogue": {
+ "text": "Wow, Maria. So nice to see you. Let's catch up.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Brian",
+ "opacity": 0,
+ "startTime": 4.54
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f75ca1748e8059234fa3d.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f75ca1748e8059234fa3d.md
new file mode 100644
index 0000000000..66fec57d96
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f75ca1748e8059234fa3d.md
@@ -0,0 +1,104 @@
+---
+id: 671f75ca1748e8059234fa3d
+title: Task 89
+challengeType: 19
+dashedName: task-89
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What has Brian been doing at PyCon?
+
+## --answers--
+
+He has been organizing the sessions.
+
+### --feedback--
+
+Brian says he attended the sessions, not that he organized them.
+
+---
+
+He has been attending some interesting sessions.
+
+---
+
+He has been presenting at the sessions.
+
+### --feedback--
+
+Brian talks about attending sessions, not presenting them.
+
+---
+
+He has been networking with other attendees.
+
+### --feedback--
+
+While Brian might have been networking, his statement is specifically about attending sessions.
+
+## --video-solution--
+
+2
+
+# --explanation--
+
+To `attend sessions` means to participate in organized events, such as talks, discussions, or meetings, often as an audience member. It typically refers to events at conferences, workshops, or professional gatherings. For example:
+
+`She attended several training sessions as part of her trainee program.` - Here, she took in a training because this is part of the trainee program.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "cafe.png",
+ "characters": [
+ {
+ "character": "Brian",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-3.mp3",
+ "startTime": 1,
+ "startTimestamp": 7.3,
+ "finishTimestamp": 10.42
+ }
+ },
+ "commands": [
+ {
+ "character": "Brian",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Brian",
+ "startTime": 1,
+ "finishTime": 4.12,
+ "dialogue": {
+ "text": "I attended some really interesting sessions these last few days.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Brian",
+ "opacity": 0,
+ "startTime": 4.62
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f75e368cbd505a301ca7d.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f75e368cbd505a301ca7d.md
new file mode 100644
index 0000000000..f9e82f1d83
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f75e368cbd505a301ca7d.md
@@ -0,0 +1,94 @@
+---
+id: 671f75e368cbd505a301ca7d
+title: Task 90
+challengeType: 19
+dashedName: task-90
+---
+
+
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+How could Maria succinctly tell Brian she attended some sessions at PyCon as well?
+
+## --answers--
+
+`Yeah, me too.`
+
+---
+
+`Why not?`
+
+### --feedback--
+
+`Why not?` doesn't indicate agreement or a shared experience.
+
+## --video-solution--
+
+1
+
+# --explanation--
+
+`Me too` is used to express agreement or show that the same statement applies to the speaker. It is a concise and informal way to respond to shared experiences or feelings. For example:
+
+Person 1: `I love Python programming.`
+
+Person 2: `Me too.` - Meaning they love programming in Python as well.
+
+In this context, Maria could say `Yeah, me too` to quickly let Brian know that she also attended really interesting sessions at PyCon.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "cafe.png",
+ "characters": [
+ {
+ "character": "Brian",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-3.mp3",
+ "startTime": 1,
+ "startTimestamp": 7.3,
+ "finishTimestamp": 10.42
+ }
+ },
+ "commands": [
+ {
+ "character": "Brian",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Brian",
+ "startTime": 1,
+ "finishTime": 4.12,
+ "dialogue": {
+ "text": "I attended some really interesting sessions these last few days.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Brian",
+ "opacity": 0,
+ "startTime": 4.62
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f75fea017ea05b31a80c6.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f75fea017ea05b31a80c6.md
new file mode 100644
index 0000000000..f20217b44d
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f75fea017ea05b31a80c6.md
@@ -0,0 +1,94 @@
+---
+id: 671f75fea017ea05b31a80c6
+title: Task 91
+challengeType: 22
+dashedName: task-91
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`Yeah, me too. I BLANK out the BLANK in Python development.`
+
+## --blanks--
+
+`checked`
+
+### --feedback--
+
+This is the past tense of the verb `check`, meaning to examine or explore something.
+
+---
+
+`latest`
+
+### --feedback--
+
+This word refers to the most recent or up-to-date version of something.
+
+# --explanation--
+
+`Check out` means to examine, explore, or take a look at something. It is often used informally when discussing things of interest. For example:
+
+`I checked out the new library in town.` - This means you went to the new library to see if you liked it.
+
+`Latest` refers to the most recent or up-to-date version of something. For example:
+
+`They announced the latest features in the software update.` - This means the most recent features of the software were announced by the team or company.
+
+In her sentence, Maria says she attended events where the most recent developments in Python were discussed during her time at PyCon.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "cafe.png",
+ "characters": [
+ {
+ "character": "Maria",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.5
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-3.mp3",
+ "startTime": 1,
+ "startTimestamp": 10.74,
+ "finishTimestamp": 14.22
+ }
+ },
+ "commands": [
+ {
+ "character": "Maria",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Maria",
+ "startTime": 1,
+ "finishTime": 4.48,
+ "dialogue": {
+ "text": "Yeah, me too. I checked out the latest in Python development.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Maria",
+ "opacity": 0,
+ "startTime": 4.98
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f761703824805c35c2eda.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f761703824805c35c2eda.md
new file mode 100644
index 0000000000..204772e6e1
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f761703824805c35c2eda.md
@@ -0,0 +1,108 @@
+---
+id: 671f761703824805c35c2eda
+title: Task 92
+challengeType: 19
+dashedName: task-92
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What is Maria asking Brian about?
+
+## --answers--
+
+She is asking if he still gets excited about technology.
+
+### --feedback--
+
+Maria is referring to how they used to feel in the past, not the present.
+
+---
+
+She is asking if they used to dislike new technology.
+
+### --feedback--
+
+Maria mentions getting excited about new technology, not disliking it.
+
+---
+
+She is asking if he remembers how they used to feel excited about new technology at work.
+
+---
+
+She is asking if he remembers the latest tech updates.
+
+### --feedback--
+
+Maria's focus is on their shared feelings about new technology in the past, not current updates.
+
+## --video-solution--
+
+3
+
+# --explanation--
+
+The phrase created by using `get` followed by an adjective describes a change of state or becoming a certain way. For example:
+
+- `They always get excited when a new Python update is released.` - `Get excited` means to become enthusiastic or thrilled. This means they are always filled with enthusiasm when a new Python update comes up.
+
+- `He got tired after working on the project all night.` - This means he wasn't tired before, but he is tired now, after a whole night of working on the project.
+
+In Maria's sentence, she is asking if Brian remembers the enthusiasm they used to feel about new technologies while working together.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "cafe.png",
+ "characters": [
+ {
+ "character": "Maria",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.5
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-3.mp3",
+ "startTime": 1,
+ "startTimestamp": 14.46,
+ "finishTimestamp": 17.66
+ }
+ },
+ "commands": [
+ {
+ "character": "Maria",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Maria",
+ "startTime": 1,
+ "finishTime": 4.2,
+ "dialogue": {
+ "text": "Do you remember how we used to get excited about new tech back at work?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Maria",
+ "opacity": 0,
+ "startTime": 4.7
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f765a22e32e05d4f5074e.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f765a22e32e05d4f5074e.md
new file mode 100644
index 0000000000..08bdc903c8
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f765a22e32e05d4f5074e.md
@@ -0,0 +1,94 @@
+---
+id: 671f765a22e32e05d4f5074e
+title: Task 93
+challengeType: 19
+dashedName: task-93
+---
+
+
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+How could Brian tell Maria he definitely remembers the excitement about new tech Maria mentioned?
+
+## --answers--
+
+`Absolutely.`
+
+---
+
+`I vaguely remember.`
+
+### --feedback--
+
+`I vaguely remember` means that something is not very vivid in the speaker's memory.
+
+## --video-solution--
+
+1
+
+# --explanation--
+
+The word `Absolutely` is used to express strong agreement or affirmation. It is often used in response to a statement or question to emphasize certainty or enthusiasm. For example:
+
+Person 1: `Do you think this approach will work?`
+
+Person 2: `Absolutely!` - This means you are sure the approach will be successful.
+
+In this context, Brian could say `Absolutely` to enthusiastically confirm that he remembers getting excited about new technology at work.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "cafe.png",
+ "characters": [
+ {
+ "character": "Maria",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.5
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-3.mp3",
+ "startTime": 1,
+ "startTimestamp": 14.46,
+ "finishTimestamp": 17.66
+ }
+ },
+ "commands": [
+ {
+ "character": "Maria",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Maria",
+ "startTime": 1,
+ "finishTime": 4.2,
+ "dialogue": {
+ "text": "Do you remember how we used to get excited about new tech back at work?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Maria",
+ "opacity": 0,
+ "startTime": 4.7
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f76959b3ca3060eddbe70.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f76959b3ca3060eddbe70.md
new file mode 100644
index 0000000000..6096e864af
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f76959b3ca3060eddbe70.md
@@ -0,0 +1,103 @@
+---
+id: 671f76959b3ca3060eddbe70
+title: Task 94
+challengeType: 22
+dashedName: task-94
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`Absolutely. We used to spend our lunch breaks BLANK about the newest BLANK in programming.`
+
+## --blanks--
+
+`chatting`
+
+### --feedback--
+
+This word means talking informally with others, often in a relaxed or casual way.
+
+---
+
+`trends`
+
+### --feedback--
+
+This word refers to general directions or popular developments in a particular field.
+
+# --explanation--
+
+`Chat` means to talk informally, usually in a relaxed or casual setting. It often refers to light or friendly conversations. For example:
+
+`We chatted about our plans for the weekend during the coffee break.` - Meaning they talked about the plans.
+
+A `trend` refers to a general direction in which something is developing or becoming popular. In the context of programming, it refers to popular technologies or approaches. For example:
+
+`The trend of using AI in everyday applications is growing rapidly.` - This means the general idea is to start using AI in the creation of commonly used applications.
+
+In this sentence, Brian talks about how they used to have informal conversations (`chatting`) about new and popular developments (`trends`) in programming during lunch breaks.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "cafe.png",
+ "characters": [
+ {
+ "character": "Brian",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-3.mp3",
+ "startTime": 1,
+ "startTimestamp": 18.1,
+ "finishTimestamp": 22.8
+ }
+ },
+ "commands": [
+ {
+ "character": "Brian",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Brian",
+ "startTime": 1,
+ "finishTime": 3.46,
+ "dialogue": {
+ "text": "Absolutely. We used to spend our lunch breaks",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Brian",
+ "startTime": 3.46,
+ "finishTime": 5.7,
+ "dialogue": {
+ "text": "chatting about the newest trends in programming.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Brian",
+ "opacity": 0,
+ "startTime": 6.2
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f76b915c1cf062570fdfc.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f76b915c1cf062570fdfc.md
new file mode 100644
index 0000000000..846743c10c
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f76b915c1cf062570fdfc.md
@@ -0,0 +1,138 @@
+---
+id: 671f76b915c1cf062570fdfc
+title: Task 95
+challengeType: 19
+dashedName: task-95
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+Which workshop can we be sure Maria attended yesterday?
+
+## --answers--
+
+The Python workshop.
+
+### --feedback--
+
+Maria specifically confirms attending the AI workshop, not the Python workshop.
+
+---
+
+The AI workshop.
+
+---
+
+The cybersecurity workshop.
+
+### --feedback--
+
+Maria attended the AI workshop, as confirmed in her response.
+
+---
+
+The design workshop.
+
+### --feedback--
+
+Maria explicitly says she attended the AI workshop, not the design workshop.
+
+## --video-solution--
+
+2
+
+# --explanation--
+
+AI stands for `Artificial Intelligence`, a field of computer science that focuses on creating systems capable of performing tasks that typically require human intelligence, such as learning, reasoning, and decision-making. For example:
+
+`AI is being used to improve natural language processing in chatbots.` - This means that Artificial Intelligence is used to help chatbots communicate in a more efficient way with humans.
+
+An `AI workshop` is a session or event where participants learn about AI concepts, tools, or applications. These workshops often include hands-on activities to help attendees understand and implement AI technologies. For example:
+
+`The AI workshop covered topics like machine learning and neural networks.` - This means the AI workshop taught machine learning and neural networks.
+
+In this dialog, Maria confirms that she attended an AI workshop yesterday.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "cafe.png",
+ "characters": [
+ {
+ "character": "Brian",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ },
+ {
+ "character": "Maria",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.5
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-3.mp3",
+ "startTime": 1,
+ "startTimestamp": 23.3,
+ "finishTimestamp": 26.6
+ }
+ },
+ "commands": [
+ {
+ "character": "Brian",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Brian",
+ "startTime": 1,
+ "finishTime": 3,
+ "dialogue": {
+ "text": "Did you go to the AI workshop yesterday?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Brian",
+ "opacity": 0,
+ "startTime": 3
+ },
+ {
+ "character": "Maria",
+ "opacity": 1,
+ "startTime": 3
+ },
+ {
+ "character": "Maria",
+ "startTime": 3,
+ "finishTime": 4.3,
+ "dialogue": {
+ "text": "Yes, I did.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Maria",
+ "opacity": 0,
+ "startTime": 4.8
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f76d4b7384c063c097048.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f76d4b7384c063c097048.md
new file mode 100644
index 0000000000..c741f69cbb
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f76d4b7384c063c097048.md
@@ -0,0 +1,103 @@
+---
+id: 671f76d4b7384c063c097048
+title: Task 96
+challengeType: 22
+dashedName: task-96
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`While the speaker was BLANK BLANK neural networks, I thought about our project last year.`
+
+## --blanks--
+
+`going`
+
+### --feedback--
+
+This verb is used as part of the phrasal verb `go through`, meaning to review or explain something in detail. Use it in the `-ing` form.
+
+---
+
+`through`
+
+### --feedback--
+
+This preposition is part of the phrasal verb `go through`, referring to a detailed explanation or review.
+
+# --explanation--
+
+To `go through` means to review, explain, or examine something in detail. It is often used when covering material in a structured or methodical way. For example:
+
+`The instructor went through the project requirements step by step.` - This means the instructor checked the requirements in a detailed manner.
+
+`Neural networks` are a type of artificial intelligence inspired by the structure and function of the human brain. For example:
+
+`The AI model uses neural networks to classify images with high accuracy.` - This means the AI model uses this structure based on the human brain to process data.
+
+In this sentence, Maria describes how the speaker was explaining neural networks during the workshop, prompting her to think about a past project.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "cafe.png",
+ "characters": [
+ {
+ "character": "Maria",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.5
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-3.mp3",
+ "startTime": 1,
+ "startTimestamp": 26.66,
+ "finishTimestamp": 30.72
+ }
+ },
+ "commands": [
+ {
+ "character": "Maria",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Maria",
+ "startTime": 1,
+ "finishTime": 3.1,
+ "dialogue": {
+ "text": "While the speaker was going through neural networks,",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Maria",
+ "startTime": 3.48,
+ "finishTime": 5.06,
+ "dialogue": {
+ "text": "I thought about our project last year.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Maria",
+ "opacity": 0,
+ "startTime": 5.56
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f76eede9f200652954940.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f76eede9f200652954940.md
new file mode 100644
index 0000000000..e8e9fd0725
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f76eede9f200652954940.md
@@ -0,0 +1,91 @@
+---
+id: 671f76eede9f200652954940
+title: Task 97
+challengeType: 22
+dashedName: task-97
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`I remember you would often stay late, BLANK the code until it was just right.`
+
+## --blanks--
+
+`fine-tuning`
+
+### --feedback--
+
+This is a compound word that refers to making small adjustments to improve something or make it perfect. remember to use `-`
+
+# --explanation--
+
+`Fine-tuning` means making small, precise adjustments to improve something or optimize it to achieve the desired result. It is often used in technical or creative contexts. For example:
+
+`She spent hours fine-tuning the presentation to ensure it was perfect for the audience.` - This means she adjusted even the smallest details of the presentation to make it perfect.
+
+In this sentence, Maria describes how Brian would carefully adjust the code, making it as efficient or correct as possible.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "cafe.png",
+ "characters": [
+ {
+ "character": "Maria",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.5
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-3.mp3",
+ "startTime": 1,
+ "startTimestamp": 30.98,
+ "finishTimestamp": 34.96
+ }
+ },
+ "commands": [
+ {
+ "character": "Maria",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Maria",
+ "startTime": 1,
+ "finishTime": 2.84,
+ "dialogue": {
+ "text": "I remember you would often stay late,",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Maria",
+ "startTime": 3,
+ "finishTime": 4.98,
+ "dialogue": {
+ "text": "fine-tuning the code until it was just right.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Maria",
+ "opacity": 0,
+ "startTime": 5.48
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f7708379ef00668b843d4.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f7708379ef00668b843d4.md
new file mode 100644
index 0000000000..581e026f56
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f7708379ef00668b843d4.md
@@ -0,0 +1,119 @@
+---
+id: 671f7708379ef00668b843d4
+title: Task 98
+challengeType: 19
+dashedName: task-98
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+Did Brian use to work regular hours to adjust the code?
+
+## --answers--
+
+No, he would often stay late fine-tuning the code.
+
+---
+
+Yes, he only worked regular hours to adjust the code.
+
+### --feedback--
+
+Maria explicitly mentions that Brian would often stay late, which suggests he worked beyond regular hours.
+
+---
+
+No, he only adjusted the code during meetings.
+
+### --feedback--
+
+Maria describes Brian staying late to fine-tune the code, not working on it exclusively during meetings.
+
+---
+
+Yes, but only when there was an urgent task.
+
+### --feedback--
+
+Maria indicates that staying late was a regular habit for Brian, not something limited to urgent tasks.
+
+## --video-solution--
+
+1
+
+# --explanation--
+
+`Would` in this context expresses a habitual action or repeated behavior in the past. It is often used to describe actions that someone regularly performed, similar to `used to`.
+
+However, `would` focuses more on the action itself, while `used to` can describe states or habits. For example:
+
+- `She would always read a book before going to bed.` - Reading a book before going to bed was a common action for her.
+
+`She used to live in New York before moving here.` - here `used to` is used because living in a place expresses a state of things not an action or something you would habitually do.
+
+In this sentence, Maria uses `would` to describe Brian's repeated habit of staying late to fine-tune the code, which emphasizes his dedication.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "cafe.png",
+ "characters": [
+ {
+ "character": "Maria",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.5
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-3.mp3",
+ "startTime": 1,
+ "startTimestamp": 30.98,
+ "finishTimestamp": 34.96
+ }
+ },
+ "commands": [
+ {
+ "character": "Maria",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Maria",
+ "startTime": 1,
+ "finishTime": 2.84,
+ "dialogue": {
+ "text": "I remember you would often stay late,",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Maria",
+ "startTime": 3,
+ "finishTime": 4.98,
+ "dialogue": {
+ "text": "fine-tuning the code until it was just right.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Maria",
+ "opacity": 0,
+ "startTime": 5.48
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f7727d2e4240680c126bc.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f7727d2e4240680c126bc.md
new file mode 100644
index 0000000000..54d64453b8
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f7727d2e4240680c126bc.md
@@ -0,0 +1,143 @@
+---
+id: 671f7727d2e4240680c126bc
+title: Task 99
+challengeType: 19
+dashedName: task-99
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What does Brian do now, and why does he do that?
+
+## --answers--
+
+He still fine-tunes the code himself, but not as often.
+
+### --feedback--
+
+Brian says he focuses on training others now, not doing the fine-tuning himself.
+
+---
+
+He takes care of hiring new team members for coding tasks.
+
+### --feedback--
+
+Brian mentions handling training, not hiring.
+
+---
+
+He reviews others' work without providing training.
+
+### --feedback--
+
+Brian emphasizes that he takes care of the training to help others learn.
+
+---
+
+He takes care of the training so that others can stay late to fine-tune the code.
+
+## --video-solution--
+
+4
+
+# --explanation--
+
+The phrase `so that` is used to express purpose or reason, showing why an action is done. For example:
+
+`She explained the process clearly so that everyone could understand it.` - This means her intent with explaining the process clearly was to make everyone understand it.
+
+In the dialog, Brian uses it to show that his goal in providing training is to empower others to perform at the same level as he did when he fine-tuned the code himself.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "cafe.png",
+ "characters": [
+ {
+ "character": "Maria",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.5
+ },
+ "opacity": 0
+ },
+ {
+ "character": "Brian",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-3.mp3",
+ "startTime": 1,
+ "startTimestamp": 30.98,
+ "finishTimestamp": 39.8
+ }
+ },
+ "commands": [
+ {
+ "character": "Maria",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Maria",
+ "startTime": 1,
+ "finishTime": 2.84,
+ "dialogue": {
+ "text": "I remember you would often stay late,",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Maria",
+ "startTime": 3,
+ "finishTime": 4.98,
+ "dialogue": {
+ "text": "finetuning the code until it was just right.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Maria",
+ "opacity": 0,
+ "startTime": 5.64
+ },
+ {
+ "character": "Brian",
+ "opacity": 1,
+ "startTime": 5.64
+ },
+ {
+ "character": "Brian",
+ "startTime": 6.3,
+ "finishTime": 9.82,
+ "dialogue": {
+ "text": "Now I take care of the training so that others can do the same.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Brian",
+ "opacity": 0,
+ "startTime": 10.32
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f774373f2ce0696fe9621.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f774373f2ce0696fe9621.md
new file mode 100644
index 0000000000..bc15b04b00
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f774373f2ce0696fe9621.md
@@ -0,0 +1,98 @@
+---
+id: 671f774373f2ce0696fe9621
+title: Task 100
+challengeType: 22
+dashedName: task-100
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`Speaking of which, did you BLANK to catch the BLANK talk this morning?`
+
+## --blanks--
+
+`manage`
+
+### --feedback--
+
+This word means to succeed in doing something, often with some difficulty.
+
+---
+
+`cybersecurity`
+
+### --feedback--
+
+This word refers to the practice of protecting systems, networks, and data from digital threats.
+
+# --explanation--
+
+`Speaking of which` is used to link a new topic to something that was just mentioned, often as a natural transition in conversation. For example:
+
+`The keynote speaker mentioned Python. Speaking of which, have you tried the new Python library?` - here, `speaking of which` is used to make the transition between the mention the keynote speaker made and the new library.
+
+In this context, `manage` means to succeed in doing something, especially something that might have been difficult. For example:
+
+`Despite the time crunch, I managed to submit the report on time.` - This means you were successful in sending the report before your deadline.
+
+`Cybersecurity` refers to the practice of protecting computer systems, networks, and data from digital attacks or unauthorized access. For example:
+
+`The company invested in cybersecurity measures to prevent data breaches.` - This means the company is concerned with protecting their systems.
+
+In this sentence, Brian asks if Maria attended the talk about protecting systems and data from threats in the morning.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "cafe.png",
+ "characters": [
+ {
+ "character": "Brian",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-3.mp3",
+ "startTime": 1,
+ "startTimestamp": 40.1,
+ "finishTimestamp": 44.22
+ }
+ },
+ "commands": [
+ {
+ "character": "Brian",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Brian",
+ "startTime": 1,
+ "finishTime": 5.12,
+ "dialogue": {
+ "text": "Speaking of which, did you manage to catch the cybersecurity talk this morning?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Brian",
+ "opacity": 0,
+ "startTime": 5.62
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f7767854d6806ac4fb5f4.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f7767854d6806ac4fb5f4.md
new file mode 100644
index 0000000000..5a12c90413
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f7767854d6806ac4fb5f4.md
@@ -0,0 +1,110 @@
+---
+id: 671f7767854d6806ac4fb5f4
+title: Task 101
+challengeType: 19
+dashedName: task-101
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+Why could Maria not attend the cybersecurity workshop in the morning?
+
+## --answers--
+
+Because she wasn't interested in the topic.
+
+### --feedback--
+
+Maria doesn't mention a lack of interest; she was in another workshop.
+
+---
+
+Because she forgot about it.
+
+### --feedback--
+
+Maria says she missed it because she was attending the design sprint workshop, not because she forgot.
+
+---
+
+Because she was in a design sprint workshop.
+
+---
+
+Because it was canceled.
+
+### --feedback--
+
+Maria explains that she missed the workshop because she was in another one, not because it was canceled.
+
+## --video-solution--
+
+3
+
+# --explanation--
+
+`Miss` means to fail to attend or participate in something. For example:
+
+`I missed the meeting because I was stuck in traffic.` - This means that you spent too long in traffic and this caused a delay to get to work.
+
+A `design sprint` is a time-boxed, collaborative process where a team works on solving a design problem or developing a prototype within a short period, usually a few days. For example:
+
+`The team completed a design sprint to test the new user interface concept.` This means the team participated in this collaborative process to test the concept.
+
+In this context, Maria couldn't attend the cybersecurity workshop because she was actively participating in a design sprint workshop.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "cafe.png",
+ "characters": [
+ {
+ "character": "Maria",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.5
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-3.mp3",
+ "startTime": 1,
+ "startTimestamp": 44.72,
+ "finishTimestamp": 47.16
+ }
+ },
+ "commands": [
+ {
+ "character": "Maria",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Maria",
+ "startTime": 1,
+ "finishTime": 3.44,
+ "dialogue": {
+ "text": "I missed it. I was in a design sprint workshop.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Maria",
+ "opacity": 0,
+ "startTime": 3.94
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f77bfcd2bc306c2f6f338.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f77bfcd2bc306c2f6f338.md
new file mode 100644
index 0000000000..6836a92549
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f77bfcd2bc306c2f6f338.md
@@ -0,0 +1,114 @@
+---
+id: 671f77bfcd2bc306c2f6f338
+title: Task 102
+challengeType: 19
+dashedName: task-102
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What does Maria say they did at the design sprint workshop?
+
+## --answers--
+
+They brainstormed for two hours straight.
+
+### --feedback--
+
+Maria explains that they spent two hours brainstorming during the design sprint workshop.
+
+---
+
+They worked individually for two hours straight.
+
+### --feedback--
+
+Maria mentions brainstorming, which is a collaborative activity, not individual work.
+
+---
+
+They completed the entire design in two hours straight.
+
+### --feedback--
+
+Maria says they brainstormed, not that they finished the entire design.
+
+---
+
+They took frequent breaks during their brainstorming.
+
+### --feedback--
+
+Maria emphasizes that they brainstormed for two hours without stopping.
+
+## --video-solution--
+
+1
+
+# --explanation--
+
+To `brainstorm` means to generate ideas or solutions through an open, collaborative discussion, often in a group. It focuses on creativity and problem-solving. For example:
+
+`The team brainstormed ideas for the new marketing campaign.` - This means that the team collaboratively discussed new ideas together for the new marketing campaign.
+
+`Straight` in this context means continuously or without stopping. It emphasizes uninterrupted activity. For example:
+
+`He studied for five hours straight to prepare for the exam.` - This means he did not stop studying for five hours to prepare for the exam.
+
+In this sentence, Maria explains that they brainstormed for two continuous hours during the design sprint workshop.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "cafe.png",
+ "characters": [
+ {
+ "character": "Maria",
+ "position": {
+ "x": 50,
+ "y": 0,
+ "z": 1.5
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-3.mp3",
+ "startTime": 1,
+ "startTimestamp": 47.4,
+ "finishTimestamp": 50.22
+ }
+ },
+ "commands": [
+ {
+ "character": "Maria",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Maria",
+ "startTime": 1,
+ "finishTime": 3.82,
+ "dialogue": {
+ "text": "We brainstormed for two hours straight. How was it?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Maria",
+ "opacity": 0,
+ "startTime": 4.32
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f77dedcc3b006dcfa9c73.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f77dedcc3b006dcfa9c73.md
new file mode 100644
index 0000000000..32728be1ce
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f77dedcc3b006dcfa9c73.md
@@ -0,0 +1,92 @@
+---
+id: 671f77dedcc3b006dcfa9c73
+title: Task 103
+challengeType: 22
+dashedName: task-103
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`It was BLANK, especially the parts about BLANK data.`
+
+## --blanks--
+
+`eye-opening`
+
+### --feedback--
+
+This word means enlightening or revealing, often leading to a new understanding or perspective. It's a composite word, so don't forget the hyphen between the words.
+
+---
+
+`protecting`
+
+### --feedback--
+
+This word is the `-ing` form of a verb used after the preposition `about`, referring to the act of safeguarding something.
+
+# --explanation--
+
+The term `eye-opening` describes something that is enlightening or surprising, often revealing new or unexpected information. For example:
+
+`The workshop on cybersecurity was eye-opening for the team.` - this means the workshop brought many new ideas and it helped the team understand a lot of things about cybersecurity.
+
+When a verb, like `to protect` follows a preposition, like `about`, it must be in the `-ing` form (gerund). This structure is common in English to describe actions connected to the preposition. In the sentence, `about protecting` highlights the topic being discussed. For example:
+
+`She is interested in learning more about artificial intelligence.` - here, `in` is the preposition and `to learn` is the verb in the `-ing` form.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "cafe.png",
+ "characters": [
+ {
+ "character": "Brian",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-3.mp3",
+ "startTime": 1,
+ "startTimestamp": 50.22,
+ "finishTimestamp": 53.76
+ }
+ },
+ "commands": [
+ {
+ "character": "Brian",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Brian",
+ "startTime": 1,
+ "finishTime": 4.54,
+ "dialogue": {
+ "text": "It was eye-opening, especially the parts about protecting data.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Brian",
+ "opacity": 0,
+ "startTime": 5.04
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f7800b5174406f2d0df76.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f7800b5174406f2d0df76.md
new file mode 100644
index 0000000000..9b561ad71f
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f7800b5174406f2d0df76.md
@@ -0,0 +1,70 @@
+---
+id: 671f7800b5174406f2d0df76
+title: Task 106
+challengeType: 22
+dashedName: task-106
+---
+
+# --instructions--
+
+This is a review of the entire dialogue you just studied.
+
+Place the following phrases in the correct spot:
+
+`design sprint workshop`, `neural networks`, `AI workshop`, `cybersecurity talk`, `fine-tuning the code`, and `newest trends in programming`.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`Maria and Brian meet at PyCon and talk about their experiences at the conference. Maria mentions attending an BLANK, where she explored the BLANK. Brian recalls how they used to chat during lunch breaks about the BLANK.`
+
+`Maria also remembers a project from last year and how Brian spent time BLANK. Brian, who now focuses on training, asks if Maria attended the BLANK, but she missed it because she was busy in a BLANK.`
+
+## --blanks--
+
+`AI workshop`
+
+### --feedback--
+
+Maria participated in this workshop yesterday.
+
+---
+
+`neural networks`
+
+### --feedback--
+
+This topic is part of a workshop that Maria references. It deals with systems modeled after the human brain to process data.
+
+---
+
+`newest trends in programming`
+
+### --feedback--
+
+They used to enjoy conversations about the latest technologies and developments in the programming world.
+
+---
+
+`fine-tuning the code`
+
+### --feedback--
+
+This phrase refers to making small adjustments to ensure the code works perfectly, which Maria recalls Brian often doing.
+
+---
+
+`cybersecurity talk`
+
+### --feedback--
+
+This talk focused on data protection, a topic that Brian found insightful.
+
+---
+
+`design sprint workshop`
+
+### --feedback--
+
+This type of session involves rapid brainstorming and problem-solving activities, which Maria mentions participating in for two hours.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f78193bb0510709b169b8.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f78193bb0510709b169b8.md
new file mode 100644
index 0000000000..3ce7f61d20
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f78193bb0510709b169b8.md
@@ -0,0 +1,62 @@
+---
+id: 671f78193bb0510709b169b8
+title: Task 107
+challengeType: 19
+dashedName: task-107
+---
+
+
+
+# --instructions--
+
+Read the text and answer the question below.
+
+# --questions--
+
+## --text--
+
+This is a prologue to the conversation on PyCon.
+
+`Years ago, Maria and Brian sat in their office, imagining what it would be like to attend one of the world's biggest tech conferences, PyCon. Back then, they were junior developers, excited about every new programming trend and always pushing each other to improve. They promised they would attend PyCon again one day.`
+
+`Fast forward to today: here they are, attending sessions on AI and cybersecurity, talking about design sprints, and reflecting on how far they've come. Their dream is no longer just a dream—it's real, and they're living it.`
+
+`The adventure has only just begun.`
+
+What was Maria and Brian's dream years ago?
+
+## --answers--
+
+To work on AI projects together.
+
+### --feedback--
+
+Their dream involved attending an event, not a specific project focus.
+
+---
+
+To attend one of the biggest tech conferences, PyCon.
+
+---
+
+To become senior developers in their office.
+
+### --feedback--
+
+The text describes them as junior developers with a different goal in mind.
+
+---
+
+To start their own tech company.
+
+### --feedback--
+
+The dream mentioned is related to attending a tech conference, not starting a business.
+
+## --video-solution--
+
+2
+
+# --explanation--
+
+Focus on the sentence that starts with `Years ago, Maria and Brian…`. This sentence explains Maria and Brian's goal when they were junior developers, sitting in their office and dreaming about the future.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f7834b9a323071f7a325e.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f7834b9a323071f7a325e.md
new file mode 100644
index 0000000000..41e895640e
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f7834b9a323071f7a325e.md
@@ -0,0 +1,62 @@
+---
+id: 671f7834b9a323071f7a325e
+title: Task 108
+challengeType: 19
+dashedName: task-108
+---
+
+
+
+# --instructions--
+
+Read the text and answer the question below.
+
+# --questions--
+
+## --text--
+
+This is a prologue to the conversation on PyCon.
+
+`Years ago, Maria and Brian sat in their office, imagining what it would be like to attend one of the world's biggest tech conferences, PyCon. Back then, they were junior developers, excited about every new programming trend and always pushing each other to improve. They promised they would attend PyCon again one day.`
+
+`Fast forward to today: here they are, attending sessions on AI and cybersecurity, talking about design sprints, and reflecting on how far they've come. Their dream is no longer just a dream—it's real, and they're living it.`
+
+`The adventure has only just begun.`
+
+How did Maria and Brian feel about programming trends when they were junior developers?
+
+## --answers--
+
+They were uninterested in programming trends.
+
+### --feedback--
+
+The text suggests they felt quite the opposite about programming trends.
+
+---
+
+They preferred only to work on established technologies.
+
+### --feedback--
+
+The text indicates that they were enthusiastic about new trends, not sticking solely to established tech.
+
+---
+
+They ignored new trends to focus on their work.
+
+### --feedback--
+
+Ignoring trends doesn't align with the text's description of their excitement.
+
+---
+
+They were excited about every new programming trend.
+
+## --video-solution--
+
+4
+
+# --explanation--
+
+Focus on the sentence that starts with `Back then, they were junior developers…`. This sentence provides insight into how Maria and Brian felt about new programming trends early in their careers.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f7852f3a7e80737cc21d0.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f7852f3a7e80737cc21d0.md
new file mode 100644
index 0000000000..ae445d6343
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f7852f3a7e80737cc21d0.md
@@ -0,0 +1,62 @@
+---
+id: 671f7852f3a7e80737cc21d0
+title: Task 109
+challengeType: 19
+dashedName: task-109
+---
+
+
+
+# --instructions--
+
+Read the text and answer the question below.
+
+# --questions--
+
+## --text--
+
+This is a prologue to the conversation on PyCon.
+
+`Years ago, Maria and Brian sat in their office, imagining what it would be like to attend one of the world's biggest tech conferences, PyCon. Back then, they were junior developers, excited about every new programming trend and always pushing each other to improve. They promised they would attend PyCon again one day.`
+
+`Fast forward to today: here they are, attending sessions on AI and cybersecurity, talking about design sprints, and reflecting on how far they've come. Their dream is no longer just a dream—it's real, and they're living it.`
+
+`The adventure has only just begun.`
+
+What sessions are Maria and Brian attending at PyCon?
+
+## --answers--
+
+Sessions on programming languages and web design.
+
+### --feedback--
+
+The text gives different examples of the session topics they attended.
+
+---
+
+Sessions on Python basics and data entry.
+
+### --feedback--
+
+The topics mentioned in the text are not related to basic or introductory subjects.
+
+---
+
+Sessions on AI and cybersecurity.
+
+---
+
+Sessions on project management and networking.
+
+### --feedback--
+
+The focus of the sessions mentioned in the text is more technical and specific.
+
+## --video-solution--
+
+3
+
+# --explanation--
+
+Focus on the sentence that starts with `Fast forward to today…`. This sentence lists the sessions that Maria and Brian are attending at PyCon, reflecting their current interests.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f786a18c275074d55d298.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f786a18c275074d55d298.md
new file mode 100644
index 0000000000..a0728b6376
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f786a18c275074d55d298.md
@@ -0,0 +1,62 @@
+---
+id: 671f786a18c275074d55d298
+title: Task 110
+challengeType: 19
+dashedName: task-110
+---
+
+
+
+# --instructions--
+
+Read the text and answer the question below.
+
+# --questions--
+
+## --text--
+
+This is a prologue to the conversation on PyCon.
+
+`Years ago, Maria and Brian sat in their office, imagining what it would be like to attend one of the world's biggest tech conferences, PyCon. Back then, they were junior developers, excited about every new programming trend and always pushing each other to improve. They promised they would attend PyCon again one day.`
+
+`Fast forward to today: here they are, attending sessions on AI and cybersecurity, talking about design sprints, and reflecting on how far they've come. Their dream is no longer just a dream—it's real, and they're living it.`
+
+`The adventure has only just begun.`
+
+What does the text mean when it says, `Their dream is no longer just a dream—it's real`?
+
+## --answers--
+
+They are dreaming of attending PyCon in the future.
+
+### --feedback--
+
+The text indicates that they have already realized their dream, not just planned it.
+
+---
+
+Maria and Brian are finally attending PyCon, making their dream come true.
+
+---
+
+They forgot about PyCon over the years.
+
+### --feedback--
+
+The text shows that they kept their goal of attending PyCon, without forgetting it.
+
+---
+
+They are planning to attend PyCon next year.
+
+### --feedback--
+
+The text indicates they are already attending, not planning for a future event.
+
+## --video-solution--
+
+2
+
+# --explanation
+
+Focus on the sentence that starts with `Their dream is no longer just a dream…`. This sentence tells us that Maria and Brian are now living the dream they once envisioned.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f788c2665b807636b31a8.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f788c2665b807636b31a8.md
new file mode 100644
index 0000000000..5602c903a3
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/671f788c2665b807636b31a8.md
@@ -0,0 +1,62 @@
+---
+id: 671f788c2665b807636b31a8
+title: Task 111
+challengeType: 19
+dashedName: task-111
+---
+
+
+
+# --instructions--
+
+Read the text and answer the question below.
+
+# --questions--
+
+## --text--
+
+This is a prologue to the conversation on PyCon.
+
+`Years ago, Maria and Brian sat in their office, imagining what it would be like to attend one of the world's biggest tech conferences, PyCon. Back then, they were junior developers, excited about every new programming trend and always pushing each other to improve. They promised they would attend PyCon again one day.`
+
+`Fast forward to today: here they are, attending sessions on AI and cybersecurity, talking about design sprints, and reflecting on how far they've come. Their dream is no longer just a dream—it's real, and they're living it.`
+
+`The adventure has only just begun.`
+
+Why is attending PyCon significant for Maria and Brian?
+
+## --answers--
+
+It fulfills a long-held goal they had since they were junior developers.
+
+---
+
+It's their first time working on a new tech project together.
+
+### --feedback--
+
+The text doesn't mention a new project at PyCon, but rather that attending the conference fulfills a past goal.
+
+---
+
+It allowed them to meet their favorite tech influencers.
+
+### --feedback--
+
+The text emphasizes achieving a personal dream, not meeting influencers.
+
+---
+
+It gave them a chance to launch their own product.
+
+### --feedback--
+
+There is no mention of a product launch; the significance lies in achieving their goal of attending PyCon.
+
+## --video-solution--
+
+1
+
+# --explanation--
+
+Focus on the sentence that starts with `They promised they would…`. This sentence shows that attending PyCon was their goal, making it significant as it fulfills a long-held promise.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6746005e0cf96b701d861793.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6746005e0cf96b701d861793.md
new file mode 100644
index 0000000000..74eebec915
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6746005e0cf96b701d861793.md
@@ -0,0 +1,108 @@
+---
+id: 6746005e0cf96b701d861793
+title: Task 29
+challengeType: 19
+dashedName: task-29
+---
+
+
+
+# --description--
+
+Listen to the audio and answer the question.
+
+# --questions--
+
+## --text--
+
+What is Lisa asking James about?
+
+## --answers--
+
+She's asking if it took too long to find the bug.
+
+### --feedback--
+
+Lisa is not asking about how long it took. She just wants to know if it was stressful.
+
+---
+
+She's trying to confirm if finding the bug was a stressful task.
+
+---
+
+She's asking if James was the one who didn't update the credentials.
+
+### --feedback--
+
+Lisa is not trying to know who's responsible for it.
+
+---
+
+She's asking if there is anything she can do to help.
+
+### --feedback--
+
+Help is no longer necessary, since James has already fixed the problem.
+
+## --video-solution--
+
+2
+
+# --explanation--
+
+The word `stressful` describes situations or events that cause stress, tension, or anxiety. It is often used to talk about experiences that are challenging or demanding. For example:
+
+- `The deadline was stressful because we had so much work to do.` - Meaning they felt a lot of stress due to the deadline.
+
+- `Presenting to a large audience can be stressful.` - Meaning you can be feel really anxious when you present in front of an audience.
+
+In this question, Lisa is asking James if fixing the issue with the app and the credentials was a stressful experience for him.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "Lisa",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 35.6,
+ "finishTimestamp": 36.94
+ }
+ },
+ "commands": [
+ {
+ "character": "Lisa",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Lisa",
+ "startTime": 1,
+ "finishTime": 2.34,
+ "dialogue": {
+ "text": "Wasn't it stressful though?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Lisa",
+ "opacity": 0,
+ "startTime": 2.84
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/674604ef287b978febd50bc9.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/674604ef287b978febd50bc9.md
new file mode 100644
index 0000000000..a4abb17b7f
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/674604ef287b978febd50bc9.md
@@ -0,0 +1,80 @@
+---
+id: 674604ef287b978febd50bc9
+title: Task 30
+challengeType: 22
+dashedName: task-30
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`Wasn't it stressful BLANK?`
+
+## --blanks--
+
+`though`
+
+### --feedback--
+
+This word is used to add emphasis or to show a contrast or unexpected outcome.
+
+# --explanation--
+
+`Though` is often used at the end of a sentence to add emphasis or to show a contrast with what was previously said or implied. In this context, Lisa is emphasizing her surprise or curiosity about whether James found the situation stressful despite his success. For example:
+
+`The presentation went well, though it was stressful at first.` - Here, `though` highlights the contrast between the overall success and the initial stress.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "Lisa",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 35.6,
+ "finishTimestamp": 36.94
+ }
+ },
+ "commands": [
+ {
+ "character": "Lisa",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Lisa",
+ "startTime": 1,
+ "finishTime": 2.34,
+ "dialogue": {
+ "text": "Wasn't it stressful though?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Lisa",
+ "opacity": 0,
+ "startTime": 2.84
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/674605049656269110601a79.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/674605049656269110601a79.md
new file mode 100644
index 0000000000..447b174c6e
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/674605049656269110601a79.md
@@ -0,0 +1,86 @@
+---
+id: 674605049656269110601a79
+title: Task 31
+challengeType: 22
+dashedName: task-31
+---
+
+
+
+# --description--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`BLANK it stressful though?`
+
+## --blanks--
+
+`Wasn't`
+
+### --feedback--
+
+This is singular form of the verb `to be` in the Simple Past, but in the negative form. Do not forget to capitalize it.
+
+# --explanation--
+
+In negative questions with the verb `to be` in the Simple Past, use the structure **Wasn't/Weren't + subject + complement?**
+
+This structure is often used to confirm something or to express surprise or doubt. For example:
+
+- `Wasn't she at the meeting yesterday?` - You are not only asking about her being at the meeting, you are trying to confirm it because you think she was.
+
+- `Weren't they informed about the changes?` - You are trying to confirm if they were informed or not.
+
+In Lisa's question, `Wasn't it stressful though?`, she is asking James to confirm if the situation was stressful, possibly expecting that it might have been.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "Lisa",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 35.6,
+ "finishTimestamp": 36.94
+ }
+ },
+ "commands": [
+ {
+ "character": "Lisa",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Lisa",
+ "startTime": 1,
+ "finishTime": 2.34,
+ "dialogue": {
+ "text": "Wasn't it stressful though?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Lisa",
+ "opacity": 0,
+ "startTime": 2.84
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/674609a92ccf079d86cd81db.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/674609a92ccf079d86cd81db.md
new file mode 100644
index 0000000000..46c87a9f37
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/674609a92ccf079d86cd81db.md
@@ -0,0 +1,110 @@
+---
+id: 674609a92ccf079d86cd81db
+title: Task 32
+challengeType: 22
+dashedName: task-32
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`A BLANK, but solving problems like these is what makes our job interesting, right?`
+
+## --blanks--
+
+`bit`
+
+### --feedback--
+
+This phrase is used to indicate a small amount or degree.
+
+# --explanation--
+
+`A bit` is used to indicate a small amount or degree of something. For Example:
+
+`I was a bit tired after the long day.` - Here, `a bit` emphasizes that the speaker was slightly tired, but it wasn't extreme.
+
+This phrase is commonly used in informal contexts to soften statements or describe minor degrees of feelings or situations. In this dialog, James is admitting that the situation was slightly stressful but not overwhelming.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "Lisa",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ },
+ {
+ "character": "James",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 35.6,
+ "finishTimestamp": 41.66
+ }
+ },
+ "commands": [
+ {
+ "character": "Lisa",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Lisa",
+ "startTime": 1,
+ "finishTime": 2.34,
+ "dialogue": {
+ "text": "Wasn't it stressful though?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Lisa",
+ "opacity": 0,
+ "startTime": 2.56
+ },
+ {
+ "character": "James",
+ "opacity": 1,
+ "startTime": 2.56
+ },
+ {
+ "character": "James",
+ "startTime": 2.78,
+ "finishTime": 7.06,
+ "dialogue": {
+ "text": "A bit, but solving problems like these is what makes our job interesting, right?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "James",
+ "opacity": 0,
+ "startTime": 7.56
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67460b84234b70a4772d2094.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67460b84234b70a4772d2094.md
new file mode 100644
index 0000000000..830a85712b
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67460b84234b70a4772d2094.md
@@ -0,0 +1,95 @@
+---
+id: 67460b84234b70a4772d2094
+title: Task 33
+challengeType: 19
+dashedName: task-33
+---
+
+
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+How could Lisa confirm in a single word and enthusiastically that she agrees with what James just said?
+
+## --answers--
+
+`Absolutely!`
+
+---
+
+`Objection!`
+
+### --feedback--
+
+`Objection` is normally used in court when an attorney says they disagree with what has been said or proposed by another attorney. It expresses disagreement, not agreement.
+
+## --video-solution--
+
+1
+
+
+# --explanation--
+
+`Absolutely` is used to express complete agreement or certainty. It is often used in informal or conversational contexts to emphasize strong agreement. For example:
+
+Person 1: `Do you think we should move forward with this plan?`
+
+Person 2: `Absolutely!` - Here, `Absolutely` shows that the speaker is fully in favor of the plan and has no doubts.
+
+In this dialog, Lisa is strongly agreeing with James's point about their job being interesting because of the challenges they solve.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "James",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 37.18,
+ "finishTimestamp": 41.66
+ }
+ },
+ "commands": [
+ {
+ "character": "James",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "James",
+ "startTime": 1,
+ "finishTime": 5.48,
+ "dialogue": {
+ "text": "A bit, but solving problems like these is what makes our job interesting, right?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "James",
+ "opacity": 0,
+ "startTime": 5.98
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67461094ba7296b13c1bb045.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67461094ba7296b13c1bb045.md
new file mode 100644
index 0000000000..8b47e1f3a6
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67461094ba7296b13c1bb045.md
@@ -0,0 +1,136 @@
+---
+id: 67461094ba7296b13c1bb045
+title: Task 34
+challengeType: 19
+dashedName: task-34
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What does Lisa mean?
+
+## --answers--
+
+She completely agrees with James.
+
+---
+
+She partially agrees with James.
+
+### --feedback--
+
+`Absolutely` indicates full agreement, not partial agreement.
+
+---
+
+She is not sure she understands what James is trying to say.
+
+### --feedback--
+
+`Absolutely` shows Lisa is confident and fully agrees with James.
+
+---
+
+She disagrees with James.
+
+### --feedback--
+
+`Absolutely` is a clear expression of agreement, not disagreement.
+
+## --video-solution--
+
+1
+
+# --explanation--
+
+`Absolutely` is used to express complete agreement or certainty. For example:
+
+Person 1: `Do you think this solution will work?`
+
+Person 2: `Absolutely!` - Meaning that you are entirely confident and supportive of the solution.
+
+In this dialog, Lisa, thus, is showing James she fully agrees with what he said.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "James",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ },
+ {
+ "character": "Lisa",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 37.18,
+ "finishTimestamp": 42.82
+ }
+ },
+ "commands": [
+ {
+ "character": "James",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "James",
+ "startTime": 1,
+ "finishTime": 5.48,
+ "dialogue": {
+ "text": "A bit, but solving problems like these is what makes our job interesting, right?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "James",
+ "opacity": 0,
+ "startTime": 5.75
+ },
+ {
+ "character": "Lisa",
+ "opacity": 1,
+ "startTime": 5.75
+ },
+ {
+ "character": "Lisa",
+ "startTime": 6.02,
+ "finishTime": 6.62,
+ "dialogue": {
+ "text": "Absolutely.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Lisa",
+ "opacity": 0,
+ "startTime": 7.12
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/674612ab7e6b0ab83408262a.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/674612ab7e6b0ab83408262a.md
new file mode 100644
index 0000000000..21f30fadda
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/674612ab7e6b0ab83408262a.md
@@ -0,0 +1,86 @@
+---
+id: 674612ab7e6b0ab83408262a
+title: Task 35
+challengeType: 22
+dashedName: task-35
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`Thanks for BLANK it, James.`
+
+## --blanks--
+
+`handling`
+
+### --feedback--
+
+This word means taking care of or managing something. Use it in the `-ing` form.
+
+# --explanation--
+
+`Handle` in this context means to take care of or manage a task, issue, or responsibility. For example:
+
+ `He handled the situation professionally.` - Meaning he took care of the problem as a professional.
+
+When a verb follows a preposition, like `for`, it is used in the `-ing` form. For example:
+
+`She apologized for being late.` - The preposition `for` is followed by `being` in the -ing form.
+
+In the sentence, Lisa is thanking James for managing or solving the problem.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "Lisa",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 43.04,
+ "finishTimestamp": 44.58
+ }
+ },
+ "commands": [
+ {
+ "character": "Lisa",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Lisa",
+ "startTime": 1,
+ "finishTime": 2.54,
+ "dialogue": {
+ "text": "Thanks for handling it, James.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Lisa",
+ "opacity": 0,
+ "startTime": 3.04
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/674616565854f7c788740cee.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/674616565854f7c788740cee.md
new file mode 100644
index 0000000000..5ecbaf5e72
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/674616565854f7c788740cee.md
@@ -0,0 +1,110 @@
+---
+id: 674616565854f7c788740cee
+title: Task 36
+challengeType: 19
+dashedName: task-36
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What does Lisa want to know?
+
+## --answers--
+
+She wants to know why James was debugging.
+
+### --feedback--
+
+Lisa's question isn't about the reason for debugging; it's about whether other issues came up during that time.
+
+---
+
+She wants to know when James started debugging.
+
+### --feedback--
+
+Lisa's question focuses on what else happened during debugging, not the timing.
+
+---
+
+She wants to know if any other issues appeared while James was debugging.
+
+---
+
+She wants to know if debugging is finished.
+
+### --feedback--
+
+Lisa's question is about what happened during debugging, not whether it is finished.
+
+## --video-solution--
+
+3
+
+# --explanation--
+
+In this question, Lisa uses the `Simple Past` and the `Past Continuous` to ask about two actions that occurred in the past.
+
+`Did anything else come up` describes a completed action or event that may have occurred at some point during the debugging process. (`Simple Past`)
+
+`While you were debugging` describes an ongoing activity in the past during which the event in the Simple Past could have happened. (`Past Continuous`) For example:
+
+`Did anyone call while you were working on the report?` - here, the `Simple Past` tense asks about a specific event, while the `Past Continuous` provides the background activity during which the event could have happened.
+
+This combination is used to show the occurrence of an event in the middle of another, longer one, or simultaneous longer actions happening in the past.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "Lisa",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 44.92,
+ "finishTimestamp": 47.02
+ }
+ },
+ "commands": [
+ {
+ "character": "Lisa",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Lisa",
+ "startTime": 1,
+ "finishTime": 3.1,
+ "dialogue": {
+ "text": "Did anything else come up while you were debugging?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Lisa",
+ "opacity": 0,
+ "startTime": 3.6
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/674619b6699a06d064c9717f.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/674619b6699a06d064c9717f.md
new file mode 100644
index 0000000000..4eedb646ec
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/674619b6699a06d064c9717f.md
@@ -0,0 +1,94 @@
+---
+id: 674619b6699a06d064c9717f
+title: Task 37
+challengeType: 22
+dashedName: task-37
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`Did anything else BLANK up while you were BLANK?`
+
+## --blanks--
+
+`come`
+
+### --feedback--
+
+Followed by `up` in this phrase, it means to arise or appear unexpectedly.
+
+---
+
+`debugging`
+
+### --feedback--
+
+This word refers to identifying and fixing errors or issues in code. Use the `-ing` form.
+
+# --explanation--
+
+`Come up` means to arise, appear, or occur unexpectedly. For example:
+
+`Something important came up during the meeting, and we had to address it immediately.` - Meaning something occurred during the meeting that needed immediate attention.
+
+`Debugging` refers to the process of identifying and resolving errors or issues in code. For example:
+
+`The team spent hours debugging the software before the release.` - Meaning they spent a long time identifying and solving these errors.
+
+Lisa's question asks if any other unexpected issues could be seen during the process of fixing code errors.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "Lisa",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 44.92,
+ "finishTimestamp": 47.02
+ }
+ },
+ "commands": [
+ {
+ "character": "Lisa",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Lisa",
+ "startTime": 1,
+ "finishTime": 3.1,
+ "dialogue": {
+ "text": "Did anything else come up while you were debugging?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Lisa",
+ "opacity": 0,
+ "startTime": 3.6
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67461c06865e13d715967f1d.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67461c06865e13d715967f1d.md
new file mode 100644
index 0000000000..ded0a6c923
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/67461c06865e13d715967f1d.md
@@ -0,0 +1,89 @@
+---
+id: 67461c06865e13d715967f1d
+title: Task 38
+challengeType: 22
+dashedName: task-38
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`Did BLANK else come up while you were debugging?`
+
+## --blanks--
+
+`anything`
+
+### --feedback--
+
+This word is used in questions to ask if something occurred or existed.
+
+# --explanation--
+
+`Anything` is used in questions to ask if something happened, existed, or was present. It is neutral and does not assume the existence of anything specific. For example:
+
+`Did anything unusual happen during the test?` - Meaning you are asking about unusual events that could be found during the test.
+
+In affirmative sentences, use `something` to indicate the existence of a thing. For example:
+
+`Something interesting happened during the meeting.` - Meaning a different thing than the usual happened.
+
+In negative sentences, use `anything` to indicate that no thing occurred or existed. For example:
+
+`I didn't see anything unusual in the report.` - meaning there were no surprises in the report.
+
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "Lisa",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 44.92,
+ "finishTimestamp": 47.02
+ }
+ },
+ "commands": [
+ {
+ "character": "Lisa",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Lisa",
+ "startTime": 1,
+ "finishTime": 3.1,
+ "dialogue": {
+ "text": "Did anything else come up while you were debugging?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Lisa",
+ "opacity": 0,
+ "startTime": 3.6
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/675060b39af6ab3f14f394e2.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/675060b39af6ab3f14f394e2.md
new file mode 100644
index 0000000000..a2526df227
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/675060b39af6ab3f14f394e2.md
@@ -0,0 +1,142 @@
+---
+id: 675060b39af6ab3f14f394e2
+title: Task 39
+challengeType: 19
+dashedName: task-39
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What does James mean by his answer?
+
+## --answers--
+
+He means several major issues appeared after fixing the database.
+
+### --feedback--
+
+James says, `Not really`, meaning there were no significant issues after the database was fixed.
+
+---
+
+He means the database issue is still unresolved.
+
+### --feedback--
+
+James mentions that the database issue was fixed and everything else was running smoothly afterwards.
+
+---
+
+He means debugging was stressful the whole time.
+
+### --feedback--
+
+James mentions that things ran smoothly once the database issue was resolved, implying the stress decreased.
+
+---
+
+He means there were no significant issues after fixing the database.
+
+## --video-solution--
+
+4
+
+# --explanation--
+
+James means that the situation improved right after the database issue was resolved. He uses `Not really` to indicate that no major issues occurred, though there may have been minor or insignificant ones. This phrase is often used to soften a negative response. For example:
+
+Person 1: `Did you enjoy the movie?`
+
+Person 2: `Not really. It was too slow.` - This means you did not like the movie much.
+
+`Smoothly` is an adverb meaning without problems or interruptions. While `smoothly` (adverb) describes how an action is performed, `smooth` (adjective) describes a state or quality. For example:
+
+`The meeting went smoothly after everyone arrived on time.` - This means everything was ok at the meeting.
+
+`The surface of the table is smooth.` - Meaning there were no inconsistencies in the surface.
+
+`Once` means the same as `as soon as` or `after`, indicating that everything ran smoothly after the database was fixed. For example: - `Once the updates were installed, the system worked perfectly.` (this means that the system worked after the updates were installed)
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "Lisa",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ },
+ {
+ "character": "James",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 45.12,
+ "finishTimestamp": 51.6
+ }
+ },
+ "commands": [
+ {
+ "character": "Lisa",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Lisa",
+ "startTime": 1,
+ "finishTime": 2.7,
+ "dialogue": {
+ "text": "Did anything else come up while you were debugging?",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Lisa",
+ "opacity": 0,
+ "startTime": 2.94
+ },
+ {
+ "character": "James",
+ "opacity": 1,
+ "startTime": 2.94
+ },
+ {
+ "character": "James",
+ "startTime": 3.18,
+ "finishTime": 7.48,
+ "dialogue": {
+ "text": "Not really. Everything else was running smoothly once the database issue was fixed.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "James",
+ "opacity": 0,
+ "startTime": 7.98
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6750651aafcea04c6958a4e5.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6750651aafcea04c6958a4e5.md
new file mode 100644
index 0000000000..410a3459d8
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6750651aafcea04c6958a4e5.md
@@ -0,0 +1,88 @@
+---
+id: 6750651aafcea04c6958a4e5
+title: Task 40
+challengeType: 22
+dashedName: task-40
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`Everything else BLANK running smoothly once the database issue was fixed.`
+
+## --blanks--
+
+`was`
+
+### --feedback--
+
+This word is the singular form of the verb `to be` in the Simple Past, used with subjects like `everything`, `something`, `anything`, and `nothing`.
+
+# --explanation--
+
+Words like `everything`, `something`, `anything`, and `nothing` are indefinite pronouns that take singular verbs, even though they may refer to multiple items or concepts. For example:
+
+- `Everything was ready for the presentation.` - `Everything` refers to all things and requires a singular verb.
+
+- `Something is wrong with the code.` - `Something` refers to an unspecified thing and takes a singular verb.
+
+- `Is anything missing from the report?` - `Anything` refers to any one thing in a general sense and uses a singular verb.
+
+- `Nothing was found in the logs.` - `Nothing` refers to the absence of things and requires a singular verb)
+
+In the sentence `Everything else was running smoothly`, you use `was` because `everything` is treated as singular, even though it refers to multiple elements.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "James",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 48.3,
+ "finishTimestamp": 51.6
+ }
+ },
+ "commands": [
+ {
+ "character": "James",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "James",
+ "startTime": 1,
+ "finishTime": 4.3,
+ "dialogue": {
+ "text": "Everything else was running smoothly once the database issue was fixed.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "James",
+ "opacity": 0,
+ "startTime": 4.8
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6750697ee8b87f5e665c0712.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6750697ee8b87f5e665c0712.md
new file mode 100644
index 0000000000..1919acb2f2
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6750697ee8b87f5e665c0712.md
@@ -0,0 +1,88 @@
+---
+id: 6750697ee8b87f5e665c0712
+title: Task 41
+challengeType: 22
+dashedName: task-41
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`Perfect. Let's make sure we BLANK BLANK credentials after security updates in the future.`
+
+## --blanks--
+
+`double`
+
+### --feedback--
+
+This word means to do something twice or with extra care.
+
+---
+
+`check`
+
+### --feedback--
+
+This word refers to verifying or confirming something.
+
+# --explanation--
+
+`Double check` means to verify something a second time to ensure it is correct or accurate. It is often used when dealing with important tasks to avoid errors. For example:
+
+`We need to double check the calculations before submitting the report.` - Meaning you'd like to verify if the calculations are right once more before sending the report to those who will analyze it.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "interview-room3.png",
+ "characters": [
+ {
+ "character": "Lisa",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-1.mp3",
+ "startTime": 1,
+ "startTimestamp": 51.92,
+ "finishTimestamp": 56
+ }
+ },
+ "commands": [
+ {
+ "character": "Lisa",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Lisa",
+ "startTime": 1,
+ "finishTime": 5.08,
+ "dialogue": {
+ "text": "Perfect. Let's make sure we double check credentials after security updates in the future.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Lisa",
+ "opacity": 0,
+ "startTime": 5.58
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/675846ef3e2e50e95e99aded.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/675846ef3e2e50e95e99aded.md
new file mode 100644
index 0000000000..12e2fbef9c
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/675846ef3e2e50e95e99aded.md
@@ -0,0 +1,92 @@
+---
+id: 675846ef3e2e50e95e99aded
+title: Task 104
+challengeType: 22
+dashedName: task-104
+---
+
+
+
+# --instructions--
+
+Listen to the audio and complete the sentence below.
+
+# --fillInTheBlank--
+
+## --sentence--
+
+`It made me think of how we BLANK security in our BLANK projects.`
+
+## --blanks--
+
+`handled`
+
+### --feedback--
+
+This word means to manage or deal with something. It's in its Simple Past form.
+
+---
+
+`earlier`
+
+### --feedback--
+
+This word means happening or existing before a certain point in time.
+
+# --explanation--
+
+`Handle` means to manage or deal with something, especially a task, problem, or responsibility. For example:
+
+`She handled the customer complaints with great professionalism.` - This means she was very professional when dealing with customers and their negative comments.
+
+`Earlier` means happening before a certain point in time. For example:
+
+`He referred to an earlier email to clarify the misunderstanding.` - This means he mentioned an email that was sent before to help everyone understand the case.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "cafe.png",
+ "characters": [
+ {
+ "character": "Brian",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-3.mp3",
+ "startTime": 1,
+ "startTimestamp": 54.1,
+ "finishTimestamp": 57.84
+ }
+ },
+ "commands": [
+ {
+ "character": "Brian",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Brian",
+ "startTime": 1,
+ "finishTime": 4.74,
+ "dialogue": {
+ "text": "It made me think of how we handled security in our earlier projects.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Brian",
+ "opacity": 0,
+ "startTime": 5.24
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6758486d05a8fcf01a20c8b4.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6758486d05a8fcf01a20c8b4.md
new file mode 100644
index 0000000000..06f85c5338
--- /dev/null
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-how-to-talk-about-past-experiences/6758486d05a8fcf01a20c8b4.md
@@ -0,0 +1,115 @@
+---
+id: 6758486d05a8fcf01a20c8b4
+title: Task 105
+challengeType: 19
+dashedName: task-105
+---
+
+
+
+# --instructions--
+
+Listen to the audio and answer the question below.
+
+# --questions--
+
+## --text--
+
+What did Brian think about the cybersecurity workshop?
+
+## --answers--
+
+He thought it didn't provide useful information.
+
+### --feedback--
+
+Brian mentions that the workshop made him think about past projects, indicating it had an impact.
+
+---
+
+He thought it made him reflect on how they handled security in earlier projects.
+
+---
+
+He thought it was unrelated to their previous work.
+
+### --feedback--
+
+Brian explicitly connects the workshop to how they handled security in earlier projects.
+
+---
+
+He thought it wasn't worth attending.
+
+### --feedback--
+
+Brian found the workshop impactful as it made him think about their past security practices.
+
+## --video-solution--
+
+2
+
+# --explanation--
+
+`Make` someone `think` means to prompt reflection or consideration about a particular topic or situation. It often refers to something that causes a person to evaluate or analyze an issue more deeply. For example:
+
+`The documentary made me think about how I can reduce my carbon footprint.` - This means that watching the documentary helped you think about how to pollute less.
+
+In this context, the cybersecurity workshop prompted Brian to reflect on how they managed security in their projects in the past.
+
+# --scene--
+
+```json
+{
+ "setup": {
+ "background": "cafe.png",
+ "characters": [
+ {
+ "character": "Brian",
+ "position": {
+ "x": 50,
+ "y": 15,
+ "z": 1.2
+ },
+ "opacity": 0
+ }
+ ],
+ "audio": {
+ "filename": "B1_2-3.mp3",
+ "startTime": 1,
+ "startTimestamp": 50.22,
+ "finishTimestamp": 57.84
+ }
+ },
+ "commands": [
+ {
+ "character": "Brian",
+ "opacity": 1,
+ "startTime": 0
+ },
+ {
+ "character": "Brian",
+ "startTime": 1,
+ "finishTime": 4.54,
+ "dialogue": {
+ "text": "It was eye-opening, especially the parts about protecting data.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Brian",
+ "startTime": 4.88,
+ "finishTime": 8.62,
+ "dialogue": {
+ "text": "It made me think of how we handled security in our earlier projects.",
+ "align": "center"
+ }
+ },
+ {
+ "character": "Brian",
+ "opacity": 0,
+ "startTime": 9.12
+ }
+ ]
+}
+```
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/67165185a42acc499c6ada3d.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/67165185a42acc499c6ada3d.md
index 15c1ba625a..e00d5c279b 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/67165185a42acc499c6ada3d.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/67165185a42acc499c6ada3d.md
@@ -23,7 +23,7 @@ If the screen reader updates are completely finished.
### --feedback--
-Tom’s question is about an ongoing process, not whether the updates are fully completed.
+Tom's question is about an ongoing process, not whether the updates are fully completed.
---
@@ -31,7 +31,7 @@ If the screen reader updates have not started yet.
### --feedback--
-Tom’s question suggests that the updates have already started, not that they haven’t begun.
+Tom's question suggests that the updates have already started, not that they haven't begun.
---
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6716531210ee374ae822fe83.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6716531210ee374ae822fe83.md
index 3569fd6722..18d3578908 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6716531210ee374ae822fe83.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6716531210ee374ae822fe83.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-6
---
-
+
# --instructions--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671655545e5bfc4c3dfe9871.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671655545e5bfc4c3dfe9871.md
index 5945848ef3..23fb1d4747 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671655545e5bfc4c3dfe9871.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671655545e5bfc4c3dfe9871.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-7
---
-
+
# --instructions--
@@ -15,7 +15,7 @@ Listen to the audio and complete the sentence below.
## --sentence--
-`Yes, I started a few months ago. BLANK been BLANK the BLANK from our last user BLANK. How’s the design side coming along?`
+`Yes, I started a few months ago. BLANK been BLANK the BLANK from our last user BLANK. How's the design side coming along?`
## --blanks--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/67165855c3dd824eabc1b474.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/67165855c3dd824eabc1b474.md
index e2089ae1fd..6d32c229cd 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/67165855c3dd824eabc1b474.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/67165855c3dd824eabc1b474.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-8
---
-
+
# --instructions--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6716593b4f24da4fac3154bf.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6716593b4f24da4fac3154bf.md
index 1ce1230835..265905054b 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6716593b4f24da4fac3154bf.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6716593b4f24da4fac3154bf.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-9
---
-
+
# --instructions--
@@ -15,7 +15,7 @@ Listen to the audio and complete the sentence below.
## --sentence--
-`Yes, I started a few months ago. We've been addressing the feedback from our last user survey. How’s the BLANK side BLANK?`
+`Yes, I started a few months ago. We've been addressing the feedback from our last user survey. How's the BLANK side BLANK?`
## --blanks--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6717b20b952c096b3dee0834.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6717b20b952c096b3dee0834.md
index fadad1430c..1810c7563c 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6717b20b952c096b3dee0834.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6717b20b952c096b3dee0834.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-10
---
-
+
@@ -17,7 +17,7 @@ Listen to the audio and answer the question below.
## --text--
-What’s the best answer to Sophie's question about the design side?
+What's the best answer to Sophie's question about the design side?
## --answers--
@@ -37,7 +37,7 @@ This response is unrelated to the design side and does not answer Sophie's quest
# --explanation--
-Sophie's question `How’s the design side coming along?` asks about the progress of the design work. The best answer should provide a relevant update.
+Sophie's question `How's the design side coming along?` asks about the progress of the design work. The best answer should provide a relevant update.
# --scene--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6717b6aa217d3d6ed6f83e53.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6717b6aa217d3d6ed6f83e53.md
index c0067aa9a8..0c2d06bfe5 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6717b6aa217d3d6ed6f83e53.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6717b6aa217d3d6ed6f83e53.md
@@ -45,7 +45,7 @@ These are the rules or instructions that provide direction for how something sho
To `tweak` means to make a slight adjustment or modification. For example:
-`The developer tweaked the code to improve the app’s performance.` - This means that the developer made small changes to the code to enhance how the app functions.
+`The developer tweaked the code to improve the app's performance.` - This means that the developer made small changes to the code to enhance how the app functions.
`Layouts` are the arrangement or structure of elements on a page or interface. For example:
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6717ba3d37ec4e73a50878da.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6717ba3d37ec4e73a50878da.md
index 7044f32296..06f1d20511 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6717ba3d37ec4e73a50878da.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6717ba3d37ec4e73a50878da.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-13
---
-
+
# --instructions--
@@ -15,7 +15,7 @@ Listen to the audio and complete the sentence below.
## --sentence--
-`That’s good to hear. Do you think the users BLANK BLANK the BLANK?`
+`That's good to hear. Do you think the users BLANK BLANK the BLANK?`
## --blanks--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6717c0dc8b764279dfc9326b.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6717c0dc8b764279dfc9326b.md
index d2bdf1a766..70d243060e 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6717c0dc8b764279dfc9326b.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6717c0dc8b764279dfc9326b.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-15
---
-
+
# --instructions--
@@ -23,7 +23,7 @@ If the users are happy with the design updates.
### --feedback--
-Sophie’s focus is on whether users have observed the improvements, not if they are happy with the design.
+Sophie's focus is on whether users have observed the improvements, not if they are happy with the design.
---
@@ -51,7 +51,7 @@ Sophie is interested in whether users have observed the improvements, not about
# --explanation--
-Sophie’s question shows her curiosity about whether users are aware of the positive changes made to the product.
+Sophie's question shows her curiosity about whether users are aware of the positive changes made to the product.
# --scene--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6717c3557815a17d6369a778.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6717c3557815a17d6369a778.md
index c0ea97751c..8dd9370f36 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6717c3557815a17d6369a778.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6717c3557815a17d6369a778.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-16
---
-
+
# --instructions--
@@ -47,7 +47,7 @@ These are opinions or feedback shared by users, in the plural form.
`Negative` refers to something unfavorable or critical. For example:
-`The user left a negative review about the app’s performance.` - Here, `negative` describes the unfavorable nature of the review.
+`The user left a negative review about the app's performance.` - Here, `negative` describes the unfavorable nature of the review.
`Comment` is an opinion or piece of feedback provided by someone. Its plural form is `comments`. For example:
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a383a56179f510b83cc1e.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a383a56179f510b83cc1e.md
index 79715619a6..82f5580840 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a383a56179f510b83cc1e.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a383a56179f510b83cc1e.md
@@ -5,9 +5,9 @@ challengeType: 19
dashedName: task-17
---
-
+Tom: I think so. We haven't been receiving as many negative comments. -->
# --instructions--
@@ -17,7 +17,7 @@ Listen to the audio and answer the question below.
## --text--
-How does Tom respond to Sophie’s question about user feedback?
+How does Tom respond to Sophie's question about user feedback?
## --answers--
@@ -25,11 +25,11 @@ He says the users have noticed more negative comments.
### --feedback--
-Tom actually mentions that they haven’t been receiving as many negative comments.
+Tom actually mentions that they haven't been receiving as many negative comments.
---
-He says they haven’t been receiving as many negative comments.
+He says they haven't been receiving as many negative comments.
---
@@ -41,7 +41,7 @@ Tom does not specifically mention positive comments, only that the negative ones
---
-He says he’s waiting for more feedback.
+He says he's waiting for more feedback.
### --feedback--
@@ -53,7 +53,7 @@ Tom is talking about the current trend of fewer negative comments, not waiting f
# --explanation--
-Tom's response, `We haven’t been receiving as many negative comments`, uses the `Present Perfect Continuous` in the negative form. This tense is formed by `haven’t/hasn’t + been + verb(-ing)` and is used to describe actions that have not been happening over a period of time. In this case, it shows that fewer negative comments have been received over time, indicating a possible improvement.
+Tom's response, `We haven't been receiving as many negative comments`, uses the `Present Perfect Continuous` in the negative form. This tense is formed by `haven't/hasn't + been + verb(-ing)` and is used to describe actions that have not been happening over a period of time. In this case, it shows that fewer negative comments have been received over time, indicating a possible improvement.
# --scene--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a3c13a3d6b21a1b0008f7.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a3c13a3d6b21a1b0008f7.md
index 9c830e0fb1..e9f3b3334e 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a3c13a3d6b21a1b0008f7.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a3c13a3d6b21a1b0008f7.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-18
---
-
+
# --instructions--
@@ -41,7 +41,7 @@ This refers to changes made to improve or adapt something. It's plural form.
`Adjustments` means small changes made to improve or adapt something. For example,
-`We made adjustments to the app’s layout for better user experience.` - `Adjustments` refers to the changes made to improve how users interact with the app.
+`We made adjustments to the app's layout for better user experience.` - `Adjustments` refers to the changes made to improve how users interact with the app.
# --scene--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a3dde9c50241c6c16e331.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a3dde9c50241c6c16e331.md
index de3b5acf88..b89232b499 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a3dde9c50241c6c16e331.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a3dde9c50241c6c16e331.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-19
---
-
+
# --instructions--
@@ -51,7 +51,7 @@ Sophie does not express frustration. She mentions feeling relieved instead.
# --explanation--
-Sophie’s use of `That’s a relief` indicates that she feels better or more comfortable about the progress being made, rather than feeling worried, confused, or frustrated.
+Sophie's use of `That's a relief` indicates that she feels better or more comfortable about the progress being made, rather than feeling worried, confused, or frustrated.
# --scene--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a3ed10fd6e81d06dd4690.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a3ed10fd6e81d06dd4690.md
index f58008dac2..37fd99a4a2 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a3ed10fd6e81d06dd4690.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a3ed10fd6e81d06dd4690.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-20
---
-
+
# --instructions--
@@ -51,7 +51,7 @@ Sophie is not asking about the effectiveness of the adjustments.
# --explanation--
-Sophie’s question shows that she is trying to understand the time required to continue making changes, focusing on the duration rather than the reasons or results.
+Sophie's question shows that she is trying to understand the time required to continue making changes, focusing on the duration rather than the reasons or results.
# --scene--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a40b415343c1f26e0c005.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a40b415343c1f26e0c005.md
index 69f47f8b11..dd24f2e8df 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a40b415343c1f26e0c005.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a40b415343c1f26e0c005.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-21
---
-
+
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a41b8576531207749bdae.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a41b8576531207749bdae.md
index 81b269862a..c97d340ce0 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a41b8576531207749bdae.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a41b8576531207749bdae.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-22
---
-
+
# --instructions--
@@ -15,7 +15,7 @@ Listen to the audio and complete the sentence below.
## --sentence--
-`Probably a few more weeks. We've been making steady BLANK, and I believe we’re close to BLANK the major changes.`
+`Probably a few more weeks. We've been making steady BLANK, and I believe we're close to BLANK the major changes.`
## --blanks--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a438ac97103231787ab5a.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a438ac97103231787ab5a.md
index 325b688496..307efe14aa 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a438ac97103231787ab5a.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a438ac97103231787ab5a.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-23
---
-
+
# --instructions--
@@ -51,7 +51,7 @@ Tom estimates that they will need only a few more weeks, not several months.
# --explanation--
-Tom’s statement indicates that the team has been working consistently and expects to complete the changes in a few more weeks.
+Tom's statement indicates that the team has been working consistently and expects to complete the changes in a few more weeks.
# --scene--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a45f9b4ee3325393f0d0b.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a45f9b4ee3325393f0d0b.md
index 7e6517f365..dae8e6a5b1 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a45f9b4ee3325393f0d0b.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a45f9b4ee3325393f0d0b.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-24
---
-
+
# --instructions--
@@ -15,7 +15,7 @@ Listen to the audio and complete the sentence below.
## --sentence--
-`That’s good news! It feels great to make our app more BLANK.`
+`That's good news! It feels great to make our app more BLANK.`
## --blanks--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a46fe18ae6a26c76f42f6.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a46fe18ae6a26c76f42f6.md
index ce5bea3758..efbd0d94eb 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a46fe18ae6a26c76f42f6.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a46fe18ae6a26c76f42f6.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-25
---
-
+
# --instructions--
@@ -23,7 +23,7 @@ She is happy about making the app look more colorful.
### --feedback--
-No, `accessible` doesn’t refer to colors or design aesthetics. It means making the app easier for all users, including those with different needs, to use.
+No, `accessible` doesn't refer to colors or design aesthetics. It means making the app easier for all users, including those with different needs, to use.
---
@@ -31,7 +31,7 @@ She is pleased that the app is becoming easier for everyone to use, including us
---
-She thinks the app’s loading speed has improved significantly.
+She thinks the app's loading speed has improved significantly.
### --feedback--
@@ -51,7 +51,7 @@ Sophie is focused on making the app easier to use for all, which is what `access
# --explanation--
-When Sophie says `It feels great to make our app more accessible`, she’s emphasizing the importance of making the app easier to use for all users, regardless of their abilities. Being `accessible` or `accessibility` aims to ensure that everyone, including people with disabilities, can interact with the app effectively.
+When Sophie says `It feels great to make our app more accessible`, she's emphasizing the importance of making the app easier to use for all users, regardless of their abilities. Being `accessible` or `accessibility` aims to ensure that everyone, including people with disabilities, can interact with the app effectively.
# --scene--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a4aeac046082b1bf6335b.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a4aeac046082b1bf6335b.md
index 26be04f9f2..efdc7a460f 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a4aeac046082b1bf6335b.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a4aeac046082b1bf6335b.md
@@ -33,7 +33,7 @@ An app introduces a new payment gateway to make transactions faster.
### --feedback--
-While this improves functionality, it doesn’t relate to making the app accessible to users with different needs.
+While this improves functionality, it doesn't relate to making the app accessible to users with different needs.
---
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a4e181afe602d37786dd8.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a4e181afe602d37786dd8.md
index d8fb122995..fe84c41c8a 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a4e181afe602d37786dd8.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671a4e181afe602d37786dd8.md
@@ -13,7 +13,7 @@ This is a review of the entire dialogue you just studied.
# --instructions--
-Place the following phrases in the correct spot: `negative comments`, `been addressing`, `That’s a relief`, `more accessible`, and `keep making adjustments`.
+Place the following phrases in the correct spot: `negative comments`, `been addressing`, `That's a relief`, `more accessible`, and `keep making adjustments`.
# --fillInTheBlank--
@@ -21,19 +21,19 @@ Place the following phrases in the correct spot: `negative comments`, `been addr
`Tom: Hey Sophie, have you been working on the screen reader updates recently?`
-`Sophie: Yes, I started a few months ago. We've BLANK the feedback from our last user survey. How’s the design side coming along?`
+`Sophie: Yes, I started a few months ago. We've BLANK the feedback from our last user survey. How's the design side coming along?`
`Tom: Pretty well, actually. I've been tweaking the layouts based on the guidelines you shared.`
-`Sophie: That’s good to hear. Do you think the users have noticed the improvements?`
+`Sophie: That's good to hear. Do you think the users have noticed the improvements?`
-`Tom: I think so. We haven’t been receiving as many BLANK.`
+`Tom: I think so. We haven't been receiving as many BLANK.`
-`Sophie: BLANK. How long do you think we’ll need to BLANK?`
+`Sophie: BLANK. How long do you think we'll need to BLANK?`
-`Tom: Probably a few more weeks. We've been making steady progress, and I believe we’re close to finalizing the major changes.`
+`Tom: Probably a few more weeks. We've been making steady progress, and I believe we're close to finalizing the major changes.`
-`Sophie: That’s good news! It feels great to make our app BLANK.`
+`Sophie: That's good news! It feels great to make our app BLANK.`
## --blanks--
@@ -53,7 +53,7 @@ This phrase refers to unfavorable feedback from users.
---
-`That’s a relief`
+`That's a relief`
### --feedback--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671b71da8e1b963c69b6d011.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671b71da8e1b963c69b6d011.md
index 6eef5b864b..3bbf0ae579 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671b71da8e1b963c69b6d011.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671b71da8e1b963c69b6d011.md
@@ -19,9 +19,9 @@ Read the text and answer the question below.
`Recently, they added special labels to buttons, menus, and forms, so screen readers can understand these parts better. They also improved the way headings, lists, and tables are organized, making the layouts easier for users to move through the app.`
-`Tom has been testing these improvements using popular screen readers, while Sophie has been focusing on tweaking the app’s text-to-speech function. They also increased the contrast, which helps users see different sections more clearly.`
+`Tom has been testing these improvements using popular screen readers, while Sophie has been focusing on tweaking the app's text-to-speech function. They also increased the contrast, which helps users see different sections more clearly.`
-`Sophie still wonders, “Have we done enough to make our app accessible?” They plan to conduct some surveys and add features like adjustable colors and keyboard shortcuts to make the app even more user-friendly.`
+`Sophie still wonders, "Have we done enough to make our app accessible?" They plan to conduct some surveys and add features like adjustable colors and keyboard shortcuts to make the app even more user-friendly.`
What changes have Tom and Sophie made to help screen readers?
@@ -47,7 +47,7 @@ The focus is on making the app easier to use with screen readers, not on speed.
---
-They changed the app’s language settings.
+They changed the app's language settings.
### --feedback--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671b769169e38f3fe57b141c.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671b769169e38f3fe57b141c.md
index fb59495032..57aa5bd1c9 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671b769169e38f3fe57b141c.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671b769169e38f3fe57b141c.md
@@ -19,11 +19,11 @@ Read the text and answer the question below.
`Recently, they added special labels to buttons, menus, and forms, so screen readers can understand these parts better. They also improved the way headings, lists, and tables are organized, making the layouts easier for users to move through the app.`
-`Tom has been testing these improvements using popular screen readers, while Sophie has been focusing on tweaking the app’s text-to-speech function. They also increased the contrast, which helps users see different sections more clearly.`
+`Tom has been testing these improvements using popular screen readers, while Sophie has been focusing on tweaking the app's text-to-speech function. They also increased the contrast, which helps users see different sections more clearly.`
-`Sophie still wonders, “Have we done enough to make our app accessible?” They plan to conduct some surveys and add features like adjustable colors and keyboard shortcuts to make the app even more user-friendly.`
+`Sophie still wonders, "Have we done enough to make our app accessible?" They plan to conduct some surveys and add features like adjustable colors and keyboard shortcuts to make the app even more user-friendly.`
-What was Tom’s main role in improving screen reader compatibility?
+What was Tom's main role in improving screen reader compatibility?
## --answers--
@@ -31,11 +31,11 @@ He tested the new features to make sure they worked well.
---
-He designed the app’s new color scheme.
+He designed the app's new color scheme.
### --feedback--
-Tom’s focus was on testing the screen reader features, not designing the color scheme.
+Tom's focus was on testing the screen reader features, not designing the color scheme.
---
@@ -43,7 +43,7 @@ He translated the app into different languages.
### --feedback--
-Translating the app was not part of Tom’s role in this context.
+Translating the app was not part of Tom's role in this context.
---
@@ -51,7 +51,7 @@ He added more images to the app.
### --feedback--
-Tom’s main task was to test screen reader compatibility, not to add images.
+Tom's main task was to test screen reader compatibility, not to add images.
## --video-solution--
@@ -59,7 +59,7 @@ Tom’s main task was to test screen reader compatibility, not to add images.
# --explanation--
-To find the correct answer, pay attention to the section that explains Tom’s main role in improving the app.
+To find the correct answer, pay attention to the section that explains Tom's main role in improving the app.
The paragraph states that Tom `has been testing these improvements` to ensure they were effective for screen reader users, which shows his focus on checking the compatibility of these updates.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671b77cf9ef25a416449b109.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671b77cf9ef25a416449b109.md
index e599f1a1ee..4f68fe5a22 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671b77cf9ef25a416449b109.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671b77cf9ef25a416449b109.md
@@ -19,9 +19,9 @@ Read the text and answer the question below.
`Recently, they added special labels to buttons, menus, and forms, so screen readers can understand these parts better. They also improved the way headings, lists, and tables are organized, making the layouts easier for users to move through the app.`
-`Tom has been testing these improvements using popular screen readers, while Sophie has been focusing on tweaking the app’s text-to-speech function. They also increased the contrast, which helps users see different sections more clearly.`
+`Tom has been testing these improvements using popular screen readers, while Sophie has been focusing on tweaking the app's text-to-speech function. They also increased the contrast, which helps users see different sections more clearly.`
-`Sophie still wonders, “Have we done enough to make our app accessible?” They plan to conduct some surveys and add features like adjustable colors and keyboard shortcuts to make the app even more user-friendly.`
+`Sophie still wonders, "Have we done enough to make our app accessible?" They plan to conduct some surveys and add features like adjustable colors and keyboard shortcuts to make the app even more user-friendly.`
What specific improvement did Sophie make to help users understand spoken content better?
@@ -35,11 +35,11 @@ Adding colorful icons is not related to spoken content or screen reader compatib
---
-She worked on making the app’s speech output clearer.
+She worked on making the app's speech output clearer.
---
-She changed the app’s loading speed.
+She changed the app's loading speed.
### --feedback--
@@ -47,7 +47,7 @@ Changing the loading speed is not related to improving spoken content.
---
-She redesigned the app’s interface layout.
+She redesigned the app's interface layout.
### --feedback--
@@ -59,8 +59,8 @@ Sophie's work specifically aimed to improve how users hear and understand the sp
# --explanation--
-Focus on the part that describes Sophie’s efforts to enhance screen reader compatibility.
+Focus on the part that describes Sophie's efforts to enhance screen reader compatibility.
-The paragraph mentions that her focus is `tweaking the app’s text-to-speech function` to help users better understand spoken content from the app.
+The paragraph mentions that her focus is `tweaking the app's text-to-speech function` to help users better understand spoken content from the app.
-Look for an option that aligns with Sophie’s specific task of enhancing the app’s text-to-speech functionality.
+Look for an option that aligns with Sophie's specific task of enhancing the app's text-to-speech functionality.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671b7c10cd0d274552e7b686.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671b7c10cd0d274552e7b686.md
index 8b66d6f92b..948092b43a 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671b7c10cd0d274552e7b686.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671b7c10cd0d274552e7b686.md
@@ -19,11 +19,11 @@ Read the text and answer the question below.
`Recently, they added special labels to buttons, menus, and forms, so screen readers can understand these parts better. They also improved the way headings, lists, and tables are organized, making the layouts easier for users to move through the app.`
-`Tom has been testing these improvements using popular screen readers, while Sophie has been focusing on tweaking the app’s text-to-speech function. They also increased the contrast, which helps users see different sections more clearly.`
+`Tom has been testing these improvements using popular screen readers, while Sophie has been focusing on tweaking the app's text-to-speech function. They also increased the contrast, which helps users see different sections more clearly.`
-`Sophie still wonders, “Have we done enough to make our app accessible?” They plan to conduct some surveys and add features like adjustable colors and keyboard shortcuts to make the app even more user-friendly.`
+`Sophie still wonders, "Have we done enough to make our app accessible?" They plan to conduct some surveys and add features like adjustable colors and keyboard shortcuts to make the app even more user-friendly.`
-What is Sophie concerned about regarding the app’s accessibility?
+What is Sophie concerned about regarding the app's accessibility?
## --answers--
@@ -31,15 +31,15 @@ Whether users like the new color scheme.
### --feedback--
-Sophie’s concern is about making the app accessible overall, not about color preferences.
+Sophie's concern is about making the app accessible overall, not about color preferences.
---
-Whether the app’s speed has improved enough.
+Whether the app's speed has improved enough.
### --feedback--
-Sophie’s focus is on making the app more accessible, not its speed.
+Sophie's focus is on making the app more accessible, not its speed.
---
@@ -47,7 +47,7 @@ Whether they have enough user surveys completed.
### --feedback--
-Sophie’s concern is not about the number of surveys but about the app's overall accessibility.
+Sophie's concern is not about the number of surveys but about the app's overall accessibility.
---
@@ -59,8 +59,8 @@ Whether they have done enough to make the app accessible.
# --explanation--
-To find the correct answer, focus on Sophie’s concern mentioned in the paragraph.
+To find the correct answer, focus on Sophie's concern mentioned in the paragraph.
The paragraph states that Sophie wonders, `Have we done enough to make our app accessible?` This indicates her focus on overall accessibility improvements.
-Look for an option that reflects Sophie’s concern about making the app accessible for users.
+Look for an option that reflects Sophie's concern about making the app accessible for users.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671b7dd730712747aa2d9974.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671b7dd730712747aa2d9974.md
index 5cf4154e4b..06f5d01a2d 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671b7dd730712747aa2d9974.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671b7dd730712747aa2d9974.md
@@ -19,11 +19,11 @@ Read the text and answer the question below.
`Recently, they added special labels to buttons, menus, and forms, so screen readers can understand these parts better. They also improved the way headings, lists, and tables are organized, making the layouts easier for users to move through the app.`
-`Tom has been testing these improvements using popular screen readers, while Sophie has been focusing on tweaking the app’s text-to-speech function. They also increased the contrast, which helps users see different sections more clearly.`
+`Tom has been testing these improvements using popular screen readers, while Sophie has been focusing on tweaking the app's text-to-speech function. They also increased the contrast, which helps users see different sections more clearly.`
-`Sophie still wonders, “Have we done enough to make our app accessible?” They plan to conduct some surveys and add features like adjustable colors and keyboard shortcuts to make the app even more user-friendly.`
+`Sophie still wonders, "Have we done enough to make our app accessible?" They plan to conduct some surveys and add features like adjustable colors and keyboard shortcuts to make the app even more user-friendly.`
-What might be Tom and Sophie’s next step to improve accessibility?
+What might be Tom and Sophie's next step to improve accessibility?
## --answers--
@@ -39,7 +39,7 @@ Introducing features like adjustable colors and keyboard shortcuts.
---
-Increasing the app’s speed for faster navigation.
+Increasing the app's speed for faster navigation.
### --feedback--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f46b8a64a336294268cf6.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f46b8a64a336294268cf6.md
index e3a7496386..9de6d7ee88 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f46b8a64a336294268cf6.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f46b8a64a336294268cf6.md
@@ -49,4 +49,4 @@ This sentence is in the `Present Simple` tense, not the `Present Perfect continu
# --explanation--
-The negative form of the `Present Perfect continuous` tense tense is created with `hasn't/haven't + been + present participle`. It describes an ongoing action that started in the past and continues or remains relevant but hasn’t occurred as expected.
+The negative form of the `Present Perfect continuous` tense tense is created with `hasn't/haven't + been + present participle`. It describes an ongoing action that started in the past and continues or remains relevant but hasn't occurred as expected.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f4766b90543639b60a79d.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f4766b90543639b60a79d.md
index 744384c525..5559001fed 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f4766b90543639b60a79d.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f4766b90543639b60a79d.md
@@ -49,7 +49,7 @@ This is the `Present Simple` tense.
# --explanation--
-The `Present Perfect Continuous` tense negative form is formed with `hasn't/haven't + been + present participle`, indicating an ongoing action that hasn’t occurred as expected over time. For example:
+The `Present Perfect Continuous` tense negative form is formed with `hasn't/haven't + been + present participle`, indicating an ongoing action that hasn't occurred as expected over time. For example:
`He hasn't been exercising regularly.` - This means his exercise routine has been irregular.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f47b9343cd364309aa802.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f47b9343cd364309aa802.md
index 26ecc04b17..344de0e648 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f47b9343cd364309aa802.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f47b9343cd364309aa802.md
@@ -49,7 +49,7 @@ This is in the `Present Simple` tense, not related to ongoing or completed actio
# --explanation--
-`Present Perfect Continuous` tense negative form emphasizes an ongoing action that has lacked consistency over time, while the `Present Perfect` tense negative form indicates that an action hasn’t occurred at all up to now.
+`Present Perfect Continuous` tense negative form emphasizes an ongoing action that has lacked consistency over time, while the `Present Perfect` tense negative form indicates that an action hasn't occurred at all up to now.
`Past Continuous` tense negative form deals with an action that was not happening at a specific past moment, focusing solely on the past.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f4c29b6c10a677571c3e9.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f4c29b6c10a677571c3e9.md
index ea0ac038d5..ffdb548723 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f4c29b6c10a677571c3e9.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f4c29b6c10a677571c3e9.md
@@ -45,7 +45,7 @@ This word refers to the ease of use for all users, including those with disabili
`Misaligned` means not lined up or positioned correctly. For example:
-`The images were misaligned in the presentation, making it look messy.` - This indicates that the images were not positioned properly, affecting the presentation’s clarity.
+`The images were misaligned in the presentation, making it look messy.` - This indicates that the images were not positioned properly, affecting the presentation's clarity.
`Out of sync` describes when two or more elements are not coordinated in time or movement. For example:
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f8ab3f5add66eb16be177.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f8ab3f5add66eb16be177.md
index 7f3b30304c..48b8e52080 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f8ab3f5add66eb16be177.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f8ab3f5add66eb16be177.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-43
---
-
+
# --instructions--
@@ -15,7 +15,7 @@ Listen to the audio and complete the sentence below.
## --sentence--
-`BLANK. Do you know if it’s been BLANK all the videos or just a few?`
+`BLANK. Do you know if it's been BLANK all the videos or just a few?`
## --blanks--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f8cdb0d31cb710d7ad031.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f8cdb0d31cb710d7ad031.md
index da052b1c23..6b070052ad 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f8cdb0d31cb710d7ad031.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f8cdb0d31cb710d7ad031.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-44
---
-
+
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f8e2ca90546729b1911fa.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f8e2ca90546729b1911fa.md
index 0f0f0b39f0..10d176ce9f 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f8e2ca90546729b1911fa.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f8e2ca90546729b1911fa.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-45
---
-
+
# --instructions--
@@ -15,7 +15,7 @@ Listen to the audio and complete the sentence below.
## --sentence--
-`It seems to be affecting several videos. Our BLANK team has been BLANK the platform, and noticed that the captions aren’t BLANK properly.`
+`It seems to be affecting several videos. Our BLANK team has been BLANK the platform, and noticed that the captions aren't BLANK properly.`
## --blanks--
@@ -45,7 +45,7 @@ This word in `-ing` form refers to the process of making things happen at the sa
`Quality assurance` is the process of ensuring that a product meets set quality standards. For example:
-`The quality assurance team checks the software for bugs before release.` - Here, `quality assurance` emphasizes the team’s role in maintaining the product's standard.
+`The quality assurance team checks the software for bugs before release.` - Here, `quality assurance` emphasizes the team's role in maintaining the product's standard.
`Testing` means evaluating or examining a product to verify its performance. For example:
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f92684454b37660c3f82a.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f92684454b37660c3f82a.md
index 40a6056e18..6e7c1348c7 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f92684454b37660c3f82a.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f92684454b37660c3f82a.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-46
---
-
+
# --instructions--
@@ -15,7 +15,7 @@ Listen to the audio and answer the question below.
## --text--
-Why is it a problem that `the captions aren’t syncing properly`?
+Why is it a problem that `the captions aren't syncing properly`?
## --answers--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f9ca66765d781de7213f3.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f9ca66765d781de7213f3.md
index 8ad927f930..acd962ab8b 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f9ca66765d781de7213f3.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f9ca66765d781de7213f3.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-53
---
-
+
# --instructions--
@@ -15,7 +15,7 @@ Listen to the audio and complete the sentence below.
## --sentence--
-`We're working on it. The BLANK hasn't found a definitive BLANK yet, but they’re BLANK the possibilities.`
+`We're working on it. The BLANK hasn't found a definitive BLANK yet, but they're BLANK the possibilities.`
## --blanks--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f9e83b440da8486fdf76e.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f9e83b440da8486fdf76e.md
index 9d1642b436..ceccdcd2ee 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f9e83b440da8486fdf76e.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/671f9e83b440da8486fdf76e.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-54
---
-
+
# --instructions--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6720cf38beae8c4f1d7af1c0.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6720cf38beae8c4f1d7af1c0.md
index d152f48037..360190fc74 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6720cf38beae8c4f1d7af1c0.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6720cf38beae8c4f1d7af1c0.md
@@ -23,9 +23,9 @@ Place the following phrases in the correct spot: `rendering consistently`, `clos
`James: Yes. For some reason, It hasn't been BLANK for some users. The captions are misaligned and BLANK, which isn't good for accessibility.`
-`Alice: Exactly. Do you know if it’s been affecting all the videos or just a few?`
+`Alice: Exactly. Do you know if it's been affecting all the videos or just a few?`
-`James: It seems to be affecting several videos. Our quality assurance team has been testing the platform, and noticed that the captions aren’t syncing properly.`
+`James: It seems to be affecting several videos. Our quality assurance team has been testing the platform, and noticed that the captions aren't syncing properly.`
`Alice: BLANK. Have they found out why it's happening?`
@@ -33,7 +33,7 @@ Place the following phrases in the correct spot: `rendering consistently`, `clos
`Alice: Is there a plan to fix it?`
-`James: We're working on it. The development team hasn't found a BLANK yet, but they’re narrowing down the possibilities.`
+`James: We're working on it. The development team hasn't found a BLANK yet, but they're narrowing down the possibilities.`
## --blanks--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6720e69c2152da7b9dad577e.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6720e69c2152da7b9dad577e.md
index c5fc0f7f27..73c70a7178 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6720e69c2152da7b9dad577e.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6720e69c2152da7b9dad577e.md
@@ -23,9 +23,9 @@ After their conversation, James wrote an email to Alice to update her about what
`The development team has been working hard to find the cause of the issues. We think some of the problems, like captions being misaligned or out of sync, are because the synchronization code is old. We are now updating the code and testing it on different devices to make sure the captions work better everywhere.`
-`We haven’t found a final solution yet, but we are seeing some improvements. The captions are showing up better on most devices, but we still need to do more testing to make sure it works well on all of them. We also plan to add a system that will catch any new errors quickly.`
+`We haven't found a final solution yet, but we are seeing some improvements. The captions are showing up better on most devices, but we still need to do more testing to make sure it works well on all of them. We also plan to add a system that will catch any new errors quickly.`
-`I’ll keep you updated as we make more progress. If you have any questions or ideas, please let me know.`
+`I'll keep you updated as we make more progress. If you have any questions or ideas, please let me know.`
`Best,`
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6720f18957013d8de8ebbe91.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6720f18957013d8de8ebbe91.md
index e7c917a8cf..cf24dbc12f 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6720f18957013d8de8ebbe91.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6720f18957013d8de8ebbe91.md
@@ -23,9 +23,9 @@ After their conversation, James wrote an email to Alice to update her about what
`The development team has been working hard to find the cause of the issues. We think some of the problems, like captions being misaligned or out of sync, are because the synchronization code is old. We are now updating the code and testing it on different devices to make sure the captions work better everywhere.`
-`We haven’t found a final solution yet, but we are seeing some improvements. The captions are showing up better on most devices, but we still need to do more testing to make sure it works well on all of them. We also plan to add a system that will catch any new errors quickly.`
+`We haven't found a final solution yet, but we are seeing some improvements. The captions are showing up better on most devices, but we still need to do more testing to make sure it works well on all of them. We also plan to add a system that will catch any new errors quickly.`
-`I’ll keep you updated as we make more progress. If you have any questions or ideas, please let me know.`
+`I'll keep you updated as we make more progress. If you have any questions or ideas, please let me know.`
`Best,`
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6720f2d525d22693e3fe2a99.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6720f2d525d22693e3fe2a99.md
index b249884427..3f3236c4fb 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6720f2d525d22693e3fe2a99.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6720f2d525d22693e3fe2a99.md
@@ -23,9 +23,9 @@ After their conversation, James wrote an email to Alice to update her about what
`The development team has been working hard to find the cause of the issues. We think some of the problems, like captions being misaligned or out of sync, are because the synchronization code is old. We are now updating the code and testing it on different devices to make sure the captions work better everywhere.`
-`We haven’t found a final solution yet, but we are seeing some improvements. The captions are showing up better on most devices, but we still need to do more testing to make sure it works well on all of them. We also plan to add a system that will catch any new errors quickly.`
+`We haven't found a final solution yet, but we are seeing some improvements. The captions are showing up better on most devices, but we still need to do more testing to make sure it works well on all of them. We also plan to add a system that will catch any new errors quickly.`
-`I’ll keep you updated as we make more progress. If you have any questions or ideas, please let me know.`
+`I'll keep you updated as we make more progress. If you have any questions or ideas, please let me know.`
`Best,`
@@ -39,7 +39,7 @@ The problem is fully solved now.
### --feedback--
-James clearly states that they haven’t found a final solution yet, so this is incorrect.
+James clearly states that they haven't found a final solution yet, so this is incorrect.
---
@@ -67,6 +67,6 @@ James does not provide a specific timeline for when the solution will be ready.
# --explanation--
-To identify the correct answer, focus on where James says `We haven’t found a final solution yet`. This indicates that the issue is still unresolved.
+To identify the correct answer, focus on where James says `We haven't found a final solution yet`. This indicates that the issue is still unresolved.
Look for the option that emphasizes this ongoing problem, which matches James's update.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6720f45529e496998cced6b6.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6720f45529e496998cced6b6.md
index a3b01718a3..de3ecb890e 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6720f45529e496998cced6b6.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6720f45529e496998cced6b6.md
@@ -23,9 +23,9 @@ After their conversation, James wrote an email to Alice to update her about what
`The development team has been working hard to find the cause of the issues. We think some of the problems, like captions being misaligned or out of sync, are because the synchronization code is old. We are now updating the code and testing it on different devices to make sure the captions work better everywhere.`
-`We haven’t found a final solution yet, but we are seeing some improvements. The captions are showing up better on most devices, but we still need to do more testing to make sure it works well on all of them. We also plan to add a system that will catch any new errors quickly.`
+`We haven't found a final solution yet, but we are seeing some improvements. The captions are showing up better on most devices, but we still need to do more testing to make sure it works well on all of them. We also plan to add a system that will catch any new errors quickly.`
-`I’ll keep you updated as we make more progress. If you have any questions or ideas, please let me know.`
+`I'll keep you updated as we make more progress. If you have any questions or ideas, please let me know.`
`Best,`
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6720f45ff33dd69a10d14e9d.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6720f45ff33dd69a10d14e9d.md
index 087f369951..497188534b 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6720f45ff33dd69a10d14e9d.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6720f45ff33dd69a10d14e9d.md
@@ -23,9 +23,9 @@ After their conversation, James wrote an email to Alice to update her about what
`The development team has been working hard to find the cause of the issues. We think some of the problems, like captions being misaligned or out of sync, are because the synchronization code is old. We are now updating the code and testing it on different devices to make sure the captions work better everywhere.`
-`We haven’t found a final solution yet, but we are seeing some improvements. The captions are showing up better on most devices, but we still need to do more testing to make sure it works well on all of them. We also plan to add a system that will catch any new errors quickly.`
+`We haven't found a final solution yet, but we are seeing some improvements. The captions are showing up better on most devices, but we still need to do more testing to make sure it works well on all of them. We also plan to add a system that will catch any new errors quickly.`
-`I’ll keep you updated as we make more progress. If you have any questions or ideas, please let me know.`
+`I'll keep you updated as we make more progress. If you have any questions or ideas, please let me know.`
`Best,`
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672830d9aa2e0c2ff2fad7f8.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672830d9aa2e0c2ff2fad7f8.md
index df3ee2d444..0a7baa4949 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672830d9aa2e0c2ff2fad7f8.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672830d9aa2e0c2ff2fad7f8.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-63
---
-
+
# --instructions--
@@ -15,7 +15,7 @@ Listen to the audio and complete the sentence below.
## --sentence--
-`Yes, I’ve been testing them BLANK the latest BLANK.`
+`Yes, I've been testing them BLANK the latest BLANK.`
## --blanks--
@@ -37,7 +37,7 @@ These two words together refer to a version of software that has been improved o
In the `Present Perfect Continuous` tense, `since` is used to indicate when an action began and continues up to the present. For example:
-`I’ve been learning JavaScript since 2020.` - It shows that the action of learning JavaScript started in 2020 and is still ongoing.
+`I've been learning JavaScript since 2020.` - It shows that the action of learning JavaScript started in 2020 and is still ongoing.
The term `software update` refers to changes or improvements made to a computer program. For example:
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672836d6ec0ae23f4724ccb1.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672836d6ec0ae23f4724ccb1.md
index 5f0d668502..f22293a790 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672836d6ec0ae23f4724ccb1.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672836d6ec0ae23f4724ccb1.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-65
---
-
+
# --instructions--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6728378c94eaf541fce8f334.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6728378c94eaf541fce8f334.md
index a74766adea..7b84b48b65 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6728378c94eaf541fce8f334.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6728378c94eaf541fce8f334.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-66
---
-
+
# --instructions--
@@ -15,7 +15,7 @@ Listen to the audio and complete the sentence below.
## --sentence--
-`We’ve had some positive BLANK, but there are still a few BLANK to fix.`
+`We've had some positive BLANK, but there are still a few BLANK to fix.`
## --blanks--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/67289c4908f407948ef08a55.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/67289c4908f407948ef08a55.md
index f1596b7905..5fbd193766 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/67289c4908f407948ef08a55.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/67289c4908f407948ef08a55.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-67
---
-
+
# --instructions--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6728c369d38d3ea6634c1649.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6728c369d38d3ea6634c1649.md
index 2b2a78fb9d..fbf68a2a1b 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6728c369d38d3ea6634c1649.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6728c369d38d3ea6634c1649.md
@@ -5,7 +5,7 @@ challengeType: 22
dashedName: task-73
---
-
+
# --instructions--
@@ -15,7 +15,7 @@ Listen to the audio and complete the sentence below.
## --sentence--
-`I’ve been trying to cover all BLANK to ensure that the commands work BLANK.`
+`I've been trying to cover all BLANK to ensure that the commands work BLANK.`
## --blanks--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6728c6fad8d9caa92837c75f.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6728c6fad8d9caa92837c75f.md
index 2569cfd6c4..06fb50f651 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6728c6fad8d9caa92837c75f.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/6728c6fad8d9caa92837c75f.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-74
---
-
+
# --instructions--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672a1c6ca33f8115728e7f79.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672a1c6ca33f8115728e7f79.md
index dffe5ee639..f4f868b4c5 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672a1c6ca33f8115728e7f79.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672a1c6ca33f8115728e7f79.md
@@ -35,7 +35,7 @@ If the device has been working properly.
### --feedback--
-Bob is asking about potential issues related to voice recognition, not the device’s general performance.
+Bob is asking about potential issues related to voice recognition, not the device's general performance.
---
@@ -43,7 +43,7 @@ If there is a new update for the voice recognition system.
### --feedback--
-Bob’s question is about problems with voice recognition, not about updates.
+Bob's question is about problems with voice recognition, not about updates.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672a1e2fbec6a61bf477ea49.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672a1e2fbec6a61bf477ea49.md
index b44474d7a4..296031dfbc 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672a1e2fbec6a61bf477ea49.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672a1e2fbec6a61bf477ea49.md
@@ -49,7 +49,7 @@ It refers to how correct or precise something is. In this case, it means how wel
`Background noise` refers to unwanted sounds that can interfere with hearing something clearly. For example:
-- `The microphone couldn’t pick up my voice because of the background noise.` - In this sentence, `background noise` refers to sounds like music or traffic that made it difficult for the microphone to hear your voice clearly.
+- `The microphone couldn't pick up my voice because of the background noise.` - In this sentence, `background noise` refers to sounds like music or traffic that made it difficult for the microphone to hear your voice clearly.
`Accuracy` refers to how precise or correct something is. In the case of `voice recognition`, it means how well the system can understand and process speech without errors. For example:
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672a21a4b40ed3279d513888.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672a21a4b40ed3279d513888.md
index f11795aa42..56256fc40d 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672a21a4b40ed3279d513888.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672a21a4b40ed3279d513888.md
@@ -15,11 +15,11 @@ Listen to the audio and answer the question below.
## --text--
-What might Linda be suggesting about the system’s current performance?
+What might Linda be suggesting about the system's current performance?
## --answers--
-It’s working perfectly fine with all accents and environments.
+It's working perfectly fine with all accents and environments.
### --feedback--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672a296a309d9c46658c071a.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672a296a309d9c46658c071a.md
index 185680dce4..bb942c50b3 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672a296a309d9c46658c071a.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672a296a309d9c46658c071a.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-85
---
-
+
# --instructions--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672afc3d3758e25087697611.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672afc3d3758e25087697611.md
index 735a533bbd..9037da2d74 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672afc3d3758e25087697611.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672afc3d3758e25087697611.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-86
---
-
+
# --instructions--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672afe3809d2a55224868ea5.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672afe3809d2a55224868ea5.md
index 1aa169cd61..022ed5a333 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672afe3809d2a55224868ea5.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672afe3809d2a55224868ea5.md
@@ -31,7 +31,7 @@ He thinks the project is fully complete and ready for launch.
### --feedback--
-Bob’s question about testing with real users suggests he sees the project as ongoing, not fully complete.
+Bob's question about testing with real users suggests he sees the project as ongoing, not fully complete.
---
@@ -39,7 +39,7 @@ He believes the team needs to stop working and start a new project.
### --feedback--
-Bob’s comment suggests he thinks the project is progressing well, not that it should be stopped.
+Bob's comment suggests he thinks the project is progressing well, not that it should be stopped.
---
@@ -51,7 +51,7 @@ He thinks the project has made good initial progress but needs further testing.
# --explanation--
-Bob’s comment `That's a good start` shows that he is pleased with the progress so far. However, his follow-up question about testing with real users suggests he thinks more steps are needed before the project is complete. This indicates that he feels positive about the current status but sees the need for further validation and testing.
+Bob's comment `That's a good start` shows that he is pleased with the progress so far. However, his follow-up question about testing with real users suggests he thinks more steps are needed before the project is complete. This indicates that he feels positive about the current status but sees the need for further validation and testing.
# --scene--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672b25e2a59e2956bca1a42f.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672b25e2a59e2956bca1a42f.md
index 3a80dbb2aa..b9563c5a31 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672b25e2a59e2956bca1a42f.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672b25e2a59e2956bca1a42f.md
@@ -19,7 +19,7 @@ What does Linda mean when she says `it would be helpful`?
## --answers--
-She thinks they don’t need any more feedback.
+She thinks they don't need any more feedback.
### --feedback--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672b33b15bd8bf5b2523772a.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672b33b15bd8bf5b2523772a.md
index c9dc79ade1..76d437ea80 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672b33b15bd8bf5b2523772a.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672b33b15bd8bf5b2523772a.md
@@ -21,11 +21,11 @@ Place the following phrases in the correct spot: `software update`, `real-world
`Bob: Hi Linda, have you been working on the new BLANK features?`
-`Linda: Yes, I’ve been testing them since the latest BLANK. We’ve had some positive feedback, but there are still a few bugs to fix.`
+`Linda: Yes, I've been testing them since the latest BLANK. We've had some positive feedback, but there are still a few bugs to fix.`
`Bob: How long have you been focusing on this evaluation?`
-`Linda: For the past couple of weeks. I’ve been trying to cover BLANK to ensure that the commands work consistently.`
+`Linda: For the past couple of weeks. I've been trying to cover BLANK to ensure that the commands work consistently.`
`Bob: Have you had any problems with voice recognition?`
@@ -33,7 +33,7 @@ Place the following phrases in the correct spot: `software update`, `real-world
`Bob: What about the integration with other systems? Has it been seamless?`
-`Linda: Not entirely. It’s had issues connecting with our older devices, but we’re working on it. The development team has been BLANK.`
+`Linda: Not entirely. It's had issues connecting with our older devices, but we're working on it. The development team has been BLANK.`
`Bob: That's a good start. By the way, have we tested it with real users yet?`
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672b42dafa37fe61e80a2b40.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672b42dafa37fe61e80a2b40.md
index 80a8345a7e..4d3d70ef1f 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672b42dafa37fe61e80a2b40.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672b42dafa37fe61e80a2b40.md
@@ -19,7 +19,7 @@ Read the text and answer the question below.
`One challenge is making sure the system understands different accents. The team has been testing the system with users from different regions, but there are still some problems with background noise.`
-`For example, the system sometimes has trouble understanding voices in noisy rooms, like kitchens or living rooms with TVs or radios on. To fix this, they are improving the system’s ability to filter out noise and better recognize commands.`
+`For example, the system sometimes has trouble understanding voices in noisy rooms, like kitchens or living rooms with TVs or radios on. To fix this, they are improving the system's ability to filter out noise and better recognize commands.`
`Before launching the system, the team plans to gather real-world feedback from users to see how well it works in different home settings. This feedback will help them make the system more accurate and ready for everyone to use.`
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672b4539b9ab5d645e7dcfb8.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672b4539b9ab5d645e7dcfb8.md
index e2b6f3806d..ed9f6b6d5f 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672b4539b9ab5d645e7dcfb8.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672b4539b9ab5d645e7dcfb8.md
@@ -19,7 +19,7 @@ Read the text and answer the question below.
`One challenge is making sure the system understands different accents. The team has been testing the system with users from different regions, but there are still some problems with background noise.`
-`For example, the system sometimes has trouble understanding voices in noisy rooms, like kitchens or living rooms with TVs or radios on. To fix this, they are improving the system’s ability to filter out noise and better recognize commands.`
+`For example, the system sometimes has trouble understanding voices in noisy rooms, like kitchens or living rooms with TVs or radios on. To fix this, they are improving the system's ability to filter out noise and better recognize commands.`
`Before launching the system, the team plans to gather real-world feedback from users to see how well it works in different home settings. This feedback will help them make the system more accurate and ready for everyone to use.`
@@ -51,7 +51,7 @@ Reducing the size of the devices.
### --feedback--
-The paragraph doesn’t mention device size as a challenge.
+The paragraph doesn't mention device size as a challenge.
## --video-solution--
@@ -63,4 +63,4 @@ To find the correct answer, focus on the part where Linda explains the challenge
The paragraph highlights that the team is facing difficulties with background noise and accents, which makes it challenging for the system to accurately recognize commands in noisy environments.
-Look for an option that addresses the issue of the system’s ability to handle accents and background noise.
+Look for an option that addresses the issue of the system's ability to handle accents and background noise.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672b46def9325065dbc7b29f.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672b46def9325065dbc7b29f.md
index 460e6901fe..1fc9ab4b7d 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672b46def9325065dbc7b29f.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672b46def9325065dbc7b29f.md
@@ -19,7 +19,7 @@ Read the text and answer the question below.
`One challenge is making sure the system understands different accents. The team has been testing the system with users from different regions, but there are still some problems with background noise.`
-`For example, the system sometimes has trouble understanding voices in noisy rooms, like kitchens or living rooms with TVs or radios on. To fix this, they are improving the system’s ability to filter out noise and better recognize commands.`
+`For example, the system sometimes has trouble understanding voices in noisy rooms, like kitchens or living rooms with TVs or radios on. To fix this, they are improving the system's ability to filter out noise and better recognize commands.`
`Before launching the system, the team plans to gather real-world feedback from users to see how well it works in different home settings. This feedback will help them make the system more accurate and ready for everyone to use.`
@@ -35,7 +35,7 @@ Real-world feedback is meant to test the system in real home settings, not just
---
-To improve the system’s visual design.
+To improve the system's visual design.
### --feedback--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672b4812ec997567058875da.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672b4812ec997567058875da.md
index a76e226cc2..d508281756 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672b4812ec997567058875da.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672b4812ec997567058875da.md
@@ -19,7 +19,7 @@ Read the text and answer the question below.
`One challenge is making sure the system understands different accents. The team has been testing the system with users from different regions, but there are still some problems with background noise.`
-`For example, the system sometimes has trouble understanding voices in noisy rooms, like kitchens or living rooms with TVs or radios on. To fix this, they are improving the system’s ability to filter out noise and better recognize commands.`
+`For example, the system sometimes has trouble understanding voices in noisy rooms, like kitchens or living rooms with TVs or radios on. To fix this, they are improving the system's ability to filter out noise and better recognize commands.`
`Before launching the system, the team plans to gather real-world feedback from users to see how well it works in different home settings. This feedback will help them make the system more accurate and ready for everyone to use.`
@@ -63,4 +63,4 @@ To find the correct answer, look at the part where Linda talks about what the te
The paragraph mentions that the development team `has been brainstorming solutions` to fix the issues with voice recognition, which shows they are actively working on improving the system.
-Look for an option that describes the team’s approach to solving the problems they’ve encountered.
+Look for an option that describes the team's approach to solving the problems they've encountered.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672b491aa3c094689007baf1.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672b491aa3c094689007baf1.md
index 29990a49c3..a4434c1f20 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672b491aa3c094689007baf1.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672b491aa3c094689007baf1.md
@@ -19,7 +19,7 @@ Read the text and answer the question below.
`One challenge is making sure the system understands different accents. The team has been testing the system with users from different regions, but there are still some problems with background noise.`
-`For example, the system sometimes has trouble understanding voices in noisy rooms, like kitchens or living rooms with TVs or radios on. To fix this, they are improving the system’s ability to filter out noise and better recognize commands.`
+`For example, the system sometimes has trouble understanding voices in noisy rooms, like kitchens or living rooms with TVs or radios on. To fix this, they are improving the system's ability to filter out noise and better recognize commands.`
`Before launching the system, the team plans to gather real-world feedback from users to see how well it works in different home settings. This feedback will help them make the system more accurate and ready for everyone to use.`
@@ -31,7 +31,7 @@ They will immediately launch the system to all users.
### --feedback--
-The team is still testing and improving the system before it’s ready for a wider launch.
+The team is still testing and improving the system before it's ready for a wider launch.
---
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672cca3d15975a9390545877.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672cca3d15975a9390545877.md
index a9bed39e2e..0a3f411bb2 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672cca3d15975a9390545877.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672cca3d15975a9390545877.md
@@ -51,7 +51,7 @@ Anna's question does not ask if James needs help; it focuses on whether he has r
# --explanation--
-Anna’s question is specifically about whether James has reviewed the feedback from a training program related to accessibility.
+Anna's question is specifically about whether James has reviewed the feedback from a training program related to accessibility.
# --scene--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672ccc988693199500b4cdfd.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672ccc988693199500b4cdfd.md
index 543215b20a..898a7ef018 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672ccc988693199500b4cdfd.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672ccc988693199500b4cdfd.md
@@ -5,7 +5,7 @@ challengeType: 19
dashedName: task-100
---
-
+
# --instructions--
@@ -35,7 +35,7 @@ By saying he finished working soon after the last session.
### --feedback--
-James’s statement indicates ongoing work, not that he finished shortly after starting.
+James's statement indicates ongoing work, not that he finished shortly after starting.
---
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672dc928d8765dc9f923ca71.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672dc928d8765dc9f923ca71.md
index 03a703b361..697028dae5 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672dc928d8765dc9f923ca71.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672dc928d8765dc9f923ca71.md
@@ -51,7 +51,7 @@ A `gradual process` refers to something that develops slowly, over time, rather
`The team has made steady progress in completing the project.` - This shows that the team is moving forward regularly and effectively, without major delays.
-`Understanding` refers to a person’s knowledge or awareness about a subject. For example:
+`Understanding` refers to a person's knowledge or awareness about a subject. For example:
`Her understanding of coding improved with practice.` - It highlights how her knowledge of coding grew as she spent more time practicing.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672de8ad97d683d3734ce5cd.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672de8ad97d683d3734ce5cd.md
index da035c1e18..3a6974aa37 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672de8ad97d683d3734ce5cd.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672de8ad97d683d3734ce5cd.md
@@ -23,7 +23,7 @@ He is frustrated that progress has been slow.
### --feedback--
-James doesn’t express frustration; he acknowledges the gradual nature of the process positively.
+James doesn't express frustration; he acknowledges the gradual nature of the process positively.
---
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672debc75e32a8d6e2593eac.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672debc75e32a8d6e2593eac.md
index 23aad93fe0..aa98f21456 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672debc75e32a8d6e2593eac.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672debc75e32a8d6e2593eac.md
@@ -31,7 +31,7 @@ If there are too many tasks for the team to finish.
### --feedback--
-Anna’s question is about performance in some areas, not the number of tasks.
+Anna's question is about performance in some areas, not the number of tasks.
---
@@ -43,7 +43,7 @@ If people need more tools to do their work better.
### --feedback--
-Anna’s question is about finding areas of lower performance, not about needing more tools.
+Anna's question is about finding areas of lower performance, not about needing more tools.
## --video-solution--
@@ -51,7 +51,7 @@ Anna’s question is about finding areas of lower performance, not about needing
# --explanation--
-Anna’s question is asking if there are any parts of the work where the team isn’t doing as well as they were expected to.
+Anna's question is asking if there are any parts of the work where the team isn't doing as well as they were expected to.
# --scene--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672dec93f008b3d8169568e8.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672dec93f008b3d8169568e8.md
index c4d0440860..37c72c9652 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672dec93f008b3d8169568e8.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672dec93f008b3d8169568e8.md
@@ -37,7 +37,7 @@ This answer points out areas needing improvement, which is not a positive respon
# --explanation--
-A positive answer to Anna’s question would mean that everyone is performing as well as expected, and there is nothing that needs to be improved.
+A positive answer to Anna's question would mean that everyone is performing as well as expected, and there is nothing that needs to be improved.
# --scene--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672e0ec28d829ee2b5e909f3.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672e0ec28d829ee2b5e909f3.md
index 193270d3b9..b17c08fc07 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672e0ec28d829ee2b5e909f3.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672e0ec28d829ee2b5e909f3.md
@@ -35,7 +35,7 @@ He believes the activities were well-received by all participants.
### --feedback--
-James points out that the activities were not fully relevant, meaning they weren’t well-received by everyone.
+James points out that the activities were not fully relevant, meaning they weren't well-received by everyone.
---
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672e16bcc0d877e5d3eb7f4e.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672e16bcc0d877e5d3eb7f4e.md
index 8efae5669b..967a25b5a3 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672e16bcc0d877e5d3eb7f4e.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672e16bcc0d877e5d3eb7f4e.md
@@ -23,7 +23,7 @@ Listen to the audio and complete the sentence below.
### --feedback--
-This word describes something that catches people’s interest and keeps them involved.
+This word describes something that catches people's interest and keeps them involved.
# --explanation--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672e17e63be5dce6ff5b9189.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672e17e63be5dce6ff5b9189.md
index cb2c465ff4..869168958e 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672e17e63be5dce6ff5b9189.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672e17e63be5dce6ff5b9189.md
@@ -43,7 +43,7 @@ If the activities already meet all the learning goals.
### --feedback--
-Anna’s question suggests she thinks the activities could be improved to be `more engaging`, so she isn’t assuming they already meet all goals.
+Anna's question suggests she thinks the activities could be improved to be `more engaging`, so she isn't assuming they already meet all goals.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672e1bb0774f2fea953e9388.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672e1bb0774f2fea953e9388.md
index 92eaa09863..c2e6eb6334 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672e1bb0774f2fea953e9388.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672e1bb0774f2fea953e9388.md
@@ -31,7 +31,7 @@ The team has been brainstorming ideas to make the sessions better.
---
-The team hasn’t yet considered any changes to the sessions.
+The team hasn't yet considered any changes to the sessions.
### --feedback--
@@ -43,7 +43,7 @@ The team feels the sessions are as interactive as they need to be.
### --feedback--
-James says they are working on making the sessions more interactive, so they don’t feel the sessions are finished.
+James says they are working on making the sessions more interactive, so they don't feel the sessions are finished.
## --video-solution--
@@ -51,7 +51,7 @@ James says they are working on making the sessions more interactive, so they don
# --explanation--
-James uses the `Present Perfect Continuous` tense (`has been brainstorming`) to show that the team’s work on improving the sessions is ongoing. This tense expresses that they started brainstorming in the past and are still actively doing it now, indicating continuous effort in finding new ideas.
+James uses the `Present Perfect Continuous` tense (`has been brainstorming`) to show that the team's work on improving the sessions is ongoing. This tense expresses that they started brainstorming in the past and are still actively doing it now, indicating continuous effort in finding new ideas.
# --scene--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672e1c3031816ceb9dccc66a.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672e1c3031816ceb9dccc66a.md
index 7ea12c2170..dd3bc37842 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672e1c3031816ceb9dccc66a.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672e1c3031816ceb9dccc66a.md
@@ -23,7 +23,7 @@ Add activities that focus on memorizing definitions.
### --feedback--
-Memorizing definitions doesn’t involve real-life application or hands-on practice, which James implies they are aiming for.
+Memorizing definitions doesn't involve real-life application or hands-on practice, which James implies they are aiming for.
---
@@ -31,7 +31,7 @@ Use theoretical case studies with no practical application.
### --feedback--
-Theoretical case studies alone don’t fully connect to real-life tasks, which James wants to include.
+Theoretical case studies alone don't fully connect to real-life tasks, which James wants to include.
---
@@ -39,7 +39,7 @@ Have participants discuss unrelated topics to build general communication skills
### --feedback--
-Unrelated discussions don’t meet the goal of incorporating relevant, real-life situations.
+Unrelated discussions don't meet the goal of incorporating relevant, real-life situations.
---
@@ -51,7 +51,7 @@ Create exercises that use realistic situations participants might encounter on t
# --explanation--
-Since James mentions `incorporating more real-life scenarios`, they’re likely planning to add exercises that reflect situations participants could actually encounter in their roles. This makes the training more engaging and relevant, unlike focusing on definitions, unrelated discussions, or purely theoretical case studies.
+Since James mentions `incorporating more real-life scenarios`, they're likely planning to add exercises that reflect situations participants could actually encounter in their roles. This makes the training more engaging and relevant, unlike focusing on definitions, unrelated discussions, or purely theoretical case studies.
# --scene--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672e1f1a51e86aed84df7c94.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672e1f1a51e86aed84df7c94.md
index 4bfc37f41a..c4b501f916 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672e1f1a51e86aed84df7c94.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672e1f1a51e86aed84df7c94.md
@@ -37,7 +37,7 @@ This word in the plural form refers to specific targets or objectives the team i
`Keep in touch` means to stay in regular communication with someone. For example:
-`Let’s keep in touch about the project updates.` - This means staying connected and sharing information to make sure everyone is updated on the project's progress.
+`Let's keep in touch about the project updates.` - This means staying connected and sharing information to make sure everyone is updated on the project's progress.
`Goals` are the specific targets or objectives a person or team wants to achieve. It the plural form of `goal`. For example:
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672e1fff03af3aeed5d7a84b.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672e1fff03af3aeed5d7a84b.md
index e70fc4691f..e9011fe5a5 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672e1fff03af3aeed5d7a84b.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672e1fff03af3aeed5d7a84b.md
@@ -31,7 +31,7 @@ She thinks James' ideas are confusing and suggests focusing only on accessibilit
### --feedback--
-Anna doesn’t find James’ ideas confusing; she agrees and wants to monitor progress on their shared goals.
+Anna doesn't find James' ideas confusing; she agrees and wants to monitor progress on their shared goals.
---
@@ -43,7 +43,7 @@ She thinks James' ideas are unnecessary and suggests stopping the project.
### --feedback--
-Anna doesn’t suggest stopping; she supports James’ ideas and wants to stay updated.
+Anna doesn't suggest stopping; she supports James' ideas and wants to stay updated.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672f4b05585d501f533789b4.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672f4b05585d501f533789b4.md
index 2108b8fc77..73665c2d1e 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672f4b05585d501f533789b4.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672f4b05585d501f533789b4.md
@@ -21,7 +21,7 @@ Place the following phrases in the correct spot: `gradual process` , `more engag
`Anna: Hi James, have you been reviewing the BLANK for our accessibility program?`
-`James: Yes, I’ve been working on it since the last training session. We've received a lot of positive comments, but there are some areas we still need to improve.`
+`James: Yes, I've been working on it since the last training session. We've received a lot of positive comments, but there are some areas we still need to improve.`
`Anna: That's great to hear. How long have we been running these sessions?`
@@ -43,7 +43,7 @@ Place the following phrases in the correct spot: `gradual process` , `more engag
### --feedback--
-This phrase refers to the feedback received from participants about the training sessions to see what worked well and what didn’t.
+This phrase refers to the feedback received from participants about the training sessions to see what worked well and what didn't.
---
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672f606201263928a06b2a04.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672f606201263928a06b2a04.md
index 4cf8d46470..18cf9abf59 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672f606201263928a06b2a04.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672f606201263928a06b2a04.md
@@ -19,7 +19,7 @@ Read the text and answer the question below.
`The training will start by conducting an overview of essential accessibility concepts, such as color contrast, screen reader compatibility, and keyboard navigation. To make the sessions engaging, the plan includes interactive activities and real-life scenarios — like navigating without a mouse or relying on a screen reader. These exercises are designed to show the importance of removing accessibility barriers.`
-`Throughout the training, they will gather feedback to understand what’s effective and find areas to improve. This approach will help the team develop practical skills and make accessibility a natural part of their work.`
+`Throughout the training, they will gather feedback to understand what's effective and find areas to improve. This approach will help the team develop practical skills and make accessibility a natural part of their work.`
What is the main goal of the accessibility training?
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672f630337512b2b62595731.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672f630337512b2b62595731.md
index ee74b5a8bd..6c2adca538 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672f630337512b2b62595731.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672f630337512b2b62595731.md
@@ -19,7 +19,7 @@ Read the text and answer the question below.
`The training will start by conducting an overview of essential accessibility concepts, such as color contrast, screen reader compatibility, and keyboard navigation. To make the sessions engaging, the plan includes interactive activities and real-life scenarios — like navigating without a mouse or relying on a screen reader. These exercises are designed to show the importance of removing accessibility barriers.`
-`Throughout the training, they will gather feedback to understand what’s effective and find areas to improve. This approach will help the team develop practical skills and make accessibility a natural part of their work.`
+`Throughout the training, they will gather feedback to understand what's effective and find areas to improve. This approach will help the team develop practical skills and make accessibility a natural part of their work.`
What does the training overview include?
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672f63cadac41a2c9b1897a1.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672f63cadac41a2c9b1897a1.md
index 3062ed0bf5..3950a4b2fa 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672f63cadac41a2c9b1897a1.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672f63cadac41a2c9b1897a1.md
@@ -19,7 +19,7 @@ Read the text and answer the question below.
`The training will start by conducting an overview of essential accessibility concepts, such as color contrast, screen reader compatibility, and keyboard navigation. To make the sessions engaging, the plan includes interactive activities and real-life scenarios — like navigating without a mouse or relying on a screen reader. These exercises are designed to show the importance of removing accessibility barriers.`
-`Throughout the training, they will gather feedback to understand what’s effective and find areas to improve. This approach will help the team develop practical skills and make accessibility a natural part of their work.`
+`Throughout the training, they will gather feedback to understand what's effective and find areas to improve. This approach will help the team develop practical skills and make accessibility a natural part of their work.`
How does the training plan make the sessions engaging?
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672f64ba4f91492e1192b829.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672f64ba4f91492e1192b829.md
index f2680e76b8..253577b975 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672f64ba4f91492e1192b829.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672f64ba4f91492e1192b829.md
@@ -19,7 +19,7 @@ Read the text and answer the question below.
`The training will start by conducting an overview of essential accessibility concepts, such as color contrast, screen reader compatibility, and keyboard navigation. To make the sessions engaging, the plan includes interactive activities and real-life scenarios — like navigating without a mouse or relying on a screen reader. These exercises are designed to show the importance of removing accessibility barriers.`
-`Throughout the training, they will gather feedback to understand what’s effective and find areas to improve. This approach will help the team develop practical skills and make accessibility a natural part of their work.`
+`Throughout the training, they will gather feedback to understand what's effective and find areas to improve. This approach will help the team develop practical skills and make accessibility a natural part of their work.`
Why are real-life scenarios included in the training?
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672f657580a34f2f78e278e2.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672f657580a34f2f78e278e2.md
index 2225eacac2..b7158fa6f1 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672f657580a34f2f78e278e2.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/672f657580a34f2f78e278e2.md
@@ -19,7 +19,7 @@ Read the text and answer the question below.
`The training will start by conducting an overview of essential accessibility concepts, such as color contrast, screen reader compatibility, and keyboard navigation. To make the sessions engaging, the plan includes interactive activities and real-life scenarios — like navigating without a mouse or relying on a screen reader. These exercises are designed to show the importance of removing accessibility barriers.`
-`Throughout the training, they will gather feedback to understand what’s effective and find areas to improve. This approach will help the team develop practical skills and make accessibility a natural part of their work.`
+`Throughout the training, they will gather feedback to understand what's effective and find areas to improve. This approach will help the team develop practical skills and make accessibility a natural part of their work.`
What is the purpose of gathering training feedback?
@@ -29,11 +29,11 @@ To decide if the training should be canceled.
### --feedback--
-The feedback is collected to understand what’s effective and find areas to improve, not to cancel the training.
+The feedback is collected to understand what's effective and find areas to improve, not to cancel the training.
---
-To identify areas to improve and understand what’s effective.
+To identify areas to improve and understand what's effective.
---
@@ -49,7 +49,7 @@ To see how quickly participants finish the activities.
### --feedback--
-The purpose of feedback is to assess the training’s effectiveness, not activity speed.
+The purpose of feedback is to assess the training's effectiveness, not activity speed.
## --video-solution--
@@ -59,6 +59,6 @@ The purpose of feedback is to assess the training’s effectiveness, not activit
To find the correct answer, focus on why training feedback is gathered.
-The paragraph states that feedback helps identify `what’s effective` and points out `areas to improve`.
+The paragraph states that feedback helps identify `what's effective` and points out `areas to improve`.
Look for the option that describes feedback as a way to assess and enhance the training process.
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/673de712f2dc6db0cfe76b31.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/673de712f2dc6db0cfe76b31.md
index 2a1c2f9402..094d7451d8 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/673de712f2dc6db0cfe76b31.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/673de712f2dc6db0cfe76b31.md
@@ -29,7 +29,7 @@ This word means completely or fully.
The word `entirely` means completely or fully. The phrase `not entirely` indicates that something is not complete or perfect. For example:
-`I don’t entirely agree with his opinion.` - It means you don’t fully agree with the opinion, suggesting some level of disagreement.
+`I don't entirely agree with his opinion.` - It means you don't fully agree with the opinion, suggesting some level of disagreement.
# --scene--
diff --git a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/673df0c78bdd11c7195010cb.md b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/673df0c78bdd11c7195010cb.md
index cb5d3ffedb..a453e1737c 100644
--- a/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/673df0c78bdd11c7195010cb.md
+++ b/curriculum/challenges/ukrainian/24-b1-english-for-developers/learn-present-perfect-while-talking-about-accessibility/673df0c78bdd11c7195010cb.md
@@ -15,7 +15,7 @@ This task doesn't have audio. Read the question below and select the correct ans
## --text--
-A colleague asks if your team has implemented the new feature yet. What is the best way to respond if you haven’t started but plan to?
+A colleague asks if your team has implemented the new feature yet. What is the best way to respond if you haven't started but plan to?
## --answers--
@@ -23,11 +23,11 @@ A colleague asks if your team has implemented the new feature yet. What is the b
---
-`Yes, it’s been running perfectly for years.`
+`Yes, it's been running perfectly for years.`
### --feedback--
-It implies that the feature has been implemented and in use for years, which contradicts the fact that the feature is new and hasn’t been started yet.
+It implies that the feature has been implemented and in use for years, which contradicts the fact that the feature is new and hasn't been started yet.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-availability-table/66b36358ed4f261d64840c24.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-availability-table/66b36358ed4f261d64840c24.md
index eceb6701b7..14e989d822 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-availability-table/66b36358ed4f261d64840c24.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-availability-table/66b36358ed4f261d64840c24.md
@@ -1,7 +1,7 @@
---
id: 66b36358ed4f261d64840c24
title: Створіть таблицю з вільними годинами
-challengeType: 14
+challengeType: 25
dashedName: build-an-availability-table
demoType: onClick
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-bank-account-manager/6718d2d59337c822ecb697ff.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-bank-account-manager/6718d2d59337c822ecb697ff.md
index f6d5ba4f32..3d3d9b956d 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-bank-account-manager/6718d2d59337c822ecb697ff.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-bank-account-manager/6718d2d59337c822ecb697ff.md
@@ -1,7 +1,7 @@
---
id: 6718d2d59337c822ecb697ff
title: Build a Bank Account Management Program
-challengeType: 14
+challengeType: 25
dashedName: build-a-bank-account-management-program
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-blog-post-card/66eaddd04a9e533fba689001.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-blog-post-card/66eaddd04a9e533fba689001.md
index 37ab60c03e..050e99030b 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-blog-post-card/66eaddd04a9e533fba689001.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-blog-post-card/66eaddd04a9e533fba689001.md
@@ -1,7 +1,7 @@
---
id: 66eaddd04a9e533fba689001
title: Design a Blog Post Card
-challengeType: 14
+challengeType: 25
dashedName: lab-blog-post-card
demoType: onClick
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-book-catalog-table/66ec4c8e9878d8441956516f.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-book-catalog-table/66ec4c8e9878d8441956516f.md
index 8e31bb0c5b..384fc492ca 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-book-catalog-table/66ec4c8e9878d8441956516f.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-book-catalog-table/66ec4c8e9878d8441956516f.md
@@ -1,7 +1,7 @@
---
id: 66ec4c8e9878d8441956516f
title: Build a Book Catalog Table
-challengeType: 14
+challengeType: 25
dashedName: build-a-book-catalog-table
demoType: onClick
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-book-inventory-app/66a207974c806a19d6607073.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-book-inventory-app/66a207974c806a19d6607073.md
index 4cd0a7d033..18db96bdde 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-book-inventory-app/66a207974c806a19d6607073.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-book-inventory-app/66a207974c806a19d6607073.md
@@ -1,7 +1,7 @@
---
id: 66a207974c806a19d6607073
title: Build a Book Inventory App
-challengeType: 14
+challengeType: 25
dashedName: build-a-book-inventory-app
demoType: onClick
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-book-organizer/67172b43f84bcd2dec238a3d.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-book-organizer/67172b43f84bcd2dec238a3d.md
index 8d760e3d55..12c07199ca 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-book-organizer/67172b43f84bcd2dec238a3d.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-book-organizer/67172b43f84bcd2dec238a3d.md
@@ -1,7 +1,7 @@
---
id: 67172b43f84bcd2dec238a3d
title: Build a Book Organizer
-challengeType: 14
+challengeType: 25
dashedName: build-a-book-organizer
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-bookmark-manager-app/66def5467aee701733aaf8cc.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-bookmark-manager-app/66def5467aee701733aaf8cc.md
index 78898b3027..06b800d5c4 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-bookmark-manager-app/66def5467aee701733aaf8cc.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-bookmark-manager-app/66def5467aee701733aaf8cc.md
@@ -1,7 +1,7 @@
---
id: 66def5467aee701733aaf8cc
title: Побудуйте програму диспетчера закладок
-challengeType: 14
+challengeType: 25
dashedName: build-a-bookmark-manager-app
demoType: onClick
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-business-card/6690e10ebe2181212abc9652.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-business-card/6690e10ebe2181212abc9652.md
index ba88ad22e9..2a26add886 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-business-card/6690e10ebe2181212abc9652.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-business-card/6690e10ebe2181212abc9652.md
@@ -1,7 +1,7 @@
---
id: 6690e10ebe2181212abc9652
title: Design a Business Card
-challengeType: 14
+challengeType: 25
dashedName: design-a-business-card
demoType: onClick
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-checkout-page/66da326c02141df538f29ba5.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-checkout-page/66da326c02141df538f29ba5.md
index b35b61cf8a..06941418a6 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-checkout-page/66da326c02141df538f29ba5.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-checkout-page/66da326c02141df538f29ba5.md
@@ -1,7 +1,7 @@
---
id: 66da326c02141df538f29ba5
title: Створіть платіжну сторінку
-challengeType: 14
+challengeType: 25
dashedName: build-a-checkout-page
demoType: onClick
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-colored-boxes/66f3f6eb66ea9dc41cdc30df.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-colored-boxes/66f3f6eb66ea9dc41cdc30df.md
new file mode 100644
index 0000000000..86adcee2dc
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-colored-boxes/66f3f6eb66ea9dc41cdc30df.md
@@ -0,0 +1,210 @@
+---
+id: 66f3f6eb66ea9dc41cdc30df
+title: Design a Set of Colored Boxes
+challengeType: 25
+dashedName: set-of-colored-boxes
+demoType: onClick
+---
+
+# --description--
+
+In this lab, you'll practice using CSS colors by designing boxes.
+
+**Objective:** Fulfill the user stories below and get all the tests to pass to complete the lab.
+
+**User Stories:**
+
+1. You should set the background color for `body` to `#f4f4f4`.
+2. You should have a `div` with a class of `color-grid` to hold all your color elements.
+3. You should have five `div` elements within the `.color-grid` element.
+4. The five `div` elements should each have a class of `color-box` and `color#`, where `#` is the number of the order of that `div`. For example: `color1` for the first `div`, `color2` for the second, and so on.
+5. The `.color-box` class should have a set `width` and `height` so your `div` elements are visible on the page.
+6. The `.color1` element should have a `background-color` that uses hexadecimal color value.
+7. The `.color2` element should have a `background-color` that uses an RGB color value.
+8. The `.color3` element should have a `background-color` that uses a predefined (word) color value.
+9. The `.color4` element should have a `background-color` that uses a HSL color value.
+10. The `.color5` element should have a `background-color` set.
+
+**Note:** Be sure to link your stylesheet in your HTML and apply your CSS.
+
+# --hints--
+
+`body` should have a background color of `#f4f4f4`.
+
+```js
+const body = document.body;
+const bodyBgColor = getComputedStyle(body).backgroundColor;
+assert.strictEqual(bodyBgColor, 'rgb(244, 244, 244)');
+```
+
+You should have a `div` element with a class of `color-grid`.
+
+```js
+const colorGrid = document.querySelector('div.color-grid');
+assert.exists(colorGrid);
+```
+
+You should have five `div` elements within the `.color-grid` element.
+
+```js
+const colorGridChildren = document.querySelectorAll('div.color-grid > div');
+assert.strictEqual(colorGridChildren.length, 5);
+```
+
+Each of the five `div` elements should each have a class of `color-box` and `color#`—substitute the order of the `div` for the `#` symbol.
+
+```js
+const colorGridChildren = document.querySelectorAll('div.color-grid > div');
+assert.strictEqual(colorGridChildren.length, 5);
+
+colorGridChildren.forEach((child, index) => {
+ const colorClass = `color${index + 1}`;
+ assert.isTrue(child.classList.contains('color-box'));
+ assert.isTrue(child.classList.contains(colorClass));
+});
+```
+
+The `.color-box` element should have a set `width` and `height`.
+
+```js
+const colorBox = document.querySelector('.color-box');
+assert.exists(colorBox);
+
+const colorBoxStyles = getComputedStyle(colorBox);
+const width = colorBoxStyles.width;
+const height = colorBoxStyles.height;
+
+assert.notStrictEqual(width, '0px');
+assert.notStrictEqual(height, '0px');
+```
+
+The `.color1` element should have a hexadecimal background color.
+
+```js
+assert.match(__helpers.removeCssComments(code), /\.color1\s*{[^}]*\bbackground-color\s*:\s*#[0-9a-fA-F]{3,6}\s*;[^}]*}/);
+```
+
+The `.color2` element should have an RGB background color.
+
+```js
+assert.match(__helpers.removeCssComments(code), /\.color2\s*{[^}]*\bbackground-color\s*:\s*rgb\s*\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*\)\s*;[^}]*}/);
+```
+
+The `.color3` element should have a predefined (word) background color.
+
+```js
+assert.match(__helpers.removeCssComments(code), /\.color3\s*{[^}]*\bbackground-color\s*:\s*[a-zA-Z]+\s*;[^}]*}/);
+```
+
+The `.color4` element should have a HSL background color.
+
+```js
+assert.match(__helpers.removeCssComments(code), /\.color4\s*{[^}]*\bbackground-color\s*:\s*hsl\s*\(\s*\d+\s*,\s*\d+%\s*,\s*\d+%\s*\)\s*;[^}]*}/);
+```
+
+The `.color5` element should have a background color set.
+
+```js
+assert.isNotEmpty(new __helpers.CSSHelp(document).getStyle('.color5').getPropVal('background-color', true));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
Colored Boxes
+
+
+
+
+
+```
+
+```css
+
+```
+
+# --solutions--
+
+```html
+
+
+
+
+
+
Colored Boxes
+
+
+
+
Colored Boxes
+
+
+
+```
+
+```css
+body {
+ font-family: Arial, sans-serif;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ margin: 0;
+ padding: 20px;
+ background-color: #f4f4f4;
+}
+
+h1 {
+ margin-bottom: 20px;
+}
+
+.color-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
+ gap: 10px;
+ width: 100%;
+ max-width: 800px;
+}
+
+.color-box {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ font-weight: bold;
+ border-radius: 8px;
+ text-align: center;
+ width: 100px;
+ height: 100px;
+}
+
+.color1 {
+ background-color: #33FF57;
+}
+
+.color2 {
+ background-color: rgb(128,0,128);
+}
+
+.color3 {
+ background-color: orange;
+}
+
+.color4 {
+ background-color: hsl(59, 61%, 26%);
+}
+
+.color5 {
+ background-color: red;
+}
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-confidential-email-page/66bba6fff611169359d9d36a.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-confidential-email-page/66bba6fff611169359d9d36a.md
index 172c1a819d..1315872165 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-confidential-email-page/66bba6fff611169359d9d36a.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-confidential-email-page/66bba6fff611169359d9d36a.md
@@ -1,7 +1,7 @@
---
id: 66bba6fff611169359d9d36a
title: Build a Confidential Email Page
-challengeType: 14
+challengeType: 25
dashedName: build-a-confidential-email-page
demoType: onClick
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-contact-form/66f26c32ec6f90df01a44f60.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-contact-form/66f26c32ec6f90df01a44f60.md
index 50d4ccf429..fef5f6f614 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-contact-form/66f26c32ec6f90df01a44f60.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-contact-form/66f26c32ec6f90df01a44f60.md
@@ -1,7 +1,7 @@
---
id: 66f26c32ec6f90df01a44f60
title: Design a Contact Form
-challengeType: 14
+challengeType: 25
dashedName: design-a-contact-form
demoType: onClick
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-customer-complaint-form/67279fe50237291f80eed8b8.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-customer-complaint-form/67279fe50237291f80eed8b8.md
new file mode 100644
index 0000000000..7efe9ec6bb
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-customer-complaint-form/67279fe50237291f80eed8b8.md
@@ -0,0 +1,857 @@
+---
+id: 67279fe50237291f80eed8b8
+title: Build a Customer Complaint Form
+challengeType: 25
+dashedName: build-a-customer-complaint-form
+demoType: onClick
+---
+
+# --description--
+
+For this lab, you have been provided with all the HTML and CSS. You will use JavaScript to validate the complaint form.
+
+**Objective:** Fulfill the user stories below and get all the tests to pass to complete the lab.
+
+**User Stories:**
+
+1. When the form is submitted, you should ensure that:
+ - `#full-name` is not empty.
+ - `#email` is a valid email address format.
+ - `#order-no` is a sequence of ten numbers starting with `2024`.
+ - `#product-code` follows the pattern `XX##-X###-XX#`, where `X` represents either a lowercase letter or an uppercase letter and `#` represents a number.
+ - `#quantity` is a positive integer.
+ - at least one checkbox from `#complaints-group` is checked.
+ - `#complaint-description` contains at least twenty characters if the `Other` checkbox is checked.
+ - a radio button from `#solutions-group` is selected.
+ - `#solution-description` contains at least twenty characters if the `Other` radio button is selected.
+1. You should have a function named `validateForm` that returns an object containing the following keys: `full-name`, `email`, `order-no`, `product-code`, `quantity`, `complaints-group`, `complaint-description`, `solutions-group`, and `solution-description`. The value of each key should be `true` if the corresponding form field is correctly filled and `false` otherwise.
+1. You should have a function named `isValid` that takes the object returned by `validateForm` as argument and returns `true` if every form field is correctly filled and `false` otherwise.
+1. If a change event is triggered on a form field and it has a valid value, you should set its border color to `green`. In case of checkbox and radio button groups, you should set the border color of the parent `fieldset`.
+1. If a change event is triggered on a form field and it has an invalid value, you should set its border color to `red`. In case of checkbox and radio button groups, you should set the border color of the parent `fieldset`.
+1. When you try to submit the form you should call `isValid` to validate the form.
+1. When you try to submit the form, if the form has any invalid field, each invalid field should be highlighted by setting the border color of each invalid input, textarea or fieldset (in case of checkbox and radio button groups) to `red`.
+
+# --hints--
+
+You should have a function named `validateForm`.
+
+```js
+assert.isFunction(validateForm);
+```
+
+`validateForm` should return an object.
+
+```js
+assert.isObject(validateForm());
+```
+
+`validateForm()["full-name"]` should be `false` when `#full-name` is empty, and `true` otherwise.
+
+```js
+const field = document.getElementById("full-name");
+field.value = "";
+assert.isFalse(validateForm()["full-name"]);
+field.value = "testing";
+assert.isTrue(validateForm()["full-name"]);
+```
+
+When a `change` event is triggered on `#full-name`, you should set its border color to `green` if it contains a valid value, and `red` otherwise.
+
+```js
+const field = document.getElementById("full-name");
+field.value = "testing"
+field.dispatchEvent(new Event("change", { bubbles: true }));
+assert.equal(field.style.borderColor, "green");
+field.value = ""
+field.dispatchEvent(new Event("change", { bubbles: true }));
+assert.equal(field.style.borderColor, "red");
+```
+
+`validateForm()["email"]` should be `true` when `#email` contains a valid email address, and `false` otherwise.
+
+```js
+const field = document.getElementById("email");
+field.value = "example@domain.com"
+assert.isTrue(validateForm()["email"]);
+field.value = "testing"
+assert.isFalse(validateForm()["email"]);
+```
+
+When a `change` event is triggered on `#email`, you should set its border color to `green` if it contains a valid email address, and `red` otherwise.
+
+```js
+const field = document.getElementById("email");
+field.value = "example@domain.com"
+field.dispatchEvent(new Event("change", { bubbles: true }));
+assert.equal(field.style.borderColor, "green");
+field.value = ""
+field.dispatchEvent(new Event("change", { bubbles: true }));
+assert.equal(field.style.borderColor, "red");
+```
+
+`validateForm()["order-no"]` should be `true` when `#order-no` contains a valid value, and `false` otherwise.
+
+```js
+const field = document.getElementById("order-no");
+field.value = "2024001122"
+assert.isTrue(validateForm()["order-no"]);
+field.value = "testing"
+assert.isFalse(validateForm()["order-no"]);
+```
+
+When a `change` event is triggered on `#order-no`, you should set its border color to `green` if it contains a valid value, and `red` otherwise.
+
+```js
+const field = document.getElementById("order-no");
+field.value = "2024001122"
+field.dispatchEvent(new Event("change", { bubbles: true }));
+assert.equal(field.style.borderColor, "green");
+field.value = "20240011"
+field.dispatchEvent(new Event("change", { bubbles: true }));
+assert.equal(field.style.borderColor, "red");
+```
+
+`validateForm()["product-code"]` should be `true` when `#product-code` contains a valid value, and `false` otherwise.
+
+```js
+const field = document.getElementById("product-code");
+field.value = "Xa22-X123-Xb4";
+assert.isTrue(validateForm()["product-code"]);
+field.value = "testing"
+assert.isFalse(validateForm()["product-code"]);
+```
+
+When a `change` event is triggered on `#product-code`, you should set its border color to `green` if it contains a valid value, and `red` otherwise.
+
+```js
+const field = document.getElementById("product-code");
+field.value = "Xa22-X123-Xb4"
+field.dispatchEvent(new Event("change", { bubbles: true }));
+assert.equal(field.style.borderColor, "green");
+field.value = "Xa22-123-Xb4"
+field.dispatchEvent(new Event("change", { bubbles: true }));
+assert.equal(field.style.borderColor, "red");
+```
+
+`validateForm()["quantity"]` should be `true` when `#quantity` contains a valid value, and `false` otherwise.
+
+```js
+const field = document.getElementById("quantity");
+field.value = "5";
+assert.isTrue(validateForm()["quantity"]);
+field.value = "0";
+assert.isFalse(validateForm()["quantity"]);
+```
+
+When a `change` event is triggered on `#quantity`, you should set its border color to `green` if it contains a valid value, and `red` otherwise.
+
+```js
+const field = document.getElementById("quantity");
+field.value = "2"
+field.dispatchEvent(new Event("change", { bubbles: true }));
+assert.equal(field.style.borderColor, "green");
+field.value = "0"
+field.dispatchEvent(new Event("change", { bubbles: true }));
+assert.equal(field.style.borderColor, "red");
+```
+
+When at least one checkbox from `#complaints-group` is checked, `validateForm()["complaints-group"]` should be `true`.
+
+```js
+document.getElementById("damaged-product").checked = true
+assert.isTrue(validateForm()["complaints-group"]);
+```
+
+When none of the checkboxes from `#complaints-group` is checked, `validateForm()["complaints-group"]` should be `false`.
+
+```js
+document.getElementById("damaged-product").checked = false;
+document.getElementById("nonconforming-product").checked = false;
+document.getElementById("delayed-dispatch").checked = false;
+document.getElementById("other-complaint").checked = false;
+assert.isFalse(validateForm()["complaints-group"]);
+```
+
+Once one checkbox from `#complaints-group` is checked, you should set `#complaints-group`'s border color to `green`.
+
+```js
+document.getElementById("damaged-product").checked = true;
+document.getElementById("nonconforming-product").checked = false;
+document.getElementById("delayed-dispatch").checked = false;
+document.getElementById("other-complaint").checked = false;
+const fieldset = document.getElementById("complaints-group");
+fieldset.dispatchEvent(new Event("change", { bubbles: true }));
+assert.equal(fieldset.style.borderColor, "green");
+```
+
+When all of the checkboxes from `#complaints-group` are changed to the unchecked state, you should set `#complaints-group`'s border color to `red`.
+
+```js
+document.getElementById("damaged-product").checked = false;
+document.getElementById("nonconforming-product").checked = false;
+document.getElementById("delayed-dispatch").checked = false;
+document.getElementById("other-complaint").checked = false;
+const fieldset = document.getElementById("complaints-group");
+fieldset.dispatchEvent(new Event("change", { bubbles: true }));
+assert.equal(fieldset.style.borderColor, "red");
+```
+
+When `#other-complaint` is checked and `#complaint-description` contains at least twenty characters, `validateForm()["complaint-description"]` should be `true`.
+
+```js
+document.getElementById("other-complaint").checked = true
+document.getElementById("complaint-description").value = "A sentence with at least twenty characters";
+assert.isTrue(validateForm()["complaint-description"]);
+```
+
+When `#other-complaint` is checked and `#complaint-description` contains less than twenty characters, `validateForm()["complaint-description"]` should be `false`.
+
+```js
+document.getElementById("other-complaint").checked = true
+document.getElementById("complaint-description").value = "Less than 20 chars";
+assert.isFalse(validateForm()["complaint-description"]);
+```
+
+Once the value of `#complaint-description` is changed to a valid value, you should set its border color to `green`.
+
+```js
+const field = document.getElementById("complaint-description");
+field.value = "A sentence with at least twenty characters"
+field.dispatchEvent(new Event("change", { bubbles: true }));
+assert.equal(field.style.borderColor, "green");
+```
+
+Once the value of `#complaint-description` is changed to an invalid value, you should set its border color to `red`.
+
+```js
+const field = document.getElementById("complaint-description");
+field.value = "Not enough chars"
+field.dispatchEvent(new Event("change", { bubbles: true }));
+assert.equal(field.style.borderColor, "red");
+```
+
+When a radio button from `#solutions-group` is checked, `validateForm()["solutions-group"]` should be `true`.
+
+```js
+document.getElementById("refund").checked = true
+assert.isTrue(validateForm()["solutions-group"]);
+```
+
+When none of the radio buttons from `#solutions-group` is checked, `validateForm()["solutions-group"]` should be `false`.
+
+```js
+document.getElementById("refund").checked = false;
+document.getElementById("exchange").checked = false;
+document.getElementById("other-solution").checked = false;
+assert.isFalse(validateForm()["solutions-group"]);
+```
+
+Once a radio button from `#solutions-group` is checked, you should set `#solutions-group`'s border color to `green`.
+
+```js
+document.getElementById("refund").checked = true;
+document.getElementById("exchange").checked = false;
+document.getElementById("other-solution").checked = false;
+const fieldset = document.getElementById("solutions-group");
+fieldset.dispatchEvent(new Event("change", { bubbles: true }));
+assert.equal(fieldset.style.borderColor, "green");
+```
+
+When all of the checkboxes from `#complaints-group` are changed to the unchecked state, you should set `#complaints-group`'s border color to `red`.
+
+```js
+document.getElementById("refund").checked = false;
+document.getElementById("exchange").checked = false;
+document.getElementById("other-solution").checked = false;
+const fieldset = document.getElementById("solutions-group");
+fieldset.dispatchEvent(new Event("change", { bubbles: true }));
+assert.equal(fieldset.style.borderColor, "red");
+```
+
+When `#other-solution` is checked and `#solution-description` contains at least twenty characters, `validateForm()["solution-description"]` should be `true`.
+
+```js
+document.getElementById("other-solution").checked = true
+document.getElementById("solution-description").value = "A sentence with at least twenty characters";
+assert.isTrue(validateForm()["solution-description"]);
+```
+
+When `#other-solution` is checked and `#solution-description` contains less than twenty characters, `validateForm()["solution-description"]` should be `false`.
+
+```js
+document.getElementById("other-solution").checked = true
+document.getElementById("solution-description").value = "Less than 20 chars";
+assert.isFalse(validateForm()["solution-description"]);
+```
+
+Once the value of `#solution-description` is changed to a valid value, you should set its border color to `green`.
+
+```js
+const field = document.getElementById("solution-description");
+field.value = "A sentence with at least twenty characters"
+field.dispatchEvent(new Event("change", { bubbles: true }));
+assert.equal(field.style.borderColor, "green");
+```
+
+Once the value of `#solution-description` is changed to an invalid value, you should set its border color to `red`.
+
+```js
+const field = document.getElementById("solution-description");
+field.value = "Not enough chars"
+field.dispatchEvent(new Event("change", { bubbles: true }));
+assert.equal(field.style.borderColor, "red");
+```
+
+You should have a function named `isValid`.
+
+```js
+assert.isFunction(isValid);
+```
+
+Your `isValid` function should take the `validateForm()` as its argument and return `true` when all the form fields have been filled correctly.
+
+```js
+document.getElementById("full-name").value = "testing"
+document.getElementById("email").value = "example@domain.com"
+document.getElementById("order-no").value = "2024001122"
+document.getElementById("product-code").value = "Xa22-X123-Xb4"
+document.getElementById("quantity").value = "5"
+document.getElementById("damaged-product").checked = true
+document.getElementById("other-complaint").checked = false
+document.getElementById("refund").checked = true
+document.getElementById("other-solution").checked = false
+assert.isTrue(isValid(validateForm()));
+
+document.getElementById("other-complaint").checked = true
+document.getElementById("complaint-description").value = "A sentence with at least twenty characters";
+document.getElementById("other-solution").checked = true
+document.getElementById("solution-description").value = "A sentence with at least twenty characters";
+assert.isTrue(isValid(validateForm()));
+```
+
+Your `isValid` function should take the `validateForm()` as its argument and return `false` when not all the form fields have been filled correctly.
+
+```js
+const name = document.getElementById("full-name");
+const email = document.getElementById("email");
+const orderNo = document.getElementById("order-no");
+const prCode = document.getElementById("product-code");
+const quantity = document.getElementById("quantity");
+const damaged = document.getElementById("damaged-product");
+const nonConforming = document.getElementById("nonconforming-product");
+const delayed = document.getElementById("delayed-dispatch");
+const otherC = document.getElementById("other-complaint");
+const complaintDescr = document.getElementById("complaint-description");
+const refund = document.getElementById("refund");
+const exchange = document.getElementById("exchange");
+const otherS = document.getElementById("other-solution");
+const solutionDescr = document.getElementById("solution-description");
+
+// invalid full-name
+name.value = "";
+email.value = "example@domain.com";
+orderNo.value = "2024001122";
+prCode.value = "Xa22-X123-Xb4";
+quantity.value = "5";
+damaged.checked = true;
+refund.checked = true;
+assert.isFalse(isValid(validateForm()));
+
+// invalid email
+name.value = "testing";
+email.value = "";
+assert.isFalse(isValid(validateForm()));
+
+// invalid order-no
+email.value = "example@domain.com";
+orderNo.value = "202400";
+assert.isFalse(isValid(validateForm()));
+
+// invalid product-code
+orderNo.value = "2024001122";
+prCode.value = "1a22-Xa23-Xb4";
+assert.isFalse(isValid(validateForm()));
+
+// invalid quantity
+prCode.value = "Xa22-X123-Xb4";
+quantity.value = 0;
+assert.isFalse(isValid(validateForm()));
+
+// invalid complaints-group
+quantity.value = 5;
+damaged.checked = false;
+nonConforming.checked = false;
+delayed.checked = false;
+otherC.checked = false;
+assert.isFalse(isValid(validateForm()));
+
+// invalid complaint-description
+otherC.checked = true;
+complaintDescr.value = "not enough chars";
+assert.isFalse(isValid(validateForm()));
+
+
+// invalid solutions-group
+complaintDescr.value = "A sentence with at least twenty characters";
+refund.checked = false;
+exchange.checked = false;
+otherS.checked = false;
+assert.isFalse(isValid(validateForm()));
+
+// invalid solutions-description
+otherS.checked = true;
+solutionDescr.value = "not enough chars";
+assert.isFalse(isValid(validateForm()));
+```
+
+You should call `isValid` when you try to submit the form.
+
+```js
+let flag = false;
+const temp = isValid;
+try {
+ isValid = (obj) => {flag = true};
+ document.getElementById("form").dispatchEvent(new Event("submit"));
+ assert.isTrue(flag);
+} finally {
+ isValid = temp;
+}
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
Customer Complaint Form
+
+
+
+
+
+
+
Complaint Form
+
+
+
+
+
+
+```
+
+```css
+* {
+ box-sizing: border-box;
+}
+
+h1 {
+ text-align: center;
+}
+
+#form {
+ max-width: 70%;
+ margin: auto;
+ border-radius: 10px;
+ box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
+ padding: 10px;
+}
+
+input {
+ border-color: rgb(118, 118, 118);
+}
+
+#personal-info input, #product-info input {
+ width: 100%;
+ margin-bottom: 10px;
+}
+
+
+fieldset {
+ margin-bottom: 10px;
+ border-radius: 5px;
+ border-color: rgb(118, 118, 118);
+}
+
+textarea {
+ width: 100%;
+ border-color: rgb(118, 118, 118);
+}
+
+#btn-container {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+#submit-btn, #clear-btn {
+ margin: 10px 15px 0;
+}
+```
+
+```js
+
+```
+
+## --solutions--
+
+```html
+
+
+
+
+
Customer Complaint Form
+
+
+
+
+
+
+
Complaint Form
+
+
+
+ Full Name:
+
+
+
+
+ Email Address:
+
+
+
+
+
+
+ Order No:
+
+
+
+ Product Code:
+
+
+
+ Quantity:
+
+
+
+
+
+ Complaint Reason:
+
+
+ Damaged Product
+
+
+
+
+ Nonconforming Product
+
+
+
+
+ Delayed Dispatch
+
+
+
+
+ Other
+
+
+
+
+ Description of Complaint Reason
+
+
+
+
+ Desired Solution
+
+ Refund
+
+
+ Exchange
+
+
+ Other
+
+
+
+ Description of Desired Solution
+
+
+
+ Submit
+
+ Clear
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ box-sizing: border-box;
+}
+
+h1 {
+ text-align: center;
+}
+
+#form {
+ max-width: 70%;
+ margin: auto;
+ border-radius: 10px;
+ box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
+ padding: 10px;
+}
+
+input {
+ border-color: rgb(118, 118, 118);
+}
+
+#personal-info input, #product-info input {
+ width: 100%;
+ margin-bottom: 10px;
+}
+
+
+fieldset {
+ margin-bottom: 10px;
+ border-radius: 5px;
+ border-color: rgb(118, 118, 118);
+}
+
+textarea {
+ width: 100%;
+ border-color: rgb(118, 118, 118);
+}
+
+#btn-container {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+#submit-btn, #clear-btn {
+ margin: 10px 15px 0;
+}
+```
+
+```js
+const form = document.getElementById("form");
+const fullName = document.getElementById("full-name");
+const emailAddress = document.getElementById("email");
+const orderNo = document.getElementById("order-no");
+const productCode = document.getElementById("product-code");
+const quantity = document.getElementById("quantity");
+const complaints = document.querySelectorAll('input[name="complaint"]');
+const complaintDescription = document.getElementById("complaint-description");
+const complaintTextAreaDiv = document.getElementById("complaint-description-container");
+const solutions = document.querySelectorAll('input[name="solutions"]');
+const solutionDescription = document.getElementById("solution-description");
+const solutionTextAreaDiv = document.getElementById("solution-description-container");
+const submitBtn = document.getElementById("submit-btn");
+const messageBox = document.getElementById("message-box");
+const clearBtn = document.getElementById("clear-btn");
+
+const hideTextareas = () => {
+ complaintTextAreaDiv.style.display = "none";
+ solutionTextAreaDiv.style.display = "none";
+}
+
+hideTextareas();
+
+const formFields = {
+ "full-name": fullName,
+ "email": emailAddress,
+ "order-no": orderNo,
+ "product-code": productCode,
+ "quantity": quantity,
+ "complaints-group": Array.from(complaints),
+ "complaint-description": complaintDescription,
+ "solutions-group": Array.from(solutions),
+ "solution-description": solutionDescription
+}
+
+const clearForm = () => {
+ Object.entries(formFields).forEach(entry => {
+ const [key, val] = entry;
+ if (Array.isArray(val)) {
+ val.forEach(i => i.checked = false);
+ } else {
+ val.value = "";
+ }
+ hideTextareas();
+ messageBox.innerText = "";
+ document.getElementById(key).style.borderColor = "rgb(118, 118, 118)";
+ })
+}
+
+const validateForm = () => {
+ const complaintsArr = Array.from(complaints).map(i => i.checked);
+ const solutionsArr = Array.from(solutions).map(i => i.checked);
+ const validationObject = {
+ "full-name": Boolean(fullName.value.trim()),
+ "email": /^\S+@\S+\.\S+$/.test(emailAddress.value.trim()),
+ "order-no": /^2024\d{6}$/.test(orderNo.value.trim()),
+ "product-code": /[A-Z]{2}\d{2}-[A-Z]\d{3}-[A-Z]{2}\d/i.test(productCode.value.trim()),
+ "quantity": Number(quantity.value.trim()) > 0,
+ "complaints-group": complaintsArr.some(i => i),
+ "complaint-description": null,
+ "solutions-group": solutionsArr.some(i => i),
+ "solution-description": null
+ }
+
+ if (complaintsArr[3]) {
+ complaintTextAreaDiv.style.display = "block";
+ const complaintsDescriptionVal = complaintDescription.value.trim();
+ if (complaintsDescriptionVal.length < 20) {
+ validationObject["complaint-description"] = false;
+ } else {
+ validationObject["complaint-description"] = true;
+ }
+ } else {
+ complaintTextAreaDiv.style.display = "none";
+ }
+ if (solutionsArr[2]) {
+ solutionTextAreaDiv.style.display = "block";
+ const solutionDescriptionVal = solutionDescription.value.trim();
+ if (solutionDescriptionVal.length < 20) {
+ validationObject["solution-description"] = false;
+ } else {
+ validationObject["solution-description"] = true;
+ }
+ } else {
+ solutionTextAreaDiv.style.display = "none";
+ }
+ if (validationObject["complaint-description"] === null) delete validationObject["complaint-description"];
+ if (validationObject["solution-description"] === null) delete validationObject["solution-description"];
+
+ return validationObject;
+}
+
+clearBtn.addEventListener("click", clearForm);
+
+Object.keys(formFields).forEach(key => {
+ document.getElementById(key).addEventListener("change", (e) => {
+ const validationObject = validateForm();
+ if (Object.values(validationObject).every(val => val)) messageBox.innerText = "";
+ if (!validationObject[key]) {
+ document.getElementById(key).style.borderColor = "red";
+ } else {
+ document.getElementById(key).style.borderColor = "green";
+ }
+ });
+});
+
+const isValid = (validationObj) => Object.values(validationObj).every(i => i);
+
+form.addEventListener("submit", (e) => {
+ e.preventDefault();
+ const validationObject = validateForm();
+ if (!isValid(validationObject)) {
+ messageBox.innerText = "Please, fill out the required fields correctly before submitting.";
+ Object.keys(validationObject).forEach(key => {
+ if (!validationObject[key]) {
+ document.getElementById(key).style.borderColor = "red";
+ } else {
+ document.getElementById(key).style.borderColor = "green";
+ }
+ });
+ } else {
+ messageBox.innerText = "";
+ alert("Form successfully submitted.");
+ clearForm();
+ }
+});
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-date-conversion/66f686b8ebdb982fa8e14330.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-date-conversion/66f686b8ebdb982fa8e14330.md
index 92866f2246..61652a9b06 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-date-conversion/66f686b8ebdb982fa8e14330.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-date-conversion/66f686b8ebdb982fa8e14330.md
@@ -1,7 +1,7 @@
---
id: 66f686b8ebdb982fa8e14330
title: Build a Date Conversion Program
-challengeType: 14
+challengeType: 25
dashedName: lab-date-conversion
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-email-masker/66b205e6eacba4c4e54ea434.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-email-masker/66b205e6eacba4c4e54ea434.md
index df5635a8da..9f02d1c69e 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-email-masker/66b205e6eacba4c4e54ea434.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-email-masker/66b205e6eacba4c4e54ea434.md
@@ -1,7 +1,7 @@
---
id: 66b205e6eacba4c4e54ea434
title: Build an Email Masker
-challengeType: 14
+challengeType: 25
dashedName: build-an-email-masker
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-event-flyer-page/66e45c8140f9fda5c105ae26.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-event-flyer-page/66e45c8140f9fda5c105ae26.md
index b934e0ecb7..41d79d80c3 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-event-flyer-page/66e45c8140f9fda5c105ae26.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-event-flyer-page/66e45c8140f9fda5c105ae26.md
@@ -1,7 +1,7 @@
---
id: 66e45c8140f9fda5c105ae26
title: Build an Event Flyer Page
-challengeType: 14
+challengeType: 25
dashedName: build-an-event-flyer-page
demoType: onClick
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-event-hub/66ebd4ae2812430bb883c787.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-event-hub/66ebd4ae2812430bb883c787.md
index 3ab317eee8..ff6d8c8146 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-event-hub/66ebd4ae2812430bb883c787.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-event-hub/66ebd4ae2812430bb883c787.md
@@ -1,7 +1,7 @@
---
id: 66ebd4ae2812430bb883c787
title: Build an Event Hub
-challengeType: 14
+challengeType: 25
dashedName: lab-event-hub
demoType: onClick
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-factorial-calculator/66c07238b01053abaf812065.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-factorial-calculator/66c07238b01053abaf812065.md
index c28ce726bd..4ecd12ca5c 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-factorial-calculator/66c07238b01053abaf812065.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-factorial-calculator/66c07238b01053abaf812065.md
@@ -1,7 +1,7 @@
---
id: 66c07238b01053abaf812065
title: Build a Factorial Calculator
-challengeType: 14
+challengeType: 25
dashedName: build-a-factorial-calculator
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-favorite-icon-toggler/66bf6bacf178eac7b96d4f5e.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-favorite-icon-toggler/66bf6bacf178eac7b96d4f5e.md
index 5acfa5cd38..2d4dba8d26 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-favorite-icon-toggler/66bf6bacf178eac7b96d4f5e.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-favorite-icon-toggler/66bf6bacf178eac7b96d4f5e.md
@@ -1,7 +1,7 @@
---
id: 66bf6bacf178eac7b96d4f5e
title: Build a Favorite Icon Toggler
-challengeType: 14
+challengeType: 25
dashedName: build-a-favorite-icon-toggler
demoType: onClick
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-fcc-forum-leaderboard/673c91f0b934834bc4a3ecc2.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-fcc-forum-leaderboard/673c91f0b934834bc4a3ecc2.md
index 5bf3e1cc15..55e29ad88d 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-fcc-forum-leaderboard/673c91f0b934834bc4a3ecc2.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-fcc-forum-leaderboard/673c91f0b934834bc4a3ecc2.md
@@ -1,7 +1,7 @@
---
id: 673c91f0b934834bc4a3ecc2
title: Build an fCC Forum Leaderboard
-challengeType: 14
+challengeType: 25
dashedName: build-an-fcc-forum-leaderboard
demoType: onClick
---
@@ -16,39 +16,39 @@ Fulfill the user stories below and get all the tests to pass to complete the lab
1. You should have a function named `timeAgo` that takes a timestamp in the ISO 8601 format as the argument.
1. The `timeAgo` function should compute the time difference between the time passed as an argument and the current time and return:
- - `xm ago` (`x` represents minutes) if the amount of minutes that have passed is less than `60`.
- - `xh ago` (`x` represents hours) if the amount of hours that have passed is less than `24`.
- - `xd ago` (`x` represents days) otherwise.
+ - `xm ago` (`x` represents minutes) if the amount of minutes that have passed is less than `60`.
+ - `xh ago` (`x` represents hours) if the amount of hours that have passed is less than `24`.
+ - `xd ago` (`x` represents days) otherwise.
1. You should have a function named `viewCount` that takes the number of views of a post as the argument.
1. If the value of the views passed as the argument is greater than or equal to `1000`, the `viewCount` function should return a string with the views value divided by `1000`, rounded down to the nearest whole number and the letter `k` appended to it. Otherwise, it should return the views value.
1. You should have a function named `forumCategory` that takes the id of a selected category as the argument.
1. The `forumCategory` function should verify that the selected category id is a property of the `allCategories` object and should return a string containing an anchor element with:
- - the text of the `category` key of the selected category.
- - a class of `category` followed by the `className` property of the selected category.
- - an `href` with the value of `
//`, where `` is the `className` property of the selected category and `id` is the argument passed to `forumCategory`.
+ - the text of the `category` key of the selected category.
+ - a class of `category` followed by the `className` property of the selected category.
+ - an `href` with the value of `//`, where `` is the `className` property of the selected category and `id` is the argument passed to `forumCategory`.
1. If the `allCategories` object does not have the selected category id as its property, `className` and `category` should be indicated as `general`.
1. You should have a function named `avatars` that takes two arrays representing posters and users, respectively.
-1. The `avatars` function should return a string made by joining `img` elements, one for each poster found inside the user array. *Hint:* You can find users by comparing the `user_id` property of the poster with the `id` property` of the user.
+1. The `avatars` function should return a string made by joining `img` elements, one for each poster found inside the user array. _Hint:_ You can find users by comparing the `user_id` property of the poster with the `id` property` of the user.
1. The `avatars` function should set each avatar's size by accessing the `avatar_template` property and replacing `{size}` with `30`.
1. Each image element should have an alt text with the value of the `name` property of the poster.
1. Each image element should have a source with the value of the `avatar_template` property of the poster. In case `avatar_template` contains a relative path, you should set the source to `/`.
1. You should have a function named `showLatestPosts` that takes a single parameter.
1. The `showLatestPosts` should extract the `users` and `topic_list` properties from the object passed as argument. Also, it should process the following properties of the objects from the `topics` array, which is contained in `topic_list`:
- - `id`: the id of the post
- - `title`: the title of the post
- - `views`: the number of views of the post
- - `posts_count`: the number of replies to the topic
- - `slug`: the slug of the post
- - `posters`: the posters for that topic
- - `category_id`: an integer indicating the category id for the post
- - `bumped_at`: a timestamp in the ISO 8601 format
+ - `id`: the id of the post
+ - `title`: the title of the post
+ - `views`: the number of views of the post
+ - `posts_count`: the number of replies to the topic
+ - `slug`: the slug of the post
+ - `posters`: the posters for that topic
+ - `category_id`: an integer indicating the category id for the post
+ - `bumped_at`: a timestamp in the ISO 8601 format
1. The `showLatestPosts` should set the inner HTML of `#posts-container` to a string made by joining `tr` elements, one for each item in `topics`.
1. Each `tr` element should have five `td` elements in it:
- - a `td` containing two anchor elements, one with the class of `post-title`, an `href` of `/`, an anchor text of ``, and one obtained by calling `forumCategory` with `category_id`.
- - a `td` containing a `div` element with class `avatar-container` that contains the images returned by the `avatars` function called with `posters` and `users` as arguments.
- - a `td` containing the number of replies to the post. *Hint:* use `posts_count - 1`.
- - a `td` containing the number of views of the post.
- - a `td` containing the time passed since the last activity.
+ - a `td` containing two anchor elements, one with the class of `post-title`, an `href` of `/`, an anchor text of ``, and one obtained by calling `forumCategory` with `category_id`.
+ - a `td` containing a `div` element with class `avatar-container` that contains the images returned by the `avatars` function called with `posters` and `users` as arguments.
+ - a `td` containing the number of replies to the post. _Hint:_ use `posts_count - 1`.
+ - a `td` containing the number of views of the post.
+ - a `td` containing the time passed since the last activity.
1. You should have an async function named `fetchData`.
1. The `fetchData` function should request data from `forumLatest` and call `showLatestPosts` passing it the response parsed as JSON.
1. If there's an error when fetching data, the `fetchData` function should log the error to the console.
@@ -66,10 +66,10 @@ When the time difference between the time passed as argument and the current tim
```js
const generateTime = () => {
- const currentTime = new Date();
- return new Date(currentTime - (1000 * 60 * 50)).toISOString()
-}
-const expected = "50m ago";
+ const currentTime = new Date();
+ return new Date(currentTime - 1000 * 60 * 50).toISOString();
+};
+const expected = '50m ago';
const actual = timeAgo(generateTime());
assert.equal(actual, expected);
```
@@ -78,10 +78,10 @@ When the time difference between the time passed as argument and the current tim
```js
const generateTime = () => {
- const currentTime = new Date();
- return new Date(currentTime - (1000 * 60 * 60)).toISOString()
-}
-const expected = "1h ago";
+ const currentTime = new Date();
+ return new Date(currentTime - 1000 * 60 * 60).toISOString();
+};
+const expected = '1h ago';
const actual = timeAgo(generateTime());
assert.equal(actual, expected);
```
@@ -90,10 +90,10 @@ When the time difference between the time passed as argument and the current tim
```js
const generateTime = () => {
- const currentTime = new Date();
- return new Date(currentTime - (1000 * ( 60 * 115))).toISOString()
-}
-const expected = "1h ago";
+ const currentTime = new Date();
+ return new Date(currentTime - 1000 * (60 * 115)).toISOString();
+};
+const expected = '1h ago';
const actual = timeAgo(generateTime());
assert.equal(actual, expected);
```
@@ -102,10 +102,10 @@ When the time difference between the time passed as argument and the current tim
```js
const generateTime = () => {
- const currentTime = new Date();
- return new Date(currentTime - (1000 * 60 * 60 * 15)).toISOString()
-}
-const expected = "15h ago";
+ const currentTime = new Date();
+ return new Date(currentTime - 1000 * 60 * 60 * 15).toISOString();
+};
+const expected = '15h ago';
const actual = timeAgo(generateTime());
assert.equal(actual, expected);
```
@@ -114,10 +114,10 @@ When the time difference between the time passed as argument and the current tim
```js
const generateTime = () => {
- const currentTime = new Date();
- return new Date(currentTime - (1000 * 60 * 60 * 24)).toISOString()
-}
-const expected = "1d ago";
+ const currentTime = new Date();
+ return new Date(currentTime - 1000 * 60 * 60 * 24).toISOString();
+};
+const expected = '1d ago';
const actual = timeAgo(generateTime());
assert.equal(actual, expected);
```
@@ -126,10 +126,10 @@ When the time difference between the time passed as argument and the current tim
```js
const generateTime = () => {
- const currentTime = new Date();
- return new Date(currentTime - (1000 * 60 * 60 * 46)).toISOString()
-}
-const expected = "1d ago";
+ const currentTime = new Date();
+ return new Date(currentTime - 1000 * 60 * 60 * 46).toISOString();
+};
+const expected = '1d ago';
const actual = timeAgo(generateTime());
assert.equal(actual, expected);
```
@@ -138,10 +138,10 @@ When the time difference between the time passed as argument and the current tim
```js
const generateTime = () => {
- const currentTime = new Date();
- return new Date(currentTime - (1000 * 60 * 60 * 24 * 3)).toISOString()
-}
-const expected = "3d ago";
+ const currentTime = new Date();
+ return new Date(currentTime - 1000 * 60 * 60 * 24 * 3).toISOString();
+};
+const expected = '3d ago';
const actual = timeAgo(generateTime());
assert.equal(actual, expected);
```
@@ -162,13 +162,13 @@ assert.strictEqual(597, viewCount(597));
`viewCount(1000)` should return `1k`.
```js
-assert.equal("1k", viewCount(1000));
+assert.equal('1k', viewCount(1000));
```
`viewCount(2730)` should return `2k`.
```js
-assert.equal("2k", viewCount(2730));
+assert.equal('2k', viewCount(2730));
```
You should have a function named `forumCategory` that takes a single argument.
@@ -193,11 +193,17 @@ assert.match(actual, /^<\s*a.+?>\s*Project Feedback\s*<\/a>$/);
```js
let actual = forumCategory(299);
-assert.match(actual, /href=("|')https:\/\/forum\.freecodecamp\.org\/c\/career\/299\1/);
+assert.match(
+ actual,
+ /href=("|')https:\/\/forum\.freecodecamp\.org\/c\/career\/299\1/
+);
// prevent hardcoding
actual = forumCategory(409);
-assert.match(actual, /href=("|')https:\/\/forum\.freecodecamp\.org\/c\/feedback\/409\1/);
+assert.match(
+ actual,
+ /href=("|')https:\/\/forum\.freecodecamp\.org\/c\/feedback\/409\1/
+);
```
`forumCategory(299)` should return a string containing an anchor element with `class="category career"`.
@@ -222,10 +228,16 @@ assert.match(actual, /^<\s*a.+?>\s*General\s*<\/a>$/);
```js
let actual = forumCategory(200);
-assert.match(actual, /href=("|')https:\/\/forum\.freecodecamp\.org\/c\/general\/200/);
+assert.match(
+ actual,
+ /href=("|')https:\/\/forum\.freecodecamp\.org\/c\/general\/200/
+);
actual = forumCategory(220);
-assert.match(actual, /href=("|')https:\/\/forum\.freecodecamp\.org\/c\/general\/220/);
+assert.match(
+ actual,
+ /href=("|')https:\/\/forum\.freecodecamp\.org\/c\/general\/220/
+);
```
`forumCategory(200)` should return a string containing an anchor element with `class="category career"`.
@@ -245,58 +257,64 @@ assert.lengthOf(avatars, 2);
The `avatars` function should return a string made by joining `img` elements, one for each poster found in the user array.
```js
-const posters = [{ "user_id": 6 }, { "user_id": 285941 }, { "user_id": 170865 }]
+const posters = [{ user_id: 6 }, { user_id: 285941 }, { user_id: 170865 }];
const users = [
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/quincylarson/{size}/212400_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/quincylarson/{size}/212400_2.png',
id: 6,
- name: "Quincy Larson",
- username: "QuincyLarson"
+ name: 'Quincy Larson',
+ username: 'QuincyLarson'
},
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/jwilkins.oboe/{size}/179497_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/jwilkins.oboe/{size}/179497_2.png',
id: 285941,
- name: "Jessica Wilkins",
- username: "jwilkins.oboe"
+ name: 'Jessica Wilkins',
+ username: 'jwilkins.oboe'
},
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/ilenia/{size}/270648_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/ilenia/{size}/270648_2.png',
id: 170865,
- name: "Ilenia",
- username: "ilenia"
+ name: 'Ilenia',
+ username: 'ilenia'
},
- {id: 20}
-]
+ { id: 20 }
+];
const actual = avatars(posters, users);
const matches = actual.match(/<\s*img\s+.+?>/g);
-assert.lengthOf(matches, 3)
+assert.lengthOf(matches, 3);
```
Each `img` element in the string returned by the `avatars` function should have an `alt` text with the value of the `name` property of the poster.
```js
-const posters = [{ "user_id": 6 }, { "user_id": 285941 }, { "user_id": 170865 }]
+const posters = [{ user_id: 6 }, { user_id: 285941 }, { user_id: 170865 }];
const users = [
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/quincylarson/{size}/212400_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/quincylarson/{size}/212400_2.png',
id: 6,
- name: "Quincy Larson",
- username: "QuincyLarson"
+ name: 'Quincy Larson',
+ username: 'QuincyLarson'
},
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/jwilkins.oboe/{size}/179497_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/jwilkins.oboe/{size}/179497_2.png',
id: 285941,
- name: "Jessica Wilkins",
- username: "jwilkins.oboe"
+ name: 'Jessica Wilkins',
+ username: 'jwilkins.oboe'
},
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/ilenia/{size}/270648_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/ilenia/{size}/270648_2.png',
id: 170865,
- name: "Ilenia",
- username: "ilenia"
+ name: 'Ilenia',
+ username: 'ilenia'
},
- {id: 20}
-]
+ { id: 20 }
+];
const actual = avatars(posters, users);
const matches = actual.match(/<\s*img\s+.+?>/g);
@@ -308,28 +326,31 @@ assert.match(matches[2], /alt="Ilenia"/);
The `avatars` function should set each avatar's size by accessing the `avatar_template` property and replacing `{size}` with `30`.
```js
-const posters = [{ "user_id": 6 }, { "user_id": 285941 }, { "user_id": 170865 }]
+const posters = [{ user_id: 6 }, { user_id: 285941 }, { user_id: 170865 }];
const users = [
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/quincylarson/{size}/212400_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/quincylarson/{size}/212400_2.png',
id: 6,
- name: "Quincy Larson",
- username: "QuincyLarson"
+ name: 'Quincy Larson',
+ username: 'QuincyLarson'
},
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/jwilkins.oboe/{size}/179497_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/jwilkins.oboe/{size}/179497_2.png',
id: 285941,
- name: "Jessica Wilkins",
- username: "jwilkins.oboe"
+ name: 'Jessica Wilkins',
+ username: 'jwilkins.oboe'
},
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/ilenia/{size}/270648_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/ilenia/{size}/270648_2.png',
id: 170865,
- name: "Ilenia",
- username: "ilenia"
+ name: 'Ilenia',
+ username: 'ilenia'
},
- {id: 20}
-]
+ { id: 20 }
+];
const actual = avatars(posters, users);
assert.notMatch(actual, /\{size\}/);
assert.lengthOf(actual.match(/\/30\//g), 3);
@@ -338,35 +359,47 @@ assert.lengthOf(actual.match(/\/30\//g), 3);
Each `img` element in the string returned by the `avatars` function should have the `src` with the value of the `avatar_template` property of the poster. In case `avatar_template` contains a relative path, it should be set to `/`.
```js
-const posters = [{ "user_id": 6 }, { "user_id": 285941 }, { "user_id": 170865 }]
+const posters = [{ user_id: 6 }, { user_id: 285941 }, { user_id: 170865 }];
const users = [
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/quincylarson/{size}/212400_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/quincylarson/{size}/212400_2.png',
id: 6,
- name: "Quincy Larson",
- username: "QuincyLarson"
+ name: 'Quincy Larson',
+ username: 'QuincyLarson'
},
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/jwilkins.oboe/{size}/179497_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/jwilkins.oboe/{size}/179497_2.png',
id: 285941,
- name: "Jessica Wilkins",
- username: "jwilkins.oboe"
+ name: 'Jessica Wilkins',
+ username: 'jwilkins.oboe'
},
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/ilenia/{size}/270648_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/ilenia/{size}/270648_2.png',
id: 170865,
- name: "Ilenia",
- username: "ilenia"
+ name: 'Ilenia',
+ username: 'ilenia'
},
- {id: 20}
-]
+ { id: 20 }
+];
const actual = avatars(posters, users);
const matches = actual.match(/<\s*img\s+.+?>/g);
-assert.match(matches[0], /src="https:\/\/sea1\.discourse-cdn\.com\/freecodecamp\/user_avatar\/forum\.freecodecamp\.org\/quincylarson\/30\/212400_2\.png"/);
-assert.match(matches[1], /src="https:\/\/sea1\.discourse-cdn\.com\/freecodecamp\/user_avatar\/forum\.freecodecamp\.org\/jwilkins\.oboe\/30\/179497_2\.png"/);
-assert.match(matches[2], /src="https:\/\/sea1\.discourse-cdn\.com\/freecodecamp\/user_avatar\/forum\.freecodecamp\.org\/ilenia\/30\/270648_2\.png"/);
+assert.match(
+ matches[0],
+ /src="https:\/\/sea1\.discourse-cdn\.com\/freecodecamp\/user_avatar\/forum\.freecodecamp\.org\/quincylarson\/30\/212400_2\.png"/
+);
+assert.match(
+ matches[1],
+ /src="https:\/\/sea1\.discourse-cdn\.com\/freecodecamp\/user_avatar\/forum\.freecodecamp\.org\/jwilkins\.oboe\/30\/179497_2\.png"/
+);
+assert.match(
+ matches[2],
+ /src="https:\/\/sea1\.discourse-cdn\.com\/freecodecamp\/user_avatar\/forum\.freecodecamp\.org\/ilenia\/30\/270648_2\.png"/
+);
```
You should have a function named `showLatestPosts` that takes a single parameter.
@@ -391,9 +424,11 @@ try {
fetch = source => {
testArr.push(source);
return temp(source);
- }
+ };
fetchData();
- assert.deepEqual(testArr, ["https://cdn.freecodecamp.org/curriculum/forum-latest/latest.json"])
+ assert.deepEqual(testArr, [
+ 'https://cdn.freecodecamp.org/curriculum/forum-latest/latest.json'
+ ]);
} finally {
fetch = temp;
}
@@ -409,7 +444,7 @@ async () => {
showLatestPosts = data => {
testArr.push(data);
return temp(data);
- }
+ };
await fetchData();
assert.isNotEmpty(testArr);
} catch (err) {
@@ -417,7 +452,7 @@ async () => {
} finally {
fetch = temp;
}
-}
+};
```
If there is an error, your `fetchData` function should log the error to the console.
@@ -428,15 +463,19 @@ const temp1 = fetch;
const temp2 = console.log;
async () => {
try {
- console.log = obj => {testArr.push(obj.toString())};
- fetch = source => {throw new Error("This is a test error");}
+ console.log = obj => {
+ testArr.push(obj.toString());
+ };
+ fetch = source => {
+ throw new Error('This is a test error');
+ };
await fetchData();
- assert.deepEqual(testArr, ["Error: This is a test error"]);
+ assert.deepEqual(testArr, ['Error: This is a test error']);
} finally {
fetch = temp1;
console.log = temp2;
}
-}
+};
```
`showLatestPosts` should set the inner HTML of `#posts-container` to a string made by joining `tr` elements, one for each item in `topics`.
@@ -445,53 +484,56 @@ async () => {
const data = {
users: [
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/quincylarson/{size}/212400_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/quincylarson/{size}/212400_2.png',
id: 6,
- name: "Quincy Larson",
- username: "QuincyLarson"
+ name: 'Quincy Larson',
+ username: 'QuincyLarson'
},
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/jwilkins.oboe/{size}/179497_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/jwilkins.oboe/{size}/179497_2.png',
id: 285941,
- name: "Jessica Wilkins",
- username: "jwilkins.oboe"
+ name: 'Jessica Wilkins',
+ username: 'jwilkins.oboe'
},
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/ilenia/{size}/270648_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/ilenia/{size}/270648_2.png',
id: 170865,
- name: "Ilenia",
- username: "ilenia"
+ name: 'Ilenia',
+ username: 'ilenia'
}
],
topic_list: {
topics: [
{
- bumped_at: "2024-04-15T16:01:26.403Z",
+ bumped_at: '2024-04-15T16:01:26.403Z',
category_id: 1,
id: 684569,
- posters: [{user_id: 6}, {user_id: 170865}, {user_id: 285941}],
+ posters: [{ user_id: 6 }, { user_id: 170865 }, { user_id: 285941 }],
posts_count: 8,
- slug: "the-freecodecamp-podcast-is-back-now-with-video",
- title: "The freeCodeCamp Podcast is back – now with video",
+ slug: 'the-freecodecamp-podcast-is-back-now-with-video',
+ title: 'The freeCodeCamp Podcast is back – now with video',
views: 542
},
{
- bumped_at: "2024-04-19T13:52:03.523Z",
+ bumped_at: '2024-04-19T13:52:03.523Z',
category_id: 421,
id: 686149,
- posters: [{user_id: 170865}],
+ posters: [{ user_id: 170865 }],
posts_count: 1,
- slug: "problem-with-making-changes-to-styles-js",
- title: "Problem with making changes to styles. (JS)",
+ slug: 'problem-with-making-changes-to-styles-js',
+ title: 'Problem with making changes to styles. (JS)',
views: 9
}
]
}
-}
-const pContainer = document.getElementById("posts-container");
-pContainer.innerHTML = "";
+};
+const pContainer = document.getElementById('posts-container');
+pContainer.innerHTML = '';
showLatestPosts(data);
-assert.lengthOf(pContainer.querySelectorAll("tr"), 2);
+assert.lengthOf(pContainer.querySelectorAll('tr'), 2);
```
Each `tr` element from the string returned by `showLatestPosts` should contain `5` `td` elements.
@@ -500,54 +542,57 @@ Each `tr` element from the string returned by `showLatestPosts` should contain `
const data = {
users: [
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/quincylarson/{size}/212400_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/quincylarson/{size}/212400_2.png',
id: 6,
- name: "Quincy Larson",
- username: "QuincyLarson"
+ name: 'Quincy Larson',
+ username: 'QuincyLarson'
},
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/jwilkins.oboe/{size}/179497_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/jwilkins.oboe/{size}/179497_2.png',
id: 285941,
- name: "Jessica Wilkins",
- username: "jwilkins.oboe"
+ name: 'Jessica Wilkins',
+ username: 'jwilkins.oboe'
},
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/ilenia/{size}/270648_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/ilenia/{size}/270648_2.png',
id: 170865,
- name: "Ilenia",
- username: "ilenia"
+ name: 'Ilenia',
+ username: 'ilenia'
}
],
topic_list: {
topics: [
{
- bumped_at: "2024-04-15T16:01:26.403Z",
+ bumped_at: '2024-04-15T16:01:26.403Z',
category_id: 1,
id: 684569,
- posters: [{user_id: 6}, {user_id: 170865}, {user_id: 285941}],
+ posters: [{ user_id: 6 }, { user_id: 170865 }, { user_id: 285941 }],
posts_count: 8,
- slug: "the-freecodecamp-podcast-is-back-now-with-video",
- title: "The freeCodeCamp Podcast is back – now with video",
+ slug: 'the-freecodecamp-podcast-is-back-now-with-video',
+ title: 'The freeCodeCamp Podcast is back – now with video',
views: 542
},
{
- bumped_at: "2024-04-19T13:52:03.523Z",
+ bumped_at: '2024-04-19T13:52:03.523Z',
category_id: 421,
id: 686149,
- posters: [{user_id: 170865}],
+ posters: [{ user_id: 170865 }],
posts_count: 1,
- slug: "problem-with-making-changes-to-styles-js",
- title: "Problem with making changes to styles. (JS)",
+ slug: 'problem-with-making-changes-to-styles-js',
+ title: 'Problem with making changes to styles. (JS)',
views: 9
}
]
}
-}
-const pContainer = document.getElementById("posts-container");
-pContainer.innerHTML = "";
+};
+const pContainer = document.getElementById('posts-container');
+pContainer.innerHTML = '';
showLatestPosts(data);
-assert.lengthOf(pContainer.querySelectorAll("tr:first-child>td"), 5);
-assert.lengthOf(pContainer.querySelectorAll("tr:last-child>td"), 5);
+assert.lengthOf(pContainer.querySelectorAll('tr:first-child>td'), 5);
+assert.lengthOf(pContainer.querySelectorAll('tr:last-child>td'), 5);
```
The first `td` element of each table row from the string returned by `showLatestPosts` should contain two anchor elements, the first with the class of `post-title`, an `href` of `/`, an anchor text of ``, and the second obtained by calling `forumCategory` with `category_id`.
@@ -556,74 +601,91 @@ The first `td` element of each table row from the string returned by `showLatest
const data = {
users: [
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/quincylarson/{size}/212400_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/quincylarson/{size}/212400_2.png',
id: 6,
- name: "Quincy Larson",
- username: "QuincyLarson"
+ name: 'Quincy Larson',
+ username: 'QuincyLarson'
},
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/jwilkins.oboe/{size}/179497_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/jwilkins.oboe/{size}/179497_2.png',
id: 285941,
- name: "Jessica Wilkins",
- username: "jwilkins.oboe"
+ name: 'Jessica Wilkins',
+ username: 'jwilkins.oboe'
},
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/ilenia/{size}/270648_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/ilenia/{size}/270648_2.png',
id: 170865,
- name: "Ilenia",
- username: "ilenia"
+ name: 'Ilenia',
+ username: 'ilenia'
}
],
topic_list: {
topics: [
{
- bumped_at: "2024-04-15T16:01:26.403Z",
+ bumped_at: '2024-04-15T16:01:26.403Z',
category_id: 1,
id: 684569,
- posters: [{user_id: 6}, {user_id: 170865}, {user_id: 285941}],
+ posters: [{ user_id: 6 }, { user_id: 170865 }, { user_id: 285941 }],
posts_count: 8,
- slug: "the-freecodecamp-podcast-is-back-now-with-video",
- title: "The freeCodeCamp Podcast is back – now with video",
+ slug: 'the-freecodecamp-podcast-is-back-now-with-video',
+ title: 'The freeCodeCamp Podcast is back – now with video',
views: 542
},
{
- bumped_at: "2024-04-19T13:52:03.523Z",
+ bumped_at: '2024-04-19T13:52:03.523Z',
category_id: 421,
id: 686149,
- posters: [{user_id: 170865}],
+ posters: [{ user_id: 170865 }],
posts_count: 1,
- slug: "problem-with-making-changes-to-styles-js",
- title: "Problem with making changes to styles. (JS)",
+ slug: 'problem-with-making-changes-to-styles-js',
+ title: 'Problem with making changes to styles. (JS)',
views: 9
}
]
}
-}
-const pContainer = document.getElementById("posts-container");
-pContainer.innerHTML = "";
+};
+const pContainer = document.getElementById('posts-container');
+pContainer.innerHTML = '';
showLatestPosts(data);
-const anchors1 = pContainer.querySelectorAll("tr:first-child>td>a");
+const anchors1 = pContainer.querySelectorAll('tr:first-child>td>a');
assert.lengthOf(anchors1, 2);
-const anchors2 = pContainer.querySelectorAll("tr:last-child>td>a");
+const anchors2 = pContainer.querySelectorAll('tr:last-child>td>a');
assert.lengthOf(anchors2, 2);
-assert.equal(anchors1[0].classList[0], "post-title");
-assert.equal(anchors1[0].href, "https://forum.freecodecamp.org/t/the-freecodecamp-podcast-is-back-now-with-video/684569");
-assert.equal(anchors1[0].innerText.trim(), "The freeCodeCamp Podcast is back – now with video");
-
-assert.equal(anchors1[1].classList[0], "category");
-assert.equal(anchors1[1].classList[1], "general");
-assert.equal(anchors1[1].href, "https://forum.freecodecamp.org/c/general/1");
-
-
-assert.equal(anchors2[0].classList[0], "post-title");
-assert.equal(anchors2[0].href, "https://forum.freecodecamp.org/t/problem-with-making-changes-to-styles-js/686149");
-assert.equal(anchors2[0].innerText.trim(), "Problem with making changes to styles. (JS)");
-
-assert.equal(anchors2[1].classList[0], "category");
-assert.equal(anchors2[1].classList[1], "javascript");
-assert.equal(anchors2[1].href, "https://forum.freecodecamp.org/c/javascript/421");
+assert.equal(anchors1[0].classList[0], 'post-title');
+assert.equal(
+ anchors1[0].href,
+ 'https://forum.freecodecamp.org/t/the-freecodecamp-podcast-is-back-now-with-video/684569'
+);
+assert.equal(
+ anchors1[0].innerText.trim(),
+ 'The freeCodeCamp Podcast is back – now with video'
+);
+
+assert.equal(anchors1[1].classList[0], 'category');
+assert.equal(anchors1[1].classList[1], 'general');
+assert.equal(anchors1[1].href, 'https://forum.freecodecamp.org/c/general/1');
+
+assert.equal(anchors2[0].classList[0], 'post-title');
+assert.equal(
+ anchors2[0].href,
+ 'https://forum.freecodecamp.org/t/problem-with-making-changes-to-styles-js/686149'
+);
+assert.equal(
+ anchors2[0].innerText.trim(),
+ 'Problem with making changes to styles. (JS)'
+);
+
+assert.equal(anchors2[1].classList[0], 'category');
+assert.equal(anchors2[1].classList[1], 'javascript');
+assert.equal(
+ anchors2[1].href,
+ 'https://forum.freecodecamp.org/c/javascript/421'
+);
```
The second `td` element of each table row from the string returned by `showLatestPosts` should contain the images returned by the `avatars` function called with `posters` and `users` as arguments, nested within a `div` element with the class of `avatar-container`.
@@ -632,130 +694,154 @@ The second `td` element of each table row from the string returned by `showLates
const data = {
users: [
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/quincylarson/{size}/212400_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/quincylarson/{size}/212400_2.png',
id: 6,
- name: "Quincy Larson",
- username: "QuincyLarson"
+ name: 'Quincy Larson',
+ username: 'QuincyLarson'
},
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/jwilkins.oboe/{size}/179497_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/jwilkins.oboe/{size}/179497_2.png',
id: 285941,
- name: "Jessica Wilkins",
- username: "jwilkins.oboe"
+ name: 'Jessica Wilkins',
+ username: 'jwilkins.oboe'
},
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/ilenia/{size}/270648_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/ilenia/{size}/270648_2.png',
id: 170865,
- name: "Ilenia",
- username: "ilenia"
+ name: 'Ilenia',
+ username: 'ilenia'
}
],
topic_list: {
topics: [
{
- bumped_at: "2024-04-15T16:01:26.403Z",
+ bumped_at: '2024-04-15T16:01:26.403Z',
category_id: 1,
id: 684569,
- posters: [{user_id: 6}, {user_id: 170865}, {user_id: 285941}],
+ posters: [{ user_id: 6 }, { user_id: 170865 }, { user_id: 285941 }],
posts_count: 8,
- slug: "the-freecodecamp-podcast-is-back-now-with-video",
- title: "The freeCodeCamp Podcast is back – now with video",
+ slug: 'the-freecodecamp-podcast-is-back-now-with-video',
+ title: 'The freeCodeCamp Podcast is back – now with video',
views: 542
},
{
- bumped_at: "2024-04-19T13:52:03.523Z",
+ bumped_at: '2024-04-19T13:52:03.523Z',
category_id: 421,
id: 686149,
- posters: [{user_id: 170865}],
+ posters: [{ user_id: 170865 }],
posts_count: 1,
- slug: "problem-with-making-changes-to-styles-js",
- title: "Problem with making changes to styles. (JS)",
+ slug: 'problem-with-making-changes-to-styles-js',
+ title: 'Problem with making changes to styles. (JS)',
views: 9
}
]
}
-}
-const pContainer = document.getElementById("posts-container");
-pContainer.innerHTML = "";
+};
+const pContainer = document.getElementById('posts-container');
+pContainer.innerHTML = '';
showLatestPosts(data);
-const div1 = pContainer.querySelector("tr:first-child>td:nth-child(2)>div");
-assert.equal(div1.classList[0], "avatar-container");
+const div1 = pContainer.querySelector('tr:first-child>td:nth-child(2)>div');
+assert.equal(div1.classList[0], 'avatar-container');
-const div2 = pContainer.querySelector("tr:last-child>td:nth-child(2)>div");
-assert.equal(div2.classList[0], "avatar-container");
+const div2 = pContainer.querySelector('tr:last-child>td:nth-child(2)>div');
+assert.equal(div2.classList[0], 'avatar-container');
-const imgs1 = div1.querySelectorAll("img");
+const imgs1 = div1.querySelectorAll('img');
assert.lengthOf(imgs1, 3);
-assert.equal(imgs1[0].src, "https://sea1.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/quincylarson/30/212400_2.png");
-assert.equal(imgs1[0].alt, "Quincy Larson");
-assert.equal(imgs1[1].src, "https://sea1.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/ilenia/30/270648_2.png");
-assert.equal(imgs1[1].alt, "Ilenia");
-assert.equal(imgs1[2].src, "https://sea1.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/jwilkins.oboe/30/179497_2.png");
-assert.equal(imgs1[2].alt, "Jessica Wilkins");
-
-const imgs2 = div2.querySelectorAll("img");
+assert.equal(
+ imgs1[0].src,
+ 'https://sea1.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/quincylarson/30/212400_2.png'
+);
+assert.equal(imgs1[0].alt, 'Quincy Larson');
+assert.equal(
+ imgs1[1].src,
+ 'https://sea1.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/ilenia/30/270648_2.png'
+);
+assert.equal(imgs1[1].alt, 'Ilenia');
+assert.equal(
+ imgs1[2].src,
+ 'https://sea1.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/jwilkins.oboe/30/179497_2.png'
+);
+assert.equal(imgs1[2].alt, 'Jessica Wilkins');
+
+const imgs2 = div2.querySelectorAll('img');
assert.lengthOf(imgs2, 1);
-assert.equal(imgs2[0].src, "https://sea1.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/ilenia/30/270648_2.png");
-assert.equal(imgs2[0].alt, "Ilenia");
+assert.equal(
+ imgs2[0].src,
+ 'https://sea1.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/ilenia/30/270648_2.png'
+);
+assert.equal(imgs2[0].alt, 'Ilenia');
```
-The third `td` element of each table row from the string returned by `showLatestPosts` should contain the number of replies to the post. *Hint:* use `posts_count - 1`.
+The third `td` element of each table row from the string returned by `showLatestPosts` should contain the number of replies to the post. _Hint:_ use `posts_count - 1`.
```js
const data = {
users: [
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/quincylarson/{size}/212400_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/quincylarson/{size}/212400_2.png',
id: 6,
- name: "Quincy Larson",
- username: "QuincyLarson"
+ name: 'Quincy Larson',
+ username: 'QuincyLarson'
},
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/jwilkins.oboe/{size}/179497_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/jwilkins.oboe/{size}/179497_2.png',
id: 285941,
- name: "Jessica Wilkins",
- username: "jwilkins.oboe"
+ name: 'Jessica Wilkins',
+ username: 'jwilkins.oboe'
},
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/ilenia/{size}/270648_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/ilenia/{size}/270648_2.png',
id: 170865,
- name: "Ilenia",
- username: "ilenia"
+ name: 'Ilenia',
+ username: 'ilenia'
}
],
topic_list: {
topics: [
{
- bumped_at: "2024-04-15T16:01:26.403Z",
+ bumped_at: '2024-04-15T16:01:26.403Z',
category_id: 1,
id: 684569,
- posters: [{user_id: 6}, {user_id: 170865}, {user_id: 285941}],
+ posters: [{ user_id: 6 }, { user_id: 170865 }, { user_id: 285941 }],
posts_count: 8,
- slug: "the-freecodecamp-podcast-is-back-now-with-video",
- title: "The freeCodeCamp Podcast is back – now with video",
+ slug: 'the-freecodecamp-podcast-is-back-now-with-video',
+ title: 'The freeCodeCamp Podcast is back – now with video',
views: 542
},
{
- bumped_at: "2024-04-19T13:52:03.523Z",
+ bumped_at: '2024-04-19T13:52:03.523Z',
category_id: 421,
id: 686149,
- posters: [{user_id: 170865}],
+ posters: [{ user_id: 170865 }],
posts_count: 1,
- slug: "problem-with-making-changes-to-styles-js",
- title: "Problem with making changes to styles. (JS)",
+ slug: 'problem-with-making-changes-to-styles-js',
+ title: 'Problem with making changes to styles. (JS)',
views: 9
}
]
}
-}
-const pContainer = document.getElementById("posts-container");
-pContainer.innerHTML = "";
+};
+const pContainer = document.getElementById('posts-container');
+pContainer.innerHTML = '';
showLatestPosts(data);
-assert.equal(pContainer.querySelector("tr:first-child>td:nth-child(3)").innerText, "7");
+assert.equal(
+ pContainer.querySelector('tr:first-child>td:nth-child(3)').innerText,
+ '7'
+);
-assert.equal(pContainer.querySelector("tr:last-child>td:nth-child(3)").innerText, "0");
+assert.equal(
+ pContainer.querySelector('tr:last-child>td:nth-child(3)').innerText,
+ '0'
+);
```
The fourth `td` element of each table row from the string returned by `showLatestPosts` should contain the number of views of the post.
@@ -764,56 +850,65 @@ The fourth `td` element of each table row from the string returned by `showLates
const data = {
users: [
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/quincylarson/{size}/212400_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/quincylarson/{size}/212400_2.png',
id: 6,
- name: "Quincy Larson",
- username: "QuincyLarson"
+ name: 'Quincy Larson',
+ username: 'QuincyLarson'
},
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/jwilkins.oboe/{size}/179497_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/jwilkins.oboe/{size}/179497_2.png',
id: 285941,
- name: "Jessica Wilkins",
- username: "jwilkins.oboe"
+ name: 'Jessica Wilkins',
+ username: 'jwilkins.oboe'
},
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/ilenia/{size}/270648_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/ilenia/{size}/270648_2.png',
id: 170865,
- name: "Ilenia",
- username: "ilenia"
+ name: 'Ilenia',
+ username: 'ilenia'
}
],
topic_list: {
topics: [
{
- bumped_at: "2024-04-15T16:01:26.403Z",
+ bumped_at: '2024-04-15T16:01:26.403Z',
category_id: 1,
id: 684569,
- posters: [{user_id: 6}, {user_id: 170865}, {user_id: 285941}],
+ posters: [{ user_id: 6 }, { user_id: 170865 }, { user_id: 285941 }],
posts_count: 8,
- slug: "the-freecodecamp-podcast-is-back-now-with-video",
- title: "The freeCodeCamp Podcast is back – now with video",
+ slug: 'the-freecodecamp-podcast-is-back-now-with-video',
+ title: 'The freeCodeCamp Podcast is back – now with video',
views: 542
},
{
- bumped_at: "2024-04-19T13:52:03.523Z",
+ bumped_at: '2024-04-19T13:52:03.523Z',
category_id: 421,
id: 686149,
- posters: [{user_id: 170865}],
+ posters: [{ user_id: 170865 }],
posts_count: 1,
- slug: "problem-with-making-changes-to-styles-js",
- title: "Problem with making changes to styles. (JS)",
+ slug: 'problem-with-making-changes-to-styles-js',
+ title: 'Problem with making changes to styles. (JS)',
views: 9
}
]
}
-}
-const pContainer = document.getElementById("posts-container");
-pContainer.innerHTML = "";
+};
+const pContainer = document.getElementById('posts-container');
+pContainer.innerHTML = '';
showLatestPosts(data);
-assert.equal(pContainer.querySelector("tr:first-child>td:nth-child(4)").innerText, "542");
+assert.equal(
+ pContainer.querySelector('tr:first-child>td:nth-child(4)').innerText,
+ '542'
+);
-assert.equal(pContainer.querySelector("tr:last-child>td:nth-child(4)").innerText, "9");
+assert.equal(
+ pContainer.querySelector('tr:last-child>td:nth-child(4)').innerText,
+ '9'
+);
```
The fifth `td` element of each table row from the string returned by `showLatestPosts` should contain time passed since the last activity, generated using the `timeAgo` function.
@@ -822,50 +917,53 @@ The fifth `td` element of each table row from the string returned by `showLatest
const data = {
users: [
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/quincylarson/{size}/212400_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/quincylarson/{size}/212400_2.png',
id: 6,
- name: "Quincy Larson",
- username: "QuincyLarson"
+ name: 'Quincy Larson',
+ username: 'QuincyLarson'
},
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/jwilkins.oboe/{size}/179497_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/jwilkins.oboe/{size}/179497_2.png',
id: 285941,
- name: "Jessica Wilkins",
- username: "jwilkins.oboe"
+ name: 'Jessica Wilkins',
+ username: 'jwilkins.oboe'
},
{
- avatar_template: "/user_avatar/forum.freecodecamp.org/ilenia/{size}/270648_2.png",
+ avatar_template:
+ '/user_avatar/forum.freecodecamp.org/ilenia/{size}/270648_2.png',
id: 170865,
- name: "Ilenia",
- username: "ilenia"
+ name: 'Ilenia',
+ username: 'ilenia'
}
],
topic_list: {
topics: [
{
- bumped_at: "2024-04-15T16:01:26.403Z",
+ bumped_at: '2024-04-15T16:01:26.403Z',
category_id: 1,
id: 684569,
- posters: [{user_id: 6}, {user_id: 170865}, {user_id: 285941}],
+ posters: [{ user_id: 6 }, { user_id: 170865 }, { user_id: 285941 }],
posts_count: 8,
- slug: "the-freecodecamp-podcast-is-back-now-with-video",
- title: "The freeCodeCamp Podcast is back – now with video",
+ slug: 'the-freecodecamp-podcast-is-back-now-with-video',
+ title: 'The freeCodeCamp Podcast is back – now with video',
views: 542
},
{
- bumped_at: "2024-04-19T13:52:03.523Z",
+ bumped_at: '2024-04-19T13:52:03.523Z',
category_id: 421,
id: 686149,
- posters: [{user_id: 170865}],
+ posters: [{ user_id: 170865 }],
posts_count: 1,
- slug: "problem-with-making-changes-to-styles-js",
- title: "Problem with making changes to styles. (JS)",
+ slug: 'problem-with-making-changes-to-styles-js',
+ title: 'Problem with making changes to styles. (JS)',
views: 9
}
]
}
-}
-const calcTime = (time) => {
+};
+const calcTime = time => {
const currentTime = new Date();
const lastPost = new Date(time);
const timeDifference = currentTime - lastPost;
@@ -875,13 +973,19 @@ const calcTime = (time) => {
const daysAgo = Math.floor(hoursAgo / 24);
return `${daysAgo}d ago`;
};
-const pContainer = document.getElementById("posts-container");
-pContainer.innerHTML = "";
+const pContainer = document.getElementById('posts-container');
+pContainer.innerHTML = '';
showLatestPosts(data);
-assert.equal(pContainer.querySelector("tr:first-child>td:nth-child(5)").innerText, calcTime("2024-04-15T16:01:26.403Z"));
+assert.equal(
+ pContainer.querySelector('tr:first-child>td:nth-child(5)').innerText,
+ calcTime('2024-04-15T16:01:26.403Z')
+);
-assert.equal(pContainer.querySelector("tr:last-child>td:nth-child(5)").innerText, calcTime("2024-04-19T13:52:03.523Z"));
+assert.equal(
+ pContainer.querySelector('tr:last-child>td:nth-child(5)').innerText,
+ calcTime('2024-04-19T13:52:03.523Z')
+);
```
# --seed--
@@ -889,7 +993,7 @@ assert.equal(pContainer.querySelector("tr:last-child>td:nth-child(5)").innerText
## --seed-contents--
```html
-
+
@@ -932,184 +1036,185 @@ assert.equal(pContainer.querySelector("tr:last-child>td:nth-child(5)").innerText
```css
* {
- margin: 0;
- padding: 0;
- box-sizing: border-box;
- }
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
- :root {
- --main-bg-color: #2a2a40;
- --black: #000;
- --dark-navy: #0a0a23;
- --dark-grey: #d0d0d5;
- --medium-grey: #dfdfe2;
- --light-grey: #f5f6f7;
- --peach: #f28373;
- --salmon-color: #f0aea9;
- --light-blue: #8bd9f6;
- --light-orange: #f8b172;
- --light-green: #93cb5b;
- --golden-yellow: #f1ba33;
- --gold: #f9aa23;
- --green: #6bca6b;
- }
+:root {
+ --main-bg-color: #2a2a40;
+ --black: #000;
+ --dark-navy: #0a0a23;
+ --dark-grey: #d0d0d5;
+ --medium-grey: #dfdfe2;
+ --light-grey: #f5f6f7;
+ --peach: #f28373;
+ --salmon-color: #f0aea9;
+ --light-blue: #8bd9f6;
+ --light-orange: #f8b172;
+ --light-green: #93cb5b;
+ --golden-yellow: #f1ba33;
+ --gold: #f9aa23;
+ --green: #6bca6b;
+}
- body {
- background-color: var(--main-bg-color);
- }
+body {
+ background-color: var(--main-bg-color);
+}
- nav {
- background-color: var(--dark-navy);
- padding: 10px 0;
- }
+nav {
+ background-color: var(--dark-navy);
+ padding: 10px 0;
+}
- .fcc-logo {
- width: 210px;
- display: block;
- margin: auto;
- }
+.fcc-logo {
+ width: 210px;
+ display: block;
+ margin: auto;
+}
- .title {
- margin: 25px 0;
- text-align: center;
- color: var(--light-grey);
- }
+.title {
+ margin: 25px 0;
+ text-align: center;
+ color: var(--light-grey);
+}
- .table-wrapper {
- padding: 0 25px;
- overflow-x: auto;
- }
+.table-wrapper {
+ padding: 0 25px;
+ overflow-x: auto;
+}
- table {
- width: 100%;
- color: var(--dark-grey);
- margin: auto;
- table-layout: fixed;
- border-collapse: collapse;
- overflow-x: scroll;
- }
+table {
+ width: 100%;
+ color: var(--dark-grey);
+ margin: auto;
+ table-layout: fixed;
+ border-collapse: collapse;
+ overflow-x: scroll;
+}
- #topics {
- text-align: start;
- width: 60%;
- }
+#topics {
+ text-align: start;
+ width: 60%;
+}
- th {
- border-bottom: 2px solid var(--dark-grey);
- padding-bottom: 10px;
- font-size: 1.3rem;
- }
+th {
+ border-bottom: 2px solid var(--dark-grey);
+ padding-bottom: 10px;
+ font-size: 1.3rem;
+}
- td:not(:first-child) {
- text-align: center;
- }
+td:not(:first-child) {
+ text-align: center;
+}
- td {
- border-bottom: 1px solid var(--dark-grey);
- padding: 20px 0;
- }
+td {
+ border-bottom: 1px solid var(--dark-grey);
+ padding: 20px 0;
+}
- .post-title {
- font-size: 1.2rem;
- color: var(--medium-grey);
- text-decoration: none;
- }
+.post-title {
+ font-size: 1.2rem;
+ color: var(--medium-grey);
+ text-decoration: none;
+}
- .category {
- padding: 3px;
- color: var(--black);
- text-decoration: none;
- display: block;
- width: fit-content;
- margin: 10px 0 10px;
- }
+.category {
+ padding: 3px;
+ color: var(--black);
+ text-decoration: none;
+ display: block;
+ width: fit-content;
+ margin: 10px 0 10px;
+}
- .career {
- background-color: var(--salmon-color);
- }
+.career {
+ background-color: var(--salmon-color);
+}
- .feedback,
- .html-css {
- background-color: var(--light-blue);
- }
+.feedback,
+.html-css {
+ background-color: var(--light-blue);
+}
- .support {
- background-color: var(--light-orange);
- }
+.support {
+ background-color: var(--light-orange);
+}
- .general {
- background-color: var(--light-green);
- }
+.general {
+ background-color: var(--light-green);
+}
- .javascript {
- background-color: var(--golden-yellow);
- }
+.javascript {
+ background-color: var(--golden-yellow);
+}
- .backend {
- background-color: var(--gold);
- }
+.backend {
+ background-color: var(--gold);
+}
- .python {
- background-color: var(--green);
- }
+.python {
+ background-color: var(--green);
+}
- .motivation {
- background-color: var(--peach);
- }
+.motivation {
+ background-color: var(--peach);
+}
- .avatar-container {
- display: flex;
- justify-content: center;
- gap: 10px;
- flex-wrap: wrap;
- }
+.avatar-container {
+ display: flex;
+ justify-content: center;
+ gap: 10px;
+ flex-wrap: wrap;
+}
- .avatar-container img {
- width: 30px;
- height: 30px;
- }
+.avatar-container img {
+ width: 30px;
+ height: 30px;
+}
- @media (max-width: 750px) {
- .table-wrapper {
- padding: 0 15px;
- }
+@media (max-width: 750px) {
+ .table-wrapper {
+ padding: 0 15px;
+ }
- table {
- width: 700px;
- }
+ table {
+ width: 700px;
+ }
- th {
- font-size: 1.2rem;
- }
+ th {
+ font-size: 1.2rem;
+ }
- .post-title {
- font-size: 1.1rem;
- }
+ .post-title {
+ font-size: 1.1rem;
}
+}
```
```js
-const forumLatest = "https://cdn.freecodecamp.org/curriculum/forum-latest/latest.json";
-const forumTopicUrl = "https://forum.freecodecamp.org/t/";
-const forumCategoryUrl = "https://forum.freecodecamp.org/c/";
-const avatarUrl = "https://sea1.discourse-cdn.com/freecodecamp";
+const forumLatest =
+ 'https://cdn.freecodecamp.org/curriculum/forum-latest/latest.json';
+const forumTopicUrl = 'https://forum.freecodecamp.org/t/';
+const forumCategoryUrl = 'https://forum.freecodecamp.org/c/';
+const avatarUrl = 'https://sea1.discourse-cdn.com/freecodecamp';
const allCategories = {
- 299: { category: "Career Advice", className: "career" },
- 409: { category: "Project Feedback", className: "feedback" },
- 417: { category: "freeCodeCamp Support", className: "support" },
- 421: { category: "JavaScript", className: "javascript" },
- 423: { category: "HTML - CSS", className: "html-css" },
- 424: { category: "Python", className: "python" },
- 432: { category: "You Can Do This!", className: "motivation" },
- 560: { category: "Backend Development", className: "backend" },
+ 299: { category: 'Career Advice', className: 'career' },
+ 409: { category: 'Project Feedback', className: 'feedback' },
+ 417: { category: 'freeCodeCamp Support', className: 'support' },
+ 421: { category: 'JavaScript', className: 'javascript' },
+ 423: { category: 'HTML - CSS', className: 'html-css' },
+ 424: { category: 'Python', className: 'python' },
+ 432: { category: 'You Can Do This!', className: 'motivation' },
+ 560: { category: 'Backend Development', className: 'backend' }
};
```
# --solutions--
```html
-
+
@@ -1152,182 +1257,183 @@ const allCategories = {
```css
* {
- margin: 0;
- padding: 0;
- box-sizing: border-box;
- }
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
- :root {
- --main-bg-color: #2a2a40;
- --black: #000;
- --dark-navy: #0a0a23;
- --dark-grey: #d0d0d5;
- --medium-grey: #dfdfe2;
- --light-grey: #f5f6f7;
- --peach: #f28373;
- --salmon-color: #f0aea9;
- --light-blue: #8bd9f6;
- --light-orange: #f8b172;
- --light-green: #93cb5b;
- --golden-yellow: #f1ba33;
- --gold: #f9aa23;
- --green: #6bca6b;
- }
+:root {
+ --main-bg-color: #2a2a40;
+ --black: #000;
+ --dark-navy: #0a0a23;
+ --dark-grey: #d0d0d5;
+ --medium-grey: #dfdfe2;
+ --light-grey: #f5f6f7;
+ --peach: #f28373;
+ --salmon-color: #f0aea9;
+ --light-blue: #8bd9f6;
+ --light-orange: #f8b172;
+ --light-green: #93cb5b;
+ --golden-yellow: #f1ba33;
+ --gold: #f9aa23;
+ --green: #6bca6b;
+}
- body {
- background-color: var(--main-bg-color);
- }
+body {
+ background-color: var(--main-bg-color);
+}
- nav {
- background-color: var(--dark-navy);
- padding: 10px 0;
- }
+nav {
+ background-color: var(--dark-navy);
+ padding: 10px 0;
+}
- .fcc-logo {
- width: 210px;
- display: block;
- margin: auto;
- }
+.fcc-logo {
+ width: 210px;
+ display: block;
+ margin: auto;
+}
- .title {
- margin: 25px 0;
- text-align: center;
- color: var(--light-grey);
- }
+.title {
+ margin: 25px 0;
+ text-align: center;
+ color: var(--light-grey);
+}
- .table-wrapper {
- padding: 0 25px;
- overflow-x: auto;
- }
+.table-wrapper {
+ padding: 0 25px;
+ overflow-x: auto;
+}
- table {
- width: 100%;
- color: var(--dark-grey);
- margin: auto;
- table-layout: fixed;
- border-collapse: collapse;
- overflow-x: scroll;
- }
+table {
+ width: 100%;
+ color: var(--dark-grey);
+ margin: auto;
+ table-layout: fixed;
+ border-collapse: collapse;
+ overflow-x: scroll;
+}
- #topics {
- text-align: start;
- width: 60%;
- }
+#topics {
+ text-align: start;
+ width: 60%;
+}
- th {
- border-bottom: 2px solid var(--dark-grey);
- padding-bottom: 10px;
- font-size: 1.3rem;
- }
+th {
+ border-bottom: 2px solid var(--dark-grey);
+ padding-bottom: 10px;
+ font-size: 1.3rem;
+}
- td:not(:first-child) {
- text-align: center;
- }
+td:not(:first-child) {
+ text-align: center;
+}
- td {
- border-bottom: 1px solid var(--dark-grey);
- padding: 20px 0;
- }
+td {
+ border-bottom: 1px solid var(--dark-grey);
+ padding: 20px 0;
+}
- .post-title {
- font-size: 1.2rem;
- color: var(--medium-grey);
- text-decoration: none;
- }
+.post-title {
+ font-size: 1.2rem;
+ color: var(--medium-grey);
+ text-decoration: none;
+}
- .category {
- padding: 3px;
- color: var(--black);
- text-decoration: none;
- display: block;
- width: fit-content;
- margin: 10px 0 10px;
- }
+.category {
+ padding: 3px;
+ color: var(--black);
+ text-decoration: none;
+ display: block;
+ width: fit-content;
+ margin: 10px 0 10px;
+}
- .career {
- background-color: var(--salmon-color);
- }
+.career {
+ background-color: var(--salmon-color);
+}
- .feedback,
- .html-css {
- background-color: var(--light-blue);
- }
+.feedback,
+.html-css {
+ background-color: var(--light-blue);
+}
- .support {
- background-color: var(--light-orange);
- }
+.support {
+ background-color: var(--light-orange);
+}
- .general {
- background-color: var(--light-green);
- }
+.general {
+ background-color: var(--light-green);
+}
- .javascript {
- background-color: var(--golden-yellow);
- }
+.javascript {
+ background-color: var(--golden-yellow);
+}
- .backend {
- background-color: var(--gold);
- }
+.backend {
+ background-color: var(--gold);
+}
- .python {
- background-color: var(--green);
- }
+.python {
+ background-color: var(--green);
+}
- .motivation {
- background-color: var(--peach);
- }
+.motivation {
+ background-color: var(--peach);
+}
- .avatar-container {
- display: flex;
- justify-content: center;
- gap: 10px;
- flex-wrap: wrap;
- }
+.avatar-container {
+ display: flex;
+ justify-content: center;
+ gap: 10px;
+ flex-wrap: wrap;
+}
- .avatar-container img {
- width: 30px;
- height: 30px;
- }
+.avatar-container img {
+ width: 30px;
+ height: 30px;
+}
- @media (max-width: 750px) {
- .table-wrapper {
- padding: 0 15px;
- }
+@media (max-width: 750px) {
+ .table-wrapper {
+ padding: 0 15px;
+ }
- table {
- width: 700px;
- }
+ table {
+ width: 700px;
+ }
- th {
- font-size: 1.2rem;
- }
+ th {
+ font-size: 1.2rem;
+ }
- .post-title {
- font-size: 1.1rem;
- }
+ .post-title {
+ font-size: 1.1rem;
}
+}
```
```js
-const forumLatest = "https://cdn.freecodecamp.org/curriculum/forum-latest/latest.json";
-const forumTopicUrl = "https://forum.freecodecamp.org/t/";
-const forumCategoryUrl = "https://forum.freecodecamp.org/c/";
-const avatarUrl = "https://sea1.discourse-cdn.com/freecodecamp";
+const forumLatest =
+ 'https://cdn.freecodecamp.org/curriculum/forum-latest/latest.json';
+const forumTopicUrl = 'https://forum.freecodecamp.org/t/';
+const forumCategoryUrl = 'https://forum.freecodecamp.org/c/';
+const avatarUrl = 'https://sea1.discourse-cdn.com/freecodecamp';
-const postsContainer = document.getElementById("posts-container");
+const postsContainer = document.getElementById('posts-container');
const allCategories = {
- 299: { category: "Career Advice", className: "career" },
- 409: { category: "Project Feedback", className: "feedback" },
- 417: { category: "freeCodeCamp Support", className: "support" },
- 421: { category: "JavaScript", className: "javascript" },
- 423: { category: "HTML - CSS", className: "html-css" },
- 424: { category: "Python", className: "python" },
- 432: { category: "You Can Do This!", className: "motivation" },
- 560: { category: "Backend Development", className: "backend" },
+ 299: { category: 'Career Advice', className: 'career' },
+ 409: { category: 'Project Feedback', className: 'feedback' },
+ 417: { category: 'freeCodeCamp Support', className: 'support' },
+ 421: { category: 'JavaScript', className: 'javascript' },
+ 423: { category: 'HTML - CSS', className: 'html-css' },
+ 424: { category: 'Python', className: 'python' },
+ 432: { category: 'You Can Do This!', className: 'motivation' },
+ 560: { category: 'Backend Development', className: 'backend' }
};
-const forumCategory = (id) => {
+const forumCategory = id => {
let selectedCategory = {};
if (allCategories.hasOwnProperty(id)) {
@@ -1336,8 +1442,8 @@ const forumCategory = (id) => {
selectedCategory.className = className;
selectedCategory.category = category;
} else {
- selectedCategory.className = "general";
- selectedCategory.category = "General";
+ selectedCategory.className = 'general';
+ selectedCategory.category = 'General';
selectedCategory.id = 1;
}
const url = `${forumCategoryUrl}${selectedCategory.className}/${id}`;
@@ -1349,7 +1455,7 @@ const forumCategory = (id) => {
`;
};
-const timeAgo = (time) => {
+const timeAgo = time => {
const currentTime = new Date();
const lastPost = new Date(time);
@@ -1371,7 +1477,7 @@ const timeAgo = (time) => {
return `${daysAgo}d ago`;
};
-const viewCount = (views) => {
+const viewCount = views => {
const thousands = Math.floor(views / 1000);
if (views >= 1000) {
@@ -1383,17 +1489,17 @@ const viewCount = (views) => {
const avatars = (posters, users) => {
return posters
- .map((poster) => {
- const user = users.find((user) => user.id === poster.user_id);
+ .map(poster => {
+ const user = users.find(user => user.id === poster.user_id);
if (user) {
const avatar = user.avatar_template.replace(/{size}/, 30);
- const userAvatarUrl = avatar.startsWith("/user_avatar/")
+ const userAvatarUrl = avatar.startsWith('/user_avatar/')
? avatarUrl.concat(avatar)
: avatar;
return ` `;
}
})
- .join("");
+ .join('');
};
const fetchData = async () => {
@@ -1408,23 +1514,24 @@ const fetchData = async () => {
fetchData();
-const showLatestPosts = (data) => {
+const showLatestPosts = data => {
const { topic_list, users } = data;
const { topics } = topic_list;
- postsContainer.innerHTML = topics.map((item) => {
- const {
- id,
- title,
- views,
- posts_count,
- slug,
- posters,
- category_id,
- bumped_at,
- } = item;
-
- return `
+ postsContainer.innerHTML = topics
+ .map(item => {
+ const {
+ id,
+ title,
+ views,
+ posts_count,
+ slug,
+ posters,
+ category_id,
+ bumped_at
+ } = item;
+
+ return `
@@ -1441,6 +1548,7 @@ const showLatestPosts = (data) => {
${viewCount(views)}
${timeAgo(bumped_at)}
`;
- }).join("");
+ })
+ .join('');
};
```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-football-team-cards/66e7ee20b79186306fc12da5.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-football-team-cards/66e7ee20b79186306fc12da5.md
index 64ab358966..109cefc3a3 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-football-team-cards/66e7ee20b79186306fc12da5.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-football-team-cards/66e7ee20b79186306fc12da5.md
@@ -1,7 +1,7 @@
---
id: 66e7ee20b79186306fc12da5
title: Build a Set of Football Team Cards
-challengeType: 14
+challengeType: 25
dashedName: lab-football-team-cards
demoType: onClick
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-fortune-teller/66c06d618d075c7f7f1b890a.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-fortune-teller/66c06d618d075c7f7f1b890a.md
index 8de41c0116..94e12db3d9 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-fortune-teller/66c06d618d075c7f7f1b890a.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-fortune-teller/66c06d618d075c7f7f1b890a.md
@@ -1,7 +1,7 @@
---
id: 66c06d618d075c7f7f1b890a
title: Build a Fortune Teller
-challengeType: 14
+challengeType: 25
dashedName: build-a-fortune-teller
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-gradebook-app/66bb6a9c2dd58b73cd759034.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-gradebook-app/66bb6a9c2dd58b73cd759034.md
index 7ca57f9a6c..89a48ea1e4 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-gradebook-app/66bb6a9c2dd58b73cd759034.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-gradebook-app/66bb6a9c2dd58b73cd759034.md
@@ -1,7 +1,7 @@
---
id: 66bb6a9c2dd58b73cd759034
title: Створіть застосунок залікову книжку
-challengeType: 14
+challengeType: 25
dashedName: build-a-gradebook-app
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-house-painting/66d6a7a3e1aa411e94bf2346.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-house-painting/66d6a7a3e1aa411e94bf2346.md
index 7941b925cc..b15c1b4457 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-house-painting/66d6a7a3e1aa411e94bf2346.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-house-painting/66d6a7a3e1aa411e94bf2346.md
@@ -1,7 +1,7 @@
---
id: 66d6a7a3e1aa411e94bf2346
title: Build a House Painting
-challengeType: 14
+challengeType: 25
dashedName: build-a-house-painting
demoType: onClick
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-inventory-management-program/66d75dd0aa65a71600dc669b.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-inventory-management-program/66d75dd0aa65a71600dc669b.md
index 914dd24c02..ad2449cebb 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-inventory-management-program/66d75dd0aa65a71600dc669b.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-inventory-management-program/66d75dd0aa65a71600dc669b.md
@@ -1,7 +1,7 @@
---
id: 66d75dd0aa65a71600dc669b
title: Build an Inventory Management Program
-challengeType: 14
+challengeType: 25
dashedName: build-an-inventory-management-program
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-javascript-trivia-bot/66ed41f912d0bb1dc62da5dd.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-javascript-trivia-bot/66ed41f912d0bb1dc62da5dd.md
index 1232d49d15..19acd2681a 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-javascript-trivia-bot/66ed41f912d0bb1dc62da5dd.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-javascript-trivia-bot/66ed41f912d0bb1dc62da5dd.md
@@ -1,7 +1,7 @@
---
id: 66ed41f912d0bb1dc62da5dd
title: Build a JavaScript Trivia Bot
-challengeType: 14
+challengeType: 25
dashedName: lab-javascript-trivia-bot
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-job-application-form/66faac4139dbbd5dd632c860.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-job-application-form/66faac4139dbbd5dd632c860.md
index 36aa23f2ba..dce680800f 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-job-application-form/66faac4139dbbd5dd632c860.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-job-application-form/66faac4139dbbd5dd632c860.md
@@ -1,7 +1,7 @@
---
id: 66faac4139dbbd5dd632c860
title: Build a Job Application Form
-challengeType: 14
+challengeType: 25
dashedName: lab-job-application-form
demoType: onClick
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-leap-year-calculator/66c06fad3475cd92421b9ac2.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-leap-year-calculator/66c06fad3475cd92421b9ac2.md
index 49d5d237d0..0c9edb15aa 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-leap-year-calculator/66c06fad3475cd92421b9ac2.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-leap-year-calculator/66c06fad3475cd92421b9ac2.md
@@ -1,7 +1,7 @@
---
id: 66c06fad3475cd92421b9ac2
title: Build a Leap Year Calculator
-challengeType: 14
+challengeType: 25
dashedName: build-a-leap-year-calculator
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-lightbox-viewer/66db57ad34c7089b9b41bfd6.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-lightbox-viewer/66db57ad34c7089b9b41bfd6.md
index 8b8ea35b23..497a418978 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-lightbox-viewer/66db57ad34c7089b9b41bfd6.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-lightbox-viewer/66db57ad34c7089b9b41bfd6.md
@@ -1,7 +1,7 @@
---
id: 66db57ad34c7089b9b41bfd6
title: Build a Lightbox Viewer
-challengeType: 14
+challengeType: 25
dashedName: build-a-lightbox-viewer
demoType: onClick
---
@@ -27,8 +27,8 @@ Fulfill the user stories below and get all the tests to pass to complete the lab
1. Your `.lightbox` element should have a fixed position so that the preview opens on top of the current images.
1. Your `.lightbox` element should cover the entire viewport by setting the height and width to 100% of the container. You should ensure that the lightbox element starts at the top left corner of the container.
1. `.lightbox` should have a background color. Initially, its `display` property should be set to `none` to hide it.
-1. When you click one of your `.gallery-item` elements, the `.lightbox` element’s `display` property should be set to `flex` to make `.lightbox` and the two elements within it visible.
-1. When you click one of your `.gallery-item` elements, the `#lightbox-image` element’s `src` should be set to a full-size version of the image clicked by removing `-thumbnail` from the image’s `src` attribute. The full-size images are located at the following links:
+1. When you click one of your `.gallery-item` elements, the `.lightbox` element's `display` property should be set to `flex` to make `.lightbox` and the two elements within it visible.
+1. When you click one of your `.gallery-item` elements, the `#lightbox-image` element's `src` should be set to a full-size version of the image clicked by removing `-thumbnail` from the image's `src` attribute. The full-size images are located at the following links:
- `https://cdn.freecodecamp.org/curriculum/labs/stonehenge.jpg`
- `https://cdn.freecodecamp.org/curriculum/labs/storm.jpg`
@@ -151,7 +151,7 @@ Your `.lightbox` element should be hidden initially.
assert.equal(new __helpers.CSSHelp(document).getStyle('.lightbox')?.display, 'none');
```
-When you click one of your `.gallery-item` elements, the `.lightbox` element’s `display` property should be set to `flex` to make to make `.lightbox` and the two elements within it visible.
+When you click one of your `.gallery-item` elements, the `.lightbox` element's `display` property should be set to `flex` to make to make `.lightbox` and the two elements within it visible.
```js
// Get the lightbox element
@@ -178,7 +178,7 @@ galleryItem.dispatchEvent(new Event('click'));
assert.strictEqual(getComputedDisplay(lightbox), 'flex');
```
-When you click one of your `.gallery-item` elements, the `#lightbox-image` element’s `src` should be set to a full-size version of the image clicked by removing `-thumbnail` from the image’s `src` attribute.
+When you click one of your `.gallery-item` elements, the `#lightbox-image` element's `src` should be set to a full-size version of the image clicked by removing `-thumbnail` from the image's `src` attribute.
```js
// Select gallery items and lightbox image element
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-lunch-picker-program/66db529d37ad966480ebb633.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-lunch-picker-program/66db529d37ad966480ebb633.md
index 43a1f20479..6c654480b2 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-lunch-picker-program/66db529d37ad966480ebb633.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-lunch-picker-program/66db529d37ad966480ebb633.md
@@ -1,7 +1,7 @@
---
id: 66db529d37ad966480ebb633
title: Build a Lunch Picker Program
-challengeType: 14
+challengeType: 25
dashedName: build-a-lunch-picker-program
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-markdown-to-html-converter/66f55eac933ff64ce654ca74.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-markdown-to-html-converter/66f55eac933ff64ce654ca74.md
index bf975090bd..b877f975f7 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-markdown-to-html-converter/66f55eac933ff64ce654ca74.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-markdown-to-html-converter/66f55eac933ff64ce654ca74.md
@@ -1,7 +1,7 @@
---
id: 66f55eac933ff64ce654ca74
title: Build a Markdown to HTML Converter
-challengeType: 14
+challengeType: 25
dashedName: build-a-markdown-to-html-converter
demoType: onClick
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-mood-board/673b3d6b7ef7318eef926d5a.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-mood-board/673b3d6b7ef7318eef926d5a.md
index 3a892ab0e3..9db0fcc7f9 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-mood-board/673b3d6b7ef7318eef926d5a.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-mood-board/673b3d6b7ef7318eef926d5a.md
@@ -1,7 +1,7 @@
---
id: 673b3d6b7ef7318eef926d5a
title: Build a Mood Board
-challengeType: 14
+challengeType: 25
dashedName: build-a-mood-board
demoType: onClick
---
@@ -36,20 +36,23 @@ You can use the following images in your Mood Board if you would like:
- `https://cdn.freecodecamp.org/curriculum/labs/santorini.jpg`
- `https://cdn.freecodecamp.org/curriculum/labs/pigeon.jpg`
-
# --hints--
You should export a `MoodBoardItem` component.
```js
-const mockedComponent = Enzyme.mount(React.createElement(window.index.MoodBoardItem));
+const mockedComponent = Enzyme.mount(
+ React.createElement(window.index.MoodBoardItem)
+);
assert.lengthOf(mockedComponent.find('MoodBoardItem'), 1);
```
Your `MoodBoardItem` component should return a `div` with a class of `mood-board-item` at its top-level element.
```js
-const mockedComponent = Enzyme.mount(React.createElement(window.index.MoodBoardItem));
+const mockedComponent = Enzyme.mount(
+ React.createElement(window.index.MoodBoardItem)
+);
assert.equal(mockedComponent.childAt(0).type(), 'div');
assert.isTrue(mockedComponent.childAt(0).hasClass('mood-board-item'));
```
@@ -57,16 +60,23 @@ assert.isTrue(mockedComponent.childAt(0).hasClass('mood-board-item'));
The background color of the `.mood-board-item` element should be set to the value of `color` prop using inline styles.
```js
-const mockedComponent = Enzyme.mount(React.createElement(window.index.MoodBoardItem));
-mockedComponent.setProps({ color: "colorValue" });
-assert.equal(mockedComponent.find('.mood-board-item').prop('style').backgroundColor, 'colorValue');
+const mockedComponent = Enzyme.mount(
+ React.createElement(window.index.MoodBoardItem)
+);
+mockedComponent.setProps({ color: 'colorValue' });
+assert.equal(
+ mockedComponent.find('.mood-board-item').prop('style').backgroundColor,
+ 'colorValue'
+);
```
Your `MoodBoardItem` component should render an `img` element with a class of `mood-board-image` and its `src` set to the value of the `image` prop.
```js
-const mockedComponent = Enzyme.mount(React.createElement(window.index.MoodBoardItem));
-mockedComponent.setProps({ image: "imageValue" });
+const mockedComponent = Enzyme.mount(
+ React.createElement(window.index.MoodBoardItem)
+);
+mockedComponent.setProps({ image: 'imageValue' });
const img = mockedComponent.find('img.mood-board-image');
assert.lengthOf(img, 1);
assert.equal(img.prop('src'), 'imageValue');
@@ -75,8 +85,10 @@ assert.equal(img.prop('src'), 'imageValue');
Your `MoodBoardItem` component should render an `h3` element with a class of `mood-board-text` and its text set to the value of the `description` prop.
```js
-const mockedComponent = Enzyme.mount(React.createElement(window.index.MoodBoardItem));
-mockedComponent.setProps({ description: "descriptionValue" });
+const mockedComponent = Enzyme.mount(
+ React.createElement(window.index.MoodBoardItem)
+);
+mockedComponent.setProps({ description: 'descriptionValue' });
const h3 = mockedComponent.find('h3.mood-board-text');
assert.lengthOf(h3, 1);
assert.equal(h3.text(), 'descriptionValue');
@@ -85,21 +97,27 @@ assert.equal(h3.text(), 'descriptionValue');
You should export a `MoodBoard` component.
```js
-const mockedComponent = Enzyme.mount(React.createElement(window.index.MoodBoard));
+const mockedComponent = Enzyme.mount(
+ React.createElement(window.index.MoodBoard)
+);
assert.lengthOf(mockedComponent.find('MoodBoard'), 1);
```
Your `MoodBoard` component should return a `div` as its top-level element.
```js
-const mockedComponent = Enzyme.mount(React.createElement(window.index.MoodBoard));
+const mockedComponent = Enzyme.mount(
+ React.createElement(window.index.MoodBoard)
+);
assert.equal(mockedComponent.childAt(0).type(), 'div');
```
Your `MoodBoard` component should render an `h1` element with a class of `mood-board-heading` and the text `Destination Mood Board`.
```js
-const mockedComponent = Enzyme.mount(React.createElement(window.index.MoodBoard));
+const mockedComponent = Enzyme.mount(
+ React.createElement(window.index.MoodBoard)
+);
const h1 = mockedComponent.find('h1.mood-board-heading');
assert.lengthOf(h1, 1);
assert.equal(h1.text(), 'Destination Mood Board');
@@ -108,9 +126,11 @@ assert.equal(h1.text(), 'Destination Mood Board');
Your `MoodBoard` component should render at least three `MoodBoardItem` components, each should pass `color`, `image`, and `description` props with valid values.
```js
-const mockedComponent = Enzyme.mount(React.createElement(window.index.MoodBoard));
+const mockedComponent = Enzyme.mount(
+ React.createElement(window.index.MoodBoard)
+);
const mbItems = mockedComponent.find(window.index.MoodBoardItem);
-assert.isAtLeast(mbItems.length, 3)
+assert.isAtLeast(mbItems.length, 3);
const propsList = mbItems.map(item => item.props());
propsList.forEach(({ color, image, description }) => {
assert.isAtLeast(color.length, 1);
@@ -122,7 +142,9 @@ propsList.forEach(({ color, image, description }) => {
Your `MoodBoard` component should be rendered to the page's `#root` element.
```js
-const mockedComponent = Enzyme.mount(React.createElement(window.index.MoodBoard));
+const mockedComponent = Enzyme.mount(
+ React.createElement(window.index.MoodBoard)
+);
assert.equal(mockedComponent.html(), document.getElementById('root').innerHTML);
```
@@ -131,85 +153,83 @@ assert.equal(mockedComponent.html(), document.getElementById('root').innerHTML);
## --seed-contents--
```html
-
+
-
-
+
Mood Board
-
+
-
+
-
-
+
```
```css
body {
- background-color: #ffffcc;
+ background-color: #ffffcc;
}
.mood-board-heading {
- text-align: center;
- font-size: 2.5em;
- color: #333;
- margin-top: 20px;
+ text-align: center;
+ font-size: 2.5em;
+ color: #333;
+ margin-top: 20px;
}
.mood-board {
- display: grid;
- grid-template-columns: repeat(3, 1fr);
- gap: 20px;
- padding: 20px;
- max-width: 900px;
- margin: 0 auto;
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 20px;
+ padding: 20px;
+ max-width: 900px;
+ margin: 0 auto;
}
.mood-board-item {
- border-radius: 10px;
- padding: 10px;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- color: #fff;
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
- text-align: center;
- height: 250px;
+ border-radius: 10px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ color: #fff;
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
+ text-align: center;
+ height: 250px;
}
.mood-board-image {
- border-radius: 5px;
- width: 180px;
- height:150px;
- object-fit: cover;
+ border-radius: 5px;
+ width: 180px;
+ height: 150px;
+ object-fit: cover;
}
.mood-board-text {
- margin-top: 20px;
- font-size: 1.2em;
+ margin-top: 20px;
+ font-size: 1.2em;
}
```
@@ -220,94 +240,92 @@ body {
# --solutions--
```html
-
+
-
-
+
Mood Board
-
+
-
+
-
-
+
```
```css
body {
- background-color: #ffffcc;
+ background-color: #ffffcc;
}
.mood-board-heading {
- text-align: center;
- font-size: 2.5em;
- color: #333;
- margin-top: 20px;
+ text-align: center;
+ font-size: 2.5em;
+ color: #333;
+ margin-top: 20px;
}
.mood-board {
- display: grid;
- grid-template-columns: repeat(3, 1fr);
- gap: 20px;
- padding: 20px;
- max-width: 900px;
- margin: 0 auto;
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 20px;
+ padding: 20px;
+ max-width: 900px;
+ margin: 0 auto;
}
.mood-board-item {
- border-radius: 10px;
- padding: 10px;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- color: #fff;
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
- text-align: center;
- height: 250px;
+ border-radius: 10px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ color: #fff;
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
+ text-align: center;
+ height: 250px;
}
.mood-board-image {
- border-radius: 5px;
- width: 180px;
- height:150px;
- object-fit: cover;
+ border-radius: 5px;
+ width: 180px;
+ height: 150px;
+ object-fit: cover;
}
.mood-board-text {
- margin-top: 20px;
- font-size: 1.2em;
+ margin-top: 20px;
+ font-size: 1.2em;
}
```
```jsx
export function MoodBoardItem(props) {
return (
-
-
-
{props.description}
+
+
+
{props.description}
);
}
@@ -315,37 +333,37 @@ export function MoodBoardItem(props) {
export function MoodBoard() {
return (
-
Destination Mood Board
-
+
Destination Mood Board
+
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-moon-orbit/66a37f37ef5823a313de8c26.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-moon-orbit/66a37f37ef5823a313de8c26.md
index 1cceae4cd5..2b3e79f21b 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-moon-orbit/66a37f37ef5823a313de8c26.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-moon-orbit/66a37f37ef5823a313de8c26.md
@@ -1,7 +1,7 @@
---
id: 66a37f37ef5823a313de8c26
title: Build a Moon Orbit
-challengeType: 14
+challengeType: 25
dashedName: build-a-moon-orbit
demoType: onClick
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-newspaper-article/66ba762af611169359d9d369.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-newspaper-article/66ba762af611169359d9d369.md
index 92fca2c445..ced22714db 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-newspaper-article/66ba762af611169359d9d369.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-newspaper-article/66ba762af611169359d9d369.md
@@ -1,7 +1,7 @@
---
id: 66ba762af611169359d9d369
title: Build a Newspaper Article
-challengeType: 14
+challengeType: 25
dashedName: build-a-newspaper-article
demoType: onClick
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-page-of-playing-cards/66be24cb4144f955b6bcc550.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-page-of-playing-cards/66be24cb4144f955b6bcc550.md
index 0f0d6c19bb..5452c51039 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-page-of-playing-cards/66be24cb4144f955b6bcc550.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-page-of-playing-cards/66be24cb4144f955b6bcc550.md
@@ -1,7 +1,7 @@
---
id: 66be24cb4144f955b6bcc550
title: Build a Page of Playing Cards
-challengeType: 14
+challengeType: 25
dashedName: build-a-page-of-playing-cards
demoType: onClick
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-palindrome-checker/657bdc55a322aae1eac3838f.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-palindrome-checker/657bdc55a322aae1eac3838f.md
index 0adf743042..3cc6d349d3 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-palindrome-checker/657bdc55a322aae1eac3838f.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-palindrome-checker/657bdc55a322aae1eac3838f.md
@@ -1,7 +1,7 @@
---
id: 657bdc55a322aae1eac3838f
title: Створіть перевірку паліндрома
-challengeType: 14
+challengeType: 25
dashedName: build-a-palindrome-checker
demoType: onClick
---
@@ -25,12 +25,12 @@ Fulfill the user stories below and get all the tests to pass to complete the lab
1. Якщо елемент `#text-input` містить текст `_eye` та натиснути на елемент `#check-btn`, то елемент `#result` повинен містити текст `"_eye is a palindrome"`.
1. Якщо елемент `#text-input` містить текст `race car` та натиснути на елемент `#check-btn`, то елемент `#result` повинен містити текст `"race car is a palindrome"`.
1. Якщо елемент `#text-input` містить текст `not a palindrome` та натиснути на елемент `#check-btn`, то елемент `#result` повинен містити текст `"not a palindrome is not a palindrome"`.
-1. Якщо елемент `#text-input` містить текст `A man, a plan, a canal. Panama` та натиснути на елемент `#check-btn`, то елемент `#result` повинен містити текст `"A man, a plan, a canal. Panama is a palindrome"`.
+1. When the `#text-input` element contains the text `A man, a plan, a canal. Panama` and the `#check-btn` element is clicked, the `#result` element should contain the text `"A man, a plan, a canal. Panama is a palindrome"`.
1. Якщо елемент `#text-input` містить текст `never odd or even` та натиснути на елемент `#check-btn`, то елемент `#result` повинен містити текст `"never odd or even is a palindrome"`.
1. Якщо елемент `#text-input` містить текст `nope` та натиснути на елемент `#check-btn`, то елемент `#result` повинен містити текст `"nope is not a palindrome"`.
1. Якщо елемент `#text-input` містить текст `almostomla` та натиснути на елемент `#check-btn`, то елемент `#result` повинен містити текст `"almostomla is not a palindrome"`.
1. Якщо елемент `#text-input` містить текст `My age is 0, 0 si ega ym.` та натиснути на елемент `#check-btn`, то елемент `#result` повинен містити текст `"My age is 0, 0 si ega ym. is a palindrome"`.
-1. Якщо елемент `#text-input` містить текст `1 eye for of 1 eye.` та натиснути на елемент `#check-btn`, то елемент `#result` повинен містити текст `"1 eye for of 1 eye. is not a palindrome"`.
+1. When the `#text-input` element contains the text `1 eye for of 1 eye.` and the `#check-btn` element is clicked, the `#result` element should contain the text `"1 eye for of 1 eye. is not a palindrome"`.
1. Якщо елемент `#text-input` містить текст `0_0 (: /-\ :) 0-0` та натиснути на елемент `#check-btn`, то елемент `#result` повинен містити текст `"0_0 (: /-\ :) 0-0 is a palindrome"`.
1. Якщо елемент `#text-input` містить текст `five|\_/|four` та натиснути на елемент `#check-btn`, то елемент `#result` повинен містити текст `"five|\_/|four is not a palindrome"`.
@@ -136,7 +136,7 @@ checkBtn.click();
assert.strictEqual(resultEl.innerText.trim().replace(/[.,?!]+$/g, '').toLowerCase(), 'not a palindrome is not a palindrome');
```
-Якщо елемент `#text-input` містить текст `A man, a plan, a canal. Panama` та натиснути на елемент `#check-btn`, то елемент `#result` повинен містити текст `"A man, a plan, a canal. Panama is a palindrome"`.
+When the `#text-input` element contains the text `A man, a plan, a canal. Panama` and the `#check-btn` element is clicked, the `#result` element should contain the text `"A man, a plan, a canal. Panama is a palindrome"`.
```js
const inputEl = document.getElementById('text-input');
@@ -201,7 +201,7 @@ checkBtn.click();
assert.strictEqual(resultEl.innerText.trim().replace(/[.,?!]+$/g, '').toLowerCase(), 'my age is 0, 0 si ega ym. is a palindrome');
```
-Якщо елемент `#text-input` містить текст `1 eye for of 1 eye.` та натиснути на елемент `#check-btn`, то елемент `#result` повинен містити текст `"1 eye for of 1 eye. is not a palindrome"`.
+When the `#text-input` element contains the text `1 eye for of 1 eye.` and the `#check-btn` element is clicked, the `#result` element should contain the text `"1 eye for of 1 eye. is not a palindrome"`.
```js
const inputEl = document.getElementById('text-input');
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-password-generator/66f53dc2c5bd6a11d6c3282f.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-password-generator/66f53dc2c5bd6a11d6c3282f.md
new file mode 100644
index 0000000000..d5e93675f7
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-password-generator/66f53dc2c5bd6a11d6c3282f.md
@@ -0,0 +1,116 @@
+---
+id: 66f53dc2c5bd6a11d6c3282f
+title: Build a Password Generator App
+challengeType: 25
+dashedName: lab-password-generator
+---
+
+# --description--
+
+In this lab, you'll practice using functions by building a random password generator.
+
+**Objective:** Fulfill the user stories below and get all the tests to pass to complete the lab.
+
+**User Stories:**
+
+1. You should create a function called `generatePassword` that takes a parameter. You can name the parameter whatever you like.
+2. Your function should return a string which represents a randomly generated password. You should use the following string and different `Math` methods to help you return a new string with random characters in it: `ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()`.
+3. You should define a variable called `password` and assign it the result of calling the `generatePassword` function with a numeric argument that represents the desired password length.
+4. You should have a `console.log` that logs the message `"Generated password:"` followed by the `password` variable.
+
+# --hints--
+
+You should have a `generatePassword` function with a parameter. You can name the parameter whatever you like.
+
+```js
+assert.isFunction(generatePassword);
+assert.lengthOf(generatePassword, 1);
+```
+
+Your `generatePassword` function should return a string.
+
+```js
+const result = generatePassword(5);
+assert.isString(result);
+```
+
+Your `generatePassword` function should return a new string that is the correct length.
+
+```js
+const length = 8;
+const password = generatePassword(length);
+assert.lengthOf(password, length);
+```
+
+Your function should return a randomly generated password with valid characters.
+
+```js
+const validChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()";
+const password = generatePassword(10);
+for (let char of password) {
+ assert.include(validChars, char);
+}
+```
+
+Your function should return a new random string each time it is called.
+
+```js
+const password1 = generatePassword(10);
+const password2 = generatePassword(10);
+assert.notStrictEqual(password1, password2);
+```
+
+You should have a `password` variable.
+
+```js
+assert.isDefined(password);
+```
+
+Your `password` variable should be a string.
+
+```js
+assert.isString(password);
+```
+
+You should call the `generatePassword` function with a numeric argument and store the returned password in the `password` variable.
+
+```js
+assert.isDefined(password);
+assert.isString(password);
+const testLength = password.length;
+assert.strictEqual(password.length, testLength);
+assert.match(password, /^[A-Za-z0-9!@#$%^&*()]+$/);
+```
+
+You should log the generated password to the console.
+
+```js
+const condition1 = /console\.log\(\s*["']Generated\s+password:\s*["']\s*\+\s*password\s*\);?/gm.test(code);
+const condition2 = /console\.log\(\s*`Generated\s+password:\s*\$\{password\}`\s*\);?/gm.test(code);
+assert.isTrue(condition1 || condition2);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```js
+
+```
+
+# --solutions--
+
+```js
+const generatePassword = (length) => {
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()";
+ let password = "";
+ for (let i = 0; i < length; i++) {
+ const randomIndex = Math.floor(Math.random() * chars.length);
+ password += chars[randomIndex];
+ }
+ return password;
+};
+
+const password = generatePassword(12);
+console.log(`Generated password: ${password}`);
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-permutation-generator/66fe4f33a2cc9b33f4d5cd9b.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-permutation-generator/66fe4f33a2cc9b33f4d5cd9b.md
index 6b563b0a9e..c9e1b257c2 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-permutation-generator/66fe4f33a2cc9b33f4d5cd9b.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-permutation-generator/66fe4f33a2cc9b33f4d5cd9b.md
@@ -1,7 +1,7 @@
---
id: 66fe4f33a2cc9b33f4d5cd9b
title: Build a Permutation Generator
-challengeType: 14
+challengeType: 25
dashedName: build-a-permutation-generator
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-personal-portfolio/bd7158d8c242eddfaeb5bd13.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-personal-portfolio/bd7158d8c242eddfaeb5bd13.md
index 4f09bb9f5b..63bc10c871 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-personal-portfolio/bd7158d8c242eddfaeb5bd13.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-personal-portfolio/bd7158d8c242eddfaeb5bd13.md
@@ -1,7 +1,7 @@
---
id: bd7158d8c242eddfaeb5bd13
title: Створіть особисте портфоліо
-challengeType: 14
+challengeType: 25
dashedName: build-a-personal-portfolio
demoType: onClick
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-product-landing-page/587d78af367417b2b2512b04.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-product-landing-page/587d78af367417b2b2512b04.md
index cc20e9a903..e1b0717648 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-product-landing-page/587d78af367417b2b2512b04.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-product-landing-page/587d78af367417b2b2512b04.md
@@ -1,7 +1,7 @@
---
id: 587d78af367417b2b2512b04
title: Створіть посадкову сторінку продукту
-challengeType: 14
+challengeType: 25
dashedName: build-a-product-landing-page
demoType: onClick
---
@@ -63,7 +63,7 @@ assert.exists(el);
assert.exists(el.src);
```
-Значення `src` вашого `#header-img` повинне бути активним URL (починається з `http`).
+Your `#header-img`'s `src` value should be a valid URL (starts with `http`).
```js
const el = document.getElementById('header-img');
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-project-idea-board/67051431a73f1ca25d9a6f25.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-project-idea-board/67051431a73f1ca25d9a6f25.md
index a1d4053caa..493cc70725 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-project-idea-board/67051431a73f1ca25d9a6f25.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-project-idea-board/67051431a73f1ca25d9a6f25.md
@@ -1,7 +1,7 @@
---
id: 67051431a73f1ca25d9a6f25
title: Build a Project Idea Board
-challengeType: 14
+challengeType: 25
dashedName: build-a-project-idea-board
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-pyramid-generator/66f2836c459cfb16ae76f24f.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-pyramid-generator/66f2836c459cfb16ae76f24f.md
index 3cd8457c6f..189f3336de 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-pyramid-generator/66f2836c459cfb16ae76f24f.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-pyramid-generator/66f2836c459cfb16ae76f24f.md
@@ -1,7 +1,7 @@
---
id: 66f2836c459cfb16ae76f24f
title: Побудуйте генератор пірамід
-challengeType: 14
+challengeType: 25
dashedName: lab-pyramid-generator
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-quiz-game/66f17db06803d11a1bd19a20.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-quiz-game/66f17db06803d11a1bd19a20.md
index bfc28c4ebf..99f8c9834f 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-quiz-game/66f17db06803d11a1bd19a20.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-quiz-game/66f17db06803d11a1bd19a20.md
@@ -1,7 +1,7 @@
---
id: 66f17db06803d11a1bd19a20
title: Build a Quiz Game
-challengeType: 14
+challengeType: 25
dashedName: lab-quiz-game
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-random-background-color-changer/66b62d0ad68488dd76228d6c.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-random-background-color-changer/66b62d0ad68488dd76228d6c.md
index 968e9da6ed..47de9cb1fe 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-random-background-color-changer/66b62d0ad68488dd76228d6c.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-random-background-color-changer/66b62d0ad68488dd76228d6c.md
@@ -1,7 +1,7 @@
---
id: 66b62d0ad68488dd76228d6c
title: Debug a Random Background Color Changer
-challengeType: 14
+challengeType: 25
dashedName: debug-a-random-background-color-changer
demoType: onClick
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-real-time-counter/66bb3e20d3dc5b6d0a21f5dd.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-real-time-counter/66bb3e20d3dc5b6d0a21f5dd.md
index e6974995a9..6f92a069c9 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-real-time-counter/66bb3e20d3dc5b6d0a21f5dd.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-real-time-counter/66bb3e20d3dc5b6d0a21f5dd.md
@@ -1,7 +1,7 @@
---
id: 66bb3e20d3dc5b6d0a21f5dd
title: Build a Real Time Counter
-challengeType: 14
+challengeType: 25
dashedName: build-a-real-time-counter
demoType: onClick
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-recipe-page/668f08ea07b99b1f4a91acab.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-recipe-page/668f08ea07b99b1f4a91acab.md
index e16007c7b4..a643ee5f60 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-recipe-page/668f08ea07b99b1f4a91acab.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-recipe-page/668f08ea07b99b1f4a91acab.md
@@ -1,7 +1,7 @@
---
id: 668f08ea07b99b1f4a91acab
title: Build a Recipe Page
-challengeType: 14
+challengeType: 25
dashedName: build-a-recipe-page
demoType: onClick
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-regex-sandbox/66e028680eca7d21db7e1aee.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-regex-sandbox/66e028680eca7d21db7e1aee.md
index a9ac1ebabd..95b604e3b8 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-regex-sandbox/66e028680eca7d21db7e1aee.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-regex-sandbox/66e028680eca7d21db7e1aee.md
@@ -1,7 +1,7 @@
---
id: 66e028680eca7d21db7e1aee
title: Побудуйте пісочницю регулярних виразів
-challengeType: 14
+challengeType: 25
dashedName: lab-regex-sandbox
demoType: onClick
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-reusable-footer/673b02b03134b04637bf7055.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-reusable-footer/673b02b03134b04637bf7055.md
index 39886846a1..d7f946044f 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-reusable-footer/673b02b03134b04637bf7055.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-reusable-footer/673b02b03134b04637bf7055.md
@@ -1,7 +1,7 @@
---
id: 673b02b03134b04637bf7055
title: Build a Reusable Footer
-challengeType: 14
+challengeType: 25
dashedName: build-a-reusable-footer
demoType: onClick
---
@@ -32,22 +32,29 @@ assert.lengthOf(mockedComponent.find('Footer'), 1);
Your `Footer` component should return a `footer` element.
```js
-assert.equal(Enzyme.shallow(React.createElement(window.index.Footer)).type(), 'footer');
+assert.equal(
+ Enzyme.shallow(React.createElement(window.index.Footer)).type(),
+ 'footer'
+);
```
Your `footer` should have at least three unordered lists.
```js
-const mockedComponent = Enzyme.shallow(React.createElement(window.index.Footer));
+const mockedComponent = Enzyme.shallow(
+ React.createElement(window.index.Footer)
+);
assert.isAtLeast(mockedComponent.find('ul').length, 3);
```
Each of your unordered lists should have at least two list items.
```js
-const mockedComponent = Enzyme.shallow(React.createElement(window.index.Footer));
+const mockedComponent = Enzyme.shallow(
+ React.createElement(window.index.Footer)
+);
const uls = mockedComponent.find('ul');
-uls.forEach(ul => {
+uls.forEach(ul => {
assert.isAtLeast(ul.find('li').length, 2);
});
@@ -57,17 +64,21 @@ assert.isAtLeast(uls.length, 1);
Your `footer` should have at least one paragraph element.
```js
-const mockedComponent = Enzyme.shallow(React.createElement(window.index.Footer));
+const mockedComponent = Enzyme.shallow(
+ React.createElement(window.index.Footer)
+);
assert.isAtLeast(mockedComponent.find('p').length, 1);
```
You should have a copyright (`©`) symbol within one of your paragraphs.
```js
-const mockedComponent = Enzyme.shallow(React.createElement(window.index.Footer));
+const mockedComponent = Enzyme.shallow(
+ React.createElement(window.index.Footer)
+);
let hasCopyright = false;
mockedComponent.find('p').forEach(p => {
- if(p.text().includes('©')) {
+ if (p.text().includes('©')) {
hasCopyright = true;
}
});
@@ -77,14 +88,18 @@ assert.isTrue(hasCopyright);
Your `footer` should have at least three links with the `href` value set to `#`.
```js
-const mockedComponent = Enzyme.shallow(React.createElement(window.index.Footer));
+const mockedComponent = Enzyme.shallow(
+ React.createElement(window.index.Footer)
+);
assert.isAtLeast(mockedComponent.find('a[href="#"]').length, 3);
```
None of your links should be empty.
```js
-const mockedComponent = Enzyme.shallow(React.createElement(window.index.Footer));
+const mockedComponent = Enzyme.shallow(
+ React.createElement(window.index.Footer)
+);
mockedComponent.find('a').forEach(a => {
assert.isAtLeast(a.text().length, 1);
});
@@ -103,38 +118,34 @@ assert.equal(mockedComponent.html(), document.getElementById('root').innerHTML);
## --seed-contents--
```html
-
+
-
-
+
Reusable Footer Component
-
+
-
+
-
-
+
```
@@ -143,132 +154,139 @@ assert.equal(mockedComponent.html(), document.getElementById('root').innerHTML);
```
```jsx
-export const Footer = () => {
-
-};
+export const Footer = () => {};
```
# --solutions--
```html
-
+
-
-
+
Reusable Footer Component
-
+
-
+
-
-
+
```
```css
.footer {
- background-color: #e3e1eb;
- padding: 20px;
- text-align: center;
- border-top: 1px solid #e5e7eb;
- font-family: Arial, sans-serif;
+ background-color: #e3e1eb;
+ padding: 20px;
+ text-align: center;
+ border-top: 1px solid #e5e7eb;
+ font-family: Arial, sans-serif;
}
.footer-section {
- display: grid;
- grid-template-columns: repeat(3, 1fr);
- gap: 20px;
- justify-content: center;
- margin-bottom: 20px;
- align-items: center;
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 20px;
+ justify-content: center;
+ margin-bottom: 20px;
+ align-items: center;
}
.footer ul {
- list-style: none;
- padding: 0;
- margin: 0;
+ list-style: none;
+ padding: 0;
+ margin: 0;
}
.footer li {
- margin-bottom: 10px;
+ margin-bottom: 10px;
}
.footer a {
- text-decoration: none;
- color: #1f2937;
+ text-decoration: none;
+ color: #1f2937;
}
.footer a:hover {
- color: #6366f1;
+ color: #6366f1;
}
.footer p {
- color: #6b7280;
- margin-top: 20px;
+ color: #6b7280;
+ margin-top: 20px;
}
.footer-icons {
- margin-top: 20px;
- display: flex;
- justify-content: center;
+ margin-top: 20px;
+ display: flex;
+ justify-content: center;
}
.footer-icons a {
- margin: 0 10px;
- font-size: 24px;
- color: #6b7280;
- text-decoration: none;
+ margin: 0 10px;
+ font-size: 24px;
+ color: #6b7280;
+ text-decoration: none;
}
.footer-icons a:hover {
- color: #6366f1;
+ color: #6366f1;
}
```
```jsx
-export const Footer = () =>
-
+export const Footer = () => (
+
+);
```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-sentence-maker/66c057041df6394ca796bf33.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-sentence-maker/66c057041df6394ca796bf33.md
index 874c6c4cbb..7036316d31 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-sentence-maker/66c057041df6394ca796bf33.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-sentence-maker/66c057041df6394ca796bf33.md
@@ -1,7 +1,7 @@
---
id: 66c057041df6394ca796bf33
title: Build a Sentence Maker
-challengeType: 14
+challengeType: 25
dashedName: build-a-sentence-maker
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-sorting-visualizer/6716249b5405164036fd0b0d.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-sorting-visualizer/6716249b5405164036fd0b0d.md
new file mode 100644
index 0000000000..93220c7534
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-sorting-visualizer/6716249b5405164036fd0b0d.md
@@ -0,0 +1,580 @@
+---
+id: 6716249b5405164036fd0b0d
+title: Build a Sorting Visualizer
+challengeType: 25
+dashedName: build-a-sorting-visualizer
+demoType: onClick
+---
+
+# --description--
+
+The Bubble Sort algorithm sorts a sequence of integers by comparing couples of adjacent elements starting from the beginning of the sequence. If the first element is greater than the second one, it swaps them. Then, it proceeds with the following couple. When the sequence ends, it starts a new cycle from the beginning of the sequence, and repeats the process until the elements are sorted.
+
+For this lab, you have been provided with all the HTML and CSS. You will use JavaScript to complete the Bubble Sort Visualizer so that it visualizes each step needed by the Bubble Sort algorithm to sort an array of five integers.
+
+Fulfill the user stories below and get all the tests to pass to complete the lab.
+
+**User Stories:**
+
+1. You should have a function named `generateElement` that returns a random integer between `1` and `100`, inclusive.
+1. You should have a function named `generateArray` that uses the `generateElement` function to return an array containing five random integers.
+1. You should have a function named `generateContainer` that creates and returns an empty `div` element.
+1. You should have a function named `fillArrContainer` that takes an HTML element as the first argument and an array as the second argument.
+1. The `fillArrContainer` function should fill the element passed as the first argument to the function with five `span` elements with the text of an integer from the array passed as the second argument to the function.
+1. You should have a function named `isOrdered` that takes two integers and returns a boolean indicating if the first integer is less than or equal to the second.
+1. You should have a function named `swapElements` that takes an array of integers and a numeric index.
+1. The `swapElements` function should modify the array in place by swapping the element at the passed index and the following element if `isOrdered` returns `false`.
+1. You should have a function named `highlightCurrentEls` that takes an HTML element and a numeric index.
+1. The `highlightCurrentEls` function should set the `border` of the given element's child at the given index, and the child immediately after the index, to have a `dashed` style, a `red` color, and a width of your choice.
+1. When you click `#generate-btn` you should use the `fillArrContainer` function to fill `#starting-array` with five `span` elements, each with a random number as its text.
+1. You should implement the Bubble Sort algorithm so that after you click `#sort-btn`, `#array-container` contains a `div` element for each of the steps required by the Bubble Sort algorithm to sort the starting array, including the `div` representing the starting array and a `div` representing the sorted array. The functions you have created so far can be useful here.
+1. Each `div` should contain five `span` elements, representing the array in its current state of being sorted.
+1. After you click `#sort-btn`, `#starting-array` should represent the starting step with the initial array and the first two integers highlighted.
+1. For each sorting step, you should use `highlightCurrentEls` to highlight the two numbers that are being compared, and swap them in the next step by using `swapElements`.
+
+# --hints--
+
+You should have a function named `generateElement`.
+
+```js
+assert.isFunction(generateElement);
+```
+
+Your `generateElement` function should return a random integer between `1` and `100` inclusive.
+
+```js
+const randomMocker = new __helpers.RandomMocker();
+randomMocker.mock();
+try {
+ assert.strictEqual(generateElement(), 26);
+ assert.strictEqual(generateElement(), 9);
+} finally {
+ randomMocker.restore();
+}
+```
+
+You should have a function named `generateArray`.
+
+```js
+assert.isFunction(generateArray)
+```
+
+Your `generateArray` function should make use of the `generateElement` function.
+
+```js
+let flag = false;
+const temp = generateElement;
+generateElement = () => flag = true;
+try {
+ generateArray();
+ assert.isTrue(flag);
+} finally {
+ generateElement = temp;
+}
+```
+
+Your `generateArray` function should return an array containing five random integers between `1` and `100`.
+
+```js
+const randomMocker = new __helpers.RandomMocker();
+randomMocker.mock();
+try {
+ assert.deepEqual(generateArray(), [26, 9, 58, 23, 38])
+} finally {
+ randomMocker.restore();
+}
+```
+
+You should have a function named `generateContainer`.
+
+```js
+assert.isFunction(generateContainer);
+```
+
+Your `generateContainer` function should return an empty `div` element.
+
+```js
+const div = generateContainer();
+assert.equal(div.tagName, "DIV");
+assert.isEmpty(div.children);
+```
+
+You should have a function named `fillArrContainer`.
+
+```js
+assert.isFunction(fillArrContainer);
+```
+
+Your `fillArrContainer()` function should fill the element passed as the first argument to the function with five `span` elements with the text of an integer from the array passed as the second argument to the function.
+
+```js
+const testDiv = document.createElement("div");
+const testArr = [15, 98, 17, 5, 63]
+fillArrContainer(testDiv, testArr);
+const children = testDiv.children;
+assert.lengthOf(children, 5);
+Array.from(children).forEach((el, i) => {
+ assert.equal(el.tagName, "SPAN");
+ assert.equal(el.innerText, testArr[i])
+})
+```
+
+You should have a function named `isOrdered`.
+
+```js
+assert.isFunction(isOrdered);
+```
+
+Your `isOrdered` function should take two integers and should return a boolean indicating if the first integer is less than or equal to the second.
+
+```js
+assert.lengthOf(isOrdered, 2);
+assert.isTrue(isOrdered(2, 60));
+assert.isFalse(isOrdered(10, 3));
+assert.isTrue(isOrdered(5, 5));
+```
+
+You should have a function named `swapElements`.
+
+```js
+assert.isFunction(swapElements);
+```
+
+Your `swapElements` function take an array of integers and a numeric index as arguments. It should modify the array passed in place by swapping the element at the given index and the following element if the first element is greater than the second.
+
+```js
+const testArr = [22, 4, 87, 47, 33];
+swapElements(testArr, 0);
+assert.deepEqual(testArr, [4, 22, 87, 47, 33]);
+swapElements(testArr, 1);
+assert.deepEqual(testArr, [4, 22, 87, 47, 33]);
+swapElements(testArr, 2);
+assert.deepEqual(testArr, [4, 22, 47, 87, 33]);
+swapElements(testArr, 3);
+assert.deepEqual(testArr, [4, 22, 47, 33, 87]);
+```
+
+You should have a function named `highlightCurrentEls`.
+
+```js
+assert.isFunction(highlightCurrentEls);
+```
+
+Your `highlightCurrentEls` function should give the descendants of the specified element, located at the given index and the next index, a border that is `dashed`, `red`, and set to a width of your choice.
+
+```js
+const testDiv = document.createElement("div");
+document.querySelector("body").appendChild(testDiv)
+for (let i = 0; i < 5; i++) {
+ testDiv.appendChild(document.createElement("span"));
+}
+const redBorderRegex = /dashed (rgb\(255,\s*0,\s*0\)|#FF0000|#F00|hsl\(0,\s*100%,\s*50%\))/;
+const revertBorder = () => {
+ for (const el of children) {
+ el.style.border = "revert";
+ }
+}
+const children = testDiv.children;
+
+for (let i = 0; i < 3; i++) {
+ highlightCurrentEls(testDiv, i);
+ for (let j = 0; j < 5; j++) {
+ let b = getComputedStyle(children[j]).border;
+ if (j == i || j == i + 1) {
+ assert.match(b, redBorderRegex);
+ assert.isAbove(parseFloat(b), 0);
+ } else {
+ assert.notMatch(b, redBorderRegex);
+ }
+ }
+ revertBorder();
+}
+testDiv.remove();
+```
+
+When you click `#generate-btn` you should fill `#starting-array` with five `span` elements, each with a random number between `1` and `100` as its text.
+
+```js
+const genBtn = document.querySelector("#generate-btn");
+genBtn.click();
+const children = document.querySelector("#starting-array").querySelectorAll("span");
+assert.lengthOf(children, 5);
+Array.from(children).forEach(el => {
+ assert.equal(el.tagName, "SPAN");
+ const num = Number(el.innerText);
+ assert.isAtMost(num, 100);
+ assert.isAtLeast(num, 1);
+})
+```
+
+After you click `#sort-btn`, `#array-container` should contain as many `div` elements as the steps required by the Bubble Sort algorithm to sort the starting array, including the `div` representing the starting array and a `div` representing the sorted array.
+
+```js
+const genBtn = document.querySelector("#generate-btn");
+const sortBtn = document.querySelector("#sort-btn");
+// using randomMocker to be sure that the starting array requires 13 steps to be sorted
+const randomMocker = new __helpers.RandomMocker();
+randomMocker.mock();
+try {
+ genBtn.dispatchEvent(new Event("click"));
+ sortBtn.dispatchEvent(new Event("click"));
+ const container = document.querySelector("#array-container");
+ assert.lengthOf(container.children, 13)
+ Array.from(container.children).forEach(el => {assert.equal(el.tagName, "DIV")})
+} finally {
+ randomMocker.restore();
+}
+```
+
+After you click `#sort-btn`, each `div` within `#array-container` should contain five `span`, each with a number as its text, and arranged to represent the steps required by Bubble Sort algorithm to sort the starting array.
+
+```js
+const finalArr = [9, 23, 26, 38, 58];
+const arrays = [
+ [26, 9, 58, 23, 38],
+ [9, 26, 58, 23, 38],
+ [9, 26, 58, 23, 38],
+ [9, 26, 23, 58, 38],
+ [9, 26, 23, 38, 58],
+ [9, 26, 23, 38, 58],
+ finalArr,
+ finalArr,
+ finalArr,
+ finalArr,
+ finalArr,
+ finalArr,
+ finalArr
+]
+const genBtn = document.querySelector("#generate-btn");
+const sortBtn = document.querySelector("#sort-btn");
+const randomMocker = new __helpers.RandomMocker();
+randomMocker.mock();
+try {
+ genBtn.dispatchEvent(new Event("click"));
+ sortBtn.dispatchEvent(new Event("click"));
+ const container = document.querySelector("#array-container");
+ assert.isNotEmpty(container.children);
+ Array.from(container.children).forEach((el, i) => {
+ Array.from(el.children).forEach((j, k) => {
+ assert.strictEqual(Number(j.innerText), arrays[i][k])
+ })
+ })
+} finally {
+ randomMocker.restore();
+}
+```
+
+When you click the `#sort-btn`, you should make use of the `highlightCurrentEls` function to highlight the elements being compared in each step.
+
+```js
+const sortBtn = document.querySelector("#sort-btn");
+let flag = false;
+const temp = highlightCurrentEls;
+highlightCurrentEls = () => flag = true;
+try {
+ sortBtn.dispatchEvent(new Event("click"));
+ assert.isTrue(flag);
+} finally {
+ highlightCurrentEls = temp;
+}
+```
+
+After you click `#sort-btn`, `#starting-array` should represent the starting step with the initial array and the first two integers highlighted using `highlightCurrentEls`.
+
+```js
+const genBtn = document.querySelector("#generate-btn");
+const sortBtn = document.querySelector("#sort-btn");
+genBtn.dispatchEvent(new Event("click"));
+sortBtn.dispatchEvent(new Event("click"));
+const firstContainer = document.querySelector("#starting-array");
+const children = firstContainer.children
+const redBorderRegex = /dashed (rgb\(255,\s*0,\s*0\)|#FF0000|hsl\(0,\s*100%,\s*50%\))/;
+assert.match(getComputedStyle(children[0]).border, redBorderRegex);
+assert.match(getComputedStyle(children[1]).border, redBorderRegex);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
Sorting Visualizer
+
+
+
+
+
+
+
+ Generate Array
+ Sort Array
+
+
+
+
+
+
+```
+
+```css
+* {
+ box-sizing: border-box;
+}
+
+main {
+ height: 100vh;
+ display: flex;
+ justify-content: center;
+ flex-direction: column;
+ align-items: center;
+}
+
+#array-container {
+ max-height: 95vh;
+ display: flex;
+ flex-direction: column;
+ flex-wrap: wrap;
+ gap: 2px;
+
+}
+
+#array-container>div {
+ min-width: 8rem;
+ height: 2rem;
+ box-shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;
+ border-radius: 10px;
+ margin-bottom: 0.2rem;
+ border: 2px solid darkgray;
+ display: flex;
+ justify-content: space-evenly;
+ align-items: center;
+}
+
+#starting-array {
+ border: 4px solid darkblue !important;
+}
+
+#btn-container {
+ display: flex;
+ justify-content: space-around;
+}
+
+button {
+ padding: 2px;
+ margin: 5px;
+}
+
+span {
+ border-radius: 2px;
+ padding: 0.5px;
+ margin: 0
+}
+
+@media (min-width: 430px) {
+ #array-container>div {
+ min-width: 12rem;
+ }
+ span {
+ padding: 1px;
+ margin: 1px;
+ }
+}
+```
+
+```js
+
+```
+
+# --solutions--
+
+```html
+
+
+
+
+
+
+
+
Sorting Visualizer
+
+
+
+
+
+
+
+ Generate Array
+ Sort Array
+
+
+
+
+
+
+```
+
+```css
+* {
+ box-sizing: border-box;
+}
+
+main {
+ height: 100vh;
+ display: flex;
+ justify-content: center;
+ flex-direction: column;
+ align-items: center;
+}
+
+#array-container {
+ max-height: 95vh;
+ display: flex;
+ flex-direction: column;
+ flex-wrap: wrap;
+ gap: 2px;
+
+}
+
+#array-container>div {
+ min-width: 8rem;
+ height: 2rem;
+ box-shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;
+ border-radius: 10px;
+ margin-bottom: 0.2rem;
+ border: 2px solid darkgray;
+ display: flex;
+ justify-content: space-evenly;
+ align-items: center;
+}
+
+#starting-array {
+ border: 4px solid darkblue !important;
+}
+
+#btn-container {
+ display: flex;
+ justify-content: space-around;
+}
+
+button {
+ padding: 2px;
+ margin: 5px;
+}
+
+#sort-btn {
+ display: none
+}
+
+span {
+ border-radius: 2px;
+ padding: 0.5px;
+ margin: 0
+}
+
+@media (min-width: 430px) {
+ #array-container>div {
+ min-width: 12rem;
+ }
+ span {
+ padding: 1px;
+ margin: 1px;
+ }
+}
+```
+
+```js
+const arrayContainer = document.getElementById("array-container");
+const generateArrayBtn = document.getElementById("generate-btn");
+const sortArrayBtn = document.getElementById("sort-btn");
+const arrayLength = 5;
+const minVal = 1;
+const maxVal = 100;
+const isStart = () => arrayContainer.children.length === 1;
+const clearArrayContainer = () => { arrayContainer.innerHTML = '
' };
+const showSortBtn = () => {sortArrayBtn.style.display = "inline-block"};
+const hideSortBtn = () => {sortArrayBtn.style.display = "none"};
+const generateElement = () => Math.floor(Math.random() * maxVal + minVal);
+const generateArray = () => Array.from({ length: arrayLength }, generateElement);
+const fillArrContainer = (container, arr) => {
+ container.innerHTML = "";
+ arr.forEach(i => {
+ const el = document.createElement("span");
+ el.innerText = i;
+ el.id = `number-${i}`
+ container.appendChild(el);
+ })
+}
+const isOrdered = (el1, el2) => el1 <= el2;
+
+const swapElements = (arr, n = 0) => {
+ if (n < arr.length - 1 && !isOrdered(arr[n], arr[n + 1])) {
+ const temp = arr[n];
+ arr[n] = arr[n + 1];
+ arr[n + 1] = temp;
+ }
+}
+const getLastChildren = () => arrayContainer.lastElementChild;
+const getLastArr = () => {
+ const els = Array.from(getLastChildren().children);
+ const arr = els.map(el => Number(el.id.replace("number-", "")));
+ return arr;
+}
+const generateContainer = () => {
+ const container = document.createElement("div");
+ arrayContainer.appendChild(container);
+ return container;
+}
+const highlightCurrentEls = (container, n = 0) => {
+ const children = container.children;
+ children[n].style.border = "2px dashed red";
+ children[n + 1].style.border = "2px dashed red";
+}
+
+const highlightSorted = () => {
+ getLastChildren().style.border = "4px solid green";
+}
+
+const bubbleSort = () => {
+ let swapped = true;
+ while (swapped) {
+ const startingArr = getLastArr();
+ startingArr.forEach((_, i) => {
+ if (i + 1 < arrayLength) {
+ highlightCurrentEls(getLastChildren(), i);
+ const arr = getLastArr();
+ swapElements(arr, i);
+ fillArrContainer(generateContainer(), arr);
+ }
+ })
+ const lastArr = getLastArr()
+ if (startingArr.every((el, i) => el === lastArr[i])) swapped = false;
+ }
+}
+
+
+generateArrayBtn.addEventListener("click", () => {
+ if (!isStart()) {
+ clearArrayContainer();
+ }
+ fillArrContainer(document.getElementById("starting-array"), generateArray());
+ showSortBtn();
+});
+
+sortArrayBtn.addEventListener("click", () => {
+ bubbleSort();
+ highlightSorted();
+ hideSortBtn();
+})
+```
+
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-stylized-to-do-list/66c051d13a6a20255a963695.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-stylized-to-do-list/66c051d13a6a20255a963695.md
index 5cb97f40fc..c0ae47b95e 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-stylized-to-do-list/66c051d13a6a20255a963695.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-stylized-to-do-list/66c051d13a6a20255a963695.md
@@ -1,7 +1,7 @@
---
id: 66c051d13a6a20255a963695
title: Створіть стилізований список справ
-challengeType: 14
+challengeType: 25
dashedName: build-a-stylized-to-do-list
demoType: onClick
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-survey-form/587d78af367417b2b2512b03.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-survey-form/587d78af367417b2b2512b03.md
index 8a5353e6e4..c586d0e217 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-survey-form/587d78af367417b2b2512b03.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-survey-form/587d78af367417b2b2512b03.md
@@ -1,7 +1,7 @@
---
id: 587d78af367417b2b2512b03
title: Створіть форму для опитування
-challengeType: 14
+challengeType: 25
dashedName: build-a-survey-form
demoType: onClick
---
@@ -35,261 +35,297 @@ Fulfill the user stories below and get all the tests to pass to complete the lab
```js
const el = document.getElementById('title');
-assert(!!el && el.tagName === 'H1');
+assert.isNotNull(el);
+assert.strictEqual(el.tagName, 'H1');
```
`#title` не повинен бути порожнім.
```js
const el = document.getElementById('title');
-assert(!!el && el.innerText.length > 0);
+assert.isNotNull(el);
+assert.isAbove(el.innerText.length, 0);
```
Ви повинні мати елемент `p` з `id` зі значенням `description`.
```js
const el = document.getElementById('description');
-assert(!!el && el.tagName === 'P');
+assert.isNotNull(el);
+assert.strictEqual(el.tagName, 'P');
```
`#description` не повинен бути порожнім.
```js
const el = document.getElementById('description');
-assert(!!el && el.innerText.length > 0);
+assert.isNotNull(el);
+assert.isAbove(el.innerText.length, 0);
```
Ви повинні мати елемент `form` з `id` зі значенням `survey-form`.
```js
const el = document.getElementById('survey-form');
-assert(!!el && el.tagName === 'FORM');
+assert.isNotNull(el);
+assert.strictEqual(el.tagName, 'FORM');
```
Ви повинні мати елемент `input` з `id` зі значенням `name`.
```js
const el = document.getElementById('name');
-assert(!!el && el.tagName === 'INPUT');
+assert.isNotNull(el);
+assert.strictEqual(el.tagName, 'INPUT');
```
`#name` повинен мати `type` зі значенням `text`.
```js
const el = document.getElementById('name');
-assert(!!el && el.type === 'text');
+assert.isNotNull(el);
+assert.strictEqual(el.type, 'text');
```
`#name` повинен вимагати введення.
```js
const el = document.getElementById('name');
-assert(!!el && el.required);
+assert.isNotNull(el);
+assert.isTrue(el.required);
```
`#name` має бути нащадком `#survey-form`.
```js
const el = document.querySelector('#survey-form #name');
-assert(!!el);
+assert.isNotNull(el);
```
Ви повинні мати елемент `input` з `id` зі значенням `email`.
```js
const el = document.getElementById('email');
-assert(!!el && el.tagName === 'INPUT');
+assert.isNotNull(el);
+assert.strictEqual(el.tagName, 'INPUT');
```
`#email` повинен мати `type` зі значенням `email`.
```js
const el = document.getElementById('email');
-assert(!!el && el.type === 'email');
+assert.isNotNull(el);
+assert.strictEqual(el.type, 'email');
```
`#email` повинен вимагати введення.
```js
const el = document.getElementById('email');
-assert(!!el && el.required);
+assert.isNotNull(el);
+assert.isTrue(el.required);
```
`#email` має бути нащадком `#survey-form`.
```js
const el = document.querySelector('#survey-form #email');
-assert(!!el);
+assert.isNotNull(el);
```
Ви повинні мати елемент `input` з `id` зі значенням `number`.
```js
const el = document.getElementById('number');
-assert(!!el && el.tagName === 'INPUT');
+assert.isNotNull(el);
+assert.strictEqual(el.tagName, 'INPUT');
```
`#number` має бути нащадком `#survey-form`.
```js
const el = document.querySelector('#survey-form #number');
-assert(!!el);
+assert.isNotNull(el);
```
`#number` повинен мати `type` зі значенням `number`.
```js
const el = document.getElementById('number');
-assert(!!el && el.type === 'number');
+assert.isNotNull(el);
+assert.strictEqual(el.type, 'number');
```
`#number` повинен мати атрибут `min` з числовим значенням.
```js
const el = document.getElementById('number');
-assert(!!el && el.min && isFinite(el.min));
+assert.isNotNull(el);
+assert.isNotEmpty(el.min);
+assert.isTrue(isFinite(el.min));
```
`#number` повинен мати атрибут `max` з числовим значенням.
```js
const el = document.getElementById('number');
-assert(!!el && el.max && isFinite(el.max));
+assert.isNotNull(el);
+assert.isNotEmpty(el.max);
+assert.isTrue(isFinite(el.max));
```
Ви повинні мати елемент `label` з `id` зі значенням `name-label`.
```js
const el = document.getElementById('name-label');
-assert(!!el && el.tagName === 'LABEL');
+assert.isNotNull(el);
+assert.strictEqual(el.tagName, 'LABEL');
```
Ви повинні мати елемент `label` з `id` зі значенням `email-label`.
```js
const el = document.getElementById('email-label');
-assert(!!el && el.tagName === 'LABEL');
+assert.isNotNull(el);
+assert.strictEqual(el.tagName, 'LABEL');
```
Ви повинні мати елемент `label` з `id` зі значенням `number-label`.
```js
const el = document.getElementById('number-label');
-assert(!!el && el.tagName === 'LABEL');
+assert.isNotNull(el);
+assert.strictEqual(el.tagName, 'LABEL');
```
`#name-label` має містити текст, який описує введені дані.
```js
const el = document.getElementById('name-label');
-assert(!!el && el.innerText.length > 0);
+assert.isNotNull(el);
+assert.isAbove(el.innerText.length, 0);
```
`#email-label` має містити текст, який описує введені дані.
```js
const el = document.getElementById('email-label');
-assert(!!el && el.innerText.length > 0);
+assert.isNotNull(el);
+assert.isAbove(el.innerText.length, 0);
```
`#number-label` має містити текст, який описує введені дані.
```js
const el = document.getElementById('number-label');
-assert(!!el && el.innerText.length > 0);
+assert.isNotNull(el);
+assert.isAbove(el.innerText.length, 0);
```
`#name-label` має бути нащадком `#survey-form`.
```js
const el = document.querySelector('#survey-form #name-label');
-assert(!!el);
+assert.isNotNull(el);
```
`#email-label` має бути нащадком `#survey-form`.
```js
const el = document.querySelector('#survey-form #email-label');
-assert(!!el);
+assert.isNotNull(el);
```
`#number-label` має бути нащадком `#survey-form`.
```js
const el = document.querySelector('#survey-form #number-label');
-assert(!!el);
+assert.isNotNull(el);
```
Your `#name` should have a `placeholder` attribute and value.
```js
const el = document.getElementById('name');
-assert(!!el && !!el.placeholder && el.placeholder.length > 0);
+assert.isNotNull(el);
+assert.isNotNull(el.placeholder);
+assert.isAbove(el.placeholder.length, 0);
```
Your `#email` should have a `placeholder` attribute and value.
```js
const el = document.getElementById('email');
-assert(!!el && !!el.placeholder && el.placeholder.length > 0);
+assert.isNotNull(el);
+assert.isNotNull(el.placeholder);
+assert.isAbove(el.placeholder.length, 0);
```
Your `#number` should have a `placeholder` attribute and value.
```js
const el = document.getElementById('number');
-assert(!!el && !!el.placeholder && el.placeholder.length > 0);
+assert.isNotNull(el);
+assert.isNotNull(el.placeholder);
+assert.isAbove(el.placeholder.length, 0);
```
You should have a `select` field with an `id` of `dropdown`.
```js
const el = document.getElementById('dropdown');
-assert(!!el && el.tagName === 'SELECT');
+assert.isNotNull(el);
+assert.strictEqual(el.tagName, 'SELECT');
```
`#dropdown` повинен мати щонайменше два елементи `option` з можливістю вибору (не відключені).
```js
const els = document.querySelectorAll('#dropdown option:not([disabled])');
-assert(els.length >= 2);
+assert.isAtLeast(els.length, 2);
```
`#dropdown` має бути нащадком `#survey-form`.
```js
const el = document.querySelector('#survey-form #dropdown');
-assert(!!el);
+assert.isNotNull(el);
```
Ви повинні мати щонайменше два елементи `input` з `type` зі значенням `radio` (радіокнопки).
```js
const els = document.querySelectorAll('input[type="radio"]');
-assert(els.length >= 2);
+assert.isAtLeast(els.length, 2);
```
Ви повинні мати щонайменше дві радіокнопки, які є нащадками `#survey-form`.
```js
const els = document.querySelectorAll('#survey-form input[type="radio"]');
-assert(els.length >= 2);
+assert.isAtLeast(els.length, 2);
```
Всі радіокнопки повинні мати атрибут та значення `value`.
```js
const els1 = document.querySelectorAll('input[type="radio"]');
-const els2 = document.querySelectorAll('input[type="radio"][value=""], input[type="radio"]:not([value])');
-assert(els1.length > 0 && els2.length === 0);
+const els2 = document.querySelectorAll(
+ 'input[type="radio"][value=""], input[type="radio"]:not([value])'
+);
+assert.isAbove(els1.length, 0);
+assert.lengthOf(els2, 0);
```
Всі радіокнопки повинні мати атрибут та значення `name`.
```js
const els1 = document.querySelectorAll('input[type="radio"]');
-const els2 = document.querySelectorAll('input[type="radio"][name=""], input[type="radio"]:not([name])');
-assert(els1.length > 0 && els2.length === 0);
+const els2 = document.querySelectorAll(
+ 'input[type="radio"][name=""], input[type="radio"]:not([name])'
+);
+assert.isAbove(els1.length, 0);
+assert.lengthOf(els2, 0);
```
В кожній групі радіокнопок мають бути щонайменше 2 радіокнопки.
@@ -302,59 +338,64 @@ if (radioButtons) {
radioButtons.forEach(el => {
if (!groups[el.name]) groups[el.name] = [];
groups[el.name].push(el);
- })
+ });
}
const groupKeys = Object.keys(groups);
groupKeys.forEach(key => {
if (groups[key].length < 2) assert(false);
-})
+});
-assert(groupKeys.length > 0);
+assert.isAbove(groupKeys.length, 0);
```
Ви повинні мати щонайменше два елементи `input` з `type` зі значенням `checkbox` (прапорцями), що є нащадками `#survey-form`.
```js
const els = document.querySelectorAll('#survey-form input[type="checkbox"]');
-assert(els.length >= 2);
+assert.isAtLeast(els.length, 2);
```
Всі прапорці всередині `#survey-form` повинні мати атрибут та значення `value`.
```js
const els1 = document.querySelectorAll('#survey-form input[type="checkbox"]');
-const els2 = document.querySelectorAll('#survey-form input[type="checkbox"][value=""], #survey-form input[type="checkbox"]:not([value])');
-assert(els1.length > 0 && els2.length === 0);
+const els2 = document.querySelectorAll(
+ '#survey-form input[type="checkbox"][value=""], #survey-form input[type="checkbox"]:not([value])'
+);
+assert.isAbove(els1.length, 0);
+assert.lengthOf(els2, 0);
```
Ви повинні мати щонайменше один елемент `textarea`, що є нащадком `#survey-form`.
```js
const el = document.querySelector('#survey-form textarea');
-assert(!!el);
+assert.isNotNull(el);
```
Ви повинні мати елемент `input` або `button` з `id` зі значенням `submit`.
```js
const el = document.getElementById('submit');
-assert(!!el && (el.tagName === 'INPUT' || el.tagName === 'BUTTON'));
+assert.isNotNull(el);
+assert.isTrue(el.tagName === 'INPUT' || el.tagName === 'BUTTON');
```
`#submit` повинен мати `type` зі значенням `submit`.
```js
const el = document.getElementById('submit');
-assert(!!el && el.type === 'submit');
+assert.isNotNull(el);
+assert.strictEqual(el.type, 'submit');
```
`#submit` має бути нащадком `#survey-form`.
```js
const el = document.querySelector('#survey-form #submit');
-assert(!!el);
+assert.isNotNull(el);
```
# --seed--
@@ -364,17 +405,13 @@ assert(!!el);
```html
-
-
+
Survey Form
-
-
-
-
-
+
-
+
+
```
# --solutions--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-technical-documentation-page/587d78b0367417b2b2512b05.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-technical-documentation-page/587d78b0367417b2b2512b05.md
index 9d3dede78b..fbe5727b82 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-technical-documentation-page/587d78b0367417b2b2512b05.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-technical-documentation-page/587d78b0367417b2b2512b05.md
@@ -1,7 +1,7 @@
---
id: 587d78b0367417b2b2512b05
title: Побудуйте сторінку технічної документації
-challengeType: 14
+challengeType: 25
demoType: onClick
dashedName: build-a-technical-documentation-page
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-travel-agency-page/669e2f60e83c011754f711f9.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-travel-agency-page/669e2f60e83c011754f711f9.md
index 40c1874501..ea8c24a116 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-travel-agency-page/669e2f60e83c011754f711f9.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-travel-agency-page/669e2f60e83c011754f711f9.md
@@ -1,7 +1,7 @@
---
id: 669e2f60e83c011754f711f9
title: Створіть сторінку туристичної агенції
-challengeType: 14
+challengeType: 25
dashedName: build-a-travel-agency-page
demoType: onClick
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-tribute-page/bd7158d8c442eddfaeb5bd18.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-tribute-page/bd7158d8c442eddfaeb5bd18.md
index 814bab8b9d..6ceec56768 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-tribute-page/bd7158d8c442eddfaeb5bd18.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-tribute-page/bd7158d8c442eddfaeb5bd18.md
@@ -1,7 +1,7 @@
---
id: bd7158d8c442eddfaeb5bd18
title: Побудуйте сторінку данини
-challengeType: 14
+challengeType: 25
demoType: onClick
dashedName: build-a-tribute-page
---
@@ -253,7 +253,7 @@ assert(leftMargin - rightMargin < 6 && rightMargin - leftMargin < 6)
1938 - Marries wife of 69 years Margret Gibson.
Gets laid off due to budget cuts. Inspired by Elvin Charles Stakman,
he returns to school study under Stakman, who teaches him about
- breeding pest-resistent plants.
+ breeding pest-resistant plants.
1941 - Tries to enroll in the military after the
@@ -269,7 +269,7 @@ assert(leftMargin - rightMargin < 6 && rightMargin - leftMargin < 6)
1944 - Rejects a 100% salary increase from Dupont,
leaves behind his pregnant wife, and flies to Mexico to head a new
plant pathology program. Over the next 16 years, his team breeds
- 6,000 different strains of disease resistent wheat - including
+ 6,000 different strains of disease resistant wheat - including
different varieties for each major climate on Earth.
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-video-compilation-page/669e81368e52b3a5c35a2dc5.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-video-compilation-page/669e81368e52b3a5c35a2dc5.md
index 8d867cf617..19f988b4fd 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-video-compilation-page/669e81368e52b3a5c35a2dc5.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-video-compilation-page/669e81368e52b3a5c35a2dc5.md
@@ -1,7 +1,7 @@
---
id: 669e81368e52b3a5c35a2dc5
title: Створіть сторінку із відео
-challengeType: 14
+challengeType: 25
dashedName: build-a-video-compilation-page
demoType: onClick
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-voting-system/673b567e3ba535dda140d278.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-voting-system/673b567e3ba535dda140d278.md
index afe533d6f5..e86fb0152f 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-voting-system/673b567e3ba535dda140d278.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-voting-system/673b567e3ba535dda140d278.md
@@ -1,7 +1,7 @@
---
id: 673b567e3ba535dda140d278
title: Build a Voting System
-challengeType: 14
+challengeType: 25
dashedName: build-a-voting-system
---
@@ -35,8 +35,7 @@ In this lab, you will build a voting system that uses `Map` to create a poll and
- If the voter has already voted, the function should display the message `Voter has already voted for "".`
- - If the voter has not voted, `voterId` should be added to the `Set` of `voters` for this option. The function should return the message `Voter voted for "".`
-
+ - If the voter has not voted, `voterId` should be added to the `Set` of `voters` for this option. The function should return the message `Voter voted for "".`
6. You should have at least three options in your `poll`.
@@ -51,7 +50,7 @@ OptionB: N votes
.
.
-/*
+/*
sample output
Poll Results:
@@ -115,9 +114,8 @@ const pollCopy = new Map(poll);
try {
poll.clear();
- addOption("Turkey");
- assert.instanceOf(poll.get("Turkey"), Set);
-
+ addOption('Turkey');
+ assert.instanceOf(poll.get('Turkey'), Set);
} finally {
poll.clear();
pollCopy.forEach((val, key) => {
@@ -132,7 +130,7 @@ try {
const pollCopy = new Map(poll);
try {
poll.clear();
- assert.equal(addOption("Egypt"), 'Option "Egypt" added to the poll.');
+ assert.equal(addOption('Egypt'), 'Option "Egypt" added to the poll.');
} finally {
poll.clear();
pollCopy.forEach((val, key) => {
@@ -144,7 +142,7 @@ try {
Adding an empty option should return `"Option cannot be empty."`
```js
-assert.equal(addOption(""), 'Option cannot be empty.');
+assert.equal(addOption(''), 'Option cannot be empty.');
```
When `Turkey` is already added, `addOption("Turkey")` should return `Option "Turkey" already exists.`
@@ -153,10 +151,9 @@ When `Turkey` is already added, `addOption("Turkey")` should return `Option "Tur
const pollCopy = new Map(poll);
try {
poll.clear();
- addOption("Turkey");
- addOption("Turkey");
- assert.equal(addOption("Turkey"), 'Option "Turkey" already exists.');
-
+ addOption('Turkey');
+ addOption('Turkey');
+ assert.equal(addOption('Turkey'), 'Option "Turkey" already exists.');
} finally {
poll.clear();
pollCopy.forEach((val, key) => {
@@ -171,8 +168,11 @@ When `Malysia` exists in the voting options, `vote("Malysia", "traveler1")` shou
const pollCopy = new Map(poll);
try {
poll.clear();
- addOption("Malysia");
- assert.equal(vote("Malysia", "traveler1"), 'Voter traveler1 voted for "Malysia".');
+ addOption('Malysia');
+ assert.equal(
+ vote('Malysia', 'traveler1'),
+ 'Voter traveler1 voted for "Malysia".'
+ );
} finally {
poll.clear();
pollCopy.forEach((val, key) => {
@@ -187,11 +187,10 @@ try {
const pollCopy = new Map(poll);
try {
poll.clear();
- addOption("Alaska");
- vote("Alaska", "seal");
- assert.isTrue(poll.get("Alaska").has("seal"));
-
- } finally {
+ addOption('Alaska');
+ vote('Alaska', 'seal');
+ assert.isTrue(poll.get('Alaska').has('seal'));
+} finally {
poll.clear();
pollCopy.forEach((val, key) => {
poll.set(key, val);
@@ -205,9 +204,12 @@ When `traveler1` tries to vote for `Algeria` again, `vote("Algeria", "traveler1"
const pollCopy = new Map(poll);
try {
poll.clear();
- addOption("Algeria");
- vote("Algeria", "traveler1");
- assert.equal(vote("Algeria", "traveler1"), 'Voter traveler1 has already voted for "Algeria".');
+ addOption('Algeria');
+ vote('Algeria', 'traveler1');
+ assert.equal(
+ vote('Algeria', 'traveler1'),
+ 'Voter traveler1 has already voted for "Algeria".'
+ );
} finally {
poll.clear();
pollCopy.forEach((val, key) => {
@@ -222,12 +224,12 @@ Duplicate votes should not increase the size of the `Set`.
const pollCopy = new Map(poll);
try {
poll.clear();
- addOption("Turkey");
- vote("Turkey", "traveler1");
- const voterSet = poll.get("Turkey");
+ addOption('Turkey');
+ vote('Turkey', 'traveler1');
+ const voterSet = poll.get('Turkey');
const initialSize = voterSet.size;
- vote("Turkey", "traveler1");
+ vote('Turkey', 'traveler1');
assert.equal(voterSet.size, initialSize);
} finally {
poll.clear();
@@ -243,7 +245,10 @@ When `Nigeria` is not in the voting options, `vote("Nigeria", "traveler2")` shou
const pollCopy = new Map(poll);
try {
poll.clear();
-assert.equal(vote("Nigeria", "traveler2"), 'Option "Nigeria" does not exist.');
+ assert.equal(
+ vote('Nigeria', 'traveler2'),
+ 'Option "Nigeria" does not exist.'
+ );
} finally {
poll.clear();
pollCopy.forEach((val, key) => {
@@ -258,10 +263,10 @@ A unique option should be able to receive multiple votes.
const pollCopy = new Map(poll);
try {
poll.clear();
- addOption("Bali");
- assert.equal(vote("Bali", "traveler1"), 'Voter traveler1 voted for "Bali".');
- assert.equal(vote("Bali", "traveler2"), 'Voter traveler2 voted for "Bali".');
- assert.equal(poll.get("Bali").size, 2);
+ addOption('Bali');
+ assert.equal(vote('Bali', 'traveler1'), 'Voter traveler1 voted for "Bali".');
+ assert.equal(vote('Bali', 'traveler2'), 'Voter traveler2 voted for "Bali".');
+ assert.equal(poll.get('Bali').size, 2);
} finally {
poll.clear();
pollCopy.forEach((val, key) => {
@@ -273,18 +278,20 @@ try {
`displayResults()` should return the results in the correct format.
```js
-
const pollCopy = new Map(poll);
try {
poll.clear();
- addOption("Turkey");
- addOption("Morocco");
+ addOption('Turkey');
+ addOption('Morocco');
- vote("Turkey", "traveler1");
- vote("Turkey", "traveler2");
- vote("Morocco", "traveler3");
+ vote('Turkey', 'traveler1');
+ vote('Turkey', 'traveler2');
+ vote('Morocco', 'traveler3');
- assert.equal(displayResults(), "Poll Results:\nTurkey: 2 votes\nMorocco: 1 votes");
+ assert.equal(
+ displayResults(),
+ 'Poll Results:\nTurkey: 2 votes\nMorocco: 1 votes'
+ );
} finally {
poll.clear();
pollCopy.forEach((val, key) => {
@@ -307,8 +314,8 @@ try {
const poll = new Map();
function addOption(option) {
- if (!option || option.trim() === "") {
- return "Option cannot be empty.";
+ if (!option || option.trim() === '') {
+ return 'Option cannot be empty.';
}
if (!poll.has(option)) {
poll.set(option, new Set());
@@ -318,7 +325,6 @@ function addOption(option) {
}
}
-
function vote(option, voterId) {
if (!poll.has(option)) {
return `Option "${option}" does not exist.`;
@@ -327,26 +333,24 @@ function vote(option, voterId) {
if (voters.has(voterId)) {
return `Voter ${voterId} has already voted for "${option}".`;
} else {
- voters.add(voterId);
+ voters.add(voterId);
return `Voter ${voterId} voted for "${option}".`;
}
}
function displayResults() {
- let results = "Poll Results:\n";
- for (let [option, voters] of poll.entries()) {
- results += `${option}: ${voters.size} votes\n`;
- }
- return results.trim();
+ let results = 'Poll Results:\n';
+ for (let [option, voters] of poll.entries()) {
+ results += `${option}: ${voters.size} votes\n`;
+ }
+ return results.trim();
}
+addOption('Turkey');
+addOption('Morocco');
+addOption('Spain');
-addOption("Turkey");
-addOption("Morocco");
-addOption("Spain");
-
-vote("Turkey", "traveler1");
-vote("Turkey", "traveler2");
-vote("Morocco", "traveler3");
-
+vote('Turkey', 'traveler1');
+vote('Turkey', 'traveler2');
+vote('Morocco', 'traveler3');
```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lab-weather-app/66f12a88741aeb16b9246c59.md b/curriculum/challenges/ukrainian/25-front-end-development/lab-weather-app/66f12a88741aeb16b9246c59.md
index d07e1c609d..ad5b97d0cd 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lab-weather-app/66f12a88741aeb16b9246c59.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lab-weather-app/66f12a88741aeb16b9246c59.md
@@ -1,7 +1,7 @@
---
id: 66f12a88741aeb16b9246c59
title: Build a Weather App
-challengeType: 14
+challengeType: 25
dashedName: lab-weather-app
demoType: onClick
---
@@ -27,7 +27,7 @@ You will use a weather API. The output data has the following format:
"temp_min": 1.72, // min temperature of the day in C
"temp_max": 3.49, // max temperature of the day in C
"pressure": 1010, // atmospheric pressure in hPa
- "humidity": 81, // humidity in %
+ "humidity": 81 // humidity in %
},
"visibility": 10000, // distance in meters
"wind": {
@@ -35,7 +35,7 @@ You will use a weather API. The output data has the following format:
"deg": 285, // orientation of the wind in degrees
"gust": 3.13 // gust speed in m/s
},
- "name": "London",
+ "name": "London"
}
```
@@ -43,7 +43,8 @@ You will use a weather API. The output data has the following format:
1. You should have a `button` element with an `id` of `get-forecast`.
-1. You should have a `select` element with seven `option` elements nested within it. The first option should have an empty string as its text and `value` attribute. The rest should have the follow for their text and values (with the value being lowercase):
+1. You should have a `select` element with seven `option` elements nested within it. The first option should have an empty string as its text and `value` attribute. The rest should have the following for their text and values (with the value being lowercase):
+
- New York
- Los Angeles
- Chicago
@@ -105,105 +106,112 @@ Inside the `select` element the first child should be an `option` element with a
```js
assert.exists(document.querySelector('select > option[value=""]'));
-assert.strictEqual(document.querySelector('select > option:first-child').value, "");
+assert.strictEqual(
+ document.querySelector('select > option:first-child').value,
+ ''
+);
```
Inside the `select` element there should be 6 `option` elements, one for each of the following cities: Paris, London, Tokyo, Los Angeles, Chicago, New York.
```js
-["Paris", "London", "Tokyo", "Los Angeles", "Chicago", "New York"].forEach(city => {
- const el = document.querySelector(`select > option[value="${city.toLowerCase()}"]`);
+['Paris', 'London', 'Tokyo', 'Los Angeles', 'Chicago', 'New York'].forEach(
+ city => {
+ const el = document.querySelector(
+ `select > option[value="${city.toLowerCase()}"]`
+ );
assert.exists(el);
- assert.strictEqual(el.innerText.trim(), city)
-});
+ assert.strictEqual(el.innerText.trim(), city);
+ }
+);
```
You should have an `img` element with the id `weather-icon` for displaying the weather icon.
```js
async () => {
- document.querySelector('select').value = "chicago";
- document.querySelector('#get-forecast').click();
- await new Promise(resolve => setTimeout(resolve, 800));
- assert.exists(document.querySelector("img#weather-icon"));
-}
+ document.querySelector('select').value = 'chicago';
+ document.querySelector('#get-forecast').click();
+ await new Promise(resolve => setTimeout(resolve, 800));
+ assert.exists(document.querySelector('img#weather-icon'));
+};
```
You should have an element with the id `main-temperature` for displaying the main temperature.
```js
async () => {
- document.querySelector('select').value = "london";
- document.querySelector('#get-forecast').click();
- await new Promise(resolve => setTimeout(resolve, 800));
- assert.exists(document.querySelector("#main-temperature"));
-}
+ document.querySelector('select').value = 'london';
+ document.querySelector('#get-forecast').click();
+ await new Promise(resolve => setTimeout(resolve, 800));
+ assert.exists(document.querySelector('#main-temperature'));
+};
```
You should have an element with the id `feels-like` for displaying what the temperature feels like.
```js
async () => {
- document.querySelector('select').value = "london";
- document.querySelector('#get-forecast').click();
- await new Promise(resolve => setTimeout(resolve, 800));
- assert.exists(document.querySelector("#feels-like"));
-}
+ document.querySelector('select').value = 'london';
+ document.querySelector('#get-forecast').click();
+ await new Promise(resolve => setTimeout(resolve, 800));
+ assert.exists(document.querySelector('#feels-like'));
+};
```
You should have an element with the id `humidity` for displaying the amount of humidity in air.
```js
async () => {
- document.querySelector('select').value = "london";
- document.querySelector('#get-forecast').click();
- await new Promise(resolve => setTimeout(resolve, 800));
- assert.exists(document.querySelector("#humidity"));
-}
+ document.querySelector('select').value = 'london';
+ document.querySelector('#get-forecast').click();
+ await new Promise(resolve => setTimeout(resolve, 800));
+ assert.exists(document.querySelector('#humidity'));
+};
```
You should have an element with the id `wind` element for displaying the wind speed.
```js
async () => {
- document.querySelector('select').value = "new york";
- document.querySelector('#get-forecast').click();
- await new Promise(resolve => setTimeout(resolve, 800));
- assert.exists(document.querySelector("#wind"));
-}
+ document.querySelector('select').value = 'new york';
+ document.querySelector('#get-forecast').click();
+ await new Promise(resolve => setTimeout(resolve, 800));
+ assert.exists(document.querySelector('#wind'));
+};
```
You should have an element with the id `wind-gust` element for displaying the wind gust.
```js
async () => {
- document.querySelector('select').value = "new york";
- document.querySelector('#get-forecast').click();
- await new Promise(resolve => setTimeout(resolve, 800));
- assert.exists(document.querySelector("#wind-gust"));
-}
+ document.querySelector('select').value = 'new york';
+ document.querySelector('#get-forecast').click();
+ await new Promise(resolve => setTimeout(resolve, 800));
+ assert.exists(document.querySelector('#wind-gust'));
+};
```
You should have an element with the id `weather-main` element for displaying the main weather type.
```js
async () => {
- document.querySelector('select').value = "new york";
- document.querySelector('#get-forecast').click();
- await new Promise(resolve => setTimeout(resolve, 800));
- assert.exists(document.querySelector("#weather-main"));
-}
+ document.querySelector('select').value = 'new york';
+ document.querySelector('#get-forecast').click();
+ await new Promise(resolve => setTimeout(resolve, 800));
+ assert.exists(document.querySelector('#weather-main'));
+};
```
You should have an element with the id `location` element for displaying the current location.
```js
async () => {
- document.querySelector('select').value = "new york";
- document.querySelector('#get-forecast').click();
- await new Promise(resolve => setTimeout(resolve, 800));
- assert.exists(document.querySelector("#location"));
-}
+ document.querySelector('select').value = 'new york';
+ document.querySelector('#get-forecast').click();
+ await new Promise(resolve => setTimeout(resolve, 800));
+ assert.exists(document.querySelector('#location'));
+};
```
You should have a `showWeather` function.
@@ -222,261 +230,288 @@ The `getWeather` function should accept a city as it's only argument and return
```js
async () => {
- try {
- const city = "chicago";
- const url = `https://weather-proxy.freecodecamp.rocks/api/city/${city}`;
- const outputFunction = await getWeather(city);
- const json = await fetch(url).then(data => data.json());
- assert.deepEqual(outputFunction, json)
- } catch (err) {
- throw new Error(err);
- }
-}
+ try {
+ const city = 'chicago';
+ const url = `https://weather-proxy.freecodecamp.rocks/api/city/${city}`;
+ const outputFunction = await getWeather(city);
+ const json = await fetch(url).then(data => data.json());
+ assert.deepEqual(outputFunction, json);
+ } catch (err) {
+ throw new Error(err);
+ }
+};
```
The `showWeather` function should call the `getWeather` function to get the weather data.
```js
async () => {
- try {
- let flag = false;
- const temp = getWeather;
- getWeather = async (location) => {
- flag = true;
- return await fetch(`https://weather-proxy.freecodecamp.rocks/api/city/${location}`).then(data => data.json())
- }
- await showWeather("london");
- getWeather = temp;
- assert.isTrue(flag)
- } catch (err) {
- throw new Error(err);
- }
-}
+ try {
+ let flag = false;
+ const temp = getWeather;
+ getWeather = async location => {
+ flag = true;
+ return await fetch(
+ `https://weather-proxy.freecodecamp.rocks/api/city/${location}`
+ ).then(data => data.json());
+ };
+ await showWeather('london');
+ getWeather = temp;
+ assert.isTrue(flag);
+ } catch (err) {
+ throw new Error(err);
+ }
+};
```
When New York is selected the `showWeather` function should display the data from the API in the respective HTML elements. If the value from the API is `undefined`, you should show `N/A`.
```js
async () => {
- try {
- // function that construct an object with the id-value pairs that we expect in the page from an object
- const helper = (wobj) => ({
- "weather-icon": wobj.weather[0].icon,
- "main-temperature": wobj.main.temp || 'N/A',
- "feels-like": wobj.main.feels_like || 'N/A',
- humidity: wobj.main.humidity || 'N/A',
- wind: wobj.wind.speed || 'N/A',
- "wind-gust": wobj.wind.gust || 'N/A',
- "weather-main": wobj.weather[0].main || 'N/A',
- location: wobj.name || 'N/A'
- })
- const city = "new york";
- document.querySelector('select').value = city;
- document.querySelector('#get-forecast').click();
-
-
- // fetch the expected values from the API to confront
- const body = await fetch(`https://weather-proxy.freecodecamp.rocks/api/city/${city}`).then(
- data => data.json()
- )
-
- await new Promise(resolve => setTimeout(resolve, 800));
-
- // construct the object from the data from the API
- const extractedData = helper(body);
-
- // check that all things are in place
- for (const id in extractedData) {
- if (id === "weather-icon") {
- assert.equal(document.querySelector('#weather-icon').src, extractedData[id]);
- } else {
- assert.include(document.querySelector(`#${id}`).innerText.toLowerCase(), `${extractedData[id]}`.toLowerCase());
- }
- }
- } catch (err) {
- throw new Error(err);
+ try {
+ // function that construct an object with the id-value pairs that we expect in the page from an object
+ const helper = wobj => ({
+ 'weather-icon': wobj.weather[0].icon,
+ 'main-temperature': wobj.main.temp || 'N/A',
+ 'feels-like': wobj.main.feels_like || 'N/A',
+ humidity: wobj.main.humidity || 'N/A',
+ wind: wobj.wind.speed || 'N/A',
+ 'wind-gust': wobj.wind.gust || 'N/A',
+ 'weather-main': wobj.weather[0].main || 'N/A',
+ location: wobj.name || 'N/A'
+ });
+ const city = 'new york';
+ document.querySelector('select').value = city;
+ document.querySelector('#get-forecast').click();
+
+ // fetch the expected values from the API to confront
+ const body = await fetch(
+ `https://weather-proxy.freecodecamp.rocks/api/city/${city}`
+ ).then(data => data.json());
+
+ await new Promise(resolve => setTimeout(resolve, 800));
+
+ // construct the object from the data from the API
+ const extractedData = helper(body);
+
+ // check that all things are in place
+ for (const id in extractedData) {
+ if (id === 'weather-icon') {
+ assert.equal(
+ document.querySelector('#weather-icon').src,
+ extractedData[id]
+ );
+ } else {
+ assert.include(
+ document.querySelector(`#${id}`).innerText.toLowerCase(),
+ `${extractedData[id]}`.toLowerCase()
+ );
+ }
}
-}
+ } catch (err) {
+ throw new Error(err);
+ }
+};
```
When Chicago is selected the `showWeather` function should display the data from the API in the respective HTML elements. If the value from the API is `undefined`, you should show `N/A`.
```js
async () => {
- try {
- // function that construct an object with the id-value pairs that we expect in the page from an object
- const helper = (wobj) => ({
- "weather-icon": wobj.weather[0].icon,
- "main-temperature": wobj.main.temp || 'N/A',
- "feels-like": wobj.main.feels_like || 'N/A',
- humidity: wobj.main.humidity || 'N/A',
- wind: wobj.wind.speed || 'N/A',
- "wind-gust": wobj.wind.gust || 'N/A',
- "weather-main": wobj.weather[0].main || 'N/A',
- location: wobj.name || 'N/A'
- })
- const city = "chicago";
- document.querySelector('select').value = city;
- document.querySelector('#get-forecast').click();
-
-
- // fetch the expected values from the API to confront
- const body = await fetch(`https://weather-proxy.freecodecamp.rocks/api/city/${city}`).then(
- data => data.json()
- )
-
- await new Promise(resolve => setTimeout(resolve, 800));
-
- // construct the object from the data from the API
- const extractedData = helper(body);
-
- // check that all things are in place
- for (const id in extractedData) {
- if (id === "weather-icon") {
- assert.equal(document.querySelector('#weather-icon').src, extractedData[id]);
- } else {
- assert.include(document.querySelector(`#${id}`).innerText.toLowerCase(), `${extractedData[id]}`.toLowerCase());
- }
- }
- } catch (err) {
- throw new Error(err);
+ try {
+ // function that construct an object with the id-value pairs that we expect in the page from an object
+ const helper = wobj => ({
+ 'weather-icon': wobj.weather[0].icon,
+ 'main-temperature': wobj.main.temp || 'N/A',
+ 'feels-like': wobj.main.feels_like || 'N/A',
+ humidity: wobj.main.humidity || 'N/A',
+ wind: wobj.wind.speed || 'N/A',
+ 'wind-gust': wobj.wind.gust || 'N/A',
+ 'weather-main': wobj.weather[0].main || 'N/A',
+ location: wobj.name || 'N/A'
+ });
+ const city = 'chicago';
+ document.querySelector('select').value = city;
+ document.querySelector('#get-forecast').click();
+
+ // fetch the expected values from the API to confront
+ const body = await fetch(
+ `https://weather-proxy.freecodecamp.rocks/api/city/${city}`
+ ).then(data => data.json());
+
+ await new Promise(resolve => setTimeout(resolve, 800));
+
+ // construct the object from the data from the API
+ const extractedData = helper(body);
+
+ // check that all things are in place
+ for (const id in extractedData) {
+ if (id === 'weather-icon') {
+ assert.equal(
+ document.querySelector('#weather-icon').src,
+ extractedData[id]
+ );
+ } else {
+ assert.include(
+ document.querySelector(`#${id}`).innerText.toLowerCase(),
+ `${extractedData[id]}`.toLowerCase()
+ );
+ }
}
-}
+ } catch (err) {
+ throw new Error(err);
+ }
+};
```
When London is selected the `showWeather` function should display the data from the API in the respective HTML elements. If the value from the API is `undefined`, you should show `N/A`.
```js
async () => {
- try {
- // function that construct an object with the id-value pairs that we expect in the page from an object
- const helper = (wobj) => ({
- "weather-icon": wobj.weather[0].icon,
- "main-temperature": wobj.main.temp || 'N/A',
- "feels-like": wobj.main.feels_like || 'N/A',
- humidity: wobj.main.humidity || 'N/A',
- wind: wobj.wind.speed || 'N/A',
- "wind-gust": wobj.wind.gust || 'N/A',
- "weather-main": wobj.weather[0].main || 'N/A',
- location: wobj.name || 'N/A'
- })
- const city = "london";
- document.querySelector('select').value = city;
- document.querySelector('#get-forecast').click();
-
-
- // fetch the expected values from the API to confront
- const body = await fetch(`https://weather-proxy.freecodecamp.rocks/api/city/${city}`).then(
- data => data.json()
- )
-
- await new Promise(resolve => setTimeout(resolve, 800));
-
- // construct the object from the data from the API
- const extractedData = helper(body);
-
- // check that all things are in place
- for (const id in extractedData) {
- if (id === "weather-icon") {
- assert.equal(document.querySelector('#weather-icon').src, extractedData[id]);
- } else {
- assert.include(document.querySelector(`#${id}`).innerText.toLowerCase(), `${extractedData[id]}`.toLowerCase());
- }
- }
- } catch (err) {
- throw new Error(err);
+ try {
+ // function that construct an object with the id-value pairs that we expect in the page from an object
+ const helper = wobj => ({
+ 'weather-icon': wobj.weather[0].icon,
+ 'main-temperature': wobj.main.temp || 'N/A',
+ 'feels-like': wobj.main.feels_like || 'N/A',
+ humidity: wobj.main.humidity || 'N/A',
+ wind: wobj.wind.speed || 'N/A',
+ 'wind-gust': wobj.wind.gust || 'N/A',
+ 'weather-main': wobj.weather[0].main || 'N/A',
+ location: wobj.name || 'N/A'
+ });
+ const city = 'london';
+ document.querySelector('select').value = city;
+ document.querySelector('#get-forecast').click();
+
+ // fetch the expected values from the API to confront
+ const body = await fetch(
+ `https://weather-proxy.freecodecamp.rocks/api/city/${city}`
+ ).then(data => data.json());
+
+ await new Promise(resolve => setTimeout(resolve, 800));
+
+ // construct the object from the data from the API
+ const extractedData = helper(body);
+
+ // check that all things are in place
+ for (const id in extractedData) {
+ if (id === 'weather-icon') {
+ assert.equal(
+ document.querySelector('#weather-icon').src,
+ extractedData[id]
+ );
+ } else {
+ assert.include(
+ document.querySelector(`#${id}`).innerText.toLowerCase(),
+ `${extractedData[id]}`.toLowerCase()
+ );
+ }
}
-}
+ } catch (err) {
+ throw new Error(err);
+ }
+};
```
When Tokyo is selected the `showWeather` function should display the data from the API in the respective HTML elements. If the value from the API is `undefined`, you should show `N/A`.
```js
async () => {
- try {
- // function that construct an object with the id-value pairs that we expect in the page from an object
- const helper = (wobj) => ({
- "weather-icon": wobj.weather[0].icon,
- "main-temperature": wobj.main.temp || 'N/A',
- "feels-like": wobj.main.feels_like || 'N/A',
- humidity: wobj.main.humidity || 'N/A',
- wind: wobj.wind.speed || 'N/A',
- "wind-gust": wobj.wind.gust || 'N/A',
- "weather-main": wobj.weather[0].main || 'N/A',
- location: wobj.name || 'N/A'
- })
- const city = "tokyo";
- document.querySelector('select').value = city;
- document.querySelector('#get-forecast').click();
-
-
- // fetch the expected values from the API to confront
- const body = await fetch(`https://weather-proxy.freecodecamp.rocks/api/city/${city}`).then(
- data => data.json()
- )
-
- await new Promise(resolve => setTimeout(resolve, 800));
-
- // construct the object from the data from the API
- const extractedData = helper(body);
-
- // check that all things are in place
- for (const id in extractedData) {
- if (id === "weather-icon") {
- assert.equal(document.querySelector('#weather-icon').src, extractedData[id]);
- } else {
- assert.include(document.querySelector(`#${id}`).innerText.toLowerCase(), `${extractedData[id]}`.toLowerCase());
- }
- }
- } catch (err) {
- throw new Error(err);
+ try {
+ // function that construct an object with the id-value pairs that we expect in the page from an object
+ const helper = wobj => ({
+ 'weather-icon': wobj.weather[0].icon,
+ 'main-temperature': wobj.main.temp || 'N/A',
+ 'feels-like': wobj.main.feels_like || 'N/A',
+ humidity: wobj.main.humidity || 'N/A',
+ wind: wobj.wind.speed || 'N/A',
+ 'wind-gust': wobj.wind.gust || 'N/A',
+ 'weather-main': wobj.weather[0].main || 'N/A',
+ location: wobj.name || 'N/A'
+ });
+ const city = 'tokyo';
+ document.querySelector('select').value = city;
+ document.querySelector('#get-forecast').click();
+
+ // fetch the expected values from the API to confront
+ const body = await fetch(
+ `https://weather-proxy.freecodecamp.rocks/api/city/${city}`
+ ).then(data => data.json());
+
+ await new Promise(resolve => setTimeout(resolve, 800));
+
+ // construct the object from the data from the API
+ const extractedData = helper(body);
+
+ // check that all things are in place
+ for (const id in extractedData) {
+ if (id === 'weather-icon') {
+ assert.equal(
+ document.querySelector('#weather-icon').src,
+ extractedData[id]
+ );
+ } else {
+ assert.include(
+ document.querySelector(`#${id}`).innerText.toLowerCase(),
+ `${extractedData[id]}`.toLowerCase()
+ );
+ }
}
-}
+ } catch (err) {
+ throw new Error(err);
+ }
+};
```
When Los Angeles is selected the `showWeather` function should display the data from the API in the respective HTML elements. If the value from the API is `undefined`, you should show `N/A`.
```js
async () => {
- try {
- // function that construct an object with the id-value pairs that we expect in the page from an object
- const helper = (wobj) => ({
- "weather-icon": wobj.weather[0].icon,
- "main-temperature": wobj.main.temp || 'N/A',
- "feels-like": wobj.main.feels_like || 'N/A',
- humidity: wobj.main.humidity || 'N/A',
- wind: wobj.wind.speed || 'N/A',
- "wind-gust": wobj.wind.gust || 'N/A',
- "weather-main": wobj.weather[0].main || 'N/A',
- location: wobj.name || 'N/A'
- })
- const city = "los angeles";
- document.querySelector('select').value = city;
- document.querySelector('#get-forecast').click();
-
-
- // fetch the expected values from the API to confront
- const body = await fetch(`https://weather-proxy.freecodecamp.rocks/api/city/${city}`).then(
- data => data.json()
- )
-
- await new Promise(resolve => setTimeout(resolve, 800));
-
- // construct the object from the data from the API
- const extractedData = helper(body);
-
- // check that all things are in place
- for (const id in extractedData) {
- if (id === "weather-icon") {
- assert.equal(document.querySelector('#weather-icon').src, extractedData[id]);
- } else {
- assert.include(document.querySelector(`#${id}`).innerText.toLowerCase(), `${extractedData[id]}`.toLowerCase());
- }
- }
- } catch (err) {
- throw new Error(err);
+ try {
+ // function that construct an object with the id-value pairs that we expect in the page from an object
+ const helper = wobj => ({
+ 'weather-icon': wobj.weather[0].icon,
+ 'main-temperature': wobj.main.temp || 'N/A',
+ 'feels-like': wobj.main.feels_like || 'N/A',
+ humidity: wobj.main.humidity || 'N/A',
+ wind: wobj.wind.speed || 'N/A',
+ 'wind-gust': wobj.wind.gust || 'N/A',
+ 'weather-main': wobj.weather[0].main || 'N/A',
+ location: wobj.name || 'N/A'
+ });
+ const city = 'los angeles';
+ document.querySelector('select').value = city;
+ document.querySelector('#get-forecast').click();
+
+ // fetch the expected values from the API to confront
+ const body = await fetch(
+ `https://weather-proxy.freecodecamp.rocks/api/city/${city}`
+ ).then(data => data.json());
+
+ await new Promise(resolve => setTimeout(resolve, 800));
+
+ // construct the object from the data from the API
+ const extractedData = helper(body);
+
+ // check that all things are in place
+ for (const id in extractedData) {
+ if (id === 'weather-icon') {
+ assert.equal(
+ document.querySelector('#weather-icon').src,
+ extractedData[id]
+ );
+ } else {
+ assert.include(
+ document.querySelector(`#${id}`).innerText.toLowerCase(),
+ `${extractedData[id]}`.toLowerCase()
+ );
+ }
}
-}
+ } catch (err) {
+ throw new Error(err);
+ }
+};
```
If there is an error, your `getWeather` function should log the error to the console.
@@ -490,11 +525,17 @@ const temp4 = alert;
async () => {
try {
alert = () => {};
- console.log = obj => {testArr.push(obj.toString())};
- console.error = obj => {testArr.push(obj.toString())};
- fetch = source => {throw new Error("This is a test error");}
- await getWeather("chicago");
- assert.include(testArr[0], "This is a test error");
+ console.log = obj => {
+ testArr.push(obj.toString());
+ };
+ console.error = obj => {
+ testArr.push(obj.toString());
+ };
+ fetch = source => {
+ throw new Error('This is a test error');
+ };
+ await getWeather('chicago');
+ assert.include(testArr[0], 'This is a test error');
assert.lengthOf(testArr, 1);
} finally {
fetch = temp1;
@@ -502,7 +543,7 @@ async () => {
console.error = temp3;
alert = temp4;
}
-}
+};
```
When Paris is selected the app should show an alert with `Something went wrong, please try again later`.
@@ -512,17 +553,19 @@ const testArr = [];
const temp4 = alert;
async () => {
try {
- alert = (msg) => {testArr.push(msg)};
- const city = "paris";
+ alert = msg => {
+ testArr.push(msg);
+ };
+ const city = 'paris';
document.querySelector('select').value = city;
document.querySelector('#get-forecast').click();
await new Promise(resolve => setTimeout(resolve, 800));
- assert.include(testArr[0], "Something went wrong, please try again later");
+ assert.include(testArr[0], 'Something went wrong, please try again later');
assert.lengthOf(testArr, 1);
} finally {
alert = temp4;
}
-}
+};
```
# --seed--
@@ -530,20 +573,15 @@ async () => {
## --seed-contents--
```html
-
+
-
-
-
+
+
Weather App
-
-
-
-
-
+
+
-
```
```css
@@ -557,68 +595,66 @@ async () => {
# --solutions--
```html
-
+
-
-
-
+
+
Weather App
-
-
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
- Weather for:
-
-
- New York
- Los Angeles
- Chicago
- Paris
- Tokyo
- London
-
- Get Forecast
+ Weather for:
+
+
+ New York
+ Los Angeles
+ Chicago
+ Paris
+ Tokyo
+ London
+
+ Get Forecast
-
-
+
```
@@ -648,7 +684,7 @@ body {
padding: 20px;
border-radius: 10px;
background-color: #6cd488;
- box-shadow: 6px 6px 6px rgba(0,0,0,0.5);
+ box-shadow: 6px 6px 6px rgba(0, 0, 0, 0.5);
}
.btn-wrap > span {
@@ -658,7 +694,7 @@ body {
}
.btn-wrap > span::first-letter {
- font-size: 1.3em
+ font-size: 1.3em;
}
#location-selector {
@@ -682,7 +718,7 @@ body {
background-color: #eee;
border-radius: 10px;
border: 2px solid black;
- box-shadow: 6px 6px 6px rgba(0,0,0,0.5);
+ box-shadow: 6px 6px 6px rgba(0, 0, 0, 0.5);
}
#weather-info {
@@ -781,13 +817,15 @@ body {
background-color: black;
}
-.north, .south {
+.north,
+.south {
width: 3px;
height: 8px;
left: 50%;
}
-.east, .west {
+.east,
+.west {
width: 8px;
height: 3px;
top: 50%;
@@ -825,20 +863,16 @@ const mainEl = document.getElementById('weather-main');
const locationEl = document.getElementById('location');
const arrowEl = document.getElementById('compass-arrow');
-getForecastBtn.addEventListener('click', () =>
- selectEl.value && showWeather(selectEl.value)
+getForecastBtn.addEventListener(
+ 'click',
+ () => selectEl.value && showWeather(selectEl.value)
);
async function showWeather(city) {
const json = await getWeather(city);
const {
weather,
- main:
- {
- temp,
- feels_like,
- humidity
- },
+ main: { temp, feels_like, humidity },
wind: { speed, gust, deg = 0 },
name
} = json;
@@ -861,7 +895,9 @@ async function showWeather(city) {
async function getWeather(city) {
try {
- const response = await fetch(`https://weather-proxy.freecodecamp.rocks/api/city/${city}`)
+ const response = await fetch(
+ `https://weather-proxy.freecodecamp.rocks/api/city/${city}`
+ );
if (!response.ok) {
alert('Something went wrong, please try again later');
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-best-practices-for-accessibility-and-css/672c35a79fa53e00de9f2a49.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-best-practices-for-accessibility-and-css/672c35a79fa53e00de9f2a49.md
index 830ac0e056..17f41fe05f 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-best-practices-for-accessibility-and-css/672c35a79fa53e00de9f2a49.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-best-practices-for-accessibility-and-css/672c35a79fa53e00de9f2a49.md
@@ -14,35 +14,35 @@ Watch the lecture video and answer the questions below.
## --text--
-Which CSS property hides content visually but keeps it in the document flow and accessible to screen readers?
+What is the main accessibility issue when using the `display: none` and `visibility: hidden` style declarations, or the `hidden` attribute to hide content?
## --answers--
-`display: none;`
+These methods make it so that only assistive technologies like screen readers can access the hidden content.
### --feedback--
-Think about which property affects layout but not screen reader access.
+Think about the accessibility concern each of these methods has in common.
---
-`visibility: hidden;`
+Content is only hidden until users move their mouse over the content.
### --feedback--
-Think about which property affects layout but not screen reader access.
+Think about the accessibility concern each of these methods has in common.
---
-`opacity: 0;`
+These methods remove the content from the accessibility tree, making it impossible for assistive technologies like screen readers to access the hidden content.
---
-`position: absolute; left: -9999px;`
+These methods do not work with some browsers.
### --feedback--
-Think about which property affects layout but not screen reader access.
+Think about the accessibility concern each of these methods has in common.
## --video-solution--
@@ -50,7 +50,7 @@ Think about which property affects layout but not screen reader access.
## --text--
-What is the primary purpose of the "visually hidden" or "sr-only" CSS technique?
+What is the primary purpose of the "visually hidden" or "screen reader only" CSS technique?
## --answers--
@@ -86,35 +86,35 @@ Consider the needs of users who rely on screen readers.
## --text--
-When using the aria-hidden attribute, what effect does it have on content?
+When should you hide content on a web page?
## --answers--
-It makes the content invisible.
+When the content you're hiding is less important than other content on the page.
### --feedback--
-Think about how this attribute affects the accessibility tree.
+Think about how hiding content affects accessibility and the user experience as a whole.
---
-It removes the content from the DOM.
+When the content you're hiding is incorrect.
### --feedback--
-Think about how this attribute affects the accessibility tree.
+Think about how hiding content affects accessibility and the user experience as a whole.
---
-It tells assistive technologies to ignore the content.
+Only when it genuinely enhances the user experience.
---
-It makes the content unclickable.
+Whenever you feel like it.
### --feedback--
-Think about how this attribute affects the accessibility tree.
+Think about how hiding content affects accessibility and the user experience as a whole.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-best-practices-for-responsive-web-design/672cf07a2b9796eb49719e03.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-best-practices-for-responsive-web-design/672cf07a2b9796eb49719e03.md
index 2537cf3d3a..8f39dba92b 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-best-practices-for-responsive-web-design/672cf07a2b9796eb49719e03.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-best-practices-for-responsive-web-design/672cf07a2b9796eb49719e03.md
@@ -50,35 +50,35 @@ Think about how websites adapt to various device sizes.
## --text--
-In a mobile-first approach, which type of media query is typically used for breakpoints?
+Which of the following is a commonly used breakpoint for smaller devices like smart phones?
## --answers--
-`max-width`
+1640px
### --feedback--
-Consider how styles are added as screen sizes increase from mobile to desktop.
+Review the beginning of the video to see where this was discussed.
---
-`min-width`
+640px
---
-`max-height`
+1200px
### --feedback--
-Consider how styles are added as screen sizes increase from mobile to desktop.
+Review the beginning of the video to see where this was discussed.
---
-`min-height`
+2000px
### --feedback--
-Consider how styles are added as screen sizes increase from mobile to desktop.
+Review the beginning of the video to see where this was discussed.
## --video-solution--
@@ -114,7 +114,7 @@ Think about which screen resolution is less commonly targeted in responsive desi
---
-`2560px` (4K displays).
+`6000px` (really large device).
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-common-design-tools/672bb619f0d4538d0528760d.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-common-design-tools/672bb619f0d4538d0528760d.md
index 1f8865f3c2..b201185a11 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-common-design-tools/672bb619f0d4538d0528760d.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-common-design-tools/672bb619f0d4538d0528760d.md
@@ -94,7 +94,7 @@ Complex video editing features.
### --feedback--
-Consider Adobe XD’s primary use in UI/UX design and its relationship with other Adobe tools.
+Consider Adobe XD's primary use in UI/UX design and its relationship with other Adobe tools.
---
@@ -106,7 +106,7 @@ Being a raster-based image editor.
### --feedback--
-Consider Adobe XD’s primary use in UI/UX design and its relationship with other Adobe tools.
+Consider Adobe XD's primary use in UI/UX design and its relationship with other Adobe tools.
---
@@ -114,7 +114,7 @@ Specialized 3D modeling capabilities.
### --feedback--
-Consider Adobe XD’s primary use in UI/UX design and its relationship with other Adobe tools.
+Consider Adobe XD's primary use in UI/UX design and its relationship with other Adobe tools.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-debugging-techniques/6733aa9b006d29f4d11307a5.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-debugging-techniques/6733aa9b006d29f4d11307a5.md
index 0b6eb0b1b0..97f2f84848 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-debugging-techniques/6733aa9b006d29f4d11307a5.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-debugging-techniques/6733aa9b006d29f4d11307a5.md
@@ -22,15 +22,15 @@ Trying to call a variable like a function.
### --feedback--
-It’s like grammar for your code.
+It's like grammar for your code.
---
-Trying to use a value that’s out of range.
+Trying to use a value that's out of range.
### --feedback--
-It’s like grammar for your code.
+It's like grammar for your code.
---
@@ -38,11 +38,11 @@ Writing something incorrectly in your code, like missing a parenthesis or semico
---
-Accessing a variable before it’s declared.
+Accessing a variable before it's declared.
### --feedback--
-It’s like grammar for your code.
+It's like grammar for your code.
## --video-solution--
@@ -58,7 +58,7 @@ What will happen if you try to call a variable that holds a number as if it were
### --feedback--
-The error happens because the variable is being treated like a function when it’s not.
+The error happens because the variable is being treated like a function when it's not.
---
@@ -66,7 +66,7 @@ The error happens because the variable is being treated like a function when it
### --feedback--
-The error happens because the variable is being treated like a function when it’s not.
+The error happens because the variable is being treated like a function when it's not.
---
@@ -78,7 +78,7 @@ The error happens because the variable is being treated like a function when it
### --feedback--
-The error happens because the variable is being treated like a function when it’s not.
+The error happens because the variable is being treated like a function when it's not.
## --video-solution--
@@ -86,7 +86,7 @@ The error happens because the variable is being treated like a function when it
## --text--
-Which error occurs when you try to access an array index that doesn’t exist?
+Which error occurs when you try to access an array index that doesn't exist?
## --answers--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-html-fundamentals/670803abcb3e980233da4768.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-html-fundamentals/670803abcb3e980233da4768.md
index a6032fda57..6082d4b9f3 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-html-fundamentals/670803abcb3e980233da4768.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-html-fundamentals/670803abcb3e980233da4768.md
@@ -2,7 +2,7 @@
id: 670803abcb3e980233da4768
title: What are Div Elements and When Should You Use Them?
challengeType: 11
-videoId: nVAaxZ34khk
+videoId: NFAto1m5EhI
dashedName: what-are-div-elements
---
@@ -14,35 +14,35 @@ Watch the video and answer the questions below.
## --text--
-What type of element is a `div` element?
+What semantic meaning does a `div` element have?
## --answers--
-An inline-level element.
+The `div` element represents a container for introductory content or a set of navigational links.
### --feedback--
-Think about how a `div` element occupies space.
+Think about why it is a ghost.
---
-An inline-block element.
+The `div` element defines a footer for a document or section.
### --feedback--
-Think about how a `div` element occupies space.
+Think about why it is a ghost.
---
-A block-inline element.
+The `div` specifies the main page content and should be unique.
### --feedback--
-Think about how a `div` element occupies space.
+Think about why it is a ghost.
---
-A block-level element.
+The `div` element has no semantic meaning.
## --video-solution--
@@ -94,35 +94,57 @@ Review the beginning of the video for the correct syntax.
## --text--
-What should you group using a `div` element?
+What is the correct syntax for using a `div` to group elements together?
## --answers--
-Block-level content and larger sections.
+```html
+
+
I'm a paragraph
+
I'm another paragraph
+
+```
---
-Inline texts and smaller sections.
+```html
+
+
I'm a paragraph
+
I'm another paragraph
+
+```
### --feedback--
-Think about related and larger content.
+Review the middle part of the video for the correct syntax.
---
-The whole HTML content.
+```html
+
+
+
I'm another paragraph
+
+```
### --feedback--
-Think about related and larger content.
+Review the middle part of the video for the correct syntax.
---
-Images and media files only.
+```html
+
I'm a paragraph
+
I'm another paragraph
+/>
+```
### --feedback--
-Think about related and larger content.
+Review the middle part of the video for the correct syntax.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-html-fundamentals/6708143cab2b583ecd3324f5.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-html-fundamentals/6708143cab2b583ecd3324f5.md
index adef974b6d..715cff09bf 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-html-fundamentals/6708143cab2b583ecd3324f5.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-html-fundamentals/6708143cab2b583ecd3324f5.md
@@ -2,7 +2,7 @@
id: 6708143cab2b583ecd3324f5
title: What Are Attributes, and How Do They Work?
challengeType: 11
-videoId: nVAaxZ34khk
+videoId: zUCIsEDCIMU
dashedName: what-are-attributes
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-html-fundamentals/6708382cf088b216580a9ff1.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-html-fundamentals/6708382cf088b216580a9ff1.md
index d3e6ff98df..22c5a4e439 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-html-fundamentals/6708382cf088b216580a9ff1.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-html-fundamentals/6708382cf088b216580a9ff1.md
@@ -116,10 +116,6 @@ Only classes can hold multiple separate values.
`id="main heading"`
-### --feedback--
-
-Only classes can hold multiple separate values.
-
## --video-solution--
4
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-importance-of-accessibility-and-good-html-structure/672a536f8386288b9ed0a154.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-importance-of-accessibility-and-good-html-structure/672a536f8386288b9ed0a154.md
index ea40b20532..45fc8e9a14 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-importance-of-accessibility-and-good-html-structure/672a536f8386288b9ed0a154.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-importance-of-accessibility-and-good-html-structure/672a536f8386288b9ed0a154.md
@@ -94,7 +94,7 @@ Dragon.
### --feedback--
-Most voice recognition software, especially ones that come bundled with operating systems, often include words like “control“ or “access“. Focus on the options that don’t follow this convention.
+Most voice recognition software, especially ones that come bundled with operating systems, often include words like "control" or "access". Focus on the options that don't follow this convention.
---
@@ -106,7 +106,7 @@ Voice Control.
### --feedback--
-Most voice recognition software, especially ones that come bundled with operating systems, often include words like “control“ or “access“. Focus on the options that don’t follow this convention.
+Most voice recognition software, especially ones that come bundled with operating systems, often include words like "control" or "access". Focus on the options that don't follow this convention.
---
@@ -114,7 +114,7 @@ Voice Access.
### --feedback--
-Most voice recognition software, especially ones that come bundled with operating systems, often include words like “control“ or “access“. Focus on the options that don’t follow this convention.
+Most voice recognition software, especially ones that come bundled with operating systems, often include words like "control" or "access". Focus on the options that don't follow this convention.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript-libraries-and-frameworks/6734e3a9cc78faaf4248d335.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript-libraries-and-frameworks/6734e3a9cc78faaf4248d335.md
index 051b5c4ea8..87f6104018 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript-libraries-and-frameworks/6734e3a9cc78faaf4248d335.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript-libraries-and-frameworks/6734e3a9cc78faaf4248d335.md
@@ -1,20 +1,50 @@
---
id: 6734e3a9cc78faaf4248d335
title: What Is the Role of JS Libraries and Frameworks, and Why Are They Used in the Industry?
-challengeType: 11
-videoId: nVAaxZ34khk
+challengeType: 19
+#videoId: nVAaxZ34khk
dashedName: what-is-the-role-of-js-libraries-and-frameworks-and-why-are-they-used-in-the-industry
---
# --description--
-Watch the video lecture and answer the questions below.
+The video for this lecture isn't available yet, one will be available soon. Here is a transcript of the lecture for now:
+
+JavaScript libraries and frameworks provide pre-built code that streamlines the development process. While both libraries and frameworks serve to improve productivity and standardize coding practices, they differ in their approach and level of control they provide to developers.
+
+Libraries are generally more focused on providing solutions to specific tasks, such as manipulating the DOM, handling events, or managing AJAX requests.
+
+An example of a JavaScript library is jQuery.
+
+jQuery became very popular in the early 2010s and was widely used to simplify DOM manipulation, event handling, animations, effects, and more. This library also offered a rich ecosystem of plugins, which made it easy to build common web components like datepickers, sliders, and modal dialogs.
+
+Although jQuery is no longer as widely used as it once was, it significantly helped developers by making tasks that were complex in vanilla JavaScript much easier to implement.
+
+Frameworks, on the other hand, provide a more defined structure for building applications. They often come with a set of rules and conventions that developers need to follow.
+
+For example, Angular encourages a component-based architecture with a set of conventions and tools that provide a structured approach to organizing and building applications. Angular gives developers clear guidelines on how to structure components, manage state, handle routing, and interact with services, making it a more opinionated framework.
+
+Other examples of frameworks include Remix and NextJS.
+
+In contrast, React, a UI library, is more flexible and doesn't enforce any particular architectural pattern. React focuses primarily on the view layer and leaves a lot of the choices on application design up to the developers.
+
+Although libraries and frameworks are used across projects of all sizes, The choice between using them often depends on the project's requirements. Libraries offer flexibility for specific functionalities, while frameworks provide a structured approach towards complex applications.
+
+In the industry, libraries and frameworks are widely used for several reasons. They significantly speed up development by providing quick solutions for common problems.
+
+One common problem in JavaScript is working with dates and timezones. But there are libraries out there with built in solutions to help you with date manipulation, timezones, parsing and formatting of dates.
+
+A lot of popular libraries and frameworks are well-tested and maintained by large communities. This means they're often more practical than building the same thing from scratch.
+
+Libraries and frameworks follow best practices and patterns that have been proven effective in real life scenarios. This can lead to more robust and scalable applications.
+
+In conclusion, libraries and frameworks offer quick solutions to common problems, speed up development, and promote best practices. Understanding the differences between libraries and frameworks, and knowing when to use them is a valuable skill for any JavaScript developer.
# --questions--
## --text--
-Why was jQuery a popular library of choice in the early 2010’s?
+Why was jQuery a popular library of choice in the early 2010's?
## --answers--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript-libraries-and-frameworks/6734e867bbf41cc5b11648c4.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript-libraries-and-frameworks/6734e867bbf41cc5b11648c4.md
index f643612a40..6384efbdf9 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript-libraries-and-frameworks/6734e867bbf41cc5b11648c4.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript-libraries-and-frameworks/6734e867bbf41cc5b11648c4.md
@@ -1,14 +1,32 @@
---
id: 6734e867bbf41cc5b11648c4
title: What Are Single Page Applications, and What Are Some Issues Surrounding Them?
-challengeType: 11
-videoId: nVAaxZ34khk
+challengeType: 19
+#videoId: nVAaxZ34khk
dashedName: what-are-single-page-applications-and-what-are-some-issues-surrounding-them
---
# --description--
-Watch the lecture video and answer the questions below.
+The video for this lecture isn't available yet, one will be available soon. Here is a transcript of the lecture for now:
+
+Unlike traditional multi-page websites, single page applications (SPAs) load only one HTML page and dynamically update the content as the user interacts with the app, without reloading the entire page. This approach can lead to faster, more responsive applications, but it also comes a set of challenges and considerations.
+
+SPAs heavily use JavaScript to manage the application's state and render content. Instead of requesting new HTML pages from the server, SPAs use JavaScript to manipulate the DOM and fetch data asynchronously. This is often done using libraries and frameworks like React, Vue, or Angular, which provide great tools for building complex user interfaces.
+
+SPAs have some common issues. One significant issue is that screen readers may struggle with dynamically updated content. When content changes without a page reload/refresh, screen readers might not notify these changes, which makes our users unaware of updates on our web app.
+
+Another challenge with SPAs is with navigation and browser history. Users expect the back and forward buttons to work as they do on traditional websites. This might not work properly in SPAs because technically, the URL of the web app doesn’t change. Since, the URL of the web app doesn’t change, they can’t bookmark any specific page. Refreshing the page might reset the application to its initial state, rather than maintaining the current view.
+
+SPAs can pose challenges for SEO optimization.
+
+Search engines like Google can have difficulty indexing dynamically loaded content because they may not execute JavaScript properly or may miss content that isn’t included in the initial HTML page. This can lead to pages not being indexed correctly.
+
+However, modern search engines have improved their ability to crawl SPAs, and there are techniques such as server-side rendering (SSR), pre rendering, and the use of SEO-friendly URLs that can help mitigate these issues and improve SEO for SPAs.
+
+Performance is another consideration. SPAs load the entire application in one go, which means that if the loading time increases, users will be seeing a blank screen for a longer period of time. Now consider the scenario of users with slower internet speeds. Overall, the user experience will not be very pleasant.
+
+In conclusion, while Single Page Applications offer many benefits, they also present unique challenges. Developers need to be careful of accessibility, usability, SEO, and performance considerations when building SPAs. By addressing these issues, it's possible to create SPAs that are fast, responsive, and accessible to all users.
# --questions--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript-libraries-and-frameworks/6734e86f590727c5e7e9ec5e.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript-libraries-and-frameworks/6734e86f590727c5e7e9ec5e.md
index 41ae2d9b62..5c3163ec9d 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript-libraries-and-frameworks/6734e86f590727c5e7e9ec5e.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript-libraries-and-frameworks/6734e86f590727c5e7e9ec5e.md
@@ -1,14 +1,30 @@
---
id: 6734e86f590727c5e7e9ec5e
title: What Is React, and What Is It Commonly Used For?
-challengeType: 11
-videoId: nVAaxZ34khk
+challengeType: 19
+#videoId: nVAaxZ34khk
dashedName: what-is-react-and-what-is-it-commonly-used-for
---
# --description--
-Watch the lecture video and answer the questions below.
+The video for this lecture isn't available yet, one will be available soon. Here is a transcript of the lecture for now:
+
+React is one of the most popular JavaScript libraries for building user interfaces and web applications. Originally developed and maintained by Facebook, React has gained huge popularity in web development due to its efficiency, flexibility, and features.
+
+A fundamental concept in React is the creation of reusable UI components. These components, such as buttons, cards, and avatar components, can be easily reused throughout your application. You can nest these components inside each other to build more complex, dynamic interfaces.
+
+One of the key advantages of React is that these custom components can update and render independently as data changes.
+
+Unlike traditional JavaScript, which requires direct manipulation of the DOM (Document Object Model), React uses a virtual DOM, which improves performance and efficiency. You’ll learn more about the virtual DOM and how it works in upcoming lecture videos.
+
+In addition to reusable components, React also provides a powerful way to manage the state of your application. State refers to the data that determines how a component renders and behaves.
+
+With React, you can easily track and update the state of components, ensuring that the UI reflects the most current data. You will learn more about working with state in future lecture videos.
+
+While there are many libraries within the JavaScript ecosystem, freeCodeCamp will mainly be focused on teaching React because of its wide spread use and demand in the industry.
+
+Over the next few lectures, we will dive deeper into building custom components, managing state, and more.
# --questions--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript-libraries-and-frameworks/6734e879c78ee6c61db25b90.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript-libraries-and-frameworks/6734e879c78ee6c61db25b90.md
index 419372cd3e..c0d9ac8920 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript-libraries-and-frameworks/6734e879c78ee6c61db25b90.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript-libraries-and-frameworks/6734e879c78ee6c61db25b90.md
@@ -1,14 +1,117 @@
---
id: 6734e879c78ee6c61db25b90
title: What Are Components in React, and How Do They Work?
-challengeType: 11
-videoId: nVAaxZ34khk
+challengeType: 19
+#videoId: nVAaxZ34khk
dashedName: what-are-components-in-react-and-how-do-they-work
---
# --description--
-Watch the lecture video and answer the questions below.
+The video for this lecture isn't available yet, one will be available soon. Here is a transcript of the lecture for now:
+
+Components are the building blocks of React applications that allow developers to break down complex user interfaces into smaller, manageable pieces, making it easier to develop and maintain large-scale applications.
+
+The two types of components in React are functional and class based components. In modern React, developers will use functional components and all of the examples we look at today will be functional components.
+
+At a higher level, you can think of component like JavaScript functions that return elements describing the UI.
+
+This UI is described using JSX, a syntax extension for JavaScript that looks similar to HTML but allows you to write UI elements in a more declarative way.
+
+Let's look at an example of a React component:
+
+```js
+function Greeting() {
+ const name = "John"
+ {/* The result will be Hello John*/}
+ return
Hello {name} ;
+}
+```
+
+In this example, we've defined a component called Greeting. The curly braces `{}` inside the `h1` tags enable us to embed JavaScript expressions, allowing us to access the name variable within the h1 element.
+
+We are also applying a `className` called title to the `h1` element.
+
+But why are we using `className` instead of class like with regular HTML elements?
+
+Well this is because in JavaScript, `class` is a reserved name. So, we need to use `className` instead.
+
+We are also using a comment in JSX showing what the result will be. It is important to note that you can use regular comment syntax like this but it needs to be wrapped in curly braces in order for it to work.
+
+```js
+{/* Block Comments */}
+```
+
+Another thing you might have noticed is that we are using a capital letter at the beginning of the component name. But why can’t we use all lower case letters?
+
+This is because React treats components with a capital letter as custom components, while elements with lowercase letters are considered built-in HTML elements.
+
+When React encounters a lowercase tag (like `
` or `
`), it assumes it's a standard HTML element. However, if the component name starts with a capital letter, React will treat it as a user-defined component and render it accordingly. This distinction helps React differentiate between native HTML tags and components that you create.
+
+To use this `Greeting` component in our application, we would write something like this:
+
+```js
+
+```
+
+This would render an `` element with the text `"Hello, John"` to the page. But take a closer look at the syntax here. When we use the component, it ends with a forward slash and then the greater than symbol.
+
+When working with JSX, all tags and uses of components need to be explicitly closed. So if the component or tag does not have any children, then you need to explicitly close it like shown here
+
+```js
+
+
+```
+
+So far we have only been looking at how to render a single h1 element. But you can actually render multiple elements.
+
+Let’s take a look at the following example code here:
+
+```js
+function Greeting() {
+ const name = "John";
+ {/* This will throw an error */}
+ return Hello {name}
+ Nice to meet you.
+}
+```
+
+We are trying to add another sentence of `"Nice to meet you"` but it is not rendering on the page correctly.
+
+There seems to be an error message instead. The error message says `"Adjacent JSX elements must be wrapped in an enclosing tag."`
+
+The reason why you are getting that error message is because multiple sibling elements need to be wrapped in a parent element. While you could wrap the h1 and p elements in a single div, there is another way to silence the error.
+
+React ``s are used to group elements together.
+
+Here is what the revised example will look like:
+
+```js
+function Greeting() {
+ const name = "John";
+ return (
+
+ Hello {name}
+ Nice to meet you.
+
+ );
+}
+```
+
+You can also choose to use empty JSX tags which can serve as shorthand for Fragments.
+
+```js
+ function Greeting() {
+ const name = "John";
+ return (
+ <>
+ Hello {name}
+ Nice to meet you.
+ >
+ );
+}
+```
+
# --questions--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript-libraries-and-frameworks/6734e88cc46e6dc679420040.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript-libraries-and-frameworks/6734e88cc46e6dc679420040.md
index 158d5b4c12..cfd23df155 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript-libraries-and-frameworks/6734e88cc46e6dc679420040.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript-libraries-and-frameworks/6734e88cc46e6dc679420040.md
@@ -1,14 +1,63 @@
---
id: 6734e88cc46e6dc679420040
title: What is Vite and How Can It Be Used to Setup a New React Project?
-challengeType: 11
-videoId: nVAaxZ34khk
+challengeType: 19
+#videoId: nVAaxZ34khk
dashedName: what-is-vite-and-how-can-it-be-used-to-setup-a-new-react-project
---
# --description--
-Watch the lecture video and answer the questions below.
+The video for this lecture isn't available yet, one will be available soon. Here is a transcript of the lecture for now:
+
+Unlike working with smaller vanilla HTML, CSS, and JavaScript projects, starting a new React project includes a few more steps to ensure that everything runs correctly. Instead of trying to setup of all of the necessary configurations by yourself, there are tools that will do that for you.
+
+One of the most popular tools for setting up projects is Vite. Vite, which means "fast" in French, is a build tool that aims to provide a faster development experience for modern web projects. Vite can be used with React, as well as with other libraries and frameworks like Vue or Svelte. You can even use it with vanilla JavaScript projects.
+
+To create a new project with Vite, you will need to use the command line. If you are using Windows machine, then you can use the Command Prompt or Windows PowerShell. If you are using a Mac, then you can use the Terminal app.
+
+Once you have the command line open, you can use the following command:
+
+```bash
+npm create vite@latest my-react-app -- --template react
+```
+
+This command creates a new React project named `my-react-app` using Vite's React template.
+
+You can then open up the new project and see the React boilerplate code that Vite has provided for you.
+
+The great thing about Vite is that it will only provide the files that are absolutely necessary to get started with your React project.
+
+To actually run the project as is, you will need to install the dependencies using the following commands in the command line:
+
+```bash
+ cd my-react-app
+ npm install
+```
+
+The `cd my-react-app` command ensures that you change to the correct directory where your project is located.
+
+The `npm install` command is used to install the dependencies needed to properly run your React project. Dependencies are libraries or packages that your React project requires in order to function correctly, such as React itself, ReactDOM, or other third-party packages that provide additional functionality.
+
+Running `npm install` will read the `package.json` file in your project directory and install all the dependencies listed there, allowing you to build and run your React app without missing any necessary components.
+
+The `package.json` file is a key configuration file in projects that contains metadata about your project, including its name, version, and dependencies. It also defines scripts, licensing information, and other settings that help manage the project and its dependencies.
+
+Once the dependencies are installed, you should notice a new folder in your project called `node_modules`.
+
+The `node_modules` folder is where all the packages and libraries required by your project are stored. This folder contains the actual code for the dependencies listed in your package.json file, including both your project's direct dependencies and any dependencies of those dependencies.
+
+To run your project, run the `npm run dev` command and open up a new browser tab at `http://localhost:5173/`.
+
+You should see the starter template that Vite has provided for you.
+
+If you need to stop the local server, press `CTRL + C` in the command line.
+
+To actually see the code for this starter template, you can go into your project inside the src folder and you should see the `App.jsx` file.
+
+From there you can start to modify the file, save your changes and see the new changes display in the browser.
+
+And with that, you're ready to begin building your React application!
# --questions--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript-libraries-and-frameworks/674ba6876f7ada867135bb95.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript-libraries-and-frameworks/674ba6876f7ada867135bb95.md
index ea0054f4ca..bbc991edf0 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript-libraries-and-frameworks/674ba6876f7ada867135bb95.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript-libraries-and-frameworks/674ba6876f7ada867135bb95.md
@@ -1,14 +1,106 @@
---
id: 674ba6876f7ada867135bb95
title: How Can You Import and Export Components in React?
-challengeType: 11
-videoId: nVAaxZ34khk
+challengeType: 19
+#videoId: nVAaxZ34khk
dashedName: how-can-you-import-and-export-components-in-react
---
# --description--
-Watch the lecture video and answer the questions below.
+The video for this lecture isn't available yet, one will be available soon. Here is a transcript of the lecture for now:
+
+In this lecture, we will take a look at how to import and export components in React.
+
+In this example, we have a `Cat` component that belongs in a file called `Cat.jsx`. For the file extension, we are using the jsx file extension because this file is mainly working with JSX.
+
+```js
+function Cat() {
+ return (
+
+
Mr. Whiskers
+
+
+ );
+}
+```
+
+This `Cat` component returns a JSX markup with a title and image for a cat called Mr.Whiskers.
+
+If we want to use our `Cat` component in another file, we need to first export it like this:
+
+```js
+function Cat() {
+ return (
+
+
Mr. Whiskers
+
+
+ );
+}
+
+export default Cat;
+```
+
+We are using the default keyword because this will be the default export from the module. You can also choose to export the component on the same line as the component definition like this:
+
+```js
+export default function Cat() {
+ return (
+
+
Mr. Whiskers
+
+
+ );
+}
+```
+
+You can choose to import child components in other parent component files. Or import them in the root component file. For this example, we will import the Cat component inside the root component file.
+
+Every React project will have a top-level component, typically called `App.jsx`. This file is usually located in the src directory of your project. You’ll learn more about common project layouts in a future lecture video.
+
+```js
+export default function App() {
+ return (
+ // return component here
+ );
+}
+```
+
+To use the `Cat` component inside the root `App` component, you will need to import it like this:
+
+```js
+import Cat from "./Cat";
+
+export default function App() {
+ return (
+ // return component here
+ );
+}
+```
+
+Now, you can return the `Cat` component inside the `App` component like this:
+
+```js
+import Cat from "./Cat";
+
+export default function App() {
+ return (
+
+ );
+}
+```
+
+As you continue building your own React projects, you’ll become more comfortable organizing components, importing them where needed, and creating sophisticated UIs by composing these modular components.
# --questions--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript/672d26385dbe73203c4dac81.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript/672d26385dbe73203c4dac81.md
index 6ca9e5d940..540aa9a2dd 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript/672d26385dbe73203c4dac81.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript/672d26385dbe73203c4dac81.md
@@ -58,7 +58,7 @@ JavaScript adds more styles to the CSS file.
### --feedback--
-Think about how JavaScript can change the webpage’s content or styles without needing a page reload.
+Think about how JavaScript can change the webpage's content or styles without needing a page reload.
---
@@ -66,7 +66,7 @@ JavaScript creates a new version of HTML for the page.
### --feedback--
-Think about how JavaScript can change the webpage’s content or styles without needing a page reload.
+Think about how JavaScript can change the webpage's content or styles without needing a page reload.
---
@@ -78,7 +78,7 @@ JavaScript only works in the backend.
### --feedback--
-Think about how JavaScript can change the webpage’s content or styles without needing a page reload.
+Think about how JavaScript can change the webpage's content or styles without needing a page reload.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript/672d497cb1a1675e47bf7ea1.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript/672d497cb1a1675e47bf7ea1.md
index e39d154003..1020c4b8d3 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript/672d497cb1a1675e47bf7ea1.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript/672d497cb1a1675e47bf7ea1.md
@@ -90,7 +90,7 @@ Why is it important to use descriptive names for your variables?
## --answers--
-It’s required by JavaScript.
+It's required by JavaScript.
### --feedback--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript/672d49959621885e9d3e672c.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript/672d49959621885e9d3e672c.md
index 046193f28b..889b2fe97d 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript/672d49959621885e9d3e672c.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript/672d49959621885e9d3e672c.md
@@ -66,7 +66,7 @@ When you want to track a value that will change during program execution.
---
-When you want to declare a variable but don’t want it to be accessible in a specific block of code.
+When you want to declare a variable but don't want it to be accessible in a specific block of code.
### --feedback--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript/672d49e65a1c855fe7bb3fdb.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript/672d49e65a1c855fe7bb3fdb.md
index ab6814c50b..f86b39c3de 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript/672d49e65a1c855fe7bb3fdb.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-introduction-to-javascript/672d49e65a1c855fe7bb3fdb.md
@@ -98,7 +98,7 @@ Think about how comments help clarify but should not clutter the code.
---
-Only use comments for complex logic or unclear code.
+Use comments to provide context and leave notes for yourself and other developers.
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-understanding-computer-internet-and-tooling-basics/672ab849aa1ef70eefd29364.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-understanding-computer-internet-and-tooling-basics/672ab849aa1ef70eefd29364.md
index dba5d2ea48..0fcef9d4cc 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-understanding-computer-internet-and-tooling-basics/672ab849aa1ef70eefd29364.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-understanding-computer-internet-and-tooling-basics/672ab849aa1ef70eefd29364.md
@@ -14,7 +14,7 @@ Watch the lecture video and answer the questions below.
## --text--
-Which of the follow is considered an unsafe password?
+Which of the following is considered an unsafe password?
## --answers--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-understanding-how-to-work-with-floats-and-positioning-in-css/672c3a84fb8d4613776cc99e.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-understanding-how-to-work-with-floats-and-positioning-in-css/672c3a84fb8d4613776cc99e.md
index edff7974ad..e145d64473 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-understanding-how-to-work-with-floats-and-positioning-in-css/672c3a84fb8d4613776cc99e.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-understanding-how-to-work-with-floats-and-positioning-in-css/672c3a84fb8d4613776cc99e.md
@@ -22,7 +22,7 @@ Which of the following is the default positioning for all elements?
### --feedback--
-Think about what kind of positioning doesn’t need any special CSS declaration.
+Think about what kind of positioning doesn't need any special CSS declaration.
---
@@ -30,7 +30,7 @@ Think about what kind of positioning doesn’t need any special CSS declaration.
### --feedback--
-Think about what kind of positioning doesn’t need any special CSS declaration.
+Think about what kind of positioning doesn't need any special CSS declaration.
---
@@ -38,7 +38,7 @@ Think about what kind of positioning doesn’t need any special CSS declaration.
### --feedback--
-Think about what kind of positioning doesn’t need any special CSS declaration.
+Think about what kind of positioning doesn't need any special CSS declaration.
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-understanding-how-to-work-with-floats-and-positioning-in-css/672c3a8fac7c5613b4bb75de.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-understanding-how-to-work-with-floats-and-positioning-in-css/672c3a8fac7c5613b4bb75de.md
index 5b2646ed2c..db49a6e67b 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-understanding-how-to-work-with-floats-and-positioning-in-css/672c3a8fac7c5613b4bb75de.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-understanding-how-to-work-with-floats-and-positioning-in-css/672c3a8fac7c5613b4bb75de.md
@@ -106,7 +106,7 @@ Consider what the element falls back to when no positioned ancestor is available
---
-Relative to the initial containing block (usually the browser’s viewport).
+Relative to the initial containing block (usually the browser's viewport).
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-arrays/67329f508a6ec45b046700b3.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-arrays/67329f508a6ec45b046700b3.md
index 273ad05c90..dabc6bc4a6 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-arrays/67329f508a6ec45b046700b3.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-arrays/67329f508a6ec45b046700b3.md
@@ -14,40 +14,35 @@ Watch the video lecture and answer the questions below.
## --text--
-What will be the output of the following code?
-
-```js
-let numbers = [1, 2, 3, 4, 5];
-console.log(numbers[2]);
-```
+Which of the following is NOT true about JavaScript arrays?
## --answers--
-`2`
+They are zero-indexed.
### --feedback--
-Remember that arrays in JavaScript are zero-indexed.
+Recall how each value in an array is numerically indexed, and how that affects the way values are stored.
---
-`3`
+They are an unordered collection of values.
---
-`4`
+They can contain another array as a value.
### --feedback--
-Remember that arrays in JavaScript are zero-indexed.
+Recall how each value in an array is numerically indexed, and how that affects the way values are stored.
---
-`5`
+They are dynamic, and their size can change after they're created.
### --feedback--
-Remember that arrays in JavaScript are zero-indexed.
+Recall how each value in an array is numerically indexed, and how that affects the way values are stored.
## --video-solution--
@@ -58,38 +53,37 @@ Remember that arrays in JavaScript are zero-indexed.
What will be the output of the following code?
```js
-let fruits = ['apple', 'banana'];
-fruits.push('orange');
-console.log(fruits);
+let numbers = [1, 2, 3, 4, 5];
+console.log(numbers[2]);
```
## --answers--
-`['apple', 'banana']`
+`2`
### --feedback--
-The `push()` method adds a new element to the end of an array.
+Remember that arrays in JavaScript are zero-indexed.
---
-`['apple', 'banana', 'orange']`
+`3`
---
-`['banana', 'orange']`
+`4`
### --feedback--
-The `push()` method adds a new element to the end of an array.
+Remember that arrays in JavaScript are zero-indexed.
---
-`['orange', 'apple', 'banana']`
+`5`
### --feedback--
-The `push()` method adds a new element to the end of an array.
+Remember that arrays in JavaScript are zero-indexed.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-audio-and-video/6733d852175df50937f06061.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-audio-and-video/6733d852175df50937f06061.md
index 025caa8592..9ad78c1c1a 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-audio-and-video/6733d852175df50937f06061.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-audio-and-video/6733d852175df50937f06061.md
@@ -22,7 +22,7 @@ Which method is used to access the user's media devices?
### --feedback--
-This method accesses the user’s media devices.
+This method accesses the user's media devices.
---
@@ -30,7 +30,7 @@ This method accesses the user’s media devices.
### --feedback--
-This method accesses the user’s media devices.
+This method accesses the user's media devices.
---
@@ -42,7 +42,7 @@ This method accesses the user’s media devices.
### --feedback--
-This method accesses the user’s media devices.
+This method accesses the user's media devices.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-backgrounds-and-borders/672b98be592cfb451f651451.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-backgrounds-and-borders/672b98be592cfb451f651451.md
index 9f69392f93..0080dd6da9 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-backgrounds-and-borders/672b98be592cfb451f651451.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-backgrounds-and-borders/672b98be592cfb451f651451.md
@@ -74,7 +74,7 @@ It makes the gradient extend to the farthest corner of the element.
---
-It makes the gradient only appear within the element’s `padding`.
+It makes the gradient only appear within the element's `padding`.
### --feedback--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-backgrounds-and-borders/672b98cd77b6b7456b6ef2de.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-backgrounds-and-borders/672b98cd77b6b7456b6ef2de.md
index 49ecdfbbfc..50823d9683 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-backgrounds-and-borders/672b98cd77b6b7456b6ef2de.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-backgrounds-and-borders/672b98cd77b6b7456b6ef2de.md
@@ -94,15 +94,15 @@ It makes the website look less colorful.
### --feedback--
-Think about how users who can’t distinguish between certain colors might be affected.
+Think about how users who can't distinguish between certain colors might be affected.
---
-It doesn’t affect users with visual impairments.
+It doesn't affect users with visual impairments.
### --feedback--
-Think about how users who can’t distinguish between certain colors might be affected.
+Think about how users who can't distinguish between certain colors might be affected.
---
@@ -114,7 +114,7 @@ It requires more CSS code.
### --feedback--
-Think about how users who can’t distinguish between certain colors might be affected.
+Think about how users who can't distinguish between certain colors might be affected.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-backgrounds-and-borders/672b98db3bcdd545ab3b3c73.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-backgrounds-and-borders/672b98db3bcdd545ab3b3c73.md
index 467ca6704d..f6ea379d54 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-backgrounds-and-borders/672b98db3bcdd545ab3b3c73.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-backgrounds-and-borders/672b98db3bcdd545ab3b3c73.md
@@ -102,35 +102,35 @@ Consider which property specifically targets one side of an element's border.
## --text--
-What's a potential advantage of using `box-shadow` to create a border effect instead of the `border` property?
+Which CSS property would you use to round the corners of a border?
## --answers--
-It's more widely supported by browsers.
+`border-style`
### --feedback--
-Think about the flexibility of box-shadow and how it can be used to layer multiple effects.
+Think of a word related to a circle or curve.
---
-It allows for multiple "borders" with a single property.
+`border-radius`
---
-It's more performant.
+`border-spacing`
### --feedback--
-Think about the flexibility of box-shadow and how it can be used to layer multiple effects.
+Think of a word related to a circle or curve.
---
-It can create gradients without additional properties.
+`border-bottom`
### --feedback--
-Think about the flexibility of box-shadow and how it can be used to layer multiple effects.
+Think of a word related to a circle or curve.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-common-string-methods/67326c15b3b2f0c5827927cc.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-common-string-methods/67326c15b3b2f0c5827927cc.md
index 3bc56fab66..0c0fe33399 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-common-string-methods/67326c15b3b2f0c5827927cc.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-common-string-methods/67326c15b3b2f0c5827927cc.md
@@ -18,7 +18,7 @@ What will the following code output?
```js
let text = "JavaScript is awesome!";
-let result = text.slice(0, 10);
+let result = text.slice(0, 9);
console.log(result);
```
@@ -97,7 +97,7 @@ What will the following code return?
```js
let sentence = "Learning JavaScript is fun!";
-let extracted = sentence.slice(9, -4);
+let extracted = sentence.slice(9, -5);
console.log(extracted);
```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-common-string-methods/67326c1fdaf9c0c5ad1a2589.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-common-string-methods/67326c1fdaf9c0c5ad1a2589.md
index 573a12eb0e..8757b78eaf 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-common-string-methods/67326c1fdaf9c0c5ad1a2589.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-common-string-methods/67326c1fdaf9c0c5ad1a2589.md
@@ -53,7 +53,7 @@ Think about how `toUpperCase()` affects the entire string.
What will the following code output?
```js
-javascriptCopy codelet phrase = "JavaScript is Fun!";
+let phrase = "JavaScript is Fun!";
console.log(phrase.toLowerCase());
```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-common-string-methods/67326c29dcd98fc5ecc49779.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-common-string-methods/67326c29dcd98fc5ecc49779.md
index d4e7bd05cf..82c13638cf 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-common-string-methods/67326c29dcd98fc5ecc49779.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-common-string-methods/67326c29dcd98fc5ecc49779.md
@@ -50,35 +50,42 @@ Think about what happens when there are multiple instances of the word you are t
## --text--
-How can you replace all instances of a word in a string?
+What will the following code output?
+
+```js
+let phrase = "freeCodeCamp is awesome!";
+let updatedPhrase = phrase.replace("freecodecamp", "fCC");
+
+console.log(updatedPhrase);
+```
## --answers--
-Use a `for` loop.
+`"fcc is awesome!"`
### --feedback--
-Consider how regular expressions can help with multiple replacements.
+Remember that the `replace()` method is case-sensitive.
---
-Use `replace()` with a case-sensitive string.
+`"fCC is awesome!"`
### --feedback--
-Consider how regular expressions can help with multiple replacements.
+Remember that the `replace()` method is case-sensitive.
---
-Use `replace()` with a global regular expression.
+`"freeCodeCamp is awesome!"`
---
-Use `replaceAll()` instead of `replace()`.
+`undefined`
### --feedback--
-Consider how regular expressions can help with multiple replacements.
+Remember that the `replace()` method is case-sensitive.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-common-string-methods/67326c3c3ab931c644cea05b.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-common-string-methods/67326c3c3ab931c644cea05b.md
index 3e2c98fa43..f18ca82e72 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-common-string-methods/67326c3c3ab931c644cea05b.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-common-string-methods/67326c3c3ab931c644cea05b.md
@@ -95,7 +95,9 @@ console.log(str.trimEnd());
## --answers--
-`"Code"`
+```js
+"Code"
+```
### --feedback--
@@ -103,11 +105,15 @@ Consider which part of the string is affected by `trimEnd()`.
---
-`" Code"`
+```js
+" Code"
+```
---
-`"Code "`
+```js
+"Code "
+```
### --feedback--
@@ -115,7 +121,9 @@ Consider which part of the string is affected by `trimEnd()`.
---
-`" Code "`
+```js
+" Code "
+```
### --feedback--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-css-grid/673226732b19aa1cacd0a75c.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-css-grid/673226732b19aa1cacd0a75c.md
index bba9197b3c..2df523b761 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-css-grid/673226732b19aa1cacd0a75c.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-css-grid/673226732b19aa1cacd0a75c.md
@@ -91,7 +91,7 @@ What happens when you use `grid-template-columns: 1fr 1fr 1fr 1fr;` in a CSS gri
## --answers--
-The container will have four columns, each taking up 10% of the container’s width.
+The container will have four columns, each taking up 10% of the container's width.
### --feedback--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-css-variables/672aa8985acb7361e656f94c.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-css-variables/672aa8985acb7361e656f94c.md
index 50cd496e23..692fca0f87 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-css-variables/672aa8985acb7361e656f94c.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-css-variables/672aa8985acb7361e656f94c.md
@@ -86,7 +86,7 @@ Think about the function used to reference custom properties in CSS.
## --text--
-What is a key advantage of using CSS custom properties over preprocessor variables?
+What is something you should be aware of when using CSS custom properties?
## --answers--
@@ -94,27 +94,27 @@ They can be used with older versions of CSS.
### --feedback--
-Consider the dynamic nature of CSS custom properties compared to preprocessor variables.
+Consider how recently CSS custom properties were introduced, and how that might cause issues for people with older devices.
---
-They can be manipulated using JavaScript at runtime.
+They might not be supported by older browsers.
---
-They are faster to process than preprocessor variables.
+They can lead to faster page speeds.
### --feedback--
-Consider the dynamic nature of CSS custom properties compared to preprocessor variables.
+Consider how recently CSS custom properties were introduced, and how that might cause issues for people with older devices.
---
-They can hold more complex values than preprocessor variables.
+They increase repetition in your stylesheets.
### --feedback--
-Consider the dynamic nature of CSS custom properties compared to preprocessor variables.
+Consider how recently CSS custom properties were introduced, and how that might cause issues for people with older devices.
## --video-solution--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-data-in-react/6734e3ceee2da4b0301719b7.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-data-in-react/6734e3ceee2da4b0301719b7.md
index 3e86207006..d9706a50d9 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-data-in-react/6734e3ceee2da4b0301719b7.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-data-in-react/6734e3ceee2da4b0301719b7.md
@@ -1,14 +1,136 @@
---
id: 6734e3ceee2da4b0301719b7
title: How Do You Pass Props from Parent to Child Component in React?
-challengeType: 11
-videoId: nVAaxZ34khk
+challengeType: 19
+#videoId: nVAaxZ34khk
dashedName: how-do-you-pass-props-from-parent-to-child-component-in-react
---
# --description--
-Watch the video lecture and answer the questions below.
+The video for this lecture isn't available yet, one will be available soon. Here is a transcript of the lecture for now:
+
+In the previous lectures, we learned how to build small components in React like this:
+
+```js
+function Greeting() {
+ const developerName = "Jessica";
+ return Hi {developerName}! ;
+}
+```
+
+We can choose to nest this component inside another parent component or the root component like this:
+
+```js
+function App() {
+ return ;
+}
+
+function Greeting() {
+ const developerName = "Jessica";
+ return Hi {developerName}! ;
+}
+```
+
+While this code will run fine and display the result of Hi Jessica! on the screen, it is not that flexible of a component.
+
+What if we wanted to display a different name like Naomi, Tom, or Oliver?
+
+This is where React props comes in.
+
+Props, which is short for properties, is the way for Parent components to pass data down to the child component.
+
+Props can be of any type: strings, numbers, booleans, objects, or arrays.
+
+Let’s update our example from earlier to now accept a `name` prop:
+
+```js
+function App() {
+ return ;
+}
+
+export default App;
+
+function Greeting(props) {
+ console.log(props);
+ return Hi {props.name}! ;
+}
+```
+
+For the child component called `Greeting` we are now using `props.name` instead of hardcoding the name `"Jessica"`. We are also logging props to the console which is showing as an object.
+
+Then inside of the parent App component, we are passing the value to the name prop so it can be passed down to the child.
+
+The result will be the same on the screen like earlier, but now we have created a more flexible component.
+
+Now we have the ability to reuse the child component several times and pass in different names each time.
+
+```js
+function App() {
+ return (
+ <>
+
+
+
+
+ >
+ );
+}
+```
+
+You can also choose to use object destructuring in the props to make it more readable.
+
+Here's how you could rewrite the `Greeting` component:
+
+```js
+function Greeting({ name }) {
+ return Hi {name}! ;
+}
+```
+
+This code achieves the same result but makes it clearer which props the component is expecting to receive.
+
+Sometimes, you can have a lot of properties that you have to pass as props. Instead of passing them one by one, you can use the spread operator (`...`), after converting them to an object.
+
+Here is an example of a new child component called `DeveloperCard`:
+
+```js
+function DeveloperCard({ name, age, country }) {
+ return (
+
+
Developer: {name}
+
Age: {age}
+
Country: {country}
+
+ );
+}
+```
+
+This `DeveloperCard` component accepts three props: `name`, `age`, and `country`.
+
+In the parent `App` component, we can use the spread syntax to pass all the properties from an object as individual props to the child component.
+
+```js
+function App() {
+ const developerObj = {
+ name: "Alice",
+ age: 30,
+ country: "USA",
+ };
+
+ return (
+
+
+
+ );
+}
+```
+
+This is particularly useful when working with arrays of objects and passing multiple sets of properties to child components. For example, you might have a list of developers where each object in the array has the same structure but represents a different person.
+
+You will learn more about how to render lists in React in future lectures.
+
+Using props in React makes your components more flexible and reusable, allowing you to build more complex UIs. However, it's important to note that props are immutable, meaning they cannot be changed once passed to a component. If you need to handle user input and modify data, you should use state instead. You'll learn more about managing state in future lectures.
# --questions--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-data-in-react/673500abfe36cd015b67b1b7.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-data-in-react/673500abfe36cd015b67b1b7.md
index 59701e4b40..25b6b6c3bf 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-data-in-react/673500abfe36cd015b67b1b7.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-data-in-react/673500abfe36cd015b67b1b7.md
@@ -1,14 +1,71 @@
---
id: 673500abfe36cd015b67b1b7
title: How Does Conditional Rendering Work in React Components?
-challengeType: 11
-videoId: nVAaxZ34khk
+challengeType: 19
+#videoId: nVAaxZ34khk
dashedName: how-does-conditional-rendering-work-in-react-components
---
# --description--
-Watch the lecture video and answer the questions below.
+The video for this lecture isn't available yet, one will be available soon. Here is a transcript of the lecture for now:
+
+Conditional rendering in React allows you to create dynamic user interfaces. It is used to show different content based on certain conditions or states within your application.
+
+The most common approaches of using Conditional rendering includes using if statements, the ternary operator, and `logical AND (&&)` operator.
+
+The simplest form of conditional rendering uses an if statement.
+
+Here's an example:
+
+```js
+function Greeting({ isLoggedIn }) {
+ if (isLoggedIn) {
+ return Welcome back! ;
+ }
+ return Please sign in ;
+}
+```
+
+In this example, the `Greeting` component checks the `isLoggedIn` prop. If it's true, it returns a welcome message, otherwise, it prompts the user to sign in.
+
+Here is an example using the Greeting component inside of the parent App component.
+
+```js
+function App() {
+ return (
+
+
+
+ );
+}
+```
+
+For simpler conditions, the ternary operator (?) is often used directly within JSX. It allows for inline conditional rendering, which can make your code more concise:
+
+```js
+function Greeting({ isLoggedIn }) {
+ return {isLoggedIn ? "Welcome back!" : "Please sign in."} ;
+}
+```
+
+This code achieves the same result as the previous example but in a more compact form. The ternary operator checks isLoggedIn and renders the appropriate message.
+
+Another common pattern for conditional rendering is using the `logical AND (&&)` operator. This is particularly useful when you want to render something or nothing based on a condition:
+
+```js
+function Notification({ message }) {
+ return (
+
+ {message &&
{message}
}
+
+ );
+}
+```
+
+In this example, the paragraph element with the message is only rendered if the `message` prop is truthy. If `message` is falsy (meaning it is an empty string, `null`, or `undefined`), nothing is rendered to the screen.
+
+By mastering these techniques of conditional rendering, you can build more interactive and user-friendly applications that adapt to changing data and user interactions.
# --questions--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-data-in-react/673500b41af8500191febedc.md b/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-data-in-react/673500b41af8500191febedc.md
index 957731e786..bf14742e40 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-data-in-react/673500b41af8500191febedc.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/lecture-working-with-data-in-react/673500b41af8500191febedc.md
@@ -1,14 +1,80 @@
---
id: 673500b41af8500191febedc
title: How Do You Render Lists in React?
-challengeType: 11
-videoId: nVAaxZ34khk
+challengeType: 19
+#videoId: nVAaxZ34khk
dashedName: how-do-you-render-lists-in-react
---
# --description--
-Watch the lecture video and answer the questions below.
+The video for this lecture isn't available yet, one will be available soon. Here is a transcript of the lecture for now:
+
+Rendering lists is a fundamental task in React web apps, and is used for displaying data to users. In React, the `map()` method is used to transform an array of data into an array of JSX elements that can be rendered in the UI.
+
+Here is an example of a component called `FruitList` that displays a list of fruits:
+
+```js
+function FruitList() {
+ const fruits = ['Apple', 'Banana', 'Cherry', 'Date'];
+ return (
+
+ {fruits.map(fruit => {fruit} )}
+
+ );
+}
+```
+
+In this example, the `map()` function iterates over each item in the fruits array. For each fruit, it creates a new `` element containing the fruit's name. The newly created array of ` ` elements is then displayed inside the `
-
-
-
-```
+`readInputOnly`
---
-```html
-
-
-
-```
+`read-only`
---
-All of the other choices are correct.
+`only-read`
#### --answer--
-```html
-
-
-
-
-```
+`readonly`
### --question--
@@ -329,11 +305,11 @@ Which attribute specifies that an input must be filled out before submitting the
---
-`imp`
+`obligatory`
---
-It is not possible via HTML only.
+`essential`
#### --answer--
@@ -343,153 +319,185 @@ It is not possible via HTML only.
#### --text--
-How can you hide an input from the user?
+What are Devtools used for?
#### --distractors--
-` `
+These tools are built directly into the browser and they are used to spot any linting issues in your code.
---
-` `
+These tools are built directly into the browser and are used to automatically format your code.
---
-It is not possible via HTML.
+These tools are built directly into the browser and are used to help you ensure 100% test coverage for your code.
#### --answer--
-` `
+These tools are built directly into the browser and are used to help you debug, profile, and analyze web pages.
### --question--
#### --text--
-What does the `target` attribute of a form do?
+Which of the following is the correct way to disable an input?
#### --distractors--
-It specifies the variable we intend to change.
+```html
+
+```
---
-It specifies different ways to store the response of the form.
+```html
+
+```
---
-It specifies different keyword searches.
+```html
+
+```
#### --answer--
-It indicates where to display the response after submitting the form.
+```html
+
+```
### --question--
#### --text--
-Which of the following `type` attributes for the `input` element is correct??
+Which of the following is a valid value for the `type` attribute?
#### --distractors--
-` `
+```html
+
+```
---
-` `
+```html
+
+```
---
-` `
+```html
+
+```
#### --answer--
-All of the other choices.
+```html
+
+```
### --question--
#### --text--
-What does the `action` attribute do?
+Which of the following is the correct use of the `size` attribute?
#### --distractors--
-It works as the `submit` attribute.
+```html
+
+```
---
-It is used to collect data from the user.
+```html
+
+```
---
-It defines the next steps to be taken.
+```html
+
+```
#### --answer--
-It defines where the form's response is sent.
+```html
+
+```
### --question--
#### --text--
-How can you define the length of an input?
+Which of the following attributes is used to specify the minimum number of characters required in an input field?
#### --distractors--
-It is not possible.
+`minlen`
---
-` `
+`Mlength`
---
-` `
+`minimumLen`
#### --answer--
-` `
+`minlength`
### --question--
#### --text--
-How can you remove form validation?
+Which of the following button examples does **NOT** use a correct value for the `type` attribute?
#### --distractors--
-` `
+```html
+Submit
+```
---
-` `
+```html
+Example Button
+```
---
-` `
+```html
+Reset
+```
#### --answer--
-` `
+```html
+Example Btn
+```
### --question--
#### --text--
-Which attribute is used to associate a label with an input?
+Which attribute is used to specify the value for a button?
#### --distractors--
-`des`
+`buttonValue`
---
-`to`
+`val`
---
-`describe`
+`btnVal`
#### --answer--
-`for`
+`value`
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/quiz-javascript-classes/67358ac128957c865dcf3ddf.md b/curriculum/challenges/ukrainian/25-front-end-development/quiz-javascript-classes/67358ac128957c865dcf3ddf.md
index 9cfe16961e..0dfe06296f 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/quiz-javascript-classes/67358ac128957c865dcf3ddf.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/quiz-javascript-classes/67358ac128957c865dcf3ddf.md
@@ -460,7 +460,7 @@ The subclass cannot create new instances.
#### --answer--
-The superclass’s constructor will be used by default.
+The superclass's constructor will be used by default.
### --question--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/quiz-javascript-objects/66edcd0ecb4b25dc64a34804.md b/curriculum/challenges/ukrainian/25-front-end-development/quiz-javascript-objects/66edcd0ecb4b25dc64a34804.md
index 1f529807fd..04ccf94347 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/quiz-javascript-objects/66edcd0ecb4b25dc64a34804.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/quiz-javascript-objects/66edcd0ecb4b25dc64a34804.md
@@ -117,7 +117,7 @@ const person = {
#### --text--
-Which of the following property key can only be used with a bracket notation as opposed to dot notation?
+Which of the following property keys can only be used with a bracket notation as opposed to dot notation?
#### --distractors--
@@ -425,19 +425,19 @@ Which of the following is true for an object sealed with `Object.seal`?
#### --distractors--
-Values of existing properties cannot be changed
+Values of existing properties cannot be changed.
---
-Values of existing properties can be changed but doing this will unseal the object
+Values of existing properties can be changed but doing this will unseal the object.
---
-New properties can be added but existing properties can not be removed
+New properties can be added but existing properties can not be removed.
#### --answer--
-New properties cannot be added and existing properties cannot be removed
+New properties cannot be added and existing properties cannot be removed.
### --question--
@@ -447,19 +447,19 @@ Which of the following is true for an object frozen with `Object.freeze`?
#### --distractors--
-New properties can be added but existing properties can not be removed
+New properties can be added but existing properties can not be removed.
---
-New properties can be added but doing this will unfreeze the object
+New properties can be added but doing this will unfreeze the object.
---
-Values of existing properties can be changed but doing this will unfreeze the object
+Values of existing properties can be changed but doing this will unfreeze the object.
#### --answer--
-Values of existing properties cannot be changed
+Values of existing properties cannot be changed.
### --question--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/quiz-javascript-regular-expressions/66edd3011f18f4ee1bd9d28b.md b/curriculum/challenges/ukrainian/25-front-end-development/quiz-javascript-regular-expressions/66edd3011f18f4ee1bd9d28b.md
index 7128948cae..3ba595809d 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/quiz-javascript-regular-expressions/66edd3011f18f4ee1bd9d28b.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/quiz-javascript-regular-expressions/66edd3011f18f4ee1bd9d28b.md
@@ -89,7 +89,7 @@ An object containing information about the (sub)string the regular expression ma
---
-Null, the method `test` only validates if the given regular expression is valid.
+`null`, the method `test` only validates if the given regular expression is valid.
#### --answer--
@@ -305,7 +305,7 @@ The lookbehind should be placed to the left of the main pattern of the regular e
#### --text--
-Which quantifier matches preceding element zero or one times?
+Which quantifier matches the preceding element zero or one times?
#### --distractors--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/quiz-javascript-strings/66edc31c44f1b9c1d5c5ebca.md b/curriculum/challenges/ukrainian/25-front-end-development/quiz-javascript-strings/66edc31c44f1b9c1d5c5ebca.md
index f678caf28f..69e599f250 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/quiz-javascript-strings/66edc31c44f1b9c1d5c5ebca.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/quiz-javascript-strings/66edc31c44f1b9c1d5c5ebca.md
@@ -21,19 +21,19 @@ What is the return value for the `includes()` method?
#### --distractors--
-If the substring is found within the string, the method returns the string otherwise, it returns `undefined`.
+If the substring is found within the string, the method returns the string. Otherwise, it returns `undefined`.
---
-If the substring is found within the string, the method returns `true` otherwise, it returns and empty string.
+If the substring is found within the string, the method returns `true`. Otherwise, it returns an empty string.
---
-If the substring is found within the string, the method returns the string otherwise, it returns `null`.
+If the substring is found within the string, the method returns the string. Otherwise, it returns `null`.
#### --answer--
-If the substring is found within the string, the method returns `true` otherwise, it returns `false`.
+If the substring is found within the string, the method returns `true`. Otherwise, it returns `false`.
### --question--
@@ -165,7 +165,7 @@ It displays a confirmation box with a message.
#### --answer--
-It displays a dialog box that prompts the user for input.
+It displays a dialog box that waits for the user input.
### --question--
@@ -463,7 +463,7 @@ How do you remove whitespace from the beginning and end of a string?
#### --text--
-Which of the following is the correct syntax for escaping strings?
+Which of the following is the correct syntax for escaping quotes?
#### --distractors--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/quiz-semantic-html/66ed903cf45ce3ece4053ebe.md b/curriculum/challenges/ukrainian/25-front-end-development/quiz-semantic-html/66ed903cf45ce3ece4053ebe.md
index 7579004a67..9ea0ef0e53 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/quiz-semantic-html/66ed903cf45ce3ece4053ebe.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/quiz-semantic-html/66ed903cf45ce3ece4053ebe.md
@@ -153,7 +153,7 @@ What is a typical use case of the `ruby` element?
#### --distractors--
-It specifies the document’s character encoding.
+It specifies the document's character encoding.
---
@@ -201,7 +201,7 @@ It styles text with custom fonts.
---
-It specifies the document’s character encoding.
+It specifies the document's character encoding.
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/quiz-styling-forms/66ed9043f45ce3ece4053ebf.md b/curriculum/challenges/ukrainian/25-front-end-development/quiz-styling-forms/66ed9043f45ce3ece4053ebf.md
index 19470e6d1b..9e01e081b0 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/quiz-styling-forms/66ed9043f45ce3ece4053ebf.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/quiz-styling-forms/66ed9043f45ce3ece4053ebf.md
@@ -47,7 +47,7 @@ It makes the text input focusable with a keyboard.
---
-It hides the input’s placeholder text.
+It hides the input's placeholder text.
---
@@ -55,7 +55,7 @@ It removes the default browser styling for inputs.
#### --answer--
-It ensures padding and borders are included in the element’s width and height.
+It ensures padding and borders are included in the element's width and height.
### --question--
@@ -77,7 +77,7 @@ It automatically adjusts the font size.
#### --answer--
-It ensures the input doesn’t stretch too wide on larger screens.
+It ensures the input doesn't stretch too wide on larger screens.
### --question--
@@ -87,7 +87,7 @@ Why should you add `:focus` styles to text inputs?
#### --distractors--
-It hides the input’s border.
+It hides the input's border.
---
@@ -289,7 +289,7 @@ When you want to fully customize the form control's style.
---
-When the browser’s default styles are hard to override.
+When the browser's default styles are hard to override.
---
@@ -417,7 +417,7 @@ What issue can arise when using `overflow: hidden;` on form elements?
#### --distractors--
-It improves the form’s overall accessibility.
+It improves the form's overall accessibility.
---
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/review-basic-css/671a887a7e62c75e9ab1ee4a.md b/curriculum/challenges/ukrainian/25-front-end-development/review-basic-css/671a887a7e62c75e9ab1ee4a.md
index 516dc86d30..110593e646 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/review-basic-css/671a887a7e62c75e9ab1ee4a.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/review-basic-css/671a887a7e62c75e9ab1ee4a.md
@@ -68,7 +68,7 @@ ul li {
}
```
-- **Next-sibling Combinator (`+`)**: This combinator selects an element that immediately follows a specified sibling element. The following example will select the paragraph element that immediately follow the `h2` element.
+- **Next-sibling Combinator (`+`)**: This combinator selects an element that immediately follows a specified sibling element. The following example will select the paragraph element that immediately follows the `h2` element.
```html
I am a sub heading
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/review-basic-html/67072fc183c7ca6c588feb4d.md b/curriculum/challenges/ukrainian/25-front-end-development/review-basic-html/67072fc183c7ca6c588feb4d.md
index 07d30165b2..8aed808474 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/review-basic-html/67072fc183c7ca6c588feb4d.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/review-basic-html/67072fc183c7ca6c588feb4d.md
@@ -12,7 +12,9 @@ Review the concepts below to prepare for the upcoming quiz.
## HTML Basics
- **Role of HTML**: Foundation of web structure.
-- **Block-level elements**: The `div` element is a generic HTML element that does not hold any semantic meaning. It is used as a generic container to hold over HTML elements.
+- **HTML Elements**: Used to represent content on the page. Most of them are made by an opening and a closing tag (e.g., ` `, `
`).
+- **`div` elements**: The `div` element is a generic HTML element that does not hold any semantic meaning. It is used as a generic container to hold over HTML elements.
+- **Void Elements**: Do not have a closing tag (e.g., ` `).
- **Attributes**: Adding metadata and behavior to elements.
## Identifiers and Grouping
@@ -33,7 +35,7 @@ Review the concepts below to prepare for the upcoming quiz.
## SEO and Social Sharing
-- **Meta tags (`description`)**: How it impacts SEO.
+- **Meta tags (`description`)**: Providing a short description for the web page and impacting SEO.
- **Open Graph tags**: Enhancing social media sharing.
## Media Elements and Optimization
@@ -54,7 +56,6 @@ Review the concepts below to prepare for the upcoming quiz.
- **Absolute vs. relative paths**: Navigating directories.
- **Path syntax**: Understanding `/`, `./`, `../` for file navigation.
- **Link states**: Managing different link interactions (hover, active).
-- **Inline vs. block-level links**: Layout and behavior differences.
# --assignment--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/review-css-accessibility/671a955b74ab5588735800d1.md b/curriculum/challenges/ukrainian/25-front-end-development/review-css-accessibility/671a955b74ab5588735800d1.md
index a2beaedae0..6c425c284b 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/review-css-accessibility/671a955b74ab5588735800d1.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/review-css-accessibility/671a955b74ab5588735800d1.md
@@ -16,7 +16,7 @@ Review the concepts below to prepare for the upcoming quiz.
## Best Practices With CSS and Accessibility
-- **`display: none;`**: Using `display: none;` means that screen readers and other assistive technologies won’t be able to access this content, as it is not included in the accessibility tree. Therefore, it is important to use this method only when you want to completely remove content from both visual presentation and accessibility.
+- **`display: none;`**: Using `display: none;` means that screen readers and other assistive technologies won't be able to access this content, as it is not included in the accessibility tree. Therefore, it is important to use this method only when you want to completely remove content from both visual presentation and accessibility.
- **`visibility: hidden;`**: This property and value hides the content visually but keeps it in the document flow, meaning it still occupies space on the page. These elements will also no longer be read by screen readers because they will have been removed from the accessibility tree.
- **`.sr-only` CSS class**: This is a common technique used to visually hide content while keeping it accessible to screen readers.
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/review-css-flexbox/671a940c69cdee833d4cc312.md b/curriculum/challenges/ukrainian/25-front-end-development/review-css-flexbox/671a940c69cdee833d4cc312.md
index f96930b45c..a14acbae2c 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/review-css-flexbox/671a940c69cdee833d4cc312.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/review-css-flexbox/671a940c69cdee833d4cc312.md
@@ -16,7 +16,7 @@ Review the concepts below to prepare for the upcoming quiz.
## The `flex-direction` Property
-- **Definition**: This property sets the direction of the main axis. The default value of `flex-direction` is `row`, which places all the flex items on the same row, in the direction of your browser’s default language (left to right or right to left).
+- **Definition**: This property sets the direction of the main axis. The default value of `flex-direction` is `row`, which places all the flex items on the same row, in the direction of your browser's default language (left to right or right to left).
- **`flex-direction: row-reverse;`**: This reverses the items in the row.
- **`flex-direction: column;`**: This will align the flex items vertically instead of horizontally.
- **`flex-direction: column-reverse;`**: This reverses the order of the flex items vertically.
@@ -24,7 +24,7 @@ Review the concepts below to prepare for the upcoming quiz.
## The `flex-wrap` Property
- **Definition**: This property determines how flex items are wrapped within a flex container to fit the available space. `flex-wrap` can take three possible values: `nowrap`, `wrap`, and `wrap-reverse`.
-- **`flex-wrap: nowrap;`**: This is the default value. Flex items won’t be wrapped onto a new line, even if their width exceed the container's width.
+- **`flex-wrap: nowrap;`**: This is the default value. Flex items won't be wrapped onto a new line, even if their width exceed the container's width.
- **`flex-wrap: wrap;`**: This property will wrap the items when they exceed the width of their container.
- **`flex-wrap: wrap-reverse;`**: This property will wrap flex items in reverse order.
- **`flex-flow` Property**: This property is a shorthand property for `flex-direction` and `flex-wrap`. In this example, we set `flex-direction` to `column` and `flex-wrap` to `wrap-reverse`.
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/review-css-pseudo-classes/671a907bad4538752765f2ff.md b/curriculum/challenges/ukrainian/25-front-end-development/review-css-pseudo-classes/671a907bad4538752765f2ff.md
index 41467db42f..5fb9d6edf0 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/review-css-pseudo-classes/671a907bad4538752765f2ff.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/review-css-pseudo-classes/671a907bad4538752765f2ff.md
@@ -34,7 +34,7 @@ Review the concepts below to prepare for the upcoming quiz.
## Location Pseudo-classes
- **Location Pseudo-classes**: These pseudo-classes are used for styling links and elements that are targeted within the current document.
-- **`:any-link` Pseudo-class**: This pseudo-class is a combination of the :link and :visited pseudo-classes. So, it matches any anchor element with an href attribute, regardless of whether it’s visited or not.
+- **`:any-link` Pseudo-class**: This pseudo-class is a combination of the :link and :visited pseudo-classes. So, it matches any anchor element with an href attribute, regardless of whether it's visited or not.
- **`:link` Pseudo-class**: This pseudo-class allows you to target all unvisited links on a webpage. You can use it to style links differently before the user clicks on them.
- **`:local-link` Pseudo-class**: This pseudo-class targets links that point to the same document. It can be useful when you want to differentiate internal links from external ones.
- **`:visited` Pseudo-class**: This pseudo-class targets a link the user has visited.
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/review-css/671a9a0a140c2b9d6a75629f.md b/curriculum/challenges/ukrainian/25-front-end-development/review-css/671a9a0a140c2b9d6a75629f.md
index 3d30ed302e..ca255cbb7d 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/review-css/671a9a0a140c2b9d6a75629f.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/review-css/671a9a0a140c2b9d6a75629f.md
@@ -35,7 +35,7 @@ Review the concepts below to prepare for the upcoming exam.
- **Descendant Combinator**: This combinator is used to target elements that are descendants of a specified parent element. The following example will target all `li` items inside `ul` elements.
- **Child Combinator (`>`)**: This combinator is used to select elements that are direct children of a specified parent element. The following example will target all `p` elements that are direct children of the `container` class.
-- **Next-sibling Combinator (`+`)**: This combinator selects an element that immediately follows a specified sibling element. The following example will select the paragraph element that immediately follow the `h2` element.
+- **Next-sibling Combinator (`+`)**: This combinator selects an element that immediately follows a specified sibling element. The following example will select the paragraph element that immediately follows the `h2` element.
- **Subsequent-sibling Combinator (`~`)**: This combinator selects all siblings of a specified element that come after it. The following example will style only the second paragraph element because it is the only one that is a sibling of the `ul` element and share the same parent.
@@ -157,7 +157,7 @@ Review the concepts below to prepare for the upcoming exam.
## Location Pseudo-classes
- **Location Pseudo-classes**: These pseudo-classes are used for styling links and elements that are targeted within the current document.
-- **`:any-link` Pseudo-class**: This pseudo-class is a combination of the :link and :visited pseudo-classes. So, it matches any anchor element with an href attribute, regardless of whether it’s visited or not.
+- **`:any-link` Pseudo-class**: This pseudo-class is a combination of the :link and :visited pseudo-classes. So, it matches any anchor element with an href attribute, regardless of whether it's visited or not.
- **`:link` Pseudo-class**: This pseudo-class allows you to target all unvisited links on a webpage. You can use it to style links differently before the user clicks on them.
- **`:local-link` Pseudo-class**: This pseudo-class targets links that point to the same document. It can be useful when you want to differentiate internal links from external ones.
- **`:visited` Pseudo-class**: This pseudo-class targets a link the user has visited.
@@ -285,7 +285,7 @@ Review the concepts below to prepare for the upcoming exam.
## The `flex-direction` Property
-- **Definition**: This property sets the direction of the main axis. The default value of `flex-direction` is `row`, which places all the flex items on the same row, in the direction of your browser’s default language (left to right or right to left).
+- **Definition**: This property sets the direction of the main axis. The default value of `flex-direction` is `row`, which places all the flex items on the same row, in the direction of your browser's default language (left to right or right to left).
- **`flex-direction: row-reverse;`**: This reverses the items in the row.
- **`flex-direction: column;`**: This will align the flex items vertically instead of horizontally.
- **`flex-direction: column-reverse;`**: This reverses the order of the flex items vertically.
@@ -293,7 +293,7 @@ Review the concepts below to prepare for the upcoming exam.
## The `flex-wrap` Property
- **Definition**: This property determines how flex items are wrapped within a flex container to fit the available space. `flex-wrap` can take three possible values: `nowrap`, `wrap`, and `wrap-reverse`.
-- **`flex-wrap: nowrap;`**: This is the default value. Flex items won’t be wrapped onto a new line, even if their width exceed the container's width.
+- **`flex-wrap: nowrap;`**: This is the default value. Flex items won't be wrapped onto a new line, even if their width exceed the container's width.
- **`flex-wrap: wrap;`**: This property will wrap the items when they exceed the width of their container.
- **`flex-wrap: wrap-reverse;`**: This property will wrap flex items in reverse order.
- **`flex-flow` Property**: This property is a shorthand property for `flex-direction` and `flex-wrap`. In this example, we set `flex-direction` to `column` and `flex-wrap` to `wrap-reverse`.
@@ -373,7 +373,7 @@ Review the concepts below to prepare for the upcoming exam.
## Best Practices With CSS and Accessibility
-- **`display: none;`**: Using `display: none;` means that screen readers and other assistive technologies won’t be able to access this content, as it is not included in the accessibility tree. Therefore, it is important to use this method only when you want to completely remove content from both visual presentation and accessibility.
+- **`display: none;`**: Using `display: none;` means that screen readers and other assistive technologies won't be able to access this content, as it is not included in the accessibility tree. Therefore, it is important to use this method only when you want to completely remove content from both visual presentation and accessibility.
- **`visibility: hidden;`**: This property and value hides the content visually but keeps it in the document flow, meaning it still occupies space on the page. These elements will also no longer be read by screen readers because they will have been removed from the accessibility tree.
- **`.sr-only` CSS class**: This is a common technique used to visually hide content while keeping it accessible to screen readers.
- **`aria-hidden` attribute**: Used to hide an element from people using assistive technology such as screen readers. For example, this can be used to hide decorative images that do not provide any meaningful content.
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/review-debugging-javascript/6723cd54fc196dbd053f9dfb.md b/curriculum/challenges/ukrainian/25-front-end-development/review-debugging-javascript/6723cd54fc196dbd053f9dfb.md
index d0820b9388..5bf0e7b4f4 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/review-debugging-javascript/6723cd54fc196dbd053f9dfb.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/review-debugging-javascript/6723cd54fc196dbd053f9dfb.md
@@ -36,7 +36,7 @@ const developerObj = {
developerObj.map()
```
-- **RangeError**: These errors happen when your code tries to use a value that’s outside the range of what JavaScript can handle.
+- **RangeError**: These errors happen when your code tries to use a value that's outside the range of what JavaScript can handle.
```js
const arr = [];
@@ -58,7 +58,7 @@ function validateNumber(input) {
## `try...catch...finally`
-- **Definition**: The `try` block is used to wrap code that might throw an error. It acts as a safe space to try something that could fail. The `catch` block captures and handles errors that occur in the try block. You can use the error object inside catch to inspect what went wrong. The `finally` block runs after the try and catch blocks, regardless of whether an error occurred. It’s commonly used for cleanup tasks, such as closing files or releasing resources.
+- **Definition**: The `try` block is used to wrap code that might throw an error. It acts as a safe space to try something that could fail. The `catch` block captures and handles errors that occur in the try block. You can use the error object inside catch to inspect what went wrong. The `finally` block runs after the try and catch blocks, regardless of whether an error occurred. It's commonly used for cleanup tasks, such as closing files or releasing resources.
```js
function processInput(input) {
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/review-dom-manipulation-and-click-events-with-javascript/6723cc7a8e7aa3b9befd4bac.md b/curriculum/challenges/ukrainian/25-front-end-development/review-dom-manipulation-and-click-events-with-javascript/6723cc7a8e7aa3b9befd4bac.md
index 021d0ab750..bce084bcbb 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/review-dom-manipulation-and-click-events-with-javascript/6723cc7a8e7aa3b9befd4bac.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/review-dom-manipulation-and-click-events-with-javascript/6723cc7a8e7aa3b9befd4bac.md
@@ -15,7 +15,7 @@ Review the concepts below to prepare for the upcoming quiz.
- **Web API**: Web APIs are specifically designed for web applications. These types of APIs are often divided into two main categories: browser APIs and third-party APIs.
- **Browser APIs**: These APIs expose data from the browser. As a web developer, you can access and manipulate this data using JavaScript.
- **Third-Party APIs**: These are not built into the browser by default. You have to retrieve their code in some way. Usually, they will have detailed documentation explaining how to use their services. An example is the Google Maps API, which you can use to display interactive maps on your website.
-- **DOM**: The DOM stands for Document Object Model. It’s a programming interface that lets you interact with HTML documents. With the DOM, you can add, modify, or delete elements on a webpage. The root of the DOM tree is the `` element. It’s the top-level container for all the content of an HTML document. All other nodes are descendants of this root node. Then, below the root node, we find other nodes in the hierarchy. A parent node is an element that contains other elements. A child node is an element that is contained within another element.
+- **DOM**: The DOM stands for Document Object Model. It's a programming interface that lets you interact with HTML documents. With the DOM, you can add, modify, or delete elements on a webpage. The root of the DOM tree is the `` element. It's the top-level container for all the content of an HTML document. All other nodes are descendants of this root node. Then, below the root node, we find other nodes in the hierarchy. A parent node is an element that contains other elements. A child node is an element that is contained within another element.
- **`navigator` Interface**: This provides information about the browser environment, such as the user agent string, the platform, and the version of the browser. A user agent string is a text string that identifies the browser and operating system being used.
- **`window` Interface**: This represents the browser window that contains the DOM document. It provides methods and properties for interacting with the browser window, such as resizing the window, opening new windows, and navigating to different URLs.
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/review-form-validation-with-javascript/6723ce555ff2dfc0cc04b69a.md b/curriculum/challenges/ukrainian/25-front-end-development/review-form-validation-with-javascript/6723ce555ff2dfc0cc04b69a.md
index 023f056019..9c220360ea 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/review-form-validation-with-javascript/6723ce555ff2dfc0cc04b69a.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/review-form-validation-with-javascript/6723ce555ff2dfc0cc04b69a.md
@@ -11,7 +11,7 @@ Review the concepts below to prepare for the upcoming quiz.
## Validating Forms with JavaScript
-- **Constraint Validation API**: Certain HTML elements, such as the `textarea` and `input` elements, expose a constraint validation API. This API allows you to assert that the user’s provided value for that element passes any HTML-level validation you have written, such as minimum length or pattern matching.
+- **Constraint Validation API**: Certain HTML elements, such as the `textarea` and `input` elements, expose a constraint validation API. This API allows you to assert that the user's provided value for that element passes any HTML-level validation you have written, such as minimum length or pattern matching.
- **`checkValidity()` method**: This method returns `true` if the element matches all HTML validation (based on its attributes), and `false` if it fails.
```js
@@ -63,7 +63,7 @@ button.addEventListener('click',(event) => {
## Submitting Forms
- **Definition**: There are three ways a form can be submitted. The first is when the user clicks a button in the form which has the `type` attribute set to `submit`. The second is when the user presses the `Enter` key on any editable `input` field in the form. The third is through a JavaScript call to the `requestSubmit()` or `submit()` methods of the `form` element.
-- **`action` Attribute**: The `action` attribute should contain either a URL or a relative path for the current domain. This value determines where the form attempts to send data - if you do not set an `action` attribute, the form will send data to the current page’s URL.
+- **`action` Attribute**: The `action` attribute should contain either a URL or a relative path for the current domain. This value determines where the form attempts to send data - if you do not set an `action` attribute, the form will send data to the current page's URL.
```js
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/review-javascript-arrays/6723c66f623701a3cdf72130.md b/curriculum/challenges/ukrainian/25-front-end-development/review-javascript-arrays/6723c66f623701a3cdf72130.md
index e84ae23c5c..8c3f6af11a 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/review-javascript-arrays/6723c66f623701a3cdf72130.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/review-javascript-arrays/6723c66f623701a3cdf72130.md
@@ -76,7 +76,7 @@ console.log(second); // "banana"
console.log(third); // "orange"
```
-- **Rest Syntax**: This allows you to capture the remaining elements of an array that haven’t been destructured into a new array.
+- **Rest Syntax**: This allows you to capture the remaining elements of an array that haven't been destructured into a new array.
```js
const fruits = ["apple", "banana", "orange", "mango", "kiwi"];
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/review-javascript-audio-and-video/6723cf27c6e9a0c3f3041385.md b/curriculum/challenges/ukrainian/25-front-end-development/review-javascript-audio-and-video/6723cf27c6e9a0c3f3041385.md
index 425c938655..0ba5228a9d 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/review-javascript-audio-and-video/6723cf27c6e9a0c3f3041385.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/review-javascript-audio-and-video/6723cf27c6e9a0c3f3041385.md
@@ -36,9 +36,9 @@ function pauseAudio() {
## Different Audio and Video Formats
- **MIME type**: A MIME type, standing for Multipurpose Internet Mail Extensions, is a standardized way to programmatically indicate a file type. The MIME type can tell an application, such as your browser, how to handle a specific file. In the case of audio and video, the MIME type indicates it is a multimedia format that can be embedded in the web page.
-- **`source` Element**: This is used to specify a file type and source - and can include multiple different types by using multiple source elements. When you do this, the browser will determine the best format to use for the user’s current environment.
+- **`source` Element**: This is used to specify a file type and source - and can include multiple different types by using multiple source elements. When you do this, the browser will determine the best format to use for the user's current environment.
- **MP3**: This is a type of digital file format used to store music, audio, or sound. It's a compressed version of a sound recording that makes the file size smaller, so it's easier to store and share. An MP3 file has the MIME type audio/mp3
-- **MP4**: An MP4 is a type of digital file format used to store video and audio. It serves as a container that holds both the video (images) and the sound (music or speech) in one file. An MP4, can have the MIME type audio/mp4 OR video/mp4, depending on whether it’s a video file or audio-only.
+- **MP4**: An MP4 is a type of digital file format used to store video and audio. It serves as a container that holds both the video (images) and the sound (music or speech) in one file. An MP4, can have the MIME type audio/mp4 OR video/mp4, depending on whether it's a video file or audio-only.
## codecs
@@ -50,7 +50,7 @@ function pauseAudio() {
## Media Capture and Streams API
-- **Definition**: The Media Capture and Streams API, or the MediaStream API, is used to capture audio and video from your device. In order to use the API, you need to create the `MediaStream` object. You could do this with the constructor, but it would not be tied to the user’s hardware. Instead, the `mediaDevices` property of the `global` navigator object has a `getUserMedia()` method for you to use.
+- **Definition**: The Media Capture and Streams API, or the MediaStream API, is used to capture audio and video from your device. In order to use the API, you need to create the `MediaStream` object. You could do this with the constructor, but it would not be tied to the user's hardware. Instead, the `mediaDevices` property of the `global` navigator object has a `getUserMedia()` method for you to use.
```js
window.navigator.mediaDevices.getUserMedia({
@@ -72,7 +72,7 @@ window.navigator.mediaDevices.getUserMedia({
## Screen Capture API
-- **Definition**: The Screen Capture API is used to record a user’s screen. This API is exposed by calling the `getDisplayMedia()` method of the `mediaDevices` object and consuming the returned media stream.
+- **Definition**: The Screen Capture API is used to record a user's screen. This API is exposed by calling the `getDisplayMedia()` method of the `mediaDevices` object and consuming the returned media stream.
## MediaStream Recording API
@@ -80,7 +80,7 @@ window.navigator.mediaDevices.getUserMedia({
## Media Source Extensions API
-- **topic**: The Media Source Extensions API is what allows you to directly pass a user’s webcam feed to a video element with the `srcObject` property.
+- **topic**: The Media Source Extensions API is what allows you to directly pass a user's webcam feed to a video element with the `srcObject` property.
## Web Audio API
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/review-javascript-events/6723cc0ca05ce9b87a319ceb.md b/curriculum/challenges/ukrainian/25-front-end-development/review-javascript-events/6723cc0ca05ce9b87a319ceb.md
index 497f523801..bac65e3eef 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/review-javascript-events/6723cc0ca05ce9b87a319ceb.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/review-javascript-events/6723cc0ca05ce9b87a319ceb.md
@@ -38,7 +38,7 @@ selectEl.addEventListener("change", (e) => {
## Event Bubbling
-- **Definition**: Event bubbling, or propagation, refers to how an event “bubbles up” to parent objects when triggered.
+- **Definition**: Event bubbling, or propagation, refers to how an event "bubbles up" to parent objects when triggered.
## Event Delegation
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/review-javascript-math/6723c463e51a2d9b747d7529.md b/curriculum/challenges/ukrainian/25-front-end-development/review-javascript-math/6723c463e51a2d9b747d7529.md
index 6af2aefde7..2852de734d 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/review-javascript-math/6723c463e51a2d9b747d7529.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/review-javascript-math/6723c463e51a2d9b747d7529.md
@@ -152,7 +152,7 @@ const num = 4;
console.log(-num); // -4
```
-- **Logical NOT (`!`) Operator**: This operator flips the boolean value of its operand. So, if the operand is `true`, it becomes `false`, and if it’s `false`, it becomes `true`.
+- **Logical NOT (`!`) Operator**: This operator flips the boolean value of its operand. So, if the operand is `true`, it becomes `false`, and if it's `false`, it becomes `true`.
## Bitwise Operators
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/review-javascript-regular-expressions/6723cdfa4ae237bf6b7e32eb.md b/curriculum/challenges/ukrainian/25-front-end-development/review-javascript-regular-expressions/6723cdfa4ae237bf6b7e32eb.md
index 9b25149e70..d401947daf 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/review-javascript-regular-expressions/6723cdfa4ae237bf6b7e32eb.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/review-javascript-regular-expressions/6723cdfa4ae237bf6b7e32eb.md
@@ -11,7 +11,7 @@ Review the concepts below to prepare for the upcoming quiz.
## Regular Expressions and Common Methods
-- **Definition**: Regular Expressions, or Regex, are used to create a “pattern”, which you can then use to check against a string, extract text, and more.
+- **Definition**: Regular Expressions, or Regex, are used to create a "pattern", which you can then use to check against a string, extract text, and more.
```js
const regex = /freeCodeCamp/;
@@ -65,7 +65,7 @@ for (let match of iterator) {
## Regular Expression Modifiers
-- **Definition**: Modifiers, often referred to as “flags”, modify the behavior of a regular expression.
+- **Definition**: Modifiers, often referred to as "flags", modify the behavior of a regular expression.
- **`i` Flag**: This flag makes a regex ignore case.
```js
@@ -82,7 +82,7 @@ console.log(regex.test("freeCodeCamp")); // true
console.log(regex.test("freeCodeCamp is great")); // false
```
-- **Anchor Definition**: The `^` anchor, at the beginning of the regular expression, says “match the start of the string”. The `$` anchor, at the end of the regular expression, says “match the end of the string”.
+- **Anchor Definition**: The `^` anchor, at the beginning of the regular expression, says "match the start of the string". The `$` anchor, at the end of the regular expression, says "match the end of the string".
```js
const start = /^freeCodeCamp/i;
@@ -194,7 +194,7 @@ const regex = /^\d{4}$/;
## Capturing Groups and Backreferences
-- **Capturing Groups**: A capturing group allows you to “capture” a portion of the matched string to use however you might need. Capturing groups are defined by parentheses containing the pattern to capture, with no leading characters like a lookahead.
+- **Capturing Groups**: A capturing group allows you to "capture" a portion of the matched string to use however you might need. Capturing groups are defined by parentheses containing the pattern to capture, with no leading characters like a lookahead.
```js
const regex = /free(code)camp/i;
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/review-javascript-strings/6723c1946e4cd7909a836bb4.md b/curriculum/challenges/ukrainian/25-front-end-development/review-javascript-strings/6723c1946e4cd7909a836bb4.md
index 562fab5a8f..b1519c457b 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/review-javascript-strings/6723c1946e4cd7909a836bb4.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/review-javascript-strings/6723c1946e4cd7909a836bb4.md
@@ -62,7 +62,7 @@ console.log(char); // A
## Other Common String Methods
- **The `indexOf` Method**: This method is used to search for a substring within a string. If the substring is found, `indexOf` returns the index (or position) of the first occurrence of that substring. If the substring is not found, `indexOf` returns -1, which indicates that the search was unsuccessful.
-- **The `includes()` Method**: This method is used to check if a string contains a specific substring. If the substring is found within the string, the method returns true otherwise, it returns false.
+- **The `includes()` Method**: This method is used to check if a string contains a specific substring. If the substring is found within the string, the method returns true. Otherwise, it returns false.
- **The `slice()` Method**: This method extracts a portion of a string and returns a new string, without modifying the original string. It takes two parameters: the starting index and the optional ending index.
- **The `toUpperCase()` Method**: This method converts all the characters to uppercase letters and returns a new string with all uppercase characters.
- **The `toLowerCase()` Method**: This method converts all characters in a string to lowercase.
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/review-javascript-variables-and-data-types/6723be264695fb7e619fe1fa.md b/curriculum/challenges/ukrainian/25-front-end-development/review-javascript-variables-and-data-types/6723be264695fb7e619fe1fa.md
index a43eadb8af..2d96f60bfa 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/review-javascript-variables-and-data-types/6723be264695fb7e619fe1fa.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/review-javascript-variables-and-data-types/6723be264695fb7e619fe1fa.md
@@ -15,7 +15,7 @@ While HTML and CSS provide website structure, JavaScript brings interactivity to
## Data Types in JavaScript
-Data types help the program understand the kind of data it’s working with, whether it's a number, text, or something else.
+Data types help the program understand the kind of data it's working with, whether it's a number, text, or something else.
- **Number**: A number represents both integers and floating-point values. Examples of integers include 7, 19, and 90.
- **Floating point**: A floating point number is a number with a decimal point. Examples include 3.14, 0.5, and 0.0001.
@@ -201,7 +201,7 @@ let isLoggedin = true;
console.log(typeof isLoggedin); // boolean
```
-- However, there’s a well-known quirk in JavaScript when it comes to null. The `typeof` operator returns `object` for null values.
+- However, there's a well-known quirk in JavaScript when it comes to null. The `typeof` operator returns `object` for null values.
```js
let user = null;
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/review-javascript/6723d3cfdd0717d3f1bf27e3.md b/curriculum/challenges/ukrainian/25-front-end-development/review-javascript/6723d3cfdd0717d3f1bf27e3.md
index a7e99d583a..3343a69ca7 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/review-javascript/6723d3cfdd0717d3f1bf27e3.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/review-javascript/6723d3cfdd0717d3f1bf27e3.md
@@ -16,7 +16,7 @@ While HTML and CSS provide website structure, JavaScript brings interactivity to
## Data Types in JavaScript
-Data types help the program understand the kind of data it’s working with, whether it's a number, text, or something else.
+Data types help the program understand the kind of data it's working with, whether it's a number, text, or something else.
- **Number**: A number represents both integers and floating-point values. Examples of integers include 7, 19, and 90.
- **Floating point**: A floating point number is a number with a decimal point. Examples include 3.14, 0.5, and 0.0001.
@@ -202,7 +202,7 @@ let isLoggedin = true;
console.log(typeof isLoggedin); // boolean
```
-- However, there’s a well-known quirk in JavaScript when it comes to null. The `typeof` operator returns `object` for null values.
+- However, there's a well-known quirk in JavaScript when it comes to null. The `typeof` operator returns `object` for null values.
```js
let user = null;
@@ -262,7 +262,7 @@ console.log(char); // A
## Other Common String Methods
- **The `indexOf` Method**: This method is used to search for a substring within a string. If the substring is found, `indexOf` returns the index (or position) of the first occurrence of that substring. If the substring is not found, `indexOf` returns -1, which indicates that the search was unsuccessful.
-- **The `includes()` Method**: This method is used to check if a string contains a specific substring. If the substring is found within the string, the method returns true otherwise, it returns false.
+- **The `includes()` Method**: This method is used to check if a string contains a specific substring. If the substring is found within the string, the method returns true. Otherwise, it returns false.
- **The `slice()` Method**: This method extracts a portion of a string and returns a new string, without modifying the original string. It takes two parameters: the starting index and the optional ending index.
- **The `toUpperCase()` Method**: This method converts all the characters to uppercase letters and returns a new string with all uppercase characters.
- **The `toLowerCase()` Method**: This method converts all characters in a string to lowercase.
@@ -416,7 +416,7 @@ const num = 4;
console.log(-num); // -4
```
-- **Logical NOT (`!`) Operator**: This operator flips the boolean value of its operand. So, if the operand is `true`, it becomes `false`, and if it’s `false`, it becomes `true`.
+- **Logical NOT (`!`) Operator**: This operator flips the boolean value of its operand. So, if the operand is `true`, it becomes `false`, and if it's `false`, it becomes `true`.
## Bitwise Operators
@@ -669,7 +669,7 @@ console.log(second); // "banana"
console.log(third); // "orange"
```
-- **Rest Syntax**: This allows you to capture the remaining elements of an array that haven’t been destructured into a new array.
+- **Rest Syntax**: This allows you to capture the remaining elements of an array that haven't been destructured into a new array.
```js
const fruits = ["apple", "banana", "orange", "mango", "kiwi"];
@@ -1381,7 +1381,7 @@ console.log(hasSomeEvenNumbers); // true
- **Web API**: Web APIs are specifically designed for web applications. These types of APIs are often divided into two main categories: browser APIs and third-party APIs.
- **Browser APIs**: These APIs expose data from the browser. As a web developer, you can access and manipulate this data using JavaScript.
- **Third-Party APIs**: These are not built into the browser by default. You have to retrieve their code in some way. Usually, they will have detailed documentation explaining how to use their services. An example is the Google Maps API, which you can use to display interactive maps on your website.
-- **DOM**: The DOM stands for Document Object Model. It’s a programming interface that lets you interact with HTML documents. With the DOM, you can add, modify, or delete elements on a webpage. The root of the DOM tree is the `` element. It’s the top-level container for all the content of an HTML document. All other nodes are descendants of this root node. Then, below the root node, we find other nodes in the hierarchy. A parent node is an element that contains other elements. A child node is an element that is contained within another element.
+- **DOM**: The DOM stands for Document Object Model. It's a programming interface that lets you interact with HTML documents. With the DOM, you can add, modify, or delete elements on a webpage. The root of the DOM tree is the `` element. It's the top-level container for all the content of an HTML document. All other nodes are descendants of this root node. Then, below the root node, we find other nodes in the hierarchy. A parent node is an element that contains other elements. A child node is an element that is contained within another element.
- **`navigator` Interface**: This provides information about the browser environment, such as the user agent string, the platform, and the version of the browser. A user agent string is a text string that identifies the browser and operating system being used.
- **`window` Interface**: This represents the browser window that contains the DOM document. It provides methods and properties for interacting with the browser window, such as resizing the window, opening new windows, and navigating to different URLs.
@@ -1746,7 +1746,7 @@ selectEl.addEventListener("change", (e) => {
## Event Bubbling
-- **Definition**: Event bubbling, or propagation, refers to how an event “bubbles up” to parent objects when triggered.
+- **Definition**: Event bubbling, or propagation, refers to how an event "bubbles up" to parent objects when triggered.
## Event Delegation
@@ -1779,7 +1779,7 @@ const developerObj = {
developerObj.map()
```
-- **RangeError**: These errors happen when your code tries to use a value that’s outside the range of what JavaScript can handle.
+- **RangeError**: These errors happen when your code tries to use a value that's outside the range of what JavaScript can handle.
```js
const arr = [];
@@ -1801,7 +1801,7 @@ function validateNumber(input) {
## `try...catch...finally`
-- **Definition**: The `try` block is used to wrap code that might throw an error. It acts as a safe space to try something that could fail. The `catch` block captures and handles errors that occur in the try block. You can use the error object inside catch to inspect what went wrong. The `finally` block runs after the try and catch blocks, regardless of whether an error occurred. It’s commonly used for cleanup tasks, such as closing files or releasing resources.
+- **Definition**: The `try` block is used to wrap code that might throw an error. It acts as a safe space to try something that could fail. The `catch` block captures and handles errors that occur in the try block. You can use the error object inside catch to inspect what went wrong. The `finally` block runs after the try and catch blocks, regardless of whether an error occurred. It's commonly used for cleanup tasks, such as closing files or releasing resources.
```js
function processInput(input) {
@@ -1848,7 +1848,7 @@ console.dir(document);
## Regular Expressions and Common Methods
-- **Definition**: Regular Expressions, or Regex, are used to create a “pattern”, which you can then use to check against a string, extract text, and more.
+- **Definition**: Regular Expressions, or Regex, are used to create a "pattern", which you can then use to check against a string, extract text, and more.
```js
const regex = /freeCodeCamp/;
@@ -1902,7 +1902,7 @@ for (let match of iterator) {
## Regular Expression Modifiers
-- **Definition**: Modifiers, often referred to as “flags”, modify the behavior of a regular expression.
+- **Definition**: Modifiers, often referred to as "flags", modify the behavior of a regular expression.
- **`i` Flag**: This flag makes a regex ignore case.
```js
@@ -1919,7 +1919,7 @@ console.log(regex.test("freeCodeCamp")); // true
console.log(regex.test("freeCodeCamp is great")); // false
```
-- **Anchor Definition**: The `^` anchor, at the beginning of the regular expression, says “match the start of the string”. The `$` anchor, at the end of the regular expression, says “match the end of the string”.
+- **Anchor Definition**: The `^` anchor, at the beginning of the regular expression, says "match the start of the string". The `$` anchor, at the end of the regular expression, says "match the end of the string".
```js
const start = /^freeCodeCamp/i;
@@ -2031,7 +2031,7 @@ const regex = /^\d{4}$/;
## Capturing Groups and Backreferences
-- **Capturing Groups**: A capturing group allows you to “capture” a portion of the matched string to use however you might need. Capturing groups are defined by parentheses containing the pattern to capture, with no leading characters like a lookahead.
+- **Capturing Groups**: A capturing group allows you to "capture" a portion of the matched string to use however you might need. Capturing groups are defined by parentheses containing the pattern to capture, with no leading characters like a lookahead.
```js
const regex = /free(code)camp/i;
@@ -2046,7 +2046,7 @@ console.log("freecoooooooodecamp".replace(regex, "paid$1world"));
## Validating Forms with JavaScript
-- **Constraint Validation API**: Certain HTML elements, such as the `textarea` and `input` elements, expose a constraint validation API. This API allows you to assert that the user’s provided value for that element passes any HTML-level validation you have written, such as minimum length or pattern matching.
+- **Constraint Validation API**: Certain HTML elements, such as the `textarea` and `input` elements, expose a constraint validation API. This API allows you to assert that the user's provided value for that element passes any HTML-level validation you have written, such as minimum length or pattern matching.
- **`checkValidity()` method**: This method returns `true` if the element matches all HTML validation (based on its attributes), and `false` if it fails.
```js
@@ -2098,7 +2098,7 @@ button.addEventListener('click',(event) => {
## Submitting Forms
- **Definition**: There are three ways a form can be submitted. The first is when the user clicks a button in the form which has the `type` attribute set to `submit`. The second is when the user presses the `Enter` key on any editable `input` field in the form. The third is through a JavaScript call to the `requestSubmit()` or `submit()` methods of the `form` element.
-- **`action` Attribute**: The `action` attribute should contain either a URL or a relative path for the current domain. This value determines where the form attempts to send data - if you do not set an `action` attribute, the form will send data to the current page’s URL.
+- **`action` Attribute**: The `action` attribute should contain either a URL or a relative path for the current domain. This value determines where the form attempts to send data - if you do not set an `action` attribute, the form will send data to the current page's URL.
```js
@@ -2219,9 +2219,9 @@ function pauseAudio() {
## Different Audio and Video Formats
- **MIME type**: A MIME type, standing for Multipurpose Internet Mail Extensions, is a standardized way to programmatically indicate a file type. The MIME type can tell an application, such as your browser, how to handle a specific file. In the case of audio and video, the MIME type indicates it is a multimedia format that can be embedded in the web page.
-- **`source` Element**: This is used to specify a file type and source - and can include multiple different types by using multiple source elements. When you do this, the browser will determine the best format to use for the user’s current environment.
+- **`source` Element**: This is used to specify a file type and source - and can include multiple different types by using multiple source elements. When you do this, the browser will determine the best format to use for the user's current environment.
- **MP3**: This is a type of digital file format used to store music, audio, or sound. It's a compressed version of a sound recording that makes the file size smaller, so it's easier to store and share. An MP3 file has the MIME type audio/mp3
-- **MP4**: An MP4 is a type of digital file format used to store video and audio. It serves as a container that holds both the video (images) and the sound (music or speech) in one file. An MP4, can have the MIME type audio/mp4 OR video/mp4, depending on whether it’s a video file or audio-only.
+- **MP4**: An MP4 is a type of digital file format used to store video and audio. It serves as a container that holds both the video (images) and the sound (music or speech) in one file. An MP4, can have the MIME type audio/mp4 OR video/mp4, depending on whether it's a video file or audio-only.
## codecs
@@ -2233,7 +2233,7 @@ function pauseAudio() {
## Media Capture and Streams API
-- **Definition**: The Media Capture and Streams API, or the MediaStream API, is used to capture audio and video from your device. In order to use the API, you need to create the `MediaStream` object. You could do this with the constructor, but it would not be tied to the user’s hardware. Instead, the `mediaDevices` property of the `global` navigator object has a `getUserMedia()` method for you to use.
+- **Definition**: The Media Capture and Streams API, or the MediaStream API, is used to capture audio and video from your device. In order to use the API, you need to create the `MediaStream` object. You could do this with the constructor, but it would not be tied to the user's hardware. Instead, the `mediaDevices` property of the `global` navigator object has a `getUserMedia()` method for you to use.
```js
window.navigator.mediaDevices.getUserMedia({
@@ -2255,7 +2255,7 @@ window.navigator.mediaDevices.getUserMedia({
## Screen Capture API
-- **Definition**: The Screen Capture API is used to record a user’s screen. This API is exposed by calling the `getDisplayMedia()` method of the `mediaDevices` object and consuming the returned media stream.
+- **Definition**: The Screen Capture API is used to record a user's screen. This API is exposed by calling the `getDisplayMedia()` method of the `mediaDevices` object and consuming the returned media stream.
## MediaStream Recording API
@@ -2263,7 +2263,7 @@ window.navigator.mediaDevices.getUserMedia({
## Media Source Extensions API
-- **topic**: The Media Source Extensions API is what allows you to directly pass a user’s webcam feed to a video element with the `srcObject` property.
+- **topic**: The Media Source Extensions API is what allows you to directly pass a user's webcam feed to a video element with the `srcObject` property.
## Web Audio API
@@ -2335,9 +2335,9 @@ console.log(map); // Map(3) { 'flower' => 'rose', 'fruit' => 'apple', 'vegetable
## Create, Read, Update, Delete (CRUD)
- **Create**: This refers to the process of creating new data. For example, in a web app, this could be when a user adds a new post to a blog.
-- **Read**: This is the operation where data is retrieved from a database. For instance, when you visit a blog post or view your profile on a website, you’re performing a read operation to fetch and display data stored in the database.
+- **Read**: This is the operation where data is retrieved from a database. For instance, when you visit a blog post or view your profile on a website, you're performing a read operation to fetch and display data stored in the database.
- **Update**: This involves modifying existing data in the database. An example would be editing a blog post or updating your profile information.
-- **Delete**: This is the operation that removes data from a database. For instance, when you delete a blog post or account, you’re performing a delete operation.
+- **Delete**: This is the operation that removes data from a database. For instance, when you delete a blog post or account, you're performing a delete operation.
## HTTP Methods
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/review-local-storage-and-crud/6723d0ac516099c902394e8b.md b/curriculum/challenges/ukrainian/25-front-end-development/review-local-storage-and-crud/6723d0ac516099c902394e8b.md
index b8d05c1f1f..57a3a0c8e2 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/review-local-storage-and-crud/6723d0ac516099c902394e8b.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/review-local-storage-and-crud/6723d0ac516099c902394e8b.md
@@ -16,9 +16,9 @@ Review the concepts below to prepare for the upcoming quiz.
## Create, Read, Update, Delete (CRUD)
- **Create**: This refers to the process of creating new data. For example, in a web app, this could be when a user adds a new post to a blog.
-- **Read**: This is the operation where data is retrieved from a database. For instance, when you visit a blog post or view your profile on a website, you’re performing a read operation to fetch and display data stored in the database.
+- **Read**: This is the operation where data is retrieved from a database. For instance, when you visit a blog post or view your profile on a website, you're performing a read operation to fetch and display data stored in the database.
- **Update**: This involves modifying existing data in the database. An example would be editing a blog post or updating your profile information.
-- **Delete**: This is the operation that removes data from a database. For instance, when you delete a blog post or account, you’re performing a delete operation.
+- **Delete**: This is the operation that removes data from a database. For instance, when you delete a blog post or account, you're performing a delete operation.
## HTTP Methods
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/review-react-basics/67487e141bb6a7140a352e12.md b/curriculum/challenges/ukrainian/25-front-end-development/review-react-basics/67487e141bb6a7140a352e12.md
index 9b2c7e68ff..8ccd73190c 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/review-react-basics/67487e141bb6a7140a352e12.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/review-react-basics/67487e141bb6a7140a352e12.md
@@ -138,7 +138,7 @@ function Child(props) {
}
```
-You can pass multiple props using the spread operator `(...)`, after converting them to an object. Here’s an example:
+You can pass multiple props using the spread operator `(...)`, after converting them to an object. Here's an example:
```jsx
// Parent component
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/review-semantic-html/671a83934b61f64cefe87a61.md b/curriculum/challenges/ukrainian/25-front-end-development/review-semantic-html/671a83934b61f64cefe87a61.md
index 8ee1918a05..6f610660e1 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/review-semantic-html/671a83934b61f64cefe87a61.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/review-semantic-html/671a83934b61f64cefe87a61.md
@@ -17,6 +17,10 @@ Review the concepts below to prepare for the upcoming quiz.
## Semantic HTML Elements
+- **Header element**: used to define the header of a document or section.
+- **Main element**: used to contain the main content of the web page.
+- **Navigation Section (`nav`) element**: represents a section with navigation links.
+- **Figure element**: used to contain illustrations and diagrams.
- **Emphasis (`em`) element**: marks text that has stress emphasis.
- **Idiomatic Text (`i`) element**: used for highlighting alternative voice or mood, idiomatic terms from another language, technical terms, and thoughts.
- **Strong Importance (`strong`) element**: marks text that has strong importance.
@@ -24,14 +28,15 @@ Review the concepts below to prepare for the upcoming quiz.
- **Description List (`dl`) element**: used to represent a list of term-description groupings.
- **Description Term (`dt`) element**: used to represent the term being defined.
- **Description Details (`dd`) element**: used to represent the description of the term.
-- **Block Quotation (`blockquote`) element**: used to represent a section that is quoted from another source.
+- **Block Quotation (`blockquote`) element**: used to represent a section that is quoted from another source. This element has a `cite` attribute. The value of the `cite` attribute is the URL of the source.
- **Inline Quotation (`q`) element**: used to represent a short inline quotation.
- **Abbreviation (`abbr`) element**: used to represent an abbreviation or acronym.
- **Contact Address (`address`) element**: used to represent the contact information.
-- **(Date) Time (`time`) element**: used to represent a date and/or time.
+- **(Date) Time (`time`) element**: used to represent a date and/or time. The `datetime` attribute is used to translate dates and times into a machine-readable format.
- **Superscript (`sup`) element**: used to represent superscript text.
- **Subscript (`sub`) element**: used to represent subscript text.
- **Inline Code (`code`) element**: used to represent a fragment of computer code.
+- **Preformatted Text (`pre`) element**: represents preformatted text
- **Unarticulated Annotation (`u`) element**: used to represent a span of inline text which should be rendered in a way that indicates that it has a non-textual annotation.
- **Ruby Annotation (`ruby`) element**: used to represent the text of a ruby annotation.
- **Strikethrough (`s`) element**: used to represent content that is no longer accurate or relevant.
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-cafe-menu/5f35e5c4321f818cdc4bed30.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-cafe-menu/5f35e5c4321f818cdc4bed30.md
index 9b4427a9f3..4d2c5908b0 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/workshop-cafe-menu/5f35e5c4321f818cdc4bed30.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-cafe-menu/5f35e5c4321f818cdc4bed30.md
@@ -7,7 +7,7 @@ dashedName: step-29
# --description--
-Має хороший вигляд. Час додати деякі елементи меню. Додайте порожній елемент `article` під заголовком `Coffee`. Він міститиме смак та ціну кожного напою, який ви пропонуєте.
+It's looking good. Час додати деякі елементи меню. Додайте порожній елемент `article` під заголовком `Coffee`. Він міститиме смак та ціну кожного напою, який ви пропонуєте.
# --hints--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-calorie-counter/63b61490e633a22b4593e62f.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-calorie-counter/63b61490e633a22b4593e62f.md
index 65223d73bb..6ab42100a2 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/workshop-calorie-counter/63b61490e633a22b4593e62f.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-calorie-counter/63b61490e633a22b4593e62f.md
@@ -65,7 +65,7 @@ You should assign the `#output` element to `output`.
```js
// assert.deepEqual(output, document.getElementById('output')); cannot be used,
// as browser defines `output` variable on it own for `#output`.
-assert.match(code, /const\s+output\s*=\s*document.getElementById\(('|")output\1\)/);
+assert.match(code, /const\s+output\s*=\s*document\.getElementById\(('|")output\1\)/);
```
# --seed--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-calorie-counter/63c9e8fe3a6f022a05a04675.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-calorie-counter/63c9e8fe3a6f022a05a04675.md
index e0db1f9357..b74f722f58 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/workshop-calorie-counter/63c9e8fe3a6f022a05a04675.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-calorie-counter/63c9e8fe3a6f022a05a04675.md
@@ -13,66 +13,205 @@ Using the same interpolation syntax, add a second `p` element with the text `con
You should add a second `p` element to your template literal.
+
```js
-assert.isAtLeast(getTemplateContents(code)?.match(/[^<]*<\/p>/g)?.length, 2);
+
+const entryDropdownElement = document.getElementById('entry-dropdown');
+budgetNumberInput.value = 2000;
+addEntry();
+
+const breakfastValueElement = document.getElementById("breakfast-1-calories");
+breakfastValueElement.value = 300;
+entryDropdownElement.value = "lunch";
+addEntry();
+
+const lunchValueElement = document.getElementById("lunch-1-calories");
+lunchValueElement.value = 600;
+entryDropdownElement.value = "dinner";
+addEntry();
+
+const dinnerValueElement = document.getElementById("dinner-1-calories");
+dinnerValueElement.value = 700;
+entryDropdownElement.value = "snacks";
+addEntry();
+
+const snacksValueElement = document.getElementById("snacks-1-calories");
+snacksValueElement.value = 200;
+entryDropdownElement.value = "exercise";
+addEntry();
+
+const exerciseValueElement = document.getElementById("exercise-1-calories");
+exerciseValueElement.value = 300;
+const fakeEvent = { preventDefault: () => {} };
+calculateCalories(fakeEvent);
+
+
+const output = document.getElementById('output');
+assert.isAtLeast(output.children.length, 4);
```
Your second `p` element should be on a new line.
+
```js
-assert.match(getTemplateContents(code), /
\s*[^<]*<\/p>\n\s*
[^<]*<\/p>/);
-```
-Your second `p` element should come after your existing `p` element.
+const entryDropdownElement = document.getElementById('entry-dropdown');
+budgetNumberInput.value = 2000;
+addEntry();
-```js
-assert.match(getTemplateContents(code), /
\$\{budgetCalories\}\s*Calories\s*Budgeted<\/p>\s*
/);
+const breakfastValueElement = document.getElementById("breakfast-1-calories");
+breakfastValueElement.value = 300;
+entryDropdownElement.value = "lunch";
+addEntry();
+
+const lunchValueElement = document.getElementById("lunch-1-calories");
+lunchValueElement.value = 600;
+entryDropdownElement.value = "dinner";
+addEntry();
+
+const dinnerValueElement = document.getElementById("dinner-1-calories");
+dinnerValueElement.value = 700;
+entryDropdownElement.value = "snacks";
+addEntry();
+
+const snacksValueElement = document.getElementById("snacks-1-calories");
+snacksValueElement.value = 200;
+entryDropdownElement.value = "exercise";
+addEntry();
+
+const exerciseValueElement = document.getElementById("exercise-1-calories");
+exerciseValueElement.value = 300;
+const fakeEvent = { preventDefault: () => {} };
+calculateCalories(fakeEvent);
+
+assert.strictEqual(output.children[3].innerText,"1800 Calories Consumed");
+
+dinnerValueElement.value = 300;
+calculateCalories(fakeEvent);
+assert.strictEqual(output.children[3].innerText,"1400 Calories Consumed");
```
Your second `p` element should have the text `${consumedCalories} Calories Consumed`.
```js
-const secondP = getTemplateContents(code)?.split(/
/)?.[2];
-assert.match(secondP, /\$\{consumedCalories\}\s*Calories\s*Consumed<\/p>/);
+
+const entryDropdownElement = document.getElementById('entry-dropdown');
+budgetNumberInput.value = 2000;
+addEntry();
+
+const breakfastValueElement = document.getElementById("breakfast-1-calories");
+breakfastValueElement.value = 300;
+entryDropdownElement.value = "lunch";
+addEntry();
+
+const lunchValueElement = document.getElementById("lunch-1-calories");
+lunchValueElement.value = 600;
+entryDropdownElement.value = "dinner";
+addEntry();
+
+const dinnerValueElement = document.getElementById("dinner-1-calories");
+dinnerValueElement.value = 700;
+entryDropdownElement.value = "snacks";
+addEntry();
+
+const snacksValueElement = document.getElementById("snacks-1-calories");
+snacksValueElement.value = 200;
+entryDropdownElement.value = "exercise";
+addEntry();
+
+const exerciseValueElement = document.getElementById("exercise-1-calories");
+exerciseValueElement.value = 300;
+const fakeEvent = { preventDefault: () => {} };
+calculateCalories(fakeEvent);
+
+assert.strictEqual(output.children[3].innerText,"1800 Calories Consumed");
+
+dinnerValueElement.value = 300;
+calculateCalories(fakeEvent);
+assert.strictEqual(output.children[3].innerText,"1400 Calories Consumed");
+
```
You should add a third `p` element to your template literal.
```js
-assert.lengthOf(getTemplateContents(code)?.match(/
[^<]*<\/p>/g), 3);
-```
-Your third `p` element should be on a new line.
+const entryDropdownElement = document.getElementById('entry-dropdown');
+budgetNumberInput.value = 2000;
+addEntry();
-```js
-assert.match(getTemplateContents(code), /
\s*[^<]*<\/p>\s*
[^<]*<\/p>\n\s*
[^<]*<\/p>/);
-```
+const breakfastValueElement = document.getElementById("breakfast-1-calories");
+breakfastValueElement.value = 300;
+entryDropdownElement.value = "lunch";
+addEntry();
-Your third `p` element should come after your second existing `p` element.
+const lunchValueElement = document.getElementById("lunch-1-calories");
+lunchValueElement.value = 600;
+entryDropdownElement.value = "dinner";
+addEntry();
-```js
-assert.match(getTemplateContents(code), /
\$\{consumedCalories\}\s*Calories\s*Consumed<\/p>\s*
/);
+const dinnerValueElement = document.getElementById("dinner-1-calories");
+dinnerValueElement.value = 700;
+entryDropdownElement.value = "snacks";
+addEntry();
+
+const snacksValueElement = document.getElementById("snacks-1-calories");
+snacksValueElement.value = 200;
+entryDropdownElement.value = "exercise";
+addEntry();
+
+const exerciseValueElement = document.getElementById("exercise-1-calories");
+exerciseValueElement.value = 300;
+const fakeEvent = { preventDefault: () => {} };
+calculateCalories(fakeEvent);
+
+assert.lengthOf(output.children,5);
```
Your third `p` element should have the text `${exerciseCalories} Calories Burned`.
```js
-const thirdP = getTemplateContents(code)?.split(/
/)?.[3];
-assert.match(thirdP, /\$\{exerciseCalories\}\s*Calories\s*Burned<\/p>/);
-```
-# --seed--
+const entryDropdownElement = document.getElementById('entry-dropdown');
+budgetNumberInput.value = 2000;
+addEntry();
-## --after-user-code--
+const breakfastValueElement = document.getElementById("breakfast-1-calories");
+breakfastValueElement.value = 300;
+entryDropdownElement.value = "lunch";
+addEntry();
+
+const lunchValueElement = document.getElementById("lunch-1-calories");
+lunchValueElement.value = 600;
+entryDropdownElement.value = "dinner";
+addEntry();
+
+const dinnerValueElement = document.getElementById("dinner-1-calories");
+dinnerValueElement.value = 700;
+entryDropdownElement.value = "snacks";
+addEntry();
+
+const snacksValueElement = document.getElementById("snacks-1-calories");
+snacksValueElement.value = 200;
+entryDropdownElement.value = "exercise";
+addEntry();
+
+const exerciseValueElement = document.getElementById("exercise-1-calories");
+exerciseValueElement.value = 300;
+const fakeEvent = { preventDefault: () => {} };
+calculateCalories(fakeEvent);
+
+assert.strictEqual(output.children[4].innerText,"300 Calories Burned");
+
+exerciseValueElement.value = Math.floor(Math.random() * 500);
+
+calculateCalories(fakeEvent);
+assert.strictEqual(output.children[4].innerText, exerciseValueElement.value.toString() + " Calories Burned");
-```js
-function getTemplateContents(code) {
- return code
- .split(/output\s*\.\s*innerHTML\s*=\s*/)?.[1]
- ?.split(/`/)?.[1];
-}
```
+# --seed--
+
## --seed-contents--
```html
@@ -270,7 +409,7 @@ function addEntry() {
targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
}
---fcc-editable-region--
+
function calculateCalories(e) {
e.preventDefault();
isError = false;
@@ -292,6 +431,7 @@ function calculateCalories(e) {
return;
}
+--fcc-editable-region--
const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
const surplusOrDeficit = remainingCalories < 0 ? 'Surplus' : 'Deficit';
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-calorie-counter/660404511dbf1b90eb23b617.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-calorie-counter/660404511dbf1b90eb23b617.md
index 203947b61e..936462caf7 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/workshop-calorie-counter/660404511dbf1b90eb23b617.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-calorie-counter/660404511dbf1b90eb23b617.md
@@ -18,13 +18,13 @@ Open up the console to see the result. In the next step, you will learn more abo
You should have a `console.log` below your `isInvalidInput` function.
```js
-assert.match(code, /console.log\(/);
+assert.match(code, /console\.log\(/);
```
Your console statement should have the value of `isInvalidInput("1e3")`.
```js
-assert.match(code, /console.log\(isInvalidInput\(('|")1e3\s*\1\);?\)/);
+assert.match(code, /console\.log\(isInvalidInput\(('|")1e3\s*\1\);?\)/);
```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-calorie-counter/6604080b66ff6e942d8225b1.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-calorie-counter/6604080b66ff6e942d8225b1.md
index b1f808ba93..08a71268db 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/workshop-calorie-counter/6604080b66ff6e942d8225b1.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-calorie-counter/6604080b66ff6e942d8225b1.md
@@ -31,13 +31,13 @@ Open up the console to see the result. You will learn more about what this resul
You should have a `console.log` below your `isInvalidInput` function.
```js
-assert.match(code, /console.log\(/);
+assert.match(code, /console\.log\(/);
```
Your console statement should have the value of `isInvalidInput("10")`.
```js
-assert.match(code, /console.log\(isInvalidInput\(('|")10\s*\1\);?\)/);
+assert.match(code, /console\.log\(isInvalidInput\(('|")10\s*\1\);?\)/);
```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-calorie-counter/66040ae710de0e96c26a0201.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-calorie-counter/66040ae710de0e96c26a0201.md
index cc6ce6d01e..d9080dfe2d 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/workshop-calorie-counter/66040ae710de0e96c26a0201.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-calorie-counter/66040ae710de0e96c26a0201.md
@@ -18,7 +18,7 @@ Now that you have finished testing your `isInvalidInput` function, you can remov
You should remove your `console.log(isInvalidInput("10"));`.
```js
-assert.notMatch(code, /console.log\(isInvalidInput\("10"\)\);?/g)
+assert.notMatch(code, /console\.log\(isInvalidInput\("10"\)\);?/g)
```
# --seed--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-cat-painting/646ceb843412c74edee27a79.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-cat-painting/646ceb843412c74edee27a79.md
index 28446c8578..910f201646 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/workshop-cat-painting/646ceb843412c74edee27a79.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-cat-painting/646ceb843412c74edee27a79.md
@@ -14,49 +14,49 @@ Using a class selector, give the `.cat-right-ear` element `height` and `width` p
You should have a `.cat-right-ear` selector.
```js
-assert(new __helpers.CSSHelp(document)?.getStyle('.cat-head'))
+assert.exists(new __helpers.CSSHelp(document)?.getStyle('.cat-right-ear'))
```
Your `.cat-right-ear` selector should have a `height` property set to `100px`. Don't forget to add a semi-colon.
```js
-assert(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.height === '100px')
+assert.strictEqual(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.height, '100px')
```
Your `.cat-right-ear` selector should have a `width` property set to `100px`. Don't forget to add a semi-colon.
```js
-assert(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.width === '100px')
+assert.strictEqual(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.width, '100px')
```
Your `.cat-right-ear` selector should have a `background-color` property set to `white`. Don't forget to add a semi-colon.
```js
-assert(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.backgroundColor === 'white')
+assert.strictEqual(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.backgroundColor, 'white')
```
Your `.cat-right-ear` selector should have a `border-left` property set to `35px solid blue`. Don't forget to add a semi-colon.
```js
-assert(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.borderLeft === '35px solid blue')
+assert.strictEqual(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.borderLeft, '35px solid blue')
```
Your `.cat-right-ear` selector should have a `border-right` property set to `35px solid blue`. Don't forget to add a semi-colon.
```js
-assert(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.borderRight === '35px solid blue')
+assert.strictEqual(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.borderRight, '35px solid blue')
```
Your `.cat-right-ear` selector should have a `border-top` property set to `35px solid red`. Don't forget to add a semi-colon.
```js
-assert(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.borderTop === '35px solid red')
+assert.strictEqual(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.borderTop, '35px solid red')
```
Your `.cat-right-ear` selector should have a `border-bottom` property set to `35px solid red`. Don't forget to add a semi-colon.
```js
-assert(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.borderBottom === '35px solid red')
+assert.strictEqual(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.borderBottom, '35px solid red')
```
# --seed--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-cat-painting/646cf2249f02ca5233d9af7c.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-cat-painting/646cf2249f02ca5233d9af7c.md
index b37aa9386b..ef3f32fb5e 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/workshop-cat-painting/646cf2249f02ca5233d9af7c.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-cat-painting/646cf2249f02ca5233d9af7c.md
@@ -16,25 +16,25 @@ Using a class selector, give the `.cat-right-ear` element a left and right borde
You should have a `.cat-right-ear` selector.
```js
-assert(new __helpers.CSSHelp(document).getStyle('.cat-right-ear'))
+assert.exists(new __helpers.CSSHelp(document).getStyle('.cat-right-ear'))
```
Your `.cat-right-ear` selector should have a `border-left` property set to `35px solid transparent`.
```js
-assert(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.borderLeft === '35px solid transparent')
+assert.strictEqual(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.borderLeft, '35px solid transparent')
```
Your `.cat-right-ear` selector should have a `border-right` property set to `35px solid transparent`.
```js
-assert(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.borderRight === '35px solid transparent')
+assert.strictEqual(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.borderRight, '35px solid transparent')
```
Your `.cat-right-ear` selector should have a `border-bottom` property set to `70px solid #5e5e5e`.
```js
-assert(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.borderBottom === '70px solid rgb(94, 94, 94)')
+assert.strictEqual(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.borderBottom, '70px solid rgb(94, 94, 94)')
```
# --seed--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-cat-painting/6676a8b01e56ec1a1e07c202.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-cat-painting/6676a8b01e56ec1a1e07c202.md
index 26922a2a3c..c71c0d6eda 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/workshop-cat-painting/6676a8b01e56ec1a1e07c202.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-cat-painting/6676a8b01e56ec1a1e07c202.md
@@ -19,50 +19,50 @@ Remove the `background-color` property, and you should see a triangle.
You should have a `.cat-right-ear` selector.
```js
-assert(new __helpers.CSSHelp(document)?.getStyle('.cat-right-ear'))
+assert.exists(new __helpers.CSSHelp(document)?.getStyle('.cat-right-ear'))
```
Your `.cat-right-ear` selector should have a `height` property set to `0`. Don't forget to add a semi-colon.
```js
-assert(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.height == '0px')
+assert.strictEqual(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.height, '0px')
```
Your `.cat-right-ear` selector should have a `width` property set to `0`. Don't forget to add a semi-colon.
```js
-assert(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.width === '0px')
+assert.strictEqual(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.width, '0px')
```
Your `.cat-right-ear` selector should have a `border-left` property set to `35px solid transparent`. Don't forget to add a semi-colon.
```js
-assert(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.borderLeft === '35px solid transparent')
+assert.strictEqual(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.borderLeft, '35px solid transparent')
```
Your `.cat-right-ear` selector should have a `border-right` property set to `35px solid transparent`. Don't forget to add a semi-colon.
```js
-assert(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.borderRight === '35px solid transparent')
+assert.strictEqual(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.borderRight, '35px solid transparent')
```
Your `.cat-right-ear` selector should have a `border-top` property set to `35px solid transparent`. Don't forget to add a semi-colon.
```js
-assert(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.borderTop === '35px solid transparent')
+assert.strictEqual(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.borderTop, '35px solid transparent')
```
Your `.cat-right-ear` selector should have a `border-bottom` property set to `35px solid red`. Don't forget to add a semi-colon.
```js
-assert(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.borderBottom === '35px solid red')
+assert.strictEqual(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.borderBottom, '35px solid red')
```
Your `.cat-right-ear` selector should not have a `background-color` property.
```js
-assert(!new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.backgroundColor)
+assert.isEmpty(new __helpers.CSSHelp(document).getStyle('.cat-right-ear')?.backgroundColor)
```
# --seed--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-cat-photo-app/5dc174fcf86c76b9248c6eb2.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-cat-photo-app/5dc174fcf86c76b9248c6eb2.md
index c1e8b49834..2d15027842 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/workshop-cat-photo-app/5dc174fcf86c76b9248c6eb2.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-cat-photo-app/5dc174fcf86c76b9248c6eb2.md
@@ -49,9 +49,11 @@ assert.equal(document.querySelector('h1').innerText.toLowerCase(), 'catphotoapp'
You appear to be using a browser extension that is modifying the page. Be sure to turn off all browser extensions.
```js
-assert.isAtMost(document.querySelectorAll('script').length, 2);
-assert.equal(document.querySelectorAll('style').length, 1);
-assert.equal(document.querySelectorAll('link').length, 0);
+if(__checkForBrowserExtensions){
+ assert.isAtMost(document.querySelectorAll('script').length, 2);
+ assert.equal(document.querySelectorAll('style').length, 1);
+ assert.equal(document.querySelectorAll('link').length, 0);
+}
```
# --seed--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-cat-photo-app/5dc24614f86c76b9248c6ebd.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-cat-photo-app/5dc24614f86c76b9248c6ebd.md
index b8e42b9307..6751691733 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/workshop-cat-photo-app/5dc24614f86c76b9248c6ebd.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-cat-photo-app/5dc24614f86c76b9248c6ebd.md
@@ -15,7 +15,7 @@ Here is an example linking to `https://www.freecodecamp.org`:
```
-Add an anchor element after the paragraph that links to `https://freecatphotoapp.com`. At this point, the link won’t show up in the preview.
+Add an anchor element after the paragraph that links to `https://freecatphotoapp.com`. At this point, the link won't show up in the preview.
# --hints--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-colored-markers/61764c602bee6974e7790f35.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-colored-markers/61764c602bee6974e7790f35.md
index fc6529131a..c13f28167a 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/workshop-colored-markers/61764c602bee6974e7790f35.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-colored-markers/61764c602bee6974e7790f35.md
@@ -7,7 +7,7 @@ dashedName: step-11
# --description--
-To give the markers different colors, you’ll need to add a unique class to each one. You can add multiple classes to an element by listing them in the `class` attribute and separating them with a space. For example, the following code adds both the `animal` and `dog` classes to a `div` element:
+To give the markers different colors, you'll need to add a unique class to each one. You can add multiple classes to an element by listing them in the `class` attribute and separating them with a space. For example, the following code adds both the `animal` and `dog` classes to a `div` element:
```html
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-colored-markers/617bbb6b97a83f6d1f7d6e38.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-colored-markers/617bbb6b97a83f6d1f7d6e38.md
index 75f886d201..fd00f7b450 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/workshop-colored-markers/617bbb6b97a83f6d1f7d6e38.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-colored-markers/617bbb6b97a83f6d1f7d6e38.md
@@ -7,7 +7,7 @@ dashedName: step-26
# --description--
-Now that you've practiced with secondary colors, let’s review how to create
tertiary colors . Tertiary colors are created by combining a primary color with a nearby secondary color.
+Now that you've practiced with secondary colors, let's review how to create
tertiary colors . Tertiary colors are created by combining a primary color with a nearby secondary color.
To create the tertiary color orange, update the `rgb` function in the `.one` CSS rule by setting red to its maximum value (`255`) and green to `127`.
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-colored-markers/61a49d15bdbb5e57cc6fd280.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-colored-markers/61a49d15bdbb5e57cc6fd280.md
index c01ff418d3..b1b5000288 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/workshop-colored-markers/61a49d15bdbb5e57cc6fd280.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-colored-markers/61a49d15bdbb5e57cc6fd280.md
@@ -7,7 +7,7 @@ dashedName: step-49
# --description--
-Color-stops allow you to fine-tune where colors are placed along the gradient line. They are a length unit like `px` or percentages that follow a color in the `linear-gradient` function.
+Color-stops allow you to fine-tune where colors are placed along the gradient line. They are used in the `linear-gradient` function to specify where a color ends and the transition to the next color begins. Either a percentage or a length value can be used to define the color-stop position.
For example, in this red-black gradient, the transition from red to black takes place at the 90% point along the gradient line, so red takes up most of the available space:
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-library-manager/67116d7584d0b469b14579bf.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-library-manager/67116d7584d0b469b14579bf.md
index 1dfbc1497d..3d446000e1 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/workshop-library-manager/67116d7584d0b469b14579bf.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-library-manager/67116d7584d0b469b14579bf.md
@@ -66,7 +66,7 @@ Your object should have a `pages` property.
assert.property(library[0], "pages")
```
-The value of yoour `pages` property should be a number.
+The value of your `pages` property should be a number.
```js
assert.isNumber(library[0]?.pages)
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-library-manager/67116d7584d0b469b14579c1.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-library-manager/67116d7584d0b469b14579c1.md
index ac6bae6794..ba73c877ea 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/workshop-library-manager/67116d7584d0b469b14579c1.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-library-manager/67116d7584d0b469b14579c1.md
@@ -49,7 +49,7 @@ library.forEach((book) => {
});
```
-Your `displayBooks` function should contain the total of `8` books avaialble in the library.
+Your `displayBooks` function should contain the total of `8` books available in the library.
```js
function getNumOfBooks(catalog) {
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-library-manager/67116d7584d0b469b14579c2.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-library-manager/67116d7584d0b469b14579c2.md
index 4c5530c6d5..f41268b973 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/workshop-library-manager/67116d7584d0b469b14579c2.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-library-manager/67116d7584d0b469b14579c2.md
@@ -37,7 +37,7 @@ Your `getBookSummaries` function should use a higher order function. Ex. (`filte
assert.match(getBookSummaries.toString(), /filter|map|reduce|forEach/);
```
-Your `getBookSummaries` function should contain the total of `8` books avaialble in the library.
+Your `getBookSummaries` function should contain the total of `8` books available in the library.
```js
assert.lengthOf(getBookSummaries(library), 8);
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67471d60ce8e6268fe9e12f6.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67471d60ce8e6268fe9e12f6.md
new file mode 100644
index 0000000000..adb3c8b8cf
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67471d60ce8e6268fe9e12f6.md
@@ -0,0 +1,604 @@
+---
+id: 67471d60ce8e6268fe9e12f6
+title: Step 1
+challengeType: 0
+dashedName: step-1
+demoType: onLoad
+---
+
+# --description--
+
+In this workshop you will create a music player app capable of playing, pausing, and skipping songs from a playlist.
+
+The HTML and CSS of this project have been provided for you, so you can focus on the JavaScript.
+
+Start by accessing the `#playlist-songs`, `#play`, and `#pause` elements and assign them to the variables `playlistSongs`, `playButton` and `pauseButton`, respectively.
+
+
+# --hints--
+
+You should have a variable called `playlistSongs`.
+
+```js
+assert.isDefined(playlistSongs);
+```
+
+You should assign the `#playlist-songs` element to the variable `playlistSongs`.
+
+```js
+assert.equal(playlistSongs, document.getElementById('playlist-songs'));
+```
+
+You should have a variable called `playButton`.
+
+```js
+assert.isDefined(playButton);
+```
+
+You should assign the `#play` element to the variable `playButton`.
+
+```js
+assert.equal(playButton, document.getElementById('play'));
+```
+
+You should have a variable called `pauseButton`.
+
+```js
+assert.isDefined(pauseButton);
+```
+
+You should assign the `#pause` element to the variable `pauseButton`.
+
+```js
+assert.equal(pauseButton, document.getElementById('pause'));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6747237371f13173c9f6c27e.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6747237371f13173c9f6c27e.md
new file mode 100644
index 0000000000..30f83c65df
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6747237371f13173c9f6c27e.md
@@ -0,0 +1,591 @@
+---
+id: 6747237371f13173c9f6c27e
+title: Step 2
+challengeType: 0
+dashedName: step-2
+---
+
+# --description--
+
+Access the `#next` and `#previous` elements from the HTML file.
+
+Assign them to variables named `nextButton`, and `previousButton`, respectively.
+
+# --hints--
+
+You should have a variable called `nextButton`.
+
+```js
+assert.isDefined(nextButton);
+```
+
+You should assign the `#next` element to the variable `nextButton`.
+
+```js
+assert.equal(nextButton, document.getElementById('next'));
+```
+
+You should have a variable called `previousButton`.
+
+```js
+assert.isDefined(previousButton);
+```
+
+You should assign the `#previous` element to the variable `previousButton`.
+
+```js
+assert.equal(previousButton, document.getElementById('previous'));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+--fcc-editable-region--
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674724ff8af92f7733e6d980.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674724ff8af92f7733e6d980.md
new file mode 100644
index 0000000000..94809445c6
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674724ff8af92f7733e6d980.md
@@ -0,0 +1,585 @@
+---
+id: 674724ff8af92f7733e6d980
+title: Step 3
+challengeType: 0
+dashedName: step-3
+---
+
+# --description--
+
+Next, create an ampty array named `allSongs` to store all the songs.
+
+# --hints--
+
+You should have a variable called `allSongs`.
+
+```js
+assert.isDefined(allSongs)
+```
+
+You should assign an array to your `allSongs` variable.
+
+```js
+assert.isArray(allSongs)
+```
+
+Your array should be empty.
+
+```js
+assert.isEmpty(allSongs)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6747257cdf5412781e138bb2.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6747257cdf5412781e138bb2.md
new file mode 100644
index 0000000000..03f55f6703
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6747257cdf5412781e138bb2.md
@@ -0,0 +1,619 @@
+---
+id: 6747257cdf5412781e138bb2
+title: Step 4
+challengeType: 0
+dashedName: step-4
+---
+
+# --description--
+
+Inside the `allSongs` array, create an object with the following properties and values:
+
+```js
+id: 0,
+title: "Scratching The Surface",
+artist: "Quincy Larson",
+duration: "4:25",
+src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+```
+
+# --hints--
+
+Your `allSongs` array should have one value.
+
+```js
+assert.equal(allSongs.length, 1);
+```
+
+Your `allSongs` array should have an object as its first value.
+
+```js
+assert.isObject(allSongs[0]);
+```
+
+Your `allSongs` array should have an object with an `id` property set to the number `0`.
+
+```js
+assert.strictEqual(allSongs[0].id, 0);
+```
+
+Your `allSongs` array should have an object with a `title` property set to the string `"Scratching The Surface"`.
+
+```js
+assert.equal(allSongs[0].title, "Scratching The Surface");
+```
+
+Your `allSongs` array should have an object with an `artist` property set to the string `"Quincy Larson"`.
+
+```js
+assert.equal(allSongs[0].artist, "Quincy Larson");
+```
+
+Your `allSongs` array should have an object with a `duration` property set to the string `"4:25"`.
+
+```js
+assert.equal(allSongs[0].duration, "4:25");
+```
+
+Your `allSongs` array should have an object with a `src` property set to the string `"https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3"`.
+
+```js
+assert.equal(allSongs[0].src, "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+--fcc-editable-region--
+const allSongs = [
+
+]
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6747274264e8a5799fb3e0b5.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6747274264e8a5799fb3e0b5.md
new file mode 100644
index 0000000000..5660a8dedd
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6747274264e8a5799fb3e0b5.md
@@ -0,0 +1,626 @@
+---
+id: 6747274264e8a5799fb3e0b5
+title: Step 5
+challengeType: 0
+dashedName: step-5
+---
+
+# --description--
+
+Add a second object with the following keys and values:
+
+```js
+id: 1,
+title: "Can't Stay Down",
+artist: "Quincy Larson",
+duration: "4:15",
+src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+```
+
+# --hints--
+
+Your `allSongs` array should have two values.
+
+```js
+assert.equal(allSongs.length, 2);
+```
+
+Your `allSongs` array should have an object as its second value.
+
+```js
+assert.isObject(allSongs[1]);
+```
+
+The second object in your `allSongs` array should have an `id` property set to the number `1`.
+
+```js
+assert.strictEqual(allSongs[1].id, 1);
+```
+
+The second object in your `allSongs` array should have a `title` property set to the string `"Can't Stay Down"`.
+
+```js
+assert.equal(allSongs[1].title, "Can't Stay Down");
+```
+
+The second object in your `allSongs` array should have an `artist` property set to the string `"Quincy Larson"`.
+
+```js
+assert.equal(allSongs[1].artist, "Quincy Larson");
+```
+
+The second object in your `allSongs` array should have a `duration` property set to the string `"4:15"`.
+
+```js
+assert.equal(allSongs[1].duration, "4:15");
+```
+
+The second object in your `allSongs` array should have a `src` property set to the string `"https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3"`.
+
+```js
+assert.equal(allSongs[1].src, "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+--fcc-editable-region--
+
+--fcc-editable-region--
+];
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674728eda5829d7b4c360643.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674728eda5829d7b4c360643.md
new file mode 100644
index 0000000000..d4725a42a5
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674728eda5829d7b4c360643.md
@@ -0,0 +1,629 @@
+---
+id: 674728eda5829d7b4c360643
+title: Step 6
+challengeType: 0
+dashedName: step-6
+---
+
+# --description--
+
+Add a third object with the following properties and values:
+
+```js
+id: 2,
+title: "Still Learning",
+artist: "Quincy Larson",
+duration: "3:51",
+src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+```
+
+# --hints--
+
+Your `allSongs` array should have an object as its third value.
+
+```js
+assert.isObject(allSongs[2]);
+```
+
+The third object in your `allSongs` array should have an `id` property set to the number `2`.
+
+```js
+assert.equal(allSongs[2].id, 2);
+```
+
+The third object in your `allSongs` array should have a `title` property set to the string `"Still Learning"`.
+
+```js
+assert.equal(allSongs[2].title, "Still Learning");
+```
+
+The third object in your `allSongs` array should have an `artist` property set to the string `"Quincy Larson"`.
+
+```js
+assert.equal(allSongs[2].artist, "Quincy Larson");
+```
+
+The third object in your `allSongs` array should have a `duration` property set to the string `"3:51"`.
+
+```js
+assert.equal(allSongs[2].duration, "3:51");
+```
+
+The third object in your `allSongs` array should have a `src` property set to the string `"https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3"`.
+
+```js
+assert.equal(allSongs[2].src, "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+];
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6747299cbed5107c6a00d64c.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6747299cbed5107c6a00d64c.md
new file mode 100644
index 0000000000..d2ac453312
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6747299cbed5107c6a00d64c.md
@@ -0,0 +1,656 @@
+---
+id: 6747299cbed5107c6a00d64c
+title: Step 7
+challengeType: 0
+dashedName: step-7
+---
+
+# --description--
+
+The rest of the songs has been added to the `allSongs` array for you.
+
+In the previous lecture video, you learned about the
Web Audio API and how to use it to play songs. All modern browsers support the Web Audio API, which lets you generate and process audio in web applications.
+
+Create a variable named `audio` and set it equal to `new Audio()`. This will create a new HTML5 `audio` element.
+
+# --hints--
+
+You should have a variable named `audio`.
+
+```js
+assert.isDefined(audio);
+```
+
+You should assign a new instance of the `Audio` object to the variable named `audio`.
+
+```js
+assert.instanceOf(audio, Audio)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67472ab9f570797dbb01568a.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67472ab9f570797dbb01568a.md
new file mode 100644
index 0000000000..c2fa6984fa
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67472ab9f570797dbb01568a.md
@@ -0,0 +1,656 @@
+---
+id: 67472ab9f570797dbb01568a
+title: Step 8
+challengeType: 0
+dashedName: step-8
+---
+
+# --description--
+
+Your music player should keep track of the songs, the current song playing, and the time of the current song. To do this, you will need to create an object to store this information.
+
+Start by declaring a new variable called `userData` and assign it an empty object.
+
+# --hints--
+
+You should have a variable named `userData`.
+
+```js
+assert.isDefined(userData);
+```
+
+You should assign an empty object to your `userData` variable.
+
+```js
+assert.deepEqual(userData, {});
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67472eef7b4b7ba77b50929b.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67472eef7b4b7ba77b50929b.md
new file mode 100644
index 0000000000..11e4adee44
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67472eef7b4b7ba77b50929b.md
@@ -0,0 +1,664 @@
+---
+id: 67472eef7b4b7ba77b50929b
+title: Step 9
+challengeType: 0
+dashedName: step-9
+---
+
+# --description--
+
+In your `userData` object, create a `songs` property and set its value to the `allSongs` array.
+
+Then, to handle the current song's information and track its playback time, create a `currentSong` and `songCurrentTime` properties. Set the values to `null` and `0`, respectively.
+
+# --hints--
+
+Your `userData` object should have a `songs` key set to the `allSongs` array.
+
+```js
+assert.propertyVal(userData, "songs", allSongs);
+```
+
+Your `userData` object should have a `currentSong` key set to `null`.
+
+```js
+assert.propertyVal(userData, "currentSong", null);
+```
+
+Your `userData` object should have a `songCurrentTime` key set to `0`.
+
+```js
+assert.propertyVal(userData, "songCurrentTime", 0);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+--fcc-editable-region--
+const userData = {
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67473042e8751eac62fafc82.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67473042e8751eac62fafc82.md
new file mode 100644
index 0000000000..0cde6737d9
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67473042e8751eac62fafc82.md
@@ -0,0 +1,661 @@
+---
+id: 67473042e8751eac62fafc82
+title: Step 10
+challengeType: 0
+dashedName: step-10
+---
+
+# --description--
+
+It's time to begin implementing the functionality for playing the displayed songs.
+
+Define a `playSong` function that takes an single parameter which will represent the unique identifier of the song you want to play.
+
+# --hints--
+
+You should have an empty function named `playSong`.
+
+```js
+assert.isFunction(playSong);
+```
+
+Your `playSong` function should take a single parameter.
+
+```js
+assert.lengthOf(playSong, 1);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674735e3b28351b8b8f05807.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674735e3b28351b8b8f05807.md
new file mode 100644
index 0000000000..c2cb8ceec2
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674735e3b28351b8b8f05807.md
@@ -0,0 +1,709 @@
+---
+id: 674735e3b28351b8b8f05807
+title: Step 11
+challengeType: 0
+dashedName: step-11
+---
+
+# --description--
+
+The `find()` method retrieves the first element within an array that fulfills the conditions specified in the provided callback function. If no element satisfies the condition, the method returns `undefined`.
+
+In the example below, the `find()` method is used to find the first number greater than 25:
+
+```js
+const numbers = [10, 20, 30, 40, 50];
+
+// Find the first number greater than 25
+const foundNumber = numbers.find((number) => number > 25);
+console.log(foundNumber); // Output: 30
+```
+
+Within your `playSong` function, use the `find()` method on the `userData.songs` array to search for a song which has an `id` strictly equal to the `id` passed into the `playSong` function. Assign the `find` call to a variable named `song`.
+
+# --hints--
+
+Your `playSong` function should call the `find` method on `userData.songs`.
+
+```js
+let flag = false;
+const temp = userData.songs.find;
+userData.songs.find = foo => {flag = true};
+try {
+ playSong(0);
+ assert.isTrue(flag);
+} finally {
+ userData.songs.find = temp;
+}
+```
+
+Your `find` call should return a song whose `id` is strictly equal to the `id` passed into the `playSong` function.
+
+```js
+const testArr = [
+ {id: 0},
+ {id: 1},
+ {id: 2},
+]
+let callback;
+const testFind = id => testArr.find(callback);
+const temp = userData.songs.find;
+userData.songs.find = foo => {callback = foo};
+try {
+ playSong(0);
+ assert.deepEqual(testFind(0), {id: 0});
+ playSong(1);
+ assert.deepEqual(testFind(1), {id: 1});
+ playSong(2);
+ assert.deepEqual(testFind(2), {id: 2});
+ playSong(3);
+ assert.isUndefined(testFind(3));
+ playSong("0");
+ assert.isUndefined(testFind("0"));
+} finally {
+ userData.songs.find = temp;
+}
+```
+
+You should assign your `find` call to a variable named `song`.
+
+```js
+assert.match(__helpers.removeJSComments(code), /(const|let)\s+song\s*=\s*userData\s*\.\s*songs\s*\.\s*find\s*\(.+\)/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+--fcc-editable-region--
+const playSong = id => {
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674757668684f9deaa6ac3c0.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674757668684f9deaa6ac3c0.md
new file mode 100644
index 0000000000..cd1ecd5530
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674757668684f9deaa6ac3c0.md
@@ -0,0 +1,676 @@
+---
+id: 674757668684f9deaa6ac3c0
+title: Step 12
+challengeType: 0
+dashedName: step-12
+---
+
+# --description--
+
+Still inside the `playSong` function, set the `audio.src` property equal to `song.src`. This tells the audio element where to find the audio data for the selected song.
+
+Also, set the `audio.title` property equal to `song.title`. This tells the audio element what to display as the title of the song.
+
+# --hints--
+
+You should set the `audio.src` property equal to `song.src` inside your `playSong` function.
+
+```js
+const temp = audio;
+try {
+ playSong(2);
+ assert.equal(audio.src, "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3");
+} finally {
+ audio = temp;
+}
+```
+
+You should set the `audio.title` property equal to `song.title` inside your `playSong` function.
+
+```js
+const temp = audio;
+try {
+ playSong(2);
+ assert.equal(audio.title, "Still Learning");
+} finally {
+ audio = temp;
+}
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+--fcc-editable-region--
+const playSong = id => {
+ const song = userData.songs.find((song) => song.id === id);
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674836ba82e9057dfee1849c.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674836ba82e9057dfee1849c.md
new file mode 100644
index 0000000000..1a6d3945d3
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674836ba82e9057dfee1849c.md
@@ -0,0 +1,690 @@
+---
+id: 674836ba82e9057dfee1849c
+title: Step 15
+challengeType: 0
+dashedName: step-15
+---
+
+# --description--
+
+Next, use the `classList` property and the `add()` method to add the `playing` class to the `playButton` element. This will look for the class `playing` in the CSS file and add it to the `playButton` element.
+
+Then, set `userData.currentSong` to `song`, and to finally play the song, use the `play()` method on the `audio` variable. `play()` is a method from the web audio API for playing an mp3 file.
+
+# --hints--
+
+You should add the `playing` class to the `playButton` element within your `playSong` function.
+
+```js
+playButton.classList.remove("playing");
+playSong(0);
+assert.isTrue(playButton.classList.contains("playing"));
+```
+
+You should set `userData.currentSong` to `song` within your `playSong` function.
+
+```js
+userData.currentSong = null;
+playSong(0);
+assert.deepEqual(userData.currentSong, {id: 0, title: "Scratching The Surface", artist: "Quincy Larson", duration: "4:25", src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3"});
+```
+
+You should call the `play()` method on the `audio` variable within your `playSong` function.
+
+```js
+let flag = false;
+const temp = audio.play;
+audio.play = () => {flag = true};
+try {
+ playSong(0);
+ assert.isTrue(flag);
+} finally {
+ audio.play = temp;
+}
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = id => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+--fcc-editable-region--
+
+--fcc-editable-region--
+}
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674850b437668dd08edddbe2.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674850b437668dd08edddbe2.md
new file mode 100644
index 0000000000..b473bbbd8c
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674850b437668dd08edddbe2.md
@@ -0,0 +1,687 @@
+---
+id: 674850b437668dd08edddbe2
+title: Step 16
+challengeType: 0
+dashedName: step-16
+---
+
+# --description--
+
+In previous steps you built out the functionality for playing a song. Now you need to add the functionality to the play button.
+
+Use the `addEventListener()` method on `playButton` and pass in a `"click"` event for the first argument. For now, use a callback that calls `playSong(0)` as the second argument.
+
+Then, test it by clicking the play button.
+
+
+# --hints--
+
+You should add an event listener for the `click` event to the `playButton` and pass a callback function that calls `playSong(0)` as the second argument to the `addEventListener` method.
+
+```js
+let flag;
+const testArr = [];
+const temp = playSong;
+playSong = id => {
+ flag = true;
+ testArr.push(id);
+}
+try {
+ assert.isUndefined(flag);
+ assert.isEmpty(testArr);
+ playButton.click();
+ assert.isTrue(flag);
+ assert.deepEqual(testArr, [0]);
+} finally {
+ playSong = temp;
+}
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = id => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing")
+ audio.play()
+}
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6748567229cc8fe3f706de02.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6748567229cc8fe3f706de02.md
new file mode 100644
index 0000000000..4c491a7de2
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6748567229cc8fe3f706de02.md
@@ -0,0 +1,698 @@
+---
+id: 6748567229cc8fe3f706de02
+title: Step 21
+challengeType: 0
+dashedName: step-21
+---
+
+# --description--
+
+Now you need to work on pausing the currently playing song.
+
+Define a `pauseSong` function that takes no parameters. Within your new function, to store the current time of the song when it is paused, set the `songCurrentTime` of the `userData` object to the `currentTime` of the `audio` variable.
+
+
+# --hints--
+
+You should have a `pauseSong` function.
+
+```js
+assert.isFunction(pauseSong);
+```
+
+Yor `pauseSong` function should set the `songCurrentTime` of the `userData` object to the `currentTime` of the `audio` variable.
+
+```js
+userData.songCurrentTime = 0;
+audio.currentTime = 10;
+pauseSong()
+assert.equal(userData.songCurrentTime, 10);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = id => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing")
+ audio.play()
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+playButton.addEventListener("click", () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ } else {
+ playSong(userData.currentSong.id);
+ }
+});
+
+const songs = document.querySelectorAll(".playlist-song");
+
+songs.forEach((song) => {
+ const id = song.getAttribute("id").slice(5);
+ const songBtn = song.querySelector("button");
+ songBtn.addEventListener("click", () => {
+ playSong(Number(id));
+ })
+})
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6748bab9827a356c39559214.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6748bab9827a356c39559214.md
new file mode 100644
index 0000000000..365b3f5e13
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6748bab9827a356c39559214.md
@@ -0,0 +1,707 @@
+---
+id: 6748bab9827a356c39559214
+title: Step 22
+challengeType: 0
+dashedName: step-22
+---
+
+# --description--
+
+Use `classList` and `remove()` method to remove the `playing` class from the `playButton`, since the song will be paused at this point.
+
+To finally pause the song, use the `pause()` method on the `audio` variable. `pause()` is a method of the Web Audio API for pausing music files.
+
+# --hints--
+
+Your `pauseSong` function should remove the `playing` class from the `playButton`.
+
+```js
+playButton.classList.add("playing");
+pauseSong();
+assert.isFalse(playButton.classList.contains("playing"));
+```
+
+Your `pauseSong` function should call the `pause()` method on `audio`.
+
+```js
+let flag;
+const temp = audio.pause;
+audio.pause = () => {flag = true};
+try {
+ pauseSong();
+ assert.isTrue(flag);
+} finally {
+ audio.pause = temp;
+}
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = id => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing");
+ audio.play()
+}
+
+const pauseSong = () => {
+ userData.songCurrentTime = audio.currentTime;
+--fcc-editable-region--
+
+--fcc-editable-region--
+}
+
+playButton.addEventListener("click", () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ } else {
+ playSong(userData.currentSong.id);
+ }
+});
+
+const songs = document.querySelectorAll(".playlist-song");
+
+songs.forEach((song) => {
+ const id = song.getAttribute("id").slice(5);
+ const songBtn = song.querySelector("button");
+ songBtn.addEventListener("click", () => {
+ playSong(Number(id));
+ })
+})
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674dda6c6ae8bb538678e125.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674dda6c6ae8bb538678e125.md
new file mode 100644
index 0000000000..9e2345c817
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674dda6c6ae8bb538678e125.md
@@ -0,0 +1,671 @@
+---
+id: 674dda6c6ae8bb538678e125
+title: Step 13
+challengeType: 0
+dashedName: step-13
+---
+
+# --description--
+
+Before playing the song, you need to make sure it starts from the beginning. This can be achieved by the use of the `currentTime` property on the `audio` object.
+
+Add an `if` statement to check if no current song is playing by verifying that `userData.currentSong` is falsy. Inside `if` block, set the `currentTime` property of the `audio` object to `0`.
+
+# --hints--
+
+Your `playSong` function should set the `currentTime` property of the `audio` object to `0` when no current song is playing.
+
+```js
+const temp1 = audio.currentTime;
+const temp2 = userData.currentSong;
+audio.currentTime = 10;
+userData.currentSong = null;
+try {
+ playSong(0);
+ assert.strictEqual(audio.currentTime, 0);
+} finally {
+ audio.currentTime = temp1;
+ userData.currentSong = temp2;
+}
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = id => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+--fcc-editable-region--
+
+--fcc-editable-region--
+}
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674de4ee2039496c30a31b71.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674de4ee2039496c30a31b71.md
new file mode 100644
index 0000000000..dc4ea3f5a2
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674de4ee2039496c30a31b71.md
@@ -0,0 +1,693 @@
+---
+id: 674de4ee2039496c30a31b71
+title: Step 14
+challengeType: 0
+dashedName: step-14
+---
+
+# --description--
+
+Add an `else` block to handle the song's current playback time. This allows you to resume the current song at the point where it was paused.
+
+Within the `else` block, set the `currentTime` property of the `audio` object to the value stored in `userData.songCurrentTime`.
+
+# --hints--
+
+Your `playSong` function should set the `currentTime` property of the `audio` object to the value stored in `userData.songCurrentTime` when there's a current song playing.
+
+```js
+const temp1 = audio.currentTime;
+const temp2 = userData.currentSong;
+const temp3 = userData.songCurrentTime;
+audio.currentTime = 10;
+userData.currentSong = allSongs[2];
+userData.songCurrentTime = 15;
+try {
+ playSong(0);
+ assert.strictEqual(audio.currentTime, 15);
+} finally {
+ audio.currentTime = temp1;
+ userData.currentSong = temp2;
+ userData.songCurrentTime = temp3;
+}
+```
+
+You should not modify the existing `if` statement and its content.
+
+```js
+const temp1 = audio.currentTime;
+const temp2 = userData.currentSong;
+audio.currentTime = 10;
+userData.currentSong = null;
+try {
+ playSong(0);
+ assert.strictEqual(audio.currentTime, 0);
+} finally {
+ audio.currentTime = temp1;
+ userData.currentSong = temp2;
+}
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = id => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+--fcc-editable-region--
+ if (userData.currentSong === null) {
+ audio.currentTime = 0
+ }
+
+--fcc-editable-region--
+}
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674e2e4e04eb381ccfe92e15.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674e2e4e04eb381ccfe92e15.md
new file mode 100644
index 0000000000..a0e5c54bd9
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674e2e4e04eb381ccfe92e15.md
@@ -0,0 +1,708 @@
+---
+id: 674e2e4e04eb381ccfe92e15
+title: Step 23
+challengeType: 0
+dashedName: step-23
+---
+
+# --description--
+
+Now it is time to test out the pause button.
+
+Add a `"click"` event listener to the `pauseButton` element, then pass in `pauseSong` as the second argument of the event listener. This is the function the event listener will run.
+
+Test out your app by first clicking on the play button followed by the pause button. You should see that everything is working as expected.
+
+# --hints--
+
+You should call the `addEventListener()` method on your `pauseButton` variable.
+
+```js
+assert.match(__helpers.removeJSComments(code), /pauseButton\.addEventListener\(/)
+```
+
+Your event listener should listen for a `"click"` event.
+
+```js
+assert.match(__helpers.removeJSComments(code), /pauseButton\.addEventListener\(\s*('|"|`)click\1/)
+```
+
+You should pass in `pauseSong` as the second argument of your `addEventListener` method.
+
+```js
+assert.match(__helpers.removeJSComments(code), /pauseButton\.addEventListener\(\s*('|"|`)click\1\s*,\s*pauseSong\s*\)/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = id => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing");
+ audio.play()
+}
+
+const pauseSong = () => {
+ userData.songCurrentTime = audio.currentTime;
+ playButton.classList.remove("playing");
+ audio.pause();
+}
+
+playButton.addEventListener("click", () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ } else {
+ playSong(userData.currentSong.id);
+ }
+});
+
+const songs = document.querySelectorAll(".playlist-song");
+
+songs.forEach((song) => {
+ const id = song.getAttribute("id").slice(5);
+ const songBtn = song.querySelector("button");
+ songBtn.addEventListener("click", () => {
+ playSong(Number(id));
+ })
+})
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674e305b7bda7c1f4f37a930.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674e305b7bda7c1f4f37a930.md
new file mode 100644
index 0000000000..5512907279
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674e305b7bda7c1f4f37a930.md
@@ -0,0 +1,719 @@
+---
+id: 674e305b7bda7c1f4f37a930
+title: Step 24
+challengeType: 0
+dashedName: step-24
+---
+
+# --description--
+
+Before you start working on playing the next and previous song, you need to get the index of each song in the `songs` property of `userData`. To do that you can use the `indexOf()` array method, which returns the first index at which a given element can be found in the array, or `-1` if the element is not present.
+
+```js
+const animals = ["dog", "cat", "horse"];
+animals.indexOf("cat") // 1
+```
+
+Create a function named `getCurrentSongIndex` that returns the index at which `userData.currentSong` can be found in `userData.songs` and `-1` when the current song is `null`.
+
+# --hints--
+
+You should have a function named `getCurrentSongIndex`.
+
+```js
+assert.isFunction(getCurrentSongIndex);
+```
+
+Your `getCurrentSongIndex` function should return the index at which `userData.currentSong` can be found in `userData.songs`.
+
+```js
+userData.currentSong = allSongs[2]
+assert.strictEqual(getCurrentSongIndex(), 2);
+
+userData.currentSong = allSongs[4]
+assert.strictEqual(getCurrentSongIndex(), 4);
+```
+
+Your `getCurrentSongIndex` function should return `-1` when `userData.currentSong` is `null`.
+
+```js
+userData.currentSong = null
+assert.strictEqual(getCurrentSongIndex(), -1);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = id => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing");
+ audio.play()
+}
+
+const pauseSong = () => {
+ userData.songCurrentTime = audio.currentTime;
+ playButton.classList.remove("playing");
+ audio.pause();
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+playButton.addEventListener("click", () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ } else {
+ playSong(userData.currentSong.id);
+ }
+});
+
+const songs = document.querySelectorAll(".playlist-song");
+
+songs.forEach((song) => {
+ const id = song.getAttribute("id").slice(5);
+ const songBtn = song.querySelector("button");
+ songBtn.addEventListener("click", () => {
+ playSong(Number(id));
+ })
+})
+
+pauseButton.addEventListener("click", pauseSong);
+
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674e316e3892d32108ad2bb9.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674e316e3892d32108ad2bb9.md
new file mode 100644
index 0000000000..f505ac3ea7
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674e316e3892d32108ad2bb9.md
@@ -0,0 +1,692 @@
+---
+id: 674e316e3892d32108ad2bb9
+title: Step 17
+challengeType: 0
+dashedName: step-17
+---
+
+# --description--
+
+Anytime you click the play button, the first song of your playlist will always play. To fix this, within the arrow function of the event listener, replace `playSong(0)` with an `if` statement that checks if `userData.currentSong` is `null`.
+
+Inside the `if` block, call the `playSong` function with the `id` of the first song in the `userData.songs` array.
+
+# --hints--
+
+You should modify the callback of the event listener to call the `playSong` function with the `id` of the first song in the `userData.songs` array when `userData.currentSong` is `null`.
+
+```js
+let flag;
+const testArr = [];
+const temp1 = playSong;
+const temp2 = userData.currentSong;
+userData.currentSong = allSongs[3];
+playSong = id => {
+ flag = true;
+ testArr.push(id);
+}
+try {
+ playButton.click();
+ assert.isUndefined(flag);
+ assert.isEmpty(testArr);
+
+ userData.currentSong = null;
+ playButton.click();
+ assert.isTrue(flag);
+ assert.deepEqual(testArr, [0]);
+} finally {
+ playSong = temp1;
+ userData.currentSong = temp2;
+}
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = id => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing")
+ audio.play()
+}
+--fcc-editable-region--
+playButton.addEventListener("click", () => {
+ playSong(0);
+});
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674e34c42ee8f1237e4623cc.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674e34c42ee8f1237e4623cc.md
new file mode 100644
index 0000000000..f2d054e966
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674e34c42ee8f1237e4623cc.md
@@ -0,0 +1,712 @@
+---
+id: 674e34c42ee8f1237e4623cc
+title: Step 18
+challengeType: 0
+dashedName: step-18
+---
+
+# --description--
+
+Add an `else` block. Inside the `else` block, call the `playSong` function with the `id` of the currently playing song as an argument.
+
+This ensures that the currently playing song will continue to play when the play button is clicked.
+
+# --hints--
+
+When the `playButton` is clicked and `userData.currentSong` is not `null`, you should call the `playSong` function with the `id` of the currently playing song.
+
+```js
+let flag;
+const testArr = [];
+const temp1 = playSong;
+const temp2 = userData.currentSong;
+userData.currentSong = allSongs[3];
+playSong = id => {
+ flag = true;
+ testArr.push(id);
+}
+try {
+ playButton.click();
+ assert.isTrue(flag);
+ assert.deepEqual(testArr, [3]);
+} finally {
+ playSong = temp1;
+ userData.currentSong = temp2;
+}
+```
+
+You should still call the `playSong` function with the `id` of the first song in your playlist when the `playButton` is clicked and `userData.currentSong` is `null`,
+
+```js
+let flag;
+const testArr = [];
+const temp1 = playSong;
+const temp2 = userData.currentSong;
+userData.currentSong = null;
+playSong = id => {
+ flag = true;
+ testArr.push(id);
+}
+try {
+ playButton.click();
+ assert.isTrue(flag);
+ assert.deepEqual(testArr, [0]);
+} finally {
+ playSong = temp1;
+ userData.currentSong = temp2;
+}
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = id => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing")
+ audio.play()
+}
+--fcc-editable-region--
+playButton.addEventListener("click", () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ }
+});
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674f489bf617af2bea9b92b5.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674f489bf617af2bea9b92b5.md
new file mode 100644
index 0000000000..ca606f0d40
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674f489bf617af2bea9b92b5.md
@@ -0,0 +1,729 @@
+---
+id: 674f489bf617af2bea9b92b5
+title: Step 25
+challengeType: 0
+dashedName: step-25
+---
+
+# --description--
+
+Now, create a function named `getNextSong`. Make it return the song that can be found at `getCurrentSongIndex()` plus one in `userData.songs`, or `undefined` if the current song is the last one in the playlist.
+
+# --hints--
+
+You should have a function named `getNextSong`.
+
+```js
+assert.isFunction(getNextSong);
+```
+
+Your `getNextSong` function should call `getCurrentSongIndex`.
+
+```js
+let flag;
+const temp = getCurrentSongIndex;
+getCurrentSongIndex = () => {flag = true};
+try {
+ getNextSong();
+ assert.isTrue(flag);
+} finally {
+ getCurrentSongIndex = temp;
+}
+```
+
+Your `getNextSong` function should return the song next to the current song.
+
+```js
+userData.currentSong = allSongs[2]
+assert.equal(getNextSong(), allSongs[3]);
+
+userData.currentSong = allSongs[4]
+assert.equal(getNextSong(), allSongs[5]);
+```
+
+Your `getNextSong` function should return `undefined` when the current song is the last one in the playlist.
+
+```js
+userData.currentSong = allSongs[9]
+assert.isUndefined(getNextSong());
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = id => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing");
+ audio.play()
+}
+
+const pauseSong = () => {
+ userData.songCurrentTime = audio.currentTime;
+ playButton.classList.remove("playing");
+ audio.pause();
+}
+
+const getCurrentSongIndex = () => userData.songs.indexOf(userData.currentSong);
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+playButton.addEventListener("click", () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ } else {
+ playSong(userData.currentSong.id);
+ }
+});
+
+const songs = document.querySelectorAll(".playlist-song");
+
+songs.forEach((song) => {
+ const id = song.getAttribute("id").slice(5);
+ const songBtn = song.querySelector("button");
+ songBtn.addEventListener("click", () => {
+ playSong(Number(id));
+ })
+})
+
+pauseButton.addEventListener("click", pauseSong);
+
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674f50cce486fb404751a29c.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674f50cce486fb404751a29c.md
new file mode 100644
index 0000000000..73a63b1ce9
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674f50cce486fb404751a29c.md
@@ -0,0 +1,729 @@
+---
+id: 674f50cce486fb404751a29c
+title: Step 26
+challengeType: 0
+dashedName: step-26
+---
+
+# --description--
+
+Now that you know how to find the next song to play, create a function named `playNextSong`. Inside the `playNextSong` function, create an `if` statement to check if the `currentSong` of `userData` is strictly equal to `null`. This will check if there's no current song playing in the `userData` object.
+
+If the condition is true, call the `playSong` function with the `id` of the first song in the `userData.songs` array as an argument.
+
+# --hints--
+
+You should have a function named `playNextSong`.
+
+```js
+assert.isFunction(playNextSong);
+```
+
+When the `currentSong` of `userData` is strictly equal to `null`, your `playNextSong` function should call the `playSong` function with the `id` of the first song in the `userData.songs` array as an argument.
+
+```js
+let flag;
+const testArr = [];
+const temp = playSong;
+playSong = id => {
+ flag = true;
+ testArr.push(id);
+}
+try {
+ userData.currentSong = allSongs[2];
+ playNextSong();
+ assert.isUndefined(flag);
+ assert.isEmpty(testArr);
+ userData.currentSong = undefined;
+ playNextSong();
+ assert.isUndefined(flag);
+ assert.isEmpty(testArr);
+ userData.currentSong = null;
+ playNextSong();
+ assert.isTrue(flag);
+ assert.deepEqual(testArr, [0]);
+} finally {
+ playSong = temp;
+}
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = id => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing");
+ audio.play()
+}
+
+const pauseSong = () => {
+ userData.songCurrentTime = audio.currentTime;
+ playButton.classList.remove("playing");
+ audio.pause();
+}
+
+const getCurrentSongIndex = () => userData.songs.indexOf(userData.currentSong);
+
+const getNextSong = () => userData.songs[getCurrentSongIndex() + 1];
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+playButton.addEventListener("click", () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ } else {
+ playSong(userData.currentSong.id);
+ }
+});
+
+const songs = document.querySelectorAll(".playlist-song");
+
+songs.forEach((song) => {
+ const id = song.getAttribute("id").slice(5);
+ const songBtn = song.querySelector("button");
+ songBtn.addEventListener("click", () => {
+ playSong(Number(id));
+ })
+})
+
+pauseButton.addEventListener("click", pauseSong);
+
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674f534fa181f64a789ffcf9.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674f534fa181f64a789ffcf9.md
new file mode 100644
index 0000000000..4ea90ee238
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/674f534fa181f64a789ffcf9.md
@@ -0,0 +1,787 @@
+---
+id: 674f534fa181f64a789ffcf9
+title: Step 27
+challengeType: 0
+dashedName: step-27
+---
+
+# --description--
+
+If `userData.currentSong` is not `null` you need to find the next song to play. Remember that you can use `getNextSong` for that.
+
+Complete your `playNextSong` function so that can play the next song in the playlist. If the current song is the last one, set `userData.currentSong` to `null`, `userData.songCurrentTime` to zero and call the `pauseSong` function.
+
+# --hints--
+
+When the `currentSong` of `userData` is truthy and not the last song of the playlist, the `playNextSong` function should play the song next to the current song.
+
+```js
+let flag;
+const testArr = [];
+const temp1 = userData.currentSong;
+userData.currentSong = allSongs[3];
+const temp2 = playSong;
+playSong = id => {
+ flag = true;
+ testArr.push(id);
+}
+try {
+ playNextSong();
+ assert.isTrue(flag);
+ userData.currentSong = allSongs[4];
+ playNextSong();
+ assert.deepEqual(testArr, [4, 5]);
+} finally {
+ userData.currentSong = temp1;
+ playSong = temp2;
+}
+```
+
+When the `currentSong` of `userData` is the last song of the playlist, the `playNextSong` function should set `userData.currentSong` to `null`.
+
+```js
+const temp = userData.currentSong;
+userData.currentSong = allSongs[9];
+try {
+ playNextSong();
+ assert.isNull(userData.currentSong);
+} finally {
+ userData.currentSong = temp;
+}
+```
+
+When the `currentSong` of `userData` is the last song of the playlist, the `playNextSong` function should set `userData.songCurrentTime` to `0`.
+
+```js
+const temp = userData.songCurrentTime;
+userData.songCurrentTime = 10;
+try {
+ userData.currentSong = allSongs[9];
+ playNextSong();
+ assert.strictEqual(userData.songCurrentTime, 0);
+} finally {
+ userData.songCurrentTime = temp;
+}
+```
+
+When the `currentSong` of `userData` is the last song of the playlist, the `playNextSong` function should call the `pauseSong` function.
+
+```js
+let flag;
+const temp = pauseSong;
+pauseSong = () => {flag = true};
+try {
+ userData.currentSong = allSongs[9];
+ playNextSong();
+ assert.isTrue(flag);
+} finally {
+ pauseSong = temp;
+}
+```
+
+When the `currentSong` of `userData` is equal to `null`, your `playNextSong` function should still call the `playSong` function with the `id` of the first song in the `userData.songs` array as an argument.
+
+```js
+let flag;
+const testArr = [];
+const temp = playSong;
+playSong = id => {
+ flag = true;
+ testArr.push(id);
+}
+try {
+ userData.currentSong = null;
+ playNextSong();
+ assert.isTrue(flag);
+ assert.deepEqual(testArr, [0]);
+} finally {
+ playSong = temp;
+}
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = id => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing");
+ audio.play()
+}
+
+const pauseSong = () => {
+ userData.songCurrentTime = audio.currentTime;
+ playButton.classList.remove("playing");
+ audio.pause();
+}
+
+const getCurrentSongIndex = () => userData.songs.indexOf(userData.currentSong);
+
+const getNextSong = () => userData.songs[getCurrentSongIndex() + 1];
+
+--fcc-editable-region--
+const playNextSong = () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ }
+
+}
+--fcc-editable-region--
+
+
+playButton.addEventListener("click", () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ } else {
+ playSong(userData.currentSong.id);
+ }
+});
+
+const songs = document.querySelectorAll(".playlist-song");
+
+songs.forEach((song) => {
+ const id = song.getAttribute("id").slice(5);
+ const songBtn = song.querySelector("button");
+ songBtn.addEventListener("click", () => {
+ playSong(Number(id));
+ })
+})
+
+pauseButton.addEventListener("click", pauseSong);
+
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67503cecd563135d4f27b38e.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67503cecd563135d4f27b38e.md
new file mode 100644
index 0000000000..ab71844ed4
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67503cecd563135d4f27b38e.md
@@ -0,0 +1,729 @@
+---
+id: 67503cecd563135d4f27b38e
+title: Step 28
+challengeType: 0
+dashedName: step-28
+---
+
+# --description--
+
+Now it is time to test out the `playNextSong` function.
+
+Add a `"click"` event listener to the `nextButton` element, then pass in `playNextSong` as the second argument of your event listener. This is the function the event listener will run.
+
+Test out your app by first clicking on the play button followed by the next button. You should see that everything is working as expected.
+
+# --hints--
+
+You should call the `addEventListener()` method on your `nextButton` variable.
+
+```js
+assert.match(__helpers.removeJSComments(code), /nextButton\.addEventListener\(/)
+```
+
+Your event listener should listen for a `"click"` event.
+
+```js
+assert.match(__helpers.removeJSComments(code), /nextButton\.addEventListener\(\s*('|"|`)click\1/)
+```
+
+You should pass in `playNextSong` as the second argument of your `addEventListener` method.
+
+```js
+assert.match(__helpers.removeJSComments(code), /nextButton\.addEventListener\(\s*('|"|`)click\1\s*,\s*playNextSong\s*\)/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = id => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing");
+ audio.play()
+}
+
+const pauseSong = () => {
+ userData.songCurrentTime = audio.currentTime;
+ playButton.classList.remove("playing");
+ audio.pause();
+}
+
+const getCurrentSongIndex = () => userData.songs.indexOf(userData.currentSong);
+
+const getNextSong = () => userData.songs[getCurrentSongIndex() + 1];
+
+const playNextSong = () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ return
+ }
+ const nextSong = getNextSong();
+ if (nextSong) {
+ playSong(nextSong.id);
+ } else {
+ userData.currentSong = null;
+ userData.songCurrentTime = 0;
+ pauseSong();
+ }
+}
+
+playButton.addEventListener("click", () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ } else {
+ playSong(userData.currentSong.id);
+ }
+});
+
+const songs = document.querySelectorAll(".playlist-song");
+
+songs.forEach((song) => {
+ const id = song.getAttribute("id").slice(5);
+ const songBtn = song.querySelector("button");
+ songBtn.addEventListener("click", () => {
+ playSong(Number(id));
+ })
+})
+
+pauseButton.addEventListener("click", pauseSong);
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/675057ce9acd418619127da4.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/675057ce9acd418619127da4.md
new file mode 100644
index 0000000000..c5a4503eb2
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/675057ce9acd418619127da4.md
@@ -0,0 +1,746 @@
+---
+id: 675057ce9acd418619127da4
+title: Step 29
+challengeType: 0
+dashedName: step-29
+---
+
+# --description--
+
+Now, create a function named `getPreviousSong`. Make it return the song that can be found at `getCurrentSongIndex()` minus one in `userData.songs`, or `undefined` if the current song is the first one in the playlist.
+
+# --hints--
+
+You should have a function named `getPreviousSong`.
+
+```js
+assert.isFunction(getPreviousSong);
+```
+
+Your `getPreviousSong` function should call `getCurrentSongIndex`.
+
+```js
+let flag;
+const temp = getCurrentSongIndex;
+getCurrentSongIndex = () => {flag = true};
+try {
+ getPreviousSong();
+ assert.isTrue(flag);
+} finally {
+ getCurrentSongIndex = temp;
+}
+```
+
+Your `getPreviousSong` function should return the song before the current song.
+
+```js
+userData.currentSong = allSongs[4]
+assert.equal(getPreviousSong(), allSongs[3]);
+
+userData.currentSong = allSongs[3]
+assert.equal(getPreviousSong(), allSongs[2]);
+```
+
+Your `getPreviousSong` function should return `undefined` when the current song is the first one in the playlist.
+
+```js
+userData.currentSong = allSongs[0]
+assert.isUndefined(getPreviousSong());
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = id => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing");
+ audio.play()
+}
+
+const pauseSong = () => {
+ userData.songCurrentTime = audio.currentTime;
+ playButton.classList.remove("playing");
+ audio.pause();
+}
+
+const getCurrentSongIndex = () => userData.songs.indexOf(userData.currentSong);
+
+const getNextSong = () => userData.songs[getCurrentSongIndex() + 1];
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+const playNextSong = () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ return
+ }
+ const nextSong = getNextSong();
+ if (nextSong) {
+ playSong(nextSong.id);
+ } else {
+ userData.currentSong = null;
+ userData.songCurrentTime = 0;
+ pauseSong();
+ }
+}
+
+playButton.addEventListener("click", () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ } else {
+ playSong(userData.currentSong.id);
+ }
+});
+
+const songs = document.querySelectorAll(".playlist-song");
+
+songs.forEach((song) => {
+ const id = song.getAttribute("id").slice(5);
+ const songBtn = song.querySelector("button");
+ songBtn.addEventListener("click", () => {
+ playSong(Number(id));
+ })
+})
+
+pauseButton.addEventListener("click", pauseSong);
+
+nextButton.addEventListener("click", playNextSong);
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67505d3a32d45997d2af4c0f.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67505d3a32d45997d2af4c0f.md
new file mode 100644
index 0000000000..c787318a4e
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67505d3a32d45997d2af4c0f.md
@@ -0,0 +1,770 @@
+---
+id: 67505d3a32d45997d2af4c0f
+title: Step 30
+challengeType: 0
+dashedName: step-30
+---
+
+# --description--
+
+Create a function named `playPreviousSong`. Inside your new function, use the value returned by the `getPreviousSong` function to find the song to play. When `getPreviousSong()` is `undefined`, play the first song in your playlist. Otherwise, play the song before the current song playing.
+
+# --hints--
+
+You should have a function named `playPreviousSong`.
+
+```js
+assert.isFunction(playPreviousSong);
+```
+
+The `playPreviousSong` function should play the song before the current song playing in the playlist.
+
+```js
+let flag;
+const testArr = [];
+const temp1 = userData.currentSong;
+userData.currentSong = allSongs[4];
+const temp2 = playSong;
+playSong = id => {
+ flag = true;
+ testArr.push(id);
+}
+try {
+ playPreviousSong();
+ assert.isTrue(flag);
+ userData.currentSong = allSongs[3];
+ flag = false;
+ playPreviousSong();
+ assert.isTrue(flag);
+ assert.deepEqual(testArr, [3, 2]);
+} finally {
+ userData.currentSong = temp1;
+ playSong = temp2;
+}
+```
+
+When `getPreviousSong()` is `undefined`, the `playPreviousSong` function should play the first song in the playlist.
+
+```js
+let flag;
+const testArr = [];
+const temp1 = userData.currentSong;
+userData.currentSong = allSongs[0];
+const temp2 = playSong;
+playSong = id => {
+ flag = true;
+ testArr.push(id);
+}
+try {
+ playPreviousSong();
+ assert.isTrue(flag);
+ userData.currentSong = null;
+ flag = false;
+ playPreviousSong();
+ assert.isTrue(flag);
+ assert.deepEqual(testArr, [0, 0]);
+} finally {
+ userData.currentSong = temp1;
+ playSong = temp2;
+}
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = id => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing");
+ audio.play()
+}
+
+const pauseSong = () => {
+ userData.songCurrentTime = audio.currentTime;
+ playButton.classList.remove("playing");
+ audio.pause();
+}
+
+const getCurrentSongIndex = () => userData.songs.indexOf(userData.currentSong);
+
+const getNextSong = () => userData.songs[getCurrentSongIndex() + 1];
+
+const getPreviousSong = () => userData.songs[getCurrentSongIndex() - 1];
+
+const playNextSong = () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ return
+ }
+ const nextSong = getNextSong();
+ if (nextSong) {
+ playSong(nextSong.id);
+ } else {
+ userData.currentSong = null;
+ userData.songCurrentTime = 0;
+ pauseSong();
+ }
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+playButton.addEventListener("click", () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ } else {
+ playSong(userData.currentSong.id);
+ }
+});
+
+const songs = document.querySelectorAll(".playlist-song");
+
+songs.forEach((song) => {
+ const id = song.getAttribute("id").slice(5);
+ const songBtn = song.querySelector("button");
+ songBtn.addEventListener("click", () => {
+ playSong(Number(id));
+ })
+})
+
+pauseButton.addEventListener("click", pauseSong);
+
+nextButton.addEventListener("click", playNextSong);
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/675069b67b8267b36fa550b3.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/675069b67b8267b36fa550b3.md
new file mode 100644
index 0000000000..d6c824ef5f
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/675069b67b8267b36fa550b3.md
@@ -0,0 +1,738 @@
+---
+id: 675069b67b8267b36fa550b3
+title: Step 31
+challengeType: 0
+dashedName: step-31
+---
+
+# --description--
+
+Add a `"click"` event listener to the `previousButton` element, then pass in `playPreviousSong` as the second argument.
+
+# --hints--
+
+You should call the `addEventListener()` method on your `previousButton` variable.
+
+```js
+assert.match(__helpers.removeJSComments(code), /previousButton\.addEventListener\(/)
+```
+
+Your event listener should listen for a `"click"` event.
+
+```js
+assert.match(__helpers.removeJSComments(code), /previousButton\.addEventListener\(\s*('|"|`)click\1/)
+```
+
+You should pass in `playPreviousSong` as the second argument of your `addEventListener` method.
+
+```js
+assert.match(__helpers.removeJSComments(code), /previousButton\.addEventListener\(\s*('|"|`)click\1\s*,\s*playPreviousSong\s*\)/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = id => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing");
+ audio.play()
+}
+
+const pauseSong = () => {
+ userData.songCurrentTime = audio.currentTime;
+ playButton.classList.remove("playing");
+ audio.pause();
+}
+
+const getCurrentSongIndex = () => userData.songs.indexOf(userData.currentSong);
+
+const getNextSong = () => userData.songs[getCurrentSongIndex() + 1];
+
+const getPreviousSong = () => userData.songs[getCurrentSongIndex() - 1];
+
+const playPreviousSong = () => {
+ const previousSong = getPreviousSong();
+ if (previousSong) {
+ playSong(previousSong.id);
+ } else {
+ playSong(userData.songs[0].id);
+ }
+};
+
+const playNextSong = () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ return
+ }
+ const nextSong = getNextSong();
+ if (nextSong) {
+ playSong(nextSong.id);
+ } else {
+ userData.currentSong = null;
+ userData.songCurrentTime = 0;
+ pauseSong();
+ }
+}
+
+playButton.addEventListener("click", () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ } else {
+ playSong(userData.currentSong.id);
+ }
+});
+
+const songs = document.querySelectorAll(".playlist-song");
+
+songs.forEach((song) => {
+ const id = song.getAttribute("id").slice(5);
+ const songBtn = song.querySelector("button");
+ songBtn.addEventListener("click", () => {
+ playSong(Number(id));
+ })
+})
+
+pauseButton.addEventListener("click", pauseSong);
+
+nextButton.addEventListener("click", playNextSong);
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6750712ee950facad5edc203.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6750712ee950facad5edc203.md
new file mode 100644
index 0000000000..a7da8200c2
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6750712ee950facad5edc203.md
@@ -0,0 +1,727 @@
+---
+id: 6750712ee950facad5edc203
+title: Step 32
+challengeType: 0
+dashedName: step-32
+---
+
+# --description--
+
+If you play a bit with your player you'll notice a few bugs. First, when you play a song, pause it and then press either the previous button or next button, the song won't start from the beginning.
+
+To start fixing that, add second parameter named `start` to your `playSong` function. Give it the default value of `true`.
+
+# --hints--
+
+Your `playSong` function should have a second parameter named `start` with the default value of `true`.
+
+```js
+assert.match(__helpers.removeJSComments(code), /const\s+playSong\s*=\s*\(\s*id\s*,\s*start\s*\=\s*true\s*\)\s*=>\s*\{/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+--fcc-editable-region--
+const playSong = id => {
+--fcc-editable-region--
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing");
+ audio.play()
+}
+
+const pauseSong = () => {
+ userData.songCurrentTime = audio.currentTime;
+ playButton.classList.remove("playing");
+ audio.pause();
+}
+
+const getCurrentSongIndex = () => userData.songs.indexOf(userData.currentSong);
+
+const getNextSong = () => userData.songs[getCurrentSongIndex() + 1];
+
+const getPreviousSong = () => userData.songs[getCurrentSongIndex() - 1];
+
+const playPreviousSong = () => {
+ const previousSong = getPreviousSong();
+ if (previousSong) {
+ playSong(previousSong.id);
+ } else {
+ playSong(userData.songs[0].id);
+ }
+};
+
+const playNextSong = () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ return
+ }
+ const nextSong = getNextSong();
+ if (nextSong) {
+ playSong(nextSong.id);
+ } else {
+ userData.currentSong = null;
+ userData.songCurrentTime = 0;
+ pauseSong();
+ }
+}
+
+playButton.addEventListener("click", () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ } else {
+ playSong(userData.currentSong.id);
+ }
+});
+
+const songs = document.querySelectorAll(".playlist-song");
+
+songs.forEach((song) => {
+ const id = song.getAttribute("id").slice(5);
+ const songBtn = song.querySelector("button");
+ songBtn.addEventListener("click", () => {
+ playSong(Number(id));
+ })
+})
+
+pauseButton.addEventListener("click", pauseSong);
+
+nextButton.addEventListener("click", playNextSong);
+
+previousButton.addEventListener("click", playPreviousSong);
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67516a431252ed30832fa7c6.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67516a431252ed30832fa7c6.md
new file mode 100644
index 0000000000..ab14226258
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67516a431252ed30832fa7c6.md
@@ -0,0 +1,727 @@
+---
+id: 67516a431252ed30832fa7c6
+title: Step 33
+challengeType: 0
+dashedName: step-33
+---
+
+# --description--
+
+Now, use the **OR** operator to add the `start` parameter as a second condition to the `if` statement after `userData.currentSong === null`.
+
+
+# --hints--
+
+You should use the **OR** operator to add the `start` parameter as a second condition to the `if` statement after `userData.currentSong === null`.
+
+```js
+assert.match(__helpers.removeJSComments(code), /if\s+\(\s*userData\s*\.\s*currentSong\s*===\s*null\s+\|\|\s+start(\s*\=\s*true\s*)?\)\s*\{/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = (id, start=true) => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+--fcc-editable-region--
+ if (userData.currentSong === null) {
+--fcc-editable-region--
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing");
+ audio.play()
+}
+
+const pauseSong = () => {
+ userData.songCurrentTime = audio.currentTime;
+ playButton.classList.remove("playing");
+ audio.pause();
+}
+
+const getCurrentSongIndex = () => userData.songs.indexOf(userData.currentSong);
+
+const getNextSong = () => userData.songs[getCurrentSongIndex() + 1];
+
+const getPreviousSong = () => userData.songs[getCurrentSongIndex() - 1];
+
+const playPreviousSong = () => {
+ const previousSong = getPreviousSong();
+ if (previousSong) {
+ playSong(previousSong.id);
+ } else {
+ playSong(userData.songs[0].id);
+ }
+};
+
+const playNextSong = () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ return
+ }
+ const nextSong = getNextSong();
+ if (nextSong) {
+ playSong(nextSong.id);
+ } else {
+ userData.currentSong = null;
+ userData.songCurrentTime = 0;
+ pauseSong();
+ }
+}
+
+playButton.addEventListener("click", () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ } else {
+ playSong(userData.currentSong.id);
+ }
+});
+
+const songs = document.querySelectorAll(".playlist-song");
+
+songs.forEach((song) => {
+ const id = song.getAttribute("id").slice(5);
+ const songBtn = song.querySelector("button");
+ songBtn.addEventListener("click", () => {
+ playSong(Number(id));
+ })
+})
+
+pauseButton.addEventListener("click", pauseSong);
+
+nextButton.addEventListener("click", playNextSong);
+
+previousButton.addEventListener("click", playPreviousSong);
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67516ca9b7fe6636208c5ab5.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67516ca9b7fe6636208c5ab5.md
new file mode 100644
index 0000000000..11d12b14ce
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67516ca9b7fe6636208c5ab5.md
@@ -0,0 +1,726 @@
+---
+id: 67516ca9b7fe6636208c5ab5
+title: Step 34
+challengeType: 0
+dashedName: step-34
+---
+
+# --description--
+
+Finally, pass `false` as the second argument to the `playSong(userData.currentSong.id)` function call. Then, test that everything works as expected by playing a song, pausing it and then pressing either the previous button or the next button.
+
+# --hints--
+
+You should pass `false` as the second argument to the `playSong(userData.currentSong.id)` function call.
+
+```js
+assert.match(__helpers.removeJSComments(code), /playSong\s*\(\s*userData\s*\.\s*currentSong\s*\.\s*id\s*,\s*false\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = (id, start=true) => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null || start) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing");
+ audio.play()
+}
+
+const pauseSong = () => {
+ userData.songCurrentTime = audio.currentTime;
+ playButton.classList.remove("playing");
+ audio.pause();
+}
+
+const getCurrentSongIndex = () => userData.songs.indexOf(userData.currentSong);
+
+const getNextSong = () => userData.songs[getCurrentSongIndex() + 1];
+
+const getPreviousSong = () => userData.songs[getCurrentSongIndex() - 1];
+
+const playPreviousSong = () => {
+ const previousSong = getPreviousSong();
+ if (previousSong) {
+ playSong(previousSong.id);
+ } else {
+ playSong(userData.songs[0].id);
+ }
+};
+
+const playNextSong = () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ return
+ }
+ const nextSong = getNextSong();
+ if (nextSong) {
+ playSong(nextSong.id);
+ } else {
+ userData.currentSong = null;
+ userData.songCurrentTime = 0;
+ pauseSong();
+ }
+}
+
+playButton.addEventListener("click", () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ } else {
+--fcc-editable-region--
+ playSong(userData.currentSong.id);
+--fcc-editable-region--
+ }
+});
+
+const songs = document.querySelectorAll(".playlist-song");
+
+songs.forEach((song) => {
+ const id = song.getAttribute("id").slice(5);
+ const songBtn = song.querySelector("button");
+ songBtn.addEventListener("click", () => {
+ playSong(Number(id));
+ })
+})
+
+pauseButton.addEventListener("click", pauseSong);
+
+nextButton.addEventListener("click", playNextSong);
+
+previousButton.addEventListener("click", playPreviousSong);
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67516e888477083c31614dc7.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67516e888477083c31614dc7.md
new file mode 100644
index 0000000000..701d0ca5c9
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67516e888477083c31614dc7.md
@@ -0,0 +1,743 @@
+---
+id: 67516e888477083c31614dc7
+title: Step 36
+challengeType: 0
+dashedName: step-36
+---
+
+# --description--
+
+If you check closely, you'd see the currently playing song is not highlighted in the playlist, so you don't really know which song is playing. You can fix this by creating a function to highlight any song that is being played.
+
+Create a function named `highlightCurrentSong`. Inside the function, check that a `.playlist-song` element with `aria-current="true"` exists. If so, use the `removeAttribute` method to remove the `aria-current` attribute from it.
+
+# --hints--
+
+You should have a function named `highlightCurrentSong`.
+
+```js
+assert.isFunction(highlightCurrentSong)
+```
+
+Your `highlightCurrentSong` function should use the `removeAttribute` method to remove the `aria-current` attribute from the `.playlist-song` element with `aria-current="true"` if that element exists.
+
+```js
+const songs = document.querySelectorAll(".playlist-song");
+songs.forEach(song => {song.removeAttribute("aria-current")});
+assert.doesNotThrow(highlightCurrentSong);
+songs[3].setAttribute("aria-current", "true");
+highlightCurrentSong();
+songs.forEach(song => {assert.isNull(song.getAttribute("aria-current"))});
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = (id, start=true) => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null || start) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing");
+ audio.play()
+}
+
+const pauseSong = () => {
+ userData.songCurrentTime = audio.currentTime;
+ playButton.classList.remove("playing");
+ audio.pause();
+}
+
+const getCurrentSongIndex = () => userData.songs.indexOf(userData.currentSong);
+
+const getNextSong = () => userData.songs[getCurrentSongIndex() + 1];
+
+const getPreviousSong = () => userData.songs[getCurrentSongIndex() - 1];
+
+const playPreviousSong = () => {
+ if (userData.currentSong === null) return;
+ const previousSong = getPreviousSong();
+ if (previousSong) {
+ playSong(previousSong.id);
+ } else {
+ playSong(userData.songs[0].id);
+ }
+};
+
+const playNextSong = () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ return
+ }
+ const nextSong = getNextSong();
+ if (nextSong) {
+ playSong(nextSong.id);
+ } else {
+ userData.currentSong = null;
+ userData.songCurrentTime = 0;
+ pauseSong();
+ }
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+playButton.addEventListener("click", () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ } else {
+ playSong(userData.currentSong.id, false);
+ }
+});
+
+const songs = document.querySelectorAll(".playlist-song");
+
+songs.forEach((song) => {
+ const id = song.getAttribute("id").slice(5);
+ const songBtn = song.querySelector("button");
+ songBtn.addEventListener("click", () => {
+ playSong(Number(id));
+ })
+})
+
+pauseButton.addEventListener("click", pauseSong);
+
+nextButton.addEventListener("click", playNextSong);
+
+previousButton.addEventListener("click", playPreviousSong);
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67517ef2fae05b65108212db.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67517ef2fae05b65108212db.md
new file mode 100644
index 0000000000..30824527a3
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67517ef2fae05b65108212db.md
@@ -0,0 +1,754 @@
+---
+id: 67517ef2fae05b65108212db
+title: Step 37
+challengeType: 0
+dashedName: step-37
+---
+
+# --description--
+
+You need to get the `id` of the currently playing song. For this, you can use `userData.currentSong?.id`.
+
+Use `getElementById()` to select the currently playing song: pass a template literal to prefix the `id` with `song-`. Assign it to a variable named `songToHighlight`.
+
+# --hints--
+
+You should not modify the existing `highlightCurrentSong` function and its content.
+
+```js
+const songs = document.querySelectorAll(".playlist-song");
+songs.forEach(song => {song.removeAttribute("aria-current")});
+assert.doesNotThrow(highlightCurrentSong);
+songs[3].setAttribute("aria-current", "true");
+highlightCurrentSong();
+songs.forEach(song => {assert.isNull(song.getAttribute("aria-current"))});
+```
+
+You should use `document.getElementById()` and pass in `` `song-${userData.currentSong?.id}` ``.
+
+```js
+assert.match(__helpers.removeJSComments(code), /document\.getElementById\(\s*`song-\$\{userData\.currentSong\?\.id\}`\s*\)\s*;?\s*\}\s*;?/)
+```
+
+You should assign your `getElementById()` to a `songToHighlight` variable.
+
+```js
+assert.match(__helpers.removeJSComments(code), /(const|let)\s+songToHighlight\s*=\s*document\.getElementById\(\s*`song-\$\{userData\.currentSong\?\.id\}`\s*\)\s*;?\s*\}\s*;?/)
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = (id, start=true) => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null || start) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing");
+ audio.play()
+}
+
+const pauseSong = () => {
+ userData.songCurrentTime = audio.currentTime;
+ playButton.classList.remove("playing");
+ audio.pause();
+}
+
+const getCurrentSongIndex = () => userData.songs.indexOf(userData.currentSong);
+
+const getNextSong = () => userData.songs[getCurrentSongIndex() + 1];
+
+const getPreviousSong = () => userData.songs[getCurrentSongIndex() - 1];
+
+const playPreviousSong = () => {
+ if (userData.currentSong === null) return;
+ const previousSong = getPreviousSong();
+ if (previousSong) {
+ playSong(previousSong.id);
+ } else {
+ playSong(userData.songs[0].id);
+ }
+};
+
+const playNextSong = () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ return
+ }
+ const nextSong = getNextSong();
+ if (nextSong) {
+ playSong(nextSong.id);
+ } else {
+ userData.currentSong = null;
+ userData.songCurrentTime = 0;
+ pauseSong();
+ }
+}
+
+
+const highlightCurrentSong = () => {
+ const previousCurrentSong = document.querySelector('.playlist-song[aria-current="true"]');
+ previousCurrentSong?.removeAttribute("aria-current");
+--fcc-editable-region--
+
+--fcc-editable-region--
+};
+
+playButton.addEventListener("click", () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ } else {
+ playSong(userData.currentSong.id, false);
+ }
+});
+
+const songs = document.querySelectorAll(".playlist-song");
+
+songs.forEach((song) => {
+ const id = song.getAttribute("id").slice(5);
+ const songBtn = song.querySelector("button");
+ songBtn.addEventListener("click", () => {
+ playSong(Number(id));
+ })
+})
+
+pauseButton.addEventListener("click", pauseSong);
+
+nextButton.addEventListener("click", playNextSong);
+
+previousButton.addEventListener("click", playPreviousSong);
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6751d5d32e58d065652e26a5.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6751d5d32e58d065652e26a5.md
new file mode 100644
index 0000000000..64a2fda8d9
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6751d5d32e58d065652e26a5.md
@@ -0,0 +1,747 @@
+---
+id: 6751d5d32e58d065652e26a5
+title: Step 38
+challengeType: 0
+dashedName: step-38
+---
+
+# --description--
+
+Now, you need to add the `aria-current` attribute to the currently playing song.
+
+Check if `songToHighlight` exists. If so, use the `setAttribute` method on `songToHighlight` and pass in `"aria-current"` and `"true"` as the first and second arguments.
+
+# --hints--
+
+`highlightCurrentSong` should add the `aria-current` attribute to the currently playing song and remove the attribute from the previously played song.
+
+```js
+const songs = document.querySelectorAll(".playlist-song");
+songs.forEach(song => {song.removeAttribute("aria-current")});
+userData.currentSong = null;
+assert.doesNotThrow(highlightCurrentSong);
+userData.currentSong = allSongs[9];
+highlightCurrentSong();
+for (let i = 0; i < 9; i++) {
+ assert.isNull(Array.from(songs)[i].getAttribute("aria-current"));
+}
+assert.strictEqual(songs[9].getAttribute("aria-current"), "true");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = (id, start=true) => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null || start) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing");
+ audio.play()
+}
+
+const pauseSong = () => {
+ userData.songCurrentTime = audio.currentTime;
+ playButton.classList.remove("playing");
+ audio.pause();
+}
+
+const getCurrentSongIndex = () => userData.songs.indexOf(userData.currentSong);
+
+const getNextSong = () => userData.songs[getCurrentSongIndex() + 1];
+
+const getPreviousSong = () => userData.songs[getCurrentSongIndex() - 1];
+
+const playPreviousSong = () => {
+ if (userData.currentSong === null) return;
+ const previousSong = getPreviousSong();
+ if (previousSong) {
+ playSong(previousSong.id);
+ } else {
+ playSong(userData.songs[0].id);
+ }
+};
+
+const playNextSong = () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ return
+ }
+ const nextSong = getNextSong();
+ if (nextSong) {
+ playSong(nextSong.id);
+ } else {
+ userData.currentSong = null;
+ userData.songCurrentTime = 0;
+ pauseSong();
+ }
+}
+
+const highlightCurrentSong = () => {
+ const previousCurrentSong = document.querySelector('.playlist-song[aria-current="true"]');
+ previousCurrentSong?.removeAttribute("aria-current");
+--fcc-editable-region--
+ const songToHighlight = document.getElementById(
+ `song-${userData.currentSong?.id}`
+ );
+
+--fcc-editable-region--
+};
+
+playButton.addEventListener("click", () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ } else {
+ playSong(userData.currentSong.id, false);
+ }
+});
+
+const songs = document.querySelectorAll(".playlist-song");
+
+songs.forEach((song) => {
+ const id = song.getAttribute("id").slice(5);
+ const songBtn = song.querySelector("button");
+ songBtn.addEventListener("click", () => {
+ playSong(Number(id));
+ })
+})
+
+pauseButton.addEventListener("click", pauseSong);
+
+nextButton.addEventListener("click", playNextSong);
+
+previousButton.addEventListener("click", playPreviousSong);
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6751e1c117350b7d3f356e1b.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6751e1c117350b7d3f356e1b.md
new file mode 100644
index 0000000000..72d1b2f02f
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6751e1c117350b7d3f356e1b.md
@@ -0,0 +1,749 @@
+---
+id: 6751e1c117350b7d3f356e1b
+title: Step 39
+challengeType: 0
+dashedName: step-39
+---
+
+# --description--
+
+Inside the `playSong` function, call the `highlightCurrentSong` function.
+
+After that, play around with the control buttons to see how the `highlightCurrentSong` function works.
+
+# --hints--
+
+You should call `highlightCurrentSong` inside the `playSong` function.
+
+```js
+const songs = document.querySelectorAll(".playlist-song");
+songs.forEach(song => {song.removeAttribute("aria-current")});
+userData.currentSong = allSongs[9];
+playSong(9);
+pauseSong();
+for (let i = 0; i < 9; i++) {
+ assert.isNull(Array.from(songs)[i].getAttribute("aria-current"));
+}
+assert.strictEqual(songs[9].getAttribute("aria-current"), "true");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = (id, start=true) => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null || start) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing");
+--fcc-editable-region--
+
+--fcc-editable-region--
+ audio.play()
+}
+
+const pauseSong = () => {
+ userData.songCurrentTime = audio.currentTime;
+ playButton.classList.remove("playing");
+ audio.pause();
+}
+
+const getCurrentSongIndex = () => userData.songs.indexOf(userData.currentSong);
+
+const getNextSong = () => userData.songs[getCurrentSongIndex() + 1];
+
+const getPreviousSong = () => userData.songs[getCurrentSongIndex() - 1];
+
+const playPreviousSong = () => {
+ if (userData.currentSong === null) return;
+ const previousSong = getPreviousSong();
+ if (previousSong) {
+ playSong(previousSong.id);
+ } else {
+ playSong(userData.songs[0].id);
+ }
+};
+
+const playNextSong = () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ return
+ }
+ const nextSong = getNextSong();
+ if (nextSong) {
+ playSong(nextSong.id);
+ } else {
+ userData.currentSong = null;
+ userData.songCurrentTime = 0;
+ pauseSong();
+ }
+}
+
+const highlightCurrentSong = () => {
+ const previousCurrentSong = document.querySelector('.playlist-song[aria-current="true"]');
+ previousCurrentSong?.removeAttribute("aria-current");
+ const songToHighlight = document.getElementById(
+ `song-${userData.currentSong?.id}`
+ );
+
+
+ songToHighlight?.setAttribute("aria-current", "true");
+};
+
+playButton.addEventListener("click", () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ } else {
+ playSong(userData.currentSong.id, false);
+ }
+});
+
+const songs = document.querySelectorAll(".playlist-song");
+
+songs.forEach((song) => {
+ const id = song.getAttribute("id").slice(5);
+ const songBtn = song.querySelector("button");
+ songBtn.addEventListener("click", () => {
+ playSong(Number(id));
+ })
+})
+
+pauseButton.addEventListener("click", pauseSong);
+
+nextButton.addEventListener("click", playNextSong);
+
+previousButton.addEventListener("click", playPreviousSong);
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6752c62efa90554c01415e7b.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6752c62efa90554c01415e7b.md
new file mode 100644
index 0000000000..b5f61b7194
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6752c62efa90554c01415e7b.md
@@ -0,0 +1,768 @@
+---
+id: 6752c62efa90554c01415e7b
+title: Step 41
+challengeType: 0
+dashedName: step-41
+---
+
+# --description--
+
+Create a function named `setPlayerDisplay`. Inside the function, set the `textContent` of `playingSong` to the current song's title, if defined. Otherwise, set it to an empty string.
+
+Below that, set the `textContent` of `songArtist` to the current song's artist, if defined. Otherwise, set it to empty string.
+
+
+# --hints--
+
+You should have a function named `setPlayerDisplay`.
+
+```js
+assert.isFunction(setPlayerDisplay);
+```
+
+Your `setPlayerDisplay` function should set the `textContent` of `playingSong` to the current song's title, if defined, or to an empty string.
+
+```js
+userData.currentSong = null;
+setPlayerDisplay();
+assert.isEmpty(document.querySelector("#player-song-title").textContent);
+userData.currentSong = allSongs[3];
+setPlayerDisplay();
+assert.equal(document.querySelector("#player-song-title").textContent, "Cruising for a Musing");
+```
+
+Your `setPlayerDisplay` function should set the `textContent` of `songArtist` to the current song's artist, if defined, or to an empty string.
+
+```js
+userData.currentSong = null;
+setPlayerDisplay();
+assert.isEmpty(document.querySelector("#player-song-artist").textContent);
+userData.currentSong = allSongs[3];
+setPlayerDisplay();
+assert.equal(document.querySelector("#player-song-artist").textContent, "Quincy Larson");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const playingSong = document.getElementById("player-song-title");
+const songArtist = document.getElementById("player-song-artist");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = (id, start=true) => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null || start) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing");
+
+ highlightCurrentSong();
+ audio.play();
+}
+
+const pauseSong = () => {
+ userData.songCurrentTime = audio.currentTime;
+ playButton.classList.remove("playing");
+ audio.pause();
+}
+
+const getCurrentSongIndex = () => userData.songs.indexOf(userData.currentSong);
+
+const getNextSong = () => userData.songs[getCurrentSongIndex() + 1];
+
+const getPreviousSong = () => userData.songs[getCurrentSongIndex() - 1];
+
+const playPreviousSong = () => {
+ if (userData.currentSong === null) return;
+ const previousSong = getPreviousSong();
+ if (previousSong) {
+ playSong(previousSong.id);
+ } else {
+ playSong(userData.songs[0].id);
+ }
+};
+
+const playNextSong = () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ return
+ }
+ const nextSong = getNextSong();
+ if (nextSong) {
+ playSong(nextSong.id);
+ } else {
+ userData.currentSong = null;
+ userData.songCurrentTime = 0;
+ pauseSong();
+ }
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+const highlightCurrentSong = () => {
+ const previousCurrentSong = document.querySelector('.playlist-song[aria-current="true"]');
+ previousCurrentSong?.removeAttribute("aria-current");
+ const songToHighlight = document.getElementById(
+ `song-${userData.currentSong?.id}`
+ );
+
+ songToHighlight?.setAttribute("aria-current", "true");
+};
+
+playButton.addEventListener("click", () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ } else {
+ playSong(userData.currentSong.id, false);
+ }
+});
+
+const songs = document.querySelectorAll(".playlist-song");
+
+songs.forEach((song) => {
+ const id = song.getAttribute("id").slice(5);
+ const songBtn = song.querySelector("button");
+ songBtn.addEventListener("click", () => {
+ playSong(Number(id));
+ })
+})
+
+pauseButton.addEventListener("click", pauseSong);
+
+nextButton.addEventListener("click", playNextSong);
+
+previousButton.addEventListener("click", playPreviousSong);
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6752ecd811c96d5dc33ae853.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6752ecd811c96d5dc33ae853.md
new file mode 100644
index 0000000000..05a1c97013
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6752ecd811c96d5dc33ae853.md
@@ -0,0 +1,760 @@
+---
+id: 6752ecd811c96d5dc33ae853
+title: Step 42
+challengeType: 0
+dashedName: step-42
+---
+
+# --description--
+
+To ensure the player's display updates whenever a new song begins playing, call the `setPlayerDisplay()` function within the `playSong()` function.
+
+Now you should see the song title and the artist show up in the display.
+
+# --hints--
+
+You should call `setPlayerDisplay` within your `playSong` function.
+
+```js
+let flag;
+const temp = setPlayerDisplay;
+setPlayerDisplay = () => {flag = true}
+try {
+ playSong(3);
+ pauseSong();
+ assert.isTrue(flag);
+} finally {
+ setPlayerDisplay = temp;
+}
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const playingSong = document.getElementById("player-song-title");
+const songArtist = document.getElementById("player-song-artist");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = (id, start=true) => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null || start) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing");
+--fcc-editable-region--
+
+--fcc-editable-region--
+ highlightCurrentSong();
+ audio.play();
+}
+
+const pauseSong = () => {
+ userData.songCurrentTime = audio.currentTime;
+ playButton.classList.remove("playing");
+ audio.pause();
+}
+
+const getCurrentSongIndex = () => userData.songs.indexOf(userData.currentSong);
+
+const getNextSong = () => userData.songs[getCurrentSongIndex() + 1];
+
+const getPreviousSong = () => userData.songs[getCurrentSongIndex() - 1];
+
+const playPreviousSong = () => {
+ if (userData.currentSong === null) return;
+ const previousSong = getPreviousSong();
+ if (previousSong) {
+ playSong(previousSong.id);
+ } else {
+ playSong(userData.songs[0].id);
+ }
+};
+
+const playNextSong = () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ return
+ }
+ const nextSong = getNextSong();
+ if (nextSong) {
+ playSong(nextSong.id);
+ } else {
+ userData.currentSong = null;
+ userData.songCurrentTime = 0;
+ pauseSong();
+ }
+}
+
+const setPlayerDisplay = () => {
+ const currentTitle = userData.currentSong?.title;
+ const currentArtist = userData.currentSong?.artist;
+
+ playingSong.textContent = currentTitle ? currentTitle : "";
+ songArtist.textContent = currentArtist ? currentArtist : "";
+};
+
+const highlightCurrentSong = () => {
+ const previousCurrentSong = document.querySelector('.playlist-song[aria-current="true"]');
+ previousCurrentSong?.removeAttribute("aria-current");
+ const songToHighlight = document.getElementById(
+ `song-${userData.currentSong?.id}`
+ );
+
+ songToHighlight?.setAttribute("aria-current", "true");
+};
+
+playButton.addEventListener("click", () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ } else {
+ playSong(userData.currentSong.id, false);
+ }
+});
+
+const songs = document.querySelectorAll(".playlist-song");
+
+songs.forEach((song) => {
+ const id = song.getAttribute("id").slice(5);
+ const songBtn = song.querySelector("button");
+ songBtn.addEventListener("click", () => {
+ playSong(Number(id));
+ })
+})
+
+pauseButton.addEventListener("click", pauseSong);
+
+nextButton.addEventListener("click", playNextSong);
+
+previousButton.addEventListener("click", playPreviousSong);
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6752edba757ff96404faf9e9.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6752edba757ff96404faf9e9.md
new file mode 100644
index 0000000000..3feaeff1a8
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6752edba757ff96404faf9e9.md
@@ -0,0 +1,769 @@
+---
+id: 6752edba757ff96404faf9e9
+title: Step 43
+challengeType: 0
+dashedName: step-43
+---
+
+# --description--
+
+To make the application more accessible, it is important that the play button describes the current song or the first song in the playlist.
+
+Create a function named `setPlayButtonAccessibleText`. Inside the function, set the `aria-label` attribute of the play button to `Play` followed by a space and the current song's title. If `userData.currentSong` is `null`, set it to `Play`.
+
+# --hints--
+
+You should have a function named `setPlayButtonAccessibleText`.
+
+```js
+assert.isFunction(setPlayButtonAccessibleText);
+```
+
+Your `setPlayButtonAccessibleText` function should set the `aria-label` attribute of the play button to `Play` followed by a space and the current song's title.
+
+```js
+userData.currentSong = allSongs[3];
+setPlayButtonAccessibleText();
+assert.equal(playButton.getAttribute("aria-label"), "Play Cruising for a Musing");
+```
+
+ When `userData.currentSong` is `null`, `setPlayButtonAccessibleText` should set the `aria-label` attribute of the play button to `Play` followed by a space and title of the first song in your playlist.
+
+ ```js
+userData.currentSong = null;
+setPlayButtonAccessibleText();
+assert.equal(playButton.getAttribute("aria-label"), "Play");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const playingSong = document.getElementById("player-song-title");
+const songArtist = document.getElementById("player-song-artist");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = (id, start=true) => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null || start) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing");
+ setPlayerDisplay();
+ highlightCurrentSong();
+ audio.play();
+}
+
+const pauseSong = () => {
+ userData.songCurrentTime = audio.currentTime;
+ playButton.classList.remove("playing");
+ audio.pause();
+}
+
+const getCurrentSongIndex = () => userData.songs.indexOf(userData.currentSong);
+
+const getNextSong = () => userData.songs[getCurrentSongIndex() + 1];
+
+const getPreviousSong = () => userData.songs[getCurrentSongIndex() - 1];
+
+const playPreviousSong = () => {
+ if (userData.currentSong === null) return;
+ const previousSong = getPreviousSong();
+ if (previousSong) {
+ playSong(previousSong.id);
+ } else {
+ playSong(userData.songs[0].id);
+ }
+};
+
+const playNextSong = () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ return
+ }
+ const nextSong = getNextSong();
+ if (nextSong) {
+ playSong(nextSong.id);
+ } else {
+ userData.currentSong = null;
+ userData.songCurrentTime = 0;
+ pauseSong();
+ }
+}
+
+const setPlayerDisplay = () => {
+ const currentTitle = userData.currentSong?.title;
+ const currentArtist = userData.currentSong?.artist;
+
+ playingSong.textContent = currentTitle ? currentTitle : "";
+ songArtist.textContent = currentArtist ? currentArtist : "";
+};
+
+const highlightCurrentSong = () => {
+ const previousCurrentSong = document.querySelector('.playlist-song[aria-current="true"]');
+ previousCurrentSong?.removeAttribute("aria-current");
+ const songToHighlight = document.getElementById(
+ `song-${userData.currentSong?.id}`
+ );
+
+ songToHighlight?.setAttribute("aria-current", "true");
+};
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+playButton.addEventListener("click", () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ } else {
+ playSong(userData.currentSong.id, false);
+ }
+});
+
+const songs = document.querySelectorAll(".playlist-song");
+
+songs.forEach((song) => {
+ const id = song.getAttribute("id").slice(5);
+ const songBtn = song.querySelector("button");
+ songBtn.addEventListener("click", () => {
+ playSong(Number(id));
+ })
+})
+
+pauseButton.addEventListener("click", pauseSong);
+
+nextButton.addEventListener("click", playNextSong);
+
+previousButton.addEventListener("click", playPreviousSong);
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/675304e7937e62902e08a3ab.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/675304e7937e62902e08a3ab.md
new file mode 100644
index 0000000000..3605b56ff4
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/675304e7937e62902e08a3ab.md
@@ -0,0 +1,764 @@
+---
+id: 675304e7937e62902e08a3ab
+title: Step 44
+challengeType: 0
+dashedName: step-44
+---
+
+# --description--
+
+Now, call the `setPlayButtonAccessibleText` function inside the `playSong` function.
+
+# --hints--
+
+You should call the `setPlayButtonAccessibleText` function inside the `playSong` function.
+
+```js
+let flag;
+const temp = setPlayButtonAccessibleText;
+setPlayButtonAccessibleText = () => {flag = true}
+try {
+ playSong(3);
+ pauseSong();
+ assert.isTrue(flag);
+} finally {
+ setPlayButtonAccessibleText = temp;
+}
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const playingSong = document.getElementById("player-song-title");
+const songArtist = document.getElementById("player-song-artist");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = (id, start=true) => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null || start) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing");
+ setPlayerDisplay();
+ highlightCurrentSong();
+--fcc-editable-region--
+
+--fcc-editable-region--
+ audio.play();
+}
+
+const pauseSong = () => {
+ userData.songCurrentTime = audio.currentTime;
+ playButton.classList.remove("playing");
+ audio.pause();
+}
+
+const getCurrentSongIndex = () => userData.songs.indexOf(userData.currentSong);
+
+const getNextSong = () => userData.songs[getCurrentSongIndex() + 1];
+
+const getPreviousSong = () => userData.songs[getCurrentSongIndex() - 1];
+
+const playPreviousSong = () => {
+ if (userData.currentSong === null) return;
+ const previousSong = getPreviousSong();
+ if (previousSong) {
+ playSong(previousSong.id);
+ } else {
+ playSong(userData.songs[0].id);
+ }
+};
+
+const playNextSong = () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ return
+ }
+ const nextSong = getNextSong();
+ if (nextSong) {
+ playSong(nextSong.id);
+ } else {
+ userData.currentSong = null;
+ userData.songCurrentTime = 0;
+ pauseSong();
+ }
+}
+
+const setPlayerDisplay = () => {
+ const currentTitle = userData.currentSong?.title;
+ const currentArtist = userData.currentSong?.artist;
+
+ playingSong.textContent = currentTitle ? currentTitle : "";
+ songArtist.textContent = currentArtist ? currentArtist : "";
+};
+
+const highlightCurrentSong = () => {
+ const previousCurrentSong = document.querySelector('.playlist-song[aria-current="true"]');
+ previousCurrentSong?.removeAttribute("aria-current");
+ const songToHighlight = document.getElementById(
+ `song-${userData.currentSong?.id}`
+ );
+
+ songToHighlight?.setAttribute("aria-current", "true");
+};
+
+const setPlayButtonAccessibleText = () => {
+ const song = userData.currentSong;
+ playButton.setAttribute("aria-label", userData.currentSong ? `Play ${song.title}` : "Play");
+};
+
+playButton.addEventListener("click", () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ } else {
+ playSong(userData.currentSong.id, false);
+ }
+});
+
+const songs = document.querySelectorAll(".playlist-song");
+
+songs.forEach((song) => {
+ const id = song.getAttribute("id").slice(5);
+ const songBtn = song.querySelector("button");
+ songBtn.addEventListener("click", () => {
+ playSong(Number(id));
+ })
+})
+
+pauseButton.addEventListener("click", pauseSong);
+
+nextButton.addEventListener("click", playNextSong);
+
+previousButton.addEventListener("click", playPreviousSong);
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/675309b2795c2a9ae03b8812.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/675309b2795c2a9ae03b8812.md
new file mode 100644
index 0000000000..323329e819
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/675309b2795c2a9ae03b8812.md
@@ -0,0 +1,1442 @@
+---
+id: 675309b2795c2a9ae03b8812
+title: Step 46
+challengeType: 0
+dashedName: step-46
+---
+
+# --description--
+
+Notice that the album art in the HTML and songs in the `userData.songs` array have changed. We've swapped out the original songs for shorter ones that you can use to test your app.
+
+All the core functionalities are now in place. The only issue now is that the next song does not automatically play when the currently playing song ends.
+
+To fix that, you can set up an event listener which will detect when the currently playing song ends. The `"ended"` event listener is appropriate for this. It is fired when the playback of a media reaches the end.
+
+Add an event listener to the `audio` element which listens for the `"ended"` event and pass in a a reference to the `playNextSong` function. With that the music player project is complete!
+
+# --hints--
+
+You should chain the `addEventListener()` method to your `audio` variable.
+
+```js
+assert.match(__helpers.removeJSComments(code), /audio\.addEventListener\(/)
+```
+
+The event listener you used on on your `audio` variable should listen for an `"ended"` event.
+
+```js
+assert.match(__helpers.removeJSComments(code), /audio\.addEventListener\(\s*('|")ended\1/)
+```
+
+You should pass in a reference to `playNextSong` to your `"ended"` event listener.
+
+```js
+assert.match(__helpers.removeJSComments(code), /audio\.addEventListener\(\s*('|")ended\1\s*,\s*playNextSong\s*\)\s*;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Hello World
+ Rafael
+ 0:23
+
+
+
+
+
+ In the Zone
+ Rafael
+ 0:11
+
+
+
+
+
+ Camper Cat
+ Rafael
+ 0:21
+
+
+
+
+
+ Electronic
+ Rafael
+ 0:15
+
+
+
+
+
+ Sailing Away
+ Rafael
+ 0:22
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const playingSong = document.getElementById("player-song-title");
+const songArtist = document.getElementById("player-song-artist");
+const allSongs = [
+ {
+ id: 0,
+ title: "Hello World",
+ artist: "Rafael",
+ duration: "0:23",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/hello-world.mp3",
+ },
+ {
+ id: 1,
+ title: "In the Zone",
+ artist: "Rafael",
+ duration: "0:11",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/in-the-zone.mp3",
+ },
+ {
+ id: 2,
+ title: "Camper Cat",
+ artist: "Rafael",
+ duration: "0:21",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/camper-cat.mp3",
+ },
+ {
+ id: 3,
+ title: "Electronic",
+ artist: "Rafael",
+ duration: "0:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/electronic.mp3",
+ },
+ {
+ id: 4,
+ title: "Sailing Away",
+ artist: "Rafael",
+ duration: "0:22",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/sailing-away.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = (id, start=true) => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null || start) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing");
+ setPlayerDisplay();
+ highlightCurrentSong();
+ setPlayButtonAccessibleText();
+ audio.play();
+}
+
+const pauseSong = () => {
+ userData.songCurrentTime = audio.currentTime;
+ playButton.classList.remove("playing");
+ audio.pause();
+}
+
+const getCurrentSongIndex = () => userData.songs.indexOf(userData.currentSong);
+
+const getNextSong = () => userData.songs[getCurrentSongIndex() + 1];
+
+const getPreviousSong = () => userData.songs[getCurrentSongIndex() - 1];
+
+const playPreviousSong = () => {
+ if (userData.currentSong === null) return;
+ const previousSong = getPreviousSong();
+ if (previousSong) {
+ playSong(previousSong.id);
+ } else {
+ playSong(userData.songs[0].id);
+ }
+};
+
+const playNextSong = () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ return
+ }
+ const nextSong = getNextSong();
+ if (nextSong) {
+ playSong(nextSong.id);
+ } else {
+ userData.currentSong = null;
+ userData.songCurrentTime = 0;
+ setPlayerDisplay();
+ highlightCurrentSong();
+ setPlayButtonAccessibleText();
+ pauseSong();
+ }
+}
+
+const setPlayerDisplay = () => {
+ const currentTitle = userData.currentSong?.title;
+ const currentArtist = userData.currentSong?.artist;
+
+ playingSong.textContent = currentTitle ? currentTitle : "";
+ songArtist.textContent = currentArtist ? currentArtist : "";
+};
+
+const highlightCurrentSong = () => {
+ const previousCurrentSong = document.querySelector('.playlist-song[aria-current="true"]');
+ previousCurrentSong?.removeAttribute("aria-current");
+ const songToHighlight = document.getElementById(
+ `song-${userData.currentSong?.id}`
+ );
+
+ songToHighlight?.setAttribute("aria-current", "true");
+};
+
+const setPlayButtonAccessibleText = () => {
+ const song = userData.currentSong;
+ playButton.setAttribute("aria-label", userData.currentSong ? `Play ${song.title}` : "Play");
+};
+
+playButton.addEventListener("click", () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ } else {
+ playSong(userData.currentSong.id, false);
+ }
+});
+
+const songs = document.querySelectorAll(".playlist-song");
+
+songs.forEach((song) => {
+ const id = song.getAttribute("id").slice(5);
+ const songBtn = song.querySelector("button");
+ songBtn.addEventListener("click", () => {
+ playSong(Number(id));
+ })
+})
+
+pauseButton.addEventListener("click", pauseSong);
+
+nextButton.addEventListener("click", playNextSong);
+
+previousButton.addEventListener("click", playPreviousSong);
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
+
+# --solutions--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const playingSong = document.getElementById("player-song-title");
+const songArtist = document.getElementById("player-song-artist");
+
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ }
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = (id, start=true) => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null || start) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing");
+ setPlayerDisplay();
+ highlightCurrentSong();
+ setPlayButtonAccessibleText();
+ audio.play();
+}
+
+const pauseSong = () => {
+ userData.songCurrentTime = audio.currentTime;
+ playButton.classList.remove("playing");
+ audio.pause();
+}
+
+const getCurrentSongIndex = () => userData.songs.indexOf(userData.currentSong);
+
+const getNextSong = () => userData.songs[getCurrentSongIndex() + 1];
+
+const getPreviousSong = () => userData.songs[getCurrentSongIndex() - 1];
+
+const playPreviousSong = () => {
+ if (userData.currentSong === null) return;
+ const previousSong = getPreviousSong();
+ if (previousSong) {
+ playSong(previousSong.id);
+ } else {
+ playSong(userData.songs[0].id);
+ }
+};
+
+const playNextSong = () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ return
+ }
+ const nextSong = getNextSong();
+ if (nextSong) {
+ playSong(nextSong.id);
+ } else {
+ userData.currentSong = null;
+ userData.songCurrentTime = 0;
+ setPlayerDisplay();
+ highlightCurrentSong();
+ setPlayButtonAccessibleText();
+ pauseSong();
+ }
+}
+
+const setPlayerDisplay = () => {
+ const currentTitle = userData.currentSong?.title;
+ const currentArtist = userData.currentSong?.artist;
+
+ playingSong.textContent = currentTitle ? currentTitle : "";
+ songArtist.textContent = currentArtist ? currentArtist : "";
+};
+
+const highlightCurrentSong = () => {
+ const previousCurrentSong = document.querySelector('.playlist-song[aria-current="true"]');
+ previousCurrentSong?.removeAttribute("aria-current");
+ const songToHighlight = document.getElementById(
+ `song-${userData.currentSong?.id}`
+ );
+
+ songToHighlight?.setAttribute("aria-current", "true");
+};
+
+const setPlayButtonAccessibleText = () => {
+ const song = userData.currentSong;
+ playButton.setAttribute("aria-label", userData.currentSong ? `Play ${song.title}` : "Play");
+};
+
+playButton.addEventListener("click", () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ } else {
+ playSong(userData.currentSong.id, false);
+ }
+});
+
+const songs = document.querySelectorAll(".playlist-song");
+
+songs.forEach((song) => {
+ const id = song.getAttribute("id").slice(5);
+ const songBtn = song.querySelector("button");
+ songBtn.addEventListener("click", () => {
+ playSong(Number(id));
+ })
+})
+
+pauseButton.addEventListener("click", pauseSong);
+
+nextButton.addEventListener("click", playNextSong);
+
+previousButton.addEventListener("click", playPreviousSong);
+
+audio.addEventListener("ended", playNextSong);
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67532282ab9b95d7083617ee.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67532282ab9b95d7083617ee.md
new file mode 100644
index 0000000000..9632fefd63
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67532282ab9b95d7083617ee.md
@@ -0,0 +1,795 @@
+---
+id: 67532282ab9b95d7083617ee
+title: Step 45
+challengeType: 0
+dashedName: step-45
+---
+
+# --description--
+
+Inside the `playNextSong` function, call the `setPlayerDisplay`, `highlightCurrentSong`, and `setPlayButtonAccessibleText` functions to correctly update the player when the playlist ends.
+
+# --hints--
+
+You should call `setPlayerDisplay` within the `else` statement of your `playNextSong` function.
+
+```js
+let flag;
+userData.currentSong = allSongs[9];
+const temp = setPlayerDisplay;
+setPlayerDisplay = () => {flag = true}
+try {
+ playNextSong();
+ assert.isTrue(flag);
+} finally {
+ setPlayerDisplay = temp;
+}
+```
+
+You should call `highlightCurrentSong` within the `else` statement of your `playNextSong` function.
+
+```js
+let flag;
+userData.currentSong = allSongs[9];
+const temp = highlightCurrentSong;
+highlightCurrentSong = () => {flag = true}
+try {
+ playNextSong();
+ assert.isTrue(flag);
+} finally {
+ highlightCurrentSong = temp;
+}
+```
+
+You should call `setPlayButtonAccessibleText` within the `else` statement of your `playNextSong` function.
+
+```js
+let flag;
+userData.currentSong = allSongs[9];
+const temp = setPlayButtonAccessibleText;
+setPlayButtonAccessibleText = () => {flag = true}
+try {
+ playNextSong();
+ assert.isTrue(flag);
+} finally {
+ setPlayButtonAccessibleText = temp;
+}
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const playingSong = document.getElementById("player-song-title");
+const songArtist = document.getElementById("player-song-artist");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = (id, start=true) => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null || start) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing");
+ setPlayerDisplay();
+ highlightCurrentSong();
+ setPlayButtonAccessibleText();
+ audio.play();
+}
+
+const pauseSong = () => {
+ userData.songCurrentTime = audio.currentTime;
+ playButton.classList.remove("playing");
+ audio.pause();
+}
+
+const getCurrentSongIndex = () => userData.songs.indexOf(userData.currentSong);
+
+const getNextSong = () => userData.songs[getCurrentSongIndex() + 1];
+
+const getPreviousSong = () => userData.songs[getCurrentSongIndex() - 1];
+
+const playPreviousSong = () => {
+ if (userData.currentSong === null) return;
+ const previousSong = getPreviousSong();
+ if (previousSong) {
+ playSong(previousSong.id);
+ } else {
+ playSong(userData.songs[0].id);
+ }
+};
+
+const playNextSong = () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ return
+ }
+ const nextSong = getNextSong();
+ if (nextSong) {
+ playSong(nextSong.id);
+ } else {
+ userData.currentSong = null;
+ userData.songCurrentTime = 0;
+--fcc-editable-region--
+
+--fcc-editable-region--
+ pauseSong();
+ }
+}
+
+const setPlayerDisplay = () => {
+ const currentTitle = userData.currentSong?.title;
+ const currentArtist = userData.currentSong?.artist;
+
+ playingSong.textContent = currentTitle ? currentTitle : "";
+ songArtist.textContent = currentArtist ? currentArtist : "";
+};
+
+const highlightCurrentSong = () => {
+ const previousCurrentSong = document.querySelector('.playlist-song[aria-current="true"]');
+ previousCurrentSong?.removeAttribute("aria-current");
+ const songToHighlight = document.getElementById(
+ `song-${userData.currentSong?.id}`
+ );
+
+ songToHighlight?.setAttribute("aria-current", "true");
+};
+
+const setPlayButtonAccessibleText = () => {
+ const song = userData.currentSong;
+ playButton.setAttribute("aria-label", userData.currentSong ? `Play ${song.title}` : "Play");
+};
+
+playButton.addEventListener("click", () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ } else {
+ playSong(userData.currentSong.id, false);
+ }
+});
+
+const songs = document.querySelectorAll(".playlist-song");
+
+songs.forEach((song) => {
+ const id = song.getAttribute("id").slice(5);
+ const songBtn = song.querySelector("button");
+ songBtn.addEventListener("click", () => {
+ playSong(Number(id));
+ })
+})
+
+pauseButton.addEventListener("click", pauseSong);
+
+nextButton.addEventListener("click", playNextSong);
+
+previousButton.addEventListener("click", playPreviousSong);
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/675340b809683f45cae96539.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/675340b809683f45cae96539.md
new file mode 100644
index 0000000000..e9772447ea
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/675340b809683f45cae96539.md
@@ -0,0 +1,736 @@
+---
+id: 675340b809683f45cae96539
+title: Step 35
+challengeType: 0
+dashedName: step-35
+---
+
+# --description--
+
+If you press the previous button when no song is playing, the first song will play. To fix this, add an `if` statement at the beginning of the `playPreviousSong` function. Check if the current song is `null` and stop the function execution with a `return` statement.
+
+# --hints--
+
+You should add an `if` statement that checks if `userData.currentSong === null` and stops the function execution with a `return` statement inside your `playPreviousSong` function.
+
+```js
+let flag;
+userData.currentSong = null;
+const temp = playSong;
+playSong = id => {flag = true};
+try {
+ playPreviousSong();
+ assert.isUndefined(flag);
+} finally {
+ playSong = temp;
+}
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = (id, start=true) => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null || start) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing");
+ audio.play()
+}
+
+const pauseSong = () => {
+ userData.songCurrentTime = audio.currentTime;
+ playButton.classList.remove("playing");
+ audio.pause();
+}
+
+const getCurrentSongIndex = () => userData.songs.indexOf(userData.currentSong);
+
+const getNextSong = () => userData.songs[getCurrentSongIndex() + 1];
+
+const getPreviousSong = () => userData.songs[getCurrentSongIndex() - 1];
+
+const playPreviousSong = () => {
+--fcc-editable-region--
+
+--fcc-editable-region--
+ const previousSong = getPreviousSong();
+ if (previousSong) {
+ playSong(previousSong.id);
+ } else {
+ playSong(userData.songs[0].id);
+ }
+};
+
+const playNextSong = () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ return
+ }
+ const nextSong = getNextSong();
+ if (nextSong) {
+ playSong(nextSong.id);
+ } else {
+ userData.currentSong = null;
+ userData.songCurrentTime = 0;
+ pauseSong();
+ }
+}
+
+playButton.addEventListener("click", () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ } else {
+ playSong(userData.currentSong.id, false);
+ }
+});
+
+const songs = document.querySelectorAll(".playlist-song");
+
+songs.forEach((song) => {
+ const id = song.getAttribute("id").slice(5);
+ const songBtn = song.querySelector("button");
+ songBtn.addEventListener("click", () => {
+ playSong(Number(id));
+ })
+})
+
+pauseButton.addEventListener("click", pauseSong);
+
+nextButton.addEventListener("click", playNextSong);
+
+previousButton.addEventListener("click", playPreviousSong);
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6757f2b25418da4f73e29eb6.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6757f2b25418da4f73e29eb6.md
new file mode 100644
index 0000000000..e0ac27e084
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6757f2b25418da4f73e29eb6.md
@@ -0,0 +1,760 @@
+---
+id: 6757f2b25418da4f73e29eb6
+title: Step 40
+challengeType: 0
+dashedName: step-40
+---
+
+# --description--
+
+Next, you need to display the current song title and artist in the player display.
+
+As a first step, access the `#player-song-title` and `#player-song-artist` elements, responsible for displaying the song title and artist, and store them into the variables `playingSong` and `songArtist`, respectively.
+
+# --hints--
+
+You should have a variable named `playingSong`.
+
+```js
+assert.isDefined(playingSong);
+```
+
+Your `playingSong` variable should have the value of the `#player-song-title` element.
+
+```js
+assert.equal(playingSong, document.getElementById("player-song-title"));
+```
+
+You should have a variable named `songArtist`.
+
+```js
+assert.isDefined(songArtist);
+```
+
+
+Your `songArtist` variable should have the value of the `#player-song-artist` element.
+
+```js
+assert.equal(songArtist, document.getElementById("player-song-artist"));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+--fcc-editable-region--
+
+--fcc-editable-region--
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = (id, start=true) => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null || start) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing");
+ highlightCurrentSong();
+ audio.play()
+}
+
+const pauseSong = () => {
+ userData.songCurrentTime = audio.currentTime;
+ playButton.classList.remove("playing");
+ audio.pause();
+}
+
+const getCurrentSongIndex = () => userData.songs.indexOf(userData.currentSong);
+
+const getNextSong = () => userData.songs[getCurrentSongIndex() + 1];
+
+const getPreviousSong = () => userData.songs[getCurrentSongIndex() - 1];
+
+const playPreviousSong = () => {
+ if (userData.currentSong === null) return;
+ const previousSong = getPreviousSong();
+ if (previousSong) {
+ playSong(previousSong.id);
+ } else {
+ playSong(userData.songs[0].id);
+ }
+};
+
+const playNextSong = () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ return
+ }
+ const nextSong = getNextSong();
+ if (nextSong) {
+ playSong(nextSong.id);
+ } else {
+ userData.currentSong = null;
+ userData.songCurrentTime = 0;
+ pauseSong();
+ }
+}
+
+const highlightCurrentSong = () => {
+ const previousCurrentSong = document.querySelector('.playlist-song[aria-current="true"]');
+ previousCurrentSong?.removeAttribute("aria-current");
+ const songToHighlight = document.getElementById(
+ `song-${userData.currentSong?.id}`
+ );
+
+ songToHighlight?.setAttribute("aria-current", "true");
+};
+
+playButton.addEventListener("click", () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ } else {
+ playSong(userData.currentSong.id, false);
+ }
+});
+
+const songs = document.querySelectorAll(".playlist-song");
+
+songs.forEach((song) => {
+ const id = song.getAttribute("id").slice(5);
+ const songBtn = song.querySelector("button");
+ songBtn.addEventListener("click", () => {
+ playSong(Number(id));
+ })
+})
+
+pauseButton.addEventListener("click", pauseSong);
+
+nextButton.addEventListener("click", playNextSong);
+
+previousButton.addEventListener("click", playPreviousSong);
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6758a61fc7e949923716ec41.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6758a61fc7e949923716ec41.md
new file mode 100644
index 0000000000..9aa4a918a7
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/6758a61fc7e949923716ec41.md
@@ -0,0 +1,690 @@
+---
+id: 6758a61fc7e949923716ec41
+title: Step 19
+challengeType: 0
+dashedName: step-19
+---
+
+# --description--
+
+Now, use the `querySelectorAll` method to target the `.playlist-song` elements and store them in a variable named `songs`.
+
+Then, call the `forEach` method on `songs`. Pass in a callback function that uses `song` as the parameter to the method. Leave the curly braces empty for now.
+
+# --hints--
+
+You should have a variable named `songs`.
+
+```js
+assert.isDefined(songs);
+```
+
+Your should assign the collection of all `.playlist-song` elements to your `songs` variable.
+
+```js
+assert.deepEqual(songs, document.querySelectorAll(".playlist-song"));
+```
+
+You should call the `forEach` method on `songs` and pass in a callback that uses `song` as the parameter to the method.
+
+```js
+assert.match(__helpers.removeJSComments(code), /songs\s*\.\s*forEach\s*\(\s*(\(\s*song\s*\)|song)\s*=>\s*\{\s*\}\s*\)/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = id => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing")
+ audio.play()
+}
+
+playButton.addEventListener("click", () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ } else {
+ playSong(userData.currentSong.id);
+ }
+});
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67594f37fa0c684835f1b064.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67594f37fa0c684835f1b064.md
new file mode 100644
index 0000000000..3043f819af
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-music-player/67594f37fa0c684835f1b064.md
@@ -0,0 +1,696 @@
+---
+id: 67594f37fa0c684835f1b064
+title: Step 20
+challengeType: 0
+dashedName: step-20
+---
+
+# --description--
+
+When you click a song of your playlist you want to play that song. For that you'll need to add an event listener for the `click` event on each `button` element which is a child of a `song` element.
+
+Complete the callback of your `forEach` to do that. Inside the `addEventListener` callback, call `playSong(n)`, where `n` is the song id that you can get from the `id` attribute of `song`.
+
+Note that each `song` has an `id` attribute of `song-n`: you'll need to get the `n` part and convert it into a number before passing it to `playSong()`.
+
+
+# --hints--
+
+You should add an event listener for the `click` event on each `button` element which is a child of a `.playlist-song` element and call `playSong` with the `id` of the corresponding song.
+
+```js
+const testArr = [];
+const temp = playSong;
+playSong = id => {testArr.push(id)};
+const buttons = document.querySelectorAll(".playlist-song-info");
+try {
+ buttons.forEach((btn, i) => {
+ btn.dispatchEvent(new Event("click"));
+ assert.strictEqual(testArr[i], i);
+ })
+} finally {
+ playSong = temp;
+}
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+ Build a Music Player App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scratching The Surface
+ Quincy Larson
+ 4:25
+
+
+
+
+
+ Can't Stay Down
+ Quincy Larson
+ 4:15
+
+
+
+
+
+ Still Learning
+ Quincy Larson
+ 3:51
+
+
+
+
+
+ Cruising for a Musing
+ Quincy Larson
+ 3:34
+
+
+
+
+
+ Never Not Favored
+ Quincy Larson
+ 3:35
+
+
+
+
+
+ From the Ground Up
+ Quincy Larson
+ 3:12
+
+
+
+
+
+ Walking on Air
+ Quincy Larson
+ 3:25
+
+
+
+
+
+ Can't Stop Me. Can't Even Slow Me Down.
+ Quincy Larson
+ 3:52
+
+
+
+
+
+ The Surest Way Out is Through
+ Quincy Larson
+ 3:10
+
+
+
+
+
+ Chasing That Feeling
+ Quincy Larson
+ 2:43
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ /* colors */
+ --primary-color: #dfdfe2;
+ --secondary-color: #ffffff;
+ --app-background-color: #4d4d62;
+ --background-color: #1b1b32;
+ --foreground-color: #3b3b4f;
+ --highlight-color: #f1be32;
+
+ /* font sizes */
+ --root-font-size: 16px;
+ font-size: var(--root-font-size);
+
+ /* font-families */
+ --font-headline: "Roboto Mono", monospace;
+ --font-family: "Lato", sans-serif;
+ }
+
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: var(--app-background-color);
+ color: var(--primary-color);
+ font-family: var(--font-family);
+ }
+
+ h1 {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ }
+
+ h2 {
+ font-size: var(--root-font-size);
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ row-gap: 5px;
+ }
+
+ .player,
+ .playlist {
+ width: 450px;
+ background-color: var(--background-color);
+ border: 3px solid var(--foreground-color);
+ }
+
+ .player {
+ height: 260px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ .player-bar,
+ .playlist-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 5px;
+ width: 100%;
+ height: 30px;
+ background-color: var(--foreground-color);
+ }
+
+ .parallel-lines {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 6px;
+ padding: 0 5px;
+ }
+
+ .parallel-lines > div {
+ height: 2px;
+ width: 100%;
+ min-width: 75px;
+ background-color: var(--highlight-color);
+ }
+
+ .fcc-title,
+ .playlist-title {
+ color: var(--secondary-color);
+ margin: 0 10px;
+ font-family: var(--font-headline);
+ }
+
+ .player-content {
+ display: flex;
+ background-color: var(--foreground-color);
+ width: 430px;
+ height: 200px;
+ column-gap: 13px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ #player-album-art {
+ background-color: var(--secondary-color);
+ border: 6px solid var(--background-color);
+ }
+
+ #player-album-art img {
+ width: 150px;
+ display: block;
+ }
+
+ .player-display {
+ display: flex;
+ flex-direction: column;
+ row-gap: 20px;
+ padding: 14px;
+ background-color: var(--background-color);
+ height: 153px;
+ width: 226px;
+ }
+
+ .player-display-song-artist {
+ height: 80px;
+ }
+
+ .player-buttons svg {
+ fill: var(--primary-color);
+ }
+
+ .playing > svg {
+ fill: var(--highlight-color);
+ }
+
+ .player-buttons {
+ display: flex;
+ justify-content: space-around;
+ }
+
+ button {
+ background: transparent;
+ border: none;
+ color: var(--primary-color);
+ cursor: pointer;
+ font-size: var(--root-font-size);
+ outline-color: var(--highlight-color);
+ text-align: center;
+ }
+
+ .playlist-song {
+ outline-color: var(--highlight-color);
+ }
+
+ .playlist li:not(:last-child) {
+ border-bottom: 1px solid var(--background-color);
+ }
+
+ button:focus,
+ .playlist-song:focus {
+ outline-style: dashed;
+ outline-width: 2px;
+ }
+
+ /* Playlist */
+ .playlist {
+ height: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ row-gap: 10px;
+ }
+
+ #playlist-songs {
+ width: 430px;
+ height: 100%;
+ background-color: var(--foreground-color);
+ display: flex;
+ flex-direction: column;
+ row-gap: 8px;
+ padding: 8px 9px;
+ visibility: visible;
+ justify-content: start;
+ list-style: none;
+ }
+
+ .playlist-song {
+ display: flex;
+ height: 55px;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ }
+
+ [aria-current="true"] {
+ background-color: var(--background-color);
+ }
+
+ [aria-current="true"] p {
+ color: var(--highlight-color);
+ }
+
+ .playlist-song-info {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-around;
+ column-gap: 7px;
+ padding: 5px 0;
+ font-family: var(--font-family);
+ }
+
+ #player-song-title,
+ #player-song-artist {
+ margin: 0;
+ }
+
+ #player-song-artist {
+ color: var(--highlight-color);
+ font-size: 0.75rem;
+ }
+
+ #player-song-title {
+ font-size: 1.125rem;
+ }
+
+ .playlist-song-title {
+ font-size: 0.85rem;
+ width: 241px;
+ text-align: left;
+ }
+
+ .playlist-song-artist {
+ font-size: 0.725rem;
+ width: 80px;
+ }
+
+ .playlist-song-duration {
+ font-size: 0.725rem;
+ margin: auto;
+ font-family: var(--font-headline);
+ width: 30px;
+ }
+
+ .playlist-song-delete {
+ padding: 0;
+ width: 20px;
+ height: 20px;
+ }
+
+ .playlist-song-delete,
+ .playlist-song-delete {
+ fill: var(--foreground-color);
+ }
+
+ .playlist-song-delete:hover circle,
+ .playlist-song-delete:focus circle {
+ fill: #ff0000;
+ }
+
+ @media (max-width: 700px) {
+ .player,
+ .playlist {
+ width: 300px;
+ }
+
+ .player {
+ height: 340px;
+ }
+
+ #playlist-songs {
+ height: 280px;
+ padding: 5px 6px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ scrollbar-color: var(--background-color) var(--secondary-color);
+ scrollbar-width: thin;
+ }
+
+ #playlist-songs::-webkit-scrollbar {
+ width: 5px;
+ }
+
+ #playlist-songs::-webkit-scrollbar-track {
+ background: var(--background-color);
+ }
+
+ #playlist-songs::-webkit-scrollbar-thumb {
+ background: var(--secondary-color);
+ }
+
+ h1 {
+ font-size: 0.813rem;
+ }
+
+ h2 {
+ font-size: 0.75rem;
+ }
+
+ .player-bar,
+ .playlist-bar,
+ .player-content,
+ #playlist-songs {
+ width: 280px;
+ }
+
+ .playlist-song {
+ justify-content: space-between;
+ }
+
+ .playlist-song-title {
+ width: 140px;
+ }
+
+ .playlist-song-artist {
+ width: 40px;
+ }
+
+ .playlist-song-duration > button {
+ padding: 0;
+ }
+
+ .player-content {
+ display: inline;
+ position: relative;
+ justify-items: center;
+ height: 100%;
+ }
+
+ #player-album-art {
+ z-index: -100;
+ height: 280px;
+ box-shadow: none;
+ background: #000;
+ }
+
+ #player-album-art img {
+ width: 100%;
+ opacity: 0.6;
+ }
+
+ .player-display-song-artist {
+ padding: 0 10px;
+ }
+
+ .player-display-song-artist > p {
+ white-space: pre-wrap;
+ }
+
+ .player-display {
+ position: absolute;
+ width: 100%;
+ z-index: 1000;
+ background-color: transparent;
+ top: 0;
+ height: 280px;
+ justify-content: space-between;
+ text-align: center;
+ }
+ }
+```
+
+```js
+const playlistSongs = document.getElementById("playlist-songs");
+const playButton = document.getElementById("play");
+const pauseButton = document.getElementById("pause");
+const nextButton = document.getElementById("next");
+const previousButton = document.getElementById("previous");
+const allSongs = [
+ {
+ id: 0,
+ title: "Scratching The Surface",
+ artist: "Quincy Larson",
+ duration: "4:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
+ },
+ {
+ id: 1,
+ title: "Can't Stay Down",
+ artist: "Quincy Larson",
+ duration: "4:15",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
+ },
+ {
+ id: 2,
+ title: "Still Learning",
+ artist: "Quincy Larson",
+ duration: "3:51",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
+ },
+ {
+ id: 3,
+ title: "Cruising for a Musing",
+ artist: "Quincy Larson",
+ duration: "3:34",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
+ },
+ {
+ id: 4,
+ title: "Never Not Favored",
+ artist: "Quincy Larson",
+ duration: "3:35",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
+ },
+ {
+ id: 5,
+ title: "From the Ground Up",
+ artist: "Quincy Larson",
+ duration: "3:12",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
+ },
+ {
+ id: 6,
+ title: "Walking on Air",
+ artist: "Quincy Larson",
+ duration: "3:25",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
+ },
+ {
+ id: 7,
+ title: "Can't Stop Me. Can't Even Slow Me Down.",
+ artist: "Quincy Larson",
+ duration: "3:52",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
+ },
+ {
+ id: 8,
+ title: "The Surest Way Out is Through",
+ artist: "Quincy Larson",
+ duration: "3:10",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
+ },
+ {
+ id: 9,
+ title: "Chasing That Feeling",
+ artist: "Quincy Larson",
+ duration: "2:43",
+ src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
+ },
+];
+
+const audio = new Audio();
+
+const userData = {
+ songs: allSongs,
+ currentSong: null,
+ songCurrentTime: 0,
+}
+
+const playSong = id => {
+ const song = userData.songs.find((song) => song.id === id);
+ audio.src = song.src;
+ audio.title = song.title;
+ if (userData.currentSong === null) {
+ audio.currentTime = 0
+ } else {
+ audio.currentTime = userData.songCurrentTime;
+ }
+ userData.currentSong = song;
+ playButton.classList.add("playing")
+ audio.play()
+}
+
+playButton.addEventListener("click", () => {
+ if (userData.currentSong === null) {
+ playSong(userData.songs[0].id);
+ } else {
+ playSong(userData.currentSong.id);
+ }
+});
+
+
+const songs = document.querySelectorAll(".playlist-song");
+--fcc-editable-region--
+songs.forEach((song) => {
+
+});
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-reusable-mega-navbar/6740495ba48aa94e5667b436.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-reusable-mega-navbar/6740495ba48aa94e5667b436.md
index 82e8993d59..2e0e0fd742 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/workshop-reusable-mega-navbar/6740495ba48aa94e5667b436.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-reusable-mega-navbar/6740495ba48aa94e5667b436.md
@@ -3,6 +3,7 @@ id: 6740495ba48aa94e5667b436
title: Step 1
challengeType: 0
dashedName: step-1
+demoType: onLoad
---
# --description--
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-reusable-profile-card-component/674ef11f75254548672d998c.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-reusable-profile-card-component/674ef11f75254548672d998c.md
new file mode 100644
index 0000000000..274e512a79
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-reusable-profile-card-component/674ef11f75254548672d998c.md
@@ -0,0 +1,125 @@
+---
+id: 674ef11f75254548672d998c
+title: Step 1
+challengeType: 0
+dashedName: step-1
+demoType: onLoad
+---
+
+# --description--
+
+In this project, you will learn how to work with props by building a reusable profile card component.
+
+Start by using the `export` keyword to create a `Card` functional component with `name`, `title`, and `bio` as the props. Don't forget to make sure they're all wrapped in a curly brace. That way, you destructure them instead of accessing them from `props`.
+
+Also, return a pair of parentheses with an empty string inside of them for now.
+
+# --hints--
+
+You should create and export a `Card` functional component. Don't forget to return an empty string inside it.
+
+```js
+const mockedComponent = Enzyme.mount(
+ React.createElement(window.index.Card)
+);
+
+assert.lengthOf(mockedComponent.find('Card'), 1);
+```
+
+Your `Card` component should have a `name`, `title`, and `bio` props.
+
+```js
+const mockedComponent = Enzyme.mount(
+ React.createElement(window.index.Card)
+);
+
+const componentFunction = mockedComponent.type();
+const propsSource = componentFunction.toString();
+
+assert.match(propsSource, /\bname\b/);
+assert.match(propsSource, /\btitle\b/);
+assert.match(propsSource, /\bbio\b/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
Reusable Card component
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ --dark-grey: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-orange: #f89808;
+}
+
+body {
+ background-color: var(--dark-grey);
+}
+
+.flex-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-around;
+ align-items: center;
+}
+
+.card {
+ border: 5px solid var(--dark-orange);
+ border-radius: 10px;
+ width: 100%;
+ padding: 20px;
+ margin: 10px 0;
+ background-color: var(--light-grey);
+}
+
+.card-title {
+ border-bottom: 4px solid var(--dark-orange);
+ width: fit-content;
+}
+
+@media (min-width: 768px) {
+ .card {
+ width: 300px;
+ }
+}
+```
+
+```jsx
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-reusable-profile-card-component/674ef2d357676e50e4691658.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-reusable-profile-card-component/674ef2d357676e50e4691658.md
new file mode 100644
index 0000000000..cd896b45aa
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-reusable-profile-card-component/674ef2d357676e50e4691658.md
@@ -0,0 +1,116 @@
+---
+id: 674ef2d357676e50e4691658
+title: Step 2
+challengeType: 0
+dashedName: step-2
+---
+
+# --description--
+
+Inside the return, remove the empty string, then create a `div` element with a `className` of `card`.
+
+# --hints--
+
+You should not have an empty string in your Card component.
+
+```js
+assert.notMatch(code, /""/)
+```
+
+You should create a `div` element with the `className` `card` at the top level of your `Card` component.
+
+```js
+const mockedComponent = Enzyme.mount(
+ React.createElement(window.index.Card)
+);
+
+assert.equal(mockedComponent.childAt(0).type(), 'div');
+assert.isTrue(mockedComponent.childAt(0).hasClass('card'));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
Reusable Card component
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ --dark-grey: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-orange: #f89808;
+}
+
+body {
+ background-color: var(--dark-grey);
+}
+
+.flex-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-around;
+ align-items: center;
+}
+
+.card {
+ border: 5px solid var(--dark-orange);
+ border-radius: 10px;
+ width: 100%;
+ padding: 20px;
+ margin: 10px 0;
+ background-color: var(--light-grey);
+}
+
+.card-title {
+ border-bottom: 4px solid var(--dark-orange);
+ width: fit-content;
+}
+
+@media (min-width: 768px) {
+ .card {
+ width: 300px;
+ }
+}
+```
+
+```jsx
+export function Card({ name, title, bio }) {
+ return (
+ --fcc-editable-region--
+ ""
+ --fcc-editable-region--
+ )
+}
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-reusable-profile-card-component/674ef2d357676e50e4691659.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-reusable-profile-card-component/674ef2d357676e50e4691659.md
new file mode 100644
index 0000000000..cc5141ec81
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-reusable-profile-card-component/674ef2d357676e50e4691659.md
@@ -0,0 +1,166 @@
+---
+id: 674ef2d357676e50e4691659
+title: Step 3
+challengeType: 0
+dashedName: step-3
+---
+
+# --description--
+
+Inside the `div` element, create an `h2` element and interpolate the `name` prop as its text.
+
+Also, inside the `div`, create a paragraph with the `className` of `card-title` to interpolate the `title` prop, and another paragraph to interpolate the `bio` prop.
+
+# --hints--
+
+You should create an `h2` element inside your `div` element.
+
+```js
+const mockedComponent = Enzyme.mount(
+ React.createElement(window.index.Card)
+);
+
+const h2Elem = mockedComponent.find('h2');
+
+assert.equal(h2Elem.parent().type(), 'div');
+```
+
+Your `h2` element should have `{name}` as its text content.
+
+```js
+const mockedComponent = Enzyme.mount(
+ React.createElement(window.index.Card, { name: 'nameVal' })
+);
+
+const h2Elem = mockedComponent.find('h2');
+
+assert.equal(h2Elem.text(), 'nameVal');
+```
+
+You should create a `p` tag with the `className` of `card-title` inside your `div` element.
+
+```js
+const mockedComponent = Enzyme.mount(
+ React.createElement(window.index.Card)
+);
+
+const pElem = mockedComponent.find('p.card-title');
+
+assert.equal(pElem.parent().type(), 'div');
+```
+
+Your `p` element with `className` of `card-title` should have `{title}` as its text content.
+
+```js
+const mockedComponent = Enzyme.mount(
+ React.createElement(window.index.Card, { title: 'titleVal' })
+);
+
+const pElem = mockedComponent.find('p.card-title');
+
+assert.equal(pElem.text(), 'titleVal');
+assert.equal(pElem.parent().type(), 'div');
+```
+
+You should create another `p` element with `{bio}` as its text.
+
+```js
+const mockedComponent = Enzyme.mount(
+ React.createElement(window.index.Card, { bio: 'bioVal' })
+);
+
+const secondPElem = mockedComponent.children().childAt(2)
+
+assert.equal(secondPElem.type(), 'p')
+assert.equal(secondPElem.text(), 'bioVal');
+assert.equal(secondPElem.parent().type(), 'div');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
Reusable Card component
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ --dark-grey: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-orange: #f89808;
+}
+
+body {
+ background-color: var(--dark-grey);
+}
+
+.flex-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-around;
+ align-items: center;
+}
+
+.card {
+ border: 5px solid var(--dark-orange);
+ border-radius: 10px;
+ width: 100%;
+ padding: 20px;
+ margin: 10px 0;
+ background-color: var(--light-grey);
+}
+
+.card-title {
+ border-bottom: 4px solid var(--dark-orange);
+ width: fit-content;
+}
+
+@media (min-width: 768px) {
+ .card {
+ width: 300px;
+ }
+}
+```
+
+```jsx
+export function Card({ name, title, bio }) {
+ return (
+ --fcc-editable-region--
+
+
+
+ --fcc-editable-region--
+ )
+}
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-reusable-profile-card-component/674ef2d357676e50e469165a.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-reusable-profile-card-component/674ef2d357676e50e469165a.md
new file mode 100644
index 0000000000..7e92584a83
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-reusable-profile-card-component/674ef2d357676e50e469165a.md
@@ -0,0 +1,117 @@
+---
+id: 674ef2d357676e50e469165a
+title: Step 4
+challengeType: 0
+dashedName: step-4
+---
+
+# --description--
+
+To start using the `Card` component, use the `export` keyword to create an `App` functional component.
+
+Inside the `App` component, return a pair of parentheses containing an empty string.
+
+# --hints--
+
+You should export an `App` functional component.
+
+```js
+const mockedComponent = Enzyme.mount(
+ React.createElement(window.index.App)
+);
+
+assert.lengthOf(mockedComponent.find('App'), 1);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
Reusable Card component
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ --dark-grey: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-orange: #f89808;
+}
+
+body {
+ background-color: var(--dark-grey);
+}
+
+.flex-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-around;
+ align-items: center;
+}
+
+.card {
+ border: 5px solid var(--dark-orange);
+ border-radius: 10px;
+ width: 100%;
+ padding: 20px;
+ margin: 10px 0;
+ background-color: var(--light-grey);
+}
+
+.card-title {
+ border-bottom: 4px solid var(--dark-orange);
+ width: fit-content;
+}
+
+@media (min-width: 768px) {
+ .card {
+ width: 300px;
+ }
+}
+```
+
+```jsx
+export function Card({ name, title, bio }) {
+ return (
+
+
{name}
+
{title}
+
{bio}
+
+ )
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-reusable-profile-card-component/674ef2d357676e50e469165b.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-reusable-profile-card-component/674ef2d357676e50e469165b.md
new file mode 100644
index 0000000000..db3fbd1070
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-reusable-profile-card-component/674ef2d357676e50e469165b.md
@@ -0,0 +1,126 @@
+---
+id: 674ef2d357676e50e469165b
+title: Step 5
+challengeType: 0
+dashedName: step-5
+---
+
+# --description--
+
+Inside your return statement, replace the empty string with a `div` element with a `className` property of `flex-container`.
+
+# --hints--
+
+You should not have an empty string in your Card component.
+
+```js
+assert.notMatch(code, /""/)
+```
+
+You should create a `div` element with the class `flex-container`.
+
+```js
+const mockedComponent = Enzyme.mount(
+ React.createElement(window.index.App)
+);
+
+assert.equal(mockedComponent.childAt(0).type(), 'div');
+assert.isTrue(mockedComponent.childAt(0).hasClass('flex-container'));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
Reusable Card component
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ --dark-grey: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-orange: #f89808;
+}
+
+body {
+ background-color: var(--dark-grey);
+}
+
+.flex-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-around;
+ align-items: center;
+}
+
+.card {
+ border: 5px solid var(--dark-orange);
+ border-radius: 10px;
+ width: 100%;
+ padding: 20px;
+ margin: 10px 0;
+ background-color: var(--light-grey);
+}
+
+.card-title {
+ border-bottom: 4px solid var(--dark-orange);
+ width: fit-content;
+}
+
+@media (min-width: 768px) {
+ .card {
+ width: 300px;
+ }
+}
+```
+
+```jsx
+export function Card({ name, title, bio }) {
+ return (
+
+
{name}
+
{title}
+
{bio}
+
+ )
+}
+
+export function App() {
+ return (
+ --fcc-editable-region--
+ ""
+ --fcc-editable-region--
+ );
+}
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-reusable-profile-card-component/674ef2d357676e50e469165c.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-reusable-profile-card-component/674ef2d357676e50e469165c.md
new file mode 100644
index 0000000000..d6d3cddd97
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-reusable-profile-card-component/674ef2d357676e50e469165c.md
@@ -0,0 +1,144 @@
+---
+id: 674ef2d357676e50e469165c
+title: Step 6
+challengeType: 0
+dashedName: step-6
+---
+
+# --description--
+
+Now, use the `Card` component with the `name` prop set to `"Mark"`, the `title` prop set to `"Frontend developer"`, and the `bio` set to `"I like to work with different frontend technologies and play video games."`
+
+# --hints--
+
+You should use the `Card` component as an element with a `name` prop set to `"Mark"`.
+
+```js
+const mockedComponent = Enzyme.mount(React.createElement(window.index.App));
+const cardItem = mockedComponent.find(window.index.Card);
+
+const cardItemsProps = cardItem.props()
+
+assert.equal(cardItem.props().name, "Mark")
+```
+
+You should use the `Card` component as an element with a `title` prop set to `"Frontend developer"`.
+
+```js
+const mockedComponent = Enzyme.mount(React.createElement(window.index.App));
+const cardItem = mockedComponent.find(window.index.Card);
+
+const cardItemsProps = cardItem.props()
+
+assert.equal(cardItem.props().title, "Frontend developer")
+```
+
+You should use the `Card` component as an element with a `bio` prop set to `"I like to work with different frontend technologies and play video games."`.
+
+```js
+const mockedComponent = Enzyme.mount(React.createElement(window.index.App));
+const cardItem = mockedComponent.find(window.index.Card);
+
+const cardItemsProps = cardItem.props()
+
+assert.equal(cardItem.props().bio, "I like to work with different frontend technologies and play video games.")
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
Reusable Card component
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ --dark-grey: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-orange: #f89808;
+}
+
+body {
+ background-color: var(--dark-grey);
+}
+
+.flex-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-around;
+ align-items: center;
+}
+
+.card {
+ border: 5px solid var(--dark-orange);
+ border-radius: 10px;
+ width: 100%;
+ padding: 20px;
+ margin: 10px 0;
+ background-color: var(--light-grey);
+}
+
+.card-title {
+ border-bottom: 4px solid var(--dark-orange);
+ width: fit-content;
+}
+
+@media (min-width: 768px) {
+ .card {
+ width: 300px;
+ }
+}
+```
+
+```jsx
+export function Card({ name, title, bio }) {
+ return (
+
+
{name}
+
{title}
+
{bio}
+
+ )
+}
+
+export function App() {
+ return (
+
+ --fcc-editable-region--
+
+ --fcc-editable-region--
+
+ );
+}
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-reusable-profile-card-component/674ef2d357676e50e469165d.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-reusable-profile-card-component/674ef2d357676e50e469165d.md
new file mode 100644
index 0000000000..d882a9c526
--- /dev/null
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-reusable-profile-card-component/674ef2d357676e50e469165d.md
@@ -0,0 +1,265 @@
+---
+id: 674ef2d357676e50e469165d
+title: Step 7
+challengeType: 0
+dashedName: step-7
+---
+
+# --description--
+
+Again, use the `Card` component two more times with the following:
+
+| Props | First Card Values | Second Card Values |
+| ------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
+| `name` | `"Tiffany"` | `"Doug"` |
+| `title` | `"Engineering manager"` | `"Backend developer"` |
+| `bio` | `"I have worked in tech for 15 years and love to help people grow in this industry."` | `"I have been a software developer for over 20 years and I love working with Go and Rust."` |
+
+With that, your reusable profile card component project is complete!
+
+# --hints--
+
+You should use the `Card` component as an element with the appropriate props and first card values.
+
+```js
+const mockedComponent = Enzyme.mount(React.createElement(window.index.App));
+const cardItems = mockedComponent.find(window.index.Card);
+
+const propsList = cardItems.map(item => item.props());
+
+assert.deepEqual(propsList[1], {
+ name: 'Tiffany',
+ title: 'Engineering manager',
+ bio: 'I have worked in tech for 15 years and love to help people grow in this industry.'
+});
+```
+
+You should use the `Card` component as an element with the appropriate props and second card values.
+
+```js
+const mockedComponent = Enzyme.mount(React.createElement(window.index.App));
+const cardItems = mockedComponent.find(window.index.Card);
+
+const propsList = cardItems.map(item => item.props());
+
+assert.deepEqual(propsList[2], {
+ name: 'Doug',
+ title: 'Backend developer',
+ bio: 'I have been a software developer for over 20 years and I love working with Go and Rust.'
+});
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
Reusable Card component
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ --dark-grey: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-orange: #f89808;
+}
+
+body {
+ background-color: var(--dark-grey);
+}
+
+.flex-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-around;
+ align-items: center;
+}
+
+.card {
+ border: 5px solid var(--dark-orange);
+ border-radius: 10px;
+ width: 100%;
+ padding: 20px;
+ margin: 10px 0;
+ background-color: var(--light-grey);
+}
+
+.card-title {
+ border-bottom: 4px solid var(--dark-orange);
+ width: fit-content;
+}
+
+@media (min-width: 768px) {
+ .card {
+ width: 300px;
+ }
+}
+```
+
+```jsx
+export function Card({ name, title, bio }) {
+ return (
+
+
{name}
+
{title}
+
{bio}
+
+ )
+}
+
+export function App() {
+ return (
+
+
+ --fcc-editable-region--
+
+ --fcc-editable-region--
+
+ );
+}
+```
+
+# --solutions--
+
+```html
+
+
+
+
+
Reusable Card component
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ --dark-grey: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-orange: #f89808;
+}
+
+body {
+ background-color: var(--dark-grey);
+}
+
+.flex-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-around;
+ align-items: center;
+}
+
+.card {
+ border: 5px solid var(--dark-orange);
+ border-radius: 10px;
+ width: 100%;
+ padding: 20px;
+ margin: 10px 0;
+ background-color: var(--light-grey);
+}
+
+.card-title {
+ border-bottom: 4px solid var(--dark-orange);
+ width: fit-content;
+}
+
+@media (min-width: 768px) {
+ .card {
+ width: 300px;
+ }
+}
+```
+
+```jsx
+export function Card({ name, title, bio }) {
+ return (
+
+
{name}
+
{title}
+
{bio}
+
+ )
+}
+
+export function App() {
+ return (
+
+
+
+
+
+
+
+ );
+}
+```
diff --git a/curriculum/challenges/ukrainian/25-front-end-development/workshop-rps-game/66cf33305293e1b35c1aef7f.md b/curriculum/challenges/ukrainian/25-front-end-development/workshop-rps-game/66cf33305293e1b35c1aef7f.md
index f6a53bdeb7..d4b51a618b 100644
--- a/curriculum/challenges/ukrainian/25-front-end-development/workshop-rps-game/66cf33305293e1b35c1aef7f.md
+++ b/curriculum/challenges/ukrainian/25-front-end-development/workshop-rps-game/66cf33305293e1b35c1aef7f.md
@@ -7,7 +7,7 @@ dashedName: step-6
# --description--
-Тепер настав час отримати результати раунду. Виконайте функцію `getRoundResults`.
+Now it's time to get the results of the round. Виконайте функцію `getRoundResults`.
Якщо гравець виграє раунд, оновіть `playerScore` на `1` та поверніть повідомлення `"Player wins! [player's choice] beats [computer's choice]"`.