Files
Momento/memento-mobile/app/(tabs)/profile.tsx
Antigravity aeedb2846f
Some checks failed
CI / Lint, Unit Tests & Build (push) Failing after 1m21s
CI / Deploy production (on server) (push) Has been skipped
feat: App mobile Expo + API mobile dédiée
memento-mobile/ (Expo + React Native + expo-router):
- Auth: login email/password → Bearer token (expo-secure-store)
- Layout: guard auth → redirect /(auth)/login ou /(tabs)/home
- Tabs: Accueil, Carnets, Recherche, Profil
- Screens: login, home (recent notes + quick actions), notebooks list,
  note viewer (WebView HTML), search (texte), notebook detail, profile
- Design: tokens brand-accent (#A47148), ink, concrete, paper, border
- lib/config.ts: API_URL dev/prod configurable
- lib/api.ts: apiFetch avec Bearer token automatique
- lib/store.ts: Zustand auth store (login/logout/restore)

memento-note/ (API mobile dédiée):
- lib/mobile-auth.ts: createMobileToken / verifyMobileToken (HMAC-SHA256, 90j)
- POST /api/mobile/auth/login: email+password → token + user
- GET /api/mobile/auth/me: valider token, retourner profil
- GET /api/mobile/notebooks: liste carnets avec nb notes
- GET /api/mobile/notes: notes récentes (filtre par carnet optionnel)
- GET /api/mobile/notes/[id]: contenu complet d'une note
- GET /api/mobile/search: recherche fulltext titre+contenu

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-29 15:53:13 +00:00

74 lines
2.9 KiB
TypeScript

import { View, Text, TouchableOpacity, ScrollView, Alert } from 'react-native'
import { SafeAreaView } from 'react-native-safe-area-context'
import { LogOut, CreditCard, Globe } from 'lucide-react-native'
import { useAuthStore } from '@/lib/store'
const TIER_LABELS: Record<string, string> = {
FREE: 'Gratuit',
BASIC: 'Basic',
PRO: 'Pro',
BUSINESS: 'Business',
ENTERPRISE: 'Enterprise',
}
export default function ProfileScreen() {
const { user, logout } = useAuthStore()
const handleLogout = () => {
Alert.alert(
'Se déconnecter',
'Voulez-vous vraiment vous déconnecter ?',
[
{ text: 'Annuler', style: 'cancel' },
{ text: 'Déconnecter', style: 'destructive', onPress: logout },
]
)
}
return (
<SafeAreaView className="flex-1 bg-paper">
<ScrollView className="flex-1 px-5">
<Text className="text-2xl font-serif italic text-ink pt-4 pb-6">Profil</Text>
{/* User info */}
<View className="bg-white border border-border rounded-2xl p-5 mb-4">
<View className="w-14 h-14 rounded-full bg-brand/10 items-center justify-center mb-3">
<Text className="text-2xl font-bold text-brand">
{user?.name?.[0]?.toUpperCase() ?? user?.email?.[0]?.toUpperCase() ?? '?'}
</Text>
</View>
<Text className="text-[17px] font-semibold text-ink">{user?.name ?? 'Utilisateur'}</Text>
<Text className="text-[13px] text-concrete mt-0.5">{user?.email}</Text>
{user?.tier && (
<View className="mt-3 self-start bg-brand/10 px-3 py-1 rounded-full">
<Text className="text-[11px] font-bold text-brand uppercase tracking-wider">
{TIER_LABELS[user.tier] ?? user.tier}
</Text>
</View>
)}
</View>
{/* Actions */}
<View className="bg-white border border-border rounded-2xl overflow-hidden mb-4">
<TouchableOpacity className="flex-row items-center gap-3 px-4 py-3.5 border-b border-border active:bg-border/20">
<CreditCard size={18} color="#8A8A82" />
<Text className="text-[15px] text-ink flex-1">Abonnement</Text>
</TouchableOpacity>
<TouchableOpacity className="flex-row items-center gap-3 px-4 py-3.5 active:bg-border/20">
<Globe size={18} color="#8A8A82" />
<Text className="text-[15px] text-ink flex-1">Ouvrir memento-note.com</Text>
</TouchableOpacity>
</View>
<TouchableOpacity
onPress={handleLogout}
className="bg-white border border-rose-200 rounded-2xl flex-row items-center gap-3 px-4 py-3.5 active:opacity-70"
>
<LogOut size={18} color="#e11d48" />
<Text className="text-[15px] text-rose-600 font-medium">Se déconnecter</Text>
</TouchableOpacity>
</ScrollView>
</SafeAreaView>
)
}