0 ? 'bg-red-50' : undefined}
+ className={row.errors.length > 0 ? 'bg-destructive/5 dark:bg-destructive/10' : undefined}
>
|
{row.index}
@@ -361,7 +361,7 @@ export default function BatchCreatePage() {
|
{row.errors.length === 0 ? (
-
+
Valid
) : (
diff --git a/app/app/create/loading.tsx b/app/app/create/loading.tsx
new file mode 100644
index 0000000..86c991d
--- /dev/null
+++ b/app/app/create/loading.tsx
@@ -0,0 +1,30 @@
+'use client'
+
+export default function CreateStreamLoading() {
+ return (
+
+ {/* Header skeleton */}
+
+
+ {/* Form section skeleton */}
+
+ {/* Form fields skeleton */}
+ {Array.from({ length: 6 }).map((_, i) => (
+
+ ))}
+
+ {/* Button skeleton */}
+
+
+
+ )
+}
diff --git a/app/app/loading.tsx b/app/app/loading.tsx
new file mode 100644
index 0000000..983b7e0
--- /dev/null
+++ b/app/app/loading.tsx
@@ -0,0 +1,26 @@
+'use client'
+
+import { DashboardStatsSkeleton } from '@/components/streams/dashboard-stats'
+import { StreamCardSkeleton } from '@/components/streams/stream-card'
+
+export default function DashboardLoading() {
+ return (
+
+ {/* Header skeleton */}
+
+
+ {/* Stats skeleton */}
+
+
+ {/* Stream list skeleton */}
+
+ {Array.from({ length: 3 }).map((_, i) => (
+
+ ))}
+
+
+ )
+}
diff --git a/app/app/settings/loading.tsx b/app/app/settings/loading.tsx
new file mode 100644
index 0000000..d2cae16
--- /dev/null
+++ b/app/app/settings/loading.tsx
@@ -0,0 +1,28 @@
+'use client'
+
+export default function SettingsLoading() {
+ return (
+
+ {/* Header skeleton */}
+
+
+ {/* Settings sections skeleton */}
+ {Array.from({ length: 3 }).map((_, i) => (
+
+
+
+ {Array.from({ length: 2 }).map((_, j) => (
+
+ ))}
+
+
+ ))}
+
+ )
+}
diff --git a/app/app/stream/[id]/loading.tsx b/app/app/stream/[id]/loading.tsx
new file mode 100644
index 0000000..24f5690
--- /dev/null
+++ b/app/app/stream/[id]/loading.tsx
@@ -0,0 +1,39 @@
+'use client'
+
+export default function StreamDetailLoading() {
+ return (
+
+ {/* Back button skeleton */}
+
+
+ {/* Header section skeleton */}
+
+
+
+ {Array.from({ length: 4 }).map((_, i) => (
+
+ ))}
+
+
+
+ {/* Timeline/Activity section skeleton */}
+
+
+
+ {Array.from({ length: 3 }).map((_, i) => (
+
+ ))}
+
+
+
+ )
+}
diff --git a/app/app/streams/loading.tsx b/app/app/streams/loading.tsx
new file mode 100644
index 0000000..6121556
--- /dev/null
+++ b/app/app/streams/loading.tsx
@@ -0,0 +1,22 @@
+'use client'
+
+import { StreamCardSkeleton } from '@/components/streams/stream-card'
+
+export default function StreamsLoading() {
+ return (
+
+ {/* Header skeleton */}
+
+
+ {/* Stream list skeleton */}
+
+ {Array.from({ length: 5 }).map((_, i) => (
+
+ ))}
+
+
+ )
+}
diff --git a/components/streams/dashboard-stats.tsx b/components/streams/dashboard-stats.tsx
index 7d01be0..6b0413e 100644
--- a/components/streams/dashboard-stats.tsx
+++ b/components/streams/dashboard-stats.tsx
@@ -99,6 +99,7 @@ export function DashboardStats({ sent, received }: DashboardStatsProps) {
amount={topWithdrawable.amount}
token={topWithdrawable.token}
maxFractionDigits={2}
+ truncate
/>
) : (
—
diff --git a/components/ui/token-amount.tsx b/components/ui/token-amount.tsx
index ae14a2c..ea60b98 100644
--- a/components/ui/token-amount.tsx
+++ b/components/ui/token-amount.tsx
@@ -11,6 +11,8 @@ interface TokenAmountProps {
showSymbol?: boolean
/** Display amount in compact notation (e.g., "1.2K"). @default false */
compact?: boolean
+ /** Truncate the display with ellipsis. @default false */
+ truncate?: boolean
}
/** Formats a raw bigint token amount with correct decimals + symbol. */
@@ -22,13 +24,19 @@ export function TokenAmount({
maxFractionDigits = 4,
showSymbol = true,
compact = false,
+ truncate = false,
}: TokenAmountProps) {
const formattedAmount = compact
? formatCompactAmount(amount, token.decimals)
: formatTokenAmount(amount, token.decimals, maxFractionDigits)
+ const fullValue = `${formattedAmount}${showSymbol ? ` ${token.symbol}` : ''}`
+
return (
-
+
{formattedAmount}
{showSymbol && (
diff --git a/components/webhooks/webhook-settings.tsx b/components/webhooks/webhook-settings.tsx
index 11ec5b1..0a6717f 100644
--- a/components/webhooks/webhook-settings.tsx
+++ b/components/webhooks/webhook-settings.tsx
@@ -1,7 +1,7 @@
'use client'
import { useState } from 'react'
-import { Plus, Trash2, ToggleLeft, ToggleRight, Send, CheckCircle2, XCircle } from 'lucide-react'
+import { Plus, Trash2, ToggleLeft, ToggleRight, Send, CheckCircle2, XCircle, Webhook } from 'lucide-react'
import { toast } from 'sonner'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
@@ -74,7 +74,7 @@ export function WebhookSettings() {
return (
{/* Add webhook */}
-
+
Register a webhook
@@ -124,11 +124,28 @@ export function WebhookSettings() {
{/* Registered webhooks */}
- {webhooks.length > 0 && (
-
- Registered webhooks
- {webhooks.map((hook) => (
-
+
+ Registered webhooks
+ {webhooks.length === 0 ? (
+
+
+
+
+ No webhooks registered yet
+
+ Register a webhook above to start receiving real-time event notifications for your streams.
+
+
+
+ ) : (
+
+ {webhooks.map((hook) => (
+
{hook.url}
@@ -173,10 +190,11 @@ export function WebhookSettings() {
-
- ))}
-
- )}
+
+ ))}
+
+ )}
+
{/* Delivery history */}
{history.length > 0 && (
|