Repository navigation
Expand file tree
/
Copy pathseed.js
More file actions
1211 lines (1156 loc) · 76.9 KB
/
Copy pathseed.js
File metadata and controls
1211 lines (1156 loc) · 76.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
const mongoose = require('mongoose');
// Import models
require('./server/models/User');
require('./server/models/Post');
require('./server/models/WorkoutPlan');
require('./server/models/WorkoutLog');
require('./server/models/Review');
require('./server/models/Appointment');
require('./server/models/Gym');
require('./server/models/Package');
require('./server/models/Subscription');
require('./server/models/Message');
require('./server/models/Notification');
const User = mongoose.model('User');
const Post = mongoose.model('Post');
const WorkoutPlan = mongoose.model('WorkoutPlan');
const WorkoutLog = mongoose.model('WorkoutLog');
const Review = mongoose.model('Review');
const Appointment = mongoose.model('Appointment');
const Gym = mongoose.model('Gym');
const Package = mongoose.model('Package');
const Subscription = mongoose.model('Subscription');
const Message = mongoose.model('Message');
const Notification = mongoose.model('Notification');
// ─── Date helpers ────────────────────────────────────────────────────────────
/** Restituisce il lunedì della settimana corrente alle 00:00:00 */
function getMondayOfCurrentWeek() {
const today = new Date();
const day = today.getDay(); // 0=Dom, 1=Lun, ..., 6=Sab
const diff = day === 0 ? -6 : 1 - day; // quanti giorni tornare al lunedì
const monday = new Date(today);
monday.setDate(today.getDate() + diff);
monday.setHours(0, 0, 0, 0);
return monday;
}
/** Restituisce la domenica della settimana corrente alle 00:00:00 */
function getSundayOfCurrentWeek() {
const today = new Date();
const sunday = new Date(today);
sunday.setDate(today.getDate() - today.getDay());
sunday.setHours(0, 0, 0, 0);
return sunday;
}
/**
* Crea una data a partire da una base, aggiungendo N giorni e impostando l'ora.
* Es: dateAt(monday, 2, 10) → mercoledì alle 10:00
*/
function dateAt(base, daysOffset, hour, minute = 0) {
const d = new Date(base);
d.setDate(base.getDate() + daysOffset);
d.setHours(hour, minute, 0, 0);
return d;
}
/**
* Restituisce una data nel passato, N mesi fa, al giorno 15.
* Usata per distribuire le recensioni nel tempo (rating chart).
*/
function monthsAgo(n) {
const d = new Date();
d.setMonth(d.getMonth() - n);
d.setDate(15);
d.setHours(12, 0, 0, 0);
return d;
}
// ─── Main ────────────────────────────────────────────────────────────────────
async function seedDatabase() {
try {
await mongoose.connect('mongodb://127.0.0.1:27017/myworkoutplan');
console.log('✅ Connected to MongoDB');
// Svuota tutto tranne le palestre (già buone)
await Promise.all([
User.deleteMany({}),
Post.deleteMany({}),
WorkoutPlan.deleteMany({}),
WorkoutLog.deleteMany({}),
Review.deleteMany({}),
Appointment.deleteMany({}),
Gym.deleteMany({}),
Package.deleteMany({}),
Subscription.deleteMany({}),
Message.deleteMany({}),
Notification.deleteMany({})
]);
console.log('🧹 Cleared existing data');
const now = new Date();
const monday = getMondayOfCurrentWeek(); // punto di riferimento per i log
const sunday = getSundayOfCurrentWeek(); // punto di riferimento per gli appuntamenti
// ─── COACHES ─────────────────────────────────────────────────────────
const coaches = await User.create([
{
name: 'Marco Santoro',
email: 'marco@coach.it',
password: 'coach123',
role: 'coach',
description: 'Personal trainer certificato con oltre dieci anni di esperienza nel settore. Specializzato in preparazione fisica avanzata e ipertrofia muscolare. Ha guidato con successo centinaia di atleti verso i propri obiettivi di forza e composizione corporea.',
profilePicture: '/assets/coach-icon.png',
isPremium: true,
specializations: ['Forza', 'Preparazione Fisica', 'Nutrizione', 'Ipertrofia'],
rating: 4.8,
totalReviews: 0
},
{
name: 'Elena Russo',
email: 'elena@coach.it',
password: 'coach123',
role: 'coach',
description: 'Specialista in allenamento funzionale, mobilità e programmi di recupero. Certificata con qualifiche internazionali riconosciute. Approccio personalizzato e attento alle esigenze specifiche di ogni atleta, con focus sulla salute a lungo termine.',
profilePicture: '/assets/default-user.png',
isPremium: true,
specializations: ['Funzionale', 'Mobilità', 'Riabilitazione', 'Postura'],
rating: 4.9,
totalReviews: 0
},
{
name: 'Luca Moretti',
email: 'luca@coach.it',
password: 'coach123',
role: 'coach',
description: 'Esperto in trasformazione fisica e perdita di peso. Approccio scientifico che integra allenamento strutturato, alimentazione e supporto motivazionale. Risultati concreti e documentati nel tempo.',
profilePicture: '/assets/coach-icon.png',
isPremium: false,
specializations: ['Dimagrimento', 'Nutrizione', 'Cardio', 'Motivazione'],
rating: 4.7,
totalReviews: 0
}
]);
console.log(`✅ Created ${coaches.length} coaches`);
// ─── USERS ───────────────────────────────────────────────────────────
const users = await User.create([
{
name: 'Mario Rossi',
email: 'mario@test.it',
password: 'user123',
role: 'user',
description: 'Appassionato di fitness da 2 anni. Obiettivo: aumentare forza e massa muscolare. Mi alleno 4x settimana.',
profilePicture: '/assets/man.png'
},
{
name: 'Laura Bianchi',
email: 'laura@test.it',
password: 'user123',
role: 'user',
description: 'Mamma di due bambini che vuole tornare in forma post-gravidanza. Mi piacciono yoga e allenamenti funzionali.',
profilePicture: '/assets/default-user.png'
},
{
name: 'Giuseppe Verdi',
email: 'giuseppe@test.it',
password: 'user123',
role: 'user',
description: 'Principiante assoluto. Voglio perdere 15kg e costruire abitudini sane. Molto motivato!',
profilePicture: '/assets/boy.png'
},
{
name: 'Sofia Romano',
email: 'sofia@test.it',
password: 'user123',
role: 'user',
description: 'Atleta amatoriale di CrossFit. Mi alleno 6 giorni a settimana. Obiettivo: competere a livello nazionale.',
profilePicture: '/assets/default-user.png'
},
{
name: 'Alessandro Ferrari',
email: 'alessandro@test.it',
password: 'user123',
role: 'user',
description: 'Impiegato 35enne. Vita sedentaria, voglio mantenermi in forma e prevenire problemi di salute.',
profilePicture: '/assets/man.png'
},
{
name: 'Chiara Galli',
email: 'chiara@test.it',
password: 'user123',
role: 'user',
description: 'Runner appassionata. Corro mezze maratone. Voglio migliorare la resistenza e prevenire infortuni.',
profilePicture: '/assets/default-user.png'
},
{
name: 'Davide Costa',
email: 'davide@test.it',
password: 'user123',
role: 'user',
description: 'Ex atleta di calcio. Voglio rimanere in forma e recuperare la mobilità perduta.',
profilePicture: '/assets/boy.png'
},
{
name: 'Francesca Ricci',
email: 'francesca@test.it',
password: 'user123',
role: 'user',
description: 'Personal trainer in formazione. Sto studiando per la certificazione e voglio la migliore preparazione.',
profilePicture: '/assets/default-user.png'
}
]);
console.log(`✅ Created ${users.length} users`);
// ─── GYMS ────────────────────────────────────────────────────────────
const gyms = await Gym.create([
{
name: 'FitZone Centro',
location: { lat: 37.5079, lng: 15.0830, address: 'Via Etnea 122, Catania' },
rating: 4.5,
openingHours: { open: '06:00', close: '22:00' },
amenities: ['Pesi Liberi', 'Cardio', 'Spogliatoi', 'Sauna']
},
{
name: 'PowerGym Elite',
location: { lat: 37.5065, lng: 15.0940, address: 'Viale Vittorio Veneto 45, Catania' },
rating: 4.7,
openingHours: { open: '07:00', close: '23:00' },
amenities: ['Allenamento Funzionale', 'Pesi', 'Personal Training', 'Piscina']
},
{
name: 'Active Fitness',
location: { lat: 37.5050, lng: 15.0870, address: 'Via Plebiscito 88, Catania' },
rating: 4.2,
openingHours: { open: '06:30', close: '21:30' },
amenities: ['Cardio', 'Pesi', 'Corsi di Gruppo']
},
{
name: 'Iron Temple Gym',
location: { lat: 37.5015, lng: 15.0820, address: 'Corso Italia 200, Catania' },
rating: 4.9,
openingHours: { open: '05:00', close: '24:00' },
amenities: ['Sollevamento Pesi', 'Pesi Olimpici', 'Personal Training']
}
]);
console.log(`✅ Created ${gyms.length} gyms`);
// ─── PACKAGES ────────────────────────────────────────────────────────
const packages = await Package.create([
// Marco
{
coach: coaches[0]._id,
name: 'Pacchetto Completo Premium',
description: 'Piano completo: schede personalizzate, appuntamenti settimanali e supporto chat 24/7',
price: 150, duration: 30,
services: { chat: true, appointments: true, workoutPlans: true },
active: true
},
{
coach: coaches[0]._id,
name: 'Solo Schede Allenamento',
description: 'Ricevi schede personalizzate aggiornate ogni 4 settimane',
price: 50, duration: 30,
services: { chat: false, appointments: false, workoutPlans: true },
active: true
},
// Elena
{
coach: coaches[1]._id,
name: 'Programma Funzionale + Chat',
description: 'Allenamento funzionale personalizzato con supporto chat per domande e feedback',
price: 80, duration: 30,
services: { chat: true, appointments: false, workoutPlans: true },
active: true
},
{
coach: coaches[1]._id,
name: 'Riabilitazione Completa',
description: 'Programma di riabilitazione con sessioni in presenza e monitoraggio continuo',
price: 200, duration: 30,
services: { chat: true, appointments: true, workoutPlans: true },
active: true
},
// Luca
{
coach: coaches[2]._id,
name: 'Trasformazione 30 Giorni',
description: 'Programma intensivo di dimagrimento: allenamento strutturato, supporto nutrizionale e motivazionale',
price: 120, duration: 30,
services: { chat: true, appointments: true, workoutPlans: true },
active: true
}
]);
console.log(`✅ Created ${packages.length} packages`);
// ─── SUBSCRIPTIONS ───────────────────────────────────────────────────
const subscriptions = await Subscription.create([
// Mario → Marco (completo)
{
user: users[0]._id, coach: coaches[0]._id, package: packages[0]._id,
status: 'active',
startDate: new Date(now.getTime() - 15 * 86400000),
endDate: new Date(now.getTime() + 15 * 86400000)
},
// Laura → Elena (riabilitazione)
{
user: users[1]._id, coach: coaches[1]._id, package: packages[3]._id,
status: 'active',
startDate: new Date(now.getTime() - 10 * 86400000),
endDate: new Date(now.getTime() + 20 * 86400000)
},
// Giuseppe → Luca (trasformazione)
{
user: users[2]._id, coach: coaches[2]._id, package: packages[4]._id,
status: 'active',
startDate: new Date(now.getTime() - 5 * 86400000),
endDate: new Date(now.getTime() + 25 * 86400000)
},
// Sofia → Marco (solo schede)
{
user: users[3]._id, coach: coaches[0]._id, package: packages[1]._id,
status: 'active',
startDate: new Date(now.getTime() - 20 * 86400000),
endDate: new Date(now.getTime() + 10 * 86400000)
},
// Alessandro → Elena (funzionale + chat)
{
user: users[4]._id, coach: coaches[1]._id, package: packages[2]._id,
status: 'active',
startDate: new Date(now.getTime() - 12 * 86400000),
endDate: new Date(now.getTime() + 18 * 86400000)
},
// Chiara → Luca
{
user: users[5]._id, coach: coaches[2]._id, package: packages[4]._id,
status: 'active',
startDate: new Date(now.getTime() - 8 * 86400000),
endDate: new Date(now.getTime() + 22 * 86400000)
},
// Davide → Marco (solo schede)
{
user: users[6]._id, coach: coaches[0]._id, package: packages[1]._id,
status: 'active',
startDate: new Date(now.getTime() - 7 * 86400000),
endDate: new Date(now.getTime() + 23 * 86400000)
},
// Francesca → Marco (completo)
{
user: users[7]._id, coach: coaches[0]._id, package: packages[0]._id,
status: 'active',
startDate: new Date(now.getTime() - 3 * 86400000),
endDate: new Date(now.getTime() + 27 * 86400000)
}
]);
console.log(`✅ Created ${subscriptions.length} subscriptions`);
// ─── WORKOUT PLANS ───────────────────────────────────────────────────
const workoutPlans = await WorkoutPlan.create([
{
coach: coaches[0]._id, client: users[0]._id,
name: 'Programma Forza 4x Settimana',
description: 'Piano di allenamento per massimizzare la forza sui grandi multiarticolari. Focus su squat, panca e stacco.',
exercises: [
{ name: 'Squat', sets: 5, reps: '5', weight: 100, notes: 'Scendi fino a parallelo. Riposo 3min' },
{ name: 'Panca Piana', sets: 5, reps: '5', weight: 80, notes: 'Mantieni scapole retratte' },
{ name: 'Stacco da Terra', sets: 3, reps: '5', weight: 120, notes: 'Tecnica corretta, schiena dritta durante tutta la traiettoria' },
{ name: 'Military Press', sets: 4, reps: '8', weight: 40, notes: 'Core attivo' },
{ name: 'Rematore Bilanciere',sets: 4, reps: '8', weight: 60, notes: 'Gomiti vicino al corpo' }
]
},
{
coach: coaches[1]._id, client: users[1]._id,
name: 'Ritorno in Forma Post-Gravidanza',
description: 'Allenamento funzionale progressivo per recuperare forza core e mobilità. Esercizi sicuri ed efficaci.',
exercises: [
{ name: 'Plank', sets: 3, reps: '30 sec', notes: 'Concentrati sulla respirazione' },
{ name: 'Goblet Squat', sets: 3, reps: '12', weight: 8, notes: 'Kettlebell davanti al petto' },
{ name: 'Push-up (ginocchia)', sets: 3, reps: '10', notes: 'Progressione verso push-up completi' },
{ name: 'Bird Dog', sets: 3, reps: '10 per lato', notes: 'Stabilità core' },
{ name: 'Ponte Glutei', sets: 3, reps: '15', notes: 'Attiva glutei, non lower back' }
]
},
{
coach: coaches[2]._id, client: users[2]._id,
name: 'Dimagrimento Corpo Completo 3x',
description: 'Circuito a corpo completo per massimizzare il consumo calorico. Esercizi semplici ma efficaci per principianti.',
exercises: [
{ name: 'Camminata veloce', sets: 1, reps: '20 min', notes: 'Riscaldamento cardiovascolare' },
{ name: 'Squat Corpo Libero', sets: 3, reps: '15', notes: 'Concentrati sulla forma' },
{ name: 'Push-up a muro', sets: 3, reps: '12', notes: 'Progressione graduale' },
{ name: 'Affondi Alternati', sets: 3, reps: '10 per gamba', notes: 'Mantieni equilibrio' },
{ name: 'Plank', sets: 3, reps: '20 sec', notes: 'Core forte' },
{ name: 'Jumping Jacks', sets: 3, reps: '30', notes: 'Mantieni ritmo costante' }
]
},
{
coach: coaches[0]._id, client: users[3]._id,
name: 'Forza e Condizionamento Avanzato',
description: 'Sessione intensa per atleti avanzati. Combinazione di forza esplosiva e condizionamento atletico.',
exercises: [
{ name: 'Slancio con Bilanciere', sets: 5, reps: '3', weight: 60, notes: 'Tecnica olimpica, concentrarsi sulla traiettoria' },
{ name: 'Trazioni', sets: 5, reps: '10', notes: 'Ampiezza completa del movimento, esecuzione controllata' },
{ name: 'Box Jump', sets: 4, reps: '8', notes: 'Box 60cm, atterraggio morbido' },
{ name: 'Thruster', sets: 4, reps: '12', weight: 40, notes: 'Movimento fluido' },
{ name: 'Burpees', sets: 4, reps: '15', notes: 'Esplosività' }
]
},
{
coach: coaches[1]._id, client: users[4]._id,
name: 'Allenamento Funzionale per Vita Sedentaria',
description: 'Allenamento efficiente di 45 minuti progettato per contrastare gli effetti di una vita sedentaria. Attenzione alla postura e alla mobilità articolare.',
exercises: [
{ name: 'Cat-Cow Stretch', sets: 2, reps: '10', notes: 'Mobilità toracica' },
{ name: 'Goblet Squat', sets: 3, reps: '12', weight: 12, notes: 'Profondità completa' },
{ name: 'TRX Row', sets: 3, reps: '12', notes: 'Rafforza upper back' },
{ name: 'Lunges Walking', sets: 3, reps: '20 totali', notes: 'Attiva catena posteriore' },
{ name: 'Dead Bug', sets: 3, reps: '10 per lato', notes: 'Anti-rotazione core' },
{ name: 'Farmer Walk', sets: 3, reps: '40m', weight: 20, notes: 'Grip e postura' }
]
},
{
coach: coaches[2]._id, client: users[5]._id,
name: 'Strength per Runner',
description: 'Programma di forza complementare alla corsa. Previene infortuni e migliora le prestazioni atletiche.',
exercises: [
{ name: 'Bulgarian Split Squat', sets: 3, reps: '10 per gamba', weight: 15, notes: 'Unilaterale per equilibrio' },
{ name: 'Single Leg Deadlift', sets: 3, reps: '8 per gamba', weight: 10, notes: 'Stabilità caviglia' },
{ name: 'Calf Raises', sets: 4, reps: '15', weight: 20, notes: 'Forza polpacci' },
{ name: 'Side Plank', sets: 3, reps: '30 sec per lato', notes: 'Stabilità laterale' },
{ name: 'Glute Bridge', sets: 4, reps: '12', weight: 40, notes: 'Glutei forti = corsa veloce' }
]
},
{
coach: coaches[0]._id, client: users[0]._id,
name: 'Ciclo Ipertrofia 4x Settimana',
description: 'Blocco di ipertrofia da alternare al ciclo di forza. Volume aumentato con carichi moderati per stimolare la crescita muscolare e consolidare le basi per il successivo picco di forza.',
exercises: [
{ name: 'Squat', sets: 4, reps: '8', weight: 85, notes: 'Carico al 80% del massimale, ritmo controllato nella discesa (3 secondi)' },
{ name: 'Panca Piana', sets: 4, reps: '8', weight: 70, notes: 'Pausa di 1 secondo sul petto, esplosivo in spinta' },
{ name: 'Stacco Rumeno', sets: 3, reps: '10', weight: 90, notes: 'Catena posteriore, schiena neutra per tutta la traiettoria' },
{ name: 'Military Press', sets: 4, reps: '10', weight: 35, notes: 'Scapole depresse, non iperestendere la zona lombare' },
{ name: 'Trazioni Zavorate', sets: 4, reps: '8', weight: 10, notes: 'Ampiezza completa, non strappare nella fase concentrica' },
{ name: 'Curl con Bilanciere', sets: 3, reps: '12', weight: 30, notes: 'Isolamento bicipiti, gomiti fissi' }
]
},
]);
console.log(`✅ Created ${workoutPlans.length} workout plans`);
// ─── WORKOUT LOGS ─────────────────────────────────────────────────────
//
// Obiettivo: riempire il bar chart "Statistiche Settimanali" della dashboard utente.
// Il chart mostra Lun-Dom della settimana corrente e conta i log per giorno.
//
// Ogni utente ha una frequenza diversa così il grafico sembra realistico:
// Mario → 4x/week (Lun, Mar, Mer, Gio)
// Laura → 2x/week (Lun, Mer)
// Giuseppe → 3x/week (Lun, Mar, Gio)
// Sofia → 5x/week (Lun, Mar, Mer, Gio, Ven)
// Alessandro→ 3x/week (Lun, Mer, Ven)
// Chiara → 4x/week (Lun, Mar, Gio, Ven)
//
// In più: ultime 3 settimane di log per riempire il contatore "questo mese".
//
// Nota: dateAt(monday, offset, ora) → genera la data del giorno giusto
// della settimana corrente all'ora specificata.
const logs = [];
// ── Mario: 4x/week ──────────────────────────────────────────────────
// Progressione realistica: i pesi crescono settimana su settimana con
// alcune sessioni positive (record personale) e alcune negative (calo).
// Settimana corrente (picco del ciclo):
// Lun → sessione solida, tutti i 5x5 completati
// Mar → giornata brillante: +2kg sullo squat rispetto al programma
// Mer → giornata storta: mancate 2 ripetizioni sullo squat, stacco ridotto
// Gio → ripresa: back to normal, buona panca
// Lun: sessione standard corrente
logs.push({
user: users[0]._id, plan: workoutPlans[0]._id,
date: dateAt(monday, 0, 10),
exercises: [
{ name: 'Squat', sets: [{ reps: 5, weight: 100 }, { reps: 5, weight: 100 }, { reps: 5, weight: 100 }, { reps: 5, weight: 100 }, { reps: 5, weight: 100 }] },
{ name: 'Panca Piana', sets: [{ reps: 5, weight: 82 }, { reps: 5, weight: 82 }, { reps: 5, weight: 82 }, { reps: 4, weight: 82 }] },
{ name: 'Stacco da Terra',sets: [{ reps: 5, weight: 122 }, { reps: 5, weight: 122 }, { reps: 4, weight: 122 }] },
{ name: 'Military Press', sets: [{ reps: 8, weight: 42 }, { reps: 8, weight: 42 }, { reps: 7, weight: 42 }] }
]
});
// Mar: giornata brillante — nuovo record sullo squat
logs.push({
user: users[0]._id, plan: workoutPlans[0]._id,
date: dateAt(monday, 1, 10),
exercises: [
{ name: 'Squat', sets: [{ reps: 5, weight: 102 }, { reps: 5, weight: 102 }, { reps: 5, weight: 102 }, { reps: 5, weight: 102 }, { reps: 3, weight: 102 }] },
{ name: 'Rematore Bilanciere',sets: [{ reps: 8, weight: 62 }, { reps: 8, weight: 62 }, { reps: 8, weight: 62 }, { reps: 6, weight: 62 }] },
{ name: 'Military Press', sets: [{ reps: 8, weight: 42 }, { reps: 8, weight: 42 }, { reps: 8, weight: 42 }, { reps: 6, weight: 42 }] }
]
});
// Mer: giornata difficile — mancate ripetizioni, stacco dimezzato
logs.push({
user: users[0]._id, plan: workoutPlans[0]._id,
date: dateAt(monday, 2, 10),
exercises: [
{ name: 'Squat', sets: [{ reps: 5, weight: 100 }, { reps: 5, weight: 100 }, { reps: 4, weight: 100 }, { reps: 3, weight: 100 }] },
{ name: 'Panca Piana', sets: [{ reps: 5, weight: 80 }, { reps: 5, weight: 80 }, { reps: 5, weight: 80 }] },
{ name: 'Stacco da Terra',sets: [{ reps: 5, weight: 120 }, { reps: 4, weight: 120 }] }
]
});
// Gio: ripresa — panca record, squat corretto
logs.push({
user: users[0]._id, plan: workoutPlans[0]._id,
date: dateAt(monday, 3, 10),
exercises: [
{ name: 'Squat', sets: [{ reps: 5, weight: 100 }, { reps: 5, weight: 100 }, { reps: 5, weight: 100 }, { reps: 5, weight: 100 }, { reps: 4, weight: 100 }] },
{ name: 'Panca Piana', sets: [{ reps: 5, weight: 83 }, { reps: 5, weight: 83 }, { reps: 5, weight: 83 }, { reps: 5, weight: 83 }] },
{ name: 'Stacco da Terra',sets: [{ reps: 5, weight: 122 }, { reps: 5, weight: 122 }, { reps: 5, weight: 122 }] },
{ name: 'Rematore Bilanciere',sets: [{ reps: 8, weight: 60 }, { reps: 8, weight: 60 }, { reps: 7, weight: 60 }] }
]
});
// Settimana -1: carichi leggermente più bassi, progressione in corso
// Lun: squat 96, Mar: buona sessione 97, Mer: flessione 94, Gio: chiusura 96
const marioW1Sessions = [
{ d: 0, sq: [[5,96],[5,96],[5,96],[5,96],[4,96]], bp: [[5,79],[5,79],[5,79],[3,79]], dl: [[5,117],[5,117],[5,117]] },
{ d: 1, sq: [[5,97],[5,97],[5,97],[5,97],[5,97]], bp: [[5,80],[5,80],[5,80],[4,80]], dl: [[5,118],[5,118],[4,118]] },
{ d: 2, sq: [[5,94],[5,94],[4,94],[3,94]], bp: [[5,78],[5,78],[5,78]], dl: [[5,115],[3,115]] },
{ d: 3, sq: [[5,96],[5,96],[5,96],[5,96]], bp: [[5,79],[5,79],[5,79],[5,79]], dl: [[5,117],[5,117],[5,117]] }
];
marioW1Sessions.forEach(s => {
logs.push({
user: users[0]._id, plan: workoutPlans[0]._id,
date: dateAt(monday, -(7) + s.d, 10),
exercises: [
{ name: 'Squat', sets: s.sq.map(([reps,weight]) => ({ reps, weight })) },
{ name: 'Panca Piana', sets: s.bp.map(([reps,weight]) => ({ reps, weight })) },
{ name: 'Stacco da Terra',sets: s.dl.map(([reps,weight]) => ({ reps, weight })) }
]
});
});
// Settimana -2: fase di accumulazione
const marioW2Sessions = [
{ d: 0, sq: [[5,92],[5,92],[5,92],[5,92],[5,92]], bp: [[5,75],[5,75],[5,75],[4,75]], dl: [[5,112],[5,112],[5,112]] },
{ d: 1, sq: [[5,93],[5,93],[5,93],[5,93],[4,93]], bp: [[5,76],[5,76],[5,76],[5,76]], dl: [[5,113],[5,113],[4,113]] },
{ d: 2, sq: [[5,90],[5,90],[4,90],[4,90]], bp: [[5,74],[5,74],[5,74]], dl: [[5,110],[5,110]] },
{ d: 3, sq: [[5,92],[5,92],[5,92],[5,92]], bp: [[5,75],[5,75],[5,75],[5,75]], dl: [[5,112],[5,112],[5,112]] }
];
marioW2Sessions.forEach(s => {
logs.push({
user: users[0]._id, plan: workoutPlans[0]._id,
date: dateAt(monday, -(14) + s.d, 10),
exercises: [
{ name: 'Squat', sets: s.sq.map(([reps,weight]) => ({ reps, weight })) },
{ name: 'Panca Piana', sets: s.bp.map(([reps,weight]) => ({ reps, weight })) },
{ name: 'Stacco da Terra',sets: s.dl.map(([reps,weight]) => ({ reps, weight })) }
]
});
});
// Settimana -3: inizio del ciclo, pesi di partenza più bassi
const marioW3Sessions = [
{ d: 0, sq: [[5,87],[5,87],[5,87],[5,87],[5,87]], bp: [[5,71],[5,71],[5,71],[4,71]], dl: [[5,107],[5,107],[5,107]] },
{ d: 1, sq: [[5,88],[5,88],[5,88],[5,88]], bp: [[5,72],[5,72],[5,72],[5,72]], dl: [[5,108],[5,108],[4,108]] },
{ d: 2, sq: [[5,86],[5,86],[5,86],[4,86]], bp: [[5,70],[5,70],[5,70]], dl: [[5,105],[5,105]] },
{ d: 3, sq: [[5,87],[5,87],[5,87],[5,87],[3,87]], bp: [[5,71],[5,71],[5,71],[5,71]], dl: [[5,107],[5,107],[5,107]] }
];
marioW3Sessions.forEach(s => {
logs.push({
user: users[0]._id, plan: workoutPlans[0]._id,
date: dateAt(monday, -(21) + s.d, 10),
exercises: [
{ name: 'Squat', sets: s.sq.map(([reps,weight]) => ({ reps, weight })) },
{ name: 'Panca Piana', sets: s.bp.map(([reps,weight]) => ({ reps, weight })) },
{ name: 'Stacco da Terra',sets: s.dl.map(([reps,weight]) => ({ reps, weight })) }
]
});
});
// ── Mario: Ciclo Ipertrofia (workoutPlans[6]) — blocco precedente ──
// Eseguito 2x/settimana (Lun + Gio) nelle settimane -4, -5, -6
// prima di passare all'attuale ciclo di forza
const iperSessions = [
// Settimana -6: inizio blocco, carichi conservativi
{ offset: -42, sq: [[8,80],[8,80],[8,80],[8,80]], bp: [[8,65],[8,65],[8,65],[8,65]], rdl: [[10,85],[10,85],[10,85]], mp: [[10,32],[10,32],[10,32],[10,32]], pull: [[8,8],[8,8],[8,8],[7,8]], curl: [[12,28],[12,28],[12,28]] },
{ offset: -39, sq: [[8,81],[8,81],[8,81],[8,81]], bp: [[8,66],[8,66],[8,66],[7,66]], rdl: [[10,86],[10,86],[10,86]], mp: [[10,32],[10,32],[10,32],[10,32]], pull: [[8,8],[8,8],[8,8],[8,8]], curl: [[12,28],[12,28],[12,28]] },
// Settimana -5: progressione
{ offset: -35, sq: [[8,83],[8,83],[8,83],[8,83]], bp: [[8,68],[8,68],[8,68],[8,68]], rdl: [[10,88],[10,88],[10,88]], mp: [[10,34],[10,34],[10,34],[9,34]], pull: [[8,10],[8,10],[8,10],[8,10]], curl: [[12,30],[12,30],[12,30]] },
{ offset: -32, sq: [[8,84],[8,84],[8,84],[7,84]], bp: [[8,68],[8,68],[8,68],[8,68]], rdl: [[10,89],[10,89],[10,89]], mp: [[10,34],[10,34],[10,34],[10,34]], pull: [[8,10],[8,10],[8,10],[8,10]], curl: [[12,30],[12,30],[12,30]] },
// Settimana -4: picco del blocco ipertrofia
{ offset: -28, sq: [[8,86],[8,86],[8,86],[8,86]], bp: [[8,70],[8,70],[8,70],[8,70]], rdl: [[10,91],[10,91],[10,91]], mp: [[10,36],[10,36],[10,36],[10,36]], pull: [[8,12],[8,12],[8,12],[8,12]], curl: [[12,32],[12,32],[12,32]] },
{ offset: -25, sq: [[8,87],[8,87],[8,87],[8,87]], bp: [[8,70],[8,70],[8,70],[7,70]], rdl: [[10,92],[10,92],[10,92]], mp: [[10,36],[10,36],[10,36],[10,36]], pull: [[8,12],[8,12],[7,12],[7,12]], curl: [[12,32],[12,32],[12,32]] }
];
iperSessions.forEach(s => {
logs.push({
user: users[0]._id, plan: workoutPlans[6]._id,
date: dateAt(monday, s.offset, 18),
exercises: [
{ name: 'Squat', sets: s.sq.map(([reps,weight]) => ({ reps, weight })) },
{ name: 'Panca Piana', sets: s.bp.map(([reps,weight]) => ({ reps, weight })) },
{ name: 'Stacco Rumeno', sets: s.rdl.map(([reps,weight]) => ({ reps, weight })) },
{ name: 'Military Press', sets: s.mp.map(([reps,weight]) => ({ reps, weight })) },
{ name: 'Trazioni Zavorate', sets: s.pull.map(([reps,weight]) => ({ reps, weight })) },
{ name: 'Curl con Bilanciere', sets: s.curl.map(([reps,weight]) => ({ reps, weight })) }
]
});
});
// ── Laura: 2x/week ──────────────────────────────────────────────────
// Settimana corrente: Lun(0), Mer(2)
[0, 2].forEach(d => {
logs.push({
user: users[1]._id, plan: workoutPlans[1]._id,
date: dateAt(monday, d, 14),
exercises: [
{ name: 'Plank', sets: [{ reps: 30, weight: 0 }, { reps: 30, weight: 0 }, { reps: 25, weight: 0 }] },
{ name: 'Goblet Squat', sets: [{ reps: 12, weight: 8 }, { reps: 12, weight: 8 }, { reps: 10, weight: 8 }] }
]
});
});
// Settimane precedenti
for (let week = 1; week <= 3; week++) {
[0, 3].forEach(d => {
logs.push({
user: users[1]._id, plan: workoutPlans[1]._id,
date: dateAt(monday, -(week * 7) + d, 14),
exercises: [
{ name: 'Plank', sets: [{ reps: 25, weight: 0 }, { reps: 25, weight: 0 }] },
{ name: 'Goblet Squat',sets: [{ reps: 10, weight: 8 }, { reps: 10, weight: 8 }] }
]
});
});
}
// ── Giuseppe: 3x/week ───────────────────────────────────────────────
// Settimana corrente: Lun(0), Mar(1), Gio(3)
[0, 1, 3].forEach(d => {
logs.push({
user: users[2]._id, plan: workoutPlans[2]._id,
date: dateAt(monday, d, 17),
exercises: [
{ name: 'Squat Corpo Libero', sets: [{ reps: 15, weight: 0 }, { reps: 15, weight: 0 }, { reps: 12, weight: 0 }] },
{ name: 'Push-up a muro', sets: [{ reps: 12, weight: 0 }, { reps: 12, weight: 0 }, { reps: 10, weight: 0 }] }
]
});
});
// Settimane precedenti
for (let week = 1; week <= 2; week++) {
[0, 2, 4].forEach(d => {
logs.push({
user: users[2]._id, plan: workoutPlans[2]._id,
date: dateAt(monday, -(week * 7) + d, 17),
exercises: [
{ name: 'Squat Corpo Libero', sets: [{ reps: 12, weight: 0 }, { reps: 12, weight: 0 }] }
]
});
});
}
// ── Sofia: 5x/week ──────────────────────────────────────────────────
// Settimana corrente: Lun(0), Mar(1), Mer(2), Gio(3), Ven(4)
[0, 1, 2, 3, 4].forEach(d => {
logs.push({
user: users[3]._id, plan: workoutPlans[3]._id,
date: dateAt(monday, d, 8),
exercises: [
{ name: 'Clean & Jerk', sets: [{ reps: 3, weight: 60 }, { reps: 3, weight: 60 }, { reps: 3, weight: 60 }] },
{ name: 'Pull-ups', sets: [{ reps: 10, weight: 0 }, { reps: 10, weight: 0 }, { reps: 8, weight: 0 }] }
]
});
});
// Settimane precedenti
for (let week = 1; week <= 2; week++) {
[0, 1, 2, 3, 4].forEach(d => {
logs.push({
user: users[3]._id, plan: workoutPlans[3]._id,
date: dateAt(monday, -(week * 7) + d, 8),
exercises: [
{ name: 'Clean & Jerk', sets: [{ reps: 3, weight: 58 }, { reps: 3, weight: 58 }] }
]
});
});
}
// ── Alessandro: 3x/week ─────────────────────────────────────────────
// Settimana corrente: Lun(0), Mer(2), Ven(4)
[0, 2, 4].forEach(d => {
logs.push({
user: users[4]._id, plan: workoutPlans[4]._id,
date: dateAt(monday, d, 18),
exercises: [
{ name: 'Goblet Squat', sets: [{ reps: 12, weight: 12 }, { reps: 12, weight: 12 }, { reps: 10, weight: 12 }] },
{ name: 'TRX Row', sets: [{ reps: 12, weight: 0 }, { reps: 12, weight: 0 }, { reps: 10, weight: 0 }] }
]
});
});
// Settimane precedenti
for (let week = 1; week <= 2; week++) {
[0, 2, 4].forEach(d => {
logs.push({
user: users[4]._id, plan: workoutPlans[4]._id,
date: dateAt(monday, -(week * 7) + d, 18),
exercises: [
{ name: 'Goblet Squat', sets: [{ reps: 10, weight: 12 }, { reps: 10, weight: 12 }] }
]
});
});
}
// ── Chiara: 4x/week ─────────────────────────────────────────────────
// Settimana corrente: Lun(0), Mar(1), Gio(3), Ven(4)
[0, 1, 3, 4].forEach(d => {
logs.push({
user: users[5]._id, plan: workoutPlans[5]._id,
date: dateAt(monday, d, 7),
exercises: [
{ name: 'Bulgarian Split Squat', sets: [{ reps: 10, weight: 15 }, { reps: 10, weight: 15 }, { reps: 8, weight: 15 }] },
{ name: 'Calf Raises', sets: [{ reps: 15, weight: 20 }, { reps: 15, weight: 20 }, { reps: 12, weight: 20 }] }
]
});
});
// Settimane precedenti
for (let week = 1; week <= 2; week++) {
[0, 1, 3, 4].forEach(d => {
logs.push({
user: users[5]._id, plan: workoutPlans[5]._id,
date: dateAt(monday, -(week * 7) + d, 7),
exercises: [
{ name: 'Calf Raises', sets: [{ reps: 12, weight: 20 }, { reps: 12, weight: 20 }] }
]
});
});
}
await WorkoutLog.create(logs);
console.log(`✅ Created ${logs.length} workout logs`);
// ─── APPOINTMENTS ─────────────────────────────────────────────────────
//
// Obiettivo 1: riempire il donut chart "Ore Settimanali" del coach.
// Il chart conta i completed di questa settimana (Dom-Sab).
// Formula: ogni appuntamento completato = 1.5h → su 40h totali.
//
// Marco → 4 completati questa settimana → 6.0h lavorate
// Elena → 3 completati questa settimana → 4.5h lavorate
// Luca → 2 completati questa settimana → 3.0h lavorate
//
// Obiettivo 2: riempire la lista appuntamenti del coach e del cliente.
// Appuntamenti futuri confermati visibili su mappa e lista.
//
// Nota: usiamo `dateAt(sunday, offset, ora)` perché il chart usa Dom-Sab.
// sunday+1 = Lunedì, sunday+2 = Martedì, ecc.
const appts = [];
// ── Marco: 4 completati questa settimana ────────────────────────────
appts.push(
// Lun 10:00 — con Mario @ FitZone Centro (Via Etnea)
{ coach: coaches[0]._id, client: users[0]._id, date: dateAt(sunday, 1, 10), status: 'completed', notes: 'Sessione squat - nuovo record personale sui 102 kg',
location: { address: gyms[0].location.address, lat: gyms[0].location.lat, lng: gyms[0].location.lng } },
// Mar 15:00 — con Sofia @ PowerGym Elite
{ coach: coaches[0]._id, client: users[3]._id, date: dateAt(sunday, 2, 15), status: 'completed', notes: 'Sessione forza esplosiva ad alta intensità',
location: { address: gyms[1].location.address, lat: gyms[1].location.lat, lng: gyms[1].location.lng } },
// Mer 11:00 — con Mario @ Active Fitness (Via Plebiscito)
{ coach: coaches[0]._id, client: users[0]._id, date: dateAt(sunday, 3, 11), status: 'completed', notes: 'Sessione parte superiore - ottima progressione sulla panca',
location: { address: gyms[2].location.address, lat: gyms[2].location.lat, lng: gyms[2].location.lng } },
// Gio 16:00 — con Sofia @ Iron Temple Gym
{ coach: coaches[0]._id, client: users[3]._id, date: dateAt(sunday, 4, 16), status: 'completed', notes: 'Perfezionamento tecnica sollevamenti olimpici',
location: { address: gyms[3].location.address, lat: gyms[3].location.lat, lng: gyms[3].location.lng } }
);
// ── Marco: 3 completati settimana precedente ─────────────────────────
appts.push(
// Lun scorso @ FitZone Centro — Mario
{ coach: coaches[0]._id, client: users[0]._id, date: dateAt(sunday, -6, 10), status: 'completed', notes: 'Sessione gambe, focus sulla profondità dello squat',
location: { address: gyms[0].location.address, lat: gyms[0].location.lat, lng: gyms[0].location.lng } },
// Mer scorsa @ PowerGym Elite — Davide (primo appuntamento)
{ coach: coaches[0]._id, client: users[6]._id, date: dateAt(sunday, -4, 17), status: 'completed', notes: 'Prima sessione con Davide: valutazione della forma su squat e stacco',
location: { address: gyms[1].location.address, lat: gyms[1].location.lat, lng: gyms[1].location.lng } },
// Ven scorsa @ Iron Temple Gym — Sofia
{ coach: coaches[0]._id, client: users[3]._id, date: dateAt(sunday, -2, 15), status: 'completed', notes: 'Sessione condizionamento: circuito bilanciere ad alta frequenza',
location: { address: gyms[3].location.address, lat: gyms[3].location.lat, lng: gyms[3].location.lng } }
);
// ── Marco: 4 completati due settimane fa ────────────────────────────
appts.push(
// Lun -2 settimane @ FitZone Centro — Mario
{ coach: coaches[0]._id, client: users[0]._id, date: dateAt(sunday, -13, 10), status: 'completed', notes: 'Sessione forza: squat 96 kg, stacco 117 kg. Progressi costanti.',
location: { address: gyms[0].location.address, lat: gyms[0].location.lat, lng: gyms[0].location.lng } },
// Mar -2 settimane @ Active Fitness — Francesca (prima sessione)
{ coach: coaches[0]._id, client: users[7]._id, date: dateAt(sunday, -12, 14), status: 'completed', notes: 'Valutazione iniziale con Francesca. Definizione del programma personalizzato.',
location: { address: gyms[2].location.address, lat: gyms[2].location.lat, lng: gyms[2].location.lng } },
// Gio -2 settimane @ PowerGym Elite — Mario
{ coach: coaches[0]._id, client: users[0]._id, date: dateAt(sunday, -10, 11), status: 'completed', notes: 'Sessione parte superiore: panca 80 kg, rematore 62 kg',
location: { address: gyms[1].location.address, lat: gyms[1].location.lat, lng: gyms[1].location.lng } },
// Ven -2 settimane @ Iron Temple Gym — Sofia
{ coach: coaches[0]._id, client: users[3]._id, date: dateAt(sunday, -9, 16), status: 'completed', notes: 'Tecnica pulizia bilanciere + lavoro sulla bassa schiena',
location: { address: gyms[3].location.address, lat: gyms[3].location.lat, lng: gyms[3].location.lng } }
);
// ── Elena: 3 completati questa settimana ────────────────────────────
appts.push(
// Lun 14:00 — con Laura
{ coach: coaches[1]._id, client: users[1]._id, date: dateAt(sunday, 1, 14), status: 'completed', notes: 'Riabilitazione spalla - ottimi progressi',
location: { address: gyms[2].location.address, lat: gyms[2].location.lat, lng: gyms[2].location.lng } },
// Mer 18:00 — con Alessandro
{ coach: coaches[1]._id, client: users[4]._id, date: dateAt(sunday, 3, 18), status: 'completed', notes: 'Sessione funzionale a corpo completo',
location: { address: gyms[2].location.address, lat: gyms[2].location.lat, lng: gyms[2].location.lng } },
// Gio 10:00 — con Laura
{ coach: coaches[1]._id, client: users[1]._id, date: dateAt(sunday, 4, 10), status: 'completed', notes: 'Continuazione mobilità',
location: { address: gyms[2].location.address, lat: gyms[2].location.lat, lng: gyms[2].location.lng } }
);
// ── Luca: 2 completati questa settimana ─────────────────────────────
appts.push(
// Mar 17:00 — con Giuseppe
{ coach: coaches[2]._id, client: users[2]._id, date: dateAt(sunday, 2, 17), status: 'completed', notes: 'Prima sessione - programma dimagrimento',
location: { address: gyms[3].location.address, lat: gyms[3].location.lat, lng: gyms[3].location.lng } },
// Gio 18:00 — con Chiara
{ coach: coaches[2]._id, client: users[5]._id, date: dateAt(sunday, 4, 18), status: 'completed', notes: 'Valutazione della forza per la corsa',
location: { address: gyms[3].location.address, lat: gyms[3].location.lat, lng: gyms[3].location.lng } }
);
// ── Appuntamenti FUTURI confermati ───────────────────────────────────
appts.push(
// Marco — 6 appuntamenti futuri su 4 palestre Catania
{ coach: coaches[0]._id, client: users[0]._id, date: dateAt(now, 1, 10), status: 'confirmed', notes: 'Sessione gambe: nuovo tentativo 105 kg squat',
location: { address: gyms[0].location.address, lat: gyms[0].location.lat, lng: gyms[0].location.lng } },
{ coach: coaches[0]._id, client: users[3]._id, date: dateAt(now, 2, 16), status: 'confirmed', notes: 'Sessione condizionamento atletico e forza esplosiva',
location: { address: gyms[1].location.address, lat: gyms[1].location.lat, lng: gyms[1].location.lng } },
{ coach: coaches[0]._id, client: users[6]._id, date: dateAt(now, 3, 17), status: 'confirmed', notes: 'Seconda sessione Davide: introduzione al programma di forza base',
location: { address: gyms[3].location.address, lat: gyms[3].location.lat, lng: gyms[3].location.lng } },
{ coach: coaches[0]._id, client: users[7]._id, date: dateAt(now, 5, 14), status: 'confirmed', notes: 'Seconda sessione Francesca: esercizi fondamentali e mobilità',
location: { address: gyms[2].location.address, lat: gyms[2].location.lat, lng: gyms[2].location.lng } },
{ coach: coaches[0]._id, client: users[0]._id, date: dateAt(now, 6, 10), status: 'confirmed', notes: 'Sessione parte superiore: panca e rematore',
location: { address: gyms[1].location.address, lat: gyms[1].location.lat, lng: gyms[1].location.lng } },
{ coach: coaches[0]._id, client: users[3]._id, date: dateAt(now, 8, 16), status: 'confirmed', notes: 'Programmazione prossimo ciclo di allenamento',
location: { address: gyms[0].location.address, lat: gyms[0].location.lat, lng: gyms[0].location.lng } },
{ coach: coaches[0]._id, client: users[6]._id, date: dateAt(now, 10, 17), status: 'confirmed', notes: 'Valutazione progressi Davide dopo due settimane',
location: { address: gyms[3].location.address, lat: gyms[3].location.lat, lng: gyms[3].location.lng } },
{ coach: coaches[0]._id, client: users[7]._id, date: dateAt(now, 12, 15), status: 'confirmed', notes: 'Terza sessione Francesca: carichi progressivi',
location: { address: gyms[2].location.address, lat: gyms[2].location.lat, lng: gyms[2].location.lng } },
// Elena
{ coach: coaches[1]._id, client: users[1]._id, date: dateAt(now, 1, 14), status: 'confirmed', notes: 'Continuazione riabilitazione',
location: { address: gyms[2].location.address, lat: gyms[2].location.lat, lng: gyms[2].location.lng } },
{ coach: coaches[1]._id, client: users[4]._id, date: dateAt(now, 3, 19), status: 'confirmed',
location: { address: gyms[2].location.address, lat: gyms[2].location.lat, lng: gyms[2].location.lng } },
// Luca
{ coach: coaches[2]._id, client: users[2]._id, date: dateAt(now, 2, 17), status: 'confirmed', notes: 'Verifica settimanale del peso corporeo',
location: { address: gyms[3].location.address, lat: gyms[3].location.lat, lng: gyms[3].location.lng } },
{ coach: coaches[2]._id, client: users[5]._id, date: dateAt(now, 5, 18), status: 'confirmed', notes: 'Revisione programma corsa',
location: { address: gyms[3].location.address, lat: gyms[3].location.lat, lng: gyms[3].location.lng } },
// Marco — 2 appuntamenti in zone senza marker completati
// Zona nord-ovest Catania (Via Galatea — nessun completato in questa area)
{ coach: coaches[0]._id, client: users[0]._id, date: dateAt(now, 7, 11), status: 'confirmed', notes: 'Sessione stacco da terra: obiettivo 125 kg',
location: { address: 'Via Galatea 14, Catania', lat: 37.5210, lng: 15.0672 } },
// Zona sud Catania — Librino (Via Palermo — area distante dalle palestre abituali)
{ coach: coaches[0]._id, client: users[7]._id, date: dateAt(now, 9, 15), status: 'confirmed', notes: 'Sessione mobilità e rinforzo muscolare per Francesca',
location: { address: 'Via Palermo 112, Catania', lat: 37.4895, lng: 15.0645 } }
);
await Appointment.create(appts);
const completedThisWeek = appts.filter(a => a.status === 'completed').length;
console.log(`✅ Created ${appts.length} appointments (${completedThisWeek} completed this week)`);
// ─── REVIEWS ──────────────────────────────────────────────────────────
//
// Obiettivo: riempire il grafico "Valutazione nel Tempo" del coach.
// Il chart raggruppa le recensioni per mese e ne calcola la media.
// Per avere 6 punti sul grafico, servono recensioni in 6 mesi diversi.
//
// IMPORTANTE: il modello Review ha `timestamps: true` e un campo
// esplicito `createdAt`. Creiamo i documenti con `new Review()` e
// impostiamo `createdAt` manualmente prima di `save()`, così Mongoose
// rispetta la data che vogliamo invece di usare Date.now.
//
// Il post-save hook di Review aggiorna automaticamente rating e
// totalReviews del coach — non serve farlo a mano.
//
// Trend:
// Marco → da 4.0 a 5.0 (crescita costante)
// Elena → costantemente alta 4.5-5.0
// Luca → da 3.5 a 5.0 (miglioramento marcato)
const reviewsData = [
// ── Marco ─────────────────────────────────────────────────────────
// Trend: partenza incerta → miglioramento → picco → piccola flessione → consolidamento
{ coach: coaches[0]._id, user: users[7]._id, rating: 3.5, createdAt: monthsAgo(5), comment: 'Il programma iniziale mi sembrava troppo generico per le mie esigenze. Marco ha dimostrato comunque disponibilità nel personalizzarlo nel corso delle settimane.' },
{ coach: coaches[0]._id, user: users[6]._id, rating: 4.0, createdAt: monthsAgo(4), comment: 'Schede ben strutturate, competenza tecnica indiscutibile. La comunicazione è migliorata rispetto ai primi mesi. In crescita.' },
{ coach: coaches[0]._id, user: users[4]._id, rating: 5.0, createdAt: monthsAgo(3), comment: 'Progressione straordinaria in due mesi. Ha individuato con precisione i miei punti deboli e costruito un piano attorno a quelli. Il migliore con cui abbia mai lavorato.' },
{ coach: coaches[0]._id, user: users[3]._id, rating: 3.5, createdAt: monthsAgo(2), comment: 'Periodo complicato: le ultime schede erano probabilmente eccessive per il mio recupero. Qualche infortunio minore da gestire. Mi aspettavo un adattamento più rapido del programma.' },
{ coach: coaches[0]._id, user: users[0]._id, rating: 5.0, createdAt: monthsAgo(1), comment: 'In tre mesi: squat da 80 a 102 kg, panca da 65 a 83 kg, stacco da 90 a 122 kg. Numeri che parlano da soli. Marco segue ogni dettaglio con attenzione.' },
{ coach: coaches[0]._id, user: users[2]._id, rating: 4.5, createdAt: monthsAgo(0), comment: 'Eccellente preparatore fisico. Risposta ai messaggi a volte lenta, ma la qualità del lavoro è molto alta. Consigliato a chi è disposto a impegnarsi seriamente.' },
// ── Elena ─────────────────────────────────────────────────────────
{ coach: coaches[1]._id, user: users[6]._id, rating: 4.5, createdAt: monthsAgo(5), comment: 'Elena è fantastica! Approccio olistico al benessere unico nel suo genere.' },
{ coach: coaches[1]._id, user: users[7]._id, rating: 5, createdAt: monthsAgo(4), comment: 'Molto preparata, spiega ogni esercizio con precisione. Mai avuto un coach così attento.' },
{ coach: coaches[1]._id, user: users[5]._id, rating: 5, createdAt: monthsAgo(3), comment: 'Grazie a Elena ho recuperato la mobilità dopo 3 anni di problemi alla spalla!' },
{ coach: coaches[1]._id, user: users[3]._id, rating: 5, createdAt: monthsAgo(2), comment: 'Consigliata da un fisioterapista, non sono rimasto deluso. Top assoluto!' },
{ coach: coaches[1]._id, user: users[4]._id, rating: 5, createdAt: monthsAgo(1), comment: 'Non ho più mal di schiena dopo anni di problemi. Elena è una professionista eccellente!' },
{ coach: coaches[1]._id, user: users[1]._id, rating: 5, createdAt: monthsAgo(0), comment: 'Fondamentale per il mio recupero dopo la gravidanza. Professionalità e attenzione fuori dal comune.' },
// ── Luca ──────────────────────────────────────────────────────────
{ coach: coaches[2]._id, user: users[7]._id, rating: 3, createdAt: monthsAgo(5), comment: 'Programma molto intenso, forse troppo per chi inizia. Ma i risultati ci sono.' },
{ coach: coaches[2]._id, user: users[6]._id, rating: 3.5, createdAt: monthsAgo(4), comment: 'Buoni risultati in 4 settimane. Potrebbe essere più disponibile nelle risposte.' },
{ coach: coaches[2]._id, user: users[3]._id, rating: 4, createdAt: monthsAgo(3), comment: 'Ottimo per dimagrimento. Approccio scientifico che funziona davvero!' },
{ coach: coaches[2]._id, user: users[4]._id, rating: 5, createdAt: monthsAgo(2), comment: 'Ho perso 8kg in 6 settimane! Programma rigoroso ma i risultati parlano chiaro!' },
{ coach: coaches[2]._id, user: users[5]._id, rating: 4, createdAt: monthsAgo(1), comment: 'Ottimo per dimagrimento e trasformazione fisica. Consigliatissimo!' },
{ coach: coaches[2]._id, user: users[2]._id, rating: 5, createdAt: monthsAgo(0), comment: 'Ho perso 12 kg in due mesi seguendo il programma di Luca. Un percorso che ha cambiato radicalmente le mie abitudini.' }
];
// Crea le review una per una impostando createdAt manuale
for (const r of reviewsData) {
const doc = new Review({
coach: r.coach, user: r.user,
rating: r.rating, comment: r.comment
});
doc.createdAt = r.createdAt; // sovrascrive il default Date.now
doc.updatedAt = r.createdAt;
await doc.save(); // il post-save hook aggiorna automaticamente il coach
}
console.log(`✅ Created ${reviewsData.length} reviews (distributed over 6 months)`);
// ─── POSTS ───────────────────────────────────────────────────────────
await Post.create([
{
author: coaches[0]._id,
content: 'Ottimo risultato per Mario questa settimana: nuovo record personale allo squat con 120 kg per 5 ripetizioni! Quando ha iniziato tre mesi fa faticava con 80 kg. Questo è il risultato concreto di una programmazione intelligente e di una costanza esemplare. Prossimo obiettivo: 140 kg.',
likes: [users[0]._id, users[1]._id, users[3]._id, users[7]._id, coaches[1]._id],
comments: [
{ user: users[0]._id, text: 'Grazie Coach, non ci credevo quando mi hai detto che ce l\'avrei fatta. Ora punto ai 140 kg!' },
{ user: users[3]._id, text: 'Complimenti Mario, un risultato davvero notevole.' }
]
},
{
author: users[0]._id,
content: 'Dodicesima settimana del programma completata. La forza su tutti gli esercizi principali è in costante crescita, il peso corporeo è stabile ma la composizione è visibilmente migliorata. Chiunque abbia dubbi sull\'efficacia di una programmazione seria dovrebbe provare a lavorare con un coach qualificato. Grazie Marco per il supporto quotidiano.',
likes: [coaches[0]._id, users[1]._id, users[2]._id, users[4]._id]
},
{
author: coaches[1]._id,
content: 'Riflessione sulla mobilità articolare: non si tratta solo di allungarsi.\n\nLa vera mobilità è forza espressa nell\'intera ampiezza di movimento. Include controllo, stabilità e coordinazione: non basta allungare un muscolo, occorre anche rafforzare le nuove posizioni acquisite.\n\nConsigio: dedicate almeno 15 minuti prima dell\'allenamento alla mobilità dinamica. I risultati sugli esercizi principali saranno evidenti.',
likes: [users[1]._id, users[4]._id, users[6]._id, coaches[0]._id],
comments: [
{ user: users[1]._id, text: 'Assolutamente vero. Da quando mi dedico alla mobilità in modo sistematico i dolori alle spalle sono scomparsi. Grazie Elena.' },
{ user: users[4]._id, text: 'Un consiglio prezioso. Dovrebbero leggerlo tutti.' }
]
},
{
author: users[3]._id,
content: 'Sessione gambe di oggi:\n\n5x3 Slancio con bilanciere a 60 kg\n5x10 Trazioni\n4x8 Salto sul box (60 cm)\n\nDomani mi alzerò dal letto con qualche difficoltà, ma la soddisfazione è grande. Il condizionamento atletico richiede sacrificio ma i risultati si vedono.',
likes: [coaches[0]._id, users[0]._id, users[7]._id]
},
{
author: coaches[2]._id,
content: 'Un principio fondamentale della trasformazione fisica: non si può compensare un\'alimentazione scorretta con il solo allenamento.\n\nLa composizione corporea dipende per circa il 70% dall\'alimentazione, per il 20% dall\'allenamento e per il 10% dal recupero. Imparare a gestire l\'apporto calorico, almeno nella fase iniziale, e dare priorità a proteine e verdure sono passi imprescindibili per chi cerca risultati duraturi.',
likes: [users[2]._id, users[5]._id, coaches[1]._id]
},
{
author: users[2]._id,
content: 'Aggiornamento dopo sei settimane di programma: meno 8 kg.\n\nNel corso degli anni ho provato numerosi approcci senza risultati stabili. Con Coach Luca ho finalmente trovato un metodo che funziona: un piano strutturato, obiettivi chiari e un monitoraggio costante dei progressi. A chi sta valutando di iniziare: vale la pena farlo con serietà.',
likes: [coaches[2]._id, users[0]._id, users[1]._id, users[5]._id],
comments: [
{ user: coaches[2]._id, text: 'Ottimo lavoro Giuseppe. Questi risultati sono il frutto della tua costanza e dedizione. Continuiamo così.' },
{ user: users[1]._id, text: 'Risultato straordinario. Continua a impegnarti così.' }
]
},
{
author: users[1]._id,
content: 'Primo allenamento dopo due anni di interruzione forzata.\n\nNon sono più quella di prima, ma sto tornando in forma con gradualità. Squat con manubrio, plank, piegamenti sulle braccia: tutto è impegnativo ma la sensazione di muoversi di nuovo è bellissima.\n\nGrazie a Elena per il programma calibrato sulle mie esigenze e per la grande pazienza.',
likes: [coaches[1]._id, users[0]._id, users[3]._id, users[4]._id]
},
{
author: coaches[0]._id,
content: 'I cinque errori tecnici più frequenti nello stacco da terra, che possono portare a infortuni:\n\n1. Schiena curva durante il sollevamento\n2. Bilanciere tenuto lontano dalle tibie\n3. Tirare con le braccia anziché spingere il pavimento con i piedi\n4. Non attivare i muscoli dorsali prima del sollevamento\n5. Iperestendere la schiena nella fase finale\n\nLa tecnica corretta viene sempre prima del carico. Senza eccezioni.',
likes: [users[0]._id, users[3]._id, users[7]._id, coaches[1]._id]
}
]);
console.log('✅ Created 8 posts');
// ─── MESSAGES ────────────────────────────────────────────────────────
await Message.create([
{ sender: users[0]._id, receiver: coaches[0]._id, content: 'Ciao Coach, oggi ho eseguito lo squat a 120 kg e sono riuscito a completare 3 ripetizioni. Pensi che sia il momento giusto per aumentare il carico?' },
{ sender: coaches[0]._id, receiver: users[0]._id, content: 'Ottimo lavoro Mario. Tre ripetizioni a 120 kg è un risultato solido. Ti consiglio di consolidare ancora una settimana a questo carico, poi la prossima settimana aumentiamo a 125 kg.' },
{ sender: users[0]._id, receiver: coaches[0]._id, content: 'Perfetto, grazie per il consiglio. Ci vediamo giovedì per la sessione?' },
{ sender: coaches[0]._id, receiver: users[0]._id, content: 'Certamente, giovedì alle 10:00 da FitZone. Sarà una sessione focalizzata sugli arti inferiori.' },
{ sender: users[1]._id, receiver: coaches[1]._id, content: 'Elena, durante gli squat con manubrio di oggi ho avvertito un fastidio alla spalla. Non era dolore acuto, ma un leggero bruciore.' },
{ sender: coaches[1]._id, receiver: users[1]._id, content: 'Grazie per avermelo comunicato Laura. Domani durante la sessione faremo una valutazione accurata. Nel frattempo applica ghiaccio per 15 minuti, tre volte nel corso della giornata. Non preoccuparti.' },
{ sender: users[2]._id, receiver: coaches[2]._id, content: 'Coach, sono già a meno 8 kg. Non riuscivo a crederci. Grazie per il supporto costante.' },
{ sender: coaches[2]._id, receiver: users[2]._id, content: 'Sono molto soddisfatto dei tuoi progressi Giuseppe. Questi risultati sono frutto della tua dedizione. Continuando con questo ritmo raggiungeremo l\'obiettivo dei 15 kg entro il secondo mese.' }
]);
console.log('✅ Created 8 messages');
// ─── NOTIFICATIONS ───────────────────────────────────────────────────
//
// Notifiche per Mario (users[0]) e Marco (coaches[0]).
// Alcune già lette (read: true), altre nuove (read: false) per simulare
// uno stato realistico della campanella.
// Types: 'workout_plan' | 'subscription' | 'message' | 'workout_completed' | 'appointment'
const notifs = [];
// ── Notifiche per Mario ───────────────────────────────────────────────
notifs.push(
// Scheda assegnata (letta)
{