From 72d0c250f59bfb607fdd63ba0d750a30509800dc Mon Sep 17 00:00:00 2001 From: Maciej Gierada Date: Thu, 20 Jun 2024 14:58:31 +0200 Subject: [PATCH] feat: add ohno button --- ui/package-lock.json | 78 +++++++++++++++++++++++- ui/package.json | 4 +- ui/src/app/layout.js | 9 ++- ui/src/app/page.js | 8 ++- ui/src/components/ActionButton/index.jsx | 39 ++++++++++++ ui/src/components/ui/sonner.jsx | 29 +++++++++ ui/src/utils/helper.js | 20 ++++++ 7 files changed, 181 insertions(+), 6 deletions(-) create mode 100644 ui/src/components/ActionButton/index.jsx create mode 100644 ui/src/components/ui/sonner.jsx create mode 100644 ui/src/utils/helper.js diff --git a/ui/package-lock.json b/ui/package-lock.json index d22d4df..0e2c6af 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -9,16 +9,18 @@ "version": "0.1.0", "dependencies": { "@radix-ui/react-popover": "^1.0.7", - "@radix-ui/react-slot": "^1.0.2", + "@radix-ui/react-slot": "^1.1.0", "axios": "1.7.2", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "date-fns": "^3.6.0", "lucide-react": "^0.394.0", "next": "14.2.4", + "next-themes": "^0.3.0", "react": "^18", "react-day-picker": "^8.10.1", "react-dom": "^18", + "sonner": "^1.5.0", "tailwind-merge": "^2.3.0", "tailwindcss-animate": "^1.0.7" }, @@ -684,6 +686,25 @@ } } }, + "node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-slot": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz", + "integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-popper": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.3.tgz", @@ -790,7 +811,7 @@ } } }, - "node_modules/@radix-ui/react-slot": { + "node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz", "integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==", @@ -809,6 +830,39 @@ } } }, + "node_modules/@radix-ui/react-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", + "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", + "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-use-callback-ref": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz", @@ -3966,6 +4020,16 @@ } } }, + "node_modules/next-themes": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.3.0.tgz", + "integrity": "sha512-/QHIrsYpd6Kfk7xakK4svpDI5mmXP0gfvCoJdGpZQ2TOrQZmsW0QxjaiLn8wbIKjtm4BTSqLoix4lxYYOnLJ/w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8 || ^17 || ^18", + "react-dom": "^16.8 || ^17 || ^18" + } + }, "node_modules/next/node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", @@ -4980,6 +5044,16 @@ "node": ">=8" } }, + "node_modules/sonner": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sonner/-/sonner-1.5.0.tgz", + "integrity": "sha512-FBjhG/gnnbN6FY0jaNnqZOMmB73R+5IiyYAw8yBj7L54ER7HB3fOSE5OFiQiE2iXWxeXKvg6fIP4LtVppHEdJA==", + "license": "MIT", + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, "node_modules/source-map-js": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", diff --git a/ui/package.json b/ui/package.json index 4fb5817..7077c21 100644 --- a/ui/package.json +++ b/ui/package.json @@ -11,16 +11,18 @@ }, "dependencies": { "@radix-ui/react-popover": "^1.0.7", - "@radix-ui/react-slot": "^1.0.2", + "@radix-ui/react-slot": "^1.1.0", "axios": "1.7.2", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "date-fns": "^3.6.0", "lucide-react": "^0.394.0", "next": "14.2.4", + "next-themes": "^0.3.0", "react": "^18", "react-day-picker": "^8.10.1", "react-dom": "^18", + "sonner": "^1.5.0", "tailwind-merge": "^2.3.0", "tailwindcss-animate": "^1.0.7" }, diff --git a/ui/src/app/layout.js b/ui/src/app/layout.js index 8d402bc..96a939d 100644 --- a/ui/src/app/layout.js +++ b/ui/src/app/layout.js @@ -1,9 +1,10 @@ "use client"; // Add this line to indicate the file is a client component -import { Inter } from "next/font/google"; import "./globals.css"; import { useEffect } from "react"; +import { Toaster } from "@/components/ui/sonner"; + export default function RootLayout({ children }) { useEffect(() => { document.documentElement.classList.add("dark"); @@ -11,7 +12,11 @@ export default function RootLayout({ children }) { return ( - {children} + + +
{children}
+ + ); } diff --git a/ui/src/app/page.js b/ui/src/app/page.js index 8bb0f49..ae4cb58 100644 --- a/ui/src/app/page.js +++ b/ui/src/app/page.js @@ -2,6 +2,7 @@ import CounterDisplay from "@/components/CounterDisplay"; import Callendar from "@/components/Callendar"; import { DisplayCard } from "@/components/Card"; import HealthStatus from "@/components/HealthStatus"; +import { ActionButton } from "@/components/ActionButton"; /** * @typedef {Object} CounterApiResponse @@ -114,7 +115,12 @@ const Home = async () => { Click dates to see the details.

-
+
+ +
); }; diff --git a/ui/src/components/ActionButton/index.jsx b/ui/src/components/ActionButton/index.jsx new file mode 100644 index 0000000..c9f6f22 --- /dev/null +++ b/ui/src/components/ActionButton/index.jsx @@ -0,0 +1,39 @@ +"use client"; +import { toast } from "sonner"; + +import { Button } from "@/components/ui/button"; +import formatCurrentDate from "@/utils/helper"; + +/** + * @typedef {Object} ActionButtonProps + * @property {string} toast_message - the message to be displayed on on the toast popup + * @property {string} cta_button - the call to action to be displayed on the button + */ + +/** + * ActionButton component + * @param {ActionButtonProps} actionButtonProps + * @returns {JSX.Element} + */ +export function ActionButton({ toast_message, cta_button }) { + return ( + + ); +} diff --git a/ui/src/components/ui/sonner.jsx b/ui/src/components/ui/sonner.jsx new file mode 100644 index 0000000..bd51a92 --- /dev/null +++ b/ui/src/components/ui/sonner.jsx @@ -0,0 +1,29 @@ +"use client"; +import { useTheme } from "next-themes" +import { Toaster as Sonner } from "sonner" + +const Toaster = ({ + ...props +}) => { + const { theme = "system" } = useTheme() + + return ( + () + ); +} + +export { Toaster } diff --git a/ui/src/utils/helper.js b/ui/src/utils/helper.js new file mode 100644 index 0000000..ae343ce --- /dev/null +++ b/ui/src/utils/helper.js @@ -0,0 +1,20 @@ +/* + * This function formats the current date and time in a human-readable format. + * @returns {string} formattedNow - The formatted date and time in the following format + * Thursday, June 20 at 2024 at 2:41 PM + */ +const formatCurrentDate = () => { + const options = { + weekday: "long", + year: "numeric", + month: "long", + day: "2-digit", + hour: "numeric", + minute: "2-digit", + hour12: true, + }; + const now = new Date(); + return now.toLocaleString("en-US", options).replace(/,([^,]*)$/, " at$1"); +}; + +export default formatCurrentDate;