feat: Add customer management, payments, and push notifications with security enhancements
Some checks failed
Build and Deploy LittleShop / Build TeleBot Docker Image (push) Failing after 11s
Build and Deploy LittleShop / Build LittleShop Docker Image (push) Failing after 15s
Build and Deploy LittleShop / Deploy to Production VPS (Manual Only) (push) Has been skipped
Build and Deploy LittleShop / Deploy to Pre-Production (CT109) (push) Has been skipped

Major Feature Additions:
- Customer management: Full CRUD with data export and privacy compliance
- Payment management: Centralized payment tracking and administration
- Push notification subscriptions: Manage and track web push subscriptions

Security Enhancements:
- IP whitelist middleware for administrative endpoints
- Data retention service with configurable policies
- Enhanced push notification security documentation
- Security fixes progress tracking (2025-11-14)

UI/UX Improvements:
- Enhanced navigation with improved mobile responsiveness
- Updated admin dashboard with order status counts
- Improved product CRUD forms
- New customer and payment management interfaces

Backend Improvements:
- Extended customer service with data export capabilities
- Enhanced order service with status count queries
- Improved crypto payment service with better error handling
- Updated validators and configuration

Documentation:
- DEPLOYMENT_NGINX_GUIDE.md: Nginx deployment instructions
- IP_STORAGE_ANALYSIS.md: IP storage security analysis
- PUSH_NOTIFICATION_SECURITY.md: Push notification security guide
- UI_UX_IMPROVEMENT_PLAN.md: Planned UI/UX enhancements
- UI_UX_IMPROVEMENTS_COMPLETED.md: Completed improvements

Cleanup:
- Removed temporary database WAL files
- Removed stale commit message file

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-16 19:33:02 +00:00
parent 47e43d4ff8
commit a2247d7c02
45 changed files with 5302 additions and 371 deletions

View File

