initial commit with assignment answer

This commit is contained in:
Jacob 2023-06-25 20:39:58 +02:00
parent c931627492
commit 2a6f2ef35a
22 changed files with 1213 additions and 0 deletions

42
src/1/index.tsx Normal file
View File

@ -0,0 +1,42 @@
import { FunctionComponent, useState } from "react";
function ListItemComponent(props: any) {
return <li>{props.itemNumber}</li>;
}
function ListComponent(props: any) {
return <div>
<ul>
{props.items.map((item: string) => <ListItemComponent itemNumber={item} />)}
</ul>
</div>
}
const Task1: FunctionComponent = () => {
const [items, setItems] = useState([
"Item 1",
"Item 2",
"Item 3",
"Item 4",
"Item 5",
]);
return <div>
#List goes here#
#Iterating over list
<ul>
{items.map((item) => <li>{item}</li>)}
</ul>
#Iterating over list but using a unique component for the items
<ul>
{items.map((item) => <ListItemComponent itemNumber={item} />)}
</ul>
#Containing the entire list inside a component
<ListComponent items={items}/>
</div>;
};
export default Task1;

25
src/2/index.tsx Normal file
View File

@ -0,0 +1,25 @@
import { FunctionComponent, useState } from "react";
function LiveInputComponent(props: any) {
return <input onChange={e => props.setValue(e.target.value)} />
}
function ValueDisplayer(props: any) {
return <p>{props.value}</p>
}
const Task2: FunctionComponent = () => {
const [value, setValue] = useState("");
return (
<div>
<label>Controlled Input: </label>
<LiveInputComponent setValue={setValue}/>
<br />
<br />
<p>#Show Input value here#</p>
<ValueDisplayer value={value}/>
</div>
);
};
export default Task2;

48
src/3/index.tsx Normal file
View File

@ -0,0 +1,48 @@
import { FunctionComponent, useState } from "react";
function LiveInputComponent(props: any) {
return <input onChange={e => props.setValue(e.target.value)} />
}
function ListItemComponent(props: any) {
return <li>{props.itemNumber}</li>;
}
function ListComponent(props: any) {
return <ul>
{mapItems(filterItems(props.items, props.filter))}
</ul>
}
const filterDown = (filter: string) => (word: string) => String(word).includes(filter);
const filterItems = (items: any, filter: any) => items.filter(filterDown(filter));
const mapItems = (filteredItems: any) => filteredItems.map((item: string) => <ListItemComponent itemNumber={item} />);
const Task3: FunctionComponent = () => {
const [inputValue, setInputValue] = useState("");
const [items, setItems] = useState([
"atem",
"btem",
"bbtem",
"dbtem",
"etem",
"ftm",
"gtem",
"hm",
"tm",
"item",
]);
return (
<div>
<label>Search Input: </label>
<LiveInputComponent setValue={setInputValue}/>
<br />
<br />
<ListComponent items={items} filter={inputValue}/>
</div>
);
};
export default Task3;

181
src/4/index.scss Normal file
View File

