Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
136 commits
Select commit Hold shift + click to select a range
986b28a
First stab at questions
acbart Feb 2, 2022
2c852d6
Move Question interface to separate file
acbart Feb 6, 2022
dc3662a
Create answer interface
acbart Feb 8, 2022
51221ee
First stab at nested tasks
acbart Feb 8, 2022
3a793cc
Document Question interface
acbart Feb 9, 2022
5c39a97
Expand questions test data
acbart Feb 9, 2022
6ae0b6f
Add a little hint for a tough one
acbart Feb 9, 2022
b1bbbc8
Nested tests (phew)
acbart Feb 9, 2022
3d36619
Forgot the task record!
acbart Feb 19, 2022
44c7d67
Fix typo in editOption test, and missing return type for editOption
acbart Mar 1, 2022
d4d4a78
Update App.tsx
lremmler Sep 1, 2025
475c8e7
Update App.tsx
lremmler Sep 3, 2025
1b65e32
Update App.css
lremmler Sep 6, 2025
0344be5
Update App.css
lremmler Sep 7, 2025
f1cd720
Update App.css
lremmler Sep 8, 2025
85b1d7b
Update App.css
lremmler Sep 8, 2025
f755e64
Update App.tsx
lremmler Sep 9, 2025
6db35f8
Update App.css
lremmler Sep 9, 2025
0afcd8c
Update App.tsx
lremmler Sep 9, 2025
b312540
Create functions.ts
lremmler Sep 9, 2025
05acc40
Create arrays.ts
lremmler Sep 10, 2025
6f452de
Create objects.ts
lremmler Sep 15, 2025
d49f820
Update objects.ts
lremmler Sep 15, 2025
1e30353
Update objects.ts
lremmler Sep 15, 2025
b67630c
Update objects.ts
lremmler Sep 16, 2025
744f79d
Update objects.ts
lremmler Sep 16, 2025
5019737
Update objects.ts
lremmler Sep 16, 2025
9fa4a4f
Update objects.ts
lremmler Sep 16, 2025
787e5c9
Update objects.ts
lremmler Sep 17, 2025
d67d6e3
Update objects.ts
lremmler Sep 17, 2025
c5b2b17
Update objects.ts
lremmler Sep 17, 2025
8e1951a
Update objects.ts
lremmler Sep 17, 2025
5b1ca6d
Update objects.ts
lremmler Sep 18, 2025
7a6d5a5
Update objects.ts
lremmler Sep 18, 2025
3f76b11
Update objects.ts
lremmler Sep 18, 2025
f509ace
Update objects.ts
lremmler Sep 18, 2025
e065776
Update objects.ts
lremmler Sep 18, 2025
c11e2fa
Create questions.json
lremmler Sep 25, 2025
d0bfac2
Update objects.ts
lremmler Sep 25, 2025
548fdf5
Create questions.ts
lremmler Sep 25, 2025
9ab4207
Update objects.ts
lremmler Sep 25, 2025
7719920
Create questions.ts
lremmler Sep 25, 2025
73068b4
Update questions.json
lremmler Sep 25, 2025
d33f1f1
Update questions.json
lremmler Sep 25, 2025
7e2e28c
Update questions.json
lremmler Sep 25, 2025
ad8d11e
Update questions.json
lremmler Sep 25, 2025
7681866
Create global.d.ts
lremmler Sep 25, 2025
7b67a09
Update questions.json
lremmler Sep 25, 2025
fdb7dd2
Create typedQuestions.ts
lremmler Sep 25, 2025
58cc252
Create questions.json.ts
lremmler Sep 25, 2025
0e4a094
Update objects.ts
lremmler Sep 25, 2025
3a237b7
Update objects.ts
lremmler Sep 25, 2025
396a364
Update questions.json.ts
lremmler Sep 25, 2025
f803e25
Update typedQuestions.ts
lremmler Sep 25, 2025
7fa4988
Update global.d.ts
lremmler Sep 25, 2025
a3a075b
Update questions.json.ts
lremmler Sep 25, 2025
7b837bf
Update global.d.ts
lremmler Sep 25, 2025
5e3aaea
Update objects.ts
lremmler Sep 25, 2025
5671736
Update typedQuestions.ts
lremmler Sep 25, 2025
899478d
Update questions.json.ts
lremmler Sep 25, 2025
6290cc2
Update questions.json
lremmler Sep 25, 2025
9782029
Update objects.ts
lremmler Sep 25, 2025
bfbb72a
Update questions.json.ts
lremmler Sep 25, 2025
7fd6684
Update typedQuestions.ts
lremmler Sep 25, 2025
5f0f05d
Update questions.ts
lremmler Sep 25, 2025
1975e0d
Update objects.ts
lremmler Sep 25, 2025
462c22d
Update questions.json.ts
lremmler Sep 25, 2025
4bc0fc3
Update typedQuestions.ts
lremmler Sep 25, 2025
e061f4a
Update global.d.ts
lremmler Sep 25, 2025
1994339
Update typedQuestions.ts
lremmler Sep 25, 2025
aaa299a
Update questions.json.ts
lremmler Sep 25, 2025
4e5e7f5
Update questions.json
lremmler Sep 25, 2025
0462874
Update objects.ts
lremmler Sep 25, 2025
3339469
Update questions.ts
lremmler Sep 25, 2025
2df48f2
Update global.d.ts
lremmler Sep 25, 2025
1a3cb31
Update global.d.ts
lremmler Sep 25, 2025
bd60459
Update questions.ts
lremmler Sep 25, 2025
1e34f74
Update objects.ts
lremmler Sep 25, 2025
831fb37
Update questions.json
lremmler Sep 25, 2025
cb8a711
Update questions.json.ts
lremmler Sep 25, 2025
a1f723d
Update typedQuestions.ts
lremmler Sep 25, 2025
ff675ee
Create tsconfig.json
lremmler Sep 25, 2025
1264762
Update objects.ts
lremmler Sep 25, 2025
878a141
Update questions.ts
lremmler Sep 25, 2025
84d888f
Update objects.ts
lremmler Sep 25, 2025
b8f4824
Update objects.ts
lremmler Sep 25, 2025
2fd602d
Update objects.ts
lremmler Sep 25, 2025
b0ed9bc
Update questions.json.ts
lremmler Sep 25, 2025
9a9c8dc
Update typedQuestions.ts
lremmler Sep 25, 2025
4b5031b
Update objects.ts
lremmler Sep 25, 2025
d537eea
Update objects.ts
lremmler Sep 25, 2025
da03062
Update objects.ts
lremmler Sep 25, 2025
c03ed83
Update objects.ts
lremmler Sep 25, 2025
64933cf
Update objects.ts
lremmler Sep 25, 2025
e9386e3
Update objects.ts
lremmler Sep 25, 2025
07d088a
Update objects.ts
lremmler Sep 25, 2025
f0df6f7
Update objects.ts
lremmler Sep 25, 2025
175cc7b
Create question.ts
lremmler Sep 25, 2025
d24cec5
Create nested.ts
lremmler Sep 26, 2025
d22b78d
Create answer.ts
lremmler Sep 26, 2025
9306c98
Create components
lremmler Sep 26, 2025
c343f36
Delete src/components
lremmler Sep 26, 2025
4f00bc4
Create Counter.tsx
lremmler Sep 26, 2025
bc19218
Create RevealAnswer.tsx
lremmler Sep 26, 2025
627c403
Create ChangeType
lremmler Sep 26, 2025
6fa6156
Create StartAttempt
lremmler Sep 26, 2025
aa2cd02
Create TwoDice
lremmler Sep 26, 2025
fd34472
Create CycleHoliday
lremmler Sep 26, 2025
7f38a0a
Rename CycleHoliday to CycleHoliday.tsx
lremmler Sep 26, 2025
cb2adf2
Rename ChangeType to ChangeType.tsx
lremmler Sep 26, 2025
99cff95
Rename StartAttempt to StartAttempt.tsx
lremmler Sep 26, 2025
b22bf5a
Rename TwoDice to TwoDice.tsx
lremmler Sep 26, 2025
f6d2db2
Update App.tsx
lremmler Sep 26, 2025
d8af9c5
Create package.json
lremmler Sep 26, 2025
a84151e
Update Counter.tsx
lremmler Oct 2, 2025
9046afe
Update App.tsx
lremmler Oct 2, 2025
40d29be
Update Counter.tsx
lremmler Oct 2, 2025
754df09
Update .eslintrc.js
lremmler Oct 2, 2025
878c1d2
Update .eslintrc.js
lremmler Oct 2, 2025
726cf1c
Create .eslintrc.json
lremmler Oct 2, 2025
aba1441
Create .eslintignore
lremmler Oct 2, 2025
b45bf06
Merge branch 'task-nested' into main
lremmler Oct 2, 2025
17aeef4
Update answer.ts
lremmler Oct 2, 2025
4a996b1
Delete src/interfaces/question.ts
lremmler Oct 2, 2025
73499fe
Update questions.ts
lremmler Oct 2, 2025
6244e13
Update Counter.tsx
lremmler Oct 2, 2025
414772d
Update RevealAnswer.tsx
lremmler Oct 2, 2025
6034158
Update ChangeType.tsx
lremmler Oct 2, 2025
7ab2ad5
Update StartAttempt.tsx
lremmler Oct 2, 2025
50e89e3
Update TwoDice.tsx
lremmler Oct 2, 2025
afa318c
Update CycleHoliday.tsx
lremmler Oct 2, 2025
0de0ed9
Update .eslintrc.json
lremmler Oct 2, 2025
e39c92e
Update package.json
lremmler Oct 2, 2025
b8b0664
Update package.json
lremmler Oct 2, 2025
74ae419
Update .eslintrc.json
lremmler Oct 2, 2025
fea51a7
Update package.json
lremmler Oct 2, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
**/*.test.tsx
**/*.test.ts
12 changes: 12 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"extends": ["react-app", "react-app/jest"],
"rules": {},
"overrides": [
{
"files": ["**/*.test.ts", "**/*.test.tsx"],
"rules": {
"testing-library/no-render-in-setup": "off"
}
}
]
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"test": "react-scripts test",
"test:cov": "react-scripts test --coverage --watchAll",
"eject": "react-scripts eject",
"lint": "eslint ./src --ext .tsx --ext .ts --max-warnings 0",
"lint": "eslint ./src --ext .tsx --ext .ts --max-warnings 0 --ignore-pattern \"*.test.ts\" --ignore-pattern \"*.test.tsx\"",
"eslint-output": "eslint-output ./src --ext .tsx --ext .ts --max-warnings 0",
"format": "prettier --config .prettierrc --write src/**/*.{ts,tsx}"
},
Expand Down
5 changes: 5 additions & 0 deletions public/tasks/task-nested.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Task - Nested

