webapp/src/components/market/DashboardOverview.vue
padreug ea5a2380f1 feat: Add market integration roadmap to NOSTR architecture documentation
- Introduce a comprehensive roadmap for integrating nostr-market-app purchasing functionality into the web-app.
- Outline key components of the shopping cart system, checkout process, and order management.
- Detail phased implementation strategy, including enhanced user experience and advanced features.
- Include security, performance, and testing considerations to ensure robust integration.

feat: Enhance market store with new order and cart management features

- Introduce new interfaces for Order, OrderItem, ContactInfo, and ShippingZone to support enhanced order management.
- Update Stall and Product interfaces to include currency and shipping details.
- Implement a comprehensive shopping cart system with stall-specific carts, including methods for adding, removing, and updating items.
- Add payment-related interfaces and methods for managing payment requests and statuses.
- Enhance filter options to include in-stock status and payment methods, improving product filtering capabilities.
- Refactor computed properties and methods for better cart management and checkout processes.

feat: Implement shopping cart functionality with new components and routing

- Add ShoppingCart, CartItem, and CartSummary components to manage cart items and display summaries.
- Introduce Cart.vue page to serve as the main shopping cart interface, integrating cart and summary components.
- Update Navbar.vue to include a cart icon with item count, enhancing user navigation.
- Implement cart management features in the market store, including item addition, quantity updates, and removal.
- Establish routing for the cart page, ensuring seamless navigation for users.
- Enhance ProductCard.vue to support adding items to the cart directly from the product listing.

feat: Update cart and checkout functionality with improved navigation and button labels

- Change "Proceed to Checkout" button text to dynamic "Place Order" based on context in CartSummary.vue.
- Update "Continue Shopping" button to "Back to Cart" in CartSummary.vue for clearer navigation.
- Modify routing for checkout to include stall ID in ShoppingCart.vue, enhancing checkout process.
- Simplify Cart.vue by removing CartSummary component and focusing on ShoppingCart display.
- Add new route for checkout with stall ID in router configuration for better handling of checkout flows.

feat: Enhance cart and checkout components with improved shipping address handling

- Update CartSummary.vue to use readonly types for cart items and shipping zones, ensuring immutability.
- Modify Checkout.vue to conditionally display the shipping address field based on the selected shipping zone's requirements for physical shipping.
- Add a digital delivery note for products that do not require a shipping address.
- Introduce a computed property to determine if a shipping address is required, improving validation logic during checkout.
- Update market store to include a new property for shipping zones indicating if physical shipping is required.

feat: Implement order placement functionality in checkout process

- Add a "Place Order" button in Checkout.vue that triggers the order placement process.
- Introduce loading state during order placement to enhance user experience.
- Implement createAndPlaceOrder method in market store to handle order creation and status updates.
- Include error handling for order placement failures, providing user feedback on errors.
- Update checkout logic to validate shipping zone and contact information before proceeding.

feat: Add Order History page and update Navbar for order tracking

- Introduce a new OrderHistory.vue page to display users' past orders with filtering and sorting options.
- Update Navbar.vue to include an "Order History" option with a badge showing the count of orders.
- Implement computed properties for order count and enhance user navigation experience.

feat: Integrate Nostr functionality for order management and user notifications

- Add NostrExtensionGuide component to inform users about the required Nostr extension for order transmission.
- Implement useNostrOrders composable to manage Nostr connection, event creation, and order sending.
- Update Checkout.vue to display Nostr connection status and provide feedback on order transmission.
- Enhance OrderHistory.vue to show Nostr transmission status and details for each order.
- Modify market store to handle Nostr event details and errors during order placement, ensuring local fallback.
- Introduce types for Nostr events to improve type safety and integration with the existing order management system.

refactor: Update Nostr relay configuration to use environment variable

- Change DEFAULT_RELAYS to dynamically retrieve relay URLs from the VITE_MARKET_RELAYS environment variable.
- Add error handling to ensure relays are configured before establishing a connection.
- Modify createBlankEvent function to return a more precise type.
- Update event signing process to ensure the event ID is generated correctly before signing.

refactor: useAuth switch Enhance Nostr order management with authentication checks

