File size: 2,685 Bytes
ca28016
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
'use client';

import React, { useState, useEffect, createContext, useContext } from 'react';

interface ClientTimeContextType {
  mounted: boolean;
  currentTime: Date;
}

const ClientTimeContext = createContext<ClientTimeContextType>({
  mounted: false,
  currentTime: new Date(0)
});

export function ClientTimeProvider({ children }: { children: React.ReactNode }) {
  const [mounted, setMounted] = useState(false);
  const [currentTime, setCurrentTime] = useState(new Date(0));

  useEffect(() => {
    setMounted(true);
    // Don't update time immediately to prevent hydration mismatch
    // Wait a bit before starting the interval
    const timeout = setTimeout(() => {
      setCurrentTime(new Date());
      
      // Update time every second to keep it fresh
      const interval = setInterval(() => {
        setCurrentTime(new Date());
      }, 1000);

      return () => clearInterval(interval);
    }, 100); // Small delay to ensure hydration is complete

    return () => clearTimeout(timeout);
  }, []);

  return (
    <ClientTimeContext.Provider value={{ mounted, currentTime }}>
      {children}
    </ClientTimeContext.Provider>
  );
}

export function useClientTime() {
  return useContext(ClientTimeContext);
}

// Universal client-safe timestamp component
export function SafeTimestamp({ 
  timestamp, 
  format = 'time',
  fallback = '--:--:--'
}: { 
  timestamp: Date | string;
  format?: 'time' | 'datetime' | 'date';
  fallback?: string;
}) {
  const { mounted } = useClientTime();
  
  if (!mounted) {
    return <span>{fallback}</span>;
  }
  
  const date = typeof timestamp === 'string' ? new Date(timestamp) : timestamp;
  
  switch (format) {
    case 'time':
      return <span>{date.toLocaleTimeString()}</span>;
    case 'datetime':
      return <span>{date.toLocaleString()}</span>;
    case 'date':
      return <span>{date.toLocaleDateString()}</span>;
    default:
      return <span>{date.toLocaleTimeString()}</span>;
  }
}

// Current time display that's always client-safe
export function CurrentTime({ 
  format = 'time',
  fallback = '--:--:--'
}: {
  format?: 'time' | 'datetime' | 'date';
  fallback?: string;
}) {
  const { mounted, currentTime } = useClientTime();
  
  if (!mounted || currentTime.getTime() === 0) {
    return <span>{fallback}</span>;
  }
  
  switch (format) {
    case 'time':
      return <span>{currentTime.toLocaleTimeString()}</span>;
    case 'datetime':
      return <span>{currentTime.toLocaleString()}</span>;
    case 'date':
      return <span>{currentTime.toLocaleDateString()}</span>;
    default:
      return <span>{currentTime.toLocaleTimeString()}</span>;
  }
}

export default ClientTimeProvider;