diff --git a/.vscode/settings.json b/.vscode/settings.json
index 94fdbe6e..b65a4494 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -5,7 +5,9 @@
"editor.detectIndentation": false,
"editor.insertSpaces": true,
"editor.tabSize": 2,
- "editor.codeActionsOnSave": { "source.fixAll.eslint": true },
+ "editor.codeActionsOnSave": {
+ "source.fixAll.eslint": "explicit"
+ },
"editor.bracketPairColorization.enabled": true,
"editor.guides.bracketPairs": "active",
"[javascript]": {
diff --git a/3-JSKata/1-objects-and-arrays/kata.js b/3-JSKata/1-objects-and-arrays/kata.js
index ef4a6734..dc040a2c 100644
--- a/3-JSKata/1-objects-and-arrays/kata.js
+++ b/3-JSKata/1-objects-and-arrays/kata.js
@@ -4,46 +4,79 @@
// getGreeting should return a string containing
// 'Hello ' and the contents of `name`
-function getGreeting(name) {}
+function getGreeting(name) {
+ return 'Hello ' + name
+}
// ageOneYear should return a new object with an `age` property 1 greater
// than the `age` property of `obj`
-function ageOneYear(obj) {}
+function ageOneYear(obj) {
+ console.log(obj)
+ let newObj = {
+ ...obj,
+ age: obj['age'] + 1,
+ }
+ console.log(newObj)
+
+ return newObj
+}
// makeObject should return an object that looks like this:
// (but using the arguments passed to the function)
// {
// key: value
// }
-function makeObject(key, value) {}
+function makeObject(key, value) {
+ return { [key]: value }
+}
// getPropertyValue should return the value of the
// property contained in the `key` of `obj`
-function getPropertyValue(obj, key) {}
+function getPropertyValue(obj, key) {
+ return obj[key]
+}
// addName should return a copy of `obj` with the addition of a `name`
// property that has the value of the `name` argument
// Tip: consider the object literal spread syntax
-function addName(obj, name) {}
+function addName(obj, name) {
+ let newObj = {
+ ...obj,
+ name: name,
+ }
+ return newObj
+}
// deleteProperty should return a new copy of `obj` without the property name
// that matches the `key` parameter
// Tip: consider JavaScript's `delete` operator
-function deleteProperty(obj, key) {}
+function deleteProperty(obj, key) {
+ let newObj = { ...obj }
+ delete newObj[key]
+ return newObj
+}
// returnErrorIfFalsy should return a JavaScript Error object with message:
// 'Oh no, an error!'
// if val evaluates to false
// Tip: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
-function returnErrorIfFalsy(val) {}
+function returnErrorIfFalsy(val) {
+ if (val == false) {
+ return Error('Oh no, an error!')
+ }
+}
// keys should return an array of the object's property names (keys)
// For example, given { foo: 1, bar: 2 } it would return ['foo', 'bar']
-function getKeys(obj) {}
+function getKeys(obj) {
+ return Object.keys(obj)
+}
// getValues should return an array of the object's own values
// For example, given { foo: 1, bar: 2 } it would return [1, 2]
-function getValues(obj) {}
+function getValues(obj) {
+ return Object.values(obj)
+}
/**
* Arrays
@@ -52,57 +85,111 @@ function getValues(obj) {}
// makeArrayOfItem should return an array that is `length` long, made up of
// `item`. For example, makeArrayOfItem('foo', 2) would return:
// ['foo', 'foo']
-function makeArrayOfItem(item, length) {}
+function makeArrayOfItem(item, length) {
+ return Array(length).fill(item)
+}
// makeArrayOfItems should return an array containing all arguments passed to it
// Tip: consider JavaScript's Rest parameters
-function makeArrayOfItems() {}
+function makeArrayOfItems() {
+ return [...arguments]
+}
// hasItem should return true if `item` is present in `arr` at least once,
// otherwise it should return false.
// Tip: there is an array function that makes this straightforward
-function hasItem(arr, item) {}
+function hasItem(arr, item) {
+ return arr.includes(item)
+}
// getItemAtIndex should return arr[idx] but only if that index exists:
// if it doesn't, return a JavaScript Error object.
-function getItemAtIndex(arr, idx) {}
+function getItemAtIndex(arr, idx) {
+ if (arr[idx]) {
+ return arr[idx]
+ } else {
+ return Error()
+ }
+}
// replaceItemAtIndex should return a copy of `arr` with
// the element at `idx` replaced with `item`
// Tip: consider the array literal spread syntax
-function replaceItemAtIndex(arr, idx, item) {}
+function replaceItemAtIndex(arr, idx, item) {
+ let newArr = [...arr]
+ newArr[idx] = item
+ return newArr
+}
// insertItemAtIndex should return a copy of `arr` with `item` inserted at
// `idx` without overwriting any array values (the array should get longer)
-function insertItemAtIndex(arr, item, idx) {}
+function insertItemAtIndex(arr, item, idx) {
+ let newArr = [...arr]
+ newArr.splice(idx, 0, item)
+ return newArr
+}
// deleteItemAtIndex should return a copy of `arr` without
// the element at `idx` (the array should get shorter).
-function deleteItemAtIndex(arr, idx) {}
+function deleteItemAtIndex(arr, idx) {
+ let newArr = [...arr]
+ newArr.splice(idx, 1)
+ return newArr
+}
// deleteItem should return an array with every instance of `item` removed
-function deleteItem(arr, item) {}
+function deleteItem(arr, item) {
+ let newArr = []
+ for (const i in arr) {
+ if (arr[i] != item) {
+ newArr.push(arr[i])
+ }
+ }
+ return newArr
+}
// zipObject should return an object built from two arrays
// For example, given ['foo', 'bar'] and [1, 2] it would return
// { foo: 1, bar: 2 }
-function zipObject(keys, values) {}
+function zipObject(keys, values) {
+ let newObj = {}
+ for (const i in keys) {
+ newObj[keys[i]] = values[i]
+ }
+ return newObj
+}
// unzipObject should return an array of arrays, each one a pair of keys and values
// For example, given {foo: 1, bar: 2} it would return
// [['foo', 1], ['bar', 2]]
-function unzipObject(obj) {}
+function unzipObject(obj) {
+ return Object.entries(obj)
+}
// findOneByProperty should return an object from `arr` that has the
// property AND value of `search`. For example, given:
// [{a: 1}, {b: 2, c: 3}] and {b: 2}
// it will return:
// {b: 2, c: 3}
-function findOneByProperty(arr, search) {}
+function findOneByProperty(arr, search) {
+ let key = Object.keys(search)[0]
+ let value = search[key]
+ return arr.find((obj) => obj[key] == value)
+}
// findAll should return an array containing all objects in `arr` that
// have the property and value of `search`
-function findAll(arr, search) {}
+function findAll(arr, search) {
+ let newArr = []
+ let key = Object.keys(search)[0]
+ let value = search[key]
+ for (obj of arr) {
+ if (obj[key] == value) {
+ newArr.push(obj)
+ }
+ }
+ return newArr
+}
module.exports = {
addName,
diff --git a/3-JSKata/2-strings-and-numbers/utilities.js b/3-JSKata/2-strings-and-numbers/utilities.js
index 5ce1008c..ca348f56 100644
--- a/3-JSKata/2-strings-and-numbers/utilities.js
+++ b/3-JSKata/2-strings-and-numbers/utilities.js
@@ -1,24 +1,58 @@
-function getType(thing) {}
+function getType(thing) {
+ return typeof thing
+}
-function isNumber(thing) {}
+function isNumber(thing) {
+ return typeof thing == 'number'
+}
-function toNumber(str) {}
+function toNumber(str) {
+ return Number(str)
+}
-function isStringNumber(str) {}
+function isStringNumber(str) {
+ return typeof str == 'string' && !isNaN(str)
+}
-function add(a, b) {}
+function add(a, b) {
+ return a + b
+}
-function addStrings(a, b) {}
+function addStrings(a, b) {
+ return String(Number(a) + Number(b))
+}
-function addStringsOrNumbers(a, b) {}
+function addStringsOrNumbers(a, b) {
+ if (typeof a == 'number' && typeof b == 'number') {
+ return a + b
+ } else {
+ return String(Number(a) + Number(b))
+ }
+}
-function isEmail(str) {}
+function isEmail(str) {
+ console.log
+ const emailRegex = /.+@.+\..+/
+ return emailRegex.test(str)
+}
-function countIf(array, fn) {}
+function countIf(array, fn) {
+ count = 0
+ for (const item of array) {
+ if (fn(item)) {
+ count++
+ }
+ }
+ return count
+}
-function filterStringsWithCommas(str) {}
+function filterStringsWithCommas(str) {
+ return str.includes(',')
+}
-function splitStringByCommas(str) {}
+function splitStringByCommas(str) {
+ return str.split(',')
+}
module.exports = {
getType,
diff --git a/3-JSKata/3-data-structures/find.js b/3-JSKata/3-data-structures/find.js
index 73dadfc9..2674b232 100644
--- a/3-JSKata/3-data-structures/find.js
+++ b/3-JSKata/3-data-structures/find.js
@@ -1,3 +1,6 @@
-function find(arr, searchDetails) {}
+function find(arr, searchDetails) {
+ searchKey = Object.keys(searchDetails)[0]
+ return arr.find((obj) => obj[searchKey] == searchDetails[searchKey])
+}
module.exports = find
diff --git a/3-JSKata/3-data-structures/getPropTypes.js b/3-JSKata/3-data-structures/getPropTypes.js
index bdcb34a8..f0c31583 100644
--- a/3-JSKata/3-data-structures/getPropTypes.js
+++ b/3-JSKata/3-data-structures/getPropTypes.js
@@ -1,3 +1,9 @@
-function getPropTypes(obj) {}
+function getPropTypes(obj) {
+ let propTypes = []
+ for (const i in obj) {
+ propTypes.push(typeof obj[i])
+ }
+ return propTypes
+}
module.exports = getPropTypes
diff --git a/3-JSKata/3-data-structures/getType.js b/3-JSKata/3-data-structures/getType.js
index 7300746a..305be5ad 100644
--- a/3-JSKata/3-data-structures/getType.js
+++ b/3-JSKata/3-data-structures/getType.js
@@ -1,3 +1,5 @@
-function getType(thing) {}
+function getType(thing) {
+ return typeof thing
+}
module.exports = getType
diff --git a/3-JSKata/3-data-structures/getValue.js b/3-JSKata/3-data-structures/getValue.js
index a2ce34fd..6859439d 100644
--- a/3-JSKata/3-data-structures/getValue.js
+++ b/3-JSKata/3-data-structures/getValue.js
@@ -1,3 +1,5 @@
-function getValue(obj, key) {}
+function getValue(obj, key) {
+ return obj[key]
+}
module.exports = getValue
diff --git a/3-JSKata/3-data-structures/matrix.js b/3-JSKata/3-data-structures/matrix.js
index f4e7dcde..a9ae1824 100644
--- a/3-JSKata/3-data-structures/matrix.js
+++ b/3-JSKata/3-data-structures/matrix.js
@@ -1,6 +1,18 @@
-function getMatrix(n) {}
+function getMatrix(n) {
+ let newMatrix = []
+ for (let i = 0; i < n; i++) {
+ const row = Array(n).fill(0)
+ newMatrix.push(row)
+ }
+ return newMatrix
+}
-function updateMatrix(matrix, coords, value) {}
+function updateMatrix(matrix, coords, value) {
+ const x = coords[0]
+ const y = coords[1]
+ matrix[x][y] = value
+ return matrix
+}
module.exports = {
getMatrix,
diff --git a/3-JSKata/3-data-structures/positions.js b/3-JSKata/3-data-structures/positions.js
index 01f59b65..cdbfca5e 100644
--- a/3-JSKata/3-data-structures/positions.js
+++ b/3-JSKata/3-data-structures/positions.js
@@ -1,6 +1,10 @@
-function getFirst(arr) {}
+function getFirst(arr) {
+ return arr[0]
+}
-function getLast(arr) {}
+function getLast(arr) {
+ return arr[arr.length - 1]
+}
module.exports = {
getFirst,
diff --git a/3-JSKata/3-data-structures/where.js b/3-JSKata/3-data-structures/where.js
index 6a2bdc3b..8f6605d8 100644
--- a/3-JSKata/3-data-structures/where.js
+++ b/3-JSKata/3-data-structures/where.js
@@ -1,3 +1,22 @@
-function where(arr, searchDetails) {}
+function where(arr, searchDetails) {
+ let newArr = []
+ const searchKey = Object.keys(searchDetails)
+
+ for (const obj of arr) {
+ let match = true
+
+ for (const i in searchKey) {
+ if (obj[searchKey[i]] != searchDetails[searchKey[i]]) {
+ match = false
+ }
+ }
+
+ if (match) {
+ newArr.push(obj)
+ }
+ }
+ console.log(newArr)
+ return newArr
+}
module.exports = where
diff --git a/3-JSKata/4-types/functions.js b/3-JSKata/4-types/functions.js
index e69de29b..30fd99d6 100644
--- a/3-JSKata/4-types/functions.js
+++ b/3-JSKata/4-types/functions.js
@@ -0,0 +1,41 @@
+function callsFunction(func) {
+ func()
+}
+
+function callsProperty(obj) {
+ obj.increment()
+}
+
+function filter(arr, func) {
+ const elements = []
+ for (i in arr) {
+ if (func(arr[i])) {
+ elements.push(arr[i])
+ }
+ }
+ return elements
+}
+
+function find(arr, func) {
+ for (i in arr) {
+ if (func(arr[i])) {
+ return arr[i]
+ }
+ }
+}
+
+function map(arr, func) {
+ const elements = []
+ for (i in arr) {
+ elements.push(func(arr[i]))
+ }
+ return elements
+}
+
+module.exports = {
+ callsFunction,
+ callsProperty,
+ filter,
+ find,
+ map,
+}
diff --git a/3-JSKata/4-types/types.js b/3-JSKata/4-types/types.js
index e69de29b..5fe0f05b 100644
--- a/3-JSKata/4-types/types.js
+++ b/3-JSKata/4-types/types.js
@@ -0,0 +1,34 @@
+function getBoolean() {
+ return true
+}
+
+function getFunction() {
+ return function () {
+ return
+ }
+}
+
+function getNull() {
+ return null
+}
+
+function getNumber() {
+ return 1
+}
+
+function getObject() {
+ return { 1: 1, 2: 2 }
+}
+
+function getString() {
+ return 'hi'
+}
+
+module.exports = {
+ getBoolean,
+ getFunction,
+ getNull,
+ getNumber,
+ getObject,
+ getString,
+}
diff --git a/3-JSKata/README.md b/3-JSKata/README.md
index 792849fe..5661d878 100644
--- a/3-JSKata/README.md
+++ b/3-JSKata/README.md
@@ -82,10 +82,10 @@ If things aren't working as you are expecting, `console.log` out the variables a
## Exercises
-- [ ] [Object and arrays](./1-objects-and-arrays/README.md) (2hrs)
-- [ ] [Strings and numbers](./2-strings-and-numbers/README.md) (2hrs)
-- [ ] [Data structures](./3-data-structures/README.md) (2hrs)
-- [ ] [Types](./4-types/README.md) (2hrs)
+- [x] [Object and arrays](./1-objects-and-arrays/README.md) (2hrs)
+- [x] [Strings and numbers](./2-strings-and-numbers/README.md) (2hrs)
+- [x] [Data structures](./3-data-structures/README.md) (2hrs)
+- [x] [Types](./4-types/README.md) (2hrs)
diff --git a/4-React/src/components/Dog/Dog.jsx b/4-React/src/components/Dog/Dog.jsx
new file mode 100644
index 00000000..d7705725
--- /dev/null
+++ b/4-React/src/components/Dog/Dog.jsx
@@ -0,0 +1,19 @@
+export function Dog(props) {
+ const imageBreed = props.breed.charAt(0).toLowerCase() + props.breed.slice(1)
+ return (
+
+