import React from 'react';
import { Heading, Box, Flex, Icon, Link as CLink, Button } from '@chakra-ui/core';
import { Link, Redirect } from "react-router-dom";
import DayPicker from "react-day-picker";
import "react-day-picker/lib/style.css";
import { sources } from '../sources.json';
function addDays(date, days) {
var result = new Date(date);
result.setDate(result.getDate() + days);
return result;
}
export default class Location extends React.Component {
constructor(props) {
super(props);
this.state = { tides: [{ date: '', time: '', distance: 0 }],
waves: false,
weather: false,
locationIndex: 0,
loaded: false,
date: new Date(new Date().toLocaleDateString()),
id: '',
name: '',
nextTideable: '',
urls: { marine: '', weather: '' },
redirectToDay: false,
showDayPicker: false,
goodTides: [],
okTides: [],
tidesDate: new Date(2000, 1, 1)
};
}
update = () => {
fetch(`/api/location/${this.state.id}/date/` + this.state.date.toISOString())
.then(res => res.json())
.then(obj => {
const waves = obj.waves.length > 0 ? obj.waves
.sort((a, b) => new Date(a.date) - new Date(b.date))[0] : false;
const highestSwell = waves ? waves.swellDetails
.reduce((r, x) => x.height > r.height ? x : r, { height: -1 }) :
false;
const windHigher = waves ? waves.windHeight > highestSwell.height : false;
const w = obj.weather;
const nextTideable = new Date(obj.nextTideable.date);
this.setState({ tides: obj.tides,
waves: waves ?
{ height: windHigher ? waves.windHeight : highestSwell.height,
direction: windHigher ? '' : highestSwell.direction,
swell: obj.waves.map(w => w.swellText),
wind: obj.waves.map(w => w.windText)
} : false,
weather: w ?
{ wind: { speed: w.windSpeed,
direction: w.windDirection },
conditions: w.shortForecast,
high: w.temperature
} : false,
name: obj.name,
loaded: true,
nextTideable: nextTideable.getFullYear() + '/' +
(nextTideable.getMonth() + 1) + '/' +
nextTideable.getDate(),
urls: obj.urls,
redirectToDay: false
});
});
}
fetchTideability = () => {
fetch(`/api/location/${this.state.id}/tide/` + this.state.date.toISOString())
.then(res => res.json())
.then(obj => this.setState({
goodTides: obj.goodTides.map(x => new Date(x))
.filter(x => x.getHours() < 22 && x.getHours() > 5),
okTides: obj.okTides.map(x => new Date(x))
.concat(obj.goodTides.map(x => new Date(x))
.filter(x => x.getHours() >= 22 && x.getHours() <= 5)),
tidesDate: this.state.date
}));
}
componentDidMount() {
const { match: { params } } = this.props;
this.setState({ id: params.id,
date: params.y ? new Date(parseInt(params.y), parseInt(params.m) - 1, parseInt(params.d)) :
this.state.date },
() => {
this.update();
this.fetchTideability();
});
}
componentDidUpdate(oldProps) {
const { match: { params } } = this.props;
const oldParams = oldProps.match.params;
const date = '' + params.y + params.m + params.d;
const oldDate = '' + oldParams.y + oldParams.m + oldParams.d;
if (params.id !== oldProps.match.params.id ||
date !== oldDate) {
this.setState({ id: params.id, loaded: false,
date: params.y ? new Date(parseInt(params.y), parseInt(params.m) - 1, parseInt(params.d)) : this.state.date
},
() => {
this.update();
// if its been a month since we fetched good/okTides
if (params.id !== oldProps.match.params.id ||
Math.abs(this.state.date - this.state.tidesDate) >= 2588400000) {
this.fetchTideability();
}
});
}
}
dayClick = day => {
this.setState({ redirectToDay: day });
}
toggleDayPicker = () => {
this.setState({ showDayPicker: !this.state.showDayPicker });
}
render() {
if (this.state.loaded && this.state.redirectToDay) {
return ();
} else if (this.state.loaded) {
const sourceIndex = sources.map(source => source.id).indexOf(this.state.id);
const prevLocationObj = sources[sourceIndex === 0 ?
sources.length - 1 : sourceIndex - 1];
const nextLocationObj = sources[sourceIndex === sources.length - 1 ?
0 : sourceIndex + 1];
const prevLocation =
(
);
const nextLocation =
(
);
const nextDayDate = addDays(this.state.date, 1);
const nextDay = '/location/' + this.state.id + '/' +
nextDayDate.getFullYear() + '/' +
(nextDayDate.getMonth() + 1) + '/' +
nextDayDate.getDate();
const prevDayDate = addDays(this.state.date, -1);
// const today = new Date(new Date().toLocaleDateString());
const prevDay =
'/location/' + this.state.id + '/' +
prevDayDate.getFullYear() + '/' +
(prevDayDate.getMonth() + 1) + '/' +
prevDayDate.getDate();
const { weather } = this.state;
const tideMin = Math.min.apply(Math, this.state.tides.map(x => x.distance)),
tideColor = tideMin < -0.3 ? 'green' : tideMin < 0 ? 'orange' : 'black';
const waveColor = this.state.waves.height < 5 ? 'green' :
this.state.waves.height < 10 ? 'orange' : 'red';
const conditionsScore = RegExp('rain', 'g').test(weather.conditions) ? 5 : 0;
const tempScore = weather.high >= 60 ? 0 : weather.high >= 50 ? 5 : 10;
const windSpeed = weather.wind ? weather.wind.speed : "0";
const maxWind = Math.max.apply(Math, windSpeed.match(/[0-9]+/g).map(x => parseInt(x)));
const windScore = maxWind <= 10 ? 0 : maxWind <= 20 ? 5 : 10;
const weatherScore = Math.max(conditionsScore, tempScore, windScore);
const weatherColor = weatherScore < 5 ? 'green' : weatherScore === 5 ? 'orange' : 'red';
return (
{prevLocation}
{this.state.name}
{nextLocation}
{this.state.showDayPicker ? (
) : (<>>)}
Tide
{this.state.tides.map((tide, i) => (
Level: {tide.distance} ft
Time: {new Date(tide.date).toLocaleTimeString()}
))}
{this.state.waves ? (
Waves
Max waves: {this.state.waves.height}ft {this.state.waves.direction}
) : (<>>)}
{this.state.weather ? (
Weather
Conditions: {weather.conditions}
High: {weather.high}
Wind: {weather.wind.speed} {weather.wind.direction}
) : (<>>)}
);
} else {
return ('Loading...');
}
}
}