diff --git a/dashboard/package-lock.json b/dashboard/package-lock.json index ec6d436000..ca5a2a9c1e 100644 --- a/dashboard/package-lock.json +++ b/dashboard/package-lock.json @@ -47,6 +47,7 @@ "cron-validator": "^1.3.1", "d3-array": "^2.11.0", "d3-time-format": "^3.0.0", + "date-fns": "^3.6.0", "dayjs": "^1.11.5", "deep-diff": "^1.0.2", "dotenv": "^8.2.0", @@ -3604,6 +3605,22 @@ "react-popper": "^2.2.5" } }, + "node_modules/@types/react-datepicker/node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, "node_modules/@types/react-dom": { "version": "18.0.11", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.11.tgz", @@ -7042,15 +7059,12 @@ "integrity": "sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg==" }, "node_modules/date-fns": { - "version": "2.29.3", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", - "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==", - "engines": { - "node": ">=0.11" - }, + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" } }, "node_modules/dayjs": { @@ -13733,6 +13747,21 @@ "react-dom": "^16.9.0 || ^17 || ^18" } }, + "node_modules/react-datepicker/node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, "node_modules/react-diff-viewer": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/react-diff-viewer/-/react-diff-viewer-3.1.1.tgz", @@ -20987,6 +21016,17 @@ "@types/react": "*", "date-fns": "^2.0.1", "react-popper": "^2.2.5" + }, + "dependencies": { + "date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.21.0" + } + } } }, "@types/react-dom": { @@ -23803,9 +23843,9 @@ "integrity": "sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg==" }, "date-fns": { - "version": "2.29.3", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", - "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==" + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==" }, "dayjs": { "version": "1.11.7", @@ -28921,6 +28961,16 @@ "prop-types": "^15.7.2", "react-onclickoutside": "^6.12.2", "react-popper": "^2.3.0" + }, + "dependencies": { + "date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "requires": { + "@babel/runtime": "^7.21.0" + } + } } }, "react-diff-viewer": { diff --git a/dashboard/package.json b/dashboard/package.json index 467d3350bf..253d7b9a3f 100644 --- a/dashboard/package.json +++ b/dashboard/package.json @@ -42,6 +42,7 @@ "cron-validator": "^1.3.1", "d3-array": "^2.11.0", "d3-time-format": "^3.0.0", + "date-fns": "^3.6.0", "dayjs": "^1.11.5", "deep-diff": "^1.0.2", "dotenv": "^8.2.0", diff --git a/dashboard/src/main/home/Home.tsx b/dashboard/src/main/home/Home.tsx index 5f7d97ab5e..986b404c5c 100644 --- a/dashboard/src/main/home/Home.tsx +++ b/dashboard/src/main/home/Home.tsx @@ -24,7 +24,7 @@ import { fakeGuardedRoute } from "shared/auth/RouteGuard"; import { Context } from "shared/Context"; import DeploymentTargetProvider from "shared/DeploymentTargetContext"; import { pushFiltered, pushQueryParams, type PorterUrl } from "shared/routing"; -import { relativeDate, timeFrom } from "shared/string_utils"; +import { intlFormatDistance, isPast } from "date-fns"; import midnight from "shared/themes/midnight"; import standard from "shared/themes/standard"; import { @@ -377,13 +377,7 @@ const Home: React.FC = (props) => { if (timestamp === "") { return true; } - - const diff = timeFrom(timestamp); - if (diff.when === "future") { - return false; - } - - return true; + return isPast(new Date(timestamp)) ? true : false; }; const showCardBanner = !hasPaymentEnabled; @@ -424,7 +418,7 @@ const Home: React.FC = (props) => { connect a valid payment method . Your free trial is ending {" "} - {relativeDate(plan.trial_info.ending_before, true)}. + {intlFormatDistance(Date.parse(plan.trial_info.ending_before), new Date())}. )} {!trialExpired && showBillingModal && ( diff --git a/dashboard/src/main/home/project-settings/BillingPage.tsx b/dashboard/src/main/home/project-settings/BillingPage.tsx index 81b9fab5dd..1ff1e36dd7 100644 --- a/dashboard/src/main/home/project-settings/BillingPage.tsx +++ b/dashboard/src/main/home/project-settings/BillingPage.tsx @@ -17,7 +17,7 @@ import { usePorterCredits, useSetDefaultPaymentMethod, } from "lib/hooks/useStripe"; -import { relativeDate } from "shared/string_utils"; +import { intlFormat, intlFormatDistance } from "date-fns"; import { Context } from "shared/Context"; import cardIcon from "assets/credit-card.svg"; @@ -82,8 +82,6 @@ function BillingPage(): JSX.Element { return (credits / 100).toFixed(2); }; - const readableDate = (s: string): string => new Date(s).toLocaleDateString(); - const onCreate = async (): Promise => { await refetchPaymentMethods({ throwOnError: false, cancelRefetch: false }); setShouldCreate(false); @@ -233,10 +231,10 @@ function BillingPage(): JSX.Element { plan.trial_info.ending_before !== "" ? ( Free trial ends{" "} - {relativeDate(plan.trial_info.ending_before, true)} + {intlFormatDistance(Date.parse(plan.trial_info.ending_before), new Date())} ) : ( - Started on {readableDate(plan.starting_on)} + Started on {intlFormat(Date.parse(plan.starting_on))} )}