7 changed files with 309 additions and 38 deletions
@ -0,0 +1,48 @@ |
|||
.modal { |
|||
display: block; /* Shown by default */ |
|||
position: fixed; /* Stay in place */ |
|||
z-index: 1; /* Sit on top */ |
|||
left: 0; |
|||
top: 0; |
|||
width: 100%; /* Full width */ |
|||
height: 100%; /* Full height */ |
|||
overflow: auto; /* Enable scroll if needed */ |
|||
background-color: rgb(0,0,0); /* Fallback color */ |
|||
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */ |
|||
} |
|||
|
|||
/* Modal Content/Box */ |
|||
.modal-content { |
|||
background-color: #fefefe; |
|||
margin: 15% auto; /* 15% from the top and centered */ |
|||
padding: 20px; |
|||
border: 1px solid #888; |
|||
width: 50%; /* Could be more or less, depending on screen size */ |
|||
} |
|||
|
|||
/* The Close Button */ |
|||
.close { |
|||
color: #aaa; |
|||
float: right; |
|||
font-size: 28px; |
|||
font-weight: bold; |
|||
} |
|||
|
|||
.close:hover, |
|||
.close:focus { |
|||
color: black; |
|||
text-decoration: none; |
|||
cursor: pointer; |
|||
} |
|||
|
|||
.detail-weather-image { |
|||
height: 256px; |
|||
width: 256px; |
|||
display: block; |
|||
margin-left: auto; |
|||
margin-right: auto; |
|||
} |
|||
|
|||
.label { |
|||
padding-right: 10px; |
|||
} |
|||
@ -0,0 +1,137 @@ |
|||
import './DetailModal.css' |
|||
import moment from "moment"; |
|||
|
|||
function DetailModal(props) { |
|||
|
|||
const weather = props.weather |
|||
let url = `http://localhost:3001/images/${weather.summary.replaceAll(' ', '_')}.png` |
|||
let formattedDate = moment(weather.date).format("DD/MM/YYYY HH:mm:ss") |
|||
let temperature = Math.round((weather.temperature + Number.EPSILON) * 100) / 100 |
|||
let apparentTemperature = Math.round((weather.apparentTemperature + Number.EPSILON) * 100) / 100 |
|||
|
|||
return ( |
|||
<div id="myModal" className="modal"> |
|||
|
|||
<div className="modal-content"> |
|||
<span className="close" onClick={props.handleClick}>×</span> |
|||
<div className="w3-row"> |
|||
<div className="w3-col"> |
|||
<img src={url} alt={weather.summary} className="detail-weather-image"/> |
|||
</div> |
|||
</div> |
|||
|
|||
<div className="w3-row"> |
|||
<div className="w3-half w3-right-align"> |
|||
<span className="label">Device ID</span> |
|||
</div> |
|||
<div className="w3-half w3-left-align"> |
|||
<span>{weather.deviceId}</span> |
|||
</div> |
|||
</div> |
|||
|
|||
<div className="w3-row"> |
|||
<div className="w3-half w3-right-align"> |
|||
<span className="label">Date</span> |
|||
</div> |
|||
<div className="w3-half w3-left-align"> |
|||
<span>{formattedDate}</span> |
|||
</div> |
|||
</div> |
|||
|
|||
<div className="w3-row"> |
|||
<div className="w3-half w3-right-align"> |
|||
<span className="label">Summary</span> |
|||
</div> |
|||
<div className="w3-half w3-left-align"> |
|||
<span>{weather.summary}</span> |
|||
</div> |
|||
</div> |
|||
|
|||
<div className="w3-row"> |
|||
<div className="w3-half w3-right-align"> |
|||
<span className="label">Precip. Type</span> |
|||
</div> |
|||
<div className="w3-half w3-left-align"> |
|||
<span>{weather.precipType}</span> |
|||
</div> |
|||
</div> |
|||
|
|||
<div className="w3-row"> |
|||
<div className="w3-half w3-right-align"> |
|||
<span className="label">Temperature</span> |
|||
</div> |
|||
<div className="w3-half w3-left-align"> |
|||
<span>{temperature}℃</span> |
|||
</div> |
|||
</div> |
|||
|
|||
<div className="w3-row"> |
|||
<div className="w3-half w3-right-align"> |
|||
<span className="label">Apparent Temperature</span> |
|||
</div> |
|||
<div className="w3-half w3-left-align"> |
|||
<span>{apparentTemperature}℃</span> |
|||
</div> |
|||
</div> |
|||
|
|||
<div className="w3-row"> |
|||
<div className="w3-half w3-right-align"> |
|||
<span className="label">Humidity</span> |
|||
</div> |
|||
<div className="w3-half w3-left-align"> |
|||
<span>{weather.humidity}</span> |
|||
</div> |
|||
</div> |
|||
|
|||
<div className="w3-row"> |
|||
<div className="w3-half w3-right-align"> |
|||
<span className="label">Wind Bearing</span> |
|||
</div> |
|||
<div className="w3-half w3-left-align"> |
|||
<span>{weather.windBearing}</span> |
|||
</div> |
|||
</div> |
|||
|
|||
<div className="w3-row"> |
|||
<div className="w3-half w3-right-align"> |
|||
<span className="label">Visibility</span> |
|||
</div> |
|||
<div className="w3-half w3-left-align"> |
|||
<span>{weather.visibility}</span> |
|||
</div> |
|||
</div> |
|||
|
|||
<div className="w3-row"> |
|||
<div className="w3-half w3-right-align"> |
|||
<span className="label">Loud Cover</span> |
|||
</div> |
|||
<div className="w3-half w3-left-align"> |
|||
<span>{weather.loudCover}</span> |
|||
</div> |
|||
</div> |
|||
|
|||
<div className="w3-row"> |
|||
<div className="w3-half w3-right-align"> |
|||
<span className="label">Pressure</span> |
|||
</div> |
|||
<div className="w3-half w3-left-align"> |
|||
<span>{weather.pressure}</span> |
|||
</div> |
|||
</div> |
|||
|
|||
<div className="w3-row"> |
|||
<div className="w3-half w3-right-align"> |
|||
<span className="label">Daily Summary</span> |
|||
</div> |
|||
<div className="w3-half w3-left-align"> |
|||
<span>{weather.dailySummary}</span> |
|||
</div> |
|||
</div> |
|||
|
|||
</div> |
|||
|
|||
</div> |
|||
) |
|||
} |
|||
|
|||
export default DetailModal |
|||
@ -0,0 +1,7 @@ |
|||
.forecast-text { |
|||
font-size: 8px; |
|||
} |
|||
|
|||
.forecast-image { |
|||
width:100% |
|||
} |
|||
@ -0,0 +1,38 @@ |
|||
import moment from "moment"; |
|||
import './ForecastContent.css'; |
|||
|
|||
function ForecastContent(props) { |
|||
|
|||
let image; |
|||
let header; |
|||
let summary; |
|||
let date; |
|||
let time; |
|||
if (props.forecast != null) { |
|||
const forecast = props.forecast |
|||
|
|||
let url = `http://localhost:3001/images/${forecast.summary.replaceAll(' ', '_')}.png` |
|||
image = <img src={url} alt={forecast.summary} className="forecast-image"/> |
|||
let temperature = Math.round((forecast.temperature + Number.EPSILON) * 100) / 100 |
|||
header = <p className="forecast-text">{temperature}℃</p> |
|||
summary = <p className="forecast-text">{forecast.summary}</p> |
|||
let formattedDate = moment(forecast.date).format("DD/MM") |
|||
date = <p className="forecast-text">{formattedDate}</p> |
|||
let formattedTime = moment(forecast.date).format("HH:mm") |
|||
time = <p className="forecast-text">{formattedTime}</p> |
|||
} |
|||
|
|||
return ( |
|||
<div className="w3-quarter"> |
|||
{image} |
|||
<div className="weather-card-container"> |
|||
{header} |
|||
{summary} |
|||
{date} |
|||
{time} |
|||
</div> |
|||
</div> |
|||
) |
|||
} |
|||
|
|||
export default ForecastContent |
|||
@ -0,0 +1,47 @@ |
|||
import moment from "moment/moment"; |
|||
import DetailModal from "./DetailModal"; |
|||
import {useState} from "react"; |
|||
|
|||
function WeatherCardContent(props) { |
|||
const [modalVisible, setModalVisible] = useState(props.modalVisible) |
|||
function handleClick(e) { |
|||
e.preventDefault(); |
|||
setModalVisible(!modalVisible) |
|||
} |
|||
|
|||
let device; |
|||
let image; |
|||
let header; |
|||
let summary; |
|||
let date; |
|||
let modal; |
|||
if (props.weather != null) { |
|||
const weather = props.weather |
|||
device = <h3>Device {weather.deviceId}</h3> |
|||
let url = `http://localhost:3001/images/${weather.summary.replaceAll(' ', '_')}.png` |
|||
image = <img onClick={handleClick} src={url} alt={weather.summary} className="weather-image"/> |
|||
let temperature = Math.round((weather.temperature + Number.EPSILON) * 100) / 100 |
|||
header = <h4>{temperature}℃</h4> |
|||
summary = <p>{weather.summary}</p> |
|||
let formattedDate = moment(weather.date).format("DD/MM/YYYY HH:mm:ss") |
|||
date = <p>{formattedDate}</p> |
|||
if (modalVisible) { |
|||
modal = <DetailModal weather={props.weather} handleClick={handleClick} /> |
|||
} |
|||
} |
|||
|
|||
return ( |
|||
<div> |
|||
{device} |
|||
{image} |
|||
<div className="weather-card-container"> |
|||
{header} |
|||
{summary} |
|||
{date} |
|||
</div> |
|||
{modal} |
|||
</div> |
|||
) |
|||
} |
|||
|
|||
export default WeatherCardContent |
|||
Loading…
Reference in new issue