WIP: Améliorations UX et corrections de bugs avant création des épiques

This commit is contained in:
2026-01-17 11:10:50 +01:00
parent 772dc77719
commit ef60dafd73
84 changed files with 11846 additions and 230 deletions

View File

@@ -0,0 +1,155 @@
'use client'
import { useState } from 'react'
import { SettingsNav, SettingsSection, SettingToggle, SettingInput, SettingSelect } from '@/components/settings'
import { updateAISettings } from '@/app/actions/ai-settings'
import { toast } from 'sonner'
import { useLanguage } from '@/lib/i18n'
export default function ProfileSettingsPage() {
const { t } = useLanguage()
// Mock user data - in real implementation, load from server
const [user, setUser] = useState({
name: 'John Doe',
email: 'john@example.com'
})
const [language, setLanguage] = useState('auto')
const [showRecentNotes, setShowRecentNotes] = useState(false)
const handleNameChange = async (value: string) => {
setUser(prev => ({ ...prev, name: value }))
// TODO: Implement profile update
console.log('Name:', value)
}
const handleEmailChange = async (value: string) => {
setUser(prev => ({ ...prev, email: value }))
// TODO: Implement email update
console.log('Email:', value)
}
const handleLanguageChange = async (value: string) => {
setLanguage(value)
try {
await updateAISettings({ preferredLanguage: value as any })
} catch (error) {
console.error('Error updating language:', error)
toast.error('Failed to save language')
}
}
const handleRecentNotesChange = async (enabled: boolean) => {
setShowRecentNotes(enabled)
try {
await updateAISettings({ showRecentNotes: enabled })
} catch (error) {
console.error('Error updating recent notes setting:', error)
toast.error('Failed to save setting')
}
}
return (
<div className="container mx-auto py-10 px-4 max-w-6xl">
<div className="grid grid-cols-1 lg:grid-cols-4 gap-6">
{/* Sidebar Navigation */}
<aside className="lg:col-span-1">
<SettingsNav />
</aside>
{/* Main Content */}
<main className="lg:col-span-3 space-y-6">
<div>
<h1 className="text-3xl font-bold mb-2">Profile</h1>
<p className="text-gray-600 dark:text-gray-400">
Manage your account and personal information
</p>
</div>
{/* Profile Information */}
<SettingsSection
title="Profile Information"
icon={<span className="text-2xl">👤</span>}
description="Update your personal details"
>
<SettingInput
label="Name"
description="Your display name"
value={user.name}
onChange={handleNameChange}
placeholder="Enter your name"
/>
<SettingInput
label="Email"
description="Your email address"
value={user.email}
type="email"
onChange={handleEmailChange}
placeholder="Enter your email"
/>
</SettingsSection>
{/* Preferences */}
<SettingsSection
title="Preferences"
icon={<span className="text-2xl"></span>}
description="Customize your experience"
>
<SettingSelect
label="Language"
description="Choose your preferred language"
value={language}
options={[
{ value: 'auto', label: 'Auto-detect' },
{ value: 'en', label: 'English' },
{ value: 'fr', label: 'Français' },
{ value: 'es', label: 'Español' },
{ value: 'de', label: 'Deutsch' },
{ value: 'fa', label: 'فارسی' },
{ value: 'it', label: 'Italiano' },
{ value: 'pt', label: 'Português' },
{ value: 'ru', label: 'Русский' },
{ value: 'zh', label: '中文' },
{ value: 'ja', label: '日本語' },
{ value: 'ko', label: '한국어' },
{ value: 'ar', label: 'العربية' },
{ value: 'hi', label: 'हिन्दी' },
{ value: 'nl', label: 'Nederlands' },
{ value: 'pl', label: 'Polski' },
]}
onChange={handleLanguageChange}
/>
<SettingToggle
label="Show Recent Notes"
description="Display recently viewed notes in sidebar"
checked={showRecentNotes}
onChange={handleRecentNotesChange}
/>
</SettingsSection>
{/* AI Settings Link */}
<div className="p-6 border rounded-lg bg-gradient-to-r from-purple-50 to-pink-50 dark:from-purple-950 dark:to-pink-950">
<div className="flex items-center gap-4">
<div className="text-4xl"></div>
<div className="flex-1">
<h3 className="font-semibold text-lg mb-1">AI Settings</h3>
<p className="text-sm text-gray-600 dark:text-gray-400">
Configure AI-powered features, provider selection, and preferences
</p>
</div>
<button
onClick={() => window.location.href = '/settings/ai'}
className="px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors"
>
Configure
</button>
</div>
</div>
</main>
</div>
</div>
)
}