- Integrate user authentication checks to ensure Nostr features are only accessible to authenticated users.
- Replace direct window.nostr calls with auth store methods for retrieving public and private keys.
- Implement a helper function for signing events and mock encryption for order content.
- Remove obsolete Nostr type definitions to streamline the codebase.

feat: Enhance Checkout.vue with Nostr processing feedback and cleanup

- Update the checkout button to disable based on order placement state.
- Simplify order placement feedback by removing unnecessary Nostr processing checks.
- Introduce a new visual indicator for Nostr order processing status.
- Refactor computed properties for better clarity and efficiency in shipping zone handling.

refactor: Streamline Nostr order handling and integrate buyer public key retrieval

- Remove redundant Nostr relay tag from order event creation in useNostrOrders.
- Update Checkout.vue to retrieve the buyer's public key from the auth store, enhancing order placement logic.
- Modify createAndPlaceOrder method in market store to accept an optional Nostr orders instance for improved flexibility in order processing.

refactor: Remove Nostr-related components and streamline order processing

- Delete NostrExtensionGuide.vue and associated type definitions to simplify the codebase.
- Remove unused useNostr.ts file and related logic from useNostrOrders.ts.
- Update order handling in market store to directly integrate Nostr publishing without relying on external components.
- Enhance Checkout.vue and Cart.vue to reflect changes in Nostr integration and provide clearer order status feedback.

feat: Enhance Nostr chat functionality with malformed message handling

- Introduce tracking for malformed message IDs to prevent repeated processing attempts.
- Implement functions to mark messages as malformed, clean up old entries, and retrieve statistics on malformed messages.
- Add periodic cleanup of malformed messages to manage memory usage.
- Enhance message processing logic to skip previously identified malformed messages and provide detailed error handling for decryption failures.
- Update the return object to include new functions for managing malformed messages.

ZZ feat: Implement Lightning invoice management in market store

- Add functionality to create and manage Lightning invoices for orders.
- Introduce payment monitoring and status updates for invoices.
- Implement payment confirmation messaging via Nostr upon successful payment.
- Enhance order interface to include new fields for Lightning invoice details and payment status.

ZZ feat: Enhance OrderHistory.vue with payment status indicators and invoice management

- Add visual indicators for payment status, including 'Paid' and
'Payment Pending' badges.
- Implement expandable payment display for orders with Lightning
invoices.
- Introduce functionality to toggle payment display and generate
Lightning invoices.
- Update order status messaging to reflect payment requirements and
invoice generation status.

ZZ feat: Enhance OrderHistory.vue with payment status indicators and invoice management

- Add visual indicators for payment status, including 'Paid' and
'Payment Pending' badges.
- Implement expandable payment display for orders with Lightning
invoices.
- Introduce functionality to toggle payment display and generate
Lightning invoices.
- Update order status messaging to reflect payment requirements and
invoice generation status.

feat: Implement order event handling in useOrderEvents composable

- Introduce useOrderEvents composable to manage subscription and processing of order-related events.
- Define order event types and interfaces for better type safety and clarity.
- Implement methods to handle payment requests, order status updates, and invoice generation.
- Enhance OrderHistory.vue to display order event subscription status and last update timestamp.
- Update market store to include order update functionality for better integration with order events.

FIX: Build errors

refactor: Update component styles and improve UI consistency across market pages

- Replace various color classes with updated design tokens for better consistency.
- Change background colors of components to align with the new design system.
- Update text colors to enhance readability and maintain a cohesive look.
- Refactor class names in CartItem.vue, CartSummary.vue, DashboardOverview.vue, and other components to use the new color scheme.
- Ensure all components reflect the updated design guidelines for a unified user experience.

refactor: Remove Order History references from Navbar component

- Eliminate order count computation and related UI elements from the Navbar.
- Streamline the Navbar by removing the Order History button and badge.
- Maintain existing functionality for other menu items, ensuring a cleaner user interface.

feat: Implement QR code generation and download functionality in PaymentDisplay component

- Add QR code generation for payment requests using the qrcode library.
- Enhance UI to display loading states and error messages during QR code generation.
- Introduce a download button for users to save the generated QR code.
- Implement logic to regenerate QR code when the invoice changes.

