diff --git a/web/apps/admin/src/utils/constants.ts b/web/apps/admin/src/utils/constants.ts index ded60ed1a..82b78dbb6 100644 --- a/web/apps/admin/src/utils/constants.ts +++ b/web/apps/admin/src/utils/constants.ts @@ -1,4 +1,3 @@ -export const DEFAULT_DATE_FORMAT = "MMM DD, YYYY"; export const DEFAULT_TOKEN_PRODUCT_NAME = "token"; export const PERMISSIONS = { diff --git a/web/apps/admin/src/utils/helper.ts b/web/apps/admin/src/utils/helper.ts index 275b483ce..1898e1e01 100644 --- a/web/apps/admin/src/utils/helper.ts +++ b/web/apps/admin/src/utils/helper.ts @@ -1,6 +1,4 @@ -import dayjs from 'dayjs'; import type { TableColumnMetadata } from '~/types/types'; -import { DEFAULT_DATE_FORMAT } from './constants'; import { BillingAccount_Address } from '@raystack/proton/frontier'; const currencySymbolMap: Record = { @@ -48,12 +46,6 @@ export const capitalizeFirstLetter = (str: string) => { export const keyToColumnMetaObject = (key: any) => ({ key: key, name: key, value: key } as TableColumnMetadata); -/* - * @desc returns date string - Eg, June 13, 2025. return '-' if the date in the argument is invalid. - */ -export const getFormattedDateString = (date: string) => - date ? dayjs(date).format(DEFAULT_DATE_FORMAT) : '-'; - export const convertBillingAddressToString = ( address?: BillingAccount_Address ) => { diff --git a/web/sdk/admin/utils/connect-timestamp.ts b/web/sdk/admin/utils/connect-timestamp.ts index aef04cdb5..4c3e01f91 100644 --- a/web/sdk/admin/utils/connect-timestamp.ts +++ b/web/sdk/admin/utils/connect-timestamp.ts @@ -19,4 +19,14 @@ export function isNullTimestamp(timestamp?: Timestamp): boolean { return Number(timestamp.seconds) <= 0; } +/** Canonical admin date format (matches Apsara). */ +export const DATE_FORMAT = "DD MMM YYYY"; + +/** Formats a Timestamp, returning "-" for missing/null-time values (which would otherwise render as 01 Jan 1970). */ +export function formatTimestamp(timestamp?: Timestamp, format: string = DATE_FORMAT): string { + if (isNullTimestamp(timestamp)) return "-"; + const date = timestampToDayjs(timestamp); + return date ? date.format(format) : "-"; +} + export type TimeStamp = Timestamp; diff --git a/web/sdk/admin/views/admins/columns.tsx b/web/sdk/admin/views/admins/columns.tsx index 5170814c5..5df5c252c 100644 --- a/web/sdk/admin/views/admins/columns.tsx +++ b/web/sdk/admin/views/admins/columns.tsx @@ -20,13 +20,13 @@ export const getColumns: (options?: { cell: styles["first-column"], header: styles["first-column"], }, - filterVariant: "text", + filterType: "string", cell: (info) => info.getValue() || "-", }, { header: "Email", accessorKey: "email", - filterVariant: "text", + filterType: "string", cell: (info) => info.getValue() || "-", }, { diff --git a/web/sdk/admin/views/audit-logs/columns.tsx b/web/sdk/admin/views/audit-logs/columns.tsx index 600d82c51..889e9306e 100644 --- a/web/sdk/admin/views/audit-logs/columns.tsx +++ b/web/sdk/admin/views/audit-logs/columns.tsx @@ -1,5 +1,4 @@ import { Badge, DataTableColumnDef, Flex, Text } from "@raystack/apsara"; -import dayjs from "dayjs"; import styles from "./audit-logs.module.css"; import { AuditRecord, @@ -7,10 +6,10 @@ import { AuditRecordResource, } from "@raystack/proton/frontier"; import { + formatTimestamp, isNullTimestamp, TimeStamp, - timestampToDate, -} from "../../utils/connect-timestamp"; +} from "~/admin/utils/connect-timestamp"; import { ACTOR_TYPES, getActionBadgeColor } from "./util"; import { ComponentPropsWithoutRef } from "react"; import ActorCell from "./actor-cell"; @@ -113,14 +112,13 @@ export const getColumns = ({ if (isNullTimestamp(value)) { return -; } - const date = dayjs(timestampToDate(value)); return ( - {date.format("DD MMM YYYY")} + {formatTimestamp(value)} - {date.format("hh:mm A")} + {formatTimestamp(value, "hh:mm A")} ); diff --git a/web/sdk/admin/views/audit-logs/sidepanel-details.tsx b/web/sdk/admin/views/audit-logs/sidepanel-details.tsx index 2f6fe46d5..0bbb2b176 100644 --- a/web/sdk/admin/views/audit-logs/sidepanel-details.tsx +++ b/web/sdk/admin/views/audit-logs/sidepanel-details.tsx @@ -9,8 +9,7 @@ import { List } from "@raystack/apsara"; import styles from "./audit-logs.module.css"; import { AuditRecord } from "@raystack/proton/frontier"; import { ACTOR_TYPES } from "./util"; -import { timestampToDate } from "../../utils/connect-timestamp"; -import dayjs from "dayjs"; +import { formatTimestamp } from "~/admin/utils/connect-timestamp"; import { MapIcon } from "../../assets/icons/MapIcon"; import SidePanelLogDialog from "./sidepanel-log-dialog"; import ActorCell from "./actor-cell"; @@ -44,8 +43,6 @@ export default function SidePanelDetails({ const paths = useAdminPaths(); const { actor, event, resource, occurredAt, id, orgId, orgName, target } = rest; - const date = dayjs(timestampToDate(occurredAt)); - const session = actor?.metadata?.context as AuditSessionContext; const location = (session && `${session.Location.City}, ${session.Location.Country}`) || "-"; @@ -100,11 +97,11 @@ export default function SidePanelDetails({ Date - {date.format("DD MMM YYYY")} + {formatTimestamp(occurredAt)} Time - {date.format("hh:mm A")} + {formatTimestamp(occurredAt, "hh:mm A")} ID diff --git a/web/sdk/admin/views/invoices/columns.tsx b/web/sdk/admin/views/invoices/columns.tsx index 9c6459e5e..06db232f8 100644 --- a/web/sdk/admin/views/invoices/columns.tsx +++ b/web/sdk/admin/views/invoices/columns.tsx @@ -1,11 +1,6 @@ import { Amount, type DataTableColumnDef, Link, Text } from "@raystack/apsara"; -import dayjs from "dayjs"; import type { SearchInvoicesResponse_Invoice } from "@raystack/proton/frontier"; -import { - isNullTimestamp, - TimeStamp, - timestampToDate, -} from "../../utils/connect-timestamp"; +import { formatTimestamp, TimeStamp } from "~/admin/utils/connect-timestamp"; import { TerminologyEntity } from "../../hooks/useTerminology"; import styles from "./invoices.module.css"; @@ -29,13 +24,9 @@ export const getColumns = ({ t }: GetColumnsOptions): DataTableColumnDef< }, filterType: "date", enableColumnFilter: true, - cell: ({ getValue }) => { - const value = getValue() as TimeStamp; - const date = isNullTimestamp(value) - ? "-" - : dayjs(timestampToDate(value)).format("YYYY-MM-DD"); - return {date}; - }, + cell: ({ getValue }) => ( + {formatTimestamp(getValue() as TimeStamp)} + ), enableHiding: true, enableSorting: true, }, diff --git a/web/sdk/admin/views/organizations/details/apis/columns.tsx b/web/sdk/admin/views/organizations/details/apis/columns.tsx index 402ba34e8..e299d5fd3 100644 --- a/web/sdk/admin/views/organizations/details/apis/columns.tsx +++ b/web/sdk/admin/views/organizations/details/apis/columns.tsx @@ -1,6 +1,7 @@ import { Text, type DataTableColumnDef } from "@raystack/apsara"; import dayjs from "dayjs"; import { NULL_DATE } from "../../../../utils/constants"; +import { DATE_FORMAT } from "~/admin/utils/connect-timestamp"; import styles from "./apis.module.css"; import type { SearchOrganizationServiceUsersResponse_OrganizationServiceUser, @@ -52,7 +53,7 @@ SearchOrganizationServiceUsersResponse_OrganizationServiceUser, header: "Created on", cell: ({ getValue }) => { const value = getValue() as string; - return value !== NULL_DATE ? dayjs(value).format("YYYY-MM-DD") : "-"; + return value !== NULL_DATE ? dayjs(value).format(DATE_FORMAT) : "-"; }, enableSorting: true, enableColumnFilter: true, diff --git a/web/sdk/admin/views/organizations/details/apis/details-dialog.tsx b/web/sdk/admin/views/organizations/details/apis/details-dialog.tsx index 93f7d583f..e44e91616 100644 --- a/web/sdk/admin/views/organizations/details/apis/details-dialog.tsx +++ b/web/sdk/admin/views/organizations/details/apis/details-dialog.tsx @@ -1,7 +1,6 @@ import { Dialog, Flex, Skeleton, Tabs, Text, toastManager } from "@raystack/apsara"; import styles from "./apis.module.css"; import { useCallback, useEffect, useMemo } from "react"; -import dayjs from "dayjs"; import { useQuery } from "@connectrpc/connect-query"; import { FrontierServiceQueries, @@ -10,7 +9,7 @@ import { type SearchOrganizationServiceUsersResponse_OrganizationServiceUser } from "@raystack/proton/frontier"; import { create } from "@bufbuild/protobuf"; -import { timestampToDayjs } from "../../../../utils/connect-timestamp"; +import { formatTimestamp } from "~/admin/utils/connect-timestamp"; import { useTerminology } from "../../../../hooks/useTerminology"; interface ServiceUserDetailsDialogProps { @@ -129,7 +128,7 @@ export const ServiceUserDetailsDialog = ({ > {token.title} - {timestampToDayjs(token.createdAt)?.format("YYYY-MM-DD")} + {formatTimestamp(token.createdAt)} ))} diff --git a/web/sdk/admin/views/organizations/details/invoices/columns.tsx b/web/sdk/admin/views/organizations/details/invoices/columns.tsx index c24cf9dda..47ec8f15a 100644 --- a/web/sdk/admin/views/organizations/details/invoices/columns.tsx +++ b/web/sdk/admin/views/organizations/details/invoices/columns.tsx @@ -1,14 +1,9 @@ import styles from "./invoices.module.css"; -import dayjs from "dayjs"; import { DataTableColumnDef, Link, Amount } from "@raystack/apsara"; import type { SearchOrganizationInvoicesResponse_OrganizationInvoice, } from "@raystack/proton/frontier"; -import { - isNullTimestamp, - TimeStamp, - timestampToDate, -} from "../../../../utils/connect-timestamp"; +import { formatTimestamp, TimeStamp } from "~/admin/utils/connect-timestamp"; // https://docs.stripe.com/invoicing/overview#invoice-statuses const InvoiceStatusesMap = { @@ -38,13 +33,7 @@ export const getColumns = ({ cell: styles["first-column"], header: styles["first-column"], }, - cell: ({ getValue }) => { - const value = getValue() as TimeStamp; - const date = isNullTimestamp(value) - ? "-" - : dayjs(timestampToDate(value)).format("YYYY-MM-DD"); - return date; - }, + cell: ({ getValue }) => formatTimestamp(getValue() as TimeStamp), enableSorting: true, enableColumnFilter: true, filterType: "date", diff --git a/web/sdk/admin/views/organizations/details/members/columns.tsx b/web/sdk/admin/views/organizations/details/members/columns.tsx index 366bf2a03..50a2ce1ec 100644 --- a/web/sdk/admin/views/organizations/details/members/columns.tsx +++ b/web/sdk/admin/views/organizations/details/members/columns.tsx @@ -14,14 +14,9 @@ import type { } from "@raystack/proton/frontier"; import type { UpdateRolePayload } from "./update-role"; import styles from "./members.module.css"; -import dayjs from "dayjs"; import { DotsHorizontalIcon, UpdateIcon } from "@radix-ui/react-icons"; import { DeleteIcon } from "~/admin/assets/icons/DeleteIcon"; -import { - isNullTimestamp, - TimeStamp, - timestampToDate, -} from "../../../../utils/connect-timestamp"; +import { formatTimestamp, TimeStamp } from "~/admin/utils/connect-timestamp"; const MemberStates = { enabled: "Active", @@ -122,13 +117,9 @@ export const getColumns = ({ { accessorKey: "orgJoinedAt", header: "Joined On", - cell: ({ getValue }) => { - const value = getValue() as TimeStamp; - const date = isNullTimestamp(value) - ? "-" - : dayjs(timestampToDate(value)).format("YYYY-MM-DD"); - return {date}; - }, + cell: ({ getValue }) => ( + {formatTimestamp(getValue() as TimeStamp)} + ), enableSorting: true, enableHiding: true, // enableColumnFilter: true, diff --git a/web/sdk/admin/views/organizations/details/pat/columns.tsx b/web/sdk/admin/views/organizations/details/pat/columns.tsx index 6ae66ee0b..52c191d07 100644 --- a/web/sdk/admin/views/organizations/details/pat/columns.tsx +++ b/web/sdk/admin/views/organizations/details/pat/columns.tsx @@ -12,6 +12,7 @@ import type { SearchOrganizationPATsResponse_OrganizationPAT, } from "@raystack/proton/frontier"; import { + formatTimestamp, isNullTimestamp, timestampToDayjs, } from "~/admin/utils/connect-timestamp"; @@ -25,8 +26,6 @@ interface GetColumnsOptions { projectsMap: Record; } -const DATE_FORMAT = "DD MMM YYYY"; - export function getColumns({ projectsMap, }: GetColumnsOptions): DataTableColumnDef< @@ -90,10 +89,9 @@ export function getColumns({ accessorKey: "createdAt", header: "Created On", styles: { header: { width: "152px" } }, - cell: ({ row }) => { - const date = timestampToDayjs(row.original.createdAt); - return date ? {date.format(DATE_FORMAT)} : -; - }, + cell: ({ row }) => ( + {formatTimestamp(row.original.createdAt)} + ), enableSorting: true, enableColumnFilter: true, filterType: "date", @@ -103,12 +101,9 @@ export function getColumns({ accessorKey: "expiresAt", header: "Expiry Date", styles: { header: { width: "152px" } }, - cell: ({ row }) => { - const expiresAt = row.original.expiresAt; - if (!expiresAt || isNullTimestamp(expiresAt)) return -; - const date = timestampToDayjs(expiresAt); - return date ? {date.format(DATE_FORMAT)} : -; - }, + cell: ({ row }) => ( + {formatTimestamp(row.original.expiresAt)} + ), enableSorting: true, enableColumnFilter: true, filterType: "date", diff --git a/web/sdk/admin/views/organizations/details/projects/columns.tsx b/web/sdk/admin/views/organizations/details/projects/columns.tsx index fe58440c6..3a14a59d2 100644 --- a/web/sdk/admin/views/organizations/details/projects/columns.tsx +++ b/web/sdk/admin/views/organizations/details/projects/columns.tsx @@ -13,12 +13,7 @@ import type { } from "@raystack/proton/frontier"; import styles from "./projects.module.css"; -import dayjs from "dayjs"; -import { - isNullTimestamp, - TimeStamp, - timestampToDate, -} from "../../../../utils/connect-timestamp"; +import { formatTimestamp, TimeStamp } from "~/admin/utils/connect-timestamp"; import { DotsHorizontalIcon } from "@radix-ui/react-icons"; import { RenameProjectDialog } from "./rename-project"; import { useState } from "react"; @@ -276,13 +271,7 @@ export const getColumns = ({ { accessorKey: "createdAt", header: "Created On", - cell: ({ getValue }) => { - const value = getValue() as TimeStamp; - const date = isNullTimestamp(value) - ? "-" - : dayjs(timestampToDate(value)).format("YYYY-MM-DD"); - return date; - }, + cell: ({ getValue }) => formatTimestamp(getValue() as TimeStamp), enableSorting: true, enableHiding: true, enableColumnFilter: true, diff --git a/web/sdk/admin/views/organizations/details/side-panel/billing-details-section.tsx b/web/sdk/admin/views/organizations/details/side-panel/billing-details-section.tsx index b82e91411..efd2b0f48 100644 --- a/web/sdk/admin/views/organizations/details/side-panel/billing-details-section.tsx +++ b/web/sdk/admin/views/organizations/details/side-panel/billing-details-section.tsx @@ -8,7 +8,10 @@ import { OrganizationContext } from "../contexts/organization-context"; import { useMutation, useQuery } from "@connectrpc/connect-query"; import { CreateCheckoutRequestSchema, FrontierServiceQueries, GetUpcomingInvoiceRequestSchema } from "@raystack/proton/frontier"; import { create } from "@bufbuild/protobuf"; -import { timestampToDayjs } from "../../../../utils/connect-timestamp"; +import { + formatTimestamp, + isNullTimestamp, +} from "~/admin/utils/connect-timestamp"; export const BillingDetailsSection = () => { const { billingAccount, organization } = useContext(OrganizationContext); @@ -169,10 +172,10 @@ export const BillingDetailsSection = () => { {isLoading ? ( - ) : timestampToDayjs(due_date) ? ( + ) : !isNullTimestamp(due_date) ? ( - {timestampToDayjs(due_date)?.format("DD MMM YYYY")} + {formatTimestamp(due_date)} ) : ( - diff --git a/web/sdk/admin/views/organizations/details/side-panel/org-details-section.tsx b/web/sdk/admin/views/organizations/details/side-panel/org-details-section.tsx index 881c8b458..50e9d4dae 100644 --- a/web/sdk/admin/views/organizations/details/side-panel/org-details-section.tsx +++ b/web/sdk/admin/views/organizations/details/side-panel/org-details-section.tsx @@ -1,11 +1,10 @@ import { CalendarIcon } from "@radix-ui/react-icons"; import { Flex, List, Text, CopyButton, Tooltip } from "@raystack/apsara"; import styles from "./side-panel.module.css"; -import dayjs from "dayjs"; import { useContext } from "react"; import { OrganizationContext } from "../contexts/organization-context"; import type { Organization } from "@raystack/proton/frontier"; -import { timestampToDate } from "../../../../utils/connect-timestamp"; +import { formatTimestamp } from "~/admin/utils/connect-timestamp"; interface OrganizationDetailsSectionProps { organization: Organization; @@ -61,11 +60,7 @@ export const OrganizationDetailsSection = ({ - - {dayjs(timestampToDate(organization.createdAt)).format( - "DD MMM YYYY", - )} - + {formatTimestamp(organization.createdAt)} diff --git a/web/sdk/admin/views/organizations/details/side-panel/plan-details-section.tsx b/web/sdk/admin/views/organizations/details/side-panel/plan-details-section.tsx index 7a570f75d..10cfad2b9 100644 --- a/web/sdk/admin/views/organizations/details/side-panel/plan-details-section.tsx +++ b/web/sdk/admin/views/organizations/details/side-panel/plan-details-section.tsx @@ -7,7 +7,10 @@ import { OrganizationContext } from "../contexts/organization-context"; import { useQuery } from "@connectrpc/connect-query"; import { FrontierServiceQueries, ListSubscriptionsRequestSchema, GetPlanRequestSchema } from "@raystack/proton/frontier"; import { create } from "@bufbuild/protobuf"; -import { timestampToDayjs } from "../../../../utils/connect-timestamp"; +import { + formatTimestamp, + isNullTimestamp, +} from "~/admin/utils/connect-timestamp"; export const PlanDetailsSection = () => { const { billingAccount, organization } = useContext(OrganizationContext); @@ -69,13 +72,11 @@ export const PlanDetailsSection = () => { {isLoading ? ( - ) : timestampToDayjs(activeSubscription?.currentPeriodStartAt) ? ( + ) : !isNullTimestamp(activeSubscription?.currentPeriodStartAt) ? ( - {timestampToDayjs(activeSubscription?.currentPeriodStartAt)?.format( - "DD MMM YYYY", - )} + {formatTimestamp(activeSubscription?.currentPeriodStartAt)} ) : ( @@ -90,13 +91,11 @@ export const PlanDetailsSection = () => { {isLoading ? ( - ) : timestampToDayjs(activeSubscription?.currentPeriodEndAt) ? ( + ) : !isNullTimestamp(activeSubscription?.currentPeriodEndAt) ? ( - {timestampToDayjs(activeSubscription?.currentPeriodEndAt)?.format( - "DD MMM YYYY", - )} + {formatTimestamp(activeSubscription?.currentPeriodEndAt)} ) : ( diff --git a/web/sdk/admin/views/organizations/details/tokens/columns.tsx b/web/sdk/admin/views/organizations/details/tokens/columns.tsx index 38dc02aad..431caf00b 100644 --- a/web/sdk/admin/views/organizations/details/tokens/columns.tsx +++ b/web/sdk/admin/views/organizations/details/tokens/columns.tsx @@ -1,6 +1,4 @@ import styles from "./tokens.module.css"; -import { NULL_DATE } from "../../../../utils/constants"; -import dayjs from "dayjs"; import { Avatar, DataTableColumnDef, @@ -12,11 +10,7 @@ import { import type { SearchOrganizationTokensResponse_OrganizationToken, } from "@raystack/proton/frontier"; -import { - isNullTimestamp, - TimeStamp, - timestampToDate, -} from "../../../../utils/connect-timestamp"; +import { formatTimestamp, TimeStamp } from "~/admin/utils/connect-timestamp"; import { TerminologyEntity } from "../../../../hooks/useTerminology"; interface GetColumnsOptions { @@ -38,13 +32,7 @@ export const getColumns = ({ t }: GetColumnsOptions): DataTableColumnDef< header: styles["first-column"], }, styles: { header: { width: "180px" } }, - cell: ({ getValue }) => { - const value = getValue() as TimeStamp; - const date = isNullTimestamp(value) - ? "-" - : dayjs(timestampToDate(value)).format("YYYY-MM-DD"); - return date; - }, + cell: ({ getValue }) => formatTimestamp(getValue() as TimeStamp), enableSorting: true, enableColumnFilter: true, filterType: "date", diff --git a/web/sdk/admin/views/organizations/list/columns.tsx b/web/sdk/admin/views/organizations/list/columns.tsx index b3b57abeb..c48258bb5 100644 --- a/web/sdk/admin/views/organizations/list/columns.tsx +++ b/web/sdk/admin/views/organizations/list/columns.tsx @@ -10,12 +10,7 @@ import type { SearchOrganizationsResponse_OrganizationResult, Plan, } from "@raystack/proton/frontier"; -import { - isNullTimestamp, - TimeStamp, - timestampToDate, -} from "../../../utils/connect-timestamp"; -import dayjs from "dayjs"; +import { formatTimestamp, TimeStamp } from "~/admin/utils/connect-timestamp"; import styles from "./list.module.css"; export const SUBSCRIPTION_STATES = { @@ -118,13 +113,9 @@ export const getColumns = ({ accessorKey: "subscriptionCycleEndAt", header: "Cycle ends on", filterType: "date", - cell: ({ getValue }) => { - const value = getValue() as TimeStamp; - const date = isNullTimestamp(value) - ? "-" - : dayjs(timestampToDate(value)).format("YYYY-MM-DD"); - return {date}; - }, + cell: ({ getValue }) => ( + {formatTimestamp(getValue() as TimeStamp)} + ), enableColumnFilter: true, // enableSorting: true, enableHiding: true, @@ -171,13 +162,9 @@ export const getColumns = ({ accessorKey: "createdAt", header: "Created On", filterType: "date", - cell: ({ getValue }) => { - const value = getValue() as TimeStamp; - const date = isNullTimestamp(value) - ? "-" - : dayjs(timestampToDate(value)).format("YYYY-MM-DD"); - return {date}; - }, + cell: ({ getValue }) => ( + {formatTimestamp(getValue() as TimeStamp)} + ), enableHiding: true, defaultHidden: true, enableSorting: true, diff --git a/web/sdk/admin/views/plans/columns.tsx b/web/sdk/admin/views/plans/columns.tsx index 843a32fb2..14961846d 100644 --- a/web/sdk/admin/views/plans/columns.tsx +++ b/web/sdk/admin/views/plans/columns.tsx @@ -1,6 +1,6 @@ import { Text, type DataTableColumnDef } from "@raystack/apsara"; import type { Plan } from "@raystack/proton/frontier"; -import { timestampToDate, type TimeStamp } from "../../utils/connect-timestamp"; +import { formatTimestamp, TimeStamp } from "~/admin/utils/connect-timestamp"; import styles from "./plans.module.css"; export const getColumns: (options?: { @@ -17,7 +17,7 @@ export const getColumns: (options?: { cell: styles["first-column"], header: styles["first-column"], }, - filterVariant: "text", + filterType: "string", cell: ({ getValue }) => { const id = getValue() as string; return ( @@ -34,28 +34,19 @@ export const getColumns: (options?: { { header: "Title", accessorKey: "title", - filterVariant: "text", + filterType: "string", cell: (info) => info.getValue(), }, { header: "Interval", accessorKey: "interval", - filterVariant: "text", + filterType: "string", cell: (info) => info.getValue(), }, { header: "Created At", accessorKey: "createdAt", - cell: ({ getValue }) => { - const timestamp = getValue() as TimeStamp | undefined; - const date = timestampToDate(timestamp); - if (!date) return "-"; - return date.toLocaleString("en", { - month: "long", - day: "numeric", - year: "numeric", - }); - }, + cell: ({ getValue }) => formatTimestamp(getValue() as TimeStamp), }, ]; }; diff --git a/web/sdk/admin/views/plans/details.tsx b/web/sdk/admin/views/plans/details.tsx index fab192f4b..0473a75bc 100644 --- a/web/sdk/admin/views/plans/details.tsx +++ b/web/sdk/admin/views/plans/details.tsx @@ -1,6 +1,6 @@ import { Flex, Text, Grid } from "@raystack/apsara"; import type { Plan } from "@raystack/proton/frontier"; -import { timestampToDate } from "../../utils/connect-timestamp"; +import { formatTimestamp } from "~/admin/utils/connect-timestamp"; export default function PlanDetails({ plan }: { plan: Plan | null }) { @@ -18,16 +18,7 @@ export default function PlanDetails({ plan }: { plan: Plan | null }) { Created At - - {(() => { - const date = timestampToDate(plan?.createdAt); - return date ? date.toLocaleString("en", { - month: "long", - day: "numeric", - year: "numeric", - }) : "-"; - })()} - + {formatTimestamp(plan?.createdAt)} diff --git a/web/sdk/admin/views/preferences/columns.tsx b/web/sdk/admin/views/preferences/columns.tsx index c63c37364..c934cb989 100644 --- a/web/sdk/admin/views/preferences/columns.tsx +++ b/web/sdk/admin/views/preferences/columns.tsx @@ -23,7 +23,7 @@ export const getColumns: ( cell: styles["first-column"], header: styles["first-column"], }, - filterVariant: "text", + filterType: "string", cell: (info) => info.getValue(), footer: (props) => props.column.id, }, diff --git a/web/sdk/admin/views/preferences/details.tsx b/web/sdk/admin/views/preferences/details.tsx index e000af806..1ba89061b 100644 --- a/web/sdk/admin/views/preferences/details.tsx +++ b/web/sdk/admin/views/preferences/details.tsx @@ -11,12 +11,11 @@ import { } from "@raystack/apsara"; import { useCallback, useEffect, useState } from "react"; import Skeleton from "react-loading-skeleton"; -import dayjs from "dayjs"; import { useMutation, createConnectQueryKey, useTransport } from "@connectrpc/connect-query"; import { handleConnectError } from "~/utils/error"; import { AdminServiceQueries, CreatePreferencesRequestSchema, ListPreferencesResponse } from "@raystack/proton/frontier"; import { Preference, PreferenceTrait, PreferenceTrait_InputType } from "@raystack/proton/frontier"; -import { timestampDate } from "@bufbuild/protobuf/wkt"; +import { DATE_FORMAT, formatTimestamp } from "~/admin/utils/connect-timestamp"; import { useQueryClient } from "@tanstack/react-query"; import { create } from "@bufbuild/protobuf"; @@ -168,9 +167,7 @@ export default function PreferenceDetails({ }, { key: "Last updated", - value: - preference?.updatedAt && - dayjs(timestampDate(preference.updatedAt)).format("MMM DD, YYYY hh:mm:ss A"), + value: formatTimestamp(preference?.updatedAt, `${DATE_FORMAT} hh:mm:ss A`), }, ]; diff --git a/web/sdk/admin/views/products/columns.tsx b/web/sdk/admin/views/products/columns.tsx index 7bc7417d6..41251cfdd 100644 --- a/web/sdk/admin/views/products/columns.tsx +++ b/web/sdk/admin/views/products/columns.tsx @@ -1,6 +1,6 @@ import { Flex, Image, Amount, type DataTableColumnDef } from "@raystack/apsara"; import type { Product } from "@raystack/proton/frontier"; -import { timestampToDate, TimeStamp } from "../../utils/connect-timestamp"; +import { formatTimestamp, TimeStamp } from "~/admin/utils/connect-timestamp"; import styles from "./products.module.css"; export const getColumns = ( @@ -79,38 +79,20 @@ export const getColumns = ( { header: "Product Id", accessorKey: "id", - filterVariant: "text", + filterType: "string", cell: (info) => info.getValue(), }, { header: "Created on", accessorKey: "createdAt", - cell: ({ getValue }) => { - const timestamp = getValue() as TimeStamp | undefined; - const date = timestampToDate(timestamp); - if (!date) return "-"; - return date.toLocaleString("en", { - month: "long", - day: "numeric", - year: "numeric", - }); - }, - filterVariant: "date", + cell: ({ getValue }) => formatTimestamp(getValue() as TimeStamp), + filterType: "date", }, { header: "Updated on", accessorKey: "updatedAt", - cell: ({ getValue }) => { - const timestamp = getValue() as TimeStamp | undefined; - const date = timestampToDate(timestamp); - if (!date) return "-"; - return date.toLocaleString("en", { - month: "long", - day: "numeric", - year: "numeric", - }); - }, - filterVariant: "date", + cell: ({ getValue }) => formatTimestamp(getValue() as TimeStamp), + filterType: "date", }, ]; }; diff --git a/web/sdk/admin/views/products/prices/columns.tsx b/web/sdk/admin/views/products/prices/columns.tsx index 2038e45be..e0d2cfbcd 100644 --- a/web/sdk/admin/views/products/prices/columns.tsx +++ b/web/sdk/admin/views/products/prices/columns.tsx @@ -1,7 +1,7 @@ import type { Price as PriceType } from "@raystack/proton/frontier"; import { Amount } from "@raystack/apsara"; import type { DataTableColumnDef } from "@raystack/apsara"; -import { timestampToDate, TimeStamp } from "../../../utils/connect-timestamp"; +import { formatTimestamp, TimeStamp } from "~/admin/utils/connect-timestamp"; import styles from "./prices.module.css"; export const getColumns = ( @@ -16,31 +16,31 @@ export const getColumns = ( header: styles["first-column"], }, cell: (info) => info.getValue(), - filterVariant: "text", + filterType: "string", }, { header: "name", accessorKey: "name", cell: (info) => info.getValue(), - filterVariant: "text", + filterType: "string", }, { header: "interval", accessorKey: "interval", cell: (info) => info.getValue(), - filterVariant: "text", + filterType: "string", }, { header: "Usage Type", accessorKey: "usageType", cell: (info) => info.getValue(), - filterVariant: "text", + filterType: "string", }, { header: "billing_scheme", accessorKey: "billingScheme", cell: (info) => info.getValue(), - filterVariant: "text", + filterType: "string", }, { header: "Amount", @@ -51,36 +51,18 @@ export const getColumns = ( currency={row.original.currency} /> ), - filterVariant: "text", + filterType: "string", }, { header: "creation date", accessorKey: "createdAt", - cell: ({ getValue }) => { - const timestamp = getValue() as TimeStamp | undefined; - const date = timestampToDate(timestamp); - if (!date) return "-"; - return date.toLocaleString("en", { - month: "long", - day: "numeric", - year: "numeric", - }); - }, + cell: ({ getValue }) => formatTimestamp(getValue() as TimeStamp), }, { header: "Updated date", accessorKey: "updatedAt", enableColumnFilter: false, - cell: ({ getValue }) => { - const timestamp = getValue() as TimeStamp | undefined; - const date = timestampToDate(timestamp); - if (!date) return "-"; - return date.toLocaleString("en", { - month: "long", - day: "numeric", - year: "numeric", - }); - }, + cell: ({ getValue }) => formatTimestamp(getValue() as TimeStamp), }, ]; }; diff --git a/web/sdk/admin/views/roles/columns.tsx b/web/sdk/admin/views/roles/columns.tsx index bc7ff80df..07e331912 100644 --- a/web/sdk/admin/views/roles/columns.tsx +++ b/web/sdk/admin/views/roles/columns.tsx @@ -10,19 +10,19 @@ export const getColumns: () => DataTableColumnDef[] = () => { cell: styles["first-column"], header: styles["first-column"], }, - filterVariant: "text", + filterType: "string", cell: ({ getValue }) => getValue(), }, { header: "Title", accessorKey: "title", - filterVariant: "text", + filterType: "string", cell: info => info.getValue(), }, { header: "Name", accessorKey: "name", - filterVariant: "text", + filterType: "string", cell: info => info.getValue(), }, { diff --git a/web/sdk/admin/views/users/details/layout/side-panel-details.tsx b/web/sdk/admin/views/users/details/layout/side-panel-details.tsx index 5c4711b96..f02cabb02 100644 --- a/web/sdk/admin/views/users/details/layout/side-panel-details.tsx +++ b/web/sdk/admin/views/users/details/layout/side-panel-details.tsx @@ -3,7 +3,7 @@ import { CalendarIcon } from "@radix-ui/react-icons"; import styles from "./side-panel.module.css"; import { UserState, USER_STATES } from "../../util"; import { useUser } from "../user-context"; -import { timestampToDayjs } from "../../../../utils/connect-timestamp"; +import { formatTimestamp } from "~/admin/utils/connect-timestamp"; export const SidePanelDetails = () => { const { user } = useUser(); @@ -37,7 +37,7 @@ export const SidePanelDetails = () => { - {timestampToDayjs(user?.createdAt)?.format("DD MMM YYYY")} + {formatTimestamp(user?.createdAt)} diff --git a/web/sdk/admin/views/users/details/layout/side-panel-membership.tsx b/web/sdk/admin/views/users/details/layout/side-panel-membership.tsx index 3dc0831c3..49de4da73 100644 --- a/web/sdk/admin/views/users/details/layout/side-panel-membership.tsx +++ b/web/sdk/admin/views/users/details/layout/side-panel-membership.tsx @@ -1,11 +1,10 @@ import { Flex, List, Text, Avatar } from "@raystack/apsara"; -import dayjs from "dayjs"; import { CalendarIcon } from "@radix-ui/react-icons"; import Skeleton from "react-loading-skeleton"; import { type SearchUserOrganizationsResponse_UserOrganization } from "@raystack/proton/frontier"; import styles from "./side-panel.module.css"; import { MembershipDropdown } from "./membership-dropdown"; -import { timestampToDate, isNullTimestamp } from "../../../../utils/connect-timestamp"; +import { formatTimestamp } from "~/admin/utils/connect-timestamp"; interface SidePanelMembershipProps { data?: SearchUserOrganizationsResponse_UserOrganization; @@ -69,9 +68,7 @@ export const SidePanelMembership = ({ - {data?.orgJoinedOn && !isNullTimestamp(data.orgJoinedOn) - ? dayjs(timestampToDate(data.orgJoinedOn)).format("DD MMM YYYY") - : "-"} + {formatTimestamp(data?.orgJoinedOn)} diff --git a/web/sdk/admin/views/users/list/columns.tsx b/web/sdk/admin/views/users/list/columns.tsx index 0083dc7d7..d45f6007c 100644 --- a/web/sdk/admin/views/users/list/columns.tsx +++ b/web/sdk/admin/views/users/list/columns.tsx @@ -6,15 +6,10 @@ import { getAvatarColor, Text, } from "@raystack/apsara"; -import dayjs from "dayjs"; import styles from "./list.module.css"; import { getUserName, USER_STATES, UserState } from "../util"; import { User } from "@raystack/proton/frontier"; -import { - isNullTimestamp, - TimeStamp, - timestampToDate, -} from "../../../utils/connect-timestamp"; +import { formatTimestamp, TimeStamp } from "~/admin/utils/connect-timestamp"; interface getColumnsOptions { groupCountMap: Record>; @@ -69,11 +64,7 @@ export const getColumns = ({ header: "Joined on", filterType: "date", cell: ({ getValue }) => { - const value = getValue() as TimeStamp; - const date = isNullTimestamp(value) - ? "-" - : dayjs(timestampToDate(value)).format("YYYY-MM-DD"); - return {date}; + return {formatTimestamp(getValue() as TimeStamp)}; }, enableHiding: true, enableSorting: true, diff --git a/web/sdk/admin/views/webhooks/webhooks/columns.tsx b/web/sdk/admin/views/webhooks/webhooks/columns.tsx index 46c45c0a8..f1113c611 100644 --- a/web/sdk/admin/views/webhooks/webhooks/columns.tsx +++ b/web/sdk/admin/views/webhooks/webhooks/columns.tsx @@ -8,11 +8,9 @@ import { import styles from "./webhooks.module.css"; import { type Webhook } from "@raystack/proton/frontier"; import { - timestampToDate, - isNullTimestamp, + formatTimestamp, type TimeStamp, -} from "../../../utils/connect-timestamp"; -import dayjs from "dayjs"; +} from "~/admin/utils/connect-timestamp"; import { useState } from "react"; import type { useMutation } from "@connectrpc/connect-query"; import { DeleteWebhookDialog } from "./delete"; @@ -34,13 +32,13 @@ export const getColumns: ( cell: styles["first-column"], header: styles["first-column"], }, - filterVariant: "text", + filterType: "string", cell: (info) => info.getValue() || "-", }, { header: "State", accessorKey: "state", - filterVariant: "text", + filterType: "string", classNames: { cell: styles.stateColumn, header: styles.stateColumn }, cell: (info) => info.getValue() || "-", }, @@ -53,13 +51,9 @@ export const getColumns: ( header: "Created at", accessorKey: "createdAt", classNames: { cell: styles.dateColumn, header: styles.dateColumn }, - cell: ({ getValue }) => { - const value = getValue() as TimeStamp; - const date = isNullTimestamp(value) - ? "-" - : dayjs(timestampToDate(value)).format("YYYY-MM-DD"); - return {date}; - }, + cell: ({ getValue }) => ( + {formatTimestamp(getValue() as TimeStamp)} + ), }, { header: "Action", diff --git a/web/sdk/client/views/plans/components/plan-card.tsx b/web/sdk/client/views/plans/components/plan-card.tsx index acb16deba..8911b1b24 100644 --- a/web/sdk/client/views/plans/components/plan-card.tsx +++ b/web/sdk/client/views/plans/components/plan-card.tsx @@ -12,7 +12,10 @@ import { import { useFrontier } from '~/client/contexts/FrontierContext'; import { usePlans } from '../hooks/use-plans'; import { PlanChangeAction, getPlanChangeAction } from '~/client/utils'; -import { SUBSCRIPTION_STATES } from '~/client/utils/constants'; +import { + DEFAULT_DATE_SHORT_FORMAT, + SUBSCRIPTION_STATES +} from '~/client/utils/constants'; import { timestampToDayjs } from '~/utils/timestamp'; import { IntervalKeys, @@ -141,7 +144,7 @@ export function PlanCard({ sub.state === SUBSCRIPTION_STATES.TRIALING ); - const shortDateFormat = config?.shortDateFormat || 'DD MMM'; + const shortDateFormat = config?.shortDateFormat || DEFAULT_DATE_SHORT_FORMAT; const trialEndDate = trialSubscription?.trialEndsAt ? timestampToDayjs(trialSubscription?.trialEndsAt)?.format(shortDateFormat) : '';