time-convertor-ts

Convert time across timezones (typescript)
git clone http://git.hanabi.in/repos/time-convertor-ts.git
Log | Files | Refs | README | LICENSE

commit 3ac7f68f2964dc488d9cdf278438d0060080e9a1
parent 24b1806a61e7b1c69b51d695126df9128c3fd4ff
Author: Agastya Chandrakant <acagastya@outlook.com>
Date:   Fri,  9 Oct 2020 17:54:05 +0530

format

Diffstat:
A.prettierignore | 4++++
A.prettierrc | 8++++++++
Mpackage.json | 2++
Msrc/App.test.tsx | 8++++----
Msrc/App/comps/ErrorAlert.tsx | 2+-
Msrc/App/comps/Footer.tsx | 12++++++------
Msrc/App/comps/FutureConverted.tsx | 10+++++-----
Msrc/App/comps/Header.tsx | 8++++----
Msrc/App/comps/SavedFuture.tsx | 12++++++------
Msrc/App/comps/SavedTimezones.tsx | 12++++++------
Msrc/App/comps/ShowFuture.tsx | 10+++++-----
Msrc/App/comps/ShowSavedZones.tsx | 10+++++-----
Msrc/App/comps/TimezoneInput.tsx | 42+++++++++++++++++++++---------------------
Msrc/App/index.tsx | 26+++++++++++++-------------
Msrc/App/pages/CreateEvent.tsx | 20++++++++++----------
Msrc/App/pages/DualConvertor.tsx | 12++++++------
Msrc/App/pages/FutureConversion.tsx | 34+++++++++++++++++-----------------
Msrc/App/pages/Help.tsx | 16++++++++--------
Msrc/App/pages/SimpleConvertor.tsx | 14+++++++-------
Msrc/App/pages/UNIXTime.tsx | 24++++++++++++------------
Msrc/index.tsx | 10+++++-----
Msrc/serviceWorker.ts | 49+++++++++++++++++++++++--------------------------
Msrc/setupTests.ts | 2+-
Msrc/utils/index.ts | 53++++++++++++++++++++++++++---------------------------
Msrc/utils/interfaces.tsx | 7++++++-
Msrc/utils/useTime.ts | 8+++-----
Myarn.lock | 5+++++
27 files changed, 219 insertions(+), 201 deletions(-)

