11import { useEffect , useState , lazy , Suspense , useTransition } from "react" ;
22
3- import type { HTConference , HTEvent , HTTagGroup } from "@/types/db" ;
3+ import type { HTConference } from "@/types/db" ;
44import type { GroupedSchedule } from "@/types/ht" ;
55
66import { ConferenceHeader } from "@/components/ConferenceHeader" ;
77import ErrorPage from "@/components/ErrorPage" ;
88import LoadingPage from "@/components/LoadingPage" ;
9- import { getConferenceByCode , getEvents , getTags } from "@/lib/db" ;
9+ import { getCachedConferenceSchedule , getConferenceSchedule } from "@/lib/db" ;
1010import { useNormalizedParams } from "@/lib/utils/params" ;
11- import { buildScheduleBucketsByDay } from "@/lib/utils/schedule" ;
1211
1312const EventsList = lazy ( ( ) => import ( "./EventsList" ) ) ;
1413let eventsListPreload : Promise < unknown > | null = null ;
@@ -21,10 +20,16 @@ function preloadEventsList() {
2120
2221export function Schedule ( ) {
2322 const { confCode } = useNormalizedParams ( ) ;
23+ const [ initialSchedule ] = useState ( ( ) =>
24+ confCode ? getCachedConferenceSchedule ( confCode ) : null ,
25+ ) ;
2426
25- const [ grouped , setGrouped ] = useState < GroupedSchedule | null > ( null ) ;
26- const [ conference , setConference ] = useState < HTConference | null > ( null ) ;
27+ const [ grouped , setGrouped ] = useState < GroupedSchedule | null > ( initialSchedule ?. grouped ?? null ) ;
28+ const [ conference , setConference ] = useState < HTConference | null > (
29+ initialSchedule ?. conference ?? null ,
30+ ) ;
2731 const [ error , setError ] = useState < string | null > ( null ) ;
32+ const [ loading , setLoading ] = useState ( ! initialSchedule ) ;
2833 const [ isPending , startTransition ] = useTransition ( ) ;
2934
3035 useEffect ( ( ) => {
@@ -34,52 +39,60 @@ export function Schedule() {
3439 useEffect ( ( ) => {
3540 const id = window . setTimeout ( ( ) => {
3641 if ( error ) document . title = "Error · Schedule | Hacker Tracker" ;
37- else if ( isPending && ! grouped ) document . title = "Loading schedule… | Hacker Tracker" ;
42+ else if ( loading && ! grouped ) document . title = "Loading schedule… | Hacker Tracker" ;
3843 else if ( conference ) document . title = `Schedule · ${ conference . name } | Hacker Tracker` ;
3944 else document . title = "Schedule | Hacker Tracker" ;
4045 } , 150 ) ; // small debounce
4146 return ( ) => clearTimeout ( id ) ;
42- } , [ conference , grouped , error , isPending ] ) ;
47+ } , [ conference , grouped , error , loading ] ) ;
4348
4449 useEffect ( ( ) => {
4550 let cancelled = false ;
4651
4752 async function load ( ) {
48- if ( ! confCode ) return ;
53+ if ( ! confCode ) {
54+ setError ( "Missing required URL parameters." ) ;
55+ setLoading ( false ) ;
56+ return ;
57+ }
4958 setError ( null ) ;
5059
60+ const cachedSchedule = getCachedConferenceSchedule ( confCode ) ;
61+ if ( cachedSchedule ) {
62+ setConference ( cachedSchedule . conference ) ;
63+ setGrouped ( cachedSchedule . grouped ) ;
64+ setLoading ( false ) ;
65+ } else {
66+ setConference ( null ) ;
67+ setGrouped ( null ) ;
68+ setLoading ( true ) ;
69+ }
70+
5171 try {
52- const conf = await getConferenceByCode ( confCode ) ;
72+ const schedule = await getConferenceSchedule ( confCode ) ;
5373 if ( cancelled ) return ;
5474
55- if ( ! conf ) {
75+ if ( ! schedule ) {
5676 setError ( "Conference not found." ) ;
5777 return ;
5878 }
5979
60- const preload = preloadEventsList ( ) ;
61-
62- const [ evs , tags ] = await Promise . all ( [ getEvents ( confCode ) , getTags ( confCode ) , preload ] ) ;
80+ await preloadEventsList ( ) ;
6381 if ( cancelled ) return ;
6482
65- const tz = conf . timezone || "UTC" ;
66- const groupedSchedule = buildScheduleBucketsByDay (
67- evs as HTEvent [ ] ,
68- tags as HTTagGroup [ ] ,
69- tz ,
70- ) ;
71-
7283 startTransition ( ( ) => {
7384 if ( ! cancelled ) {
74- setConference ( conf ) ;
75- setGrouped ( groupedSchedule ) ;
85+ setConference ( schedule . conference ) ;
86+ setGrouped ( schedule . grouped ) ;
7687 }
7788 } ) ;
7889 } catch ( e ) {
7990 if ( ! cancelled ) {
8091 const msg = e instanceof Error ? e . message : "Failed to load schedule" ;
8192 setError ( msg ) ;
8293 }
94+ } finally {
95+ if ( ! cancelled ) setLoading ( false ) ;
8396 }
8497 }
8598
@@ -89,7 +102,7 @@ export function Schedule() {
89102 } ;
90103 } , [ confCode ] ) ;
91104
92- if ( ! grouped && ! conference && ! error && isPending ) {
105+ if ( ! grouped && ! conference && ! error && loading ) {
93106 return < LoadingPage message = "Loading schedule..." /> ;
94107 }
95108 if ( error ) return < ErrorPage msg = { error } /> ;
@@ -99,7 +112,7 @@ export function Schedule() {
99112 { conference && < ConferenceHeader conference = { conference } /> }
100113
101114 < main className = "relative flex-1" >
102- { isPending && (
115+ { ( loading || isPending ) && grouped && (
103116 < div className = "bg-background/40 pointer-events-none absolute inset-0 backdrop-blur-[1px] transition-opacity" />
104117 ) }
105118
0 commit comments