@ -0,0 +1,181 @@
/* DO NOT CHANGE THIS ROOT CLASS NAME*/
#task-5 {
/* Styles goes here */
padding: 10px 10px;
background: #efefef;
}
#form {
display: flex;
flex-direction: column;
align-items: center;
}
#section {
width: 300px;
display: flex;
flex-direction: column;
}
#button-section {
display: flex;
flex-direction: column;
align-items: end;
}
#section {
}
#input {
border: none;
outline:none;
background: none;
font-size: 18px;
color: #555;
padding:5px 10px 5px 5px;
border-radius: .5rem;
transition: .2s ease-in-out;
box-shadow: inset 2px 2px 2px #cbced1,
inset -2px -2px 2px #ffffff;
&:hover {
box-shadow: inset 2px 2px 2px #cbced1,
inset -2px -2px 2px #ffffff;
}
&:hover {
background: #ffe5a5;
box-shadow: inset 2px 2px 2px #755f3799,
inset -2px -2px 2px #ffefd3b8;
}
&:active {
box-shadow: inset 2px 2px 2px #cbced1,
inset -2px -2px 2px #ffffff;
}
&:focus {
background: #e5f9c4;
border: solid 2px black;
box-shadow: inset 2px 2px 2px #60753fb3, inset -2px -2px 2px #eaf6d7ba;
}
margin-bottom: 20px;
}
#email-label {
color: #444;
font-size: 1rem;
font-weight: 700;
padding-bottom: 5px;
}
#password-label {
color: #444;
font-size: 1rem;
font-weight: 700;
padding-bottom: 5px;
}
#button {
padding: 10px 20px;
background: #efefef;
border: none;
border-radius: .5rem;
color: #444;
font-size: 1rem;
font-weight: 700;
letter-spacing: .2rem;
text-align: center;
outline: none;
cursor: pointer;
transition: .2s ease-in-out;
box-shadow: 2px 2px 2px #cbced1,
-2px -2px 2px #ffffff;
&:hover {
background: #ffe5a5;
box-shadow: 2px 2px 2px #755f3799, -2px -2px 2px #ffefd3b8;
}
&:active {
background: #efefef;
box-shadow: inset 2px 2px 2px #cbced1,
inset -2px -2px 2px #ffffff;
}
&:focus {
background: #e5f9c4;
border: solid 2px black;
box-shadow: 2px 2px 2px #60753fb3, -2px -2px 2px rgb(253 255 250);
}
}
#input {
border: none;
outline:none;
background: none;
font-size: 18px;
color: #555;
padding:5px 10px 5px 5px;
border-radius: .5rem;
transition: .2s ease-in-out;
box-shadow: inset 2px 2px 2px #cbced1,
inset -2px -2px 2px #ffffff;
&:hover {
box-shadow: inset 2px 2px 2px #cbced1,
inset -2px -2px 2px #ffffff;
}
&:hover {
background: #ffe5a5;
box-shadow: inset 2px 2px 2px #755f3799,
inset -2px -2px 2px #ffefd3b8;
}
&:active {
box-shadow: inset 2px 2px 2px #cbced1,
inset -2px -2px 2px #ffffff;
}
&:focus {
box-shadow: inset 2px 2px 2px #cbced1,
inset -2px -2px 2px #ffffff;
}
margin-bottom: 20px;
}
#email-label {
color: #444;
font-size: 1rem;
font-weight: 700;
padding-bottom: 5px;
}
#password-label {
color: #444;
font-size: 1rem;
font-weight: 700;
padding-bottom: 5px;
}
#button {
padding: 10px 20px;
background: #efefef;
border: none;
border-radius: .5rem;
color: #444;
font-size: 1rem;
font-weight: 700;
letter-spacing: .2rem;
text-align: center;
outline: none;
cursor: pointer;
transition: .2s ease-in-out;
box-shadow: 2px 2px 2px #cbced1,
-2px -2px 2px #ffffff;
&:hover {
background: #ffe5a5;
box-shadow: 2px 2px 2px #755f3799, -2px -2px 2px #ffefd3b8;
}
&:active {
background: #efefef;
box-shadow: inset 2px 2px 2px #cbced1,
inset -2px -2px 2px #ffffff;
}
}

46
src/4/index.tsx Normal file
View File

@ -0,0 +1,46 @@
// Style
import { FunctionComponent, useState } from "react";
import "./index.scss";
const Task4: FunctionComponent = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const onSubmit = () => {
// If you want to do something with form submit
alert(`Email: ${email} \nPassword: ${password}`);
};
return (
<div id="task-4">
<form id="form" onSubmit={onSubmit}>
<div id="section">
<label id="email-label">Email</label>
<input
id="input"
name="email"
onChange={(event) => setEmail(event.currentTarget.value)}
placeholder="my@email.com"
value={email}
/>
</div>
<div id="section">
<label id="password-label">Password</label>
<input
id="input"
name="password"
onChange={(event) => setPassword(event.currentTarget.value)}
placeholder="myPassword123"
value={password}
/>
<div id="button-section">
<button id="button">Login</button>
</div>
</div>
</form>
</div>
);
};
export default Task4;

