diff --git a/components/SettingsButton.tsx b/components/SettingsButton.tsx new file mode 100644 index 0000000..e94d31d --- /dev/null +++ b/components/SettingsButton.tsx @@ -0,0 +1,11 @@ +export default function SettingsButton() { + return ( + <> + + + + + ); +} diff --git a/components/SettingsWrapper.tsx b/components/SettingsWrapper.tsx new file mode 100644 index 0000000..23e4805 --- /dev/null +++ b/components/SettingsWrapper.tsx @@ -0,0 +1,54 @@ +interface SettingsWrapperProps { + gbAvailable: number; + updateAvailable: (method: string) => void; + setGbAvailable: (gbAvailable: number) => void; + startDate: number; + setStartDate: (startDate: number) => void; +} + +export default function SettingsWrapper(props: SettingsWrapperProps) { + function updateStartDate(event: React.ChangeEvent) { + const updateDate = parseInt(event.target.value); + if (updateDate < 1) { + props.setStartDate(1); + } else if (updateDate > 31) { + props.setStartDate(31); + } else { + props.setStartDate(updateDate); + } + } + return ( +
+
+
+ + Data: + props.setGbAvailable(parseInt(e.target.value, 10))} + /> + GB + + {/*
+ props.updateAvailable("up")}> + props.updateAvailable("down")} + > +
*/} +
+ {/* + Renewal day: + props.setStartDate(parseInt(e.target.value, 10))} + /> + */} +
+
+ ); +} diff --git a/functions/dateFuncs.ts b/functions/dateFuncs.ts new file mode 100644 index 0000000..84f65df --- /dev/null +++ b/functions/dateFuncs.ts @@ -0,0 +1,4 @@ +export function daysBetween(date1: Date, date2: Date): number { + const oneDay = 24 * 60 * 60 * 1000; + return Math.round(Math.abs((date1.getTime() - date2.getTime()) / oneDay)); +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 72a0378..fe5c08b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "data-usage-v2", + "name": "data-usage", "lockfileVersion": 2, "requires": true, "packages": { @@ -2849,9 +2849,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001335", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001335.tgz", - "integrity": "sha512-ddP1Tgm7z2iIxu6QTtbZUv6HJxSaV/PZeSrWFZtbY4JZ69tOeNhBCl3HyRQgeNZKE5AOn1kpV7fhljigy0Ty3w==", + "version": "1.0.30001358", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001358.tgz", + "integrity": "sha512-hvp8PSRymk85R20bsDra7ZTCpSVGN/PAz9pSAjPSjKC+rNmnUk5vCRgJwiTT/O4feQ/yu/drvZYpKxxhbFuChw==", "funding": [ { "type": "opencollective", @@ -8916,9 +8916,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001335", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001335.tgz", - "integrity": "sha512-ddP1Tgm7z2iIxu6QTtbZUv6HJxSaV/PZeSrWFZtbY4JZ69tOeNhBCl3HyRQgeNZKE5AOn1kpV7fhljigy0Ty3w==" + "version": "1.0.30001358", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001358.tgz", + "integrity": "sha512-hvp8PSRymk85R20bsDra7ZTCpSVGN/PAz9pSAjPSjKC+rNmnUk5vCRgJwiTT/O4feQ/yu/drvZYpKxxhbFuChw==" }, "chalk": { "version": "4.1.2", diff --git a/pages/index.tsx b/pages/index.tsx index 3ef8199..c882f37 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,83 +1,96 @@ -import Head from 'next/head' -import { useEffect, useState } from 'react'; +import Head from "next/head"; +import { useEffect, useState } from "react"; +import SettingsButton from "../components/SettingsButton"; +import SettingsWrapper from "../components/SettingsWrapper"; export default function Home() { - const [gbAvailable, setGbAvailable] = useState(0) - useEffect(() => { - if (typeof window !== "undefined") { - const available = window.localStorage.getItem('gbAvailable'); - if (available) { - setGbAvailable(parseInt(available)); + const [gbAvailable, setGbAvailable] = useState(0); + const [startDate, setStartDate] = useState(1); + useEffect(() => { + if (typeof window !== "undefined") { + const available = window.localStorage.getItem("gbAvailable"); + if (available) { + setGbAvailable(parseInt(available)); + } else { + window.localStorage.setItem("gbAvailable", "40"); + setGbAvailable(40); + } + + const start = window.localStorage.getItem("startDate"); + if (start) { + setStartDate(parseInt(start)); } else { - window.localStorage.setItem('gbAvailable', '40'); - setGbAvailable(40); + window.localStorage.setItem("startDate", "1"); + setStartDate(1); } - } - }, []) + } + }, []); + + + - const getRemainingData = () => { - const today = new Date() - const currentDate = today.getDate(); - const lastDayOfMonth = new Date(today.getFullYear(), today.getMonth() + 1, 0).getDate(); - const mbAvailable = gbAvailable * 1000; - const mbPerDay = mbAvailable / lastDayOfMonth; - const mbLeft = Math.round(mbAvailable - mbPerDay * currentDate) || 0; - function numberWithCommas(x: number) { - return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, "."); - } - return numberWithCommas(mbLeft) - } - const getPerDayData = () => { - const today = new Date() - const mbAvailable = gbAvailable * 1000; - const lastDayOfMonth = new Date(today.getFullYear(), today.getMonth() + 1, 0).getDate(); - const mbPerDay = mbAvailable / lastDayOfMonth; - return Math.round(mbPerDay) - } + const getRemainingData = () => { + const today = new Date(); + const currentDate = today.getDate(); + const lastDayOfMonth = new Date(today.getFullYear(), today.getMonth() + 1, 0).getDate(); + const mbAvailable = gbAvailable * 1000; + const mbPerDay = mbAvailable / lastDayOfMonth; + const mbLeft = Math.round(mbAvailable - mbPerDay * currentDate) || 0; + function numberWithCommas(x: number) { + return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, "."); + } + return numberWithCommas(mbLeft); + }; - const updateAvailable = (method:string) => { - if (method === 'up') { - setGbAvailable(gbAvailable + 1); - window.localStorage.setItem('gbAvailable', (gbAvailable + 1).toString()); - } else { - if (gbAvailable === 0) { - return; - } - setGbAvailable(gbAvailable - 1); - window.localStorage.setItem('gbAvailable', (gbAvailable - 1).toString()); - } - } - return ( -
- - Data Usage - - - - - -
-
-
- updateAvailable('up')}> - updateAvailable('down')}> -
- - {gbAvailable} GB - -
-
-
-

-
- You should have {getRemainingData()} MB left with -
-
- {getPerDayData()} MB available per day -
-

-
-
- ) + const getPerDayData = () => { + const today = new Date(); + const mbAvailable = gbAvailable * 1000; + const lastDayOfMonth = new Date(today.getFullYear(), today.getMonth() + 1, 0).getDate(); + const mbPerDay = mbAvailable / lastDayOfMonth; + return Math.round(mbPerDay); + }; + + const updateAvailable = (method: string) => { + if (method === "up") { + setGbAvailable(gbAvailable + 1); + window.localStorage.setItem("gbAvailable", (gbAvailable + 1).toString()); + } else { + if (gbAvailable === 0) { + return; + } + setGbAvailable(gbAvailable - 1); + window.localStorage.setItem("gbAvailable", (gbAvailable - 1).toString()); + } + }; + return ( +
+ + Data Usage + + + + +
+

+
+ You should have {getRemainingData()} MB + left with +
+
+ {getPerDayData()} MB available per day +
+

+
+
+ ); } diff --git a/public/sw.js.map b/public/sw.js.map index f377e90..55f36fb 100644 --- a/public/sw.js.map +++ b/public/sw.js.map @@ -1 +1 @@ -{"version":3,"file":"sw.js","sources":["../../../../tmp/cea38e95b151a2c67ccaa1b967c04524/sw.js"],"sourcesContent":["import {registerRoute as workbox_routing_registerRoute} from '/home/timo/github-projects/data-usage-v2/node_modules/workbox-routing/registerRoute.mjs';\nimport {NetworkFirst as workbox_strategies_NetworkFirst} from '/home/timo/github-projects/data-usage-v2/node_modules/workbox-strategies/NetworkFirst.mjs';\nimport {NetworkOnly as workbox_strategies_NetworkOnly} from '/home/timo/github-projects/data-usage-v2/node_modules/workbox-strategies/NetworkOnly.mjs';\nimport {clientsClaim as workbox_core_clientsClaim} from '/home/timo/github-projects/data-usage-v2/node_modules/workbox-core/clientsClaim.mjs';/**\n * Welcome to your Workbox-powered service worker!\n *\n * You'll need to register this file in your web app.\n * See https://goo.gl/nhQhGp\n *\n * The rest of the code is auto-generated. Please don't update this file\n * directly; instead, make changes to your Workbox build configuration\n * and re-run your build process.\n * See https://goo.gl/2aRDsh\n */\n\n\nimportScripts(\n \n);\n\n\n\n\n\n\n\nself.skipWaiting();\n\nworkbox_core_clientsClaim();\n\n\n\nworkbox_routing_registerRoute(\"/\", new workbox_strategies_NetworkFirst({ \"cacheName\":\"start-url\", plugins: [{ cacheWillUpdate: async ({request, response, event, state}) => { if (response && response.type === 'opaqueredirect') { return new Response(response.body, {status: 200, statusText: 'OK', headers: response.headers}); } return response; } }] }), 'GET');\nworkbox_routing_registerRoute(/.*/i, new workbox_strategies_NetworkOnly({ \"cacheName\":\"dev\", plugins: [] }), 'GET');\n\n\n\n\n"],"names":["importScripts","self","skipWaiting","workbox_core_clientsClaim","workbox_routing_registerRoute","workbox_strategies_NetworkFirst","plugins","cacheWillUpdate","request","response","event","state","type","Response","body","status","statusText","headers","workbox_strategies_NetworkOnly"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAG8I;EAC9I;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;EAGAA,aAAa;EAUbC,IAAI,CAACC,WAAL;AAEAC,sBAAyB;AAIzBC,uBAA6B,CAAC,GAAD,EAAM,IAAIC,oBAAJ,CAAoC;EAAE,eAAY,WAAd;EAA2BC,EAAAA,OAAO,EAAE,CAAC;EAAEC,IAAAA,eAAe,EAAE,OAAO;EAACC,MAAAA,OAAD;EAAUC,MAAAA,QAAV;EAAoBC,MAAAA,KAApB;EAA2BC,MAAAA;EAA3B,KAAP,KAA6C;EAAE,UAAIF,QAAQ,IAAIA,QAAQ,CAACG,IAAT,KAAkB,gBAAlC,EAAoD;EAAE,eAAO,IAAIC,QAAJ,CAAaJ,QAAQ,CAACK,IAAtB,EAA4B;EAACC,UAAAA,MAAM,EAAE,GAAT;EAAcC,UAAAA,UAAU,EAAE,IAA1B;EAAgCC,UAAAA,OAAO,EAAER,QAAQ,CAACQ;EAAlD,SAA5B,CAAP;EAAiG;;EAAC,aAAOR,QAAP;EAAkB;EAA5O,GAAD;EAApC,CAApC,CAAN,EAAmU,KAAnU,CAA7B;AACAL,uBAA6B,CAAC,KAAD,EAAQ,IAAIc,mBAAJ,CAAmC;EAAE,eAAY,KAAd;EAAqBZ,EAAAA,OAAO,EAAE;EAA9B,CAAnC,CAAR,EAAgF,KAAhF,CAA7B;;"} \ No newline at end of file +{"version":3,"file":"sw.js","sources":["../../../../tmp/34189892fefad158918d432731b17f44/sw.js"],"sourcesContent":["import {registerRoute as workbox_routing_registerRoute} from '/home/timo/professional-sites/data-usage/node_modules/workbox-routing/registerRoute.mjs';\nimport {NetworkFirst as workbox_strategies_NetworkFirst} from '/home/timo/professional-sites/data-usage/node_modules/workbox-strategies/NetworkFirst.mjs';\nimport {NetworkOnly as workbox_strategies_NetworkOnly} from '/home/timo/professional-sites/data-usage/node_modules/workbox-strategies/NetworkOnly.mjs';\nimport {clientsClaim as workbox_core_clientsClaim} from '/home/timo/professional-sites/data-usage/node_modules/workbox-core/clientsClaim.mjs';/**\n * Welcome to your Workbox-powered service worker!\n *\n * You'll need to register this file in your web app.\n * See https://goo.gl/nhQhGp\n *\n * The rest of the code is auto-generated. Please don't update this file\n * directly; instead, make changes to your Workbox build configuration\n * and re-run your build process.\n * See https://goo.gl/2aRDsh\n */\n\n\nimportScripts(\n \n);\n\n\n\n\n\n\n\nself.skipWaiting();\n\nworkbox_core_clientsClaim();\n\n\n\nworkbox_routing_registerRoute(\"/\", new workbox_strategies_NetworkFirst({ \"cacheName\":\"start-url\", plugins: [{ cacheWillUpdate: async ({request, response, event, state}) => { if (response && response.type === 'opaqueredirect') { return new Response(response.body, {status: 200, statusText: 'OK', headers: response.headers}); } return response; } }] }), 'GET');\nworkbox_routing_registerRoute(/.*/i, new workbox_strategies_NetworkOnly({ \"cacheName\":\"dev\", plugins: [] }), 'GET');\n\n\n\n\n"],"names":["importScripts","self","skipWaiting","workbox_core_clientsClaim","workbox_routing_registerRoute","workbox_strategies_NetworkFirst","plugins","cacheWillUpdate","request","response","event","state","type","Response","body","status","statusText","headers","workbox_strategies_NetworkOnly"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAG8I;EAC9I;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;EAGAA,aAAa;EAUbC,IAAI,CAACC,WAAL;AAEAC,sBAAyB;AAIzBC,uBAA6B,CAAC,GAAD,EAAM,IAAIC,oBAAJ,CAAoC;EAAE,eAAY,WAAd;EAA2BC,EAAAA,OAAO,EAAE,CAAC;EAAEC,IAAAA,eAAe,EAAE,OAAO;EAACC,MAAAA,OAAD;EAAUC,MAAAA,QAAV;EAAoBC,MAAAA,KAApB;EAA2BC,MAAAA;EAA3B,KAAP,KAA6C;EAAE,UAAIF,QAAQ,IAAIA,QAAQ,CAACG,IAAT,KAAkB,gBAAlC,EAAoD;EAAE,eAAO,IAAIC,QAAJ,CAAaJ,QAAQ,CAACK,IAAtB,EAA4B;EAACC,UAAAA,MAAM,EAAE,GAAT;EAAcC,UAAAA,UAAU,EAAE,IAA1B;EAAgCC,UAAAA,OAAO,EAAER,QAAQ,CAACQ;EAAlD,SAA5B,CAAP;EAAiG;;EAAC,aAAOR,QAAP;EAAkB;EAA5O,GAAD;EAApC,CAApC,CAAN,EAAmU,KAAnU,CAA7B;AACAL,uBAA6B,CAAC,KAAD,EAAQ,IAAIc,mBAAJ,CAAmC;EAAE,eAAY,KAAd;EAAqBZ,EAAAA,OAAO,EAAE;EAA9B,CAAnC,CAAR,EAAgF,KAAhF,CAA7B;;"} \ No newline at end of file diff --git a/styles/globals.css b/styles/globals.css index 497e240..451916d 100644 --- a/styles/globals.css +++ b/styles/globals.css @@ -136,4 +136,16 @@ .chevron.bottom:before { top: 0; transform: rotate(135deg); +} + +/* Chrome, Safari, Edge, Opera */ +input::-webkit-outer-spin-button, +input::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +/* Firefox */ +input[type=number] { + -moz-appearance: textfield; } \ No newline at end of file