342 lines
14 KiB
HTML
342 lines
14 KiB
HTML
<!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> |