Une application web moderne pour simplifier la gestion de vos dépenses en groupe...
✍️ Guide de projet | 📖 Documentation principale | 💻 Voir la Démo
Cliquez pour déplier ...
Ce projet illustre l'application concrète de compétences techniques avancées en développement web full-stack à l'aide de frameworks tel que Symfony :
- 🎯 Architecture MVC avec Symfony 7.4
- 🔄 Doctrine ORM pour la gestion de la persistance (doc)
- 🛡️ Services métier pour une logique réutilisable (doc)
- 📦 DTOs pour le transfert de données structurées
- ✅ Validation côté serveur avec contraintes (doc)
- 🔐 Security Component pour l'authentification (doc)
- Templates Twig modulaires (doc)
- Dark Mode avec gestion d'état persistant
- Responsive Design (320px → ∞)
- JavaScript Vanilla moderne (ES6+)
- Animations CSS3 pour fluidité
- PostgreSQL avec schéma relationnel optimisé
- Migrations versionnées (doc)
- Relations complexes (OneToMany, ManyToMany)
- Notion de Soft Delete
La gestion des dépenses partagées (colocation, voyages, sorties) génère bien souvent :
- ❌ Calculs manuels fastidieux
- ❌ Incompréhensions sur les remboursements
- ❌ Manque de transparence
- ❌ Absence d'historique centralisé
✅ Automatisation des calculs pour l'équilibre des dépenses
✅ Transparence totale sur toutes les dépenses
✅ Collaboration avec système de rôles
✅ Historique permanent et accessible pour tous les membres
✅ Interface agréable, intuitive et multi-plateforme (responsive...)
| Contexte | Utilisation |
|---|---|
| Colocation | Courses, loyer, factures partagées |
| Voyage | Suivi des dépenses courantes en temps réel |
| Sorties | Restaurants, activités entre amis |
| Toute dépense de groupe | Randonnées , Organisation de fêtes... |
+count/
├── 📁 src/
│ ├── Controller/ # Contrôleurs MVC
│ ├── Entity/ # Modèles Doctrine
│ ├── Repository/ # Accès données
│ ├── Service/ # Logique métier
│ ├── Form/ # Types de formulaires
│ └── Security/ # Authentification
│
├── 📁 templates/
│ ├── _layouts/ # Layouts de base
│ ├── _components/ # Composants réutilisables
│ └── wallets/ # Pages wallets
│
├── 📁 public/
│ ├── styles/ # CSS (main, forms, wallets...)
│ └── scripts/ # JavaScript
│
└── 📁 migrations/ # Migrations BDD
┌─────────────────────┐
│ PRÉSENTATION │ Controller + Twig
├─────────────────────┤
│ MÉTIER │ Services + DTOs
├─────────────────────┤
│ PERSISTANCE │ Entities + Repositories
├─────────────────────┤
│ BASE DE DONNÉES │ PostgreSQL
└─────────────────────┘
| Technologie | Version | Utilisation |
|---|---|---|
| 7.4 LTS | Framework PHP full-stack (doc) | |
| 8.3 | Langage backend | |
| 2.4 | ORM pour abstraction BDD (doc) | |
| 2.* | Gestionnaire de dépendances PHP |
| Technologie | Utilisation |
|---|---|
| Moteur de templates sécurisé (doc) | |
| CSS3 | Variables, Grid, Flexbox, Animations |
| JavaScript ES6+ | DOM moderne, Async/Await, Modules |
| FontAwesome | Bibliothèque d'icônes vectorielles |
| Technologie | Justification |
|---|---|
| SGBD relationnel assez robuste avec prise en charge des transactions ACID (doc) |
Entities & Doctrine ORM
Les entités représentent les modèles de données mappés vers PostgreSQL.
Entités principales :
- User : Utilisateurs de l'application
- Wallet : Portefeuilles partagés
- XUserWallet : Table de jonction avec rôles
- Expense : Dépenses individuelles
#[ORM\Entity(repositoryClass: WalletRepository::class)]
class Wallet
{
#[ORM\Id]
#[ORM\Column(type: 'uuid')]
private ?Uuid $uid = null;
#[ORM\Column(length: 100)]
private ?string $label = null;
#[ORM\OneToMany(mappedBy: 'wallet', targetEntity: Expense::class)]
private Collection $expenses;
}Services Métier
Les services encapsulent la logique métier réutilisable.
Services implémentés :
WalletService: Gestion des walletsExpenseService: Gestion des dépensesBalanceService: Calcul des équilibresUserService: Gestion utilisateurs
class WalletService
{
public function __construct(
private WalletRepository $repository,
private EntityManagerInterface $em
) {}
public function create(User $owner, string $label): Wallet
{
$wallet = new Wallet();
$wallet->setLabel($label);
$wallet->setOwner($owner);
$this->em->persist($wallet);
$this->em->flush();
return $wallet;
}
}Form Types
Les Form Types gèrent les formulaires de manière objet.
class ExpenseType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('amount', MoneyType::class)
->add('description', TextType::class)
->add('icon', ChoiceType::class, [
'choices' => [
'Restaurant' => 'fa-utensils',
'Transport' => 'fa-car',
// ...
]
]);
}
}Templates Twig
Architecture modulaire avec héritage et composants.
{# Layout de base #}
{% extends '_layouts/base.html.twig' %}
{% block content %}
<h1>{{ wallet.label }}</h1>
{% include '_components/menu.html.twig' %}
{% for expense in expenses %}
{# ... #}
{% endfor %}
{% endblock %}Fixtures de Test
Données de test cohérentes pour développement.
class UserFixtures extends Fixture
{
public function load(ObjectManager $manager): void
{
for ($i = 1; $i <= 10; $i++) {
$user = new User();
$user->setEmail("user$i@test.com");
// ...
$manager->persist($user);
}
$manager->flush();
}
}php bin/console doctrine:fixtures:loadSécurité
- Authentification par session avec Security Component
- Hachage bcrypt des mots de passe
- CSRF Protection sur tous les formulaires
class WalletVoter extends Voter
{
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
{
$user = $token->getUser();
return match($attribute) {
'view' => $this->canView($subject, $user),
'edit' => $this->canEdit($subject, $user),
default => false
};
}
}Voir les détails
Inscription
- Formulaire avec validation email unique
- Hachage automatique du mot de passe
- Choix du genre et avatar par défaut
Connexion
- Authentification par email/mot de passe
- Système de sessions sécurisées
- Redirection intelligente après login
Profil Utilisateur
- Modification des informations
- Changement d'avatar (12 avatars 3D disponibles)
- Statistiques personnelles (wallets créés, dépenses, etc.)
Voir les détails
Création de Wallet
- Formulaire simple (nom du wallet)
- Génération automatique d'un UUID unique
- Utilisateur créateur = Owner automatiquement
Liste des Wallets
- Vue d'ensemble avec cartes modernes
- Affichage du solde total
- Badge rôle (Admin/Member)
- Animation au survol
Détails d'un Wallet
- Solde total en tête de page
- Liste paginée des dépenses
- Accordéon pour équilibres à régler
- Actions selon les droits (edit/delete/invite)
Voir les détails
Ajout de Dépense
- Montant en euros (converti en centimes)
- Description de la dépense
- Choix de catégorie avec icône (28 catégories)
- Enregistrement avec date automatique
Affichage des Dépenses
- Liste chronologique inversée
- Icône de catégorie colorée
- Montant formaté (couleur verte si c'est vous)
- Pagination (10 par page)
Actions sur Dépenses
- 👁️ Voir détails : Modal avec infos complètes
- 🗑️ Supprimer (admin seulement) : Confirmation requise
Voir les détails
3 Niveaux de Rôles
| Rôle | Permissions |
|---|---|
| 👑 Owner/Admin | Tous les droits + suppression wallet |
| Admin | Gestion membres, dépenses, paramètres |
| User | Lecture seule + ajout dépenses |
Gestion des Membres
- Invitation (sélection utilisateur)
- Attribution du rôle à l'invitation
- Promotion/rétrogradation (admin → member)
- Exclusion avec choix (garder/supprimer les dépenses)
Interface Membres
- Modal listant tous les membres
- Avatar + nom + email + rôle
- Actions contextuelles selon droits
Voir les détails
Algorithme d'Équilibrage
L'application calcule automatiquement qui doit combien à qui pour équilibrer les comptes.
Principe :
- Calcul du total des dépenses
- Calcul de la part équitable par personne
- Détermination des débiteurs et créditeurs
- Optimisation du nombre de transactions
Exemple :
Alice a payé : 100€
Bob a payé : 50€
Charlie a payé : 0€
Total : 150€ → Part/personne : 50€
Résultat :
- Bob doit 0€ à Alice (déjà à l'équilibre relatif)
- Charlie doit 50€ à Alice
Affichage
- Accordéon dépliable "Voir les équilibres"
- Instructions claires : "X rembourse Y"
- Montants colorés (vert = vous recevez, rouge = vous devez)
- Bouton "Solder tous les comptes" (admin)
Voir les détails
Design System
- Couleurs : Orange vibrant (#ff5722) + dégradés
- Typographie : Poppins (Google Fonts)
- Cards : Glassmorphism avec backdrop-filter
- Animations : Transitions fluides 0.3s cubic-bezier
Composants Réutilisables
- Header avec logo animé (spin-pause)
- Menu FAB flottant (Floating Action Button)
- Flash messages avec auto-dismiss (5s)
- Modals avec fond blur
- Boutons avec hover effects
Interactions
- Smooth scroll sur ancres
- Animations au scroll (Intersection Observer)
- Compteurs animés (statistiques)
- Floating cards avec parallax
Interface utilisateur personnalisée...
![]()
Voir les détails
Implémentation
- Toggle via bouton flottant (bas droite)
- Persistance dans localStorage
- Variables CSS dynamiques
- Transition fluide 0.3s
Activation
// Au chargement
const theme = localStorage.getItem('theme') || 'light';
document.documentElement.setAttribute('data-theme', theme);
// Au clic
document.documentElement.setAttribute('data-theme', 'dark');
localStorage.setItem('theme', 'dark');CSS
:root {
--bg-primary: #f0f2f5;
--text-dark: #212020;
}
[data-theme="dark"] {
--bg-primary: #0f172a;
--text-dark: #e2e8f0;
}Voir les détails
Breakpoints
| Largeur | Adaptations |
|---|---|
| ≥ 1200px | Layout complet desktop |
| 768-1199px | Tablette, colonnes réduites |
| 480-767px | Mobile, stack vertical |
| 320-479px | Très petit mobile, optimisé |
Techniques
- Flexbox pour layouts flexibles
- CSS Grid pour grilles responsives
- Media queries mobile-first
- Touch-friendly (boutons 44px min)
- PHP 8.2+
- Composer 2.6+
- PostgreSQL 15+
- Symfony CLI (optionnel)
# 1. Cloner le projet
# 2. Installer les dépendances
composer install
# 3. Configurer la base de données
# Éditer .env.local
DATABASE_URL="postgresql://user:password@127.0.0.1:5432/pluscount?serverVersion=15&charset=utf8"
# 4. Créer la base et exécuter les migrations
php bin/console doctrine:database:create
php bin/console doctrine:migrations:migrate
# 5. (Optionnel) Charger les fixtures
php bin/console doctrine:fixtures:load
# 6. Lancer le serveur
symfony serve
# ou
php -S localhost:8000 -t public/# config/packages/doctrine.yaml
doctrine:
dbal:
url: '%env(resolve:DATABASE_URL)%'
orm:
auto_mapping: true
mappings:
App:
is_bundle: false
dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity'- Notifications email (invitations, remboursements)
- Export PDF des dépenses
- Recherche et filtres avancés
- Graphiques de répartition (Chart.js)
- Application mobile (React Native / Flutter)
- API REST publique
- Intégration paiement (Stripe)
- Multi-langues (i18n)
- Suggestions IA basées sur historique
- Synchronisation bancaire
- Communauté et partage de templates
- Budgets et objectifs d'épargne
Les contributions sont les bienvenues !
- Fork le projet
- Créer une branche (
git checkout -b feature/AmazingFeature) - Commit les changements (
git commit -m 'Add AmazingFeature') - Push vers la branche (
git push origin feature/AmazingFeature) - Ouvrir une Pull Request
Ce projet est sous licence _.
- Équipe pédagogique : Adrien Gras & Yoan Thirion
- Communauté Symfony pour la documentation super exhaustive.
- Unsplash pour les images libres de droits
- FontAwesome pour les icônes vectorielles
Développé avec passion 🤩 par un aventurier surnommé Overlord 😉