7
src/4/simple_css.scss Normal file
View File

@ -0,0 +1,7 @@
/* DO NOT CHANGE THIS ROOT CLASS NAME*/
#task-5 {
/* Styles goes here */
padding: 10px 10px;
background: #efefef;
}

View File

@ -0,0 +1,11 @@
import { FunctionComponent } from "react";
interface InputProps {
setValue(item: string): any;
}
const Input: FunctionComponent<InputProps> = (props) => {
return <input onChange={e => props.setValue(e.target.value)} />
};
export default Input;

11
src/5/components/Item.tsx Normal file
View File

@ -0,0 +1,11 @@
import { FunctionComponent } from "react";
interface ItemProps {
itemName: string;
}
const Item: FunctionComponent<ItemProps> = (props) => {
return <li>{props.itemName}</li>;
};
export default Item;

22
src/5/components/List.tsx Normal file
View File

@ -0,0 +1,22 @@
import { FunctionComponent } from "react";
// Components
import Item from "./Item";
interface ListProps {
items: string[];
filter: string;
}
const filterDown = (filter: string) => (word: string) => String(word).includes(filter);
const filterItems = (items: any, filter: any) => items.filter(filterDown(filter));
const mapItems = (filteredItems: any) => filteredItems.map((item: string) => <Item itemName={item} />);
const List: FunctionComponent<ListProps> = (props) => {
return <ul id="list">
{mapItems(filterItems(props.items, props.filter))}
</ul>
};
export default List;

31
src/5/index.tsx Normal file
View File

@ -0,0 +1,31 @@
import { FunctionComponent, useState } from "react";
// Components
import Input from "./components/Input";
import List from "./components/List";
const Task5: FunctionComponent = () => {
const [inputValue, setInputValue] = useState("");
const [items, setItems] = useState([
"atem",
"btem",
"bbtem",
"dbtem",
"etem",
"ftm",
"gtem",
"hm",
"tm",
"item",
]);
return (
<div>
<Input setValue={setInputValue}/>
<br />
<List items={items} filter={inputValue}/>
</div>
);
};
export default Task5;

View File

@ -0,0 +1,23 @@
import { FunctionComponent } from "react";
interface AddButtonProps {
items: any[];
nextKey: number;
setNextKey: any;
setItems(items: any[]): any;
newValue: string;
}
function addItem(items: any, nextKey: number, setNextKey: any, setItems: any, newValue: string){
const newList = items.concat({key: nextKey, done: false, value: newValue});
setNextKey(nextKey + 1);
setItems(newList);
}
const AddItemButton: FunctionComponent<AddButtonProps> = (props) => {
return <div id="add-button">
<button id="button" onClick={() => addItem(props.items, props.nextKey, props.setNextKey, props.setItems, props.newValue)}>Add</button>
</div>
};
export default AddItemButton;

View File

@ -0,0 +1,13 @@
import { FunctionComponent } from "react";
interface InputProps {
setValue(item: string): any;
}
const Input: FunctionComponent<InputProps> = (props) => {
return <div id="input-section">
<input id="input" placeholder="New todo..." onChange={e => props.setValue(e.target.value)} />
</div>
};
export default Input;

View File

@ -0,0 +1,11 @@
import { FunctionComponent } from "react";
interface InputProps {
setValue(item: string): any;
}
const Input: FunctionComponent<InputProps> = (props) => {
return <input id="input" placeholder="Filter items..." onChange={e => props.setValue(e.target.value)} />
};
export default Input;

28
src/6/components/Item.tsx Normal file
View File

