From d4ee83dcb70c5b71fbd3e8069727ecfedfdb0c2a Mon Sep 17 00:00:00 2001 From: Red Adaya Date: Wed, 20 Nov 2024 08:57:04 +0800 Subject: [PATCH] rating notification --- .../app/notification/notificationbubbles.tsx | 11 ++++ .../app/notification/notificationitem.tsx | 4 +- .../app/notification/notificationpopover.tsx | 4 +- frontend/app/notification/ratingbubble.less | 48 ++++++++++++++ frontend/app/notification/ratingbubble.tsx | 65 +++++++++++++++++++ frontend/types/custom.d.ts | 3 +- 6 files changed, 130 insertions(+), 5 deletions(-) create mode 100644 frontend/app/notification/ratingbubble.less create mode 100644 frontend/app/notification/ratingbubble.tsx diff --git a/frontend/app/notification/notificationbubbles.tsx b/frontend/app/notification/notificationbubbles.tsx index 159703c18..02dfcf691 100644 --- a/frontend/app/notification/notificationbubbles.tsx +++ b/frontend/app/notification/notificationbubbles.tsx @@ -6,6 +6,7 @@ import { FloatingPortal, useFloating, useInteractions } from "@floating-ui/react import { useAtomValue } from "jotai"; import { useEffect, useState } from "react"; import { NotificationItem } from "./notificationitem"; +import { RatingBubble } from "./ratingbubble"; import { useNotification } from "./usenotification"; import clsx from "clsx"; @@ -16,6 +17,7 @@ const NotificationBubbles = () => { notifications, hoveredId, hideNotification, + removeNotification, copyNotification, handleActionClick, formatTimestamp, @@ -60,6 +62,15 @@ const NotificationBubbles = () => { > {notifications.map((notif) => { if (notif.hidden) return null; + if (notif.componentType === "rating") { + return ( + + ); + } return ( { - const { id, title, message, icon, type, timestamp, persistent, actions } = notification; - const color = type === "error" ? "red" : type === "warning" ? "yellow" : "green"; + const { id, title, message, icon, statusType, timestamp, persistent, actions } = notification; + const color = statusType === "error" ? "red" : statusType === "warning" ? "yellow" : "green"; const nIcon = icon ? icon : "bell"; const renderCloseButton = () => { diff --git a/frontend/app/notification/notificationpopover.tsx b/frontend/app/notification/notificationpopover.tsx index 3ec233a8e..c6cf9bb2c 100644 --- a/frontend/app/notification/notificationpopover.tsx +++ b/frontend/app/notification/notificationpopover.tsx @@ -37,8 +37,8 @@ const NotificationPopover = () => { setNotificationPopoverMode(!notificationPopoverMode); }, [notificationPopoverMode]); - const hasErrors = notifications.some((n) => n.type === "error"); - const hasUpdate = notifications.some((n) => n.type === "update"); + const hasErrors = notifications.some((n) => n.statusType === "error"); + const hasUpdate = notifications.some((n) => n.statusType === "update"); const addOnClassNames = hasUpdate ? "solid green" : hasErrors ? "solid red" : "ghost grey"; diff --git a/frontend/app/notification/ratingbubble.less b/frontend/app/notification/ratingbubble.less new file mode 100644 index 000000000..5b26ba14a --- /dev/null +++ b/frontend/app/notification/ratingbubble.less @@ -0,0 +1,48 @@ +// Copyright 2024, Command Line Inc. +// SPDX-License-Identifier: Apache-2.0 + +.notification-title { + font-size: 13px; + font-style: normal; + font-weight: 500; + line-height: 18px; + margin-bottom: 3px; + color: var(--success-color); +} + +.notification-message { + font-size: 13px; + font-style: normal; + font-weight: 400; + line-height: 18px; + opacity: 0.7; +} + +.close-btn { + position: absolute; + top: 5px; + right: 5px; +} + +.rating-bubble { + position: relative; + display: flex; + width: 380px; + padding: 16px 24px 16px 16px; + align-items: flex-start; + gap: 12px; + border-radius: 8px; + border: 0.5px solid rgba(255, 255, 255, 0.12); + background: #232323; + box-shadow: 0px 8px 32px 0px rgba(0, 0, 0, 0.25); +} + +.notification-inner { + display: flex; + align-items: flex-start; + column-gap: 6px; +} + +&.hovered { + background: #292929; +} diff --git a/frontend/app/notification/ratingbubble.tsx b/frontend/app/notification/ratingbubble.tsx new file mode 100644 index 000000000..6203b3b17 --- /dev/null +++ b/frontend/app/notification/ratingbubble.tsx @@ -0,0 +1,65 @@ +// Copyright 2024, Command Line Inc. +// SPDX-License-Identifier: Apache-2.0 + +import { Button } from "@/element/button"; +import { makeIconClass } from "@/util/util"; +import clsx from "clsx"; +import { useState } from "react"; + +import "./ratingbubble.less"; + +interface RatingBubbleProps { + notification: NotificationType; + onRemove: (id: string) => void; +} + +const RatingBubble = ({ notification, onRemove }: RatingBubbleProps) => { + const { id, title, message } = notification; + const [hoveredButtons, setHoveredButtons] = useState<{ [key: number]: boolean }>({}); + + const handleRatingClick = (rating: number) => { + console.log("rating clicked"); + }; + + const handleMouseEnter = (buttonIndex: number) => { + setHoveredButtons((prev) => ({ ...prev, [buttonIndex]: true })); + }; + + const handleMouseLeave = (buttonIndex: number) => { + setHoveredButtons((prev) => ({ ...prev, [buttonIndex]: false })); + }; + + return ( +
+ +
+
+ {title &&
{title}
} + {message &&
{message}
} + {[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((rating) => ( + + ))} +
+
+
+ ); +}; + +export { RatingBubble }; diff --git a/frontend/types/custom.d.ts b/frontend/types/custom.d.ts index 809f4b3d6..2df6c3537 100644 --- a/frontend/types/custom.d.ts +++ b/frontend/types/custom.d.ts @@ -320,7 +320,8 @@ declare global { hidden?: boolean; actions?: NotificationActionType[]; persistent?: boolean; - type?: "error" | "update" | "info" | "warning"; + componentType?: "rating"; + statusType?: "error" | "update" | "info" | "warning"; }; interface AbstractWshClient {