Add next open/close day panel + refactor common funcs to util

This commit is contained in:
2018-03-19 14:00:34 +05:30
parent eb3151471a
commit 047bc7c291
11 changed files with 309 additions and 118 deletions
+27
View File
@@ -47,7 +47,34 @@
height: 100%;
}
.App .upper-half {
width: 100%;
height: 80vh;
}
.App .lower-half {
width: 100%;
height: 20vh;
border-top: 5px solid antiquewhite;
}
.App .OpenXDay-container {
width: 100%;
height: 100%;
}
.App .OpenXPlusOneDay-container {
float: left;
width: 40%;
height: 100%;
}
.App .OpenXPlusOneDay-container .OpenXDayMini {
border-right: 5px solid rgba(255, 255, 255, 0.5);
}
.App .NextOpenClose-container {
float: right;
width: 60%;
height: 100%;
}
+25 -6
View File
@@ -1,10 +1,12 @@
import * as React from 'react';
import { Switch, Route, Redirect } from 'react-router-dom';
import * as moment from 'moment-timezone';
import './App.css';
import { OpenXDay } from '../OpenXDay';
import { OpenXDayMini } from '../OpenXDayMini';
import { NextOpenCloseMini } from '../NextOpenCloseMini';
import { allHolidays } from '../../Data';
import { Utils } from "../../Utils";
import { Utils, OpenOrClose } from "../../Utils";
enum OpenOrCloseOrClosed {
Open = "open",
@@ -13,19 +15,26 @@ enum OpenOrCloseOrClosed {
}
class IsNiftyOpenApp extends React.Component {
calcOpenOrCloseForOpenCloseMini(xDay: moment.Moment) {
var isTodayEventHoliday = Utils.getEventHolidayOnDate(xDay, allHolidays) !== undefined;
return isTodayEventHoliday ? OpenOrClose.Open : OpenOrClose.Close;
}
renderOpenXDay(questionString: OpenOrCloseOrClosed): React.ReactElement<{}> {
var question: OpenXDay.OpenOrClose;
var question: OpenOrClose;
if (questionString === OpenOrCloseOrClosed.Open) {
question = OpenXDay.OpenOrClose.Open;
question = OpenOrClose.Open;
} else {
question = OpenXDay.OpenOrClose.Close;
question = OpenOrClose.Close;
}
const xDay = Utils.createTodayDateInIndiaTZ();
const XPlusOneDay = xDay.add(1, "d");
const xPlusOneDay = xDay.clone().add(1, "d");
return (
<div className="IsNiftyOpenApp">
<div className="upper-half">
<div className="OpenXDay-container">
<OpenXDay
question={question}
@@ -33,13 +42,23 @@ class IsNiftyOpenApp extends React.Component {
allHolidays={allHolidays}
/>
</div>
</div>
<div className="lower-half">
<div className="OpenXPlusOneDay-container">
<OpenXDayMini
xDay={XPlusOneDay}
xDay={xPlusOneDay}
dateDescription={"tomorrow"}
allHolidays={allHolidays}
/>
</div>
<div className="NextOpenClose-container">
<NextOpenCloseMini
xDay={xDay}
openOrClose={this.calcOpenOrCloseForOpenCloseMini(xDay)}
allHolidays={allHolidays}
/>
</div>
</div>
</div>
);
}
@@ -0,0 +1,26 @@
@import "../../Utils/utils.css";
.NextOpenCloseMini {
width: 100%;
height: 100%;
font-size: 1em;
background-color: rgba(0, 0, 0, 0.75);
color: rgba(255, 255, 255, 0.60);
font-size: 2em;
position: relative;
}
@media screen and (max-width: 600px) {
.NextOpenCloseMini {
font-size: 3em;
}
}
.NextOpenCloseMini-inner {
position: absolute;
text-align: center;
left: 50%;
top: 50%;
width: 80%;
transform: translate(-50%, -50%);
}
@@ -0,0 +1,75 @@
import * as React from 'react';
import * as moment from 'moment-timezone';
import "./Component.css";
import { HolidayList } from '../../Data';
import { Utils, OpenOrClose } from "../../Utils";
export interface NextOpenCloseMiniProps {
xDay: moment.Moment;
openOrClose: OpenOrClose;
allHolidays: HolidayList;
}
export class NextOpenCloseMini extends React.Component<NextOpenCloseMiniProps, {}> {
xDay: moment.Moment;
openOrClose: OpenOrClose;
allHolidays: HolidayList;
nextOpenOrCloseDate: moment.Moment | undefined;
constructor(props: NextOpenCloseMiniProps) {
super(props);
this.xDay = props.xDay;
this.openOrClose = props.openOrClose;
this.allHolidays = props.allHolidays;
this.nextOpenOrCloseDate = Utils.findNextOpenOrCloseFromDate(this.xDay, this.allHolidays, this.openOrClose);
}
getOpeningClosingString() {
return this.openOrClose === OpenOrClose.Open ? "opening" : "closing";
}
renderDate(): JSX.Element[] {
const tmpNextDate = this.nextOpenOrCloseDate as moment.Moment;
var nextDateString = tmpNextDate.format("DD-MM-YYYY");
return [
(
<div className="openCloseDecription" key="title">
Next {this.getOpeningClosingString()} on
</div>
),
(
<div className="dateDescription" key="subTitle">
{nextDateString}
</div>
)
];
}
renderNotFound(): JSX.Element[] {
return [
(
<div className="openCloseDecription" key="title">
No more {this.getOpeningClosingString()}s
</div>
),
(
<div className="dateDescription" key="subTitle">
this year
</div>
)
];
}
render() {
return (
<div className="NextOpenCloseMini">
<div className="NextOpenCloseMini-inner">
{this.nextOpenOrCloseDate === undefined ? this.renderNotFound() : this.renderDate()}
</div>
</div>
);
}
}
@@ -0,0 +1 @@
export { NextOpenCloseMini } from './Component';
+7 -48
View File
@@ -1,33 +1,23 @@
import * as React from 'react';
import * as moment from 'moment-timezone';
import * as Linq from 'linq';
import * as classnames from 'classnames';
import "./Component.css";
import { Holiday, HolidayList, getWeekendHoliday } from '../../Data/index';
import { Holiday, HolidayList } from '../../Data/index';
import { ClosedReason } from '../ClosedReason';
import { Utils, HolidayAnswer, OpenOrClose } from "../../Utils";
export interface OpenXDayProps {
question: OpenXDay.OpenOrClose;
question: OpenOrClose;
xDay: moment.Moment;
allHolidays: HolidayList;
}
export class OpenXDay extends React.Component<OpenXDayProps, {}> {
question: OpenXDay.OpenOrClose;
question: OpenOrClose;
xDay: moment.Moment;
allHolidays: HolidayList;
answer: { open: boolean, holiday: Holiday | undefined };
static checkSameDayInSameTZ(moment1: moment.Moment, moment2: moment.Moment, raiseErrorTZMismatch: boolean = true) {
// tslint:disable-next-line:triple-equals
if (raiseErrorTZMismatch && (moment1.tz() != moment2.tz())) {
throw new Error("Timezones don't match");
}
// tslint:disable-next-line:triple-equals
return (moment1.startOf("day").format() == moment2.startOf("day").format());
}
answer: HolidayAnswer;
constructor(props: OpenXDayProps) {
super(props);
@@ -35,35 +25,11 @@ export class OpenXDay extends React.Component<OpenXDayProps, {}> {
this.xDay = props.xDay;
this.allHolidays = props.allHolidays;
this.processAnswer();
}
processAnswer(): void {
{
const matchingHoliday = Linq
.from<Holiday>(this.allHolidays)
.firstOrDefault(
(eachHoliday, _tmp) => OpenXDay.checkSameDayInSameTZ(this.xDay, eachHoliday.Date)
);
if (matchingHoliday === null) {
this.answer = { open: true, holiday: undefined };
} else {
this.answer = { open: false, holiday: matchingHoliday };
}
}
{
const weekendHoliday = getWeekendHoliday(this.xDay);
if (typeof weekendHoliday !== "undefined") {
this.answer = { open: false, holiday: weekendHoliday };
}
}
this.answer = Utils.getHolidayAnswerOnDate(this.xDay, this.allHolidays);
}
render() {
const answerBoolean = (this.question === OpenXDay.OpenOrClose.Open ? this.answer.open : !this.answer.open);
const answerBoolean = (this.question === OpenOrClose.Open ? this.answer.open : !this.answer.open);
const bgColorClass = (this.answer.open ? "green" : "red");
return (
@@ -89,10 +55,3 @@ export class OpenXDay extends React.Component<OpenXDayProps, {}> {
);
}
}
export module OpenXDay {
export enum OpenOrClose {
Open = 'open',
Close = 'closed'
}
}
+24 -6
View File
@@ -1,16 +1,34 @@
@import "../../Utils/utils.css";
.OpenXDayMini {
width: 100%;
height: 100%;
font-size: 4em;
background-color: rgba(0, 0, 0, 0.75);
color: rgba(255, 255, 255, 0.60);
font-size: 2em;
position: relative;
}
.OpenXDayMini.green {
background-color: #2ECC40;
@media screen and (max-width: 600px) {
.OpenXDayMini {
font-size: 3em;
}
}
.OpenXDayMini.red {
background-color: #FF4136;
.OpenXDayMini-inner {
position: absolute;
text-align: right;
right: 1em;
top: 50%;
width: 80%;
transform: translate(0, -50%);
}
.OpenXDayMini .green-text {
color: rgba(46, 204, 64, 0.75);
}
.OpenXDayMini .red-text {
color: rgba(255, 64, 54, 0.75);
}
+10 -44
View File
@@ -1,73 +1,39 @@
import * as React from 'react';
import * as moment from 'moment-timezone';
import * as Linq from 'linq';
import * as classnames from 'classnames';
import "./Component.css";
import { Holiday, HolidayList, getWeekendHoliday } from '../../Data/index';
import { HolidayList } from '../../Data';
import { Utils, HolidayAnswer } from "../../Utils";
export interface OpenXDayProps {
export interface OpenXDayMiniProps {
xDay: moment.Moment;
dateDescription: string;
allHolidays: HolidayList;
}
export class OpenXDayMini extends React.Component<OpenXDayProps, {}> {
export class OpenXDayMini extends React.Component<OpenXDayMiniProps, {}> {
xDay: moment.Moment;
dateDescription: string;
allHolidays: HolidayList;
answer: { open: boolean, holiday: Holiday | undefined };
answer: HolidayAnswer;
static checkSameDayInSameTZ(moment1: moment.Moment, moment2: moment.Moment, raiseErrorTZMismatch: boolean = true) {
// tslint:disable-next-line:triple-equals
if (raiseErrorTZMismatch && (moment1.tz() != moment2.tz())) {
throw new Error("Timezones don't match");
}
// tslint:disable-next-line:triple-equals
return (moment1.startOf("day").format() == moment2.startOf("day").format());
}
constructor(props: OpenXDayProps) {
constructor(props: OpenXDayMiniProps) {
super(props);
this.xDay = props.xDay;
this.dateDescription = props.dateDescription;
this.allHolidays = props.allHolidays;
this.processAnswer();
}
processAnswer(): void {
{
const matchingHoliday = Linq
.from<Holiday>(this.allHolidays)
.firstOrDefault(
(eachHoliday, _tmp) => OpenXDayMini.checkSameDayInSameTZ(this.xDay, eachHoliday.Date)
);
if (matchingHoliday === null) {
this.answer = { open: true, holiday: undefined };
} else {
this.answer = { open: false, holiday: matchingHoliday };
}
}
{
const weekendHoliday = getWeekendHoliday(this.xDay);
if (typeof weekendHoliday !== "undefined") {
this.answer = { open: false, holiday: weekendHoliday };
}
}
this.answer = Utils.getHolidayAnswerOnDate(this.xDay, this.allHolidays);
}
render() {
const bgColorClass = (this.answer.open ? "green" : "red");
const textColorClass = (this.answer.open ? "green-text" : "red-text");
return (
<div className={classnames([bgColorClass, "OpenXDayMini"])} >
<div className={"OpenXDayMini"} >
<div className="OpenXDayMini-inner">
<div className="openOrCloseText">
<div className={classnames([textColorClass, "openOrCloseText"])}>
{this.answer.open ? "Open" : "Closed"}
</div>
<div className="dateDescription">
+1 -1
View File
@@ -53,7 +53,7 @@ export function isWeekend(date: moment.Moment): boolean {
}
}
export function getWeekendHoliday(date: moment.Moment): Holiday | undefined {
export function getWeekendHolidayOnDate(date: moment.Moment): Holiday | undefined {
if (isWeekend(date)) {
const dateWeekDay = date.isoWeekday();
return { "Description": "Weekend", "Date": date, "Day": ISOWeekDay[dateWeekDay] };
+1 -1
View File
@@ -1 +1 @@
export { Utils } from "./utils";
export { Utils, HolidayAnswer, OpenOrClose } from "./utils";
+100
View File
@@ -1,7 +1,107 @@
import * as moment from 'moment-timezone';
import * as Linq from 'linq';
import { Holiday, HolidayList, getWeekendHolidayOnDate } from '../Data';
export interface HolidayAnswer {
open: boolean;
holiday: Holiday | undefined;
}
export enum OpenOrClose {
Open = 'open',
Close = 'closed'
}
export class Utils {
static invertOpenOrClose(openOrClose: OpenOrClose) {
return (openOrClose === OpenOrClose.Open) ? OpenOrClose.Close : OpenOrClose.Open;
}
static createTodayDateInIndiaTZ(): moment.Moment {
return moment.tz(moment.tz.guess()).tz("Asia/Kolkata");
}
static checkSameDayInSameTZ(moment1: moment.Moment, moment2: moment.Moment, raiseErrorTZMismatch: boolean = true) {
// tslint:disable-next-line:triple-equals
if (raiseErrorTZMismatch && (moment1.tz() != moment2.tz())) {
throw new Error("Timezones don't match");
}
// tslint:disable-next-line:triple-equals
return (moment1.clone().startOf("day").format() == moment2.clone().startOf("day").format());
}
static checkSameYearInSameTZ(moment1: moment.Moment, moment2: moment.Moment, raiseErrorTZMismatch: boolean = true) {
// tslint:disable-next-line:triple-equals
if (raiseErrorTZMismatch && (moment1.tz() != moment2.tz())) {
throw new Error("Timezones don't match");
}
// tslint:disable-next-line:triple-equals
return (moment1.clone().startOf("year").format() == moment2.clone().startOf("year").format());
}
static getHolidayAnswerOnDate(xDay: moment.Moment, allHolidays: HolidayList): HolidayAnswer {
let tmpHolidayAnswer: HolidayAnswer;
{
const eventHoliday = this.getEventHolidayOnDate(xDay, allHolidays);
if (typeof eventHoliday !== "undefined") {
tmpHolidayAnswer = { open: false, holiday: eventHoliday };
} else {
tmpHolidayAnswer = { open: true, holiday: undefined };
}
}
{
const weekendHoliday = getWeekendHolidayOnDate(xDay);
if (typeof weekendHoliday !== "undefined") {
tmpHolidayAnswer = { open: false, holiday: weekendHoliday };
}
}
return tmpHolidayAnswer;
}
static getEventHolidayOnDate(xDay: moment.Moment, allHolidays: HolidayList): Holiday | undefined {
{
const matchingHoliday = Linq
.from<Holiday>(allHolidays)
.firstOrDefault(
(eachHoliday, _tmp) => Utils.checkSameDayInSameTZ(xDay, eachHoliday.Date)
);
if (matchingHoliday === null) {
return undefined;
} else {
return matchingHoliday;
}
}
}
static findNextOpenOrCloseFromDate(
xDay: moment.Moment,
allHolidays: HolidayList,
openOrClose: OpenOrClose): moment.Moment | undefined {
let currentDay = xDay.clone().add(1, "day");
while (this.checkSameYearInSameTZ(currentDay, xDay)) {
var holidayAnswerOnCurrentDay = this.getHolidayAnswerOnDate(currentDay, allHolidays);
if ((openOrClose === OpenOrClose.Open) && holidayAnswerOnCurrentDay.open) {
return currentDay;
}
if ((openOrClose === OpenOrClose.Close) && !holidayAnswerOnCurrentDay.open) {
return currentDay;
}
currentDay = currentDay.add(1, "day");
}
return undefined;
}
}