@ -0,0 +1,28 @@
import { FunctionComponent } from "react";
interface ItemProps {
item: any;
items: any[];
setItems: any;
}
function toggleDone (items: any, setItems: any, key: number) {
setItems((items: any) => items.map( (item: any, i: number) => {
const doneStatus = item.key === key ? !item.done : item.done
return {key: item.key ,done: doneStatus, value: item.value}
}));
}
const Item: FunctionComponent<ItemProps> = (props) => {
return <div id="list-content">
<div id="item-text">
{props.item.done ? "" : props.item.value}
</div>
<button id="button" onClick={ () => toggleDone(props.items, props.setItems, props.item.key) }>&lt;-&gt;</button>
<div id="item-text">
{props.item.done ? props.item.value : ""}
</div>
</div>
};
export default Item;

33
src/6/components/List.tsx Normal file
View File

@ -0,0 +1,33 @@
import { FunctionComponent } from "react";
// Components
import Item from "./Item";
interface ListProps {
items: any[];
filter: string;
setItems: any;
}
function removeById(oldItems: any, setItems: any, key: number) {
setItems ((oldItems: any) => { return oldItems.filter((item: any) => item.key !== key) })
}
const filterDown = (filter: string) => (word: any) => String(word.value).includes(filter);
const filterItems = (items: any, filter: any) => items.filter(filterDown(filter));
const mapItems = (filteredItems: any, setItems: any) => filteredItems.map((item: any, index: number) => {
let listId = index % 2 == 0 ? "list-element" : "list-element-uneven";
return <li key={item.key} id={listId}>
<button id="button" onClick={ () => removeById(filteredItems, setItems, item.key) }>Remove</button>
<Item item={item} items={filteredItems} setItems={setItems} />
</li>
});
const List: FunctionComponent<ListProps> = (props) => {
return <ul id="list">
{mapItems(filterItems(props.items, props.filter), props.setItems)}
</ul>
};
export default List;

143
src/6/index.scss Normal file
View File

@ -0,0 +1,143 @@
/* DO NOT CHANGE THIS ROOT CLASS NAME*/
#task-6 {
background: #efefef;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
#empty {
width: 90px;
}
#input-section {
display: flex;
flex-direction: column;
}
#warning {
margin-left: 20px;
margin-right: 20px;
background: yellow;
text-align: center;
margin-bottom: -10px;
}
#list {
display:flex;
flex-direction: column;
padding: 0px;
}
#top-section {
display:flex;
flex-direction: row;
}
h3 {
text-align: center;
width: 300px;
}
#app {
display: flex;
flex-direction: column;
}
#list-element {
height: 40px;
display:flex;
flex-direction: row;
align-content: center;
}
#list-element-uneven {
height: 40px;
background: #e1e1e1;
display:flex;
flex-direction: row;
align-content: center;
}
#item-text {
width: 300px;
text-align: center;
}
#list-content {
display:flex;
flex-direction: row;
align-items:center;
justify-content: center;
}
#button {
width: 80px;
padding: 5px 10px;
margin: 5px;
background: #efefef;
border: none;
color: #444;
font-size: 0.7rem;
font-weight: 700;
letter-spacing: .2rem;
text-align: center;
outline: none;
cursor: pointer;
transition: .2s ease-in-out;
box-shadow: 2px 2px 2px #cbced1,
-2px -2px 2px #ffffff;
&:hover {
background: #ffe5a5;
box-shadow: 2px 2px 2px #755f3799, -2px -2px 2px #ffefd3b8;
}
&:active {
background: #efefef;
box-shadow: inset 2px 2px 2px #cbced1,
inset -2px -2px 2px #ffffff;
}
}
#input {
margin: 20px;
border: none;
outline:none;
background: none;
font-size: 18px;
color: #555;
padding:5px 10px 5px 5px;
border-radius: .5rem;
transition: .2s ease-in-out;
box-shadow: inset 2px 2px 2px #cbced1,
inset -2px -2px 2px #ffffff;
&:hover {
box-shadow: inset 2px 2px 2px #cbced1,
inset -2px -2px 2px #ffffff;
}
&:hover {
background: #ffe5a5;
box-shadow: inset 2px 2px 2px #755f3799,
inset -2px -2px 2px #ffefd3b8;
}
&:active {
box-shadow: inset 2px 2px 2px #cbced1,
inset -2px -2px 2px #ffffff;
}
&:focus {
box-shadow: inset 2px 2px 2px #cbced1,
inset -2px -2px 2px #ffffff;
}
margin-bottom: 20px;
}
#add-button {
display: flex;
flex-direction: column;
align-items: end;
margin-right:15px;
}

