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
+20
View File
@@ -54,4 +54,24 @@ public static class PlanLimits
PlanTier.Enterprise => 100,
_ => 0
};
/// <summary>Maximum active menu categories. Free tier is capped at 3; Pro+ is unlimited.</summary>
public static int MaxMenuCategories(PlanTier tier) => tier switch
{
PlanTier.Free => 3,
_ => int.MaxValue
};
/// <summary>Maximum menu items. Free tier is capped at 30; Pro+ is unlimited.</summary>
public static int MaxMenuItems(PlanTier tier) => tier switch
{
PlanTier.Free => 30,
_ => int.MaxValue
};
/// <summary>CRM (customers, loyalty) is only available on Pro and above.</summary>
public static bool CanAccessCrm(PlanTier tier) => tier >= PlanTier.Pro;
/// <summary>Statistics and analytics dashboards are only available on Pro and above.</summary>
public static bool CanAccessStatistics(PlanTier tier) => tier >= PlanTier.Pro;
}
+4
View File
@@ -37,6 +37,10 @@ public class Cafe : BaseEntity
public string? InstagramHandle { get; set; }
/// <summary>Cafe website URL, max 300 chars.</summary>
public string? WebsiteUrl { get; set; }
/// <summary>WGS-84 latitude (positive = north). Null until owner sets location.</summary>
public double? Latitude { get; set; }
/// <summary>WGS-84 longitude (positive = east). Null until owner sets location.</summary>
public double? Longitude { get; set; }
/// <summary>Default VAT/sales tax % for all branches unless branch override is allowed.</summary>
public decimal DefaultTaxRate { get; set; } = 9m;
public bool AllowBranchTaxOverride { get; set; }