feat: plan limits, café location, nearby API, Iran map section
CI/CD / CI · API (dotnet build + test) (push) Successful in 56s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 49s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m4s
CI/CD / CI · Admin Web (tsc) (push) Successful in 34s
CI/CD / CI · Website (tsc) (push) Successful in 44s
CI/CD / CI · Koja (tsc) (push) Successful in 50s
CI/CD / Deploy · all services (push) Successful in 3m15s

• PlanLimits: add MaxMenuCategories (Free→3), MaxMenuItems (Free→30),
  CanAccessCrm and CanAccessStatistics (Pro+ only)
• MenuController: enforce category/item limits before create (403 + PLAN_LIMIT_REACHED)
• Cafe entity + EF migration: Latitude/Longitude (double?, nullable)
• CafeSettingsController: PATCH accepts lat/lng with range validation
• PublicController: GET /api/public/map-markers (marketing SVG map feed)
  and GET /api/public/nearby (Koja nearby-cafés with Haversine sort)
• Dashboard settings: location card with OSM iframe preview + Neshan link
• Website homepage: IranMapSection — stylised SVG silhouette with
  SMIL-animated blinking dots at real café coordinates

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-06-01 15:09:09 +03:30
parent 665e3ca279
commit 5e980cdfc0
12 changed files with 619 additions and 4 deletions
+10 -2
View File
@@ -15,7 +15,9 @@ public record CafeSettingsDto(
DateTime? PlanExpiresAt,
CafeThemeDto Theme,
decimal DefaultTaxRate,
bool AllowBranchTaxOverride);
bool AllowBranchTaxOverride,
double? Latitude,
double? Longitude);
public record PatchCafeSettingsRequest(
string? Name,
@@ -30,4 +32,10 @@ public record PatchCafeSettingsRequest(
string? SnappfoodVendorId,
CafeThemeDto? Theme,
decimal? DefaultTaxRate,
bool? AllowBranchTaxOverride);
bool? AllowBranchTaxOverride,
/// <summary>WGS-84 latitude. Send null to clear.</summary>
double? Latitude,
/// <summary>WGS-84 longitude. Send null to clear.</summary>
double? Longitude,
/// <summary>When true, Latitude and Longitude are explicitly being cleared (set to null).</summary>
bool ClearLocation = false);