77
src/6/index.tsx Normal file
View File

@ -0,0 +1,77 @@
import { FunctionComponent, useState } from "react";
import Input from "./components/Input";
import AddItemInput from "./components/AddItemInput";
import List from "./components/List";
import AddItemButton from "./components/AddItemButton";
import "./index.scss";
const Empty: FunctionComponent<any> = (props) => {
return <div id="empty"/>
};
const initialItems = [{
key: 0,
done: false,
value: "Get kids",
},
{
key: 1,
done: false,
value: "Do Uniwise assignments",
},
{
key: 2,
done: false,
value: "Get rich",
},
{
key: 3,
done: false,
value: "Die trying",
},
{
key: 4,
done: false,
value: "Vacuum",
},
{
key: 5,
done: false,
value: "Clean dishes",
},]
const NameBar: FunctionComponent<any> = (props) => {
return <div id="top-section">
<Empty/>
<h3>
Pending
</h3>
<Empty/>
<h3>
Done
</h3>
</div>
};
const Task6: React.FunctionComponent = () => {
const [filterValue, setFilterValue] = useState("");
const [newValue, setNewValue] = useState("");
const [items, setItems] = useState(initialItems);
const [nextKey, setNextKey] = useState(6);
return <div id="task-6">
<div id="app">
<Input setValue={setFilterValue}/>
<AddItemInput setValue={setNewValue} />
<AddItemButton items={items} nextKey={nextKey} setNextKey={setNextKey} setItems={setItems} newValue={newValue}/>
<NameBar />
<div id="bottom-section">
<List items={items} filter={filterValue} setItems={setItems}/>
</div>
</div>
</div>;
};
export default Task6;

117
src/6/simple_css.scss Normal file
View File

@ -0,0 +1,117 @@
/* DO NOT CHANGE THIS ROOT CLASS NAME*/
#task-6 {
background: #efefef;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
#empty {
width: 90px;
}
#input-section {
display: flex;
flex-direction: column;
}
#warning {
margin-left: 20px;
margin-right: 20px;
background: yellow;
text-align: center;
margin-bottom: -10px;
}
#list {
display:flex;
flex-direction: column;
padding: 0px;
}
#top-section {
display:flex;
flex-direction: row;
}
h3 {
text-align: center;
width: 300px;
}
#app {
display: flex;
flex-direction: column;
}
#list-element {
height: 40px;
display:flex;
flex-direction: row;
align-content: center;
}
#list-element-uneven {
height: 40px;
background: #e1e1e1;
display:flex;
flex-direction: row;
align-content: center;
}
#item-text {
width: 300px;
text-align: center;
}
#list-content {
display:flex;
flex-direction: row;
align-items:center;
justify-content: center;
}
#button {
width: 80px;
padding: 5px 10px;
margin: 5px;
background: #efefef;
color: #444;
text-align: center;
transition: .2s ease-in-out;
&:hover {
background: #ffe5a5;
}
&:active {
background: #efefef;
}
&:focus {
background: #e5f9c4;
border: solid 2px black;
}
}
#input {
margin: 20px;
color: #555;
padding:5px 10px 5px 5px;
transition: .2s ease-in-out;
&:hover {
background: #ffe5a5;
}
&:focus {
background: #e5f9c4;
}
margin-bottom: 20px;
}
#add-button {
display: flex;
flex-direction: column;
align-items: end;
margin-right:15px;
}

