From ae91147b6c1e72ee824495a5aa078582fa054431 Mon Sep 17 00:00:00 2001 From: Usman Baig Date: Tue, 17 Feb 2026 20:49:55 +0100 Subject: [PATCH] chore: update @ciphera-net/ui dependency to version 0.0.57 in package.json and package-lock.json; refactor imports across multiple components for consistency --- app/auth/callback/page.tsx | 2 +- app/notifications/page.tsx | 6 +- app/onboarding/page.tsx | 2 +- app/page.tsx | 2 +- app/share/[id]/page.tsx | 2 +- app/sites/[id]/funnels/[funnelId]/page.tsx | 2 +- app/sites/[id]/page.tsx | 4 +- app/sites/[id]/realtime/page.tsx | 2 +- app/sites/[id]/settings/page.tsx | 2 +- app/sites/[id]/uptime/page.tsx | 2 +- app/sites/new/page.tsx | 2 +- app/welcome/page.tsx | 2 +- components/CodeBlock.tsx | 28 -------- components/Footer.tsx | 3 +- components/LoadingOverlay.tsx | 42 ----------- components/SwissFlagIcon.tsx | 24 ------- components/dashboard/Campaigns.tsx | 6 +- components/dashboard/Chart.tsx | 2 +- components/dashboard/ContentStats.tsx | 6 +- components/dashboard/Countries.tsx | 2 +- components/dashboard/ExportModal.tsx | 2 +- components/dashboard/GoalStats.tsx | 2 +- components/dashboard/Locations.tsx | 6 +- components/dashboard/TechSpecs.tsx | 6 +- components/dashboard/TopPages.tsx | 2 +- components/dashboard/TopReferrers.tsx | 6 +- .../notifications/NotificationCenter.tsx | 2 +- components/settings/OrganizationSettings.tsx | 13 ++-- lib/api/client.ts | 2 +- lib/integration-guides.tsx | 2 +- lib/utils/authErrors.ts | 63 ----------------- lib/utils/format.ts | 70 ------------------- package-lock.json | 8 +-- package.json | 2 +- 34 files changed, 51 insertions(+), 278 deletions(-) delete mode 100644 components/CodeBlock.tsx delete mode 100644 components/LoadingOverlay.tsx delete mode 100644 components/SwissFlagIcon.tsx delete mode 100644 lib/utils/authErrors.ts delete mode 100644 lib/utils/format.ts diff --git a/app/auth/callback/page.tsx b/app/auth/callback/page.tsx index c3fe5ac..30396c4 100644 --- a/app/auth/callback/page.tsx +++ b/app/auth/callback/page.tsx @@ -5,7 +5,7 @@ import { useRouter, useSearchParams } from 'next/navigation' import { useAuth } from '@/lib/auth/context' import { AUTH_URL, default as apiRequest } from '@/lib/api/client' import { exchangeAuthCode, setSessionAction } from '@/app/actions/auth' -import { authMessageFromErrorType, type AuthErrorType } from '@/lib/utils/authErrors' +import { authMessageFromErrorType, type AuthErrorType } from '@ciphera-net/ui' import { LoadingOverlay } from '@ciphera-net/ui' function AuthCallbackContent() { diff --git a/app/notifications/page.tsx b/app/notifications/page.tsx index b46a912..be979d5 100644 --- a/app/notifications/page.tsx +++ b/app/notifications/page.tsx @@ -13,9 +13,9 @@ import { markAllNotificationsRead, type Notification, } from '@/lib/api/notifications' -import { getAuthErrorMessage } from '@/lib/utils/authErrors' +import { getAuthErrorMessage } from '@ciphera-net/ui' import { formatTimeAgo, getTypeIcon } from '@/lib/utils/notifications' -import { Button, ArrowLeftIcon } from '@ciphera-net/ui' +import { Button, ArrowLeftIcon, Spinner } from '@ciphera-net/ui' import { toast } from '@ciphera-net/ui' const PAGE_SIZE = 50 @@ -129,7 +129,7 @@ export default function NotificationsPage() { {loading ? (
-
+
) : error ? (
diff --git a/app/onboarding/page.tsx b/app/onboarding/page.tsx index 934c8ff..72b5307 100644 --- a/app/onboarding/page.tsx +++ b/app/onboarding/page.tsx @@ -4,7 +4,7 @@ import { useState } from 'react' import { useRouter } from 'next/navigation' import { createOrganization } from '@/lib/api/organization' import { useAuth } from '@/lib/auth/context' -import { getAuthErrorMessage } from '@/lib/utils/authErrors' +import { getAuthErrorMessage } from '@ciphera-net/ui' import { LoadingOverlay } from '@ciphera-net/ui' import { Button, Input } from '@ciphera-net/ui' diff --git a/app/page.tsx b/app/page.tsx index 9c15ae4..90eed1d 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -12,7 +12,7 @@ import SiteList from '@/components/sites/SiteList' import { Button } from '@ciphera-net/ui' import { BarChartIcon, LockIcon, ZapIcon, CheckCircleIcon, XIcon, GlobeIcon } from '@ciphera-net/ui' import { toast } from '@ciphera-net/ui' -import { getAuthErrorMessage } from '@/lib/utils/authErrors' +import { getAuthErrorMessage } from '@ciphera-net/ui' function DashboardPreview() { return ( diff --git a/app/share/[id]/page.tsx b/app/share/[id]/page.tsx index 912f158..30dcfbf 100644 --- a/app/share/[id]/page.tsx +++ b/app/share/[id]/page.tsx @@ -4,7 +4,7 @@ import { useCallback, useEffect, useState } from 'react' import { useParams, useSearchParams, useRouter } from 'next/navigation' import { getPublicDashboard, getPublicStats, getPublicDailyStats, getPublicRealtime, getPublicPerformanceByPage, type DashboardData, type Stats, type DailyStat, type PerformanceByPageStat } from '@/lib/api/stats' import { toast } from '@ciphera-net/ui' -import { getAuthErrorMessage } from '@/lib/utils/authErrors' +import { getAuthErrorMessage } from '@ciphera-net/ui' import { LoadingOverlay, Button } from '@ciphera-net/ui' import Chart from '@/components/dashboard/Chart' import TopPages from '@/components/dashboard/ContentStats' diff --git a/app/sites/[id]/funnels/[funnelId]/page.tsx b/app/sites/[id]/funnels/[funnelId]/page.tsx index 2e200ef..687e5c4 100644 --- a/app/sites/[id]/funnels/[funnelId]/page.tsx +++ b/app/sites/[id]/funnels/[funnelId]/page.tsx @@ -16,7 +16,7 @@ import { ResponsiveContainer, Cell } from 'recharts' -import { getDateRange } from '@/lib/utils/format' +import { getDateRange } from '@ciphera-net/ui' const CHART_COLORS_LIGHT = { border: '#E5E5E5', diff --git a/app/sites/[id]/page.tsx b/app/sites/[id]/page.tsx index 89ea7db..d541511 100644 --- a/app/sites/[id]/page.tsx +++ b/app/sites/[id]/page.tsx @@ -6,9 +6,9 @@ import { useParams, useRouter } from 'next/navigation' import { motion } from 'framer-motion' import { getSite, type Site } from '@/lib/api/sites' import { getStats, getRealtime, getDailyStats, getTopPages, getTopReferrers, getCountries, getCities, getRegions, getBrowsers, getOS, getDevices, getScreenResolutions, getEntryPages, getExitPages, getDashboard, getCampaigns, getPerformanceByPage, type Stats, type DailyStat, type PerformanceByPageStat } from '@/lib/api/stats' -import { formatNumber, formatDuration, getDateRange } from '@/lib/utils/format' +import { formatNumber, formatDuration, getDateRange } from '@ciphera-net/ui' import { toast } from '@ciphera-net/ui' -import { getAuthErrorMessage } from '@/lib/utils/authErrors' +import { getAuthErrorMessage } from '@ciphera-net/ui' import { LoadingOverlay, Button } from '@ciphera-net/ui' import { Select, DatePicker, DownloadIcon } from '@ciphera-net/ui' import ExportModal from '@/components/dashboard/ExportModal' diff --git a/app/sites/[id]/realtime/page.tsx b/app/sites/[id]/realtime/page.tsx index f3be638..78cb713 100644 --- a/app/sites/[id]/realtime/page.tsx +++ b/app/sites/[id]/realtime/page.tsx @@ -5,7 +5,7 @@ import { useParams, useRouter } from 'next/navigation' import { getSite, type Site } from '@/lib/api/sites' import { getRealtimeVisitors, getSessionDetails, type Visitor, type SessionEvent } from '@/lib/api/realtime' import { toast } from '@ciphera-net/ui' -import { getAuthErrorMessage } from '@/lib/utils/authErrors' +import { getAuthErrorMessage } from '@ciphera-net/ui' import { LoadingOverlay, UserIcon } from '@ciphera-net/ui' import { motion, AnimatePresence } from 'framer-motion' diff --git a/app/sites/[id]/settings/page.tsx b/app/sites/[id]/settings/page.tsx index 32935e2..c537b68 100644 --- a/app/sites/[id]/settings/page.tsx +++ b/app/sites/[id]/settings/page.tsx @@ -5,7 +5,7 @@ import { useParams, useRouter } from 'next/navigation' import { getSite, updateSite, resetSiteData, deleteSite, type Site, type GeoDataLevel } from '@/lib/api/sites' import { listGoals, createGoal, updateGoal, deleteGoal, type Goal } from '@/lib/api/goals' import { toast } from '@ciphera-net/ui' -import { getAuthErrorMessage } from '@/lib/utils/authErrors' +import { getAuthErrorMessage } from '@ciphera-net/ui' import { LoadingOverlay } from '@ciphera-net/ui' import VerificationModal from '@/components/sites/VerificationModal' import ScriptSetupBlock from '@/components/sites/ScriptSetupBlock' diff --git a/app/sites/[id]/uptime/page.tsx b/app/sites/[id]/uptime/page.tsx index 2aa04d7..49c093a 100644 --- a/app/sites/[id]/uptime/page.tsx +++ b/app/sites/[id]/uptime/page.tsx @@ -19,7 +19,7 @@ import { } from '@/lib/api/uptime' import { toast } from '@ciphera-net/ui' import { useTheme } from '@ciphera-net/ui' -import { getAuthErrorMessage } from '@/lib/utils/authErrors' +import { getAuthErrorMessage } from '@ciphera-net/ui' import { LoadingOverlay, Button, Modal } from '@ciphera-net/ui' import { AreaChart, diff --git a/app/sites/new/page.tsx b/app/sites/new/page.tsx index 0ca6617..8180b11 100644 --- a/app/sites/new/page.tsx +++ b/app/sites/new/page.tsx @@ -7,7 +7,7 @@ import { createSite, listSites, getSite, type Site } from '@/lib/api/sites' import { getSubscription } from '@/lib/api/billing' import { trackSiteCreatedFromDashboard, trackSiteCreatedScriptCopied } from '@/lib/welcomeAnalytics' import { toast } from '@ciphera-net/ui' -import { getAuthErrorMessage } from '@/lib/utils/authErrors' +import { getAuthErrorMessage } from '@ciphera-net/ui' import { Button, Input } from '@ciphera-net/ui' import { CheckCircleIcon } from '@ciphera-net/ui' import ScriptSetupBlock from '@/components/sites/ScriptSetupBlock' diff --git a/app/welcome/page.tsx b/app/welcome/page.tsx index 7193206..bab5fbe 100644 --- a/app/welcome/page.tsx +++ b/app/welcome/page.tsx @@ -21,7 +21,7 @@ import { createSite, type Site } from '@/lib/api/sites' import { setSessionAction } from '@/app/actions/auth' import { useAuth } from '@/lib/auth/context' import apiRequest from '@/lib/api/client' -import { getAuthErrorMessage } from '@/lib/utils/authErrors' +import { getAuthErrorMessage } from '@ciphera-net/ui' import { trackWelcomeStepView, trackWelcomeWorkspaceSelected, diff --git a/components/CodeBlock.tsx b/components/CodeBlock.tsx deleted file mode 100644 index 8379a41..0000000 --- a/components/CodeBlock.tsx +++ /dev/null @@ -1,28 +0,0 @@ -/** - * @file Reusable code block component for integration guide pages. - * - * Renders a VS-Code-style code block with a filename tab header. - */ - -interface CodeBlockProps { - /** Filename displayed in the tab header */ - filename: string - /** The code string to render inside the block */ - children: string -} - -/** - * Renders a dark-themed code snippet with a filename tab. - */ -export function CodeBlock({ filename, children }: CodeBlockProps) { - return ( -
-
- {filename} -
-
-
{children}
-
-
- ) -} diff --git a/components/Footer.tsx b/components/Footer.tsx index ac6ed50..cf7865a 100644 --- a/components/Footer.tsx +++ b/components/Footer.tsx @@ -2,8 +2,7 @@ import Link from 'next/link' import Image from 'next/image' -import { GithubIcon, TwitterIcon } from '@ciphera-net/ui' -import SwissFlagIcon from './SwissFlagIcon' +import { GithubIcon, TwitterIcon, SwissFlagIcon } from '@ciphera-net/ui' interface FooterProps { LinkComponent?: any diff --git a/components/LoadingOverlay.tsx b/components/LoadingOverlay.tsx deleted file mode 100644 index 342cc27..0000000 --- a/components/LoadingOverlay.tsx +++ /dev/null @@ -1,42 +0,0 @@ -'use client' - -import React, { useEffect, useState } from 'react' -import { createPortal } from 'react-dom' - -interface LoadingOverlayProps { - logoSrc?: string - title?: string -} - -export default function LoadingOverlay({ - logoSrc = "/ciphera_icon_no_margins.png", - title = "Pulse" -}: LoadingOverlayProps) { - const [mounted, setMounted] = useState(false) - - useEffect(() => { - setMounted(true) - return () => setMounted(false) - }, []) - - if (!mounted) return null - - return createPortal( -
-
-
- {typeof - - CipheraPulse - -
-
-
-
, - document.body - ) -} diff --git a/components/SwissFlagIcon.tsx b/components/SwissFlagIcon.tsx deleted file mode 100644 index 4c8ea5e..0000000 --- a/components/SwissFlagIcon.tsx +++ /dev/null @@ -1,24 +0,0 @@ -'use client' - -import type { SVGProps } from 'react' - -// * Swiss flag icon – official proportions (cross 1/6 height). Uses real Swiss federal red. -const SWISS_RED = '#E41E26' // * Official Swiss flag red (federal identity) - -export default function SwissFlagIcon(props: SVGProps) { - const { className, ...rest } = props - return ( - - - - - - ) -} diff --git a/components/dashboard/Campaigns.tsx b/components/dashboard/Campaigns.tsx index 9e3a923..96c7ebf 100644 --- a/components/dashboard/Campaigns.tsx +++ b/components/dashboard/Campaigns.tsx @@ -2,8 +2,8 @@ import { useState, useEffect, useMemo } from 'react' import Link from 'next/link' -import { formatNumber } from '@/lib/utils/format' -import { Modal, ArrowRightIcon, Button } from '@ciphera-net/ui' +import { formatNumber } from '@ciphera-net/ui' +import { Modal, ArrowRightIcon, Button, Spinner } from '@ciphera-net/ui' import { ChevronDownIcon, DownloadIcon } from '@ciphera-net/ui' import { getCampaigns, CampaignStat } from '@/lib/api/stats' import { getReferrerFavicon, getReferrerIcon, getReferrerDisplayName } from '@/lib/utils/icons' @@ -293,7 +293,7 @@ export default function Campaigns({ siteId, dateRange }: CampaignsProps) {
{isLoadingFull ? (
-
+

Loading...

) : ( diff --git a/components/dashboard/Chart.tsx b/components/dashboard/Chart.tsx index 89ff932..f5c08e5 100644 --- a/components/dashboard/Chart.tsx +++ b/components/dashboard/Chart.tsx @@ -13,7 +13,7 @@ import { ReferenceLine, } from 'recharts' import type { TooltipProps } from 'recharts' -import { formatNumber, formatDuration, formatUpdatedAgo } from '@/lib/utils/format' +import { formatNumber, formatDuration, formatUpdatedAgo } from '@ciphera-net/ui' import { ArrowUpRightIcon, ArrowDownRightIcon, BarChartIcon, Select, Button, DownloadIcon } from '@ciphera-net/ui' import { Checkbox } from '@ciphera-net/ui' diff --git a/components/dashboard/ContentStats.tsx b/components/dashboard/ContentStats.tsx index 7f6852b..b7d65dd 100644 --- a/components/dashboard/ContentStats.tsx +++ b/components/dashboard/ContentStats.tsx @@ -1,9 +1,9 @@ 'use client' import { useState, useEffect } from 'react' -import { formatNumber } from '@/lib/utils/format' +import { formatNumber } from '@ciphera-net/ui' import { TopPage, getTopPages, getEntryPages, getExitPages } from '@/lib/api/stats' -import { Modal, ArrowUpRightIcon, LayoutDashboardIcon } from '@ciphera-net/ui' +import { Modal, ArrowUpRightIcon, LayoutDashboardIcon, Spinner } from '@ciphera-net/ui' interface ContentStatsProps { topPages: TopPage[] @@ -174,7 +174,7 @@ export default function ContentStats({ topPages, entryPages, exitPages, domain,
{isLoadingFull ? (
-
+

Loading...

) : ( diff --git a/components/dashboard/Countries.tsx b/components/dashboard/Countries.tsx index 49ce2ef..fba76a9 100644 --- a/components/dashboard/Countries.tsx +++ b/components/dashboard/Countries.tsx @@ -1,7 +1,7 @@ 'use client' import { useState } from 'react' -import { formatNumber } from '@/lib/utils/format' +import { formatNumber } from '@ciphera-net/ui' import * as Flags from 'country-flag-icons/react/3x2' import WorldMap from './WorldMap' import { GlobeIcon } from '@ciphera-net/ui' diff --git a/components/dashboard/ExportModal.tsx b/components/dashboard/ExportModal.tsx index bef7d2e..ca4ce39 100644 --- a/components/dashboard/ExportModal.tsx +++ b/components/dashboard/ExportModal.tsx @@ -6,7 +6,7 @@ import * as XLSX from 'xlsx' import jsPDF from 'jspdf' import autoTable from 'jspdf-autotable' import type { DailyStat } from './Chart' -import { formatNumber, formatDuration } from '@/lib/utils/format' +import { formatNumber, formatDuration } from '@ciphera-net/ui' import { getReferrerDisplayName, mergeReferrersByDisplayName } from '@/lib/utils/icons' import type { TopPage, TopReferrer, CampaignStat } from '@/lib/api/stats' diff --git a/components/dashboard/GoalStats.tsx b/components/dashboard/GoalStats.tsx index fde2a91..6c0571f 100644 --- a/components/dashboard/GoalStats.tsx +++ b/components/dashboard/GoalStats.tsx @@ -1,7 +1,7 @@ 'use client' import Link from 'next/link' -import { formatNumber } from '@/lib/utils/format' +import { formatNumber } from '@ciphera-net/ui' import { BookOpenIcon, ArrowRightIcon } from '@ciphera-net/ui' import type { GoalCountStat } from '@/lib/api/stats' diff --git a/components/dashboard/Locations.tsx b/components/dashboard/Locations.tsx index 56df267..4d85d34 100644 --- a/components/dashboard/Locations.tsx +++ b/components/dashboard/Locations.tsx @@ -1,12 +1,12 @@ 'use client' import { useState, useEffect } from 'react' -import { formatNumber } from '@/lib/utils/format' +import { formatNumber } from '@ciphera-net/ui' import * as Flags from 'country-flag-icons/react/3x2' // @ts-ignore import iso3166 from 'iso-3166-2' import WorldMap from './WorldMap' -import { Modal, GlobeIcon } from '@ciphera-net/ui' +import { Modal, GlobeIcon, Spinner } from '@ciphera-net/ui' import { SiTorproject } from 'react-icons/si' import { FaUserSecret, FaSatellite } from 'react-icons/fa' import { getCountries, getCities, getRegions } from '@/lib/api/stats' @@ -289,7 +289,7 @@ export default function Locations({ countries, cities, regions, geoDataLevel = '
{isLoadingFull ? (
-
+

Loading...

) : ( diff --git a/components/dashboard/TechSpecs.tsx b/components/dashboard/TechSpecs.tsx index c0f78ba..04f3274 100644 --- a/components/dashboard/TechSpecs.tsx +++ b/components/dashboard/TechSpecs.tsx @@ -1,10 +1,10 @@ 'use client' import { useState, useEffect } from 'react' -import { formatNumber } from '@/lib/utils/format' +import { formatNumber } from '@ciphera-net/ui' import { getBrowserIcon, getOSIcon, getDeviceIcon } from '@/lib/utils/icons' import { MdMonitor } from 'react-icons/md' -import { Modal, GridIcon } from '@ciphera-net/ui' +import { Modal, GridIcon, Spinner } from '@ciphera-net/ui' import { getBrowsers, getOS, getDevices, getScreenResolutions } from '@/lib/api/stats' interface TechSpecsProps { @@ -190,7 +190,7 @@ export default function TechSpecs({ browsers, os, devices, screenResolutions, co
{isLoadingFull ? (
-
+

Loading...

) : ( diff --git a/components/dashboard/TopPages.tsx b/components/dashboard/TopPages.tsx index 14d5de3..6976105 100644 --- a/components/dashboard/TopPages.tsx +++ b/components/dashboard/TopPages.tsx @@ -1,6 +1,6 @@ 'use client' -import { formatNumber } from '@/lib/utils/format' +import { formatNumber } from '@ciphera-net/ui' import { LayoutDashboardIcon } from '@ciphera-net/ui' interface TopPagesProps { diff --git a/components/dashboard/TopReferrers.tsx b/components/dashboard/TopReferrers.tsx index 5906876..4349118 100644 --- a/components/dashboard/TopReferrers.tsx +++ b/components/dashboard/TopReferrers.tsx @@ -1,9 +1,9 @@ 'use client' import { useState, useEffect } from 'react' -import { formatNumber } from '@/lib/utils/format' +import { formatNumber } from '@ciphera-net/ui' import { getReferrerDisplayName, getReferrerFavicon, getReferrerIcon, mergeReferrersByDisplayName } from '@/lib/utils/icons' -import { Modal, GlobeIcon } from '@ciphera-net/ui' +import { Modal, GlobeIcon, Spinner } from '@ciphera-net/ui' import { getTopReferrers, TopReferrer } from '@/lib/api/stats' interface TopReferrersProps { @@ -135,7 +135,7 @@ export default function TopReferrers({ referrers, collectReferrers = true, siteI
{isLoadingFull ? (
-
+

Loading...

) : ( diff --git a/components/notifications/NotificationCenter.tsx b/components/notifications/NotificationCenter.tsx index 1258e72..dad2ca4 100644 --- a/components/notifications/NotificationCenter.tsx +++ b/components/notifications/NotificationCenter.tsx @@ -7,7 +7,7 @@ import { useEffect, useState, useRef } from 'react' import Link from 'next/link' import { listNotifications, markNotificationRead, markAllNotificationsRead, type Notification } from '@/lib/api/notifications' -import { getAuthErrorMessage } from '@/lib/utils/authErrors' +import { getAuthErrorMessage } from '@ciphera-net/ui' import { formatTimeAgo, getTypeIcon } from '@/lib/utils/notifications' import { SettingsIcon } from '@ciphera-net/ui' diff --git a/components/settings/OrganizationSettings.tsx b/components/settings/OrganizationSettings.tsx index 8268940..9a56c0f 100644 --- a/components/settings/OrganizationSettings.tsx +++ b/components/settings/OrganizationSettings.tsx @@ -21,7 +21,7 @@ import { TRAFFIC_TIERS, PLAN_ID_SOLO, getTierIndexForLimit, getLimitForTierIndex import { getAuditLog, AuditLogEntry, GetAuditLogParams } from '@/lib/api/audit' import { getNotificationSettings, updateNotificationSettings } from '@/lib/api/notification-settings' import { toast } from '@ciphera-net/ui' -import { getAuthErrorMessage } from '@/lib/utils/authErrors' +import { getAuthErrorMessage } from '@ciphera-net/ui' import { motion, AnimatePresence } from 'framer-motion' import { AlertTriangleIcon, @@ -35,6 +35,7 @@ import { DownloadIcon, ExternalLinkIcon, LayoutDashboardIcon, + Spinner, } from '@ciphera-net/ui' // * Bell icon for notifications tab @@ -699,7 +700,7 @@ export default function OrganizationSettings() {
{isLoadingMembers ? (
-
+
) : members.length === 0 ? (
No members found.
@@ -780,7 +781,7 @@ export default function OrganizationSettings() { {isLoadingSubscription ? (
-
+
) : !subscription ? (
@@ -926,7 +927,7 @@ export default function OrganizationSettings() {
{isLoadingInvoices ? (
-
+
) : invoices.length === 0 ? (
No invoices found.
@@ -990,7 +991,7 @@ export default function OrganizationSettings() { {isLoadingNotificationSettings ? (
-
+
) : (
@@ -1117,7 +1118,7 @@ export default function OrganizationSettings() {
{isLoadingAudit ? (
-
+
) : (auditEntries ?? []).length === 0 ? (
No audit events found.
diff --git a/lib/api/client.ts b/lib/api/client.ts index a3fcac5..e012341 100644 --- a/lib/api/client.ts +++ b/lib/api/client.ts @@ -2,7 +2,7 @@ * HTTP client wrapper for API calls */ -import { authMessageFromStatus, AUTH_ERROR_MESSAGES } from '@/lib/utils/authErrors' +import { authMessageFromStatus, AUTH_ERROR_MESSAGES } from '@ciphera-net/ui' /** Request timeout in ms; network errors surface as user-facing "Network error, please try again." */ const FETCH_TIMEOUT_MS = 30_000 diff --git a/lib/integration-guides.tsx b/lib/integration-guides.tsx index 43dba84..5cfaf17 100644 --- a/lib/integration-guides.tsx +++ b/lib/integration-guides.tsx @@ -8,7 +8,7 @@ */ import { type ReactNode } from 'react' -import { CodeBlock } from '@/components/CodeBlock' +import { CodeBlock } from '@ciphera-net/ui' // * ─── Guide registry ───────────────────────────────────────────────────────── diff --git a/lib/utils/authErrors.ts b/lib/utils/authErrors.ts deleted file mode 100644 index ef138c9..0000000 --- a/lib/utils/authErrors.ts +++ /dev/null @@ -1,63 +0,0 @@ -/** - * Auth error message mapping for user-facing copy. - * Maps status codes and error types to safe, actionable messages (no sensitive details). - */ - -export const AUTH_ERROR_MESSAGES = { - /** Shown when session/token is expired; prompts re-login. */ - SESSION_EXPIRED: 'Session expired, please sign in again.', - /** Shown when credentials are invalid (e.g. wrong password, invalid token). */ - INVALID_CREDENTIALS: 'Invalid credentials', - /** Shown on network failure or timeout; prompts retry. */ - NETWORK: 'Network error, please try again.', - /** Generic fallback for server/unknown errors. */ - GENERIC: 'Something went wrong, please try again.', -} as const - -/** - * Returns the user-facing message for a given HTTP status from an API/auth response. - * Used when building ApiError messages and when mapping server-returned error types. - */ -export function authMessageFromStatus(status: number): string { - if (status === 401) return AUTH_ERROR_MESSAGES.SESSION_EXPIRED - if (status === 403) return AUTH_ERROR_MESSAGES.INVALID_CREDENTIALS - if (status >= 500) return AUTH_ERROR_MESSAGES.GENERIC - return AUTH_ERROR_MESSAGES.GENERIC -} - -/** Error type returned by auth server actions for mapping to user-facing copy. */ -export type AuthErrorType = 'network' | 'expired' | 'invalid' | 'server' - -/** - * Maps server-action error type (e.g. from exchangeAuthCode) to user-facing message. - * Used in auth callback so no sensitive details are shown. - */ -export function authMessageFromErrorType(type: AuthErrorType): string { - switch (type) { - case 'expired': - return AUTH_ERROR_MESSAGES.SESSION_EXPIRED - case 'invalid': - return AUTH_ERROR_MESSAGES.INVALID_CREDENTIALS - case 'network': - return AUTH_ERROR_MESSAGES.NETWORK - case 'server': - default: - return AUTH_ERROR_MESSAGES.GENERIC - } -} - -/** - * Maps an error (e.g. ApiError, network/abort) to a safe user-facing message. - * Use this when displaying API/auth errors in the UI so expired, invalid, and network - * cases show the correct copy without exposing sensitive details. - */ -export function getAuthErrorMessage(error: unknown): string { - if (!error) return AUTH_ERROR_MESSAGES.GENERIC - const err = error as { status?: number; name?: string; message?: string } - if (typeof err.status === 'number') return authMessageFromStatus(err.status) - if (err.name === 'AbortError') return AUTH_ERROR_MESSAGES.NETWORK - if (err instanceof Error && (err.name === 'TypeError' || /fetch|network|failed to fetch/i.test(err.message || ''))) { - return AUTH_ERROR_MESSAGES.NETWORK - } - return AUTH_ERROR_MESSAGES.GENERIC -} diff --git a/lib/utils/format.ts b/lib/utils/format.ts deleted file mode 100644 index 485efa6..0000000 --- a/lib/utils/format.ts +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Format numbers with commas - */ -export function formatNumber(num: number): string { - return new Intl.NumberFormat('en-US').format(num) -} - -/** - * Format date to YYYY-MM-DD - */ -export function formatDate(date: Date): string { - return date.toISOString().split('T')[0] -} - -/** - * Get date range for last N days - */ -export function getDateRange(days: number): { start: string; end: string } { - const end = new Date() - const start = new Date() - start.setDate(start.getDate() - days) - return { - start: formatDate(start), - end: formatDate(end), - } -} - -/** - * Format "updated X ago" for polling indicators (e.g. "Just now", "12 seconds ago") - */ -export function formatUpdatedAgo(timestamp: number): string { - const diff = Math.floor((Date.now() - timestamp) / 1000) - if (diff < 5) return 'Just now' - if (diff < 60) return `${diff} seconds ago` - if (diff < 120) return '1 minute ago' - const minutes = Math.floor(diff / 60) - return `${minutes} minutes ago` -} - -/** - * Format relative time (e.g., "2 hours ago") - */ -export function formatRelativeTime(date: string | Date): string { - const d = typeof date === 'string' ? new Date(date) : date - const now = new Date() - const diff = now.getTime() - d.getTime() - const seconds = Math.floor(diff / 1000) - const minutes = Math.floor(seconds / 60) - const hours = Math.floor(minutes / 60) - const days = Math.floor(hours / 24) - - if (days > 0) return `${days} day${days > 1 ? 's' : ''} ago` - if (hours > 0) return `${hours} hour${hours > 1 ? 's' : ''} ago` - if (minutes > 0) return `${minutes} minute${minutes > 1 ? 's' : ''} ago` - return 'Just now' -} -/** - * Format duration in seconds to "1m 30s" or "30s" - */ -export function formatDuration(seconds: number): string { - if (!seconds) return '0s' - - const m = Math.floor(seconds / 60) - const s = Math.floor(seconds % 60) - - if (m > 0) { - return `${m}m ${s}s` - } - return `${s}s` -} diff --git a/package-lock.json b/package-lock.json index 99267af..c1f34dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "name": "pulse-frontend", "version": "0.6.0-alpha", "dependencies": { - "@ciphera-net/ui": "^0.0.56", + "@ciphera-net/ui": "^0.0.57", "@ducanh2912/next-pwa": "^10.2.9", "@radix-ui/react-icons": "^1.3.0", "axios": "^1.13.2", @@ -1539,9 +1539,9 @@ } }, "node_modules/@ciphera-net/ui": { - "version": "0.0.56", - "resolved": "https://npm.pkg.github.com/download/@ciphera-net/ui/0.0.56/dfa7f3a01be81773c16c68868d0517a67e5c5860", - "integrity": "sha512-cOdq5Yu6riKQkJe6O1GNpv3k044qSr/K465uPtsAQL604gc9rC6Ooyom+jabt+N8yM3qoXL5KDaNiUBjKdTP0g==", + "version": "0.0.57", + "resolved": "https://npm.pkg.github.com/download/@ciphera-net/ui/0.0.57/1839d6ea6184b8aefa921ceeaa1d1d50d532e6a8", + "integrity": "sha512-sgdBajwBgmZnqnZ/kJ1PYpb4XR2j/yPXw1xHyMpNaLa/wLYXqylJ1ffQ3aRE7BB37IkGgDO+fzeQVjYnJvHSBA==", "dependencies": { "@radix-ui/react-icons": "^1.3.0", "clsx": "^2.1.0", diff --git a/package.json b/package.json index 187f321..04fe563 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "type-check": "tsc --noEmit" }, "dependencies": { - "@ciphera-net/ui": "^0.0.56", + "@ciphera-net/ui": "^0.0.57", "@ducanh2912/next-pwa": "^10.2.9", "@radix-ui/react-icons": "^1.3.0", "axios": "^1.13.2",