From 85ae71af0e8e6b58fbef195887ef7e95c511aa3f Mon Sep 17 00:00:00 2001 From: Mike Date: Mon, 16 Jun 2025 14:15:48 -0400 Subject: [PATCH 1/6] Get all questions --- src/components/App.js | 2 +- src/components/QuestionList.js | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/components/App.js b/src/components/App.js index 4d33c1320..850b8e9cf 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import { useState, useEffect } from "react"; import AdminNavBar from "./AdminNavBar"; import QuestionForm from "./QuestionForm"; import QuestionList from "./QuestionList"; diff --git a/src/components/QuestionList.js b/src/components/QuestionList.js index 4b3701bb2..fb5aec2b6 100644 --- a/src/components/QuestionList.js +++ b/src/components/QuestionList.js @@ -1,10 +1,18 @@ -import React from "react"; +import QuestionItem from './QuestionItem' +import { useState, useEffect } from 'react' function QuestionList() { + const [questions, setQuestions] = useState([]) + + useEffect(() => { + fetch('http://localhost:4000/questions') + .then(r => r.json()) + .then(data => setQuestions(data)) + }, []) return (

Quiz Questions

- +
); } From ff0b6d42666bf34e52ab9da990321fb89bdede0b Mon Sep 17 00:00:00 2001 From: Mike Date: Mon, 16 Jun 2025 14:34:53 -0400 Subject: [PATCH 2/6] Create new question --- db.json | 42 +++++++++++++++++++++++++++++----- src/components/App.js | 11 ++++++++- src/components/QuestionForm.js | 16 +++++++++---- src/components/QuestionList.js | 10 +------- 4 files changed, 59 insertions(+), 20 deletions(-) diff --git a/db.json b/db.json index 73ed95d1a..45b2b6ea1 100644 --- a/db.json +++ b/db.json @@ -3,37 +3,67 @@ { "id": 1, "prompt": "What special prop should always be included for lists of elements?", - "answers": ["id", "name", "key", "prop"], + "answers": [ + "id", + "name", + "key", + "prop" + ], "correctIndex": 2 }, { "id": 2, "prompt": "A React component is a function that returns ______.", - "answers": ["HTML", "JSX", "props", "state"], + "answers": [ + "HTML", + "JSX", + "props", + "state" + ], "correctIndex": 1 }, { "id": 3, "prompt": "Which event handler will run when a user is finished filling out a form?", - "answers": ["onSubmit", "onClick", "onChange", "onForm"], + "answers": [ + "onSubmit", + "onClick", + "onChange", + "onForm" + ], "correctIndex": 0 }, { "id": 4, "prompt": "______ is a tool that transpiles JSX into valid JavaScript.", - "answers": ["React", "Babel", "Webpack", "ES6"], + "answers": [ + "React", + "Babel", + "Webpack", + "ES6" + ], "correctIndex": 1 }, { "id": 5, "prompt": "What syntax makes it possible to unpack values from arrays, or properties from objects, into distinct variables?", - "answers": ["spread", "key-value", "coalescing", "destructuring"], + "answers": [ + "spread", + "key-value", + "coalescing", + "destructuring" + ], "correctIndex": 3 }, { "id": 6, "prompt": "Returning different elements from a component depending on the state of your application is known as _____ rendering.", - "answers": ["voodoo", "conditional", "reactive", "controlled"], + "answers": [ + "voodoo", + "conditional", + "reactive", + "controlled" + ], "correctIndex": 1 } ] diff --git a/src/components/App.js b/src/components/App.js index 850b8e9cf..3b098de7d 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -5,11 +5,20 @@ import QuestionList from "./QuestionList"; function App() { const [page, setPage] = useState("List"); + const [questions, setQuestions] = useState([]) + + const getAllQuestions = () => { + fetch('http://localhost:4000/questions') + .then(r => r.json()) + .then(data => setQuestions(data)) + } + + useEffect(getAllQuestions, []) return (
- {page === "Form" ? : } + {page === "Form" ? : }
); } diff --git a/src/components/QuestionForm.js b/src/components/QuestionForm.js index f02af04e7..bdcb5aba0 100644 --- a/src/components/QuestionForm.js +++ b/src/components/QuestionForm.js @@ -1,14 +1,16 @@ import React, { useState } from "react"; -function QuestionForm(props) { - const [formData, setFormData] = useState({ +function QuestionForm() { + const defaultFormState = { prompt: "", answer1: "", answer2: "", answer3: "", answer4: "", correctIndex: 0, - }); + } + const [formData, setFormData] = useState(defaultFormState); + function handleChange(event) { setFormData({ @@ -19,7 +21,13 @@ function QuestionForm(props) { function handleSubmit(event) { event.preventDefault(); - console.log(formData); + const { prompt, answer1, answer2, answer3, answer4 } = formData + if (prompt && answer1 && answer2 && answer3 && answer4) { + fetch('http://localhost:4000/questions', { method: 'POST', headers: { "Content-Type": "application/json" }, body: JSON.stringify(formData) }) + .then(setFormData(defaultFormState)).catch(console.error) + } else { + console.log('Please fill out all fields in order to create question.') + } } return ( diff --git a/src/components/QuestionList.js b/src/components/QuestionList.js index fb5aec2b6..5b715c38f 100644 --- a/src/components/QuestionList.js +++ b/src/components/QuestionList.js @@ -1,14 +1,6 @@ import QuestionItem from './QuestionItem' -import { useState, useEffect } from 'react' -function QuestionList() { - const [questions, setQuestions] = useState([]) - - useEffect(() => { - fetch('http://localhost:4000/questions') - .then(r => r.json()) - .then(data => setQuestions(data)) - }, []) +function QuestionList({ questions }) { return (

Quiz Questions

From 6fd8a4a3ce7a6c14dc579511a47a9ee27461df90 Mon Sep 17 00:00:00 2001 From: Mike Date: Mon, 16 Jun 2025 14:42:24 -0400 Subject: [PATCH 3/6] New form now saving correctly --- .gitignore | 1 + db.json | 13 ++++++++++++- src/components/App.js | 2 +- src/components/QuestionForm.js | 22 ++++++++++++++++------ 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index ae56e3810..880cd9b4b 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,4 @@ yarn-error.log* # Ignore ESLint files .eslintcache +db.json \ No newline at end of file diff --git a/db.json b/db.json index 45b2b6ea1..341dca8bc 100644 --- a/db.json +++ b/db.json @@ -65,6 +65,17 @@ "controlled" ], "correctIndex": 1 + }, + { + "prompt": "How is this working", + "answers": [ + "great", + "not great", + "so great", + "it's not" + ], + "correctIndex": 0, + "id": 7 } ] -} +} \ No newline at end of file diff --git a/src/components/App.js b/src/components/App.js index 3b098de7d..3c15830fd 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -13,7 +13,7 @@ function App() { .then(data => setQuestions(data)) } - useEffect(getAllQuestions, []) + useEffect(getAllQuestions, [page]) return (
diff --git a/src/components/QuestionForm.js b/src/components/QuestionForm.js index bdcb5aba0..0a7692ad7 100644 --- a/src/components/QuestionForm.js +++ b/src/components/QuestionForm.js @@ -8,10 +8,9 @@ function QuestionForm() { answer3: "", answer4: "", correctIndex: 0, - } + }; const [formData, setFormData] = useState(defaultFormState); - function handleChange(event) { setFormData({ ...formData, @@ -21,12 +20,23 @@ function QuestionForm() { function handleSubmit(event) { event.preventDefault(); - const { prompt, answer1, answer2, answer3, answer4 } = formData + const { prompt, answer1, answer2, answer3, answer4, correctIndex } = + formData; if (prompt && answer1 && answer2 && answer3 && answer4) { - fetch('http://localhost:4000/questions', { method: 'POST', headers: { "Content-Type": "application/json" }, body: JSON.stringify(formData) }) - .then(setFormData(defaultFormState)).catch(console.error) + const formatedFormData = { + prompt, + answers: [answer1, answer2, answer3, answer4], + correctIndex, + }; + fetch("http://localhost:4000/questions", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(formatedFormData), + }) + .then(setFormData(defaultFormState)) + .catch(console.error); } else { - console.log('Please fill out all fields in order to create question.') + console.log("Please fill out all fields in order to create question."); } } From b8310db1e1b7bf582f3d2d22723278df1502a131 Mon Sep 17 00:00:00 2001 From: Mike Date: Mon, 16 Jun 2025 14:49:33 -0400 Subject: [PATCH 4/6] Delete question and refresh state --- db.json | 11 ----------- src/components/App.js | 2 +- src/components/QuestionItem.js | 11 +++++++++-- src/components/QuestionList.js | 4 ++-- 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/db.json b/db.json index 341dca8bc..ad49dbeb5 100644 --- a/db.json +++ b/db.json @@ -65,17 +65,6 @@ "controlled" ], "correctIndex": 1 - }, - { - "prompt": "How is this working", - "answers": [ - "great", - "not great", - "so great", - "it's not" - ], - "correctIndex": 0, - "id": 7 } ] } \ No newline at end of file diff --git a/src/components/App.js b/src/components/App.js index 3c15830fd..8feb46247 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -18,7 +18,7 @@ function App() { return (
- {page === "Form" ? : } + {page === "Form" ? : }
); } diff --git a/src/components/QuestionItem.js b/src/components/QuestionItem.js index ab5e8e820..678943765 100644 --- a/src/components/QuestionItem.js +++ b/src/components/QuestionItem.js @@ -1,6 +1,6 @@ import React from "react"; -function QuestionItem({ question }) { +function QuestionItem({ question, setQuestions }) { const { id, prompt, answers, correctIndex } = question; const options = answers.map((answer, index) => ( @@ -9,6 +9,13 @@ function QuestionItem({ question }) { )); + const handleDelete = (event) => { + event.preventDefault() + fetch(`http://localhost:4000/questions/${id}`, { method: 'DELETE', headers: { "Accepts": "application/json" }, }) + .then(r => r.json()) + .then(setQuestions(questions => questions.filter(q => q.id !== id))) + } + return (
  • Question {id}

    @@ -17,7 +24,7 @@ function QuestionItem({ question }) { Correct Answer: - +
  • ); } diff --git a/src/components/QuestionList.js b/src/components/QuestionList.js index 5b715c38f..3faf3d68e 100644 --- a/src/components/QuestionList.js +++ b/src/components/QuestionList.js @@ -1,10 +1,10 @@ import QuestionItem from './QuestionItem' -function QuestionList({ questions }) { +function QuestionList({ questions, setQuestions }) { return (

    Quiz Questions

    -
      {questions.map(question => )}
    +
      {questions.map(question => )}
    ); } From f3000cc42982c64916c8cc33f1b5cb15f7fb0161 Mon Sep 17 00:00:00 2001 From: Mike Date: Mon, 16 Jun 2025 15:06:37 -0400 Subject: [PATCH 5/6] Update correct answer on click --- db.json | 4 +-- src/components/QuestionItem.js | 61 +++++++++++++++++++++------------- 2 files changed, 40 insertions(+), 25 deletions(-) diff --git a/db.json b/db.json index ad49dbeb5..6d964418b 100644 --- a/db.json +++ b/db.json @@ -9,7 +9,7 @@ "key", "prop" ], - "correctIndex": 2 + "correctIndex": 3 }, { "id": 2, @@ -31,7 +31,7 @@ "onChange", "onForm" ], - "correctIndex": 0 + "correctIndex": 2 }, { "id": 4, diff --git a/src/components/QuestionItem.js b/src/components/QuestionItem.js index 678943765..cc74c318e 100644 --- a/src/components/QuestionItem.js +++ b/src/components/QuestionItem.js @@ -1,32 +1,47 @@ import React from "react"; function QuestionItem({ question, setQuestions }) { - const { id, prompt, answers, correctIndex } = question; + const { id, prompt, answers, correctIndex } = question; - const options = answers.map((answer, index) => ( - - )); + const options = answers.map((answer, index) => ( + + )); - const handleDelete = (event) => { - event.preventDefault() - fetch(`http://localhost:4000/questions/${id}`, { method: 'DELETE', headers: { "Accepts": "application/json" }, }) - .then(r => r.json()) - .then(setQuestions(questions => questions.filter(q => q.id !== id))) - } + const handleDelete = (event) => { + event.preventDefault(); + fetch(`http://localhost:4000/questions/${id}`, { + method: "DELETE", + headers: { Accepts: "application/json" }, + }) + .then((r) => r.json()) + .then(setQuestions((questions) => questions.filter((q) => q.id !== id))); + }; - return ( -
  • -

    Question {id}

    -
    Prompt: {prompt}
    - - -
  • - ); + const updateCorrectAnswer = (e) => { + fetch(`http://localhost:4000/questions/${id}`, { + method: "PATCH", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ correctIndex: Number.parseInt(e.target.value) }), + }) + .then((r) => r.json()) + .then(setQuestions((questions) => questions)); + }; + + return ( +
  • +

    Question {id}

    +
    Prompt: {prompt}
    + + +
  • + ); } export default QuestionItem; From 2b45184fce50356fd2864952660fa5a0a6217dc3 Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 20 Jun 2025 16:18:07 -0400 Subject: [PATCH 6/6] Fix spacing --- src/components/QuestionItem.js | 74 +++++++++++++++++----------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/src/components/QuestionItem.js b/src/components/QuestionItem.js index cc74c318e..0683deca3 100644 --- a/src/components/QuestionItem.js +++ b/src/components/QuestionItem.js @@ -1,47 +1,47 @@ import React from "react"; function QuestionItem({ question, setQuestions }) { - const { id, prompt, answers, correctIndex } = question; + const { id, prompt, answers, correctIndex } = question; - const options = answers.map((answer, index) => ( - - )); + const options = answers.map((answer, index) => ( + + )); - const handleDelete = (event) => { - event.preventDefault(); - fetch(`http://localhost:4000/questions/${id}`, { - method: "DELETE", - headers: { Accepts: "application/json" }, - }) - .then((r) => r.json()) - .then(setQuestions((questions) => questions.filter((q) => q.id !== id))); - }; + const handleDelete = (event) => { + event.preventDefault(); + fetch(`http://localhost:4000/questions/${id}`, { + method: "DELETE", + headers: { Accepts: "application/json" }, + }) + .then((r) => r.json()) + .then(setQuestions((questions) => questions.filter((q) => q.id !== id))); + }; - const updateCorrectAnswer = (e) => { - fetch(`http://localhost:4000/questions/${id}`, { - method: "PATCH", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ correctIndex: Number.parseInt(e.target.value) }), - }) - .then((r) => r.json()) - .then(setQuestions((questions) => questions)); - }; + const updateCorrectAnswer = (e) => { + fetch(`http://localhost:4000/questions/${id}`, { + method: "PATCH", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ correctIndex: Number.parseInt(e.target.value) }), + }) + .then((r) => r.json()) + .then(setQuestions((questions) => questions)); + }; - return ( -
  • -

    Question {id}

    -
    Prompt: {prompt}
    - - -
  • - ); + return ( +
  • +

    Question {id}

    +
    Prompt: {prompt}
    + + +
  • + ); } export default QuestionItem;