diff --git a/package.json b/package.json index 20df85298..760960346 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "@radix-ui/react-label": "^2.1.0", "@radix-ui/react-popover": "^1.1.1", "@radix-ui/react-select": "^2.1.1", + "@radix-ui/react-separator": "^1.1.0", "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-switch": "^1.1.0", "@radix-ui/react-tabs": "^1.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b028ab784..b195f48f8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -38,6 +38,9 @@ importers: '@radix-ui/react-select': specifier: ^2.1.1 version: 2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-separator': + specifier: ^1.1.0 + version: 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-slot': specifier: ^1.1.0 version: 1.1.0(@types/react@18.3.3)(react@18.3.1) @@ -8297,8 +8300,8 @@ snapshots: '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.5.4) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.17.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.17.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.17.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0) eslint-plugin-jsx-a11y: 6.9.0(eslint@8.57.0) eslint-plugin-react: 7.35.0(eslint@8.57.0) eslint-plugin-react-hooks: 4.6.2(eslint@8.57.0) @@ -8329,13 +8332,13 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.17.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0))(eslint@8.57.0): + eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0): dependencies: debug: 4.3.5 enhanced-resolve: 5.17.1 eslint: 8.57.0 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.17.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.17.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.17.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0) fast-glob: 3.3.2 get-tsconfig: 4.7.6 is-core-module: 2.15.0 @@ -8346,18 +8349,28 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.17.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): + eslint-module-utils@2.8.1(@typescript-eslint/parser@7.17.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0): + dependencies: + debug: 3.2.7 + optionalDependencies: + '@typescript-eslint/parser': 7.17.0(eslint@8.57.0)(typescript@5.5.4) + eslint: 8.57.0 + eslint-import-resolver-node: 0.3.9 + transitivePeerDependencies: + - supports-color + + eslint-module-utils@2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.5.4) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.17.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0))(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.17.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): + eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.17.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0): dependencies: array-includes: 3.1.8 array.prototype.findlastindex: 1.2.5 @@ -8367,7 +8380,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.17.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.17.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0) hasown: 2.0.2 is-core-module: 2.15.0 is-glob: 4.0.3 @@ -8378,7 +8391,7 @@ snapshots: semver: 6.3.1 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.5.4) + '@typescript-eslint/parser': 7.17.0(eslint@8.57.0)(typescript@5.5.4) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack diff --git a/src/app/dashboard/(admin)/_components/unread-notification-card/UnreadNotificationCard.tsx b/src/app/dashboard/(admin)/_components/unread-notification-card/UnreadNotificationCard.tsx index fd62ebbe3..f6454f204 100644 --- a/src/app/dashboard/(admin)/_components/unread-notification-card/UnreadNotificationCard.tsx +++ b/src/app/dashboard/(admin)/_components/unread-notification-card/UnreadNotificationCard.tsx @@ -1,6 +1,10 @@ +"use client"; + import { BellRing } from "lucide-react"; import { FC } from "react"; +import { useNotificationStore } from "~/app/dashboard/(user-dashboard)/settings/notification/action/notification-store"; +import { notificationSettingsProperties } from "~/app/dashboard/(user-dashboard)/settings/notification/types/notification-settings.types"; import CustomButton from "~/components/common/common-button/common-button"; import { Card, @@ -29,6 +33,12 @@ const UnreadNotificationCard: FC = ({ unreadCount = 0, ...properties }) => { + const { settings, updateSettings } = useNotificationStore(); + + const handleToggleSwitch = (name: keyof notificationSettingsProperties) => { + updateSettings({ [name]: !settings[name] }); + }; + return ( = ({
- +

