Add utilities, constants, sample data and quick start guide
- Add helper functions (formatCurrency, formatDate, validation, etc.) - Add constants (colors, spacing, error messages, etc.) - Add sample data generator for testing - Add QUICKSTART.md for quick setup - Update app.json with proper configuration
This commit is contained in:
149
QUICKSTART.md
Normal file
149
QUICKSTART.md
Normal file
@@ -0,0 +1,149 @@
|
||||
# 🚀 Démarrage rapide - WalletTracker
|
||||
|
||||
Guide pour lancer l'application en 5 minutes.
|
||||
|
||||
## Étape 1 : Vérifier les prérequis
|
||||
|
||||
```bash
|
||||
# Vérifier Node.js (v16+)
|
||||
node --version
|
||||
|
||||
# Vérifier npm
|
||||
npm --version
|
||||
```
|
||||
|
||||
## Étape 2 : Installer les dépendances
|
||||
|
||||
```bash
|
||||
cd WalletTracker
|
||||
npm install
|
||||
```
|
||||
|
||||
## Étape 3 : Configurer Firebase
|
||||
|
||||
### Option A : Configuration rapide (pour tester)
|
||||
|
||||
1. Allez sur https://console.firebase.google.com/
|
||||
2. Créez un nouveau projet "WalletTracker"
|
||||
3. Ajoutez une application Web
|
||||
4. Copiez les identifiants dans `src/config/firebase.ts`
|
||||
|
||||
### Option B : Configuration complète
|
||||
|
||||
Suivez le guide détaillé dans `FIREBASE_SETUP.md`
|
||||
|
||||
## Étape 4 : Lancer l'application
|
||||
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
Vous verrez un QR code s'afficher dans le terminal.
|
||||
|
||||
## Étape 5 : Tester sur votre téléphone
|
||||
|
||||
### Sur iOS ou Android :
|
||||
|
||||
1. Téléchargez **Expo Go** depuis l'App Store ou Google Play
|
||||
2. Ouvrez Expo Go
|
||||
3. Scannez le QR code affiché dans le terminal
|
||||
4. L'application se chargera automatiquement
|
||||
|
||||
### Sur émulateur :
|
||||
|
||||
**iOS (Mac uniquement)** :
|
||||
```bash
|
||||
npm run ios
|
||||
```
|
||||
|
||||
**Android** :
|
||||
```bash
|
||||
npm run android
|
||||
```
|
||||
|
||||
## 🎉 C'est prêt !
|
||||
|
||||
Vous devriez voir l'écran de connexion de WalletTracker.
|
||||
|
||||
### Première utilisation :
|
||||
|
||||
1. Cliquez sur **"Créer un compte"**
|
||||
2. Remplissez le formulaire :
|
||||
- Nom : Votre nom
|
||||
- Email : votre@email.com
|
||||
- Mot de passe : minimum 6 caractères
|
||||
3. Cliquez sur **"Créer mon compte"**
|
||||
4. Vous êtes redirigé vers le Dashboard !
|
||||
|
||||
### Ajouter votre première transaction :
|
||||
|
||||
1. Cliquez sur le bouton **"Dépense"** ou **"Revenu"**
|
||||
2. Entrez le montant
|
||||
3. Sélectionnez une catégorie
|
||||
4. Ajoutez une note (optionnel)
|
||||
5. Cliquez sur **"Ajouter la transaction"**
|
||||
|
||||
## 📱 Commandes utiles
|
||||
|
||||
```bash
|
||||
# Lancer l'application
|
||||
npm start
|
||||
|
||||
# Lancer sur iOS
|
||||
npm run ios
|
||||
|
||||
# Lancer sur Android
|
||||
npm run android
|
||||
|
||||
# Lancer sur le web
|
||||
npm run web
|
||||
|
||||
# Nettoyer le cache
|
||||
npm start -- --clear
|
||||
```
|
||||
|
||||
## 🐛 Problèmes courants
|
||||
|
||||
### L'application ne se lance pas
|
||||
|
||||
```bash
|
||||
# Nettoyer et réinstaller
|
||||
rm -rf node_modules
|
||||
npm install
|
||||
npm start -- --clear
|
||||
```
|
||||
|
||||
### Erreur Firebase
|
||||
|
||||
Vérifiez que vous avez bien :
|
||||
- Copié les identifiants Firebase dans `src/config/firebase.ts`
|
||||
- Activé Authentication (Email/Password) dans Firebase Console
|
||||
- Créé la base de données Firestore
|
||||
|
||||
### QR code ne fonctionne pas
|
||||
|
||||
- Assurez-vous que votre téléphone et ordinateur sont sur le même réseau Wi-Fi
|
||||
- Essayez de scanner avec l'appareil photo puis ouvrir avec Expo Go
|
||||
- Utilisez le mode tunnel : `npm start -- --tunnel`
|
||||
|
||||
## 📚 Prochaines étapes
|
||||
|
||||
- Lisez le `README.md` pour comprendre l'architecture
|
||||
- Consultez `FIREBASE_SETUP.md` pour la configuration complète
|
||||
- Utilisez `TESTING.md` pour tester toutes les fonctionnalités
|
||||
|
||||
## 💡 Conseils
|
||||
|
||||
- **Développement** : Utilisez `npm start` et Expo Go pour un rechargement rapide
|
||||
- **Production** : Utilisez EAS Build pour créer des binaires iOS/Android
|
||||
- **Débogage** : Secouez votre téléphone pour ouvrir le menu de développement
|
||||
|
||||
## 🆘 Besoin d'aide ?
|
||||
|
||||
- Documentation Expo : https://docs.expo.dev/
|
||||
- Documentation Firebase : https://firebase.google.com/docs
|
||||
- React Native : https://reactnative.dev/docs/getting-started
|
||||
|
||||
---
|
||||
|
||||
**Bon développement ! 💪**
|
||||
161
src/utils/constants.ts
Normal file
161
src/utils/constants.ts
Normal file
@@ -0,0 +1,161 @@
|
||||
/**
|
||||
* Constantes utilisées dans l'application
|
||||
*/
|
||||
|
||||
// Couleurs principales
|
||||
export const COLORS = {
|
||||
primary: '#4A90E2',
|
||||
secondary: '#6C757D',
|
||||
success: '#52C41A',
|
||||
danger: '#FF6B6B',
|
||||
warning: '#FFA07A',
|
||||
info: '#13C2C2',
|
||||
light: '#F8F9FA',
|
||||
dark: '#333',
|
||||
white: '#FFF',
|
||||
gray: '#999',
|
||||
border: '#E0E0E0'
|
||||
};
|
||||
|
||||
// Couleurs des catégories par défaut
|
||||
export const CATEGORY_COLORS = {
|
||||
// Dépenses
|
||||
courses: '#FF6B6B',
|
||||
logement: '#4ECDC4',
|
||||
transport: '#45B7D1',
|
||||
loisirs: '#FFA07A',
|
||||
restaurant: '#98D8C8',
|
||||
sante: '#F7DC6F',
|
||||
vetements: '#BB8FCE',
|
||||
education: '#85C1E2',
|
||||
abonnements: '#F8B739',
|
||||
autre: '#95A5A6',
|
||||
|
||||
// Revenus
|
||||
salaire: '#52C41A',
|
||||
freelance: '#13C2C2',
|
||||
investissement: '#1890FF',
|
||||
cadeau: '#EB2F96',
|
||||
autreRevenu: '#52C41A'
|
||||
};
|
||||
|
||||
// Tailles de police
|
||||
export const FONT_SIZES = {
|
||||
xs: 11,
|
||||
sm: 12,
|
||||
md: 14,
|
||||
lg: 16,
|
||||
xl: 18,
|
||||
xxl: 24,
|
||||
xxxl: 32
|
||||
};
|
||||
|
||||
// Espacements
|
||||
export const SPACING = {
|
||||
xs: 4,
|
||||
sm: 8,
|
||||
md: 12,
|
||||
lg: 16,
|
||||
xl: 24,
|
||||
xxl: 32
|
||||
};
|
||||
|
||||
// Rayons de bordure
|
||||
export const BORDER_RADIUS = {
|
||||
sm: 8,
|
||||
md: 12,
|
||||
lg: 16,
|
||||
xl: 20,
|
||||
round: 999
|
||||
};
|
||||
|
||||
// Formats de date
|
||||
export const DATE_FORMATS = {
|
||||
short: 'DD/MM/YYYY',
|
||||
medium: 'DD MMM YYYY',
|
||||
long: 'DD MMMM YYYY',
|
||||
full: 'dddd DD MMMM YYYY'
|
||||
};
|
||||
|
||||
// Messages d'erreur
|
||||
export const ERROR_MESSAGES = {
|
||||
network: 'Erreur de connexion. Vérifiez votre connexion Internet.',
|
||||
auth: {
|
||||
invalidEmail: 'Adresse email invalide',
|
||||
weakPassword: 'Le mot de passe doit contenir au moins 6 caractères',
|
||||
emailInUse: 'Cette adresse email est déjà utilisée',
|
||||
userNotFound: 'Aucun compte trouvé avec cette adresse email',
|
||||
wrongPassword: 'Mot de passe incorrect',
|
||||
tooManyRequests: 'Trop de tentatives. Veuillez réessayer plus tard.'
|
||||
},
|
||||
transaction: {
|
||||
invalidAmount: 'Montant invalide',
|
||||
missingCategory: 'Veuillez sélectionner une catégorie',
|
||||
addFailed: 'Impossible d\'ajouter la transaction',
|
||||
updateFailed: 'Impossible de mettre à jour la transaction',
|
||||
deleteFailed: 'Impossible de supprimer la transaction'
|
||||
},
|
||||
subscription: {
|
||||
invalidName: 'Nom invalide',
|
||||
invalidAmount: 'Montant invalide',
|
||||
invalidDate: 'Date invalide',
|
||||
addFailed: 'Impossible d\'ajouter l\'abonnement',
|
||||
updateFailed: 'Impossible de mettre à jour l\'abonnement',
|
||||
deleteFailed: 'Impossible de supprimer l\'abonnement'
|
||||
}
|
||||
};
|
||||
|
||||
// Messages de succès
|
||||
export const SUCCESS_MESSAGES = {
|
||||
auth: {
|
||||
signupSuccess: 'Compte créé avec succès',
|
||||
loginSuccess: 'Connexion réussie',
|
||||
logoutSuccess: 'Déconnexion réussie'
|
||||
},
|
||||
transaction: {
|
||||
addSuccess: 'Transaction ajoutée avec succès',
|
||||
updateSuccess: 'Transaction mise à jour',
|
||||
deleteSuccess: 'Transaction supprimée'
|
||||
},
|
||||
subscription: {
|
||||
addSuccess: 'Abonnement ajouté avec succès',
|
||||
updateSuccess: 'Abonnement mis à jour',
|
||||
deleteSuccess: 'Abonnement supprimé'
|
||||
}
|
||||
};
|
||||
|
||||
// Limites
|
||||
export const LIMITS = {
|
||||
maxTransactionsPerPage: 50,
|
||||
maxCategoriesPerUser: 50,
|
||||
maxSubscriptionsPerUser: 100,
|
||||
maxNoteLength: 500,
|
||||
minPasswordLength: 6,
|
||||
maxImageSize: 5 * 1024 * 1024 // 5 MB
|
||||
};
|
||||
|
||||
// Fréquences d'abonnement
|
||||
export const SUBSCRIPTION_FREQUENCIES = [
|
||||
{ value: 'daily', label: 'Quotidien' },
|
||||
{ value: 'weekly', label: 'Hebdomadaire' },
|
||||
{ value: 'monthly', label: 'Mensuel' },
|
||||
{ value: 'yearly', label: 'Annuel' }
|
||||
];
|
||||
|
||||
// Jours de rappel par défaut
|
||||
export const DEFAULT_REMINDER_DAYS = 3;
|
||||
|
||||
// Clés de stockage AsyncStorage
|
||||
export const STORAGE_KEYS = {
|
||||
user: '@wallettracker_user',
|
||||
theme: '@wallettracker_theme',
|
||||
language: '@wallettracker_language'
|
||||
};
|
||||
|
||||
// URLs utiles
|
||||
export const URLS = {
|
||||
privacyPolicy: 'https://example.com/privacy',
|
||||
termsOfService: 'https://example.com/terms',
|
||||
support: 'https://example.com/support',
|
||||
github: 'https://github.com/yourusername/wallettracker'
|
||||
};
|
||||
251
src/utils/helpers.ts
Normal file
251
src/utils/helpers.ts
Normal file
@@ -0,0 +1,251 @@
|
||||
/**
|
||||
* Fonctions utilitaires pour l'application
|
||||
*/
|
||||
|
||||
/**
|
||||
* Formate un montant en euros
|
||||
*/
|
||||
export const formatCurrency = (amount: number): string => {
|
||||
return new Intl.NumberFormat('fr-FR', {
|
||||
style: 'currency',
|
||||
currency: 'EUR'
|
||||
}).format(amount);
|
||||
};
|
||||
|
||||
/**
|
||||
* Formate une date
|
||||
*/
|
||||
export const formatDate = (
|
||||
date: Date,
|
||||
format: 'short' | 'medium' | 'long' = 'medium'
|
||||
): string => {
|
||||
const options: Intl.DateTimeFormatOptions = {
|
||||
short: { day: '2-digit', month: '2-digit', year: 'numeric' },
|
||||
medium: { day: '2-digit', month: 'short', year: 'numeric' },
|
||||
long: { day: '2-digit', month: 'long', year: 'numeric' }
|
||||
}[format];
|
||||
|
||||
return new Intl.DateTimeFormat('fr-FR', options).format(date);
|
||||
};
|
||||
|
||||
/**
|
||||
* Formate une date relative (il y a X jours)
|
||||
*/
|
||||
export const formatRelativeDate = (date: Date): string => {
|
||||
const now = new Date();
|
||||
const diffInMs = now.getTime() - date.getTime();
|
||||
const diffInDays = Math.floor(diffInMs / (1000 * 60 * 60 * 24));
|
||||
|
||||
if (diffInDays === 0) return "Aujourd'hui";
|
||||
if (diffInDays === 1) return 'Hier';
|
||||
if (diffInDays < 7) return `Il y a ${diffInDays} jours`;
|
||||
if (diffInDays < 30) {
|
||||
const weeks = Math.floor(diffInDays / 7);
|
||||
return `Il y a ${weeks} semaine${weeks > 1 ? 's' : ''}`;
|
||||
}
|
||||
if (diffInDays < 365) {
|
||||
const months = Math.floor(diffInDays / 30);
|
||||
return `Il y a ${months} mois`;
|
||||
}
|
||||
const years = Math.floor(diffInDays / 365);
|
||||
return `Il y a ${years} an${years > 1 ? 's' : ''}`;
|
||||
};
|
||||
|
||||
/**
|
||||
* Obtient le nom du mois en français
|
||||
*/
|
||||
export const getMonthName = (date: Date, format: 'long' | 'short' = 'long'): string => {
|
||||
return new Intl.DateTimeFormat('fr-FR', {
|
||||
month: format,
|
||||
year: 'numeric'
|
||||
}).format(date);
|
||||
};
|
||||
|
||||
/**
|
||||
* Calcule le nombre de jours entre deux dates
|
||||
*/
|
||||
export const daysBetween = (date1: Date, date2: Date): number => {
|
||||
const diffInMs = Math.abs(date2.getTime() - date1.getTime());
|
||||
return Math.ceil(diffInMs / (1000 * 60 * 60 * 24));
|
||||
};
|
||||
|
||||
/**
|
||||
* Vérifie si une date est dans le mois en cours
|
||||
*/
|
||||
export const isCurrentMonth = (date: Date): boolean => {
|
||||
const now = new Date();
|
||||
return (
|
||||
date.getMonth() === now.getMonth() && date.getFullYear() === now.getFullYear()
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Obtient le premier jour du mois
|
||||
*/
|
||||
export const getFirstDayOfMonth = (date: Date): Date => {
|
||||
return new Date(date.getFullYear(), date.getMonth(), 1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Obtient le dernier jour du mois
|
||||
*/
|
||||
export const getLastDayOfMonth = (date: Date): Date => {
|
||||
return new Date(date.getFullYear(), date.getMonth() + 1, 0, 23, 59, 59);
|
||||
};
|
||||
|
||||
/**
|
||||
* Valide une adresse email
|
||||
*/
|
||||
export const isValidEmail = (email: string): boolean => {
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
return emailRegex.test(email);
|
||||
};
|
||||
|
||||
/**
|
||||
* Valide un montant
|
||||
*/
|
||||
export const isValidAmount = (amount: string | number): boolean => {
|
||||
const numAmount = typeof amount === 'string' ? parseFloat(amount) : amount;
|
||||
return !isNaN(numAmount) && numAmount > 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Tronque un texte
|
||||
*/
|
||||
export const truncate = (text: string, maxLength: number): string => {
|
||||
if (text.length <= maxLength) return text;
|
||||
return text.substring(0, maxLength) + '...';
|
||||
};
|
||||
|
||||
/**
|
||||
* Capitalise la première lettre
|
||||
*/
|
||||
export const capitalize = (text: string): string => {
|
||||
if (!text) return '';
|
||||
return text.charAt(0).toUpperCase() + text.slice(1).toLowerCase();
|
||||
};
|
||||
|
||||
/**
|
||||
* Génère une couleur aléatoire
|
||||
*/
|
||||
export const generateRandomColor = (): string => {
|
||||
const colors = [
|
||||
'#FF6B6B',
|
||||
'#4ECDC4',
|
||||
'#45B7D1',
|
||||
'#FFA07A',
|
||||
'#98D8C8',
|
||||
'#F7DC6F',
|
||||
'#BB8FCE',
|
||||
'#85C1E2',
|
||||
'#F8B739',
|
||||
'#52C41A',
|
||||
'#13C2C2',
|
||||
'#1890FF',
|
||||
'#EB2F96'
|
||||
];
|
||||
return colors[Math.floor(Math.random() * colors.length)];
|
||||
};
|
||||
|
||||
/**
|
||||
* Calcule le pourcentage
|
||||
*/
|
||||
export const calculatePercentage = (value: number, total: number): number => {
|
||||
if (total === 0) return 0;
|
||||
return (value / total) * 100;
|
||||
};
|
||||
|
||||
/**
|
||||
* Arrondit un nombre à N décimales
|
||||
*/
|
||||
export const roundTo = (num: number, decimals: number = 2): number => {
|
||||
return Math.round(num * Math.pow(10, decimals)) / Math.pow(10, decimals);
|
||||
};
|
||||
|
||||
/**
|
||||
* Groupe les transactions par date
|
||||
*/
|
||||
export const groupByDate = <T extends { date: Date }>(items: T[]): Map<string, T[]> => {
|
||||
const grouped = new Map<string, T[]>();
|
||||
|
||||
items.forEach((item) => {
|
||||
const dateKey = formatDate(item.date, 'short');
|
||||
const existing = grouped.get(dateKey) || [];
|
||||
grouped.set(dateKey, [...existing, item]);
|
||||
});
|
||||
|
||||
return grouped;
|
||||
};
|
||||
|
||||
/**
|
||||
* Groupe les transactions par mois
|
||||
*/
|
||||
export const groupByMonth = <T extends { date: Date }>(items: T[]): Map<string, T[]> => {
|
||||
const grouped = new Map<string, T[]>();
|
||||
|
||||
items.forEach((item) => {
|
||||
const monthKey = getMonthName(item.date);
|
||||
const existing = grouped.get(monthKey) || [];
|
||||
grouped.set(monthKey, [...existing, item]);
|
||||
});
|
||||
|
||||
return grouped;
|
||||
};
|
||||
|
||||
/**
|
||||
* Trie les transactions par date (plus récentes en premier)
|
||||
*/
|
||||
export const sortByDateDesc = <T extends { date: Date }>(items: T[]): T[] => {
|
||||
return [...items].sort((a, b) => b.date.getTime() - a.date.getTime());
|
||||
};
|
||||
|
||||
/**
|
||||
* Filtre les transactions par période
|
||||
*/
|
||||
export const filterByDateRange = <T extends { date: Date }>(
|
||||
items: T[],
|
||||
startDate: Date,
|
||||
endDate: Date
|
||||
): T[] => {
|
||||
return items.filter((item) => item.date >= startDate && item.date <= endDate);
|
||||
};
|
||||
|
||||
/**
|
||||
* Calcule la somme des montants
|
||||
*/
|
||||
export const sumAmounts = <T extends { amount: number }>(items: T[]): number => {
|
||||
return items.reduce((sum, item) => sum + item.amount, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* Attend X millisecondes (pour les animations)
|
||||
*/
|
||||
export const wait = (ms: number): Promise<void> => {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
};
|
||||
|
||||
/**
|
||||
* Debounce une fonction
|
||||
*/
|
||||
export const debounce = <T extends (...args: any[]) => any>(
|
||||
func: T,
|
||||
delay: number
|
||||
): ((...args: Parameters<T>) => void) => {
|
||||
let timeoutId: NodeJS.Timeout;
|
||||
|
||||
return (...args: Parameters<T>) => {
|
||||
clearTimeout(timeoutId);
|
||||
timeoutId = setTimeout(() => func(...args), delay);
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Vérifie si l'objet est vide
|
||||
*/
|
||||
export const isEmpty = (obj: any): boolean => {
|
||||
if (obj === null || obj === undefined) return true;
|
||||
if (typeof obj === 'string') return obj.trim().length === 0;
|
||||
if (Array.isArray(obj)) return obj.length === 0;
|
||||
if (typeof obj === 'object') return Object.keys(obj).length === 0;
|
||||
return false;
|
||||
};
|
||||
237
src/utils/sampleData.ts
Normal file
237
src/utils/sampleData.ts
Normal file
@@ -0,0 +1,237 @@
|
||||
/**
|
||||
* Données d'exemple pour faciliter les tests et le développement
|
||||
* Ces fonctions peuvent être utilisées pour peupler la base de données avec des données de test
|
||||
*/
|
||||
|
||||
import { transactionService } from '../services/transactionService';
|
||||
import { subscriptionService } from '../services/subscriptionService';
|
||||
import { TransactionType, SubscriptionFrequency } from '../types';
|
||||
|
||||
/**
|
||||
* Génère des transactions d'exemple pour un utilisateur
|
||||
*/
|
||||
export const generateSampleTransactions = async (userId: string) => {
|
||||
const transactions = [
|
||||
// Revenus
|
||||
{
|
||||
type: 'income' as TransactionType,
|
||||
amount: 2500,
|
||||
category: 'Salaire',
|
||||
date: new Date(2025, 9, 1),
|
||||
note: 'Salaire mensuel'
|
||||
},
|
||||
{
|
||||
type: 'income' as TransactionType,
|
||||
amount: 500,
|
||||
category: 'Freelance',
|
||||
date: new Date(2025, 9, 15),
|
||||
note: 'Projet web client XYZ'
|
||||
},
|
||||
|
||||
// Dépenses - Courses
|
||||
{
|
||||
type: 'expense' as TransactionType,
|
||||
amount: 85.50,
|
||||
category: 'Courses',
|
||||
date: new Date(2025, 9, 5),
|
||||
note: 'Supermarché Carrefour'
|
||||
},
|
||||
{
|
||||
type: 'expense' as TransactionType,
|
||||
amount: 42.30,
|
||||
category: 'Courses',
|
||||
date: new Date(2025, 9, 12),
|
||||
note: 'Marché local'
|
||||
},
|
||||
{
|
||||
type: 'expense' as TransactionType,
|
||||
amount: 67.80,
|
||||
category: 'Courses',
|
||||
date: new Date(2025, 9, 19),
|
||||
note: 'Supermarché Leclerc'
|
||||
},
|
||||
|
||||
// Dépenses - Logement
|
||||
{
|
||||
type: 'expense' as TransactionType,
|
||||
amount: 850,
|
||||
category: 'Logement',
|
||||
date: new Date(2025, 9, 1),
|
||||
note: 'Loyer mensuel'
|
||||
},
|
||||
{
|
||||
type: 'expense' as TransactionType,
|
||||
amount: 120,
|
||||
category: 'Logement',
|
||||
date: new Date(2025, 9, 10),
|
||||
note: 'Électricité et gaz'
|
||||
},
|
||||
|
||||
// Dépenses - Transport
|
||||
{
|
||||
type: 'expense' as TransactionType,
|
||||
amount: 60,
|
||||
category: 'Transport',
|
||||
date: new Date(2025, 9, 3),
|
||||
note: 'Essence'
|
||||
},
|
||||
{
|
||||
type: 'expense' as TransactionType,
|
||||
amount: 75,
|
||||
category: 'Transport',
|
||||
date: new Date(2025, 9, 8),
|
||||
note: 'Pass Navigo'
|
||||
},
|
||||
|
||||
// Dépenses - Restaurant
|
||||
{
|
||||
type: 'expense' as TransactionType,
|
||||
amount: 45,
|
||||
category: 'Restaurant',
|
||||
date: new Date(2025, 9, 6),
|
||||
note: 'Dîner au restaurant italien'
|
||||
},
|
||||
{
|
||||
type: 'expense' as TransactionType,
|
||||
amount: 28,
|
||||
category: 'Restaurant',
|
||||
date: new Date(2025, 9, 13),
|
||||
note: 'Déjeuner avec collègues'
|
||||
},
|
||||
{
|
||||
type: 'expense' as TransactionType,
|
||||
amount: 15,
|
||||
category: 'Restaurant',
|
||||
date: new Date(2025, 9, 20),
|
||||
note: 'Fast food'
|
||||
},
|
||||
|
||||
// Dépenses - Loisirs
|
||||
{
|
||||
type: 'expense' as TransactionType,
|
||||
amount: 60,
|
||||
category: 'Loisirs',
|
||||
date: new Date(2025, 9, 7),
|
||||
note: 'Cinéma et pop-corn'
|
||||
},
|
||||
{
|
||||
type: 'expense' as TransactionType,
|
||||
amount: 35,
|
||||
category: 'Loisirs',
|
||||
date: new Date(2025, 9, 14),
|
||||
note: 'Jeu vidéo Steam'
|
||||
},
|
||||
|
||||
// Dépenses - Santé
|
||||
{
|
||||
type: 'expense' as TransactionType,
|
||||
amount: 25,
|
||||
category: 'Santé',
|
||||
date: new Date(2025, 9, 9),
|
||||
note: 'Pharmacie - médicaments'
|
||||
},
|
||||
|
||||
// Dépenses - Vêtements
|
||||
{
|
||||
type: 'expense' as TransactionType,
|
||||
amount: 89,
|
||||
category: 'Vêtements',
|
||||
date: new Date(2025, 9, 16),
|
||||
note: 'Nouvelle paire de chaussures'
|
||||
}
|
||||
];
|
||||
|
||||
try {
|
||||
for (const transaction of transactions) {
|
||||
await transactionService.addTransaction(
|
||||
userId,
|
||||
transaction.type,
|
||||
transaction.amount,
|
||||
transaction.category,
|
||||
transaction.date,
|
||||
transaction.note
|
||||
);
|
||||
}
|
||||
console.log('✅ Transactions d\'exemple créées avec succès');
|
||||
} catch (error) {
|
||||
console.error('❌ Erreur lors de la création des transactions d\'exemple:', error);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Génère des abonnements d'exemple pour un utilisateur
|
||||
*/
|
||||
export const generateSampleSubscriptions = async (userId: string) => {
|
||||
const subscriptions = [
|
||||
{
|
||||
name: 'Netflix',
|
||||
amount: 15.99,
|
||||
category: 'Abonnements',
|
||||
frequency: 'monthly' as SubscriptionFrequency,
|
||||
dayOfMonth: 15
|
||||
},
|
||||
{
|
||||
name: 'Spotify',
|
||||
amount: 9.99,
|
||||
category: 'Abonnements',
|
||||
frequency: 'monthly' as SubscriptionFrequency,
|
||||
dayOfMonth: 1
|
||||
},
|
||||
{
|
||||
name: 'Amazon Prime',
|
||||
amount: 6.99,
|
||||
category: 'Abonnements',
|
||||
frequency: 'monthly' as SubscriptionFrequency,
|
||||
dayOfMonth: 10
|
||||
},
|
||||
{
|
||||
name: 'Salle de sport',
|
||||
amount: 35,
|
||||
category: 'Santé',
|
||||
frequency: 'monthly' as SubscriptionFrequency,
|
||||
dayOfMonth: 5
|
||||
},
|
||||
{
|
||||
name: 'Assurance téléphone',
|
||||
amount: 120,
|
||||
category: 'Autre',
|
||||
frequency: 'yearly' as SubscriptionFrequency,
|
||||
dayOfMonth: 1
|
||||
}
|
||||
];
|
||||
|
||||
try {
|
||||
for (const subscription of subscriptions) {
|
||||
const now = new Date();
|
||||
const nextPaymentDate = new Date(now.getFullYear(), now.getMonth(), subscription.dayOfMonth);
|
||||
|
||||
// Si la date est déjà passée ce mois-ci, passer au mois suivant
|
||||
if (nextPaymentDate < now) {
|
||||
nextPaymentDate.setMonth(nextPaymentDate.getMonth() + 1);
|
||||
}
|
||||
|
||||
await subscriptionService.addSubscription(
|
||||
userId,
|
||||
subscription.name,
|
||||
subscription.amount,
|
||||
subscription.category,
|
||||
subscription.frequency,
|
||||
nextPaymentDate,
|
||||
3
|
||||
);
|
||||
}
|
||||
console.log('✅ Abonnements d\'exemple créés avec succès');
|
||||
} catch (error) {
|
||||
console.error('❌ Erreur lors de la création des abonnements d\'exemple:', error);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Génère toutes les données d'exemple
|
||||
*/
|
||||
export const generateAllSampleData = async (userId: string) => {
|
||||
console.log('🔄 Génération des données d\'exemple...');
|
||||
await generateSampleTransactions(userId);
|
||||
await generateSampleSubscriptions(userId);
|
||||
console.log('✅ Toutes les données d\'exemple ont été générées !');
|
||||
};
|
||||
Reference in New Issue
Block a user