@@ -37,6 +37,7 @@
<link href="/_content/Radzen.Blazor/css/material-base.css" rel="stylesheet">
<link href="/css/modern-admin.css" rel="stylesheet">
<link href="/css/mobile-admin.css" rel="stylesheet">
<link href="/css/enhanced-navigation.css?v=20251114c" rel="stylesheet">
@await RenderSectionAsync("Head", required: false)
</head>
<body>
@@ -64,65 +65,106 @@
</a>
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
<ul class="navbar-nav flex-grow-1">
<!-- Dashboard (Always Visible) -->
<li class="nav-item">
<a class="nav-link" href="@Url.Action("Index", "Dashboard", new { area = "Admin" })">
<a class="nav-link @(ViewContext.RouteData.Values["controller"]?.ToString() == "Dashboard" ? "active" : "")" href="@Url.Action("Index", "Dashboard", new { area = "Admin" })">
<i class="fas fa-tachometer-alt"></i> Dashboard
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="@Url.Action("Index", "Categories", new { area = "Admin" })">
<i class="fas fa-tags"></i> Categories
<!-- Catalog Dropdown -->
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle @(new[]{"Products","Categories","VariantCollections"}.Contains(ViewContext.RouteData.Values["controller"]?.ToString()) ? "active" : "")" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
<i class="fas fa-store"></i> Catalog
</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="@Url.Action("Index", "Products", new { area = "Admin" })">
<i class="fas fa-box"></i> Products
</a></li>
<li><a class="dropdown-item" href="@Url.Action("Index", "Categories", new { area = "Admin" })">
<i class="fas fa-tags"></i> Categories
</a></li>
<li><a class="dropdown-item" href="@Url.Action("Index", "VariantCollections", new { area = "Admin" })">
<i class="fas fa-layer-group"></i> Variant Collections
</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="@Url.Action("Import", "Products", new { area = "Admin" })">
<i class="fas fa-upload"></i> Import Products
</a></li>
<li><a class="dropdown-item" href="@Url.Action("Export", "Products", new { area = "Admin" })">
<i class="fas fa-download"></i> Export Products
</a></li>
</ul>
</li>
<li class="nav-item">
<a class="nav-link" href="@Url.Action("Index", "Products", new { area = "Admin" })">
<i class="fas fa-box"></i> Products
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="@Url.Action("Index", "VariantCollections", new { area = "Admin" })">
<i class="fas fa-layer-group"></i> Variants
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="@Url.Action("Index", "Orders", new { area = "Admin" })">
<!-- Orders & Fulfillment -->
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle @(new[]{"Orders","Customers","Payments","ShippingRates"}.Contains(ViewContext.RouteData.Values["controller"]?.ToString()) ? "active" : "")" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
<i class="fas fa-shopping-cart"></i> Orders
</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="@Url.Action("Index", "Orders", new { area = "Admin" })">
<i class="fas fa-clipboard-list"></i> All Orders
</a></li>
<li><a class="dropdown-item" href="@Url.Action("Index", "Customers", new { area = "Admin" })">
<i class="fas fa-users"></i> Customers
</a></li>
<li><a class="dropdown-item" href="@Url.Action("Index", "Payments", new { area = "Admin" })">
<i class="fas fa-wallet"></i> Payment Transactions
</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="@Url.Action("Index", "Orders", new { area = "Admin", tab = "pending" })">
<i class="fas fa-clock"></i> Pending Payment
</a></li>
<li><a class="dropdown-item" href="@Url.Action("Index", "Orders", new { area = "Admin", tab = "accept" })">
<i class="fas fa-check-circle"></i> Ready to Accept
</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="@Url.Action("Index", "ShippingRates", new { area = "Admin" })">
<i class="fas fa-truck"></i> Shipping Rates
</a></li>
</ul>
</li>
<li class="nav-item">
<a class="nav-link" href="@Url.Action("Index", "Reviews", new { area = "Admin" })">
<i class="fas fa-star"></i> Reviews
<!-- Customer Communication -->
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle @(new[]{"Reviews","Messages","BotActivity"}.Contains(ViewContext.RouteData.Values["controller"]?.ToString()) ? "active" : "")" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
<i class="fas fa-comments"></i> Customers
</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="@Url.Action("Index", "Reviews", new { area = "Admin" })">
<i class="fas fa-star"></i> Reviews
</a></li>
<li><a class="dropdown-item" href="@Url.Action("Index", "Messages", new { area = "Admin" })">
<i class="fas fa-envelope"></i> Messages
</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="@Url.Action("LiveView", "BotActivity", new { area = "Admin" })">
<i class="fas fa-satellite-dish"></i> Live Activity
</a></li>
</ul>
</li>
<li class="nav-item">
<a class="nav-link" href="@Url.Action("Index", "Messages", new { area = "Admin" })">
<i class="fas fa-comments"></i> Messages
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="@Url.Action("Index", "ShippingRates", new { area = "Admin" })">
<i class="fas fa-truck"></i> Shipping
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="@Url.Action("Index", "Users", new { area = "Admin" })">
<i class="fas fa-users"></i> Users
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="@Url.Action("Index", "Bots", new { area = "Admin" })">
<i class="fas fa-robot"></i> Bots
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="@Url.Action("LiveView", "BotActivity", new { area = "Admin" })">
<i class="fas fa-satellite-dish"></i> Live Activity
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="@Url.Action("Index", "SystemSettings", new { area = "Admin" })">
<!-- Settings -->
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle @(new[]{"Users","Bots","PushSubscriptions","SystemSettings"}.Contains(ViewContext.RouteData.Values["controller"]?.ToString()) ? "active" : "")" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
<i class="fas fa-cog"></i> Settings
</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="@Url.Action("Index", "Users", new { area = "Admin" })">
<i class="fas fa-users"></i> Users
</a></li>
<li><a class="dropdown-item" href="@Url.Action("Index", "Bots", new { area = "Admin" })">
<i class="fas fa-robot"></i> Bots
</a></li>
<li><a class="dropdown-item" href="@Url.Action("Index", "PushSubscriptions", new { area = "Admin" })">
<i class="fas fa-bell"></i> Push Subscriptions
</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="@Url.Action("Index", "SystemSettings", new { area = "Admin" })">
<i class="fas fa-sliders-h"></i> System Settings
</a></li>
</ul>
</li>
</ul>
<ul class="navbar-nav">