feat: add mobile application structure with emotion picker and API integration

- Added favicon and icon assets for the mobile app.
- Implemented EmotionPicker component for selecting emotions with child options.
- Created hooks for fetching emotions, feeds, and rapport data.
- Established API service for handling requests and authentication.
- Integrated Zustand for state management of user authentication.
- Defined color palette for the application.
- Set up TypeScript types for various entities including User, Emotion, and Feed.
- Configured Babel and TypeScript for the mobile project.
- Added package.json with necessary dependencies for Expo and React Native.
This commit is contained in:
Azmog
2026-04-15 16:09:20 +02:00
parent 88f5863cb5
commit bfd35905c9
60 changed files with 2437 additions and 42 deletions
@@ -0,0 +1,83 @@
import Card from '@/components/ui/Card';
import { Phone } from 'lucide-react';
export default function ContactsUrgencePage() {
const contacts = [
{
name: 'Numéro national de prévention du suicide',
number: '3114',
description:
'Numéro national disponible 24h/24 et 7j/7. Appel gratuit et confidentiel pour les personnes en détresse psychologique et leur entourage.',
},
{
name: 'SOS Amitié',
number: '09 72 39 40 50',
description:
'Écoute et soutien pour les personnes en souffrance, solitude ou détresse morale. Service disponible 24h/24.',
},
{
name: 'Fil Santé Jeunes',
number: '0 800 235 236',
description:
'Ligne d\u2019écoute gratuite et anonyme pour les jeunes de 12 à 25 ans. Du lundi au dimanche de 9h à 23h.',
},
{
name: 'SAMU',
number: '15',
description:
'Service d\u2019aide médicale urgente. En cas d\u2019urgence vitale, appelez immédiatement le 15 ou le 112.',
},
{
name: 'SOS Médecins',
number: '3624',
description:
'Service de médecins disponible pour des consultations à domicile, 24h/24 et 7j/7.',
},
];
return (
<div className="max-w-3xl mx-auto px-4 py-12">
<h1 className="font-display text-4xl font-bold text-gray-900 dark:text-white mb-4">
Contacts d&apos;urgence
</h1>
<p className="text-lg text-gray-500 dark:text-gray-400 mb-8">
Si vous ou un proche traversez une période difficile, n&apos;hésitez pas à
contacter l&apos;un de ces services. Vous n&apos;êtes pas seul(e).
</p>
<div className="space-y-4">
{contacts.map((contact) => (
<Card key={contact.number}>
<div className="flex items-start gap-4">
<div className="flex-shrink-0 w-12 h-12 rounded-full bg-red-50 dark:bg-red-950/50 flex items-center justify-center">
<Phone size={20} className="text-red-600 dark:text-red-400" />
</div>
<div className="flex-1 min-w-0">
<h2 className="font-display text-lg font-semibold text-gray-900 dark:text-white mb-1">
{contact.name}
</h2>
<a
href={`tel:${contact.number.replace(/\s/g, '')}`}
className="inline-block text-xl font-bold text-malachite-600 dark:text-malachite-400 mb-2 hover:underline"
>
{contact.number}
</a>
<p className="text-sm text-gray-500 dark:text-gray-400 leading-relaxed">
{contact.description}
</p>
</div>
</div>
</Card>
))}
</div>
<Card className="mt-8 bg-red-50 dark:bg-red-950/30 border-red-100 dark:border-red-900">
<p className="text-sm text-red-700 dark:text-red-400 text-center leading-relaxed">
<strong>En cas d&apos;urgence vitale</strong>, appelez immédiatement le{' '}
<strong>15</strong> (SAMU) ou le <strong>112</strong> (numéro d&apos;urgence
européen).
</p>
</Card>
</div>
);
}
@@ -2,6 +2,7 @@
import { useParams } from 'next/navigation';
import Link from 'next/link';
import Image from 'next/image';
import { ArrowLeft, Calendar, User } from 'lucide-react';
import { useFeed } from '@/hooks/useFeeds';
import Skeleton from '@/components/ui/Skeleton';
@@ -52,10 +53,13 @@ export default function ArticlePage() {
{feed.image_url && (
<div className="relative w-full h-64 sm:h-80 rounded-2xl overflow-hidden bg-gray-100 dark:bg-gray-800 mb-8">
<img
<Image
src={feed.image_url}
alt={feed.titre}
width={800}
height={400}
className="w-full h-full object-cover"
unoptimized
/>
</div>
)}
@@ -1,6 +1,7 @@
'use client';
import Link from 'next/link';
import Image from 'next/image';
import { BookOpen, Calendar } from 'lucide-react';
import { useFeeds } from '@/hooks/useFeeds';
import Card from '@/components/ui/Card';
@@ -39,10 +40,13 @@ export default function InformationsPage() {
<Card hover className="h-full">
{feed.image_url && (
<div className="relative w-full h-48 mb-4 rounded-xl overflow-hidden bg-gray-100 dark:bg-gray-800">
<img
<Image
src={feed.image_url}
alt={feed.titre}
width={800}
height={400}
className="w-full h-full object-cover"
unoptimized
/>
</div>
)}
@@ -0,0 +1,73 @@
import Card from '@/components/ui/Card';
export default function MentionsLegalesPage() {
return (
<div className="max-w-3xl mx-auto px-4 py-12">
<h1 className="font-display text-4xl font-bold text-gray-900 dark:text-white mb-8">
Mentions légales
</h1>
<div className="space-y-6">
<Card>
<h2 className="font-display text-xl font-semibold text-gray-900 dark:text-white mb-3">
Éditeur de l&apos;application
</h2>
<p className="text-gray-600 dark:text-gray-400 leading-relaxed">
CESIZen est une application développée dans le cadre d&apos;un projet
pédagogique au sein de{' '}
<strong>CESI École d&apos;Ingénieurs</strong>. Cette application est
réalisée à but éducatif et n&apos;a pas de vocation commerciale.
</p>
</Card>
<Card>
<h2 className="font-display text-xl font-semibold text-gray-900 dark:text-white mb-3">
Hébergement
</h2>
<p className="text-gray-600 dark:text-gray-400 leading-relaxed">
L&apos;application est hébergée dans le cadre de l&apos;infrastructure
pédagogique de CESI. Les données sont stockées sur des serveurs
sécurisés situés en France.
</p>
</Card>
<Card>
<h2 className="font-display text-xl font-semibold text-gray-900 dark:text-white mb-3">
Propriété intellectuelle
</h2>
<p className="text-gray-600 dark:text-gray-400 leading-relaxed">
L&apos;ensemble des contenus présents sur CESIZen (textes, images,
graphismes, logo, icônes) sont la propriété exclusive de leurs auteurs
respectifs et sont protégés par les lois françaises et internationales
relatives à la propriété intellectuelle.
</p>
</Card>
<Card>
<h2 className="font-display text-xl font-semibold text-gray-900 dark:text-white mb-3">
Responsabilité
</h2>
<p className="text-gray-600 dark:text-gray-400 leading-relaxed">
CESIZen est un outil de suivi du bien-être et ne se substitue en aucun
cas à un avis médical professionnel. En cas de détresse psychologique,
veuillez contacter les services d&apos;urgence ou un professionnel de
santé.
</p>
</Card>
<Card>
<h2 className="font-display text-xl font-semibold text-gray-900 dark:text-white mb-3">
Contact
</h2>
<p className="text-gray-600 dark:text-gray-400 leading-relaxed">
Pour toute question relative aux mentions légales, vous pouvez nous
contacter via l&apos;adresse suivante :{' '}
<span className="text-malachite-600 dark:text-malachite-400">
contact@cesizen.fr
</span>
</p>
</Card>
</div>
</div>
);
}
@@ -0,0 +1,105 @@
import Card from '@/components/ui/Card';
export default function PolitiqueConfidentialitePage() {
return (
<div className="max-w-3xl mx-auto px-4 py-12">
<h1 className="font-display text-4xl font-bold text-gray-900 dark:text-white mb-8">
Politique de confidentialité
</h1>
<div className="space-y-6">
<Card>
<h2 className="font-display text-xl font-semibold text-gray-900 dark:text-white mb-3">
Conformité RGPD
</h2>
<p className="text-gray-600 dark:text-gray-400 leading-relaxed">
CESIZen s&apos;engage à respecter le Règlement Général sur la Protection
des Données (RGPD) et la loi Informatique et Libertés. La protection
de vos données personnelles est une priorité.
</p>
</Card>
<Card>
<h2 className="font-display text-xl font-semibold text-gray-900 dark:text-white mb-3">
Données collectées
</h2>
<p className="text-gray-600 dark:text-gray-400 leading-relaxed mb-3">
Dans le cadre de l&apos;utilisation de CESIZen, les données suivantes
sont collectées :
</p>
<ul className="list-disc list-inside text-gray-600 dark:text-gray-400 space-y-1">
<li>Adresse e-mail</li>
<li>Nom et prénom</li>
<li>Données relatives aux émotions enregistrées</li>
</ul>
</Card>
<Card>
<h2 className="font-display text-xl font-semibold text-gray-900 dark:text-white mb-3">
Finalité du traitement
</h2>
<p className="text-gray-600 dark:text-gray-400 leading-relaxed">
Ces données sont collectées uniquement dans le but de fournir un suivi
personnalisé du bien-être émotionnel. Elles ne sont ni vendues, ni
partagées avec des tiers à des fins commerciales.
</p>
</Card>
<Card>
<h2 className="font-display text-xl font-semibold text-gray-900 dark:text-white mb-3">
Durée de conservation
</h2>
<p className="text-gray-600 dark:text-gray-400 leading-relaxed">
Les données personnelles sont conservées pendant toute la durée
d&apos;utilisation du compte. En cas de suppression du compte, les
données sont effacées dans un délai de 30 jours.
</p>
</Card>
<Card>
<h2 className="font-display text-xl font-semibold text-gray-900 dark:text-white mb-3">
Sécurité des données
</h2>
<p className="text-gray-600 dark:text-gray-400 leading-relaxed">
Les données sont chiffrées en transit (HTTPS) et au repos. Les mots de
passe sont hachés avec des algorithmes sécurisés. L&apos;accès aux
données est strictement limité aux personnes habilitées.
</p>
</Card>
<Card>
<h2 className="font-display text-xl font-semibold text-gray-900 dark:text-white mb-3">
Vos droits
</h2>
<p className="text-gray-600 dark:text-gray-400 leading-relaxed mb-3">
Conformément au RGPD, vous disposez des droits suivants :
</p>
<ul className="list-disc list-inside text-gray-600 dark:text-gray-400 space-y-1">
<li>
<strong>Droit d&apos;accès :</strong> obtenir une copie de vos
données personnelles
</li>
<li>
<strong>Droit de rectification :</strong> corriger des données
inexactes ou incomplètes
</li>
<li>
<strong>Droit de suppression :</strong> demander l&apos;effacement
de vos données personnelles
</li>
<li>
<strong>Droit à la portabilité :</strong> récupérer vos données dans
un format structuré
</li>
</ul>
<p className="text-gray-600 dark:text-gray-400 leading-relaxed mt-3">
Pour exercer ces droits, contactez-nous à l&apos;adresse :{' '}
<span className="text-malachite-600 dark:text-malachite-400">
contact@cesizen.fr
</span>
</p>
</Card>
</div>
</div>
);
}