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