diff --git a/package-lock.json b/package-lock.json index c260bce..390a382 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,6 +32,7 @@ "react-paginate": "^8.3.0", "react-switch": "^7.1.0", "react-toastify": "^11.0.5", + "react-tooltip": "^5.29.1", "tailwind-merge": "^2.6.0", "zod": "^4.1.5" }, @@ -233,6 +234,31 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@floating-ui/core": { + "version": "1.7.3", + "resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.7.3.tgz", + "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.4", + "resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.7.4.tgz", + "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.3", + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.10", + "resolved": "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.2.10.tgz", + "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", + "license": "MIT" + }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", @@ -2171,6 +2197,12 @@ "url": "https://polar.sh/cva" } }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmmirror.com/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", + "license": "MIT" + }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", @@ -5391,6 +5423,20 @@ "react-dom": "^18 || ^19" } }, + "node_modules/react-tooltip": { + "version": "5.29.1", + "resolved": "https://registry.npmmirror.com/react-tooltip/-/react-tooltip-5.29.1.tgz", + "integrity": "sha512-rmJmEb/p99xWhwmVT7F7riLG08wwKykjHiMGbDPloNJk3tdI73oHsVOwzZ4SRjqMdd5/xwb/4nmz0RcoMfY7Bw==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.6.1", + "classnames": "^2.3.0" + }, + "peerDependencies": { + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", diff --git a/package.json b/package.json index 6b4b741..90d2f31 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "react-paginate": "^8.3.0", "react-switch": "^7.1.0", "react-toastify": "^11.0.5", + "react-tooltip": "^5.29.1", "tailwind-merge": "^2.6.0", "zod": "^4.1.5" }, diff --git a/src/app/(notifications)/notification-history/[id]/page.tsx b/src/app/(notifications)/notification-history/[id]/page.tsx new file mode 100644 index 0000000..425234d --- /dev/null +++ b/src/app/(notifications)/notification-history/[id]/page.tsx @@ -0,0 +1,80 @@ +"use client"; +import Loading from "@/app/loading"; +import Breadcrumb from "@/components/Breadcrumbs/Breadcrumb"; +import { ShowcaseSection } from "@/components/Layouts/showcase-section"; +import IsVisible from "@/components/ui/IsVisible"; +import { useGetNotificationDetails } from "@/hooks/queries/useNotificationQueries"; +import { BreadcrumbItem } from "@/types/shared"; +import { unixToDate } from "@/utils/shared"; +import { use } from "react"; + +interface IProps { + params: Promise<{ id: string }>; +} + +const NotificationDetailsPage = ({ params }: IProps) => { + const { id } = use(params); + const { data, isLoading } = useGetNotificationDetails(id); + + const breadcrumbItems: BreadcrumbItem[] = [ + { + href: "/", + name: "Dashboard", + }, + { + href: "/notification-history", + name: "Notification history", + }, + { + href: `/notification-history/${id}`, + name: "Notification details", + }, + ]; + if (isLoading) return ; + return ( + <> + + +
+ + + {data?.data.message} + + + + + {data?.data.event_type} + + + + {data?.data.link} + + + + + {data?.data.priority} + + + + + {data?.data.type} + + + + {unixToDate({ unix: data?.data.seen_at ?? 0, hasTime: false })} + + + + + {data?.data.is_scheduled ? "Yes" : "No"} + + + {data?.data.seen ? "Yes" : "No"} + +
+
+ + ); +}; + +export default NotificationDetailsPage; diff --git a/src/app/(notifications)/notification-history/page.tsx b/src/app/(notifications)/notification-history/page.tsx new file mode 100644 index 0000000..81854d7 --- /dev/null +++ b/src/app/(notifications)/notification-history/page.tsx @@ -0,0 +1,24 @@ +import Breadcrumb from "@/components/Breadcrumbs/Breadcrumb"; +import NotificationHistoryTable from "@/components/Tables/notification-history"; +import { BreadcrumbItem } from "@/types/shared"; + +const NotificationHistoryPage = () => { + const breadcrumbItems: BreadcrumbItem[] = [ + { + href: "/", + name: "Dashboard", + }, + { + href: "/notification-history", + name: "Notification history", + }, + ]; + return ( + <> + + + + ); +}; + +export default NotificationHistoryPage; diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 26c9ba9..91ecfd1 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,5 +1,6 @@ import "@/css/satoshi.css"; import "@/css/style.css"; +import "react-tooltip/dist/react-tooltip.css"; import { ConditionalLayout } from "@/components/Layouts/conditional-layout"; import "flatpickr/dist/flatpickr.min.css"; diff --git a/src/app/tenders/[details]/page.tsx b/src/app/tenders/[details]/page.tsx index e58faaa..b730785 100644 --- a/src/app/tenders/[details]/page.tsx +++ b/src/app/tenders/[details]/page.tsx @@ -4,20 +4,12 @@ import { LocationIcon } from "@/assets/icons"; import Breadcrumb from "@/components/Breadcrumbs/Breadcrumb"; import { ShowcaseSection } from "@/components/Layouts/showcase-section"; import Status from "@/components/ui/Status"; -import { - Table, - TableBody, - TableHead, - TableHeader, - TableRow, -} from "@/components/ui/table"; import { useTenderDetailQuery } from "@/hooks/queries"; import { useGetFlagQuery } from "@/hooks/queries/useFlagsQueries"; -import { msToDate, unixToDate } from "@/utils/shared"; +import { msToDate } from "@/utils/shared"; import getSymbolFromCurrency from "currency-symbol-map"; -import { use } from "react"; -import { TableCell } from "../../../components/ui/table"; import Link from "next/link"; +import { use } from "react"; interface IProps { params: Promise<{ diff --git a/src/components/Layouts/header/user-info/index.tsx b/src/components/Layouts/header/user-info/index.tsx index dee1d75..640e94e 100644 --- a/src/components/Layouts/header/user-info/index.tsx +++ b/src/components/Layouts/header/user-info/index.tsx @@ -6,16 +6,16 @@ import { DropdownContent, DropdownTrigger, } from "@/components/ui/dropdown"; +import { useUser } from "@/contexts"; import { cn } from "@/lib/utils"; import Image from "next/image"; import Link from "next/link"; import { useState } from "react"; import { LogOutIcon, SettingsIcon, UserIcon } from "./icons"; -import { useUser } from "@/contexts"; export function UserInfo() { const [isOpen, setIsOpen] = useState(false); - const { logout } = useUser(); + const { logout, user } = useUser(); const USER = { name: "John Smith", email: "johnson@nextadmin.com", @@ -28,16 +28,19 @@ export function UserInfo() { My Account
- + + + {/* {`Avatar + /> */}
- {USER.name} + {user?.full_name} = z.lazy(() => title: z.string(), url: z.string(), icon: z.any(), - items: z.array(navSubItemSchema).default([]), + items: z.array(navSubItemSchema), }), ); @@ -66,6 +66,12 @@ export const NAV_DATA: NavData = [ icon: Icons.Table, items: [], }, + { + title: "Notifications", + url: "/notification-history", + icon: Icons.NotificationIcon, + items: [], + }, ], }, ]; diff --git a/src/components/Layouts/sidebar/icons.tsx b/src/components/Layouts/sidebar/icons.tsx index 7a1e650..d0a177e 100644 --- a/src/components/Layouts/sidebar/icons.tsx +++ b/src/components/Layouts/sidebar/icons.tsx @@ -19,6 +19,20 @@ export function ChevronUp(props: PropsType) { ); } +export function NotificationIcon(props: PropsType) { + return ( + + + + ); +} export function Building(props: PropsType) { return ( diff --git a/src/components/Tables/admins/index.tsx b/src/components/Tables/admins/index.tsx index 92720a5..8afe283 100644 --- a/src/components/Tables/admins/index.tsx +++ b/src/components/Tables/admins/index.tsx @@ -3,6 +3,7 @@ import { PencilSquareIcon, TrashIcon, UserSettingIcon } from "@/assets/icons"; import ConfirmationModal from "@/components/ui/ConfirmationModal"; import Modal from "@/components/ui/modal"; +import { _TooltipDefaultParams } from "@/constants/tooltip"; import Status from "@/components/ui/Status"; import { Table, @@ -15,6 +16,7 @@ import { import TableSkeleton from "@/components/ui/TableSkeleton"; import { AdminStatus } from "@/constants/enums"; import Link from "next/link"; +import { Tooltip } from "react-tooltip"; import ChangeStatusModalContent from "./ChangeStatusModalContent"; import { useAdminsPresenter } from "./useAdminsPresenter"; @@ -82,29 +84,43 @@ const AdminsTable = () => {
diff --git a/src/components/Tables/companies/company-categories/index.tsx b/src/components/Tables/companies/company-categories/index.tsx index f8cc926..7688e98 100644 --- a/src/components/Tables/companies/company-categories/index.tsx +++ b/src/components/Tables/companies/company-categories/index.tsx @@ -12,8 +12,10 @@ import { TableRow, } from "@/components/ui/table"; import TableSkeleton from "@/components/ui/TableSkeleton"; +import { _TooltipDefaultParams } from "@/constants/tooltip"; import { unixToDate } from "@/utils/shared"; import Link from "next/link"; +import { Tooltip } from "react-tooltip"; import { Skeleton } from "../../../ui/skeleton"; import useCompanyCategoriesPresenter from "./useCompanyCategoriesPresenter"; @@ -65,7 +67,7 @@ const CompanyCategoriesTable = () => { {category.name} {category.description} - {unixToDate(category.created_at)} + {unixToDate({ unix: category.created_at, hasTime: true })} @@ -87,21 +89,29 @@ const CompanyCategoriesTable = () => {
diff --git a/src/components/Tables/companies/index.tsx b/src/components/Tables/companies/index.tsx index f42c1ce..e2261a7 100644 --- a/src/components/Tables/companies/index.tsx +++ b/src/components/Tables/companies/index.tsx @@ -1,6 +1,7 @@ "use client"; import { ExclamationIcon, PencilSquareIcon, TrashIcon } from "@/assets/icons"; import ConfirmationModal from "@/components/ui/ConfirmationModal"; +import { _TooltipDefaultParams } from "@/constants/tooltip"; import { Table, TableBody, @@ -12,6 +13,7 @@ import { import TableSkeleton from "@/components/ui/TableSkeleton"; import { formatPhoneNumber } from "@/utils/shared"; import Link from "next/link"; +import { Tooltip } from "react-tooltip"; import { useCompanyListPresenter } from "./useCompanyListPresenter"; interface IProps {} @@ -88,30 +90,42 @@ const CompaniesTable = ({}: IProps) => {
diff --git a/src/components/Tables/customers/index.tsx b/src/components/Tables/customers/index.tsx index 0d0d4da..3797bc1 100644 --- a/src/components/Tables/customers/index.tsx +++ b/src/components/Tables/customers/index.tsx @@ -9,6 +9,7 @@ import { TableHeader, TableRow, } from "@/components/ui/table"; +import { _TooltipDefaultParams } from "@/constants/tooltip"; import Link from "next/link"; import useCustomerListPresenter from "./useCustomerListPresenter"; @@ -18,6 +19,7 @@ import Status from "@/components/ui/Status"; import TableSkeleton from "@/components/ui/TableSkeleton"; import { unixToDate } from "@/utils/shared"; import { toast } from "react-toastify"; +import { Tooltip } from "react-tooltip"; import AssignToCompanyModalContent from "./AssignToCompanyModalContent"; const CustomersTable = () => { @@ -65,7 +67,7 @@ const CustomersTable = () => { {customer.full_name} {customer.email} - {unixToDate(customer.created_at)} + {unixToDate({ unix: customer.created_at, hasTime: true })} @@ -89,25 +91,36 @@ const CustomersTable = () => {
diff --git a/src/components/Tables/feedback-table/index.tsx b/src/components/Tables/feedback-table/index.tsx index 3dbd299..6751676 100644 --- a/src/components/Tables/feedback-table/index.tsx +++ b/src/components/Tables/feedback-table/index.tsx @@ -67,11 +67,11 @@ const FeedbackTable = ({ id, paramKey }: IProps) => { {item.feedback_type}
- {unixToDate(item.updated_at)} + {unixToDate({ unix: item.updated_at, hasTime: true })} - {unixToDate(item.created_at)} + {unixToDate({ unix: item.created_at, hasTime: true })} { + const { + columns, + isLoading, + metadata, + notificationHistory, + pathName, + router, + setParams, + } = useNotificationHistoryTablePresenter(); + + return ( + + + + + {columns.map((column) => ( + + {column} + + ))} + + + {isLoading && } + + {!notificationHistory?.length ? ( + + +

No notifications

+
+
+ ) : ( + notificationHistory.map((item, index) => ( + + {index + 1} + {item.title} + {item.event_type} + + {isoStringToDate({ + hasTime: true, + isoString: item.created_at, + })} + + {item.message} + + {item.priority} + + + {item.type} + + + {item.seen ? "Seen" : "Unseen"} + + + {item.status} + + + + + + )) + )} +
+
+ { + setParams((currentParams) => ({ + ...currentParams, + offset: e.selected * (metadata?.limit ?? 10), + limit: metadata?.limit ?? 1000, + })); + }} + /> +
+ ); +}; + +export default NotificationHistoryTable; diff --git a/src/components/Tables/notification-history/useNotificationHistoryTablePresenter.ts b/src/components/Tables/notification-history/useNotificationHistoryTablePresenter.ts new file mode 100644 index 0000000..f24e7f3 --- /dev/null +++ b/src/components/Tables/notification-history/useNotificationHistoryTablePresenter.ts @@ -0,0 +1,37 @@ +"use client"; +import { apiDefaultParams } from "@/constants/Api_Params"; +import { useGetNotificationHistoryQuery } from "@/hooks/queries/useNotificationQueries"; +import { usePathname, useRouter } from "next/navigation"; +import { useState } from "react"; + +const useNotificationHistoryTablePresenter = () => { + const [params, setParams] = useState>({ + ...apiDefaultParams, + }); + const { data, isLoading } = useGetNotificationHistoryQuery(params); + const columns: string[] = [ + "row", + "title", + "channel", + "created at", + "message", + "priority", + "type", + "seen", + "status", + "actions", + ]; + const pathName = usePathname(); + const router = useRouter(); + return { + notificationHistory: data?.data.notifications, + metadata: data?.meta, + isLoading, + columns, + router, + pathName, + setParams, + }; +}; + +export default useNotificationHistoryTablePresenter; diff --git a/src/components/Tables/tenders/index.tsx b/src/components/Tables/tenders/index.tsx index 547219a..a89295b 100644 --- a/src/components/Tables/tenders/index.tsx +++ b/src/components/Tables/tenders/index.tsx @@ -9,11 +9,13 @@ import { TableHeader, TableRow, } from "@/components/ui/table"; +import { Tooltip } from "react-tooltip"; import useTenderListPresenter from "./useTenderListPresenter"; import { ExclamationIcon, EyeIcon } from "@/assets/icons"; import Pagination from "@/components/ui/pagination"; import TableSkeleton from "@/components/ui/TableSkeleton"; +import { _TooltipDefaultParams } from "@/constants/tooltip"; import { cn } from "@/lib/utils"; import Link from "next/link"; const TendersTable = () => { @@ -70,18 +72,30 @@ const TendersTable = () => { colSpan={100} >
diff --git a/src/components/ui/Status.tsx b/src/components/ui/Status.tsx index 4684e37..a8d4274 100644 --- a/src/components/ui/Status.tsx +++ b/src/components/ui/Status.tsx @@ -22,6 +22,7 @@ const Status = ({ status, children }: IProps) => { "success", "verified", "published", + "sent" ]; const blues = ["awarded", "processing", "in-review", "scheduled"]; const yellows = ["pending", "warning", "on-hold", "delayed"]; diff --git a/src/components/ui/table.tsx b/src/components/ui/table.tsx index dcebaa8..8d39467 100644 --- a/src/components/ui/table.tsx +++ b/src/components/ui/table.tsx @@ -70,7 +70,7 @@ export function TableHead({ return ( ({ + id, + delayShow: 500, + delayHide: 500, + variant, + style: { backgroundColor: variant === "error" ? "#F23030" : "", ...styles }, +}); diff --git a/src/css/style.css b/src/css/style.css index a79fe56..073e170 100644 --- a/src/css/style.css +++ b/src/css/style.css @@ -49,6 +49,9 @@ .tableCheckbox:checked ~ div span { @apply opacity-100; } +.react-tooltip { + @apply !rounded-full !transition-opacity !duration-500; +} .tableCheckbox:checked ~ div { @apply border-primary bg-primary; @@ -502,17 +505,17 @@ input[type="search"]::-webkit-search-cancel-button { } .Toastify__toast--success { - background: linear-gradient(to bottom right, #82E6AC, #1A8245) !important; + background: linear-gradient(to bottom right, #82e6ac, #1a8245) !important; } .Toastify__toast--error { - background: linear-gradient(to bottom right, #F89090, #E10E0E) !important; + background: linear-gradient(to bottom right, #f89090, #e10e0e) !important; } .Toastify__toast--warning { - background: linear-gradient(to bottom right, #F59E0B, #D97706) !important; + background: linear-gradient(to bottom right, #f59e0b, #d97706) !important; } .Toastify__toast--info { - background: linear-gradient(to bottom right, #8099EC, #1C3FB7) !important; + background: linear-gradient(to bottom right, #8099ec, #1c3fb7) !important; } diff --git a/src/hooks/queries/useNotificationQueries.ts b/src/hooks/queries/useNotificationQueries.ts new file mode 100644 index 0000000..9d5646c --- /dev/null +++ b/src/hooks/queries/useNotificationQueries.ts @@ -0,0 +1,27 @@ +import { API_ENDPOINTS } from "@/lib/api"; +import { notificationService } from "@/lib/api/services/notification-service"; +import { useQuery } from "@tanstack/react-query"; +import { useMemo } from "react"; + +export const useGetNotificationHistoryQuery = ( + params?: Record, +) => { + const queryKey = useMemo( + () => [API_ENDPOINTS.NOTIFICATIONS.HISTORY, "READ NOTIFICATIONS HISTORY"], + [], + ); + return useQuery({ + queryKey, + queryFn: () => notificationService.getNotifications(params), + }); +}; +export const useGetNotificationDetails = (id: string) => { + const queryKey = useMemo( + () => [API_ENDPOINTS.NOTIFICATIONS.DETAILS(id), "NOTIFICATION DETAILS"], + [id], + ); + return useQuery({ + queryKey, + queryFn: () => notificationService.getNotificationDetails(id), + }); +}; diff --git a/src/lib/api/endpoints.ts b/src/lib/api/endpoints.ts index 587cb86..29c7d8b 100644 --- a/src/lib/api/endpoints.ts +++ b/src/lib/api/endpoints.ts @@ -50,4 +50,8 @@ export const API_ENDPOINTS = { DETAILS: (id: string) => `feedback/${id}`, DELETE: (id: string) => `feedback/${id}`, }, + NOTIFICATIONS: { + HISTORY: "notifications", + DETAILS: (id: string) => `notifications/view/${id}`, + }, } as const; diff --git a/src/lib/api/services/notification-service.ts b/src/lib/api/services/notification-service.ts new file mode 100644 index 0000000..2d888bf --- /dev/null +++ b/src/lib/api/services/notification-service.ts @@ -0,0 +1,37 @@ +import api from "../axios"; +import { API_ENDPOINTS } from "../endpoints"; +import { + TNotificationDetailsResponse, + TNotificationHistoryResponse, +} from "../types/NotificationHistory"; +import { ApiResponse } from "../types/shared"; + +export const notificationService = { + getNotifications: async ( + params?: Record, + ): Promise => { + try { + return (await api.get(API_ENDPOINTS.NOTIFICATIONS.HISTORY, { params })) + .data; + } catch (error) { + console.error( + "ERROR Caught in notification service => getNotifications", + error, + ); + throw error; + } + }, + getNotificationDetails: async ( + id: string, + ): Promise> => { + try { + return (await api.get(API_ENDPOINTS.NOTIFICATIONS.DETAILS(id))).data; + } catch (error) { + console.error( + "ERROR Caught in notification service => getNotificationDetails", + error, + ); + throw error; + } + }, +}; diff --git a/src/lib/api/types/Customers.ts b/src/lib/api/types/Customers.ts index f13f7b4..8213774 100644 --- a/src/lib/api/types/Customers.ts +++ b/src/lib/api/types/Customers.ts @@ -31,9 +31,6 @@ const customersSchema = z.object({ username: z.string(), }); -export const customersListResponse = z.object({ - customers: z.array(customersSchema), -}); const createCustomerCredentials = z.object({ address: z .object({ @@ -99,6 +96,9 @@ const createCustomerCredentials = z.object({ "Username must contain only alphanumeric characters", ), }); +export const customersListResponse = z.object({ + customers: z.array(customersSchema), +}); const assignCustomerToCompanySchema = z.object({ company_ids: z.array(z.string()), }); diff --git a/src/lib/api/types/NotificationHistory.ts b/src/lib/api/types/NotificationHistory.ts new file mode 100644 index 0000000..dc738d6 --- /dev/null +++ b/src/lib/api/types/NotificationHistory.ts @@ -0,0 +1,43 @@ +import { z } from "zod"; +import { createApiResponseSchema } from "./Factory"; + +export const notificationSchema = z.object({ + created_at: z.string(), + event_type: z.string(), + id: z.string(), + image: z.string(), + is_scheduled: z.boolean(), + link: z.string(), + message: z.string(), + metadata: z.object({ + additionalProp1: z.string(), + additionalProp2: z.string(), + additionalProp3: z.string(), + }), + method: z.object({ + additionalProp1: z.string(), + additionalProp2: z.string(), + additionalProp3: z.string(), + }), + priority: z.string(), + schedule_at: z.number(), + scheduled_at: z.number(), + seen: z.boolean(), + seen_at: z.number(), + status: z.string(), + title: z.string(), + type: z.string(), + updated_at: z.string(), + user_id: z.string(), +}); + +const notificationHistoryResponseSchema = createApiResponseSchema( + z.object({ + notifications: z.array(notificationSchema), + }), +); +export type TNotificationHistory = z.infer; +export type TNotificationDetailsResponse = z.infer; +export type TNotificationHistoryResponse = z.infer< + typeof notificationHistoryResponseSchema +>; diff --git a/src/utils/shared.ts b/src/utils/shared.ts index 2585746..6a67c54 100644 --- a/src/utils/shared.ts +++ b/src/utils/shared.ts @@ -1,11 +1,29 @@ import * as moment from "moment"; -export const unixToDate = (unix: number) => { - return moment.unix(unix).format("YYYY/MM/DD HH:MM"); +export const unixToDate = ({ + hasTime = false, + unix, +}: { + unix: number; + hasTime?: boolean; +}) => { + return moment.unix(unix).format(`YYYY/MM/DD ${hasTime && "HH:MM"}`); }; export const msToDate = (ms: number) => { return moment.default(ms).format("YYYY/MM/DD"); }; +export const isoStringToDate = ({ + hasTime = false, + isoString, +}: { + isoString: string; + hasTime: boolean; +}): string => { + return moment + .default(isoString) + .format(`YYYY/MM/DD ${hasTime ? "HH:MM" : ""}`); +}; + export const getStatusColor = (status: T) => { switch (status) { case "active":