File size: 11,339 Bytes
d97b8f9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
import React, { useState, useEffect, useRef } from "react";
import { Lock, Coffee, Users, Mail, PanelRight, X } from "lucide-react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { Switch } from "@/components/ui/switch";

interface ScheduleItem {
  time: string;
  activity: string;
  type: "focused" | "collaborative" | "rest" | "light";
  icon: React.ReactNode;
}

export default function GlobalWorkNotifications() {
  const [currentTime, setCurrentTime] = useState<Date>(new Date());
  const [lastNotifiedIndex, setLastNotifiedIndex] = useState<number>(-1);
  const [showNotificationModal, setShowNotificationModal] = useState<boolean>(false);
  const [notificationsEnabled, setNotificationsEnabled] = useState<boolean>(() => {
    if (typeof window !== 'undefined') {
      const saved = localStorage.getItem('globalWorkNotificationsEnabled');
      return saved !== null ? saved === 'true' : true;
    }
    return true;
  });
  const [currentNotification, setCurrentNotification] = useState<{
    title: string;
    description: string;
    type: "focused" | "collaborative" | "rest" | "light";
  } | null>(null);
  
  const notificationAudioRef = useRef<HTMLAudioElement | null>(null);

  // Initialize audio element
  useEffect(() => {
    const audio = new Audio('/notification.mp3');
    audio.preload = 'auto';
    audio.volume = 1.0; // Full volume
    notificationAudioRef.current = audio;
    
    return () => {
      if (notificationAudioRef.current) {
        notificationAudioRef.current.pause();
        notificationAudioRef.current = null;
      }
    };
  }, []);

  // Save notification preferences
  useEffect(() => {
    localStorage.setItem('globalWorkNotificationsEnabled', notificationsEnabled.toString());
  }, [notificationsEnabled]);

  // Update current time every minute
  useEffect(() => {
    const timer = setInterval(() => {
      setCurrentTime(new Date());
    }, 60000);
    return () => clearInterval(timer);
  }, []);

  // Daily schedule data
  const scheduleItems: ScheduleItem[] = [
    { time: "9:30 AM – 10:30 AM", activity: "Team Collaboration / Planning", type: "light", icon: <Users className="h-4 w-4" /> },
    { time: "10:30 AM – 11:30 AM", activity: "Deep Work Session 1", type: "focused", icon: <Lock className="h-4 w-4" /> },
    { time: "11:30 AM – 12:00 PM", activity: "Team Discussion / Quick Sync", type: "collaborative", icon: <Users className="h-4 w-4" /> },
    { time: "12:00 PM – 1:00 PM", activity: "Deep Work Session 2", type: "focused", icon: <Lock className="h-4 w-4" /> },
    { time: "1:00 PM – 1:45 PM", activity: "Lunch Break", type: "rest", icon: <Coffee className="h-4 w-4" /> },
    { time: "1:45 PM – 2:30 PM", activity: "Team Collaboration / Emails", type: "light", icon: <Mail className="h-4 w-4" /> },
    { time: "2:30 PM – 3:30 PM", activity: "Deep Work Session 3", type: "focused", icon: <Lock className="h-4 w-4" /> },
    { time: "3:30 PM – 4:00 PM", activity: "Team Discussion / Admin Tasks", type: "collaborative", icon: <PanelRight className="h-4 w-4" /> },
    { time: "4:00 PM – 4:15 PM", activity: "Tea Break", type: "rest", icon: <Coffee className="h-4 w-4" /> },
    { time: "4:15 PM – 4:30 PM", activity: "Flex / Light Catch-Up", type: "light", icon: <Users className="h-4 w-4" /> },
    { time: "4:30 PM – 5:30 PM", activity: "Deep Work Session 4", type: "focused", icon: <Lock className="h-4 w-4" /> },
    { time: "5:30 PM – 6:30 PM", activity: "Team Support / Wrap-Up", type: "light", icon: <Users className="h-4 w-4" /> },
  ];

  const playNotificationSound = () => {
    if (notificationAudioRef.current && notificationsEnabled) {
      try {
        notificationAudioRef.current.currentTime = 0;
        notificationAudioRef.current.play().catch(err => {
          console.log("Could not play notification sound:", err);
        });
      } catch (error) {
        console.error("Error playing notification sound:", error);
      }
    }
  };

  const showNotification = (item: ScheduleItem) => {
    if (!notificationsEnabled) return;
    
    playNotificationSound();
    
    const title = `Time for ${item.activity}`;
    const description = `${item.time} - ${

      item.type === "focused" ? "Focus on deep work" : 

      item.type === "collaborative" ? "Connect with your team" : 

      item.type === "rest" ? "Take a break to recharge" : 

      "Handle lighter tasks"

    }`;
    
    toast.info(title, { description });
    
    setCurrentNotification({ title, description, type: item.type });
    setShowNotificationModal(true);
    document.body.classList.add('overflow-hidden');
  };

  // Check current activity and show notifications only when time changes
  useEffect(() => {
    const now = currentTime;
    const hour = now.getHours();
    const minute = now.getMinutes();
    const currentTimeInMinutes = hour * 60 + minute;
    
    const index = scheduleItems.findIndex((item) => {
      const [startTime, endTime] = item.time.split(" – ");
      const [startHour, startMinutePart] = startTime.split(":");
      const startMinute = parseInt(startMinutePart);
      const startHourNum = parseInt(startHour) + (startTime.includes("PM") && parseInt(startHour) !== 12 ? 12 : 0);
      const startTimeInMinutes = startHourNum * 60 + startMinute;
      
      const [endHour, endMinutePart] = endTime.split(":");
      const endMinute = parseInt(endMinutePart);
      const endHourNum = parseInt(endHour) + (endTime.includes("PM") && parseInt(endHour) !== 12 ? 12 : 0);
      const endTimeInMinutes = endHourNum * 60 + endMinute;
      
      return currentTimeInMinutes >= startTimeInMinutes && currentTimeInMinutes < endTimeInMinutes;
    });
    
    // Only show notification if this is not the initial load and the activity has changed
    const isInitialLoad = lastNotifiedIndex === -1;
    
    if (index !== -1) {
      if (!isInitialLoad && index !== lastNotifiedIndex && notificationsEnabled) {
        console.log('Time-based notification triggered for:', scheduleItems[index].activity);
        showNotification(scheduleItems[index]);
      }
      setLastNotifiedIndex(index);
    } else if (isInitialLoad) {
      // If no current activity on initial load, set lastNotifiedIndex to avoid future false triggers
      setLastNotifiedIndex(-2);
    }
  }, [currentTime, scheduleItems, notificationsEnabled]);

  const getModalStyles = (type: "focused" | "collaborative" | "rest" | "light") => {
    switch (type) {
      case "focused": return "bg-purple-50 border-purple-200 text-purple-800";
      case "collaborative": return "bg-blue-50 border-blue-200 text-blue-800";
      case "rest": return "bg-red-50 border-red-200 text-red-800";
      case "light": return "bg-green-50 border-green-200 text-green-800";
      default: return "";
    }
  };

  const getModalIcon = (type: "focused" | "collaborative" | "rest" | "light") => {
    switch (type) {
      case "focused": return <Lock className="h-12 w-12 text-purple-600" />;
      case "collaborative": return <Users className="h-12 w-12 text-blue-600" />;
      case "rest": return <Coffee className="h-12 w-12 text-red-600" />;
      case "light": return <Mail className="h-12 w-12 text-green-600" />;
      default: return null;
    }
  };
  
  const closeModal = () => {
    setShowNotificationModal(false);
    document.body.classList.remove('overflow-hidden');
  };

  useEffect(() => {
    const handleEscapeKey = (event: KeyboardEvent) => {
      if (event.key === 'Escape' && showNotificationModal) {
        closeModal();
      }
    };
    document.addEventListener('keydown', handleEscapeKey);
    return () => document.removeEventListener('keydown', handleEscapeKey);
  }, [showNotificationModal]);

  return (
    <>

      {showNotificationModal && currentNotification && (

        <div className="fixed inset-0 z-50 flex items-center justify-center">

          <div className="absolute inset-0 bg-black bg-opacity-50 backdrop-blur-sm" onClick={closeModal} />

          

          <div className={`relative mx-4 w-full max-w-md rounded-lg border shadow-lg transform transition-all ${getModalStyles(currentNotification.type)}`}>

            <button onClick={closeModal} className="absolute right-4 top-4 rounded-full p-1 text-gray-500 hover:bg-gray-100">

              <X className="h-5 w-5" />

            </button>

            

            <div className="p-6">

              <div className="flex items-start gap-4">

                <div className="p-3 rounded-full bg-white shadow-md">

                  {getModalIcon(currentNotification.type)}

                </div>

                <div className="flex-1 pt-2">

                  <h2 className="text-xl font-bold">{currentNotification.title}</h2>

                  <p className="text-base mt-1 opacity-90">{currentNotification.description}</p>

                </div>

              </div>

              

              <div className="mt-6 p-4 rounded-md bg-white bg-opacity-50">

                {currentNotification.type === "focused" ? (

                  <p className="text-sm">🧠 Time to focus! Close distractions, silence notifications, and dedicate this time to deep, meaningful work.</p>

                ) : currentNotification.type === "collaborative" ? (

                  <p className="text-sm">πŸ‘₯ Connect with your team! This is a good time for meetings, discussions, and collaborative problem-solving.</p>

                ) : currentNotification.type === "rest" ? (

                  <p className="text-sm">πŸ”‹ Take a break! Step away from your desk, stretch, or grab a refreshment to recharge your energy.</p>

                ) : (

                  <p className="text-sm">πŸ“‹ Handle lighter tasks! This is a good time for emails, planning, and administrative tasks.</p>

                )}

              </div>

              

              <div className="mt-6">

                <div className="flex items-center gap-2 mb-4">

                  <Switch 

                    id="global-notification-toggle"

                    checked={notificationsEnabled} 

                    onCheckedChange={setNotificationsEnabled}

                  />

                  <label htmlFor="global-notification-toggle" className="text-sm cursor-pointer">

                    {notificationsEnabled ? "Notifications On" : "Notifications Off"}

                  </label>

                </div>

                

                <Button 

                  onClick={closeModal}

                  className={`font-semibold w-full ${

                    currentNotification.type === "focused" ? "bg-purple-600 hover:bg-purple-700" : 

                    currentNotification.type === "collaborative" ? "bg-blue-600 hover:bg-blue-700" : 

                    currentNotification.type === "rest" ? "bg-red-600 hover:bg-red-700" : 

                    "bg-green-600 hover:bg-green-700"

                  } text-white`}

                >

                  Acknowledge

                </Button>

              </div>

            </div>

          </div>

        </div>

      )}

    </>
  );
}