Implement server-side push notifications with scheduler and always-remind option

This commit is contained in:
Gemini Agent
2026-01-25 03:14:04 +00:00
parent ad8b45ee1f
commit 90f54766a5
17 changed files with 2429 additions and 21 deletions

View File

@@ -11,6 +11,7 @@ import Link from "next/link";
interface UserSettings {
reminderEnabled: boolean;
reminderTime: string;
reminderAlways: boolean;
llmProvider: string | null;
hasLlmKey: boolean;
llmModel: string | null;
@@ -30,7 +31,7 @@ const PROVIDERS = [
export default function SettingsPage() {
const { user, logout } = useAuth();
const { isSupported: swSupported, isRegistered: swRegistered, showNotification } = useServiceWorker();
const { isSupported: swSupported, isRegistered: swRegistered, showNotification, subscribeToPush } = useServiceWorker();
const [settings, setSettings] = useState<UserSettings | null>(null);
const [isLoading, setIsLoading] = useState(true);
const [isSaving, setIsSaving] = useState(false);
@@ -78,6 +79,13 @@ export default function SettingsPage() {
setIsPWA(isStandalone);
}, []);
// Ensure push subscription is active if permissions are granted
useEffect(() => {
if (notificationPermission === "granted" && swRegistered) {
subscribeToPush().catch(console.error);
}
}, [notificationPermission, swRegistered, subscribeToPush]);
const updateSetting = async (key: string, value: unknown) => {
setIsSaving(true);
try {
@@ -102,6 +110,14 @@ export default function SettingsPage() {
setNotificationPermission(permission);
if (permission === "granted") {
updateSetting("reminderEnabled", true);
const subscribed = await subscribeToPush();
if (subscribed) {
showNotification(APP_NAME, {
body: "Notifications enabled! You will receive daily reminders.",
icon: "/icons/icon.svg",
tag: "welcome-notification",
});
}
}
}
};
@@ -308,14 +324,28 @@ export default function SettingsPage() {
</button>
</div>
{settings.reminderEnabled && (
<div className="mt-4 flex items-center gap-3">
<label className="text-sm text-muted">Remind me at:</label>
<input
type="time"
value={settings.reminderTime}
onChange={(e) => updateSetting("reminderTime", e.target.value)}
className="px-3 py-1 bg-background border border-border rounded-lg text-sm focus:outline-none focus:border-muted"
/>
<div className="mt-4 space-y-4">
<div className="flex items-center gap-3">
<label className="text-sm text-muted">Remind me at:</label>
<input
type="time"
value={settings.reminderTime}
onChange={(e) => updateSetting("reminderTime", e.target.value)}
className="px-3 py-1 bg-background border border-border rounded-lg text-sm focus:outline-none focus:border-muted"
/>
</div>
<div className="flex items-center gap-3">
<input
type="checkbox"
id="reminderAlways"
checked={settings.reminderAlways}
onChange={(e) => updateSetting("reminderAlways", e.target.checked)}
className="w-4 h-4 rounded border-border text-accent focus:ring-accent"
/>
<label htmlFor="reminderAlways" className="text-sm text-muted cursor-pointer">
Always remind me, even if I've already journaled today
</label>
</div>
</div>
)}
{settings.reminderEnabled && notificationPermission === "granted" && swRegistered && (