Files
projectmycelium/src/views/marketplace/checkout.html
2025-09-01 21:37:01 -04:00

342 lines
14 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Checkout - Project Mycelium</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.8.0/font/bootstrap-icons.css" rel="stylesheet">
<style>
body {
background-color: #f8f9fa;
}
.navbar-brand img {
height: 30px;
}
.checkout-step {
position: relative;
padding: 1rem;
border-radius: 8px;
transition: all 0.3s ease;
}
.checkout-step.active {
background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%);
border: 2px solid #2196f3;
}
.checkout-step.completed {
background: linear-gradient(135deg, #e8f5e8 0%, #c8e6c9 100%);
border: 2px solid #4caf50;
}
.step-number {
width: 32px;
height: 32px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
margin-right: 1rem;
}
.step-number.active {
background: #2196f3;
color: white;
}
.step-number.completed {
background: #4caf50;
color: white;
}
.step-number.pending {
background: #e0e0e0;
color: #757575;
}
.payment-method {
border: 2px solid #e0e0e0;
border-radius: 8px;
padding: 1rem;
cursor: pointer;
transition: all 0.3s ease;
}
.payment-method:hover {
border-color: #2196f3;
background-color: #f5f5f5;
}
.payment-method.selected {
border-color: #2196f3;
background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%);
}
.order-summary {
position: sticky;
top: 20px;
background: white;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
.security-badge {
background: linear-gradient(135deg, #e8f5e8 0%, #c8e6c9 100%);
border: 1px solid #4caf50;
border-radius: 8px;
}
.card {
border: none;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.btn-primary {
background: linear-gradient(135deg, #0d6efd 0%, #0b5ed7 100%);
border: none;
}
.btn-primary:hover {
background: linear-gradient(135deg, #0b5ed7 0%, #0a58ca 100%);
}
.form-control:focus {
border-color: #2196f3;
box-shadow: 0 0 0 0.2rem rgba(33, 150, 243, 0.25);
}
.breadcrumb {
background: none;
padding: 0;
}
.breadcrumb-item + .breadcrumb-item::before {
content: "";
font-weight: bold;
}
</style>
</head>
<body>
<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container">
<a class="navbar-brand d-flex align-items-center" href="/">
<img src="/static/images/logo_dark.png" alt="ThreeFold Logo" class="me-2">
<span>Project Mycelium</span>
</a>
<div class="navbar-nav ms-auto">
<a class="nav-link" href="/marketplace">
<i class="bi bi-shop me-1"></i>Marketplace
</a>
<a class="nav-link" href="/cart">
<i class="bi bi-cart3 me-1"></i>Cart
</a>
<a class="nav-link active" href="/checkout">
<i class="bi bi-credit-card me-1"></i>Checkout
</a>
</div>
</div>
</nav>
<div class="container py-4">
<!-- Page Header -->
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-4 border-bottom">
<h1 class="h2 mb-0">
<i class="bi bi-credit-card me-2 text-primary"></i>Secure Checkout
</h1>
<div class="btn-toolbar">
<a href="/cart" class="btn btn-outline-secondary">
<i class="bi bi-arrow-left me-1"></i>Back to Cart
</a>
</div>
</div>
<!-- Checkout Steps -->
<div class="row mb-4">
<div class="col-12">
<div class="d-flex justify-content-between">
<div class="checkout-step active flex-fill me-2">
<div class="d-flex align-items-center">
<div class="step-number active">1</div>
<div>
<div class="fw-bold">Review Order</div>
<small class="text-muted">Verify your items</small>
</div>
</div>
</div>
<div class="checkout-step pending flex-fill me-2">
<div class="d-flex align-items-center">
<div class="step-number pending">2</div>
<div>
<div class="fw-bold">Payment</div>
<small class="text-muted">Choose payment method</small>
</div>
</div>
</div>
<div class="checkout-step pending flex-fill">
<div class="d-flex align-items-center">
<div class="step-number pending">3</div>
<div>
<div class="fw-bold">Confirmation</div>
<small class="text-muted">Order complete</small>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<!-- Checkout Form -->
<div class="col-lg-8">
<!-- Step 1: Order Review -->
<div id="step1" class="checkout-section">
<div class="card mb-4">
<div class="card-header bg-white">
<h5 class="mb-0">
<i class="bi bi-bag-check me-2"></i>Order Review
</h5>
</div>
<div class="card-body">
{% if cart_details and cart_details.items %}
{% for item in cart_details.items %}
<div class="d-flex align-items-center p-3 border-bottom">
<div class="me-3">
<div class="bg-light rounded d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
{% if item.product.category_id == "compute" %}
<i class="bi bi-cpu text-primary"></i>
{% elif item.product.category_id == "hardware" %}
<i class="bi bi-hdd-rack text-success"></i>
{% elif item.product.category_id == "gateways" %}
<i class="bi bi-globe text-info"></i>
{% elif item.product.category_id == "applications" %}
<i class="bi bi-app text-warning"></i>
{% elif item.product.category_id == "services" %}
<i class="bi bi-person-workspace text-secondary"></i>
{% else %}
<i class="bi bi-box text-muted"></i>
{% endif %}
</div>
</div>
<div class="flex-grow-1">
<h6 class="mb-1">{{ item.product.name }}</h6>
<small class="text-muted">{{ item.product.provider_name }}</small>
<div class="mt-1">
<span class="badge bg-light text-dark">Qty: {{ item.cart_item.quantity }}</span>
</div>
</div>
<div class="text-end">
<div class="fw-bold text-primary">{{ item.unit_price.formatted_display }}</div>
<small class="text-muted">per unit</small>
</div>
</div>
{% endfor %}
{% else %}
<div class="text-center py-4">
<i class="bi bi-cart-x fs-1 text-muted mb-3"></i>
<h5 class="text-muted">No items in cart</h5>
<a href="/marketplace" class="btn btn-primary">Browse Marketplace</a>
</div>
{% endif %}
</div>
</div>
<div class="d-flex justify-content-end">
<button class="btn btn-primary btn-lg" id="complete-order-btn">
Complete Order <i class="bi bi-lock ms-1"></i>
</button>
</div>
</div>
</div>
<!-- Order Summary -->
<div class="col-lg-4">
<div class="order-summary p-4">
<h5 class="mb-3">
<i class="bi bi-receipt me-2 text-primary"></i>Order Summary
</h5>
{% if cart_details %}
<div class="d-flex justify-content-between mb-2">
<span>Subtotal ({{ cart_details.item_count }} items)</span>
<span class="fw-bold" id="subtotal-display">{{ cart_details.subtotal }} {{ cart_details.currency }}</span>
</div>
<div class="d-flex justify-content-between mb-2">
<span class="text-muted">Platform fee</span>
<span class="text-muted">Free</span>
</div>
<div class="d-flex justify-content-between mb-2">
<span class="text-muted">Deployment</span>
<span class="text-success fw-bold">Free</span>
</div>
<hr>
<div class="d-flex justify-content-between mb-4">
<span class="fw-bold fs-5">Total</span>
<span class="fw-bold text-primary fs-4" id="total-display">{{ cart_details.total }} {{ cart_details.currency }}</span>
</div>
{% endif %}
<!-- Security Badges -->
<div class="security-badge p-3 mb-3">
<div class="d-flex align-items-center mb-2">
<i class="bi bi-shield-check text-success me-2 fs-5"></i>
<div>
<div class="fw-bold small">Secure Checkout</div>
<div class="small text-muted">256-bit SSL encryption</div>
</div>
</div>
<div class="d-flex align-items-center">
<i class="bi bi-lock text-success me-2 fs-5"></i>
<div>
<div class="fw-bold small">Privacy Protected</div>
<div class="small text-muted">Your data is safe with us</div>
</div>
</div>
</div>
<!-- Support -->
<div class="text-center">
<small class="text-muted">
Need help? <a href="https://threefoldfaq.crisp.help/en/" class="text-decoration-none" target="_blank">Contact Support</a>
</small>
</div>
</div>
</div>
</div>
</div>
<!-- Loading Overlay -->
<div id="loadingOverlay" class="position-fixed top-0 start-0 w-100 h-100 d-none" style="background: rgba(0,0,0,0.5); z-index: 9999;">
<div class="d-flex justify-content-center align-items-center h-100">
<div class="spinner-border text-light" role="status" style="width: 3rem; height: 3rem;">
<span class="visually-hidden">Processing...</span>
</div>
</div>
</div>
<!-- Bootstrap JS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>
<!-- Modal + Errors utilities (must load before checkout.js) -->
<script src="/static/js/modal-system.js"></script>
<script src="/static/js/utils/errors.js"></script>
<!-- JSON hydration for checkout (CSP-safe) -->
<script type="application/json" id="checkout-hydration">
{
"user_currency": {{ user_currency | default(value='USD') | json_encode() | safe }},
"cart_details": {% if cart_details is defined %}{{ cart_details | json_encode() | safe }}{% else %}null{% endif %}
}
</script>
<!-- External JS (CSP-compliant) -->
<script src="/static/js/base.js"></script>
<script src="/static/js/checkout.js"></script>
</body>
</html>