Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added functionality #3

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
76 changes: 74 additions & 2 deletions backend/main.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,85 @@
package main

import "net/http"
import (
"encoding/json"
"net/http"
)

// define the Model for a To Do item
type ToDoItem struct {
Title string `json:"title"`
Description string `json:"description"`
}

// store ToDoItem using a slice named ToDoItems
var ToDoItems []ToDoItem

func main() {
// Your code here
http.HandleFunc("/", ToDoListHandler)
http.ListenAndServe(":8080", nil)

}

func ToDoListHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")

// Your code here
if r.Method == http.MethodOptions {
w.WriteHeader(http.StatusOK)
return
}

// define what function to call if we get a GET request
if r.Method == http.MethodGet {
// define what function to call if we get a GET request
GetList(w, r)
} else if r.Method == http.MethodPost {
// define what function to call if we get a POST request
AddToList(w, r)
} else {
// error handling for if we recieve any other kind of requesy
http.Error(w, "Invalid Method", http.StatusMethodNotAllowed)

}

}

func GetList(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
// return empty slice to avoid null map error on frontend
if len(ToDoItems) == 0 {
_, _ = w.Write([]byte("[]"))
return
}

// return the to do items or an error if there is one
if err := json.NewEncoder(w).Encode(ToDoItems); err != nil {
http.Error(w, `{"error": "Internal Server Error"}`, http.StatusInternalServerError)
}
}

func AddToList(w http.ResponseWriter, r *http.Request) {
var newToDo ToDoItem // initialise new to do item

// check if the givn to do can be decoded into a ToDoItem
if err := json.NewDecoder(r.Body).Decode(&newToDo); err != nil {
// if it cannot we return a invalid input error
http.Error(w, "Invalid Input", http.StatusBadRequest)
return
}

// check if title or description are empty
if newToDo.Title == "" || newToDo.Description == "" {
// if they are we return a bad request
http.Error(w, "Title and Description are required fields", http.StatusBadRequest)
return
}

// append the new item into memory/ storage if all is well
ToDoItems = append(ToDoItems, newToDo)

// return an OK status
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(ToDoItems)
}
3 changes: 2 additions & 1 deletion frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"@types/react-dom": "^18.2.14",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"react-scripts": "^5.0.1",
"typescript": "^4.9.5",
"web-vitals": "^2.1.4"
},
Expand Down
41 changes: 38 additions & 3 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import Todo, { TodoType } from './Todo';

function App() {
const [todos, setTodos] = useState<TodoType[]>([]);
const [title, setTitle] = useState("");
const [description, setDescription] = useState("");

// Initially fetch todo
useEffect(() => {
Expand All @@ -24,6 +26,39 @@ function App() {
fetchTodos()
}, []);

// handle posting a new To-Do
const postToDo = async () => {
if (!title || !description) {
alert("Title and description are required!");
return;
}

const newToDo = { title, description };

try {
const response = await fetch('http://localhost:8080/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(newToDo),
});

if (!response.ok) {
const errorMessage = await response.text();
console.log(errorMessage);
}

// update the list with the new item
const updatedTodos = await response.json();
setTodos(updatedTodos);

} catch (error) {
console.log(error);
}
};


return (
<div className="app">
<header className="app-header">
Expand All @@ -42,9 +77,9 @@ function App() {

<h2>Add a Todo</h2>
<form>
<input placeholder="Title" name="title" autoFocus={true} />
<input placeholder="Description" name="description" />
<button>Add Todo</button>
<input onChange={(e) => setTitle(e.target.value)} placeholder="Title" name="title" autoFocus={true} />
<input onChange={(e) => setDescription(e.target.value)} placeholder="Description" name="description" />
<button onClick={(e) => { e.preventDefault(); postToDo()}}>Add Todo</button>
</form>
</div>
);
Expand Down