61
src/Intro/index.tsx Normal file
View File

@ -0,0 +1,61 @@
/*
You don't need to change anything in here.
*/
import { FunctionComponent } from "react";
const Intro: FunctionComponent = () => {
return (
<div style={{ textAlign: "left"}}>
<h1>Welcome</h1>
<p>
If you are reading this, you are most likely starting an application
process at Uniwise. In this assignment you will have the opportunity to
show your skills as well as challenge your competencies.
</p>
<h2>Intro</h2>
<p>
Before you get started with the task read the following information.
</p>
<h3>Course of action</h3>
<p>
The task consists of small simple tasks that increase in complexity and
difficulty as you solve them. It is allowed to use code from third party
libraries and npm packages. If you find that a given task is too
difficult or too easy, feel free to skip to the next task. Also feel
free to leave comments with relevant info and to elaborate as much as
you like on a given task. The goal is for you to both show your current
skills and to show your capabilities in solving problems that are new to
you.
</p>
<h3>Technologies</h3>
<p>
This test is based on ReactJS with Typescript. It would be advantageous
if you have or gain knowledge of those before the test. Also SCSS is
used for styling.
</p>
<ul>
<li>
<a href="https://reactjs.org/">ReactJs</a> - The framework
</li>
<li>
<a href="https://www.typescriptlang.org/">Typescript</a> - Typed
javascript
</li>
<li>
<a href="https://sass-lang.com/">
SCSS - CSS with superpowers
</a>
</li>
</ul>
<h3>Get started</h3>
<p>
When you are ready to start you can select a task in the top of the
screen. The associated code wil be found in the corresponding folder
inside the src folder.
</p>
</div>
);
};
export default Intro;

70
src/index.scss Normal file
View File

@ -0,0 +1,70 @@
/*
You don't need to change anything in here.
*/
html,
body {
margin: 0;
padding: 0;
font-family: "Open Sans", sans-serif;
color: #333;
}
h1,
h2,
h3,
h4,
h5 {
font-weight: 600;
margin-top: 0;
}
p {
margin-top: 0;
padding-top: 0;
}
.task-description {
font-weight: 400;
line-height: 1.5;
font-size: 18px;
}
.task-container {
border-radius: 8px;
border: 3px dashed #ddd;
padding: 16px;
}
main {
max-width: 960px;
margin: auto;
padding: 32px;
}
nav.menu {
background-color: #404040;
color: #fff;
padding: 16px;
text-align: center;
a {
display: inline-block;
cursor: pointer;
border-radius: 4px;
background-color: #777;
color: #fff;
padding: 8px 16px;
margin-right: 16px;
transition: background-color 150ms ease;
text-decoration: none;
&:hover {
background-color: #999;
}
&.active {
background-color: #86b111;
}
}
}

212
src/index.tsx Normal file
View File

