ajout bibliothèque méditation et changement de test

This commit is contained in:
2026-04-26 13:02:19 +02:00
parent f3092f2dc4
commit 5b2a2e7ddb
50 changed files with 477 additions and 778 deletions
+6
View File
@@ -39,6 +39,12 @@
<excludeFolder url="file://$MODULE_DIR$/mobile/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/.dart_tool" /> <excludeFolder url="file://$MODULE_DIR$/mobile/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/mobile/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/.pub" /> <excludeFolder url="file://$MODULE_DIR$/mobile/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/.pub" />
<excludeFolder url="file://$MODULE_DIR$/mobile/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/build" /> <excludeFolder url="file://$MODULE_DIR$/mobile/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/build" />
<excludeFolder url="file://$MODULE_DIR$/mobile/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/mobile/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/.pub" />
<excludeFolder url="file://$MODULE_DIR$/mobile/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/build" />
<excludeFolder url="file://$MODULE_DIR$/mobile/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/mobile/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/.pub" />
<excludeFolder url="file://$MODULE_DIR$/mobile/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/build" />
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
+36
View File
@@ -87,6 +87,18 @@
<option name="screenX" value="720" /> <option name="screenX" value="720" />
<option name="screenY" value="1600" /> <option name="screenY" value="1600" />
</PersistentDeviceSelectionData> </PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="30" />
<option name="brand" value="realme" />
<option name="codename" value="RMX3231" />
<option name="id" value="RMX3231" />
<option name="labId" value="google" />
<option name="manufacturer" value="realme" />
<option name="name" value="C11" />
<option name="screenDensity" value="320" />
<option name="screenX" value="720" />
<option name="screenY" value="1600" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData> <PersistentDeviceSelectionData>
<option name="api" value="36" /> <option name="api" value="36" />
<option name="brand" value="samsung" /> <option name="brand" value="samsung" />
@@ -1038,6 +1050,30 @@
<option name="screenX" value="1600" /> <option name="screenX" value="1600" />
<option name="screenY" value="2560" /> <option name="screenY" value="2560" />
</PersistentDeviceSelectionData> </PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="30" />
<option name="brand" value="motorola" />
<option name="codename" value="guamna" />
<option name="id" value="guamna" />
<option name="labId" value="google" />
<option name="manufacturer" value="Motorola" />
<option name="name" value="Moto XT2093-3" />
<option name="screenDensity" value="280" />
<option name="screenX" value="720" />
<option name="screenY" value="1600" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="30" />
<option name="brand" value="motorola" />
<option name="codename" value="guamp" />
<option name="id" value="guamp" />
<option name="labId" value="google" />
<option name="manufacturer" value="Motorola" />
<option name="name" value="Moto XT2083-1" />
<option name="screenDensity" value="280" />
<option name="screenX" value="720" />
<option name="screenY" value="1600" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData> <PersistentDeviceSelectionData>
<option name="api" value="34" /> <option name="api" value="34" />
<option name="brand" value="google" /> <option name="brand" value="google" />
@@ -12,7 +12,22 @@ class DiagnosticController extends Controller
public function index() public function index()
{ {
$events = StressEvent::all(); $events = StressEvent::all();
return view('diagnostics.index', compact('events')); $history = [];
if (Auth::check()) {
$history = \App\Models\ResultatDiag::where('id_user', Auth::id())
->orderBy('date_passage', 'desc')
->take(5)
->get();
}
return view('diagnostics.index', compact('events', 'history'));
}
public function history()
{
$history = \App\Models\ResultatDiag::where('id_user', Auth::id())
->orderBy('date_passage', 'desc')
->get();
return view('diagnostics.history', compact('history'));
} }
public function store(Request $request) public function store(Request $request)
@@ -23,8 +38,24 @@ class DiagnosticController extends Controller
$totalPoints = StressEvent::whereIn('id', $request->events)->sum('points'); $totalPoints = StressEvent::whereIn('id', $request->events)->sum('points');
} }
// Ici on pourrait enregistrer le résultat dans une table 'diagnostic_results' $niveauStress = 'Faible';
// Pour l'instant on redirige avec le score if ($totalPoints >= 300) {
$niveauStress = 'Élevé';
} elseif ($totalPoints >= 150) {
$niveauStress = 'Modéré';
}
// Enregistrement si l'utilisateur est connecté
if (Auth::check()) {
\App\Models\ResultatDiag::create([
'id_user' => Auth::id(),
'score_total' => $totalPoints,
'niveau_stress' => $niveauStress,
'event_ids' => $request->has('events') ? implode(';', $request->events) : null,
'date_passage' => now(),
]);
}
return redirect()->back()->with('score', $totalPoints); return redirect()->back()->with('score', $totalPoints);
} }
} }
@@ -13,26 +13,13 @@ class RelaxationController extends Controller
public function index() public function index()
{ {
$activities = RelaxationActivity::all(); $activities = RelaxationActivity::all();
$favorites = Auth::check() ? Auth::user()->favoritedBy->pluck('id')->toArray() : []; $favorites = [];
return view('relaxation.index', compact('activities', 'favorites')); return view('relaxation.index', compact('activities', 'favorites'));
} }
public function toggleFavorite($id) public function toggleFavorite($id)
{ {
$userId = Auth::id(); // Fonctionnalité désactivée pour le moment
$favorite = Favorite::where('user_id', $userId) return response()->json(['status' => 'disabled']);
->where('relaxation_activity_id', $id)
->first();
if ($favorite) {
$favorite->delete();
return response()->json(['status' => 'removed']);
} else {
Favorite::create([
'user_id' => $userId,
'relaxation_activity_id' => $id
]);
return response()->json(['status' => 'added']);
}
} }
} }
+24 -1
View File
@@ -2,9 +2,32 @@
namespace App\Models; namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
class ResultatDiag extends Model class ResultatDiag extends Model
{ {
// use HasFactory;
protected $table = 'resultat_diags';
protected $fillable = [
'id_user',
'date_passage',
'score_total',
'niveau_stress',
'event_ids'
];
public function user()
{
return $this->belongsTo(User::class, 'id_user');
}
public function getEventsAttribute()
{
if (!$this->event_ids) return collect();
$ids = explode(';', $this->event_ids);
return StressEvent::whereIn('id', $ids)->get();
}
} }
@@ -1,28 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('categories', function (Blueprint $table) {
$table->id(); // id_categorie
$table->string('libelle');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('categories');
}
};
@@ -1,28 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('roles', function (Blueprint $table) {
$table->id(); // id_role [cite: 210]
$table->string('libelle');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('roles');
}
};
@@ -1,32 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('activites', function (Blueprint $table) {
$table->id(); // id_activite
$table->string('titre');
$table->text('description');
$table->string('url_media');
$table->boolean('est_active')->default(true);
$table->foreignId('id_categorie')->constrained('categories'); // Asso_4
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('activites');
}
};
@@ -1,51 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->foreignId('id_role')->constrained('roles'); // Asso_1
$table->string('password');
$table->timestamp('date_inscription')->useCurrent();
$table->rememberToken();
$table->timestamps();
});
Schema::create('password_reset_tokens', function (Blueprint $table) {
$table->string('email')->primary();
$table->string('token');
$table->timestamp('created_at')->nullable();
});
Schema::create('sessions', function (Blueprint $table) {
$table->string('id')->primary();
$table->foreignId('user_id')->nullable()->index();
$table->string('ip_address', 45)->nullable();
$table->text('user_agent')->nullable();
$table->longText('payload');
$table->integer('last_activity')->index();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('users');
Schema::dropIfExists('password_reset_tokens');
Schema::dropIfExists('sessions');
}
};
@@ -1,35 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('cache', function (Blueprint $table) {
$table->string('key')->primary();
$table->mediumText('value');
$table->integer('expiration')->index();
});
Schema::create('cache_locks', function (Blueprint $table) {
$table->string('key')->primary();
$table->string('owner');
$table->integer('expiration')->index();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('cache');
Schema::dropIfExists('cache_locks');
}
};
@@ -1,57 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('jobs', function (Blueprint $table) {
$table->id();
$table->string('queue')->index();
$table->longText('payload');
$table->unsignedTinyInteger('attempts');
$table->unsignedInteger('reserved_at')->nullable();
$table->unsignedInteger('available_at');
$table->unsignedInteger('created_at');
});
Schema::create('job_batches', function (Blueprint $table) {
$table->string('id')->primary();
$table->string('name');
$table->integer('total_jobs');
$table->integer('pending_jobs');
$table->integer('failed_jobs');
$table->longText('failed_job_ids');
$table->mediumText('options')->nullable();
$table->integer('cancelled_at')->nullable();
$table->integer('created_at');
$table->integer('finished_at')->nullable();
});
Schema::create('failed_jobs', function (Blueprint $table) {
$table->id();
$table->string('uuid')->unique();
$table->text('connection');
$table->text('queue');
$table->longText('payload');
$table->longText('exception');
$table->timestamp('failed_at')->useCurrent();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('jobs');
Schema::dropIfExists('job_batches');
Schema::dropIfExists('failed_jobs');
}
};
@@ -0,0 +1,16 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
public function up(): void {
Schema::create('roles', function (Blueprint $table) {
$table->id();
$table->string('libelle');
$table->timestamps();
});
}
public function down(): void { Schema::dropIfExists('roles'); }
};
@@ -0,0 +1,21 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
public function up(): void {
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->foreignId('id_role')->constrained('roles');
$table->rememberToken();
$table->timestamps();
});
}
public function down(): void { Schema::dropIfExists('users'); }
};
@@ -0,0 +1,17 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
public function up(): void {
Schema::create('stress_events', function (Blueprint $table) {
$table->id();
$table->string('event_name');
$table->integer('points');
$table->timestamps();
});
}
public function down(): void { Schema::dropIfExists('stress_events'); }
};
@@ -4,29 +4,18 @@ use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
return new class extends Migration return new class extends Migration {
{ public function up(): void {
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('relaxation_activities', function (Blueprint $table) { Schema::create('relaxation_activities', function (Blueprint $table) {
$table->id(); $table->id();
$table->string('title'); $table->string('title');
$table->text('description');
$table->string('type'); // audio, video, article $table->string('type'); // audio, video, article
$table->string('duration')->nullable(); $table->string('category');
$table->string('url')->nullable(); $table->string('url')->nullable();
$table->text('description')->nullable(); $table->string('image_url')->nullable();
$table->timestamps(); $table->timestamps();
}); });
} }
public function down(): void { Schema::dropIfExists('relaxation_activities'); }
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('relaxation_activities');
}
}; };
@@ -4,28 +4,17 @@ use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
return new class extends Migration return new class extends Migration {
{ public function up(): void {
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('resultat_diags', function (Blueprint $table) { Schema::create('resultat_diags', function (Blueprint $table) {
$table->id(); // id_resultat $table->id();
$table->foreignId('id_user')->constrained('users'); // Asso_3 $table->foreignId('id_user')->constrained('users')->onDelete('cascade');
$table->timestamp('date_passage')->useCurrent(); $table->timestamp('date_passage')->useCurrent();
$table->integer('score_total'); $table->integer('score_total');
$table->string('niveau_stress'); $table->string('niveau_stress');
$table->text('event_ids')->nullable();
$table->timestamps(); $table->timestamps();
}); });
} }
public function down(): void { Schema::dropIfExists('resultat_diags'); }
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('resultat_diags');
}
}; };
@@ -0,0 +1,19 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
public function up(): void {
Schema::create('emotion_records', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained('users')->onDelete('cascade');
$table->string('emotion');
$table->integer('intensity')->default(3);
$table->text('note')->nullable();
$table->timestamps();
});
}
public function down(): void { Schema::dropIfExists('emotion_records'); }
};
@@ -1,33 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('personal_access_tokens', function (Blueprint $table) {
$table->id();
$table->morphs('tokenable');
$table->text('name');
$table->string('token', 64)->unique();
$table->text('abilities')->nullable();
$table->timestamp('last_used_at')->nullable();
$table->timestamp('expires_at')->nullable()->index();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('personal_access_tokens');
}
};
@@ -1,29 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('stress_events', function (Blueprint $table) {
$table->id();
$table->string('event_name'); // Nom de l'événement (ex: Mariage, Licenciement)
$table->integer('points'); // Valeur selon l'échelle de Holmes et Rahe
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('stress_events');
}
};
@@ -1,31 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('emotion_records', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->string('emotion'); // joy, sad, angry, etc.
$table->integer('intensity'); // 1 to 5
$table->text('note')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('emotion_records');
}
};
@@ -1,35 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('favorites', function (Blueprint $table) {
$table->foreignId('id_user')->constrained('users')->onDelete('cascade');
// id_activite fait référence à la table activites
// C'est ici que l'erreur se produit si le nom ne correspond pas exactement
$table->foreignId('id_activite')->constrained('activites')->onDelete('cascade');
$table->timestamp('date_ajout')->useCurrent();
// Clé primaire composée pour éviter les doublons (RGPD/Qualité)
$table->primary(['id_user', 'id_activite']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('favorites');
}
};
@@ -1,29 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('emotions', function (Blueprint $table) {
$table->id(); // id_emotion
$table->string('libelle');
$table->foreignId('id_parent')->nullable()->constrained('emotions'); // Asso_7
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('emotions');
}
};
@@ -1,29 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('evenement_stress', function (Blueprint $table) {
$table->id(); // id_event
$table->string('libelle');
$table->integer('points'); // Points associés à l'échelle [cite: 126]
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('evenement_stress');
}
};
@@ -1,31 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('exercice_respi', function (Blueprint $table) {
$table->id(); // id_respi
$table->string('nom');
$table->integer('duree_inspi'); // Cohérence cardiaque [cite: 133]
$table->integer('duree_apnee'); // [cite: 134]
$table->integer('duree_expi'); // [cite: 135]
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('exercice_respi');
}
};
@@ -1,30 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('journal_entrees', function (Blueprint $table) {
$table->id(); // id_entree
$table->foreignId('id_user')->constrained('users'); // Asso_8 [cite: 98]
$table->timestamp('date_heure')->useCurrent();
$table->text('commentaire')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('journal_entrees');
}
};
@@ -1,27 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('users_table_cesizen', function (Blueprint $table) {
$table->id();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('users_table_cesizen');
}
};
@@ -1,31 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('contenu_infos', function (Blueprint $table) {
$table->id(); // id_contenu
$table->string('titre');
$table->text('texte_contenu');
$table->timestamp('date_publication')->useCurrent();
$table->foreignId('id_auteur')->constrained('users'); // Asso_2
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('contenu_infos');
}
};
@@ -1,28 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('detail_resultats', function (Blueprint $table) {
$table->foreignId('id_resultat')->constrained('resultat_diags')->onDelete('cascade');
$table->foreignId('id_event')->constrained('evenement_stress');
$table->primary(['id_resultat', 'id_event']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('detail_resultats');
}
};
@@ -1,29 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('emotions_ressenties', function (Blueprint $table) {
$table->foreignId('id_entree')->constrained('journal_entrees')->onDelete('cascade');
$table->foreignId('id_emotion')->constrained('emotions');
$table->integer('intensite');
$table->primary(['id_entree', 'id_emotion']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('emotions_ressenties');
}
};
@@ -1,27 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('favoris', function (Blueprint $table) {
$table->id();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('favoris');
}
};
@@ -1,27 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('historique_respi', function (Blueprint $table) {
$table->id();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('historique_respi');
}
};
+1
View File
@@ -21,6 +21,7 @@ class DatabaseSeeder extends Seeder
$this->call([ $this->call([
RoleSeeder::class, RoleSeeder::class,
StressEventSeeder::class, StressEventSeeder::class,
RelaxationActivitySeeder::class,
]); ]);
$adminRole = Role::where('libelle', 'Admin')->first(); $adminRole = Role::where('libelle', 'Admin')->first();
@@ -0,0 +1,67 @@
<?php
namespace Database\Seeders;
use App\Models\RelaxationActivity;
use Illuminate\Database\Seeder;
class RelaxationActivitySeeder extends Seeder
{
public function run(): void
{
$activities = [
[
'title' => 'Méditation de Pleine Conscience',
'description' => 'Une séance guidée de 10 minutes pour se reconnecter au moment présent et calmer le flux des pensées.',
'type' => 'audio',
'category' => 'Méditation',
'url' => 'https://www.youtube.com/watch?v=sz7cpV7ERsY',
'image_url' => 'https://images.unsplash.com/photo-1506126613408-eca07ce68773?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80'
],
[
'title' => 'Yoga Doux pour le Soir',
'description' => 'Étirements légers et postures relaxantes pour préparer le corps au sommeil et relâcher les tensions de la journée.',
'type' => 'video',
'category' => 'Sport',
'url' => 'https://www.youtube.com/watch?v=v7AYKMP6rOE',
'image_url' => 'https://images.unsplash.com/photo-1544367567-0f2fcb009e0b?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80'
],
[
'title' => 'Bruits de Plage et Vagues',
'description' => 'Ambiance sonore apaisante pour le travail ou la lecture. Réduit le stress environnant.',
'type' => 'audio',
'category' => 'Musique',
'url' => 'https://www.youtube.com/watch?v=0_fS_pS_B0U',
'image_url' => 'https://images.unsplash.com/photo-1507525428034-b723cf961d3e?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80'
],
[
'title' => 'Comprendre le Cycle du Stress',
'description' => 'Un article détaillé sur les mécanismes biologiques du stress et comment les réguler au quotidien.',
'type' => 'article',
'category' => 'Lecture',
'url' => 'https://www.santepubliquefrance.fr',
'image_url' => 'https://images.unsplash.com/photo-1512820790803-83ca734da794?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80'
],
[
'title' => 'Musique Classique pour la Concentration',
'description' => 'Sélection de morceaux choisis pour favoriser le focus et la clarté mentale.',
'type' => 'audio',
'category' => 'Musique',
'url' => 'https://www.youtube.com/watch?v=5Qq3m9G4_4A',
'image_url' => 'https://images.unsplash.com/photo-1514119412350-e174d90d280e?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80'
],
[
'title' => 'Techniques de Respiration Wim Hof',
'description' => 'Apprenez la méthode de respiration qui renforce le système immunitaire et réduit l\'anxiété.',
'type' => 'video',
'category' => 'Respiration',
'url' => 'https://www.youtube.com/watch?v=tybOi4hjZFQ',
'image_url' => 'https://images.unsplash.com/photo-1518199266791-5375a83190b7?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80'
]
];
foreach ($activities as $activity) {
RelaxationActivity::create($activity);
}
}
}

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

@@ -0,0 +1,66 @@
@extends('layouts.app')
@section('title', 'Journal des Diagnostics')
@section('header_title', 'Mon Historique de Stress')
@section('content')
<div class="max-w-4xl mx-auto space-y-8">
<div class="flex items-center justify-between">
<div>
<h2 class="text-2xl font-black text-slate-900 uppercase">Journal de bord</h2>
<p class="text-slate-500">Retrouvez l'évolution de vos bilans de stress.</p>
</div>
<a href="{{ route('diagnostics.index') }}" class="px-6 py-2 bg-[--fr-blue] text-white font-bold rounded-sm shadow-md hover:bg-blue-800 transition-all text-sm uppercase tracking-widest">
Nouveau test
</a>
</div>
<div class="bg-white border border-slate-200 shadow-sm overflow-hidden">
<table class="w-full text-left border-collapse">
<thead>
<tr class="bg-slate-50 border-b border-slate-200">
<th class="px-6 py-4 text-xs font-bold text-slate-500 uppercase tracking-widest">Date du bilan</th>
<th class="px-6 py-4 text-xs font-bold text-slate-500 uppercase tracking-widest text-center">Score</th>
<th class="px-6 py-4 text-xs font-bold text-slate-500 uppercase tracking-widest">Niveau de Risque</th>
</tr>
</thead>
<tbody class="divide-y divide-slate-100">
@forelse($history as $result)
<tr class="hover:bg-slate-50 transition-colors">
<td class="px-6 py-5">
<p class="font-bold text-slate-900">{{ \Carbon\Carbon::parse($result->date_passage)->translatedFormat('d F Y') }}</p>
<p class="text-xs text-slate-400">{{ \Carbon\Carbon::parse($result->date_passage)->format('H:i') }}</p>
</td>
<td class="px-6 py-5 text-center">
<span class="text-xl font-black text-[--fr-blue]">{{ $result->score_total }}</span>
</td>
<td class="px-6 py-5">
@if($result->niveau_stress === 'Élevé')
<span class="px-3 py-1 bg-red-50 text-red-700 text-[10px] font-black uppercase rounded-full border border-red-100">Risque Élevé</span>
@elseif($result->niveau_stress === 'Modéré')
<span class="px-3 py-1 bg-orange-50 text-orange-700 text-[10px] font-black uppercase rounded-full border border-orange-100">Risque Modéré</span>
@else
<span class="px-3 py-1 bg-teal-50 text-teal-700 text-[10px] font-black uppercase rounded-full border border-teal-100">Risque Faible</span>
@endif
<div class="mt-2 flex flex-wrap gap-1">
@foreach($result->events as $event)
<span class="text-[9px] bg-slate-100 text-slate-500 px-1.5 py-0.5 rounded-sm border border-slate-200" title="{{ $event->event_name }}">
{{ Str::limit($event->event_name, 20) }}
</span>
@endforeach
</div>
</td>
</tr>
@empty
<tr>
<td colspan="4" class="px-6 py-10 text-center text-slate-400 italic">
Vous n'avez pas encore effectué de bilan de stress.
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
@endsection
@@ -25,9 +25,17 @@
</div> </div>
@else @else
<div class="bg-white p-8 border border-slate-200 shadow-sm"> <div class="bg-white p-8 border border-slate-200 shadow-sm">
<div class="mb-8"> <div class="flex items-center justify-between mb-8">
<h2 class="text-xl font-bold mb-2">Quels événements avez-vous vécus ces 12 derniers mois ?</h2> <div>
<p class="text-sm text-slate-500 italic">Cochez toutes les cases qui correspondent à votre situation actuelle.</p> <h2 class="text-xl font-bold mb-2">Quels événements avez-vous vécus ces 12 derniers mois ?</h2>
<p class="text-sm text-slate-500 italic">Cochez toutes les cases qui correspondent à votre situation actuelle.</p>
</div>
@auth
<a href="{{ route('diagnostics.history') }}" class="text-sm font-bold text-[--fr-blue] hover:underline flex items-center gap-1">
<x-heroicon-o-clock class="w-4 h-4" />
Mon Historique
</a>
@endauth
</div> </div>
<form action="{{ route('diagnostics.store') }}" method="POST" class="space-y-4"> <form action="{{ route('diagnostics.store') }}" method="POST" class="space-y-4">
@@ -49,6 +57,34 @@
</div> </div>
</form> </form>
</div> </div>
@auth
@if(count($history) > 0)
<div class="bg-white p-8 border border-slate-200 shadow-sm">
<h3 class="text-lg font-bold mb-6 flex items-center gap-2">
<x-heroicon-o-clipboard-document-list class="w-5 h-5 text-[--fr-blue]" />
Dernières entrées du journal
</h3>
<div class="space-y-4">
@foreach($history as $item)
<div class="flex items-center justify-between p-4 bg-slate-50 rounded-sm border border-slate-100">
<div>
<p class="text-sm font-bold text-slate-900">{{ \Carbon\Carbon::parse($item->date_passage)->translatedFormat('d M Y') }}</p>
<p class="text-xs text-slate-500">{{ $item->niveau_stress }}</p>
</div>
<div class="text-right">
<span class="text-lg font-black text-[--fr-blue]">{{ $item->score_total }}</span>
<p class="text-[10px] uppercase font-bold text-slate-400">points</p>
</div>
</div>
@endforeach
</div>
<div class="mt-6 text-center">
<a href="{{ route('diagnostics.history') }}" class="text-xs font-bold text-slate-400 hover:text-[--fr-blue] uppercase tracking-widest transition-colors">Voir l'historique complet</a>
</div>
</div>
@endif
@endauth
@endif @endif
</div> </div>
@endsection @endsection
+1 -1
View File
@@ -40,7 +40,7 @@
<textarea name="note" rows="3" class="w-full border-slate-200 rounded-lg focus:ring-[--fr-blue] focus:border-[--fr-blue]" placeholder="Décrivez votre état..."></textarea> <textarea name="note" rows="3" class="w-full border-slate-200 rounded-lg focus:ring-[--fr-blue] focus:border-[--fr-blue]" placeholder="Décrivez votre état..."></textarea>
</div> </div>
<button type="submit" class="w-full py-4 bg-[--fr-blue] text-white font-bold rounded-sm hover:bg-blue-800 shadow-md transition-all"> <button type="submit" class="w-full py-4 bg-[#000091] text-white font-bold rounded-sm hover:bg-blue-800 shadow-md transition-all uppercase tracking-widest">
Enregistrer dans mon journal Enregistrer dans mon journal
</button> </button>
</form> </form>
+3 -1
View File
@@ -3,8 +3,9 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<title>@yield('title', 'CESIZen') | Ministère de la Santé</title> <title>@yield('title', 'CESIZen') | Ministère de la Santé et de la Prévention</title>
@vite(['resources/css/app.css', 'resources/js/app.js']) @vite(['resources/css/app.css', 'resources/js/app.js'])
<link rel="icon" href="./img/CesiZen_logo.png" type="image/x-icon">
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script> <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
<style> <style>
:root { :root {
@@ -35,4 +36,5 @@
</main> </main>
</div> </div>
</body> </body>
@include('layouts.footer')
</html> </html>
+3 -3
View File
@@ -2,12 +2,12 @@
<div class="container mx-auto px-4 lg:px-8 py-3 flex items-center justify-between"> <div class="container mx-auto px-4 lg:px-8 py-3 flex items-center justify-between">
<div class="flex items-start justify-start gap-8"> <div class="flex items-start justify-start gap-8">
<div class="flex flex-col border-r-2 border-slate-200 pr-8" aria-hidden="true"> <div class="flex flex-col border-r-2 border-slate-200 pr-8" aria-hidden="true">
<img src="img/ministere.png" alt="Logo du Ministère de la Santé et de la Prévention" class="w-24 h-auto"> <img src="{{ asset('img/ministere.png') }}" alt="Logo du Ministère de la Santé et de la Prévention" class="w-24 h-auto">
</div> </div>
<div class="flex flex-col"> <div class="flex flex-col">
<h1 class="text-2xl font-black text-[--fr-blue] tracking-tight"> <h1 class="text-2xl font-black text-[--fr-blue] tracking-tight">
<a href="{{ route('home') }}"><img src="img/CesiZen.png" alt="Logo CesiZen" class="w-32 h-auto"></a> <a href="{{ route('home') }}"><img src="{{ asset('img/CesiZen.png') }}" alt="Logo CesiZen" class="w-32 h-auto"></a>
</h1> </h1>
</div> </div>
</div> </div>
@@ -38,4 +38,4 @@
@endauth @endauth
</nav> </nav>
</div> </div>
</header> </header>
@@ -31,7 +31,7 @@
</a> </a>
<!-- Exercices de Respiration --> <!-- Exercices de Respiration -->
<a href="{{ route('relaxation.index') }}" <a href="{{ route('relaxation.index') }}#breathing-app"
class="flex items-center gap-4 px-4 py-3 rounded-sm transition-all group {{ request()->routeIs('relaxation.*') ? 'text-white bg-[#000091] font-bold shadow-md' : 'text-slate-700 hover:bg-slate-50 font-medium border-b border-slate-100/50' }}" class="flex items-center gap-4 px-4 py-3 rounded-sm transition-all group {{ request()->routeIs('relaxation.*') ? 'text-white bg-[#000091] font-bold shadow-md' : 'text-slate-700 hover:bg-slate-50 font-medium border-b border-slate-100/50' }}"
{!! request()->routeIs('relaxation.*') ? 'aria-current="page"' : '' !!}> {!! request()->routeIs('relaxation.*') ? 'aria-current="page"' : '' !!}>
<div class="w-8 h-8 rounded-sm flex items-center justify-center transition-colors {{ request()->routeIs('relaxation.*') ? 'bg-white/20 text-white' : 'bg-indigo-50 text-indigo-700' }}" aria-hidden="true"> <div class="w-8 h-8 rounded-sm flex items-center justify-center transition-colors {{ request()->routeIs('relaxation.*') ? 'bg-white/20 text-white' : 'bg-indigo-50 text-indigo-700' }}" aria-hidden="true">
@@ -6,7 +6,7 @@
<div class="max-w-6xl mx-auto space-y-12"> <div class="max-w-6xl mx-auto space-y-12">
<!-- Module de Respiration Guidée --> <!-- Module de Respiration Guidée -->
<div x-data="breathingApp()" class="bg-white p-8 border border-slate-300 shadow-sm relative overflow-hidden"> <div id="breathing-app" x-data="breathingApp()" class="bg-white p-8 border border-slate-300 shadow-sm relative overflow-hidden">
<div class="flex flex-col lg:flex-row gap-12 items-center"> <div class="flex flex-col lg:flex-row gap-12 items-center">
<!-- Contrôles et Choix du mode --> <!-- Contrôles et Choix du mode -->
+5 -61
View File
@@ -1,69 +1,13 @@
<!DOCTYPE html> @extends('layouts.app')
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>CESIZen | Ministère de la Santé et de la Prévention</title>
<!-- Fonts --> @section('title', 'CesiZen')
<link rel="preconnect" href="https://fonts.bunny.net">
<link href="https://fonts.bunny.net/css?family=instrument-sans:400,500,600,700" rel="stylesheet" />
<!-- Scripts --> @section('content')
@vite(['resources/css/app.css', 'resources/js/app.js'])
<style>
:root {
/* Official French Government Colors (DSFR) */
--fr-blue: #000091;
--fr-blue-hover: #1212ff;
--fr-red: #E1000F;
--fr-text: #161616;
--fr-background: #F6F6F6;
/* CESIZen Adapted for RGAA (High Contrast) */
--cz-navy: #000074; /* Darker than 000080 for better contrast */
--cz-mustard: #715200; /* Darkened mustard for text on white (Contrast > 7:1) */
--cz-mustard-bg: #F8B803; /* Original mustard for backgrounds only */
--cz-jade: #00635B; /* Darkened jade for text (Contrast > 4.5:1) */
--cz-jade-bg: #26A69A; /* Original jade for backgrounds */
--cz-indigo: #303F9F;
--cz-coral: #C62828;
}
/* Focus state for RGAA */
:focus-visible {
outline: 3px solid var(--fr-blue);
outline-offset: 2px;
}
.skip-link {
position: absolute;
top: -40px;
left: 0;
background: var(--fr-blue);
color: white;
padding: 8px;
z-index: 100;
transition: top 0.2s;
}
.skip-link:focus {
top: 0;
}
</style>
</head>
<body class="bg-[#F6F6F6] text-[#161616] min-h-screen font-sans antialiased overflow-x-hidden"> <body class="bg-[#F6F6F6] text-[#161616] min-h-screen font-sans antialiased overflow-x-hidden">
<a href="#main-content" class="skip-link">Aller au contenu principal</a>
<!-- Government Official Header -->
@include('layouts.header')
<div class="flex min-h-[calc(100vh-80px)]"> <div class="flex min-h-[calc(100vh-80px)]">
<!-- Institutional Sidebar -->
@include('layouts.sidebar')
<!-- Main Workspace --> <!-- Main Workspace -->
<main id="main-content" class="flex-1 flex flex-col bg-[#F6F6F6] overflow-y-auto"> <main id="main-content" class="flex-1 flex flex-col bg-[#F6F6F6] overflow-y-auto">
@@ -164,6 +108,6 @@
</main> </main>
</div> </div>
@include('layouts.footer')
</body> </body>
</html>
@endsection
+5 -4
View File
@@ -21,7 +21,7 @@ Route::get('/register', [AuthController::class, 'showRegister'])->name('register
Route::post('/register', [AuthController::class, 'register']); Route::post('/register', [AuthController::class, 'register']);
Route::post('/logout', [AuthController::class, 'logout'])->name('logout'); Route::post('/logout', [AuthController::class, 'logout'])->name('logout');
// Protected Routes // Routes protégé par authentifications
Route::middleware('auth')->group(function () { Route::middleware('auth')->group(function () {
// Profile // Profile
Route::get('/profile', [ProfileController::class, 'index'])->name('profile.index'); Route::get('/profile', [ProfileController::class, 'index'])->name('profile.index');
@@ -29,13 +29,14 @@ Route::middleware('auth')->group(function () {
Route::put('/profile/password', [ProfileController::class, 'updatePassword'])->name('profile.password'); Route::put('/profile/password', [ProfileController::class, 'updatePassword'])->name('profile.password');
Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy'); Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
// Tracker Émotionnel (Personal data) // Tracker Émotionnel
Route::get('/emotions', [EmotionController::class, 'index'])->name('emotions.index'); Route::get('/emotions', [EmotionController::class, 'index'])->name('emotions.index');
Route::post('/emotions', [EmotionController::class, 'store'])->name('emotions.store'); Route::post('/emotions', [EmotionController::class, 'store'])->name('emotions.store');
// Diagnostic Saving (if applicable) // Diagnostic Stress
Route::get('/diagnostics/history', [DiagnosticController::class, 'history'])->name('diagnostics.history');
Route::post('/diagnostics', [DiagnosticController::class, 'store'])->name('diagnostics.store'); Route::post('/diagnostics', [DiagnosticController::class, 'store'])->name('diagnostics.store');
// Relaxation Actions // Pages Relaxation
Route::post('/relaxation/{id}/favorite', [RelaxationController::class, 'toggleFavorite'])->name('relaxation.favorite'); Route::post('/relaxation/{id}/favorite', [RelaxationController::class, 'toggleFavorite'])->name('relaxation.favorite');
}); });
+24
View File
@@ -0,0 +1,24 @@
<?php
namespace Tests\Feature;
use App\Models\EvenementStress;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
use PHPUnit\Framework\Attributes\Test;
class BusinessLogicTest extends TestCase
{
#[Test]
public function la_liste_des_evenements_de_stress_est_accessible()
{
// On crée un événement simulé
EvenementStress::create(['libelle' => 'Mariage', 'points' => 50]);
$response = $this->getJson('/api/stress-events');
$response->assertStatus(200)
->assertJsonFragment(['libelle' => 'Mariage']);
}
}
+41
View File
@@ -0,0 +1,41 @@
<?php
namespace Tests\Unit;
use Tests\TestCase;
use App\Models\User;
use App\Models\StressEvent;
use App\Models\ResultatDiag;
use Illuminate\Foundation.Testing.RefreshDatabase;
class DiagnosticTest extends TestCase
{
use RefreshDatabase;
public function test_diagnostic_score_calculation_and_storage()
{
// Créer un utilisateur
$user = User::factory()->create();
// Créer des événements de stress
$event1 = StressEvent::create(['event_name' => 'Event 1', 'points' => 100]);
$event2 = StressEvent::create(['event_name' => 'Event 2', 'points' => 60]);
// Simuler une requête de diagnostic
$response = $this->actingAs($user)
->post(route('diagnostics.store'), [
'events' => [$event1->id, $event2->id]
]);
// Vérifier la redirection et le score en session
$response->assertStatus(302);
$response->assertSessionHas('score', 160);
// Vérifier l'enregistrement en base de données
$this->assertDatabaseHas('resultat_diags', [
'id_user' => $user->id,
'score_total' => 160,
'niveau_stress' => 'Modéré'
]);
}
}
-1
View File
@@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" /> <component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
+2
View File
@@ -48,6 +48,7 @@ dependencies {
implementation(libs.compose.material3) implementation(libs.compose.material3)
implementation(libs.compose.foundation) implementation(libs.compose.foundation)
implementation(libs.compose.ui.tooling) implementation(libs.compose.ui.tooling)
implementation(libs.wear)
implementation(libs.wear.tooling.preview) implementation(libs.wear.tooling.preview)
implementation(libs.activity.compose) implementation(libs.activity.compose)
implementation(libs.core.splashscreen) implementation(libs.core.splashscreen)
@@ -55,4 +56,5 @@ dependencies {
androidTestImplementation(libs.ui.test.junit4) androidTestImplementation(libs.ui.test.junit4)
debugImplementation(libs.ui.tooling) debugImplementation(libs.ui.tooling)
debugImplementation(libs.ui.test.manifest) debugImplementation(libs.ui.test.manifest)
// Pour la gestion du réseau simplifiée
} }
+4
View File
@@ -2,6 +2,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-feature android:name="android.hardware.type.watch" /> <uses-feature android:name="android.hardware.type.watch" />
@@ -18,6 +21,7 @@
android:name="wear-sdk" android:name="wear-sdk"
android:required="false" /> android:required="false" />
<!-- <!--
Set to true if your app is Standalone, that is, it does not require the handheld Set to true if your app is Standalone, that is, it does not require the handheld
app to run. app to run.
@@ -1,5 +1,6 @@
package com.cesizen.app package com.cesizen.app
import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.widget.Toast import android.widget.Toast
@@ -29,9 +30,14 @@ import org.json.JSONObject
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkRequest
class MainActivity : ComponentActivity(), DataClient.OnDataChangedListener { class MainActivity : ComponentActivity(), DataClient.OnDataChangedListener {
private var userName by mutableStateOf<String?>(null) private var userName by mutableStateOf<String?>(null)
private var currentMood by mutableStateOf<String?>(null) private var currentMood by mutableStateOf<String?>(null)
private var isRefreshing by mutableStateOf(false) private var isRefreshing by mutableStateOf(false)
@@ -42,6 +48,21 @@ class MainActivity : ComponentActivity(), DataClient.OnDataChangedListener {
Wearable.getDataClient(this).addListener(this) Wearable.getDataClient(this).addListener(this)
refreshData() refreshData()
val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val request = NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI) // Priorité Wi-Fi
.addTransportType(NetworkCapabilities.TRANSPORT_BLUETOOTH) // Secours Bluetooth
.build()
connectivityManager.requestNetwork(request, object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
// Le système a trouvé soit du Wi-Fi, soit le pont Bluetooth du téléphone
connectivityManager.bindProcessToNetwork(network)
}
})
setContent { setContent {
WearApp( WearApp(
userName = userName, userName = userName,
+4
View File
@@ -6,6 +6,8 @@ composeBom = "2024.09.00"
composeMaterial3 = "1.5.6" composeMaterial3 = "1.5.6"
composeFoundation = "1.5.6" composeFoundation = "1.5.6"
composeUiTooling = "1.5.6" composeUiTooling = "1.5.6"
playServicesWearableVersion = "18.1.0"
wear = "1.4.0"
wearToolingPreview = "1.0.0" wearToolingPreview = "1.0.0"
activityCompose = "1.13.0" activityCompose = "1.13.0"
coreSplashscreen = "1.2.0" coreSplashscreen = "1.2.0"
@@ -13,6 +15,7 @@ coreSplashscreen = "1.2.0"
[libraries] [libraries]
play-services-wearable = { group = "com.google.android.gms", name = "play-services-wearable", version.ref = "playServicesWearable" } play-services-wearable = { group = "com.google.android.gms", name = "play-services-wearable", version.ref = "playServicesWearable" }
compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" } compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
play-services-wearable-v1810 = { module = "com.google.android.gms:play-services-wearable", version.ref = "playServicesWearableVersion" }
ui = { group = "androidx.compose.ui", name = "ui" } ui = { group = "androidx.compose.ui", name = "ui" }
ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" } ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" } ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
@@ -22,6 +25,7 @@ ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
compose-material3 = { group = "androidx.wear.compose", name = "compose-material3", version.ref = "composeMaterial3" } compose-material3 = { group = "androidx.wear.compose", name = "compose-material3", version.ref = "composeMaterial3" }
compose-foundation = { group = "androidx.wear.compose", name = "compose-foundation", version.ref = "composeFoundation" } compose-foundation = { group = "androidx.wear.compose", name = "compose-foundation", version.ref = "composeFoundation" }
compose-ui-tooling = { group = "androidx.wear.compose", name = "compose-ui-tooling", version.ref = "composeUiTooling" } compose-ui-tooling = { group = "androidx.wear.compose", name = "compose-ui-tooling", version.ref = "composeUiTooling" }
wear = { module = "androidx.wear:wear", version.ref = "wear" }
wear-tooling-preview = { group = "androidx.wear", name = "wear-tooling-preview", version.ref = "wearToolingPreview" } wear-tooling-preview = { group = "androidx.wear", name = "wear-tooling-preview", version.ref = "wearToolingPreview" }
activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" } activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
core-splashscreen = { group = "androidx.core", name = "core-splashscreen", version.ref = "coreSplashscreen" } core-splashscreen = { group = "androidx.core", name = "core-splashscreen", version.ref = "coreSplashscreen" }