diff --git a/src/Components/IsNiftyOpenApp/App.css b/src/Components/IsNiftyOpenApp/App.css index ebbe33c..558cf98 100644 --- a/src/Components/IsNiftyOpenApp/App.css +++ b/src/Components/IsNiftyOpenApp/App.css @@ -36,7 +36,7 @@ } } -@media screen and (max-width: 320px){ +@media screen and (max-width: 320px) { .App { font-size: 0.3em; } @@ -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%; } \ No newline at end of file diff --git a/src/Components/IsNiftyOpenApp/App.tsx b/src/Components/IsNiftyOpenApp/App.tsx index ae49c34..f4f064c 100644 --- a/src/Components/IsNiftyOpenApp/App.tsx +++ b/src/Components/IsNiftyOpenApp/App.tsx @@ -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,32 +15,49 @@ 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 (
-
- +
+
+ +
-
- +
+
+ +
+
+ +
); diff --git a/src/Components/NextOpenCloseMini/Component.css b/src/Components/NextOpenCloseMini/Component.css new file mode 100644 index 0000000..251a8af --- /dev/null +++ b/src/Components/NextOpenCloseMini/Component.css @@ -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%); +} \ No newline at end of file diff --git a/src/Components/NextOpenCloseMini/Component.tsx b/src/Components/NextOpenCloseMini/Component.tsx new file mode 100644 index 0000000..412c809 --- /dev/null +++ b/src/Components/NextOpenCloseMini/Component.tsx @@ -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 { + 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 [ + ( +
+ Next {this.getOpeningClosingString()} on +
+ ), + ( +
+ {nextDateString} +
+ ) + ]; + } + + renderNotFound(): JSX.Element[] { + return [ + ( +
+ No more {this.getOpeningClosingString()}s +
+ ), + ( +
+ this year +
+ ) + ]; + } + + render() { + + return ( +
+
+ {this.nextOpenOrCloseDate === undefined ? this.renderNotFound() : this.renderDate()} +
+
+ ); + } +} \ No newline at end of file diff --git a/src/Components/NextOpenCloseMini/index.tsx b/src/Components/NextOpenCloseMini/index.tsx new file mode 100644 index 0000000..5bf532b --- /dev/null +++ b/src/Components/NextOpenCloseMini/index.tsx @@ -0,0 +1 @@ +export { NextOpenCloseMini } from './Component'; \ No newline at end of file diff --git a/src/Components/OpenXDay/Component.tsx b/src/Components/OpenXDay/Component.tsx index 1dd6033..82dd900 100644 --- a/src/Components/OpenXDay/Component.tsx +++ b/src/Components/OpenXDay/Component.tsx @@ -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 { - 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 { this.xDay = props.xDay; this.allHolidays = props.allHolidays; - this.processAnswer(); - } - - processAnswer(): void { - { - const matchingHoliday = Linq - .from(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 ( @@ -88,11 +54,4 @@ export class OpenXDay extends React.Component {
); } -} - -export module OpenXDay { - export enum OpenOrClose { - Open = 'open', - Close = 'closed' - } } \ No newline at end of file diff --git a/src/Components/OpenXDayMini/Component.css b/src/Components/OpenXDayMini/Component.css index b07e789..ef93aef 100644 --- a/src/Components/OpenXDayMini/Component.css +++ b/src/Components/OpenXDayMini/Component.css @@ -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); +} \ No newline at end of file diff --git a/src/Components/OpenXDayMini/Component.tsx b/src/Components/OpenXDayMini/Component.tsx index e370f73..2781adf 100644 --- a/src/Components/OpenXDayMini/Component.tsx +++ b/src/Components/OpenXDayMini/Component.tsx @@ -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 { +export class OpenXDayMini extends React.Component { 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(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 ( -
+
-
+
{this.answer.open ? "Open" : "Closed"}
diff --git a/src/Data/index.ts b/src/Data/index.ts index c29b334..13b8e95 100644 --- a/src/Data/index.ts +++ b/src/Data/index.ts @@ -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] }; diff --git a/src/Utils/index.ts b/src/Utils/index.ts index a6deb09..0a3231b 100644 --- a/src/Utils/index.ts +++ b/src/Utils/index.ts @@ -1 +1 @@ -export { Utils } from "./utils"; \ No newline at end of file +export { Utils, HolidayAnswer, OpenOrClose } from "./utils"; \ No newline at end of file diff --git a/src/Utils/utils.ts b/src/Utils/utils.ts index c216007..c6afc2b 100644 --- a/src/Utils/utils.ts +++ b/src/Utils/utils.ts @@ -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(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; + } } \ No newline at end of file