← back to Dear Bubbe Nextjs
app/settings/page.tsx
305 lines
'use client'
import { useState, useEffect } from 'react'
import { useSession, signOut } from 'next-auth/react'
import { useRouter } from 'next/navigation'
import Link from 'next/link'
export default function SettingsPage() {
const { data: session, status } = useSession()
const router = useRouter()
const [settings, setSettings] = useState({
voiceEnabled: true,
autoListen: false,
bubbeVoice: 'yU6e7uJLZCE8eA26VAqb', // Default to original Bubbe voice
colorTheme: 'warm',
yiddishTranslations: true,
newsUpdates: true,
weatherUpdates: true,
sportsUpdates: false,
profanityFilter: false,
messageNotifications: true,
dailySummary: false
})
const [isSaving, setIsSaving] = useState(false)
const [successMessage, setSuccessMessage] = useState('')
// Redirect if not logged in
useEffect(() => {
if (status === 'unauthenticated') {
router.push('/')
}
}, [status, router])
// Load saved settings
useEffect(() => {
const savedSettings = localStorage.getItem('bubbeSettings')
if (savedSettings) {
setSettings(JSON.parse(savedSettings))
}
}, [])
const handleSave = () => {
setIsSaving(true)
// Save to localStorage
localStorage.setItem('bubbeSettings', JSON.stringify(settings))
// Show success message
setSuccessMessage('Settings saved successfully!')
setTimeout(() => {
setSuccessMessage('')
setIsSaving(false)
}, 2000)
}
const handleDeleteData = async () => {
const confirmed = confirm(
'Are you sure you want to delete your account and all data?\n\n' +
'This will permanently delete:\n' +
'• Your profile information\n' +
'• All conversation history\n' +
'• Your settings and preferences\n\n' +
'This action CANNOT be undone!'
)
if (!confirmed) return
// Double confirmation for safety
const reallyConfirmed = confirm(
'Are you ABSOLUTELY SURE?\n\n' +
'Bubbe will miss you terribly! 😢\n' +
'Last chance to cancel...'
)
if (!reallyConfirmed) return
try {
// Call API to delete server-side data
const response = await fetch('/api/user-profile', {
method: 'DELETE',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: session?.user?.email
})
})
if (response.ok) {
// Clear local storage
localStorage.clear()
// Sign out and redirect
alert('Your account has been deleted. Bubbe will miss you! 💔')
await signOut({ redirect: true, callbackUrl: '/' })
} else {
alert('Failed to delete account. Please try again.')
}
} catch (error) {
console.error('Failed to delete account:', error)
alert('An error occurred. Please try again.')
}
}
if (status === 'loading') {
return (
<div className="min-h-screen bg-gradient-to-br from-amber-50 to-orange-100 flex items-center justify-center">
<div className="text-2xl text-amber-600">Loading...</div>
</div>
)
}
return (
<div className="min-h-screen bg-gradient-to-br from-amber-50 to-orange-100 py-8">
<div className="max-w-3xl mx-auto px-4">
{/* Header */}
<div className="mb-8">
<Link href="/" className="text-amber-600 hover:text-amber-700 mb-4 inline-block">
← Back to Bubbe
</Link>
<h1 className="text-3xl font-bold text-gray-800">Settings</h1>
<p className="text-gray-600 mt-2">Customize your Bubbe experience</p>
</div>
{/* Success Message */}
{successMessage && (
<div className="mb-6 p-4 bg-green-100 border border-green-400 text-green-700 rounded-lg">
{successMessage}
</div>
)}
{/* Settings Sections */}
<div className="space-y-6">
{/* Voice Settings */}
<div className="bg-white rounded-xl shadow-lg p-6">
<h2 className="text-xl font-semibold text-gray-800 mb-4">Voice & Audio</h2>
<div className="space-y-4">
<label className="flex items-center justify-between">
<span className="text-gray-700">Enable Voice Output</span>
<input
type="checkbox"
checked={settings.voiceEnabled}
onChange={(e) => setSettings({ ...settings, voiceEnabled: e.target.checked })}
className="w-5 h-5 text-amber-600 rounded focus:ring-amber-500"
/>
</label>
<label className="flex items-center justify-between">
<span className="text-gray-700">Auto-Listen After Bubbe Speaks</span>
<input
type="checkbox"
checked={settings.autoListen}
onChange={(e) => setSettings({ ...settings, autoListen: e.target.checked })}
className="w-5 h-5 text-amber-600 rounded focus:ring-amber-500"
/>
</label>
<div>
<label className="block text-gray-700 mb-2">Bubbe's Voice (Onload)</label>
<select
value={settings.bubbeVoice}
onChange={(e) => setSettings({ ...settings, bubbeVoice: e.target.value })}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-amber-500"
>
<option value="yU6e7uJLZCE8eA26VAqb">Bubbe (Original)</option>
<option value="j9Ic6rh0FeC7nBIqew0q">Bubbeleh (Softer)</option>
<option value="VQHhI9WIBD3z8Ho2ZeUo">Bubbe Rose (Warm)</option>
</select>
<p className="text-sm text-gray-500 mt-1">Choose which voice Bubbe uses when greeting you</p>
</div>
</div>
</div>
{/* Appearance */}
<div className="bg-white rounded-xl shadow-lg p-6">
<h2 className="text-xl font-semibold text-gray-800 mb-4">Appearance</h2>
<div className="space-y-4">
<div>
<label className="block text-gray-700 mb-2">Color Theme</label>
<select
value={settings.colorTheme}
onChange={(e) => setSettings({ ...settings, colorTheme: e.target.value })}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-amber-500"
>
<option value="warm">Warm (Default)</option>
<option value="cool">Cool</option>
<option value="dark">Dark</option>
</select>
</div>
</div>
</div>
{/* Content Preferences */}
<div className="bg-white rounded-xl shadow-lg p-6">
<h2 className="text-xl font-semibold text-gray-800 mb-4">Content Preferences</h2>
<div className="space-y-4">
<label className="flex items-center justify-between">
<span className="text-gray-700">Show Yiddish Translations</span>
<input
type="checkbox"
checked={settings.yiddishTranslations}
onChange={(e) => setSettings({ ...settings, yiddishTranslations: e.target.checked })}
className="w-5 h-5 text-amber-600 rounded focus:ring-amber-500"
/>
</label>
<label className="flex items-center justify-between">
<span className="text-gray-700">Include News Updates</span>
<input
type="checkbox"
checked={settings.newsUpdates}
onChange={(e) => setSettings({ ...settings, newsUpdates: e.target.checked })}
className="w-5 h-5 text-amber-600 rounded focus:ring-amber-500"
/>
</label>
<label className="flex items-center justify-between">
<span className="text-gray-700">Include Weather Updates</span>
<input
type="checkbox"
checked={settings.weatherUpdates}
onChange={(e) => setSettings({ ...settings, weatherUpdates: e.target.checked })}
className="w-5 h-5 text-amber-600 rounded focus:ring-amber-500"
/>
</label>
<label className="flex items-center justify-between">
<span className="text-gray-700">Include Sports Updates</span>
<input
type="checkbox"
checked={settings.sportsUpdates}
onChange={(e) => setSettings({ ...settings, sportsUpdates: e.target.checked })}
className="w-5 h-5 text-amber-600 rounded focus:ring-amber-500"
/>
</label>
<label className="flex items-center justify-between">
<span className="text-gray-700">Mild Profanity Filter (Wimp Mode)</span>
<input
type="checkbox"
checked={settings.profanityFilter}
onChange={(e) => setSettings({ ...settings, profanityFilter: e.target.checked })}
className="w-5 h-5 text-amber-600 rounded focus:ring-amber-500"
/>
</label>
</div>
</div>
{/* Notifications */}
<div className="bg-white rounded-xl shadow-lg p-6">
<h2 className="text-xl font-semibold text-gray-800 mb-4">Notifications</h2>
<div className="space-y-4">
<label className="flex items-center justify-between">
<span className="text-gray-700">Message Notifications</span>
<input
type="checkbox"
checked={settings.messageNotifications}
onChange={(e) => setSettings({ ...settings, messageNotifications: e.target.checked })}
className="w-5 h-5 text-amber-600 rounded focus:ring-amber-500"
/>
</label>
<label className="flex items-center justify-between">
<span className="text-gray-700">Daily Guilt Trip Summary</span>
<input
type="checkbox"
checked={settings.dailySummary}
onChange={(e) => setSettings({ ...settings, dailySummary: e.target.checked })}
className="w-5 h-5 text-amber-600 rounded focus:ring-amber-500"
/>
</label>
</div>
</div>
{/* Save Button */}
<div className="flex justify-between items-center">
<button
onClick={handleSave}
disabled={isSaving}
className="px-6 py-3 bg-amber-500 text-white rounded-lg hover:bg-amber-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors font-medium"
>
{isSaving ? 'Saving...' : 'Save Settings'}
</button>
</div>
{/* Danger Zone */}
<div className="bg-red-50 border border-red-200 rounded-xl p-6">
<h2 className="text-xl font-semibold text-red-800 mb-4">Danger Zone</h2>
<div className="space-y-4">
<div>
<p className="text-gray-700 mb-3">
Delete all your data including profile and conversation history. This action cannot be undone.
</p>
<button
onClick={handleDeleteData}
className="px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700 transition-colors"
>
Delete All My Data
</button>
</div>
</div>
</div>
</div>
</div>
</div>
)
}