diff --git a/.prettierignore b/.prettierignore @@ -0,0 +1,3 @@ +package.json +package-lock.json +node_modules/ +\ No newline at end of file diff --git a/.prettierrc b/.prettierrc @@ -0,0 +1,8 @@ +{ + "endOfLine": "lf", + "semi": true, + "singleQuote": false, + "tabWidth": 2, + "trailingComma": "es5", + "useTabs": false +} diff --git a/package.json b/package.json @@ -29,6 +29,7 @@ "build": "react-scripts build", "deploy": "react-scripts build && gh-pages -d build", "eject": "react-scripts eject", + "format": "prettier --write \"src/**/*.(ts|tsx)\"", "ogstart": "react-scripts start", "start": "serve -l $PORT -s build", "test": "react-scripts test" @@ -56,6 +57,7 @@ "@types/react-dom": "^16.9.8", "@types/react-router-dom": "^5.1.5", "gh-pages": "^2.2.0", + "prettier": "^2.1.2", "serve": "^11.3.1" } } diff --git a/src/App.test.tsx b/src/App.test.tsx @@ -1,8 +1,8 @@ -import React from 'react'; -import { render } from '@testing-library/react'; -import App from './App/index'; +import React from "react"; +import { render } from "@testing-library/react"; +import App from "./App/index"; -test('renders learn react link', () => { +test("renders learn react link", () => { const { getByText } = render(<App />); const linkElement = getByText(/learn react/i); expect(linkElement).toBeInTheDocument(); diff --git a/src/App/comps/ErrorAlert.tsx b/src/App/comps/ErrorAlert.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React from "react"; function ErrorAlert({ msg }: { msg: string }) { return ( diff --git a/src/App/comps/Footer.tsx b/src/App/comps/Footer.tsx @@ -1,6 +1,6 @@ -import React from 'react'; +import React from "react"; -import { YEAR } from '../../utils'; +import { YEAR } from "../../utils"; function Footer<never>(): JSX.Element { return ( @@ -8,12 +8,12 @@ function Footer<never>(): JSX.Element { className="border-top mt-5 page-footer" style={{ bottom: 0, - paddingTop: '1rem', + paddingTop: "1rem", }} > <div className="text-center"> <p> - Copyright &copy; {YEAR}{' '} + Copyright &copy; {YEAR}{" "} <a href="https://en.wikinews.org/wiki/User:Acagastya" target="_blank" @@ -21,7 +21,7 @@ function Footer<never>(): JSX.Element { > Agastya </a> - . This project is licensed under{' '} + . This project is licensed under{" "} <a href="https://opensource.org/licenses/BSD-3-Clause" target="_blank" @@ -29,7 +29,7 @@ function Footer<never>(): JSX.Element { > BSD-3-Clause license </a> - . Report bugs{' '} + . Report bugs{" "} <a href="https://github.com/acagastya/time-convertor-ts/issues/new" target="_blank" diff --git a/src/App/comps/FutureConverted.tsx b/src/App/comps/FutureConverted.tsx @@ -1,11 +1,11 @@ -import React from 'react'; -import moment from 'moment-timezone'; +import React from "react"; +import moment from "moment-timezone"; -import { displayTime, friendlyStr, getAbbr } from '../../utils'; +import { displayTime, friendlyStr, getAbbr } from "../../utils"; -import { HMMDY, HMSDMY } from '../../utils'; +import { HMMDY, HMSDMY } from "../../utils"; -import { IFutureConverted } from '../../utils/interfaces'; +import { IFutureConverted } from "../../utils/interfaces"; function FutureConverted({ selectedTime, diff --git a/src/App/comps/Header.tsx b/src/App/comps/Header.tsx @@ -1,7 +1,7 @@ -import React from 'react'; -import { Link } from 'react-router-dom'; +import React from "react"; +import { Link } from "react-router-dom"; -import { basePath } from '../../utils'; +import { basePath } from "../../utils"; function Header<never>(): JSX.Element { return ( @@ -9,7 +9,7 @@ function Header<never>(): JSX.Element { <Link className="navbar-brand" to={`${basePath}/`}> <span aria-label="time-convertor" role="img"> ⏳ - </span>{' '} + </span>{" "} time convertor </Link> <button diff --git a/src/App/comps/SavedFuture.tsx b/src/App/comps/SavedFuture.tsx @@ -1,8 +1,8 @@ -import React from 'react'; +import React from "react"; -import ShowFuture from './ShowFuture'; +import ShowFuture from "./ShowFuture"; -import { getSavedZones } from '../../utils'; +import { getSavedZones } from "../../utils"; function SavedFuture({ selectedTime, @@ -17,10 +17,10 @@ function SavedFuture({ ) : ( <h5 className="border-top mt-5 text-center" - style={{ paddingTop: '1rem' }} + style={{ paddingTop: "1rem" }} > - You haven't {selectedTime ? 'saved any timezones' : 'selected a time'}{' '} - so far.{' '} + You haven't {selectedTime ? "saved any timezones" : "selected a time"}{" "} + so far.{" "} <span aria-label="Saved list is empty." role="img"> 😅 </span> diff --git a/src/App/comps/SavedTimezones.tsx b/src/App/comps/SavedTimezones.tsx @@ -1,10 +1,10 @@ -import React from 'react'; +import React from "react"; -import ShowSavedZones from './ShowSavedZones'; +import ShowSavedZones from "./ShowSavedZones"; -import { getSavedZones } from '../../utils'; +import { getSavedZones } from "../../utils"; -import { IMoment } from '../../utils/interfaces'; +import { IMoment } from "../../utils/interfaces"; function SavedTimezones({ time }: IMoment): JSX.Element { const savedZones = getSavedZones(); @@ -15,9 +15,9 @@ function SavedTimezones({ time }: IMoment): JSX.Element { ) : ( <h5 className="border-top mt-5 text-center" - style={{ paddingTop: '1rem' }} + style={{ paddingTop: "1rem" }} > - You haven't saved any timezones so far.{' '} + You haven't saved any timezones so far.{" "} <span aria-label="Saved list is empty." role="img"> 😅 </span> diff --git a/src/App/comps/ShowFuture.tsx b/src/App/comps/ShowFuture.tsx @@ -1,8 +1,8 @@ -import React from 'react'; -import moment from 'moment-timezone'; +import React from "react"; +import moment from "moment-timezone"; -import { displayTime, friendlyStr, removeTimeZone } from '../../utils'; -import { HMMDY } from '../../utils'; +import { displayTime, friendlyStr, removeTimeZone } from "../../utils"; +import { HMMDY } from "../../utils"; function ShowFuture({ selectedTime, @@ -19,7 +19,7 @@ function ShowFuture({ <li className="list-group-item list-group-item-action" key={zone} - style={{ cursor: 'pointer' }} + style={{ cursor: "pointer" }} > <h4>{friendlyStr(zone)}</h4> <span> diff --git a/src/App/comps/ShowSavedZones.tsx b/src/App/comps/ShowSavedZones.tsx @@ -1,10 +1,10 @@ -import React from 'react'; +import React from "react"; -import { displayTime, friendlyStr, removeTimeZone } from '../../utils'; +import { displayTime, friendlyStr, removeTimeZone } from "../../utils"; -import { HMSDMY } from '../../utils'; +import { HMSDMY } from "../../utils"; -import { IShowSavedTimezones } from '../../utils/interfaces'; +import { IShowSavedTimezones } from "../../utils/interfaces"; function ShowSavedZones({ savedZones, @@ -18,7 +18,7 @@ function ShowSavedZones({ <li className="list-group-item list-group-item-action" key={zone} - style={{ cursor: 'pointer' }} + style={{ cursor: "pointer" }} > <div className="row"> <div className="col"> diff --git a/src/App/comps/TimezoneInput.tsx b/src/App/comps/TimezoneInput.tsx @@ -1,31 +1,31 @@ -import React from 'react'; +import React from "react"; -import { friendlyStr, unfriendlyStr } from '../../utils'; +import { friendlyStr, unfriendlyStr } from "../../utils"; -import { timezoneList } from '../../utils'; +import { timezoneList } from "../../utils"; -import { ITimezoneInput } from '../../utils/interfaces'; +import { ITimezoneInput } from "../../utils/interfaces"; function TimezoneInput({ autofocus = false, changeValue, clearInput, - id = '', - placeholder = 'Time zone', - TZ = 'UTC', + id = "", + placeholder = "Time zone", + TZ = "UTC", }: ITimezoneInput): JSX.Element { const options = timezoneList; const [suggestions, setSuggestions] = React.useState<string[] | []>([]); const [inputValue, setInputValue] = React.useState(friendlyStr(TZ)); const [style, setStyle] = React.useState<object>({ border: 0, - borderBottom: '1px solid silver', + borderBottom: "1px solid silver", }); function handleBlur(): void { setStyle({ - 'border': 0, - 'borderBottom': '1px solid silver', + border: 0, + borderBottom: "1px solid silver", }); } @@ -55,7 +55,7 @@ function TimezoneInput({ function handleFocus(): void { setStyle({ - 'border': 'none', + border: "none", }); } @@ -65,7 +65,7 @@ function TimezoneInput({ className="list-group-item list-group-item-action" key={index} onClick={() => handleClick(str)} - style={{ cursor: 'pointer' }} + style={{ cursor: "pointer" }} > {friendlyStr(str)} </li> @@ -96,15 +96,15 @@ function TimezoneInput({ style={{ boxShadow: suggestions.length > 0 - ? '0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22)' - : 'none', - left: '15px', - maxHeight: '50vh', - overflowX: 'scroll', - scrollbarWidth: 'none', - position: 'absolute', - right: '15px', - WebkitOverflowScrolling: 'touch', + ? "0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22)" + : "none", + left: "15px", + maxHeight: "50vh", + overflowX: "scroll", + scrollbarWidth: "none", + position: "absolute", + right: "15px", + WebkitOverflowScrolling: "touch", zIndex: 2, }} > diff --git a/src/App/index.tsx b/src/App/index.tsx @@ -1,19 +1,19 @@ -import React from 'react'; -import { Route, BrowserRouter as Router, Switch } from 'react-router-dom'; +import React from "react"; +import { Route, BrowserRouter as Router, Switch } from "react-router-dom"; -import CreateEvent from './pages/CreateEvent'; -import DualConvertor from './pages/DualConvertor'; -import FutureConversion from './pages/FutureConversion'; -import Help from './pages/Help'; -import SimpleConvertor from './pages/SimpleConvertor'; -import UNIXTime from './pages/UNIXTime'; +import CreateEvent from "./pages/CreateEvent"; +import DualConvertor from "./pages/DualConvertor"; +import FutureConversion from "./pages/FutureConversion"; +import Help from "./pages/Help"; +import SimpleConvertor from "./pages/SimpleConvertor"; +import UNIXTime from "./pages/UNIXTime"; -import Footer from './comps/Footer'; -import Header from './comps/Header'; +import Footer from "./comps/Footer"; +import Header from "./comps/Header"; -import { displayTime } from '../utils'; -import { basePath, DEFAULT_TZ, HM, localTimezone, YMD } from '../utils'; -import useTime from '../utils/useTime'; +import { displayTime } from "../utils"; +import { basePath, DEFAULT_TZ, HM, localTimezone, YMD } from "../utils"; +import useTime from "../utils/useTime"; function App<never>(): JSX.Element { const now = useTime(); diff --git a/src/App/pages/CreateEvent.tsx b/src/App/pages/CreateEvent.tsx @@ -1,9 +1,9 @@ -import React from 'react'; -import moment from 'moment-timezone'; +import React from "react"; +import moment from "moment-timezone"; -import TimezoneInput from '../comps/TimezoneInput'; +import TimezoneInput from "../comps/TimezoneInput"; -import { HM, localTimezone, MAX_DATE, YMD } from '../../utils'; +import { HM, localTimezone, MAX_DATE, YMD } from "../../utils"; function CreateEvent() { const { protocol, host } = window.location; @@ -14,7 +14,7 @@ function CreateEvent() { stamp: now.unix(), time: now.format(HM), }; - const [fullurl, setFullurl] = React.useState<string>(''); + const [fullurl, setFullurl] = React.useState<string>(""); const [date, setDate] = React.useState<string>(defaults.date); const [time, setTime] = React.useState<string>(defaults.time); const [timezone, setTimezone] = React.useState<string>(localTimezone); @@ -23,7 +23,7 @@ function CreateEvent() { function copyToClipboard(): void { const el = textArea; el?.select(); - document.execCommand('copy'); + document.execCommand("copy"); } function generateLink(): void { @@ -33,17 +33,17 @@ function CreateEvent() { function handleDateChange(e: React.ChangeEvent<HTMLInputElement>): void { setDate(e.target.value); - setFullurl(''); + setFullurl(""); } function handleTimeChange(e: React.ChangeEvent<HTMLInputElement>): void { setTime(e.target.value); - setFullurl(''); + setFullurl(""); } function handleTimezoneChange(tz: React.SetStateAction<string>): void { setTimezone(tz); - setFullurl(''); + setFullurl(""); } return ( @@ -94,7 +94,7 @@ function CreateEvent() { readOnly={true} ref={(text) => (textArea = text)} style={{ - background: 'white', + background: "white", }} type="text" value={fullurl} diff --git a/src/App/pages/DualConvertor.tsx b/src/App/pages/DualConvertor.tsx @@ -1,18 +1,18 @@ -import React from 'react'; +import React from "react"; -import SavedTimezones from '../comps/SavedTimezones'; -import TimezoneInput from '../comps/TimezoneInput'; +import SavedTimezones from "../comps/SavedTimezones"; +import TimezoneInput from "../comps/TimezoneInput"; import { clearTimezones, displayTime, getSavedZones, saveTimezones, -} from '../../utils'; +} from "../../utils"; -import { HMSDMY } from '../../utils'; +import { HMSDMY } from "../../utils"; -import { IDualConvertor } from '../../utils/interfaces'; +import { IDualConvertor } from "../../utils/interfaces"; function DualConvertor({ time, diff --git a/src/App/pages/FutureConversion.tsx b/src/App/pages/FutureConversion.tsx @@ -1,15 +1,15 @@ -import React from 'react'; -import moment from 'moment-timezone'; +import React from "react"; +import moment from "moment-timezone"; -import ErrorAlert from '../comps/ErrorAlert'; -import FutureConverted from '../comps/FutureConverted'; -import SavedFuture from '../comps/SavedFuture'; -import TimezoneInput from '../comps/TimezoneInput'; +import ErrorAlert from "../comps/ErrorAlert"; +import FutureConverted from "../comps/FutureConverted"; +import SavedFuture from "../comps/SavedFuture"; +import TimezoneInput from "../comps/TimezoneInput"; -import { displayTime, getYesterday, timezoneList } from '../../utils'; -import { MAX_DATE, YMD, localTimezone } from '../../utils'; +import { displayTime, getYesterday, timezoneList } from "../../utils"; +import { MAX_DATE, YMD, localTimezone } from "../../utils"; -import { IFutureConversion } from '../../utils/interfaces'; +import { IFutureConversion } from "../../utils/interfaces"; function FutureConversion({ date, @@ -25,7 +25,7 @@ function FutureConversion({ const [selectedTime, setSelectedTime] = React.useState< moment.Moment | undefined >(undefined); - const [err, setErr] = React.useState<string>(''); + const [err, setErr] = React.useState<string>(""); function handleDateChange(e: React.ChangeEvent<HTMLInputElement>): void { setDate(e.target.value); @@ -36,12 +36,12 @@ function FutureConversion({ e.preventDefault(); // 0. Reset Error and selected time - setErr(''); + setErr(""); setSelectedTime(undefined); // 1. Validate selected date const selectedDate = moment(date); if (!selectedDate.isValid()) { - setErr('Chosen date is not valid.'); + setErr("Chosen date is not valid."); console.warn(err); return; } @@ -49,7 +49,7 @@ function FutureConversion({ // 2.1 MAX allowed const epoch = moment(MAX_DATE, YMD); if (epoch.unix() - selectedDate.unix() < 0) { - setErr('Chosen date is outside the maximum permissible limit.'); + setErr("Chosen date is outside the maximum permissible limit."); console.warn(err); return; } @@ -57,7 +57,7 @@ function FutureConversion({ const yDayMoment = moment(yesterday.format(YMD), YMD); const selectedMoment = moment(selectedDate.format(YMD), YMD); if (selectedMoment.unix() - yDayMoment.unix() < 0) { - setErr('Chosen date is in the past.'); + setErr("Chosen date is in the past."); console.warn(err); return; } @@ -67,19 +67,19 @@ function FutureConversion({ const dateTimeStr = `${dateStr} ${timeStr}`; const dateTime = moment.tz(dateTimeStr, TZ1); if (!dateTime.isValid()) { - setErr('Error occurred while parsing time.'); + setErr("Error occurred while parsing time."); console.warn(err); return; } // 4. validate chosen timezone if (timezoneList.indexOf(TZ1) < 0) { - setErr('Selected timezone is invalid.'); + setErr("Selected timezone is invalid."); console.warn(err); return; } // 5. validate set timezone if (timezoneList.indexOf(TZ2) < 0) { - setErr('Selected timezone to convert is invalid.'); + setErr("Selected timezone to convert is invalid."); console.warn(err); return; } diff --git a/src/App/pages/Help.tsx b/src/App/pages/Help.tsx @@ -1,28 +1,28 @@ -import React from 'react'; -import { Link } from 'react-router-dom'; +import React from "react"; +import { Link } from "react-router-dom"; -import { getAbbr } from '../../utils'; +import { getAbbr } from "../../utils"; -import { basePath, localTimezone } from '../../utils'; +import { basePath, localTimezone } from "../../utils"; -import { IMoment } from '../../utils/interfaces'; +import { IMoment } from "../../utils/interfaces"; function Help({ time }: IMoment): JSX.Element { return ( <div className="container"> <ol> <li> - Use the <Link to={`${basePath}/`}>homepage</Link> to convert your{' '} + Use the <Link to={`${basePath}/`}>homepage</Link> to convert your{" "} <span className="font-weight-bold">current time</span> ( {getAbbr({ time, timezone: localTimezone })}) to other timezone. </li> <li> - Use the <Link to={`${basePath}/future`}>/future</Link> to convert a{' '} + Use the <Link to={`${basePath}/future`}>/future</Link> to convert a{" "} <span className="font-weight-bold">future date</span> between different timezones. </li> <li> - Use the <Link to={`${basePath}/from-to`}>/from-to</Link> to convert{' '} + Use the <Link to={`${basePath}/from-to`}>/from-to</Link> to convert{" "} <span className="font-weight-bold">current time</span> between different timezones. </li> diff --git a/src/App/pages/SimpleConvertor.tsx b/src/App/pages/SimpleConvertor.tsx @@ -1,7 +1,7 @@ -import React from 'react'; +import React from "react"; -import SavedTimezones from '../comps/SavedTimezones'; -import TimezoneInput from '../comps/TimezoneInput'; +import SavedTimezones from "../comps/SavedTimezones"; +import TimezoneInput from "../comps/TimezoneInput"; import { clearTimezones, @@ -10,11 +10,11 @@ import { getSavedZones, localTimezone, saveTimezones, -} from '../../utils'; +} from "../../utils"; -import { HMSDMY } from '../../utils'; +import { HMSDMY } from "../../utils"; -import { ISimpleConvertor } from '../../utils/interfaces'; +import { ISimpleConvertor } from "../../utils/interfaces"; function SimpleConvertor({ setTZ1, time, TZ1 }: ISimpleConvertor): JSX.Element { return ( @@ -26,7 +26,7 @@ function SimpleConvertor({ setTZ1, time, TZ1 }: ISimpleConvertor): JSX.Element { <div className="col text-right" id="first-time-lbl-box" - style={{ cursor: 'not-allowed' }} + style={{ cursor: "not-allowed" }} > <div className="h4">{friendlyStr(localTimezone)} (Local time)</div> </div> diff --git a/src/App/pages/UNIXTime.tsx b/src/App/pages/UNIXTime.tsx @@ -1,38 +1,38 @@ -import React from 'react'; -import moment from 'moment-timezone'; -import { Link } from 'react-router-dom'; +import React from "react"; +import moment from "moment-timezone"; +import { Link } from "react-router-dom"; -import { basePath, localTimezone } from '../../utils'; -import TimezoneInput from '../comps/TimezoneInput'; +import { basePath, localTimezone } from "../../utils"; +import TimezoneInput from "../comps/TimezoneInput"; function UNIXTime(): JSX.Element { - const timestamp = +window.location.pathname.replace('/', '') * 1000; + const timestamp = +window.location.pathname.replace("/", "") * 1000; const [TZ, setTZ] = React.useState<string>(localTimezone); const urlTime = moment.tz(timestamp, TZ); const rightNow = Date.now(); - const isWas = urlTime.valueOf() >= rightNow ? 'is' : 'was'; + const isWas = urlTime.valueOf() >= rightNow ? "is" : "was"; const [instance, setInstance] = React.useState<moment.Moment>(urlTime); const [displayTime, setDisplayTime] = React.useState<string>( - instance.format('HH:mm MMM DD, YYYY Z (z)') + instance.format("HH:mm MMM DD, YYYY Z (z)") ); const [timezone, setTimezone] = React.useState<string>( - instance.format('Z (z)') + instance.format("Z (z)") ); function handleClick() { setInstance(moment.tz(timestamp, TZ)); - setDisplayTime(instance.format('HH:mm MMM DD, YYYY Z (z)')); - setTimezone(instance.format('Z (z)')); + setDisplayTime(instance.format("HH:mm MMM DD, YYYY Z (z)")); + setTimezone(instance.format("Z (z)")); } function handleTimezoneChange(tz: React.SetStateAction<string>) { setTZ(tz); - setInstance(moment.tz(timestamp, '' + tz)); + setInstance(moment.tz(timestamp, "" + tz)); } return ( diff --git a/src/index.tsx b/src/index.tsx @@ -1,13 +1,13 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import App from './App/index'; -import * as serviceWorker from './serviceWorker'; +import React from "react"; +import ReactDOM from "react-dom"; +import App from "./App/index"; +import * as serviceWorker from "./serviceWorker"; ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode>, - document.getElementById('root') + document.getElementById("root") ); // If you want your app to work offline and load faster, you can change diff --git a/src/serviceWorker.ts b/src/serviceWorker.ts @@ -11,9 +11,9 @@ // opt-in, read https://bit.ly/CRA-PWA const isLocalhost = Boolean( - window.location.hostname === 'localhost' || + window.location.hostname === "localhost" || // [::1] is the IPv6 localhost address. - window.location.hostname === '[::1]' || + window.location.hostname === "[::1]" || // 127.0.0.0/8 are considered localhost for IPv4. window.location.hostname.match( /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ @@ -26,12 +26,9 @@ type Config = { }; export function register(config?: Config) { - if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { + if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) { // The URL constructor is available in all browsers that support SW. - const publicUrl = new URL( - process.env.PUBLIC_URL, - window.location.href - ); + const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); if (publicUrl.origin !== window.location.origin) { // Our service worker won't work if PUBLIC_URL is on a different origin // from what our page is served on. This might happen if a CDN is used to @@ -39,7 +36,7 @@ export function register(config?: Config) { return; } - window.addEventListener('load', () => { + window.addEventListener("load", () => { const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; if (isLocalhost) { @@ -50,8 +47,8 @@ export function register(config?: Config) { // service worker/PWA documentation. navigator.serviceWorker.ready.then(() => { console.log( - 'This web app is being served cache-first by a service ' + - 'worker. To learn more, visit https://bit.ly/CRA-PWA' + "This web app is being served cache-first by a service " + + "worker. To learn more, visit https://bit.ly/CRA-PWA" ); }); } else { @@ -65,21 +62,21 @@ export function register(config?: Config) { function registerValidSW(swUrl: string, config?: Config) { navigator.serviceWorker .register(swUrl) - .then(registration => { + .then((registration) => { registration.onupdatefound = () => { const installingWorker = registration.installing; if (installingWorker == null) { return; } installingWorker.onstatechange = () => { - if (installingWorker.state === 'installed') { + if (installingWorker.state === "installed") { if (navigator.serviceWorker.controller) { // At this point, the updated precached content has been fetched, // but the previous service worker will still serve the older // content until all client tabs are closed. console.log( - 'New content is available and will be used when all ' + - 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' + "New content is available and will be used when all " + + "tabs for this page are closed. See https://bit.ly/CRA-PWA." ); // Execute callback @@ -90,7 +87,7 @@ function registerValidSW(swUrl: string, config?: Config) { // At this point, everything has been precached. // It's the perfect time to display a // "Content is cached for offline use." message. - console.log('Content is cached for offline use.'); + console.log("Content is cached for offline use."); // Execute callback if (config && config.onSuccess) { @@ -101,25 +98,25 @@ function registerValidSW(swUrl: string, config?: Config) { }; }; }) - .catch(error => { - console.error('Error during service worker registration:', error); + .catch((error) => { + console.error("Error during service worker registration:", error); }); } function checkValidServiceWorker(swUrl: string, config?: Config) { // Check if the service worker can be found. If it can't reload the page. fetch(swUrl, { - headers: { 'Service-Worker': 'script' } + headers: { "Service-Worker": "script" }, }) - .then(response => { + .then((response) => { // Ensure service worker exists, and that we really are getting a JS file. - const contentType = response.headers.get('content-type'); + const contentType = response.headers.get("content-type"); if ( response.status === 404 || - (contentType != null && contentType.indexOf('javascript') === -1) + (contentType != null && contentType.indexOf("javascript") === -1) ) { // No service worker found. Probably a different app. Reload the page. - navigator.serviceWorker.ready.then(registration => { + navigator.serviceWorker.ready.then((registration) => { registration.unregister().then(() => { window.location.reload(); }); @@ -131,18 +128,18 @@ function checkValidServiceWorker(swUrl: string, config?: Config) { }) .catch(() => { console.log( - 'No internet connection found. App is running in offline mode.' + "No internet connection found. App is running in offline mode." ); }); } export function unregister() { - if ('serviceWorker' in navigator) { + if ("serviceWorker" in navigator) { navigator.serviceWorker.ready - .then(registration => { + .then((registration) => { registration.unregister(); }) - .catch(error => { + .catch((error) => { console.error(error.message); }); } diff --git a/src/setupTests.ts b/src/setupTests.ts @@ -2,4 +2,4 @@ // allows you to do things like: // expect(element).toHaveTextContent(/react/i) // learn more: https://github.com/testing-library/jest-dom -import '@testing-library/jest-dom/extend-expect'; +import "@testing-library/jest-dom/extend-expect"; diff --git a/src/utils/index.ts b/src/utils/index.ts @@ -1,16 +1,16 @@ -import moment from 'moment-timezone'; +import moment from "moment-timezone"; -import { IDisplayTime } from '../utils/interfaces'; +import { IDisplayTime, IGetAbbr } from "../utils/interfaces"; /** * @description clears the zones in localStorage */ function clearTimezones<never>() { - localStorage.setItem('zones', '{}') + localStorage.setItem("zones", "{}"); } /** - * + * * @param fmtStr {string} Formatting string (ex. 'HH:mm:ss MMMM DD, YYYY') * @param time {moment.Moment} Time to be formatted * @param timezone {string} Timezone to set @@ -22,20 +22,20 @@ function displayTime({ fmtStr, time, timezone }: IDisplayTime) { /** * @description Convert a string like `foo_bar_baz` to `foo bar baz` - * @param {string} str + * @param {string} str */ function friendlyStr(str: string): string { - return str.replace(/_/g, ' '); + return str.replace(/_/g, " "); } /** - * + * * @description Obtain the abbreviation of a timezone * @param timezone {string} Time zone string * @param time {moment.Moment} moment object * @returns {string} */ -function getAbbr({ timezone, time }: { timezone: string, time: moment.Moment }): string { +function getAbbr({ timezone, time }: IGetAbbr): string { // @ts-ignore -- they most certainly won't be undefined return moment.tz.zone(timezone).abbr(time); } @@ -46,7 +46,7 @@ function getAbbr({ timezone, time }: { timezone: string, time: moment.Moment }): */ function getSavedZones<never>(): string[] | [] { // query localStorage to get JSON as string - const savedData: string = localStorage.getItem('zones') || '{}'; + const savedData: string = localStorage.getItem("zones") || "{}"; // extract array const savedZones: string[] = JSON.parse(savedData).list || []; return savedZones; @@ -58,10 +58,10 @@ function getSavedZones<never>(): string[] | [] { * @returns {moment.Moment} */ function getYesterday<never>(): moment.Moment { - const today = new Date() - const yesterday = new Date() + const today = new Date(); + const yesterday = new Date(); - yesterday.setDate(today.getDate() - 1) + yesterday.setDate(today.getDate() - 1); return moment(yesterday); } @@ -69,7 +69,7 @@ function getYesterday<never>(): moment.Moment { * @description Removes one zone from localStorage * @param {string} zone zone to be removed from the localStorage */ -function removeTimeZone(zone: string = ''): void { +function removeTimeZone(zone: string = ""): void { // get saved zones const savedZones = getSavedZones(); // filter out @@ -77,11 +77,11 @@ function removeTimeZone(zone: string = ''): void { // stringify JSON const newZonesStr = JSON.stringify({ list: updatedZones }); // save to localStorage - localStorage.setItem('zones', newZonesStr); + localStorage.setItem("zones", newZonesStr); } /** - * + * * @description takes in an array of timezones and updates the localStorage * @param timezone {string[]} An array of timezones */ @@ -93,7 +93,7 @@ function saveTimezones(timezone: string[] | [] = []) { // stringify JSON const newZonesStr = JSON.stringify({ list: newZones }); // save to localStorage - localStorage.setItem('zones', newZonesStr); + localStorage.setItem("zones", newZonesStr); } /** @@ -101,7 +101,7 @@ function saveTimezones(timezone: string[] | [] = []) { * @param {string} str */ function unfriendlyStr(str: string): string { - return str.replace(/ /g, '_'); + return str.replace(/ /g, "_"); } export { @@ -113,19 +113,19 @@ export { getYesterday, removeTimeZone, saveTimezones, - unfriendlyStr + unfriendlyStr, }; const basePath = process.env.PUBLIC_URL; -const DEFAULT_TZ = 'UTC'; -const HM = 'HH:mm'; -const HMMDY = 'HH:mm MMMM DD, YYYY'; -const HMSDMY = 'HH:mm:ss MMMM DD, YYYY'; +const DEFAULT_TZ = "UTC"; +const HM = "HH:mm"; +const HMMDY = "HH:mm MMMM DD, YYYY"; +const HMSDMY = "HH:mm:ss MMMM DD, YYYY"; const localTimezone = moment.tz.guess(); -const MAX_DATE = '2038-01-18'; +const MAX_DATE = "2038-01-18"; const timezoneList = moment.tz.names().sort(); const YEAR = new Date().getFullYear(); -const YMD = 'YYYY-MM-DD' +const YMD = "YYYY-MM-DD"; export { basePath, @@ -137,5 +137,5 @@ export { MAX_DATE, timezoneList, YEAR, - YMD -}; -\ No newline at end of file + YMD, +}; diff --git a/src/utils/interfaces.tsx b/src/utils/interfaces.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React from "react"; export interface IDisplayTime { fmtStr: string; @@ -29,6 +29,11 @@ export interface IFutureConverted { TZ2: string; } +export interface IGetAbbr { + time: moment.Moment; + timezone: string; +} + export interface IMoment { time: moment.Moment; } diff --git a/src/utils/useTime.ts b/src/utils/useTime.ts @@ -1,6 +1,5 @@ -import { useState, useEffect } from 'react'; -import moment from 'moment-timezone'; - +import { useState, useEffect } from "react"; +import moment from "moment-timezone"; /** * @description A custom hook which returns the current time as a moment object. @@ -22,4 +21,4 @@ function useTime<never>(): moment.Moment { return time; } -export default useTime; -\ No newline at end of file +export default useTime; diff --git a/yarn.lock b/yarn.lock @@ -8572,6 +8572,11 @@ prepend-http@^1.0.0: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= +prettier@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.1.2.tgz#3050700dae2e4c8b67c4c3f666cdb8af405e1ce5" + integrity sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg== + pretty-bytes@^5.1.0: version "5.3.0" resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.3.0.tgz#f2849e27db79fb4d6cfe24764fc4134f165989f2"