i18n vocabulaire exos (fr/pt-BR) + Web Push rappels de série
Build & Deploy / build (push) Successful in 17s
Build & Deploy / build (push) Successful in 17s
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,15 @@
|
||||
<?php
|
||||
|
||||
use Functional\Users\Http\Controllers\AuthController;
|
||||
use Functional\Users\Http\Controllers\PushController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
// Le préfixe api/ est ajouté par UsersServiceProvider::withRouting() : GET /api/me.
|
||||
Route::get('me', [AuthController::class, 'me'])->middleware('auth:sanctum');
|
||||
// Le préfixe api/ est ajouté par UsersServiceProvider::withRouting().
|
||||
Route::middleware('auth:sanctum')->group(function () {
|
||||
Route::get('me', [AuthController::class, 'me']);
|
||||
|
||||
// Web Push (rappels de série pilotés par le back)
|
||||
Route::post('push/subscribe', [PushController::class, 'subscribe']);
|
||||
Route::post('push/unsubscribe', [PushController::class, 'unsubscribe']);
|
||||
Route::post('push/test', [PushController::class, 'test']);
|
||||
});
|
||||
|
||||
@@ -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']);
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Laravel\Sanctum\HasApiTokens;
|
||||
use NotificationChannels\WebPush\HasPushSubscriptions;
|
||||
|
||||
/**
|
||||
* @property string $locale
|
||||
@@ -27,7 +28,7 @@ use Laravel\Sanctum\HasApiTokens;
|
||||
#[UseFactory(UserFactory::class)]
|
||||
class User extends Authenticatable implements FilamentUser
|
||||
{
|
||||
use HasApiTokens, HasFactory, Notifiable;
|
||||
use HasApiTokens, HasFactory, HasPushSubscriptions, Notifiable;
|
||||
|
||||
/** Accès au back-office Filament (à affiner : rôle admin plus tard). */
|
||||
public function canAccessPanel(Panel $panel): bool
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Functional\Users\Notifications;
|
||||
|
||||
use Illuminate\Notifications\Notification;
|
||||
use NotificationChannels\WebPush\WebPushChannel;
|
||||
use NotificationChannels\WebPush\WebPushMessage;
|
||||
|
||||
/** Notification de test envoyée quand l'utilisateur active/teste les rappels push. */
|
||||
class PushTestNotification extends Notification
|
||||
{
|
||||
/** @return array<int,string> */
|
||||
public function via(object $notifiable): array
|
||||
{
|
||||
return [WebPushChannel::class];
|
||||
}
|
||||
|
||||
public function toWebPush(object $notifiable): WebPushMessage
|
||||
{
|
||||
return (new WebPushMessage())
|
||||
->title('🔥 StreakFit')
|
||||
->body('Notifications activées — on te préviendra pour garder ta flamme !')
|
||||
->icon('/pwa-192.png')
|
||||
->badge('/pwa-192.png')
|
||||
->data(['url' => '/'])
|
||||
->options(['TTL' => 3600]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user