refactor: Replace useRelayHub with relayHubComposable across components

- Update imports in multiple components and composables to use the new relayHubComposable for better consistency and maintainability.
- Enhance OrderHistory.vue with debug information for development, displaying key states related to orders, authentication, and relay hub connectivity.
- Remove unnecessary reconnect button from RelayHubStatus.vue to streamline user interactions.
- Improve logging in useOrderEvents for better debugging and monitoring of order event subscriptions.

refactor: Update OrderHistory.vue styles for improved UI consistency

- Replace color classes with updated design tokens for better alignment with the new design system.
- Enhance readability by adjusting text colors and background styles for payment status indicators.
- Ensure a cohesive look across the component by standardizing class names and styles.

refactor: Update component styles for improved UI consistency across checkout pages

- Replace color classes with updated design tokens for better alignment with the new design system.
- Enhance readability by adjusting text colors and background styles in CartSummary.vue, PaymentDisplay.vue, Checkout.vue, and OrderHistory.vue.
- Standardize class names and styles to ensure a cohesive look across all components.

feat: Implement invoice generation and Nostr integration in MerchantStore component

- Add functionality to generate Lightning invoices for orders and send them to customers via Nostr.
- Introduce a new sendInvoiceToCustomer method to update order details and publish invoice information.
- Enhance order event handling in useOrderEvents to update existing orders with new invoice data.
- Improve error handling and logging for invoice generation and sending processes.

feat: Enhance MerchantStore and PaymentDisplay components for improved invoice handling

- Add wallet indicator in MerchantStore to display the selected wallet name during pending orders.
- Implement temporary fixes for missing buyer and seller public keys when generating invoices.
- Update invoice generation logic to utilize the first available wallet and improve error handling.
- Modify PaymentDisplay to use the new bolt11 field for payment requests and enhance date formatting.
- Refactor order event handling to ensure accurate updates and invoice management across components.

feat: Enhance order event processing in useOrderEvents composable

- Refactor processOrderEvent to handle incoming Nostr market order events with improved validation and logging.
- Implement logic to update existing orders or create new ones based on event data, ensuring accurate order management.
- Add detailed console logging for better debugging and tracking of order events and their statuses.
- Ensure compatibility with market order structure and invoice details for seamless integration with payment processing.

feat: Enhance order management with localStorage persistence

- Update createOrder method to optionally accept an order ID from events, improving order tracking.
- Convert items from readonly to mutable for better manipulation.
- Implement localStorage persistence for orders, ensuring data is saved and loaded across sessions.
- Add methods to save and load orders from localStorage, enhancing user experience and data reliability.

feat: Update invoice creation to support additional metadata and nostrmarket compatibility

- Modify createInvoice method to accept an optional extra parameter for additional metadata.
- Change invoice tag to 'nostrmarket' for improved compatibility with Nostr market.
- Include merchant and buyer public keys in the invoice data for better integration.
- Update invoice creation in market store to utilize new parameters for enhanced functionality.

feat: Enhance order and invoice handling for Nostr market compatibility

- Add originalOrderId to order events for tracking Nostr order IDs.
- Update invoice creation to utilize original Nostr order ID when generating invoices.
- Improve logging for invoice requests to LNBits, providing better visibility into the data being sent.
- Ensure compatibility with nostrmarket by adjusting order ID handling in the market store.

fix: Refine invoice creation logic for Nostr market compatibility

- Adjust order ID handling in invoice creation to prioritize originalOrderId for better compatibility with nostrmarket.
- Enhance logging to provide clearer insights into the order ID being used during invoice generation.

feat: Integrate nostrmarket service for order publishing and merchant catalog management

- Implement functionality to publish orders via the nostrmarket protocol, replacing the previous Nostr integration.
- Add methods to publish merchant catalogs, including stalls and products, to nostrmarket with event ID tracking.
- Enhance order interface to include nostrEventId for better integration with nostrmarket.
- Improve error handling and logging for nostrmarket publishing processes.

refactor: Simplify order creation logic in useOrderEvents and update contact structure in nostrmarketService

