notifica
This commit is contained in:
84
src/App.jsx
84
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() {
|
||||
<div className={`w-6 h-6 rounded-full bg-white absolute top-1 transition-all ${notificationsEnabled ? 'left-7' : 'left-1'}`}></div>
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4">
|
||||
<div>
|
||||
<p className="font-bold text-inherit flex items-center gap-2">Notificação do Outfit Diário</p>
|
||||
<p className="text-[10px] uppercase tracking-widest opacity-50 text-inherit">Receber notificação com o outfit planeado à hora marcada</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-4 w-full sm:w-auto justify-between sm:justify-end">
|
||||
{dailyOutfitNotifEnabled && (
|
||||
<input
|
||||
type="time"
|
||||
value={dailyOutfitTime}
|
||||
onChange={(e) => {
|
||||
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'}`}
|
||||
/>
|
||||
)}
|
||||
<button onClick={() => handleDailyOutfitNotifToggle(!dailyOutfitNotifEnabled)} className={`w-14 h-8 rounded-full transition-colors relative shrink-0 ${dailyOutfitNotifEnabled ? 'bg-primary-600' : 'bg-gray-200'}`}>
|
||||
<div className={`w-6 h-6 rounded-full bg-white absolute top-1 transition-all ${dailyOutfitNotifEnabled ? 'left-7' : 'left-1'}`}></div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="font-bold text-inherit flex items-center gap-2">{t('weatherAlerts')}</p>
|
||||
|
||||
Reference in New Issue
Block a user