Push Notifications @@ -53,7 +63,13 @@ const UnreadNotificationCard: FC = ({ Send notifications to device.

- + + handleToggleSwitch("mobile_push_notifications") + } + name="mobile_push_notifications" + />
{notificationsPreview.map((preview, index) => ( @@ -86,6 +102,9 @@ const UnreadNotificationCard: FC = ({ variant="primary" isDisabled={unreadCount === 0} className="w-full bg-primary" + onClick={() => { + // MARK ALL NOTIFICATION LOGIC + }} > Mark all as read diff --git a/src/app/dashboard/(admin)/admin/email/edit-in-buit-templates/[templateId]/page.tsx b/src/app/dashboard/(admin)/admin/email/edit-in-buit-templates/[templateId]/page.tsx index ec3fe4e30..dbe37e831 100644 --- a/src/app/dashboard/(admin)/admin/email/edit-in-buit-templates/[templateId]/page.tsx +++ b/src/app/dashboard/(admin)/admin/email/edit-in-buit-templates/[templateId]/page.tsx @@ -1,3 +1,5 @@ +"use client"; + import { EllipsisVertical, Eye, Redo, Undo } from "lucide-react"; import { Button } from "~/components/common/common-button"; diff --git a/src/app/dashboard/(user-dashboard)/_components/layout/navbar/index.tsx b/src/app/dashboard/(user-dashboard)/_components/layout/navbar/index.tsx index f517d2e58..018eb19d9 100644 --- a/src/app/dashboard/(user-dashboard)/_components/layout/navbar/index.tsx +++ b/src/app/dashboard/(user-dashboard)/_components/layout/navbar/index.tsx @@ -45,6 +45,7 @@ const navlinks = [ const UserNavbar = () => { const pathname = usePathname(); const currentPath = pathname?.split("/")[2]; + return (
-
+
= ({ children }) => { return (
-
+
{children}
diff --git a/src/app/dashboard/(user-dashboard)/settings/notification/_components/header.tsx b/src/app/dashboard/(user-dashboard)/settings/notification/_components/header.tsx index b66562fe0..986f39353 100644 --- a/src/app/dashboard/(user-dashboard)/settings/notification/_components/header.tsx +++ b/src/app/dashboard/(user-dashboard)/settings/notification/_components/header.tsx @@ -1,10 +1,15 @@ +import { Separator } from "~/components/ui/separator"; + interface IProperties { notificationTitle: string; } const NotificationHeader = ({ notificationTitle }: IProperties) => { return ( -

{notificationTitle}

+
+

{notificationTitle}

+ +
); }; diff --git a/src/app/dashboard/(user-dashboard)/settings/notification/_components/notification-switch-box.tsx b/src/app/dashboard/(user-dashboard)/settings/notification/_components/notification-switch-box.tsx index 9ef72b82d..2e5c5de9d 100644 --- a/src/app/dashboard/(user-dashboard)/settings/notification/_components/notification-switch-box.tsx +++ b/src/app/dashboard/(user-dashboard)/settings/notification/_components/notification-switch-box.tsx @@ -1,22 +1,35 @@ import { Switch } from "~/components/ui/switch"; +import { notificationSettingsProperties } from "../types/notification-settings.types"; interface IProperties { title: string; description: string; + name: keyof notificationSettingsProperties; + isChecked: boolean; + onToggle: (name: keyof notificationSettingsProperties) => void; + className?: string; // Add className as an optional property } -const NotificationSwitchBox = ({ title, description }: IProperties) => { +export const NotificationSwitchBox = ({ + title, + description, + name, + isChecked, + onToggle, +}: IProperties) => { return ( -
-
-

{title}

-

{description}

+
+
+

+ {title} +

+

+ {description} +

- + onToggle(name)} />
); }; - -export default NotificationSwitchBox; diff --git a/src/app/dashboard/(user-dashboard)/settings/notification/action/notification-store.ts b/src/app/dashboard/(user-dashboard)/settings/notification/action/notification-store.ts new file mode 100644 index 000000000..2f6a8d1f4 --- /dev/null +++ b/src/app/dashboard/(user-dashboard)/settings/notification/action/notification-store.ts @@ -0,0 +1,28 @@ +import create from "zustand"; + +import { notificationSettingsProperties } from "../types/notification-settings.types"; + +// Define the Zustand store +interface NotificationStore { + settings: notificationSettingsProperties; + updateSettings: ( + newSettings: Partial, + ) => void; +} + +export const useNotificationStore = create((set) => ({ + settings: { + mobile_push_notifications: false, + email_notification_activity_in_workspace: false, + email_notification_always_send_email_notifications: false, + email_notification_email_digest: false, + email_notification_announcement_and_update_emails: false, + slack_notifications_activity_on_your_workspace: false, + slack_notifications_always_send_email_notifications: false, + slack_notifications_announcement_and_update_emails: false, + }, + updateSettings: (newSettings: Partial) => + set((state) => ({ + settings: { ...state.settings, ...newSettings }, + })), +})); diff --git a/src/app/dashboard/(user-dashboard)/settings/notification/action/notification.ts b/src/app/dashboard/(user-dashboard)/settings/notification/action/notification.ts new file mode 100644 index 000000000..a86ecfe0a --- /dev/null +++ b/src/app/dashboard/(user-dashboard)/settings/notification/action/notification.ts @@ -0,0 +1,66 @@ +import axios from "axios"; + +/** + * THIS API IMPLEMENTATION ARE NOT WORKING CURRENTLY, THE BACKEND WOULD BE INTEGRTED SHORTLY. ☺️ + */ + +const notification_id = undefined; + +export const createNotification = async () => { + const data = { + message: `Welcome to HNGi8`, + }; + try { + await axios.post("/notifications", data); + } catch (error) { + return error; + } +}; + +export const RetrieveUserNotificationSettings = async () => { + try { + await axios.get("/notification-settings"); + } catch (error) { + return error; + } +}; + +export const updateUserNotificationSettings = async (settings: object) => { + try { + await axios.patch("/notification-settings", settings); + } catch (error) { + return error; + } +}; + +export const RetrieveUserNotificationAll = async () => { + try { + await axios.get("/notifications"); + } catch (error) { + return error; + } +}; + +export const RetrieveUserUnreadNotification = async () => { + try { + await axios.get("/notifications?_read=false"); + } catch (error) { + return error; + } +}; + +export const markNotificationAsRead = async () => { + try { + await axios.patch(`/notifications/${notification_id}`); + } catch (error) { + return error; + } +}; + +export const markAllNotificationAsRead = async () => { + try { + await axios.patch("/notifications"); + } catch (error) { + return error; + } +}; diff --git a/src/app/dashboard/(user-dashboard)/settings/notification/page.tsx b/src/app/dashboard/(user-dashboard)/settings/notification/page.tsx index e6f20ba1f..d486c9446 100644 --- a/src/app/dashboard/(user-dashboard)/settings/notification/page.tsx +++ b/src/app/dashboard/(user-dashboard)/settings/notification/page.tsx @@ -1,22 +1,32 @@ "use client"; -import { Check } from "lucide-react"; +import { Check, ChevronLeft } from "lucide-react"; import { useState } from "react"; import CustomButton from "~/components/common/common-button/common-button"; import NotificationSettingSavedModal from "~/components/common/modals/notification-settings-saved"; import NotificationHeader from "./_components/header"; -import NotificationSwitchBox from "./_components/notification-switch-box"; +import { NotificationSwitchBox } from "./_components/notification-switch-box"; +import { useNotificationStore } from "./action/notification-store"; const NotificationPage = () => { + const { settings, updateSettings } = useNotificationStore(); const [isOpen, setOpen] = useState(false); - const handleOpenModal = () => { + const handleToggleSwitch = (name: keyof typeof settings) => { + updateSettings({ [name]: !settings[name] }); + }; + + const handleSaveChanges = () => { setOpen(true); }; return (
+
+ + Notification +
{/* NOTIFICATION ALERT */}
@@ -25,101 +35,108 @@ const NotificationPage = () => { description={ "Receive push notifications on mentions and comments via your mobile app" } + name="mobile_push_notifications" + isChecked={settings.mobile_push_notifications} + onToggle={handleToggleSwitch} />
{/* EMAIL NOTIFICATION */}
- {/* option 1 */} -
- -
- {/* option 2 */} -
- -
- {/* option 3 */} -
- -
- {/* option 4 */} -
- -
+ + + +
{/* SLACK NOTIFICATIONS */}
- {/* option 1 */} -
- -
- {/* option 2 */} -
- -
- {/* option 3 */} -
- -
+ + +
-
+
} isLeftIconVisible={true} - isLoading={false} - isDisabled={false} - onClick={handleOpenModal} + onClick={handleSaveChanges} > Save Changes -
+ setOpen(false)} + />
); }; diff --git a/src/app/dashboard/(user-dashboard)/settings/notification/types/notification-settings.types.ts b/src/app/dashboard/(user-dashboard)/settings/notification/types/notification-settings.types.ts new file mode 100644 index 000000000..505ca8814 --- /dev/null +++ b/src/app/dashboard/(user-dashboard)/settings/notification/types/notification-settings.types.ts @@ -0,0 +1,10 @@ +export type notificationSettingsProperties = { + mobile_push_notifications: boolean; + email_notification_activity_in_workspace: boolean; + email_notification_always_send_email_notifications: boolean; + email_notification_email_digest: boolean; + email_notification_announcement_and_update_emails: boolean; + slack_notifications_activity_on_your_workspace: boolean; + slack_notifications_always_send_email_notifications: boolean; + slack_notifications_announcement_and_update_emails: boolean; +}; diff --git a/src/app/globals.css b/src/app/globals.css index 450351d4c..a5043fd7e 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -166,7 +166,7 @@ /* Custom Scrollbar Styling */ /* For Webkit Browsers */ ::-webkit-scrollbar { - width: 14px; /* Width of the scrollbar */ + width: 12px; /* Width of the scrollbar */ } ::selection { diff --git a/src/components/common/modals/notification-settings-saved/index.tsx b/src/components/common/modals/notification-settings-saved/index.tsx index 843b23578..0f45bc3c8 100644 --- a/src/components/common/modals/notification-settings-saved/index.tsx +++ b/src/components/common/modals/notification-settings-saved/index.tsx @@ -35,17 +35,17 @@ const NotificationSettingSavedModal: React.FC = ({ className={`fixed inset-0 z-50 flex items-center justify-center ${isNotificationPath ? "bg-transparent backdrop-blur-sm" : "bg-black bg-opacity-50"}`} /> event.stopPropagation()} > Notification Updated! - + Notification preferences updated successfully. Remember, you can always adjust these settings later. -
+
Done
diff --git a/src/components/ui/separator.tsx b/src/components/ui/separator.tsx new file mode 100644 index 000000000..ef26ace81 --- /dev/null +++ b/src/components/ui/separator.tsx @@ -0,0 +1,31 @@ +"use client"; + +import * as SeparatorPrimitive from "@radix-ui/react-separator"; +import * as React from "react"; + +import { cn } from "~/lib/utils"; + +const Separator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>( + ( + { className, orientation = "horizontal", decorative = true, ...properties }, + reference, + ) => ( + + ), +); +Separator.displayName = SeparatorPrimitive.Root.displayName; + +export { Separator };