- Streamline order creation by using event.id and defaulting to 'unknown' for stallId.
- Update contact structure to include address and message, removing optional email and phone fields for clarity.
- Ensure compatibility with new order data structure for improved integration with nostrmarket.

feat: Add bech32 to hex conversion utility and integrate into nostrmarketService

- Implement a new utility function to convert bech32 keys to hex format, enhancing key handling.
- Update nostrmarketService to utilize the new conversion function for user public and private keys.
- Modify contact structure to include additional fields for improved order information management.

feat: Add nostrclient configuration to AppConfig for enhanced Nostr integration

- Introduce a new nostrclient property in AppConfig to manage Nostr client settings.
- Include url and enabled fields to configure the Nostr client connection dynamically.
- Ensure compatibility with environment variables for flexible deployment configurations.

feat: Introduce comprehensive order management and fulfillment documentation

- Add ORDER_MANAGEMENT_FULFILLMENT.md to detail the complete order lifecycle, including order states, data models, and merchant/customer interfaces.
- Implement test scripts for verifying order and payment request formats in test-nostrmarket-format.js.
- Create PaymentRequestDialog.vue for handling payment requests with dynamic options and QR code generation.
- Enhance useOrderEvents.ts to process nostrmarket protocol messages for order management.
- Update nostrmarketService.ts to handle payment requests and order status updates, ensuring seamless integration with the marketplace.
- Integrate payment request dialog in Market.vue and manage its state in the market store.

refactor: Remove obsolete test script for nostrmarket order format

- Delete test-nostrmarket-format.js as it is no longer needed for verifying order and payment request formats.
- Update PaymentRequestDialog.vue to enhance UI components and integrate QR code generation for payment requests.
- Refactor payment handling and notification logic to utilize toast notifications instead of Quasar's notify system.

feat: Enhance OrderHistory component with payment request handling and QR code generation

- Add UI elements to display payment request status and options in OrderHistory.vue.
- Implement functions to copy payment requests, open Lightning wallets, and download QR codes.
- Update nostrmarketService to generate QR codes for payment requests and manage order statuses effectively.
- Remove obsolete PaymentRequestDialog integration from Market.vue for a cleaner UI.

feat: Add debug information and toast notifications in OrderHistory component

- Introduce debug info display for payment requests and hashes in OrderHistory.vue.
- Implement toast notifications for actions like copying payment requests, opening wallets, and downloading QR codes.
- Enhance error handling with user feedback for various order-related actions.
- Remove obsolete payment request dialog methods from market store for cleaner code.

feat: Revamp CartItem and ShoppingCart components for improved layout and functionality

- Enhance CartItem.vue with responsive design for desktop and mobile views, including better organization of product details, price, quantity controls, and remove button.
- Update ShoppingCart.vue to separate desktop and mobile layouts, improving the user experience with clearer action buttons and cart summary display.
- Implement consistent styling and layout adjustments for better visual coherence across different screen sizes.
2025-09-04 17:51:30 +02:00

310 lines
10 KiB
Vue

