diff --git a/services/backend/api/api.py b/services/backend/api/api.py
index 4a859c8..2b441cc 100644
--- a/services/backend/api/api.py
+++ b/services/backend/api/api.py
@@ -1,8 +1,40 @@
from fastapi import FastAPI
+from fastapi.middleware.cors import CORSMiddleware
+from .models import Condition, Forecast
+from typing import List, Optional
+from datetime import datetime, timedelta
+import random
app = FastAPI()
+origins = ["http://localhost", "http://localhost:3000"]
+
+app.add_middleware(
+ CORSMiddleware,
+ allow_origins=origins,
+ allow_credentials=True,
+ allow_methods=["*"],
+ allow_headers=["*"],
+)
+
@app.get("/")
async def get_root():
return {"data": "I am a WeatherApp"}
+
+
+@app.get("/forecast/{location}", response_model=List[Forecast])
+async def get_forecast_by_location(
+ location: str, start_date: Optional[datetime] = None, days: int = 5
+):
+ if not start_date:
+ start_date = datetime.now().date()
+ forecasts = []
+ for delta in range(days):
+ forecast_date = start_date + timedelta(days=delta)
+ # Just get a random condition and temp
+ condition = random.choice(list(Condition))
+ temp = round(random.uniform(23, 105), 1)
+ forecast = Forecast(date=forecast_date, condition=condition, temp=temp)
+ forecasts.append(forecast)
+ return forecasts
diff --git a/services/backend/api/models.py b/services/backend/api/models.py
new file mode 100644
index 0000000..ebe1ebb
--- /dev/null
+++ b/services/backend/api/models.py
@@ -0,0 +1,25 @@
+from pydantic import BaseModel
+from datetime import date
+from enum import Enum
+
+
+class Condition(str, Enum):
+ sunny = "sunny"
+ cloudy = "cloudy"
+ partial_cloudy = "partial-cloudy"
+ partial_sunny = "partial-sunny"
+ windy = "windy"
+ lightning = "lightning"
+ snow = "snow"
+ rain = "rain"
+ light_right = "light-rain"
+ heavy_rain = "heavy-rain"
+
+
+class Forecast(BaseModel):
+ date: date
+ condition: Condition
+ temp: float
+
+ class Config:
+ use_enum_values = True
diff --git a/services/backend/tests/test_api.py b/services/backend/tests/test_api.py
index 20ecd29..dbcd1dc 100644
--- a/services/backend/tests/test_api.py
+++ b/services/backend/tests/test_api.py
@@ -7,3 +7,14 @@
def test_root():
response = test_app.get("/")
assert response.status_code == 200
+
+
+def test_forecast():
+ test_location = "San Francisco, CA"
+ days = 10
+ response = test_app.get(f"/forecast/{test_location}?days={days}")
+ assert (
+ response.status_code == 200
+ ), f"Expected response 200, got {response.status_code}: {response.reason}."
+ data = response.json()
+ assert len(data) == days
diff --git a/services/frontend/src/components/WeatherForecast.js b/services/frontend/src/components/WeatherForecast.js
index 3a61ef3..11a4a94 100644
--- a/services/frontend/src/components/WeatherForecast.js
+++ b/services/frontend/src/components/WeatherForecast.js
@@ -1,34 +1,30 @@
import WeatherWidgetContainer from "./WeatherWidgetContainer";
import Header from "./Header";
-import { useState } from "react";
+import { useState, useEffect } from "react";
import PropTypes from "prop-types";
export const WeatherForecast = ({ locationData, defaultExpanded }) => {
- // Placeholder weather data
- const weatherData = [
- {
- temp: 51,
- cond: "cloudy",
- },
- {
- temp: 48,
- cond: "rain",
- },
- {
- temp: 58,
- cond: "windy",
- },
- {
- temp: 62,
- cond: "partial-cloudy",
- },
- {
- temp: 71,
- cond: "sunny",
- },
- ];
-
const [isExpanded, setIsExpanded] = useState(defaultExpanded);
+ const [weatherData, setWeatherData] = useState(null);
+ const [isLoaded, setIsLoaded] = useState(false);
+
+ useEffect(() => {
+ fetch(
+ `http://localhost:8000/forecast/${locationData.city}, ${locationData.state}`
+ )
+ .then((res) => res.json())
+ .then(
+ (result) => {
+ // console.log(result);
+ setWeatherData(result);
+ setIsLoaded(true);
+ },
+ (error) => {
+ console.log(error);
+ // TODO: Add isError state handling
+ }
+ );
+ }, [locationData]);
const toggleExpanded = () => {
setIsExpanded(!isExpanded);
@@ -42,7 +38,11 @@ export const WeatherForecast = ({ locationData, defaultExpanded }) => {
onClick={toggleExpanded}
>
"Loading..."
+ )} ) : (