Files
meezi/src/Meezi.Infrastructure/Data/MenuImageManifest.cs
T
soroush.asadi ef15fd6247 feat(api): .NET 10 multi-tenant REST API
Full backend implementation:
- Multi-tenant cafe/restaurant management (menus, orders, tables, staff)
- POS order flow with ZarinPal and Snappfood payment integration
- OTP authentication via Kavenegar SMS
- QR digital menu with public discover/finder endpoints
- Customer loyalty, coupons, CRM
- PostgreSQL via EF Core, Redis for caching/sessions
- Background jobs, webhook handlers
- Full migration history

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-27 21:33:48 +03:30

102 lines
3.5 KiB
C#

using System.Text.Json;
namespace Meezi.Infrastructure.Data;
public static class MenuImageManifest
{
private static IReadOnlyDictionary<string, string>? _urls;
private static string? _defaultDrinkUrl;
private static string? _defaultFoodUrl;
private const string FallbackDrinkUrl =
"https://images.unsplash.com/photo-1509042239860-f550ce710b93?w=600&auto=format&fit=crop";
private const string FallbackFoodUrl =
"https://images.unsplash.com/photo-1546793665-c74683f339c1?w=600";
public static string? GetImageUrl(string itemId)
{
EnsureLoaded();
return _urls!.TryGetValue(itemId, out var url) ? url : null;
}
public static string GetDefaultDrinkImageUrl()
{
EnsureLoaded();
return _defaultDrinkUrl ?? FallbackDrinkUrl;
}
public static string GetDefaultFoodImageUrl()
{
EnsureLoaded();
return _defaultFoodUrl ?? FallbackFoodUrl;
}
public static string ResolveImageUrl(string itemId, string fallback)
=> GetLocalImageOverride(itemId) ?? fallback;
/// <summary>Only imported Kaggle/upload paths override Food-101 fallbacks (not stale CDN URLs in manifest).</summary>
public static string? GetLocalImageOverride(string itemId)
{
var url = GetImageUrl(itemId);
if (string.IsNullOrWhiteSpace(url)) return null;
if (url.StartsWith("/uploads/", StringComparison.OrdinalIgnoreCase)
|| url.StartsWith("uploads/", StringComparison.OrdinalIgnoreCase))
return url.StartsWith('/') ? url : $"/{url}";
return null;
}
private static void EnsureLoaded()
{
if (_urls is not null) return;
LoadFromDisk();
}
private static void LoadFromDisk()
{
var paths = new[]
{
Path.Combine(AppContext.BaseDirectory, "data", "menu-image-manifest.json"),
Path.Combine(Directory.GetCurrentDirectory(), "data", "menu-image-manifest.json"),
Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..", "..", "..", "..", "data", "menu-image-manifest.json")),
Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), "..", "..", "data", "menu-image-manifest.json")),
};
foreach (var path in paths)
{
if (!File.Exists(path)) continue;
try
{
var json = File.ReadAllText(path);
var doc = JsonDocument.Parse(json);
if (doc.RootElement.TryGetProperty("defaults", out var defaults))
{
if (defaults.TryGetProperty("drink", out var drink))
_defaultDrinkUrl = drink.GetString();
if (defaults.TryGetProperty("food", out var food))
_defaultFoodUrl = food.GetString();
}
var map = new Dictionary<string, string>(StringComparer.Ordinal);
if (doc.RootElement.TryGetProperty("items", out var items))
{
foreach (var prop in items.EnumerateObject())
{
if (prop.Value.TryGetProperty("imageUrl", out var url))
map[prop.Name] = url.GetString() ?? "";
}
}
_urls = map;
return;
}
catch
{
// try next path
}
}
_urls = new Dictionary<string, string>(StringComparer.Ordinal);
}
}