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

@@ -2,12 +2,107 @@
ViewData["Title"] = "Dashboard";
}
<div class="row mb-4">
<div class="row mb-3">
<div class="col">
<h1><i class="fas fa-tachometer-alt"></i> Dashboard</h1>
<p class="text-muted mb-0">Welcome back! Here's what needs your attention today.</p>
</div>
</div>
<!-- PWA Install Prompt (Inline Content) -->
<div id="pwa-install-alert" class="alert alert-info alert-dismissible fade show d-flex align-items-center" role="alert" style="display: none !important;">
<i class="fas fa-mobile-alt me-3 fs-4"></i>
<div class="flex-grow-1">
<strong>Install TeleShop Admin as an App</strong>
<p class="mb-0 small">Get a better experience with offline access and a native app feel.</p>
</div>
<button id="pwa-install-btn" class="btn btn-primary btn-sm me-2">
<i class="fas fa-download"></i> Install
</button>
<button id="pwa-dismiss-btn" type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
@{
var pendingOrders = (int)ViewData["PendingOrders"]!;
var lowStockProducts = (int)ViewData["LowStockProducts"]!;
var outOfStockProducts = (int)ViewData["OutOfStockProducts"]!;
var totalUrgentActions = pendingOrders + (lowStockProducts > 5 ? 1 : 0) + (outOfStockProducts > 0 ? 1 : 0);
}
<!-- URGENT ACTIONS PANEL -->
@if (totalUrgentActions > 0)
{
<div class="row mb-4">
<div class="col">
<div class="card border-warning shadow-sm">
<div class="card-header bg-warning text-dark">
<h5 class="mb-0">
<i class="fas fa-exclamation-triangle"></i>
<strong>Urgent Actions Required</strong>
<span class="badge bg-danger ms-2">@totalUrgentActions</span>
</h5>
</div>
<div class="card-body">
<div class="list-group list-group-flush">
@if (pendingOrders > 0)
{
<a href="@Url.Action("Index", "Orders", new { area = "Admin", status = "PendingPayment" })"
class="list-group-item list-group-item-action list-group-item-warning d-flex justify-content-between align-items-center">
<div>
<i class="fas fa-shopping-cart text-warning me-2"></i>
<strong>@pendingOrders order@(pendingOrders != 1 ? "s" : "") awaiting payment</strong>
<small class="d-block text-muted">Customers may need payment reminders</small>
</div>
<i class="fas fa-chevron-right"></i>
</a>
}
@if (outOfStockProducts > 0)
{
<a href="@Url.Action("Index", "Products", new { area = "Admin" })"
class="list-group-item list-group-item-action list-group-item-danger d-flex justify-content-between align-items-center">
<div>
<i class="fas fa-box-open text-danger me-2"></i>
<strong>@outOfStockProducts product@(outOfStockProducts != 1 ? "s" : "") out of stock</strong>
<small class="d-block text-muted">Update inventory or mark as unavailable</small>
</div>
<i class="fas fa-chevron-right"></i>
</a>
}
@if (lowStockProducts > 5)
{
<a href="@Url.Action("Index", "Products", new { area = "Admin" })"
class="list-group-item list-group-item-action list-group-item-warning d-flex justify-content-between align-items-center">
<div>
<i class="fas fa-exclamation-circle text-warning me-2"></i>
<strong>@lowStockProducts products running low on stock</strong>
<small class="d-block text-muted">Stock levels below 10 units</small>
</div>
<i class="fas fa-chevron-right"></i>
</a>
}
</div>
</div>
</div>
</div>
</div>
}
else
{
<div class="row mb-4">
<div class="col">
<div class="alert alert-success d-flex align-items-center" role="alert">
<i class="fas fa-check-circle fs-4 me-3"></i>
<div>
<strong>All systems running smoothly!</strong>
<p class="mb-0 small">No urgent actions required at this time.</p>
</div>
</div>
</div>
</div>
}
<div class="row">
<div class="col-md-3">
<div class="card text-white bg-primary mb-3">
@@ -104,9 +199,6 @@
<div class="card">
<div class="card-header">
<h5><i class="fas fa-chart-line"></i> Quick Actions</h5>
<button id="pwa-install-dashboard" class="btn btn-sm btn-outline-primary" style="float: right;">
<i class="fas fa-mobile-alt"></i> Install App
</button>
</div>
<div class="card-body">
<div class="list-group list-group-flush">
@@ -147,15 +239,29 @@
<script>
document.addEventListener('DOMContentLoaded', function() {
const installBtn = document.getElementById('pwa-install-dashboard');
const installAlert = document.getElementById('pwa-install-alert');
const installBtn = document.getElementById('pwa-install-btn');
const dismissBtn = document.getElementById('pwa-dismiss-btn');
// Check if user has dismissed the alert
const alertDismissed = localStorage.getItem('pwa-install-dismissed');
// Check if app is in standalone mode (already installed)
const isStandalone = window.matchMedia('(display-mode: standalone)').matches;
// Show alert if not dismissed and not already installed
if (installAlert && !alertDismissed && !isStandalone) {
installAlert.style.display = 'flex';
}
if (installBtn) {
installBtn.addEventListener('click', function() {
// Check if app is in standalone mode
if (window.matchMedia('(display-mode: standalone)').matches) {
if (isStandalone) {
alert('App is already installed!');
return;
}
// Show manual install instructions
alert(`To install TeleShop Admin as an app:
@@ -172,5 +278,11 @@ document.addEventListener('DOMContentLoaded', function() {
The app will then work offline and appear in your apps list!`);
});
}
if (dismissBtn) {
dismissBtn.addEventListener('click', function() {
localStorage.setItem('pwa-install-dismissed', 'true');
});
}
});
</script>