diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml new file mode 100644 index 0000000..c4278b2 --- /dev/null +++ b/.github/workflows/macos.yml @@ -0,0 +1,18 @@ +name: MacOS + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: macos-latest + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js + uses: actions/setup-node@v2 + - run: npm install diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml new file mode 100644 index 0000000..772cbf3 --- /dev/null +++ b/.github/workflows/ubuntu.yml @@ -0,0 +1,18 @@ +name: Ubuntu + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js + uses: actions/setup-node@v2 + - run: npm install diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml new file mode 100644 index 0000000..c125980 --- /dev/null +++ b/.github/workflows/windows.yml @@ -0,0 +1,18 @@ +name: Windows + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: windows-latest + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js + uses: actions/setup-node@v2 + - run: npm install diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0125458 --- /dev/null +++ b/.gitignore @@ -0,0 +1,118 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env +.env.test +.env.production + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f199ea1 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 William Niemiec + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..61e4b8b --- /dev/null +++ b/README.md @@ -0,0 +1,73 @@ +![](https://github.com/wniemiec-component-react/remaining-time/blob/master/docs/img/logo/logo.jpg) + +

Remaining Time

+

Displays how many hours, minutes and seconds are left until a certain hour, minute and second.

+

+ + + + React Native compatibility + Release + License +

+
+ +## ❇ Introduction +React component that displays the time remaining until a certain hour, minute and second. + +## 🖼 Gallery + +
+
+ +## ❓ How to use +1. Install the component +``` +$ npm install --save @wniemiec-component-react/remaining-time +``` + +2. Import the component +``` +import RemainingTime from '@wniemiec-component-react/remaining-time'; +``` + +3. Use it +``` +[...] + +import React from 'react'; + +[...] + + + +[...] +``` + +## 📖 Documentation +| Property |Type|Description|Default| +|----------------|-------------------------------|-----------------------------|--------| +|hours |`number`|Hour | `23` | +|minutes |`number`|Minute| `59` | +|seconds |`number`|Second | `59` | +|fgColor |`string`|Text color | `"#000000"` | +|style |`object`|Custom style | `null` | + +## 🚩 Changelog +Details about each version are documented in the [releases section](https://github.com/wniemiec-component-react/remaining-time/releases). + +## 🤝 Contribute! +See the documentation on how you can contribute to the project [here](https://github.com/wniemiec-component-react/remaining-time/blob/master/CONTRIBUTING.md). + +## 📁 Files + +### / +| Name |Type|Description| +|----------------|-------------------------------|-----------------------------| +|docs |`Directory`|Documentation files| +|src |`Directory`| Source files| diff --git a/docs/img/screens/img1.png b/docs/img/screens/img1.png new file mode 100644 index 0000000..1a8c294 Binary files /dev/null and b/docs/img/screens/img1.png differ diff --git a/index.js b/index.js new file mode 100644 index 0000000..a474479 --- /dev/null +++ b/index.js @@ -0,0 +1,3 @@ +import RemainingTime from './src/RemainingTime'; + +export default RemainingTime; diff --git a/package.json b/package.json new file mode 100644 index 0000000..795209e --- /dev/null +++ b/package.json @@ -0,0 +1,25 @@ +{ + "name": "@wniemiec-component-react/remaining-time", + "version": "1.0.0", + "description": "Displays how many hours, minutes and seconds are left until a certain hour, minute and second.", + "main": "index.js", + "repository": { + "type": "git", + "url": "git+https://github.com/wniemiec-components-react/remaining-time.git" + }, + "keywords": [ + "wniemiec-component-react" + "wniemiec", + "component", + "react", + "remaining-time", + "remaining", + "time" + ], + "author": "William Niemiec (https://www.linkedin.com/in/williamniemiec)", + "license": "MIT", + "bugs": { + "url": "https://github.com/wniemiec-components-react/remaining-time/issues" + }, + "homepage": "https://github.com/wniemiec-components-react/remaining-time#readme" +} diff --git a/src/RemainingTime/index.js b/src/RemainingTime/index.js new file mode 100644 index 0000000..931e268 --- /dev/null +++ b/src/RemainingTime/index.js @@ -0,0 +1,89 @@ +/** + * Copyright (c) William Niemiec. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + * @format + */ + +import React, { useState, useEffect } from 'react'; + +/** + * Displays how many hours, minutes and seconds are left until a certain hour, + * minute and second. + * + * @param {number} [hours=23] Hour + * @param {number} [minutes=59] Minute + * @param {number} [seconds=59] Second + */ +export default function RemainingTime({ hours=23, minutes=59, seconds=59, fgColor='#FFFFFF', style=null }) { + const [timeLeft, setTimeLeft] = useState(0); + + useEffect(() => { + let timerControl = startTimer(setTimeLeft, hours, minutes, seconds); + + return stopTimer(timerControl); // Stops counting when destroying the + // component + }, []); + + return timeLeft; +} + +function startTimer(setTimeLeft, hours, minutes, seconds) { + return setInterval( + () => timer(setTimeLeft, hours, minutes, seconds), + 1000 + ); +} + +function timer(setTimeLeft, hours, minutes, seconds) { + const begin = getCurrentTime(); + const end = getCurrentTimeUsing(hours, minutes, seconds); + + setTimeLeft(getRemainingTime(begin, end)); +} + +function getCurrentTime() { + return new Date().getTime(); +} + +function getCurrentTimeUsing(hours, minutes, seconds) { + let end = new Date(); + + end.setHours(hours); + end.setMinutes(minutes); + end.setSeconds(seconds); + + return end.getTime(); +} + +function getRemainingTime(begin, end) { + const diff = end - begin; + + const hours = Math.floor(diff / (1000 * 60 * 60)); + const minutes = Math.floor((diff / (1000 * 60)) - (hours * 60)); + const seconds = Math.floor((diff / (1000)) - (minutes * 60) - (hours * 60 * 60)); + + return formatTime(hours, minutes, seconds); +} + +function formatTime(hours, minutes, seconds) { + let formatedHours = hours.toString(); + let formatedMinutes = minutes.toString(); + let formatedSeconds = seconds.toString(); + + if (hours < 10 && hours > 0) + formatedHours = '0' + formatedHours + if (minutes < 10 && minutes > 0) + formatedMinutes = '0' + formatedMinutes + if (seconds < 10 && seconds > 0) + formatedSeconds = '0' + formatedSeconds + + return `${formatedHours}h ${formatedMinutes}min ${formatedSeconds}s`; +} + +function stopTimer(timerControl) { + return () => clearInterval(timerControl); +}