← back to Dear Bubbe Nextjs
app/profile/page.tsx
526 lines
'use client'
import { useState, useEffect } from 'react'
import { useSession } from 'next-auth/react'
import { useRouter } from 'next/navigation'
import Link from 'next/link'
export default function ProfilePage() {
const { data: session, status } = useSession()
const router = useRouter()
const [isLoading, setIsLoading] = useState(false)
const [successMessage, setSuccessMessage] = useState('')
const [profile, setProfile] = useState({
preferredName: '',
gender: '',
relationshipStatus: '',
sameGenderPartner: false,
birthYear: '',
religiousLevel: '',
hasKids: '',
numberOfKids: 0,
incomeLevel: '',
education: '',
school: '',
degree: '',
graduationYear: '',
jobTitle: '',
company: '',
industry: '',
yearsAtJob: '',
country: '',
state: '',
city: '',
// Bubbe personality settings
bubbePersonality: 'rude', // 'rude' or 'sweet'
yiddishEnabled: true,
translationEnabled: true
})
// Redirect if not logged in
useEffect(() => {
if (status === 'unauthenticated') {
router.push('/')
}
}, [status, router])
// Load existing profile
useEffect(() => {
const loadProfile = async () => {
try {
const response = await fetch('/api/user-profile')
if (response.ok) {
const data = await response.json()
if (data.profile) {
setProfile(data.profile)
}
}
} catch (error) {
console.error('Failed to load profile:', error)
}
}
if (session) {
loadProfile()
}
}, [session])
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
setIsLoading(true)
try {
const response = await fetch('/api/user-profile', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
...profile,
email: session?.user?.email
})
})
if (response.ok) {
setSuccessMessage('Profile updated successfully!')
setTimeout(() => setSuccessMessage(''), 3000)
}
} catch (error) {
console.error('Failed to update profile:', error)
} finally {
setIsLoading(false)
}
}
const currentYear = new Date().getFullYear()
const years = Array.from({ length: 100 }, (_, i) => currentYear - i - 13)
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">My Profile</h1>
<p className="text-gray-600 mt-2">Update your information for more personalized guilt trips!</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>
)}
{/* Profile Form */}
<form onSubmit={handleSubmit} className="bg-white rounded-xl shadow-lg p-6 space-y-6">
{/* Personal Information */}
<div>
<h2 className="text-xl font-semibold text-gray-800 mb-4">Personal Information</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Preferred Name
</label>
<input
type="text"
value={profile.preferredName}
onChange={(e) => setProfile({ ...profile, preferredName: 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"
placeholder="What should Bubbe call you?"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Gender
</label>
<select
value={profile.gender}
onChange={(e) => setProfile({ ...profile, gender: 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="">Select...</option>
<option value="male">Male</option>
<option value="female">Female</option>
<option value="other">Other</option>
<option value="prefer_not_to_say">Prefer not to say</option>
</select>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Birth Year
</label>
<select
value={profile.birthYear}
onChange={(e) => setProfile({ ...profile, birthYear: 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="">Select year...</option>
{years.map(year => (
<option key={year} value={year}>{year}</option>
))}
</select>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Religious Level
</label>
<select
value={profile.religiousLevel}
onChange={(e) => setProfile({ ...profile, religiousLevel: 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="">Select...</option>
<option value="very">Very religious</option>
<option value="somewhat">Somewhat religious</option>
<option value="not_very">Not very religious</option>
<option value="secular">Secular</option>
<option value="atheist">Atheist</option>
</select>
</div>
</div>
</div>
{/* Relationship Status */}
<div>
<h2 className="text-xl font-semibold text-gray-800 mb-4">Relationship Status</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Status
</label>
<select
value={profile.relationshipStatus}
onChange={(e) => setProfile({ ...profile, relationshipStatus: 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="">Select...</option>
<option value="single">Single</option>
<option value="relationship">In a relationship</option>
<option value="engaged">Engaged</option>
<option value="married">Married</option>
<option value="divorced">Divorced</option>
<option value="widowed">Widowed</option>
<option value="complicated">It's complicated</option>
</select>
</div>
<div className="flex items-center">
<input
type="checkbox"
id="sameGenderPartner"
checked={profile.sameGenderPartner}
onChange={(e) => setProfile({ ...profile, sameGenderPartner: e.target.checked })}
className="mr-2"
/>
<label htmlFor="sameGenderPartner" className="text-sm text-gray-700">
Same-gender partner
</label>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Have Kids?
</label>
<select
value={profile.hasKids}
onChange={(e) => setProfile({ ...profile, hasKids: 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="">Select...</option>
<option value="no">No</option>
<option value="yes">Yes</option>
<option value="expecting">Expecting</option>
</select>
</div>
{profile.hasKids === 'yes' && (
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Number of Kids
</label>
<input
type="number"
min="1"
max="20"
value={profile.numberOfKids}
onChange={(e) => setProfile({ ...profile, numberOfKids: parseInt(e.target.value) || 0 })}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-amber-500"
/>
</div>
)}
</div>
</div>
{/* Career & Education */}
<div>
<h2 className="text-xl font-semibold text-gray-800 mb-4">Career & Education</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Income Level
</label>
<select
value={profile.incomeLevel}
onChange={(e) => setProfile({ ...profile, incomeLevel: 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="">Prefer not to say</option>
<option value="under_50k">Under $50K</option>
<option value="50k_100k">$50K - $100K</option>
<option value="100k_200k">$100K - $200K</option>
<option value="200k_500k">$200K - $500K</option>
<option value="over_500k">Over $500K</option>
</select>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Job Title
</label>
<input
type="text"
value={profile.jobTitle}
onChange={(e) => setProfile({ ...profile, jobTitle: 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"
placeholder="e.g., Software Engineer"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Company
</label>
<input
type="text"
value={profile.company}
onChange={(e) => setProfile({ ...profile, company: 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"
placeholder="Where do you work?"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Industry
</label>
<select
value={profile.industry}
onChange={(e) => setProfile({ ...profile, industry: 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="">Select...</option>
<option value="tech">Technology</option>
<option value="finance">Finance/Banking</option>
<option value="healthcare">Healthcare</option>
<option value="education">Education</option>
<option value="retail">Retail/Sales</option>
<option value="manufacturing">Manufacturing</option>
<option value="government">Government</option>
<option value="nonprofit">Non-profit</option>
<option value="entertainment">Entertainment/Media</option>
<option value="legal">Legal</option>
<option value="consulting">Consulting</option>
<option value="unemployed">Between jobs</option>
<option value="student">Student</option>
<option value="retired">Retired</option>
<option value="other">Other</option>
</select>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
School/University
</label>
<input
type="text"
value={profile.school}
onChange={(e) => setProfile({ ...profile, school: 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"
placeholder="Where did you study?"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Degree
</label>
<input
type="text"
value={profile.degree}
onChange={(e) => setProfile({ ...profile, degree: 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"
placeholder="e.g., BA, MBA, MD"
/>
</div>
</div>
</div>
{/* Location */}
<div>
<h2 className="text-xl font-semibold text-gray-800 mb-4">Location</h2>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Country
</label>
<input
type="text"
value={profile.country}
onChange={(e) => setProfile({ ...profile, country: 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"
placeholder="e.g., USA"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
State/Province
</label>
<input
type="text"
value={profile.state}
onChange={(e) => setProfile({ ...profile, state: 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"
placeholder="e.g., New York"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
City
</label>
<input
type="text"
value={profile.city}
onChange={(e) => setProfile({ ...profile, city: 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"
placeholder="e.g., Brooklyn"
/>
</div>
</div>
</div>
{/* Bubbe Personality Settings */}
<div>
<h2 className="text-xl font-semibold text-gray-800 mb-4">Bubbe Personality Settings</h2>
<div className="space-y-4">
{/* Personality Type */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Bubbe Personality Type
</label>
<div className="space-y-2">
<label className="flex items-start cursor-pointer p-3 border rounded-lg hover:bg-amber-50 transition-colors">
<input
type="radio"
name="personality"
value="rude"
checked={profile.bubbePersonality === 'rude'}
onChange={(e) => setProfile({ ...profile, bubbePersonality: e.target.value })}
className="mt-1 mr-3"
/>
<div>
<div className="font-medium text-gray-800">Rude Bubbe (Classic)</div>
<div className="text-sm text-gray-600">Brutally honest, sarcastic, guilt-tripping grandma who tells it like it is</div>
</div>
</label>
<label className="flex items-start cursor-pointer p-3 border rounded-lg hover:bg-amber-50 transition-colors">
<input
type="radio"
name="personality"
value="sweet"
checked={profile.bubbePersonality === 'sweet'}
onChange={(e) => setProfile({ ...profile, bubbePersonality: e.target.value })}
className="mt-1 mr-3"
/>
<div>
<div className="font-medium text-gray-800">Sweet Bubbe</div>
<div className="text-sm text-gray-600">Loving, supportive, encouraging grandma with gentle wisdom</div>
</div>
</label>
</div>
</div>
{/* Yiddish Settings */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="flex items-center cursor-pointer p-3 border rounded-lg hover:bg-amber-50 transition-colors">
<input
type="checkbox"
checked={profile.yiddishEnabled}
onChange={(e) => setProfile({ ...profile, yiddishEnabled: e.target.checked })}
className="mr-3 h-5 w-5 text-amber-600"
/>
<div>
<div className="font-medium text-gray-800">Yiddish Enabled</div>
<div className="text-sm text-gray-600">Include Yiddish words and phrases</div>
</div>
</label>
</div>
<div>
<label className="flex items-center cursor-pointer p-3 border rounded-lg hover:bg-amber-50 transition-colors">
<input
type="checkbox"
checked={profile.translationEnabled}
onChange={(e) => setProfile({ ...profile, translationEnabled: e.target.checked })}
className="mr-3 h-5 w-5 text-amber-600"
disabled={!profile.yiddishEnabled}
/>
<div>
<div className="font-medium text-gray-800">Show Translations</div>
<div className="text-sm text-gray-600">Show English translations for Yiddish words</div>
</div>
</label>
</div>
</div>
{/* Preview */}
<div className="p-4 bg-amber-50 rounded-lg">
<div className="text-sm font-medium text-gray-700 mb-2">Preview:</div>
<div className="text-gray-800">
{profile.bubbePersonality === 'rude' ? (
<>
"Oy vey{profile.translationEnabled && profile.yiddishEnabled ? ' (oh no)' : ''}, you finally update your profile?
About time, {profile.yiddishEnabled ? 'schmuck' : 'fool'}{profile.translationEnabled && profile.yiddishEnabled ? ' (jerk)' : ''}!
What took you so long?"
</>
) : (
<>
"{profile.yiddishEnabled ? 'Bubbeleh' : 'Sweetheart'}{profile.translationEnabled && profile.yiddishEnabled ? ' (sweetie)' : ''},
I'm so glad you're updating your profile!
You're such a {profile.yiddishEnabled ? 'mensch' : 'good person'}{profile.translationEnabled && profile.yiddishEnabled ? ' (decent person)' : ''}!"
</>
)}
</div>
</div>
</div>
</div>
{/* Submit Button */}
<div className="flex justify-end">
<button
type="submit"
disabled={isLoading}
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"
>
{isLoading ? 'Saving...' : 'Save Profile'}
</button>
</div>
</form>
</div>
</div>
)
}