Version: 0.0.1

Implement functions that work with nested arrays and objects immutably.
5 changes: 5 additions & 0 deletions public/tasks/task-objects.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Task - Objects

Version: 0.0.1

Implement functions that work with objects immutably.
2 changes: 1 addition & 1 deletion src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

.App-header {
width: 100%;
background-color: #282c34;
background-color: orange;
min-height: 40vh;
display: flex;
flex-direction: column;
Expand Down
75 changes: 74 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,89 @@
import React from "react";
import "./App.css";
import { Button, Container, Row, Col } from "react-bootstrap";
import { Counter } from "./components/Counter";
import { RevealAnswer } from "./components/RevealAnswer";
import { ChangeType } from "./components/ChangeType";
import { StartAttempt } from "./components/StartAttempt";
import { TwoDice } from "./components/TwoDice";
import { CycleHoliday } from "./components/CycleHoliday";

function App(): React.JSX.Element {
return (
<div className="App">
<header className="App-header">
UD CISC275 with React Hooks and TypeScript
UD CISC275 with React Hooks and TypeScript Luke Remmler Hello
World
</header>
<p>
Edit <code>src/App.tsx</code> and save. This page will
automatically reload.
</p>
<h1>Luke Remmler App</h1>
<img
src="../assets/images/pet-ada.jpg"
alt="Dr. Bart's dog Ada"
/>
Unordered List:
<ul>
<li>First thing</li>
<li>Another thing</li>
<li>A third item</li>
</ul>
<Button
onClick={() => {
console.log("Hello World!");
}}
>
Log Hello World
</Button>
<Container>
<Row>
<Col>
<div
style={{
width: "60px",
height: "120px",
backgroundColor: "red",
}}
></div>
</Col>
<Col>
<div
style={{
width: "60px",
height: "120px",
backgroundColor: "red",
}}
></div>
</Col>
</Row>
</Container>

{/* Added Components */}
<hr />
<h2>Counter Component</h2>
<Counter />

<hr />
<h2>Reveal Answer Component</h2>
<RevealAnswer />

<hr />
<h2>Change Type Component</h2>
<ChangeType />

<hr />
<h2>Start Attempt Component</h2>
<StartAttempt />

<hr />
<h2>Two Dice Component</h2>
<TwoDice />

<hr />
<h2>Cycle Holiday Component</h2>
<CycleHoliday />
</div>
);
}
Expand Down
136 changes: 136 additions & 0 deletions src/arrays.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/**
* Consume an array of numbers, and return a new array containing
* JUST the first and last number. If there are no elements, return
* an empty array. If there is one element, the resulting list should
* the number twice.
*/
export function bookEndList(numbers: number[]): number[] {
if (numbers.length === 0) {
return [];
}
if (numbers.length === 1) {
return [numbers[0], numbers[0]];
}
return [numbers[0], numbers[numbers.length - 1]];
}

/**
* Consume an array of numbers, and return a new array where each
* number has been tripled (multiplied by 3).
*/
export function tripleNumbers(numbers: number[]): number[] {
return numbers.map((num) => num * 3);
}

/**
* Consume an array of strings and convert them to integers. If
* the number cannot be parsed as an integer, convert it to 0 instead.
*/
export function stringsToIntegers(numbers: string[]): number[] {
return numbers.map((str) => {
const parsed = parseInt(str, 10);
return isNaN(parsed) ? 0 : parsed;
});
}

/**
* Consume an array of strings and return them as numbers. Note that
* the strings MAY have "$" symbols at the beginning, in which case
* those should be removed. If the result cannot be parsed as an integer,
* convert it to 0 instead.
*/
// Remember, you can write functions as lambdas too! They work exactly the same.
export const removeDollars = (amounts: string[]): number[] => {
return amounts.map((amount) => {
// Remove $ symbol if present
const cleanAmount =
amount.startsWith("$") ? amount.substring(1) : amount;
const parsed = parseInt(cleanAmount, 10);
return isNaN(parsed) ? 0 : parsed;
});
};

/**
* Consume an array of messages and return a new list of the messages. However, any
* string that ends in "!" should be made uppercase. Also, remove any strings that end
* in question marks ("?").
*/
export const shoutIfExclaiming = (messages: string[]): string[] => {
return messages
.filter((message) => !message.endsWith("?"))
.map((message) =>
message.endsWith("!") ? message.toUpperCase() : message,
);
};

/**
* Consumes an array of words and returns the number of words that are LESS THAN
* 4 letters long.
*/
export function countShortWords(words: string[]): number {
return words.filter((word) => word.length < 4).length;
}

/**
* Consumes an array of colors (e.g., 'red', 'purple') and returns true if ALL
* the colors are either 'red', 'blue', or 'green'. If an empty list is given,
* then return true.
*/
export function allRGB(colors: string[]): boolean {
if (colors.length === 0) return true;
return colors.every(
(color) => color === "red" || color === "blue" || color === "green",
);
}

/**
* Consumes an array of numbers, and produces a string representation of the
* numbers being added together along with their actual sum.
*
* For instance, the array [1, 2, 3] would become "6=1+2+3".
* And the array [] would become "0=0".
*/
export function makeMath(addends: number[]): string {
if (addends.length === 0) {
return "0=0";
}

const sum = addends.reduce((total, num) => total + num, 0);
const equation = addends.join("+");

return `${sum}=${equation}`;
}

/**
* Consumes an array of numbers and produces a new array of the same numbers,
* with one difference. After the FIRST negative number, insert the sum of all
* previous numbers in the list. If there are no negative numbers, then append
* the sum to the list.
*
* For instance, the array [1, 9, -5, 7] would become [1, 9, -5, 10, 7]
* And the array [1, 9, 7] would become [1, 9, 7, 17]
*/
export function injectPositive(values: number[]): number[] {
// Find the index of the first negative number
const firstNegativeIndex = values.findIndex((num) => num < 0);

if (firstNegativeIndex === -1) {
// No negative numbers found, append sum to the end
const sum = values.reduce((total, num) => total + num, 0);
return [...values, sum];
} else {
// Calculate sum of numbers before the first negative
const numbersBeforeNegative = values.slice(0, firstNegativeIndex);
const sum = numbersBeforeNegative.reduce(
(total, num) => total + num,
0,
);

// Insert the sum after the first negative number
return [
...values.slice(0, firstNegativeIndex + 1),
sum,
...values.slice(firstNegativeIndex + 1),
];
}
}
15 changes: 15 additions & 0 deletions src/components/ChangeType.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React, { useState } from "react";

export function ChangeType(): JSX.Element {
const [type, setType] = useState<string>("Short Answer");
return (
<div>
<button onClick={() => setType(
type === "Multiple Choice" ? "Short Answer" : "Multiple Choice"
)}>
Change Type
</button>
{type === "Multiple Choice" ? "Multiple Choice" : "Short Answer"}
</div>
);
}
12 changes: 12 additions & 0 deletions src/components/Counter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React, { useState } from "react";

export function Counter(): JSX.Element {
const [value, setValue] = useState<number>(0);
return (
<div>
<button onClick={() => setValue(value + 1)}>Add One</button>
<div>Count: {value}</div>
<button onClick={() => setValue(value - 1)}>Subtract One</button>
</div>
);
}
34 changes: 34 additions & 0 deletions src/components/CycleHoliday.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React, { useState } from "react";

export function CycleHoliday(): JSX.Element {
type Holiday = "🎁" | "🐇" | "🎃" | "🦃" | "🎄";
const [holiday, setHoliday] = useState<Holiday>("🎁");

const byAlphabet: Record<Holiday, Holiday> = {
"🎁": "🐇",
"🐇": "🎃",
"🎃": "🦃",
"🦃": "🎄",
"🎄": "🎁"
};

const byYear: Record<Holiday, Holiday> = {
"🎁": "🐇",
"🐇": "🎃",
"🎃": "🦃",
"🦃": "🎄",
"🎄": "🎁"
};

return (
<div>
<div>Holiday: {holiday}</div>
<button onClick={() => setHoliday(byAlphabet[holiday])}>
Advance by Alphabet
</button>
<button onClick={() => setHoliday(byYear[holiday])}>
Advance by Year
</button>
</div>
);
}
11 changes: 11 additions & 0 deletions src/components/RevealAnswer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React, { useState } from "react";

export function RevealAnswer(): JSX.Element {
const [visible, setVisible] = useState<boolean>(false);
return (
<div>
<button onClick={() => setVisible(!visible)}>Reveal Answer</button>
{visible && <div>42</div>}
</div>
);
}
23 changes: 23 additions & 0 deletions src/components/StartAttempt.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React, { useState } from "react";

export function StartAttempt(): JSX.Element {
const [attempts, setAttempts] = useState<number>(4);
const [progress, setProgress] = useState<boolean>(false);
return (
<div>
<div>{attempts}</div>
<button
onClick={() => {setProgress(true); setAttempts(attempts - 1);}}
disabled={progress || attempts === 0}
>
Start Quiz
</button>
<button onClick={() => setProgress(false)} disabled={!progress}>
Stop Quiz
</button>
<button onClick={() => setAttempts(attempts + 1)} disabled={progress}>
Mulligan
</button>
</div>
);
}
22 changes: 22 additions & 0 deletions src/components/TwoDice.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React, { useState } from "react";

export function TwoDice(): JSX.Element {
const [left, setLeft] = useState<number>(1);
const [right, setRight] = useState<number>(2);
return (
<div>
<div>
<span data-testid="left-die">{left}</span>
<span data-testid="right-die">{right}</span>
</div>
<button onClick={() => setLeft(Math.floor(Math.random() * 6) + 1)}>
Roll Left
</button>
<button onClick={() => setRight(Math.floor(Math.random() * 6) + 1)}>
Roll Right
</button>
{left === right && left === 1 && <div>Lose</div>}
{left === right && left !== 1 && <div>Win</div>}
</div>
);
}
Loading