From 40bfbf7c11fc7447c707bb118fbfd8e5512b6fba Mon Sep 17 00:00:00 2001 From: 230419 <230419@epvc.pt> Date: Thu, 21 May 2026 09:50:31 +0100 Subject: [PATCH] notifica --- src/App.jsx | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) 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

+
+
+ {dailyOutfitNotifEnabled && ( + { + setDailyOutfitTime(e.target.value); + saveUserSetting('dailyOutfitTime', e.target.value); + }} + className={`px-3 py-1.5 rounded-xl text-sm outline-none border font-bold ${darkMode ? 'bg-gray-800 border-gray-700 text-white' : 'bg-white border-gray-200 text-gray-900'}`} + /> + )} + +
+

{t('weatherAlerts')}