feat: add AutoRefresh component for automatic data refreshing on pages
Build Images and Deploy / Update-PROD-Stack (push) Failing after 33s
Build Images and Deploy / Update-PROD-Stack (push) Failing after 33s
This commit is contained in:
@@ -6,6 +6,7 @@ import { formatCurrency, formatPnl, pnlColor } from '@/lib/utils'
|
|||||||
import { formatDistanceToNow } from 'date-fns'
|
import { formatDistanceToNow } from 'date-fns'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { Building2, TrendingUp, TrendingDown } from 'lucide-react'
|
import { Building2, TrendingUp, TrendingDown } from 'lucide-react'
|
||||||
|
import { AutoRefresh } from '@/components/AutoRefresh'
|
||||||
import { calcFundNav } from '@/lib/pricing'
|
import { calcFundNav } from '@/lib/pricing'
|
||||||
import InvestPanel from './InvestPanel'
|
import InvestPanel from './InvestPanel'
|
||||||
import { PriceChart } from '@/components/PriceChart'
|
import { PriceChart } from '@/components/PriceChart'
|
||||||
@@ -88,6 +89,7 @@ export default async function FundPage({ params }: { params: { slug: string } })
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="max-w-4xl mx-auto space-y-8">
|
<div className="max-w-4xl mx-auto space-y-8">
|
||||||
|
<AutoRefresh intervalMs={30_000} />
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4">
|
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4">
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { ResearchPanel } from './ResearchPanel'
|
|||||||
import { Hash, Clock, Link as LinkIcon, AlertTriangle } from 'lucide-react'
|
import { Hash, Clock, Link as LinkIcon, AlertTriangle } from 'lucide-react'
|
||||||
import { formatDistanceToNow } from 'date-fns'
|
import { formatDistanceToNow } from 'date-fns'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
|
import { AutoRefresh } from '@/components/AutoRefresh'
|
||||||
|
|
||||||
const ZOMBIE_ZERO_COUNT = parseInt(process.env.ZOMBIE_ZERO_COUNT ?? '1000', 10)
|
const ZOMBIE_ZERO_COUNT = parseInt(process.env.ZOMBIE_ZERO_COUNT ?? '1000', 10)
|
||||||
const PRICE_UPDATE_INTERVAL_MINUTES = parseInt(process.env.PRICE_UPDATE_INTERVAL_MINUTES ?? '60', 10)
|
const PRICE_UPDATE_INTERVAL_MINUTES = parseInt(process.env.PRICE_UPDATE_INTERVAL_MINUTES ?? '60', 10)
|
||||||
@@ -126,7 +127,8 @@ export default async function HashtagPage({ params, searchParams }: Props) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-8">
|
<div className="space-y-8">
|
||||||
{/* Header */}
|
<AutoRefresh intervalMs={30_000} />
|
||||||
|
{/* Header */}}
|
||||||
<div className="flex flex-col sm:flex-row sm:items-end justify-between gap-4">
|
<div className="flex flex-col sm:flex-row sm:items-end justify-between gap-4">
|
||||||
<div>
|
<div>
|
||||||
<h1 className="text-3xl font-bold">#{hashtag.displayTag}</h1>
|
<h1 className="text-3xl font-bold">#{hashtag.displayTag}</h1>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { formatCurrency } from '@/lib/utils'
|
|||||||
import { calcFundNav } from '@/lib/pricing'
|
import { calcFundNav } from '@/lib/pricing'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { Trophy, TrendingUp, TrendingDown, Building2, Users } from 'lucide-react'
|
import { Trophy, TrendingUp, TrendingDown, Building2, Users } from 'lucide-react'
|
||||||
|
import { AutoRefresh } from '@/components/AutoRefresh'
|
||||||
|
|
||||||
export const dynamic = 'force-dynamic'
|
export const dynamic = 'force-dynamic'
|
||||||
|
|
||||||
@@ -119,6 +120,7 @@ export default async function LeaderboardPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="max-w-3xl mx-auto space-y-6">
|
<div className="max-w-3xl mx-auto space-y-6">
|
||||||
|
<AutoRefresh intervalMs={30_000} />
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<Trophy className="h-7 w-7 text-amber-400" />
|
<Trophy className="h-7 w-7 text-amber-400" />
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
+2
-1
@@ -6,6 +6,7 @@ import { TrendingUp, Users, Hash, AlertTriangle } from 'lucide-react'
|
|||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { formatPnl, pnlColor } from '@/lib/utils'
|
import { formatPnl, pnlColor } from '@/lib/utils'
|
||||||
import { formatDistanceToNow } from 'date-fns'
|
import { formatDistanceToNow } from 'date-fns'
|
||||||
|
import { AutoRefresh } from '@/components/AutoRefresh'
|
||||||
|
|
||||||
const ZOMBIE_ZERO_COUNT = parseInt(process.env.ZOMBIE_ZERO_COUNT ?? '1000', 10)
|
const ZOMBIE_ZERO_COUNT = parseInt(process.env.ZOMBIE_ZERO_COUNT ?? '1000', 10)
|
||||||
const PRICE_UPDATE_INTERVAL_MINUTES = parseInt(process.env.PRICE_UPDATE_INTERVAL_MINUTES ?? '60', 10)
|
const PRICE_UPDATE_INTERVAL_MINUTES = parseInt(process.env.PRICE_UPDATE_INTERVAL_MINUTES ?? '60', 10)
|
||||||
@@ -93,7 +94,7 @@ export default async function HomePage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-10">
|
<div className="space-y-10">
|
||||||
{/* Hero */}
|
<AutoRefresh intervalMs={30_000} />}
|
||||||
<div className="text-center py-8">
|
<div className="text-center py-8">
|
||||||
<h1 className="text-4xl font-bold tracking-tight mb-3">
|
<h1 className="text-4xl font-bold tracking-tight mb-3">
|
||||||
The{' '}
|
The{' '}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { redirect } from 'next/navigation'
|
|||||||
import { formatCurrency, formatNumber, formatPnl, pnlColor } from '@/lib/utils'
|
import { formatCurrency, formatNumber, formatPnl, pnlColor } from '@/lib/utils'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { Coins, ChevronUp, ChevronDown, ChevronsUpDown } from 'lucide-react'
|
import { Coins, ChevronUp, ChevronDown, ChevronsUpDown } from 'lucide-react'
|
||||||
|
import { AutoRefresh } from '@/components/AutoRefresh'
|
||||||
|
|
||||||
export const dynamic = 'force-dynamic'
|
export const dynamic = 'force-dynamic'
|
||||||
|
|
||||||
@@ -130,6 +131,7 @@ export default async function PositionsPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="max-w-4xl mx-auto space-y-6">
|
<div className="max-w-4xl mx-auto space-y-6">
|
||||||
|
<AutoRefresh intervalMs={30_000} />
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<Coins className="h-6 w-6 text-indigo-400" />
|
<Coins className="h-6 w-6 text-indigo-400" />
|
||||||
<h1 className="text-2xl font-bold">Open Positions</h1>
|
<h1 className="text-2xl font-bold">Open Positions</h1>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { prisma } from '@/lib/prisma'
|
|||||||
import { formatCurrency, pnlColor } from '@/lib/utils'
|
import { formatCurrency, pnlColor } from '@/lib/utils'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { ArrowUp, ArrowDown, ArrowUpDown, BarChart2, Building2 } from 'lucide-react'
|
import { ArrowUp, ArrowDown, ArrowUpDown, BarChart2, Building2 } from 'lucide-react'
|
||||||
|
import { AutoRefresh } from '@/components/AutoRefresh'
|
||||||
import { formatDistanceToNow } from 'date-fns'
|
import { formatDistanceToNow } from 'date-fns'
|
||||||
import { calcFundNav } from '@/lib/pricing'
|
import { calcFundNav } from '@/lib/pricing'
|
||||||
|
|
||||||
@@ -197,7 +198,8 @@ export default async function StocksPage({ searchParams }: PageProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="max-w-5xl mx-auto space-y-6">
|
<div className="max-w-5xl mx-auto space-y-6">
|
||||||
{/* Header */}
|
<AutoRefresh intervalMs={30_000} />
|
||||||
|
{/* Header */}}
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<BarChart2 className="h-6 w-6 text-indigo-400" />
|
<BarChart2 className="h-6 w-6 text-indigo-400" />
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useRouter } from 'next/navigation'
|
||||||
|
import { useEffect } from 'react'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Silently refreshes all server-component data on the current page by calling
|
||||||
|
* router.refresh() on an interval and whenever the tab regains focus.
|
||||||
|
*
|
||||||
|
* Drop this anywhere inside a server-component page — it renders nothing.
|
||||||
|
*/
|
||||||
|
export function AutoRefresh({ intervalMs = 30_000 }: { intervalMs?: number }) {
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const id = setInterval(() => router.refresh(), intervalMs)
|
||||||
|
|
||||||
|
const onFocus = () => router.refresh()
|
||||||
|
document.addEventListener('visibilitychange', onFocus)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
clearInterval(id)
|
||||||
|
document.removeEventListener('visibilitychange', onFocus)
|
||||||
|
}
|
||||||
|
}, [router, intervalMs])
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user