@ -0,0 +1,212 @@
/*
You don't need to change anything in here.
*/
import { FunctionComponent } from "react";
import ReactDOM from "react-dom/client";
import "./index.scss";
import {
BrowserRouter,
Routes,
Route,
useParams,
Navigate,
} from "react-router-dom";
import Intro from "./Intro";
import { NavLink } from "react-router-dom";
import Task1 from "./1";
import Task2 from "./2";
import Task3 from "./3";
import Task4 from "./4";
import Task5 from "./5";
import Task6 from "./6";
const Menu: FunctionComponent = () => {
return (
<nav className="menu">
<NavLink to="/">Intro</NavLink>
<NavLink to="/task/1">Task 1</NavLink>
<NavLink to="/task/2">Task 2</NavLink>
<NavLink to="/task/3">Task 3</NavLink>
<NavLink to="/task/4">Task 4</NavLink>
<NavLink to="/task/5">Task 5</NavLink>
<NavLink to="/task/6">Task 6</NavLink>
</nav>
);
};
interface ContainerProps {
children: React.ReactNode;
}
const Container: FunctionComponent<ContainerProps> = (props) => {
return (
<>
<Menu />
<main>{props.children}</main>
</>
);
};
interface TaskContainerProps {
children: React.ReactNode;
}
const TaskContainer: FunctionComponent<TaskContainerProps> = (props) => {
return <div className="task-container">{props.children}</div>;
};
const Task: FunctionComponent = () => {
let { id } = useParams<{ id: string }>();
switch (id) {
case "1":
return (
<>
<h1>Task 1 - Create a list</h1>
<p className="task-description">
This first task is purely about using JSX. Make an ordinary
unordered list using 'ul' and li'. The list must{" "}
<b>not be static</b>. You have to <b>use the array</b> in state and{" "}
<b>iterate over</b> it.
</p>
<TaskContainer>
<Task1 />
</TaskContainer>
</>
);
case "2":
return (
<>
<h1>Task 2 - Create a controlled input</h1>
<p className="task-description">
This task is purely about using <b>React's synthetic event</b>{" "}
system. Use the existing input and paragraph to display the{" "}
<b>the input value</b> in the paragraph. The paragraph must be kept
in sync.
</p>
<TaskContainer>
<Task2 />
</TaskContainer>
</>
);
case "3":
return (
<>
<h1>Task 3 - Create a searchable list</h1>
<p className="task-description">
Use the <b>knowledge</b> you used in the <b>previous 2 tasks</b> to
make at searchable list. You must have a <b>input</b> and a{" "}
<b>list</b>. The list should be <b>filtered</b> using the value in
the input as the user types.
</p>
<TaskContainer>
<Task3 />
</TaskContainer>
</>
);
case "4":
return (
<>
<h1>Task 4 - Use styles</h1>
<p className="task-description">
This task is mainly about <b>styling</b> in ReactJS in order to
create a <b>beautiful UI</b>. Use Less to style the form with
interaction feedback such as hover, focus and so on. The goal is to
make the form as aesthetically pleasing as possible.
</p>
<TaskContainer>
<Task4 />
</TaskContainer>
</>
);
case "5":
return (
<>
<h1>Task 5 - Use component composition</h1>
<p className="task-description">
Use the <b>knowledge</b> you used in the <b>previous tasks</b> to
make a searchable list. The requirement is the same as with Task 3.
<br />
<br />
Except, this time you must <b>encapsulate</b> the <b>UI</b> parts
into <b>small components</b>. This means the Input and List goes
into different small components. In order to communicate between the
input and the list, the parent component must be used by
passing props and managing state.
</p>
<TaskContainer>
<Task5 />
</TaskContainer>
</>
);
case "6":
return (
<>
<h1>Task 6 - Create a Todo List and/or Freestyle</h1>
<p className="task-description">
This task is mainly about <b>combining different concepts</b> from
ReactJS in order to create a <b>small and simple application</b>.
<br />
<br />
You can either choose to create a tiny application your self or
follow the description below to create a todo app:
</p>
<ul className="task-description">
Create todos Mark them as done See a list of done todos and a list
of pending todos. Search for todos Delete todos
</ul>
<p className="task-description">
Feel free to use Less to style the applications and to install
third-party packages if needed.
</p>
<TaskContainer>
<Task6 />
</TaskContainer>
</>
);
default:
return <Navigate to="/" />;
}
};
const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement
);
root.render(
<BrowserRouter>
<Routes>
<Route
path=""
element={
<Container>
<Intro />
</Container>
}
/>
<Route
path="task/:id"
element={
<Container>
<Task />
</Container>
}
/>
<Route path="*" element={<Navigate to="/" />} />
</Routes>
</BrowserRouter>
);

1
src/react-app-env.d.ts vendored Normal file
View File

@ -0,0 +1 @@
/// <reference types="react-scripts" />