Add push notifications (Pushe) + Capacitor shell for Koja

Iran-safe push for the Koja Android app (Cafe Bazaar / Myket / direct APK):

Backend
- PushDevice entity + EF migration; idempotent device register/unregister.
- IPushSender / PusheNotificationSender (Pushe REST) — SendToTopic for
  marketing (city-{slug}) and saved-café (cafe-{slug}) pushes, SendToTokens
  for targeted order/reservation updates.
- Public register/unregister endpoints + authorized topic broadcast.

App
- capacitor.config.ts (native WebView loads the live PWA via server.url).
- push.ts Pushe glue: topic helpers + backend device registration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-05-29 17:06:42 +03:30
parent 289c808257
commit 963d02a265
15 changed files with 3754 additions and 0 deletions
+24
View File
@@ -0,0 +1,24 @@
namespace Meezi.Core.Entities;
/// <summary>
/// A registered push-notification device (Pushe). One row per install token.
/// Used for targeted order/reservation pushes; broadcast/marketing pushes go
/// through Pushe topics (city-{slug}, cafe-{slug}) the device subscribes to
/// client-side, but we mirror the city here for server-side fallback targeting.
/// </summary>
public class PushDevice : BaseEntity
{
/// <summary>Pushe device/install token.</summary>
public string Token { get; set; } = string.Empty;
/// <summary>"android" (only platform shipped today).</summary>
public string Platform { get; set; } = "android";
/// <summary>Optional city slug the user is browsing — for city-topic targeting.</summary>
public string? City { get; set; }
/// <summary>Optional link to a platform consumer account (OTP login).</summary>
public string? ConsumerAccountId { get; set; }
public DateTime LastSeenAt { get; set; } = DateTime.UtcNow;
}