diff --git a/src/App.jsx b/src/App.jsx index 6775246..4fa19d9 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -57,6 +57,9 @@ export default function App() { // Estado para Definições const [notificationsEnabled, setNotificationsEnabled] = useState(true); + const [dailyOutfitTime, setDailyOutfitTime] = useState('08:00'); + const [dailyOutfitNotifEnabled, setDailyOutfitNotifEnabled] = useState(false); + const [lastNotifiedDate, setLastNotifiedDate] = useState(''); const [weatherAlerts, setWeatherAlerts] = useState(true); const [language, setLanguage] = useState('PT'); const [showLangModal, setShowLangModal] = useState(false); @@ -172,6 +175,23 @@ export default function App() { saveUserSetting('notificationsEnabled', newVal); }; + const handleDailyOutfitNotifToggle = async (newVal) => { + if (newVal) { + if ('Notification' in window) { + const permission = await Notification.requestPermission(); + if (permission !== 'granted') { + alert('Permissão recusada. Ative as notificações no browser para usar esta funcionalidade.'); + return; + } + } else { + alert('O seu browser não suporta notificações.'); + return; + } + } + setDailyOutfitNotifEnabled(newVal); + saveUserSetting('dailyOutfitNotifEnabled', newVal); + }; + const handleWeatherAlertsToggle = (newVal) => { setWeatherAlerts(newVal); saveUserSetting('weatherAlerts', newVal); @@ -370,6 +390,9 @@ export default function App() { if (data.settings.darkMode !== undefined) setDarkMode(data.settings.darkMode); if (data.settings.theme !== undefined) setTheme(data.settings.theme); if (data.settings.notificationsEnabled !== undefined) setNotificationsEnabled(data.settings.notificationsEnabled); + if (data.settings.dailyOutfitTime !== undefined) setDailyOutfitTime(data.settings.dailyOutfitTime); + if (data.settings.dailyOutfitNotifEnabled !== undefined) setDailyOutfitNotifEnabled(data.settings.dailyOutfitNotifEnabled); + if (data.settings.lastNotifiedDate !== undefined) setLastNotifiedDate(data.settings.lastNotifiedDate); if (data.settings.weatherAlerts !== undefined) setWeatherAlerts(data.settings.weatherAlerts); if (data.settings.cardSize !== undefined) setCardSize(data.settings.cardSize); if (data.settings.defaultPage !== undefined) { @@ -630,6 +653,45 @@ export default function App() { }; const dailyLooks = getLooksForDayGlobal(todayStrGlobal); + // Efeito para notificação diária + useEffect(() => { + if (!user || !dailyOutfitNotifEnabled || !dailyOutfitTime) return; + + const intervalId = setInterval(() => { + const now = new Date(); + const currentHour = String(now.getHours()).padStart(2, '0'); + const currentMinute = String(now.getMinutes()).padStart(2, '0'); + const currentTime = `${currentHour}:${currentMinute}`; + + const todayStr = `${now.getFullYear()}-${String(now.getMonth()+1).padStart(2,'0')}-${String(now.getDate()).padStart(2,'0')}`; + + if (currentTime === dailyOutfitTime && lastNotifiedDate !== todayStr) { + const todaysLooks = getLooksForDayGlobal(todayStr); + if (todaysLooks.length > 0) { + const mainLook = todaysLooks[0]; + if ('Notification' in window && Notification.permission === 'granted') { + navigator.serviceWorker?.getRegistration().then(reg => { + const title = 'MyCloset - Outfit Diário'; + const options = { + body: `O seu outfit planeado "${mainLook.name}" está pronto para hoje!`, + icon: '/favicon.ico' + }; + if (reg) { + reg.showNotification(title, options); + } else { + new Notification(title, options); + } + }); + setLastNotifiedDate(todayStr); + saveUserSetting('lastNotifiedDate', todayStr); + } + } + } + }, 30000); // Verifica a cada 30 segundos + + return () => clearInterval(intervalId); + }, [user, dailyOutfitNotifEnabled, dailyOutfitTime, lastNotifiedDate, outfitPlans, looks]); + const baseClothes = view === 'wishlist' ? wishlistClothes : activeClothes; const availableColors = useMemo(() => { @@ -2566,6 +2628,28 @@ export default function App() {
+Notificação do Outfit Diário
+Receber notificação com o outfit planeado à hora marcada
+{t('weatherAlerts')}