i18n vocabulaire exos (fr/pt-BR) + Web Push rappels de série
Build & Deploy / build (push) Successful in 17s

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-19 03:46:43 +02:00
co-authored by Claude Opus 4.8
parent af32669931
commit fa3e59704b
23 changed files with 954 additions and 31 deletions
@@ -85,6 +85,10 @@ class AuthController
'longest' => $streak->longest_count,
'freezes' => $streak->freezes_available,
],
'push' => [
'vapid_public_key' => config('webpush.vapid.public_key'),
'enabled' => $user->pushSubscriptions()->exists(),
],
]);
}
@@ -0,0 +1,50 @@
<?php
namespace Functional\Users\Http\Controllers;
use Functional\Users\Notifications\PushTestNotification;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
/**
* Abonnement Web Push (PWA). Le front envoie sa subscription ; on la stocke sur l'utilisateur.
* L'envoi réel des rappels est piloté par le back (commande planifiée) cf couche streaks.
*/
class PushController
{
/** POST /api/push/subscribe — enregistre/actualise l'abonnement push du navigateur. */
public function subscribe(Request $request): JsonResponse
{
$data = $request->validate([
'endpoint' => ['required', 'string'],
'keys.p256dh' => ['required', 'string'],
'keys.auth' => ['required', 'string'],
]);
$request->user()->updatePushSubscription(
$data['endpoint'],
$data['keys']['p256dh'],
$data['keys']['auth'],
);
return response()->json(['status' => 'subscribed']);
}
/** POST /api/push/unsubscribe — supprime l'abonnement (désactivation des rappels). */
public function unsubscribe(Request $request): Response
{
$request->validate(['endpoint' => ['required', 'string']]);
$request->user()->deletePushSubscription($request->input('endpoint'));
return response()->noContent();
}
/** POST /api/push/test — envoie une notif de test (bouton "tester" côté profil). */
public function test(Request $request): JsonResponse
{
$request->user()->notify(new PushTestNotification());
return response()->json(['status' => 'sent']);
}
}