<template>
<div class="space-y-6">
<!-- Stats Cards -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
<!-- Total Orders -->
<div class="bg-card p-6 rounded-lg border shadow-sm">
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-medium text-muted-foreground">Total Orders</p>
<p class="text-2xl font-bold text-foreground">{{ orderStats.total }}</p>
</div>
<div class="w-12 h-12 bg-primary/10 rounded-lg flex items-center justify-center">
<Package class="w-6 h-6 text-primary" />
</div>
</div>
<div class="mt-4">
<div class="flex items-center text-sm text-muted-foreground">
<span>{{ orderStats.pending }} pending</span>
<span class="mx-2"></span>
<span>{{ orderStats.paid }} paid</span>
</div>
</div>
</div>
<!-- Pending Payments -->
<div class="bg-card p-6 rounded-lg border shadow-sm">
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-medium text-muted-foreground">Pending Payments</p>
<p class="text-2xl font-bold text-foreground">{{ orderStats.pendingPayments }}</p>
</div>
<div class="w-12 h-12 bg-yellow-500/10 rounded-lg flex items-center justify-center">
<DollarSign class="w-6 h-6 text-yellow-500" />
</div>
</div>
<div class="mt-4">
<div class="flex items-center text-sm text-muted-foreground">
<span>Total: {{ formatPrice(orderStats.pendingAmount, 'sat') }}</span>
</div>
</div>
</div>
<!-- Recent Sales (Merchant) -->
<div class="bg-card p-6 rounded-lg border shadow-sm">
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-medium text-muted-foreground">Recent Sales</p>
<p class="text-2xl font-bold text-foreground">{{ orderStats.recentSales }}</p>
</div>
<div class="w-12 h-12 bg-green-500/10 rounded-lg flex items-center justify-center">
<Store class="w-6 h-6 text-green-500" />
</div>
</div>
<div class="mt-4">
<div class="flex items-center text-sm text-muted-foreground">
<span>Last 7 days</span>
</div>
</div>
</div>
<!-- Market Activity -->
<div class="bg-card p-6 rounded-lg border shadow-sm">
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-medium text-muted-foreground">Market Activity</p>
<p class="text-2xl font-bold text-foreground">{{ orderStats.active }}</p>
</div>
<div class="w-12 h-12 bg-purple-500/10 rounded-lg flex items-center justify-center">
<BarChart3 class="w-6 h-6 text-purple-500" />
</div>
</div>
<div class="mt-4">
<div class="flex items-center text-sm text-muted-foreground">
<span>{{ orderStats.connected ? 'Connected' : 'Disconnected' }}</span>
</div>
</div>
</div>
</div>
<!-- Quick Actions -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Customer Actions -->
<div class="bg-card p-6 rounded-lg border shadow-sm">
<h3 class="text-lg font-semibold text-foreground mb-4 flex items-center gap-2">
<ShoppingCart class="w-5 h-5 text-primary" />
Customer Actions
</h3>
<div class="space-y-3">
<Button
@click="navigateToMarket"
variant="default"
class="w-full justify-start"
>
<Store class="w-4 h-4 mr-2" />
Browse Market
</Button>
<Button
@click="navigateToOrders"
variant="outline"
class="w-full justify-start"
>
<Package class="w-4 h-4 mr-2" />
View All Orders
</Button>
<Button
@click="navigateToCart"
variant="outline"
class="w-full justify-start"
>
<ShoppingCart class="w-4 h-4 mr-2" />
Shopping Cart
</Button>
</div>
</div>
<!-- Merchant Actions -->
<div class="bg-card p-6 rounded-lg border shadow-sm">
<h3 class="text-lg font-semibold text-foreground mb-4 flex items-center gap-2">
<Store class="w-5 h-5 text-green-500" />
Merchant Actions
</h3>
<div class="space-y-3">
<Button
@click="navigateToStore"
variant="default"
class="w-full justify-start"
>
<Store class="w-4 h-4 mr-2" />
Manage Store
</Button>
<Button
@click="navigateToProducts"
variant="outline"
class="w-full justify-start"
>
<Package class="w-4 h-4 mr-2" />
Manage Products
</Button>
<Button
@click="navigateToOrders"
variant="outline"
class="w-full justify-start"
>
<Package class="w-4 h-4 mr-2" />
View Orders
</Button>
</div>
</div>
</div>
<!-- Recent Activity -->
<div class="bg-card p-6 rounded-lg border shadow-sm">
<h3 class="text-lg font-semibold text-foreground mb-4">Recent Activity</h3>
<div v-if="recentActivity.length > 0" class="space-y-3">
<div
v-for="activity in recentActivity"
:key="activity.id"
class="flex items-center justify-between p-3 bg-muted rounded-lg"
>
<div class="flex items-center gap-3">
<div class="w-8 h-8 bg-primary/10 rounded-full flex items-center justify-center">
<component :is="getActivityIcon(activity.type)" class="w-4 h-4 text-primary" />
</div>
<div>
<p class="text-sm font-medium text-foreground">{{ activity.title }}</p>
<p class="text-xs text-muted-foreground">{{ formatDate(activity.timestamp) }}</p>
</div>
</div>
<Badge :variant="getActivityVariant(activity.type)">
{{ activity.status }}
</Badge>
</div>
</div>
<div v-else class="text-center py-8 text-muted-foreground">
<Package class="w-12 h-12 mx-auto mb-3 text-muted-foreground/50" />
<p>No recent activity</p>
<p class="text-sm">Start shopping or selling to see activity here</p>
</div>
</div>
<!-- Market Status -->
<div class="bg-card p-6 rounded-lg border shadow-sm">
<h3 class="text-lg font-semibold text-foreground mb-4">Market Status</h3>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<div class="flex items-center gap-3">
<div
class="w-3 h-3 rounded-full"
:class="orderEvents.isSubscribed ? 'bg-green-500' : 'bg-yellow-500'"
></div>
<span class="text-sm text-muted-foreground">
Order Events: {{ orderEvents.isSubscribed ? 'Connected' : 'Connecting...' }}
</span>
</div>
<div class="flex items-center gap-3">
<div
class="w-3 h-3 rounded-full"
:class="isConnected ? 'bg-green-500' : 'bg-red-500'"
></div>
<span class="text-sm text-muted-foreground">
Market: {{ isConnected ? 'Connected' : 'Disconnected' }}
</span>
</div>
<div class="flex items-center gap-3">
<div
class="w-3 h-3 rounded-full"
:class="auth.isAuthenticated ? 'bg-green-500' : 'bg-red-500'"
></div>
<span class="text-sm text-muted-foreground">
Auth: {{ auth.isAuthenticated ? 'Authenticated' : 'Not Authenticated' }}
</span>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { useRouter } from 'vue-router'
import { useMarketStore } from '@/stores/market'
import { useAuth } from '@/composables/useAuth'
import { useMarket } from '@/composables/useMarket'
import { orderEvents } from '@/composables/useOrderEvents'
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import {
Package,
Store,
ShoppingCart,
DollarSign,
BarChart3,
Clock
} from 'lucide-vue-next'
const router = useRouter()
const marketStore = useMarketStore()
const auth = useAuth()
const { isConnected } = useMarket()
// Computed properties
const orderStats = computed(() => {
const orders = Object.values(marketStore.orders)
const now = Date.now() / 1000
const sevenDaysAgo = now - (7 * 24 * 60 * 60)
return {
total: orders.length,
pending: orders.filter(o => o.status === 'pending').length,
paid: orders.filter(o => o.status === 'paid').length,
pendingPayments: orders.filter(o => o.paymentStatus === 'pending').length,
pendingAmount: orders
.filter(o => o.paymentStatus === 'pending')
.reduce((sum, o) => sum + o.total, 0),
recentSales: orders.filter(o =>
o.status === 'paid' && o.createdAt > sevenDaysAgo
).length,
active: orders.filter(o =>
['pending', 'paid', 'processing'].includes(o.status)
).length,
connected: false
}
})
const recentActivity = computed(() => {
const orders = Object.values(marketStore.orders)
const now = Date.now() / 1000
const recentOrders = orders
.filter(o => o.updatedAt > now - (24 * 60 * 60)) // Last 24 hours
.sort((a, b) => b.updatedAt - a.updatedAt)
.slice(0, 5)
return recentOrders.map(order => ({
id: order.id,
type: 'order',
title: `Order ${order.id.slice(-8)} - ${order.status}`,
status: order.status,
timestamp: order.updatedAt
}))
})
// Methods
const formatPrice = (price: number, currency: string) => {
return `${price} ${currency}`
}
const formatDate = (timestamp: number) => {
return new Date(timestamp * 1000).toLocaleString()
}
const getActivityIcon = (type: string) => {
switch (type) {
case 'order': return Package
default: return Clock
}
}
const getActivityVariant = (type: string) => {
switch (type) {
case 'order': return 'secondary'
default: return 'outline'
}
}
const navigateToMarket = () => router.push('/market')
const navigateToOrders = () => router.push('/market-dashboard?tab=orders')
const navigateToCart = () => router.push('/cart')
const navigateToStore = () => router.push('/market-dashboard?tab=store')
const navigateToProducts = () => router.push('/market-dashboard?tab=store')
</script>