- Simplified useRealtimeSync to use router.refresh() polling - Created RealtimeUpdater component for easy integration - Added real-time updates to home page (3s polling) - Fixed DeleteItemButton to properly reset state on error - Updates now refresh every 3 seconds and on window focus - Changes from other users/browsers will appear quickly
70 lines
2.3 KiB
TypeScript
70 lines
2.3 KiB
TypeScript
import { getLists } from '@/lib/actions'
|
|
import ListCard from '@/components/ListCard'
|
|
import NewListButton from '@/components/NewListButton'
|
|
import GlobalSearch from '@/components/GlobalSearch'
|
|
import EmptyState from '@/components/EmptyState'
|
|
import RealtimeUpdater from '@/components/RealtimeUpdater'
|
|
import Link from 'next/link'
|
|
import { getServerSession } from 'next-auth'
|
|
import { authOptions } from '@/pages/api/auth/[...nextauth]'
|
|
import { redirect } from 'next/navigation'
|
|
|
|
export const dynamic = 'force-dynamic'
|
|
|
|
export default async function Home() {
|
|
const session = await getServerSession(authOptions)
|
|
|
|
if (!session?.user) {
|
|
redirect('/auth/login')
|
|
}
|
|
|
|
const lists = await getLists()
|
|
|
|
return (
|
|
<main className="container mx-auto px-4 sm:px-6 py-6 sm:py-8 max-w-7xl">
|
|
<RealtimeUpdater pollInterval={3000} />
|
|
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4 mb-6 sm:mb-8">
|
|
<h1 className="text-2xl sm:text-3xl lg:text-4xl font-bold text-gray-900">Ultimate Lists</h1>
|
|
<div className="flex items-center gap-3">
|
|
{session?.user && (
|
|
<>
|
|
<Link
|
|
href="/invitations"
|
|
className="px-3 py-2 text-sm text-gray-700 hover:text-gray-900 hover:bg-gray-100 rounded-lg transition-colors"
|
|
>
|
|
Invitations
|
|
</Link>
|
|
<Link
|
|
href="/profile"
|
|
className="px-3 py-2 text-sm text-gray-700 hover:text-gray-900 hover:bg-gray-100 rounded-lg transition-colors"
|
|
>
|
|
Profile
|
|
</Link>
|
|
</>
|
|
)}
|
|
<NewListButton />
|
|
</div>
|
|
</div>
|
|
|
|
{/* Global Search */}
|
|
<div className="mb-6 sm:mb-8">
|
|
<GlobalSearch />
|
|
</div>
|
|
|
|
{lists.length === 0 ? (
|
|
<EmptyState
|
|
icon="list"
|
|
title="No lists yet"
|
|
description="Create your first list to start organizing your tasks"
|
|
action={<NewListButton />}
|
|
/>
|
|
) : (
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4 sm:gap-6 animate-fade-in">
|
|
{lists.map((list) => (
|
|
<ListCard key={list.id} list={list} />
|
|
))}
|
|
</div>
|
|
)}
|
|
</main>
|
|
)
|
|
} |