From 8a1877117eb68e75e6b0e12c722161b99e7c20fe Mon Sep 17 00:00:00 2001 From: Carlo Ace Sagad Date: Wed, 25 Sep 2024 05:05:28 -0400 Subject: [PATCH 1/5] Finished Code --- src/App.css | 37 ++++++++++++++++++++++++--- src/App.jsx | 73 +++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 96 insertions(+), 14 deletions(-) diff --git a/src/App.css b/src/App.css index c7f4da8..296d56c 100644 --- a/src/App.css +++ b/src/App.css @@ -1,6 +1,35 @@ .App-header { - background-color: #222; - padding: 20px; - color: white; - text-align: center; + background-color: #222; + padding: 20px; + color: white; + text-align: center; +} + +.city-box { + border: 1px solid #ccc; + padding: 15px; + margin-top: 10px; + background-color: #f9f9f9; + border-radius: 8px; + box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.1); +} + +.city-box h3 { + margin-bottom: 5px; +} + +.city-box p { + margin: 5px 0; +} + +.App-header { + text-align: center; + margin-bottom: 20px; +} + +input { + width: 100%; + padding: 10px; + margin: 10px 0; + box-sizing: border-box; } diff --git a/src/App.jsx b/src/App.jsx index 6478b09..528acd7 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,26 +1,79 @@ -import { useState } from "react"; +import { useState, useEffect } from "react"; import "./App.css"; -function City(props) { - return
This is the City component
; +function City({ city }) { + return ( +
+

+ {city.City}, {city.State} +

+

State: {city.State}

+

+ Location: ({city.Lat}, {city.Long}) +

+

Population (estimated): {city.EstimatedPopulation}

+

Total Wages: {city.TotalWages}

+
+ ); } -function ZipSearchField(props) { - return
This is the ZipSearchField component
; +function ZipSearchField({ onZipChange }) { + return ( +
+ + onZipChange(e.target.value)} + placeholder="Enter Zip Code" + /> +
+ ); } function App() { + const [zipCode, setZipCode] = useState(""); + const [cities, setCities] = useState([]); + const [error, setError] = useState(false); + + useEffect(() => { + if (zipCode.length === 5) { + fetch(`https://ctp-zip-code-api.onrender.com/zip/${zipCode}`) + .then((response) => { + if (response.ok) { + return response.json(); + } else { + throw new Error("No results found"); + } + }) + .then((data) => { + setCities(data); + setError(false); + }) + .catch(() => { + setCities([]); + setError(true); + }); + } else { + setCities([]); + } + }, [zipCode]); + return (

Zip Code Search

- -
- - -
+ + {error ? ( +
No results found
+ ) : ( +
+ {cities.map((city) => ( + + ))} +
+ )}
); From 95536865d8ff83e4b4c3c131310b8c5b6c555bce Mon Sep 17 00:00:00 2001 From: Carlo Ace Sagad Date: Wed, 25 Sep 2024 05:38:58 -0400 Subject: [PATCH 2/5] changed city to cityData so its not confusing --- src/App.jsx | 56 +++++++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 528acd7..3b8fc00 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,18 +1,18 @@ import { useState, useEffect } from "react"; import "./App.css"; -function City({ city }) { +function City({ cityData }) { return (

- {city.City}, {city.State} + {cityData.City}, {cityData.State}

-

State: {city.State}

+

State: {cityData.State}

- Location: ({city.Lat}, {city.Long}) + Location: ({cityData.Lat}, {cityData.Long})

-

Population (estimated): {city.EstimatedPopulation}

-

Total Wages: {city.TotalWages}

+

Population (estimated): {cityData.EstimatedPopulation}

+

Total Wages: {cityData.TotalWages}

); } @@ -36,26 +36,28 @@ function App() { const [error, setError] = useState(false); useEffect(() => { - if (zipCode.length === 5) { - fetch(`https://ctp-zip-code-api.onrender.com/zip/${zipCode}`) - .then((response) => { - if (response.ok) { - return response.json(); - } else { - throw new Error("No results found"); - } - }) - .then((data) => { - setCities(data); - setError(false); - }) - .catch(() => { - setCities([]); - setError(true); - }); - } else { - setCities([]); - } + const fetchCityData = async () => { + if (zipCode.length !== 5) { + setCities([]); + return; + } + + try { + const response = await fetch( + `https://ctp-zip-code-api.onrender.com/zip/${zipCode}` + ); + if (!response.ok) throw new Error("No results found"); + + const data = await response.json(); + setCities(data); + setError(false); + } catch { + setCities([]); + setError(true); + } + }; + + fetchCityData(); }, [zipCode]); return ( @@ -70,7 +72,7 @@ function App() { ) : (
{cities.map((city) => ( - + ))}
)} From 0b62d35d3d65ef4839164916311372bc86e9155f Mon Sep 17 00:00:00 2001 From: Carlo Ace Sagad Date: Wed, 25 Sep 2024 18:23:17 -0400 Subject: [PATCH 3/5] Added some comments --- src/App.jsx | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 3b8fc00..b123cb3 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -24,6 +24,7 @@ function ZipSearchField({ onZipChange }) { onZipChange(e.target.value)} + //onZipChange prop (a function passed from the parent component) to notify the parent whenever the user changes the input value. placeholder="Enter Zip Code" /> @@ -36,8 +37,12 @@ function App() { const [error, setError] = useState(false); useEffect(() => { + //Hook for Fetching Data + // Hook that runs whenever the zipCode changes. const fetchCityData = async () => { + // Asynchronous function to fetch city data. if (zipCode.length !== 5) { + // If the zip code is not 5 characters long, clear the cities list. setCities([]); return; } @@ -46,19 +51,19 @@ function App() { const response = await fetch( `https://ctp-zip-code-api.onrender.com/zip/${zipCode}` ); - if (!response.ok) throw new Error("No results found"); + if (!response.ok) throw new Error("No results found"); // If the response is not ok, throw an error. - const data = await response.json(); - setCities(data); - setError(false); + const data = await response.json(); // Parse the response JSON. + setCities(data); // Set the cities state with the fetched data. + setError(false); // Clear any previous error state. } catch { - setCities([]); - setError(true); + setCities([]); // If there's an error, clear the cities state. + setError(true); // Set the error state to true. } }; - fetchCityData(); - }, [zipCode]); + fetchCityData(); // Call the fetchCityData function. + }, [zipCode]); // Only re-run this effect when "zipCode" changes. return (
@@ -73,6 +78,8 @@ function App() {
{cities.map((city) => ( + //key prop is a special attribute in React that helps React identify which items have changed, are added, or are removed + //city.RecordNumber is used as a unique identifier for each City component ))}
)} From 3246df4018b562e1f2e36a22e6f1f13fdc228c65 Mon Sep 17 00:00:00 2001 From: Carlo Ace Sagad Date: Sun, 13 Oct 2024 19:44:51 -0400 Subject: [PATCH 4/5] Remove base URL for deployment --- vite.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vite.config.js b/vite.config.js index 97f4bc5..ee6a7b2 100644 --- a/vite.config.js +++ b/vite.config.js @@ -4,5 +4,5 @@ import react from "@vitejs/plugin-react"; // https://vitejs.dev/config/ export default defineConfig({ plugins: [react()], - base: "/lab-react-zip-search/", + // base: "/lab-react-zip-search/", // Remove this line for Netlify/Vercel }); From f9ea7abba965c3a46a3aa030306f607d4b326066 Mon Sep 17 00:00:00 2001 From: Carlo Ace Sagad Date: Sun, 13 Oct 2024 19:52:13 -0400 Subject: [PATCH 5/5] changed the design --- src/App.jsx | 83 +++++++++++++++++++++++++++++------------------------ 1 file changed, 46 insertions(+), 37 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index b123cb3..07dcb1e 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from "react"; +import { useState } from "react"; import "./App.css"; function City({ cityData }) { @@ -17,16 +17,20 @@ function City({ cityData }) { ); } -function ZipSearchField({ onZipChange }) { +function ZipSearchField({ zipCode, setZipCode, onSearch }) { return ( -
- +
+ onZipChange(e.target.value)} - //onZipChange prop (a function passed from the parent component) to notify the parent whenever the user changes the input value. + value={zipCode} + onChange={(e) => setZipCode(e.target.value)} placeholder="Enter Zip Code" + style={{ padding: "10px", fontSize: "1.2em", marginRight: "10px" }} /> +
); } @@ -36,50 +40,55 @@ function App() { const [cities, setCities] = useState([]); const [error, setError] = useState(false); - useEffect(() => { - //Hook for Fetching Data - // Hook that runs whenever the zipCode changes. - const fetchCityData = async () => { - // Asynchronous function to fetch city data. - if (zipCode.length !== 5) { - // If the zip code is not 5 characters long, clear the cities list. - setCities([]); - return; - } + const fetchCityData = async () => { + if (zipCode.length !== 5) { + setCities([]); + setError(true); + return; + } - try { - const response = await fetch( - `https://ctp-zip-code-api.onrender.com/zip/${zipCode}` - ); - if (!response.ok) throw new Error("No results found"); // If the response is not ok, throw an error. + try { + const response = await fetch( + `https://ctp-zip-code-api.onrender.com/zip/${zipCode}` + ); + if (!response.ok) throw new Error("No results found"); - const data = await response.json(); // Parse the response JSON. - setCities(data); // Set the cities state with the fetched data. - setError(false); // Clear any previous error state. - } catch { - setCities([]); // If there's an error, clear the cities state. - setError(true); // Set the error state to true. - } - }; + const data = await response.json(); + setCities(data); + setError(false); + } catch { + setCities([]); + setError(true); + } + }; - fetchCityData(); // Call the fetchCityData function. - }, [zipCode]); // Only re-run this effect when "zipCode" changes. + const handleSearch = () => { + fetchCityData(); + }; return ( -
-
+
+

Zip Code Search

-
- +
+ {error ? (
No results found
) : (
{cities.map((city) => ( - //key prop is a special attribute in React that helps React identify which items have changed, are added, or are removed - //city.RecordNumber is used as a unique identifier for each City component ))}
)}