View File

@@ -23,11 +23,26 @@ export default async function ProfilePage() {
redirect('/login')
}
// Get user AI settings for language preference
const userAISettings = await prisma.userAISettings.findUnique({
where: { userId: session.user.id },
select: { preferredLanguage: true }
})
// Get user AI settings for language preference and recent notes setting
let userAISettings = { preferredLanguage: 'auto', showRecentNotes: false }
try {
const result = await prisma.$queryRaw<Array<{ preferredLanguage: string | null; showRecentNotes: number | null }>>`
SELECT preferredLanguage, showRecentNotes FROM UserAISettings WHERE userId = ${session.user.id}
`
if (result && result[0]) {
// Handle NULL values - if showRecentNotes is NULL, default to false
const showRecentNotesValue = result[0].showRecentNotes !== null && result[0].showRecentNotes !== undefined
? result[0].showRecentNotes === 1
: false
userAISettings = {
preferredLanguage: result[0].preferredLanguage || 'auto',
showRecentNotes: showRecentNotesValue
}
}
} catch (error) {
// Record doesn't exist, use defaults
}
return (
<div className="container max-w-2xl mx-auto py-10 px-4">

View File

@@ -1,10 +1,12 @@
'use client'
import { useState, useEffect } from 'react'
import { useRouter } from 'next/navigation'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'
import { Label } from '@/components/ui/label'
import { Switch } from '@/components/ui/switch'
import {
Select,
SelectContent,
@@ -12,7 +14,7 @@ import {
SelectTrigger,
SelectValue,
} from '@/components/ui/select'
import { updateProfile, changePassword, updateLanguage, updateFontSize } from '@/app/actions/profile'
import { updateProfile, changePassword, updateLanguage, updateFontSize, updateShowRecentNotes } from '@/app/actions/profile'
import { toast } from 'sonner'
import { useLanguage } from '@/lib/i18n'
@@ -36,10 +38,13 @@ const LANGUAGES = [
]
export function ProfileForm({ user, userAISettings }: { user: any; userAISettings?: any }) {
const router = useRouter()
const [selectedLanguage, setSelectedLanguage] = useState(userAISettings?.preferredLanguage || 'auto')
const [isUpdatingLanguage, setIsUpdatingLanguage] = useState(false)
const [fontSize, setFontSize] = useState(userAISettings?.fontSize || 'medium')
const [isUpdatingFontSize, setIsUpdatingFontSize] = useState(false)
const [showRecentNotes, setShowRecentNotes] = useState(userAISettings?.showRecentNotes ?? false)
const [isUpdatingRecentNotes, setIsUpdatingRecentNotes] = useState(false)
const { t } = useLanguage()
const FONT_SIZES = [
@@ -117,6 +122,28 @@ export function ProfileForm({ user, userAISettings }: { user: any; userAISetting
}
}
const handleShowRecentNotesChange = async (enabled: boolean) => {
setIsUpdatingRecentNotes(true)
const previousValue = showRecentNotes
try {
const result = await updateShowRecentNotes(enabled)
if (result?.error) {
toast.error(result.error)
} else {
setShowRecentNotes(enabled)
toast.success(t('profile.recentNotesUpdateSuccess') || 'Paramètre mis à jour')
// Force full page reload to ensure settings are reloaded
window.location.href = '/settings/profile'
}
} catch (error: any) {
setShowRecentNotes(previousValue)
toast.error(error?.message || 'Erreur')
} finally {
setIsUpdatingRecentNotes(false)
}
}
return (
<div className="space-y-6">
<Card>
@@ -213,6 +240,23 @@ export function ProfileForm({ user, userAISettings }: { user: any; userAISetting
{t('profile.fontSizeDescription')}
</p>
</div>
<div className="flex items-center justify-between pt-4 border-t">
<div className="space-y-0.5">
<Label htmlFor="showRecentNotes" className="text-base font-medium">
{t('profile.showRecentNotes') || 'Afficher la section Récent'}
</Label>
<p className="text-sm text-muted-foreground">
{t('profile.showRecentNotesDescription') || 'Afficher les notes récentes (7 derniers jours) sur la page principale'}
</p>
</div>
<Switch
id="showRecentNotes"
checked={showRecentNotes}
onCheckedChange={handleShowRecentNotesChange}
disabled={isUpdatingRecentNotes}
/>
</div>
</CardContent>
</Card>