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...'); } } }