Skip to content

Commit dd1df8a

Browse files
committed
feat: sync Livecounter with paused state and update dashboard visuals
1 parent a03e7a3 commit dd1df8a

2 files changed

Lines changed: 57 additions & 8 deletions

File tree

frontend/src/components/IncomingStreams.tsx

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type { Stream } from '@/lib/dashboard';
55
import { useStreamingAmount } from '@/hooks/useStreamingAmount';
66
import toast from 'react-hot-toast';
77
import { fromStroops } from '@/utils/amount';
8+
import LiveCounter from '@/components/Livecounter';
89

910
interface IncomingStreamsProps {
1011
streams: Stream[];
@@ -26,17 +27,26 @@ const ClaimableAmount: React.FC<{ stream: Stream }> = ({ stream }) => {
2627
isActive: stream.status === 'Active' && stream.isActive,
2728
});
2829

29-
const isPaused = stream.status === 'Paused';
30+
const isPaused = stream.status === 'Paused' || (stream as any).isPaused;
3031
const liveRate = stream.status === 'Active' && stream.ratePerSecond > 0;
3132

3233
return (
3334
<div className="flex flex-col">
3435
<span className={`font-bold tabular-nums ${liveRate ? 'text-emerald-600 dark:text-emerald-300' : isPaused ? 'text-gray-400 dark:text-gray-500' : 'text-gray-900 dark:text-gray-100'}`}>
35-
{formatTokenAmount(claimable)} {stream.token}
36+
{isPaused ? (
37+
<LiveCounter
38+
initial={claimable}
39+
isPaused={isPaused}
40+
pausedAt={(stream as any).pausedAt}
41+
label="Claimable"
42+
/>
43+
) : (
44+
`${formatTokenAmount(claimable)} ${stream.token}`
45+
)}
3646
</span>
3747
<span className={`text-xs tabular-nums ${liveRate ? 'text-emerald-500 dark:text-emerald-400' : isPaused ? 'text-gray-400 dark:text-gray-500' : 'text-gray-400 dark:text-gray-500'}`}>
3848
{isPaused
39-
? 'Stream paused'
49+
? ''
4050
: liveRate
4151
? `+${formatTokenAmount(stream.ratePerSecond)} ${stream.token}/sec`
4252
: 'Stream inactive'}
@@ -147,11 +157,11 @@ const IncomingStreams: React.FC<IncomingStreamsProps> = ({
147157
</thead>
148158
<tbody className="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
149159
{filteredStreams.map((stream) => {
150-
const isPaused = stream.status === 'Paused';
160+
const isPaused = stream.status === 'Paused' || (stream as any).isPaused;
151161
return (
152162
<tr
153163
key={stream.id}
154-
className={`hover:bg-gray-50 dark:hover:bg-gray-700/50 transition-colors ${isPaused ? 'bg-gray-50/50 dark:bg-gray-800/50 opacity-75' : ''}`}
164+
className={`hover:bg-gray-50 dark:hover:bg-gray-700/50 transition-colors ${isPaused ? 'bg-gray-50/50 dark:bg-gray-800/50 grayscale opacity-75' : ''}`}
155165
>
156166
<td className="px-6 py-4 whitespace-nowrap">
157167
<div className={`text-sm font-mono ${isPaused ? 'text-gray-500 dark:text-gray-400' : 'text-gray-900 dark:text-gray-100'}`}>

frontend/src/components/dashboard/dashboard-view.tsx

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ import { TopUpModal } from "../stream-creation/TopUpModal";
4949
import { CancelConfirmModal } from "../stream-creation/CancelConfirmModal";
5050
import { StreamDetailsModal } from "./StreamDetailsModal";
5151
import { Button } from "../ui/Button";
52+
import LiveCounter from "@/components/Livecounter";
5253

5354
// ─── Types ────────────────────────────────────────────────────────────────────
5455

@@ -475,6 +476,40 @@ export function DashboardView({ session, onDisconnect }: DashboardViewProps) {
475476
const [snapshot, setSnapshot] = React.useState<DashboardSnapshot | null>(null);
476477
const [isSnapshotLoading, setIsSnapshotLoading] = React.useState(true);
477478
const [snapshotError, setSnapshotError] = React.useState<string | null>(null);
479+
const [pausedStreamsData, setPausedStreamsData] = React.useState<Stream[]>([]);
480+
const [isPausedLoading, setIsPausedLoading] = React.useState(false);
481+
482+
React.useEffect(() => {
483+
if (activeTab === "paused") {
484+
setIsPausedLoading(true);
485+
const baseUrl = process.env.NEXT_PUBLIC_API_URL || "http://localhost:3001";
486+
const endpoints = [
487+
`${baseUrl}/v1/streams?status=paused&sender=${session.publicKey}`,
488+
`${baseUrl}/v1/streams?status=paused&recipient=${session.publicKey}`
489+
];
490+
Promise.all(endpoints.map(ep => fetch(ep).then(res => res.ok ? res.json() : [])))
491+
.then(([outPaused, inPaused]) => {
492+
const allPaused = [...outPaused, ...inPaused].map((s: any) => ({
493+
id: s.streamId?.toString() || s.id,
494+
recipient: s.recipient || s.sender,
495+
amount: s.depositedAmount ? parseFloat(s.depositedAmount)/1e7 : s.amount,
496+
token: "TOKEN",
497+
status: "Paused",
498+
deposited: s.depositedAmount ? parseFloat(s.depositedAmount)/1e7 : s.deposited,
499+
withdrawn: s.withdrawnAmount ? parseFloat(s.withdrawnAmount)/1e7 : s.withdrawn,
500+
date: s.startTime ? new Date(s.startTime * 1000).toISOString().split("T")[0] : s.date,
501+
ratePerSecond: s.ratePerSecond ? parseFloat(s.ratePerSecond)/1e7 : s.ratePerSecond,
502+
lastUpdateTime: s.lastUpdateTime,
503+
isActive: false,
504+
isPaused: true,
505+
pausedAt: s.pausedAt
506+
}));
507+
setPausedStreamsData(allPaused);
508+
})
509+
.catch(console.error)
510+
.finally(() => setIsPausedLoading(false));
511+
}
512+
}, [activeTab, session.publicKey]);
478513

479514
const safeLoadTemplates = (): StreamTemplate[] => {
480515
try {
@@ -804,10 +839,13 @@ export function DashboardView({ session, onDisconnect }: DashboardViewProps) {
804839

805840
// ── Paused ────────────────────────────────────────────────────────────
806841
if (activeTab === "paused") {
807-
const pausedStreams = [
842+
const pausedStreams = pausedStreamsData.length > 0 ? pausedStreamsData : [
808843
...snapshot!.outgoingStreams.filter((s) => s.status === "Paused"),
809844
...snapshot!.incomingStreams.filter((s) => s.status === "Paused"),
810845
];
846+
if (isPausedLoading) {
847+
return <div className="mt-8 text-center text-slate-400">Loading paused streams...</div>;
848+
}
811849
if (pausedStreams.length === 0) {
812850
return (
813851
<div className="glass-card p-12 rounded-3xl border-slate-800 text-center text-slate-400 mt-8">
@@ -828,14 +866,15 @@ export function DashboardView({ session, onDisconnect }: DashboardViewProps) {
828866
</thead>
829867
<tbody>
830868
{pausedStreams.map((s) => (
831-
<tr key={s.id}>
869+
<tr key={s.id} className="grayscale opacity-75">
832870
<td>#{s.id}</td>
833871
<td className="font-mono text-xs">{s.recipient}</td>
834872
<td>{s.token}</td>
835-
<td>
873+
<td className="flex items-center gap-2">
836874
<span className="px-2 py-1 rounded-full bg-yellow-500/10 text-yellow-500 text-xs font-bold">
837875
Paused
838876
</span>
877+
<LiveCounter initial={0} isPaused={(s as any).isPaused || true} pausedAt={(s as any).pausedAt} />
839878
</td>
840879
</tr>
841880
))}

0 commit comments

Comments
 (0)