diff --git a/src/components/App.tsx b/src/components/App.tsx index e67ac33..e83bc08 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -1,5 +1,5 @@ -import React, { useState } from 'react'; -import { QueryClient, QueryClientProvider } from 'react-query'; +import React, { useState, useEffect } from 'react'; +import { useQueryClient, QueryClient, QueryClientProvider, useQuery } from 'react-query'; import './App.css'; import PersonCard from './PersonCard'; import ToggleButton from 'react-bootstrap/ToggleButton'; @@ -7,11 +7,50 @@ import ToggleButtonGroup from 'react-bootstrap/ToggleButtonGroup'; const queryClient = new QueryClient(); +interface CharacterData { + id: string; + name: string; + height: string; + mass: string; + eye_color: string; + hair_color: string; + skin_color: string; +} + function App() { + return ( + + + + ) +} + +function GetPeople() { const [length, setLength] = useState(12); const [favoriteCards, setFavoriteCards] = useState([]); const [showFavorites, setShowFavorites] = useState(false); + const queryClient = useQueryClient() + + const { isLoading, error, data } = useQuery('people', () => + fetch('https://w5c9dy2dg4.execute-api.us-east-2.amazonaws.com/people', { + headers: { + 'Content-Type': 'application/json', + "Access-Control-Allow-Origin": "*", + }, + }).then(res => + res.json() + ) + ); + + useEffect(() => { + if (data) { + setFavoriteCards(data.map(person => parseInt(person.id))); + } + }, [data]); + + console.log(favoriteCards); + const handleInputChange = (event: React.ChangeEvent) => { const value = parseInt(event.target.value); if (!isNaN(value)) { @@ -21,7 +60,6 @@ function App() { } }; - // Call AWS lambda to update DynamoDB here!! const handleFavoriteToggle = (cardIndex: number) => { setFavoriteCards(prevFavorites => prevFavorites.includes(cardIndex) @@ -40,58 +78,56 @@ function App() { : Array.from({ length }, (_, index) => index); return ( - -
-
-

SWAPI React + Typescript Test!

- - Star Wars API - -
-
- - -
- - +
+

SWAPI React + Typescript Test!

+ - - All-Items - - - Favorites - - - -
- {displayedCards.map(index => ( - - ))} -
+ Star Wars API +
+
+
+ +
- + + + + All-Items + + + Favorites + + + +
+ {displayedCards.map(index => ( + + ))} +
+
); } diff --git a/src/components/PersonCard.tsx b/src/components/PersonCard.tsx index affd13b..a9e57b7 100644 --- a/src/components/PersonCard.tsx +++ b/src/components/PersonCard.tsx @@ -1,4 +1,5 @@ -import { useQuery } from 'react-query'; +import React from 'react'; +import { useQuery, useMutation, useQueryClient } from 'react-query'; import Card from 'react-bootstrap/Card'; import ToggleButton from 'react-bootstrap/ToggleButton'; @@ -9,6 +10,7 @@ interface PersonCardProps { } interface CharacterData { + id: string; name: string; height: string; mass: string; @@ -17,17 +19,58 @@ interface CharacterData { skin_color: string; } -function PersonCard({ index, isFavorite, onFavoriteToggle }: PersonCardProps): JSX.Element { +const addPerson = async (id: number, data: CharacterData): Promise => { + data.id = id.toString(); + const response = await fetch(`https://w5c9dy2dg4.execute-api.us-east-2.amazonaws.com/people`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + "Access-Control-Allow-Origin": "*", + }, + body: JSON.stringify(data), + }); + if (!response.ok) { + throw new Error('Network response was not ok'); + } + return response.json(); +} +const deletePerson = async (id: number): Promise => { + const response = await fetch(`https://w5c9dy2dg4.execute-api.us-east-2.amazonaws.com/people/${id}`, { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + "Access-Control-Allow-Origin": "*", + }, + }); + if (!response.ok) { + throw new Error('Network response was not ok'); + } +} + +function PersonCard({ index, isFavorite, onFavoriteToggle }: PersonCardProps): JSX.Element { + const queryClient = useQueryClient(); // api starts at 1 not 0 - const person = index+1; + const person = index + 1; const { isLoading, error, data } = useQuery('getPerson_' + person, () => - fetch('https://swapi.dev/api/people/' + person).then(res => + fetch('https://swapi.dev/api/people/' + person).then(res => res.json() ) ); + const addMutation = useMutation((newData: CharacterData) => addPerson(index, newData), { + onSuccess: () => { + queryClient.invalidateQueries('getPerson_' + person); + }, + }); + + const deleteMutation = useMutation(() => deletePerson(index), { + onSuccess: () => { + queryClient.invalidateQueries('getPerson_' + person); + }, + }); + if (isLoading) return (

Loading...

); if (error) return (

Error fetching data.

); @@ -43,6 +86,11 @@ function PersonCard({ index, isFavorite, onFavoriteToggle }: PersonCardProps): J } const handleFavoriteClick = () => { + if (isFavorite) { + deleteMutation.mutate(); + } else { + addMutation.mutate(data); + } onFavoriteToggle(index); }; @@ -54,6 +102,7 @@ function PersonCard({ index, isFavorite, onFavoriteToggle }: PersonCardProps): J variant={isFavorite ? 'primary' : 'outline-primary'} value={1} onClick={handleFavoriteClick} + disabled={addMutation.isLoading || deleteMutation.isLoading} > {isFavorite ? 'Unfavorite' : 'Favorite'}