First Commit

This commit is contained in:
mark committed 2026-10-19 15:22:52 -07:00
1 parent 5eb9dd037d
commit 2e62c0e60b
11877 files changed
+2035312

No files matched your search

+268
View File
@@ -0,0 +1,268 @@
<?php
/**
* Demo: Cart / Checkout Page
* Shows how to embed paypal-checkout-widget.php on a multi-item cart page.
*
* In your real app, replace $school, $cartItems, and $buyerEmail
* with values from your session and database.
*/
require_once __DIR__ . '/demo-helper.php';
// ── In your real app these come from session / DB ─────────────────────────────
// Auto-resolve to a PayPal-connected school so the buttons actually render.
// (Pass ?school=Name to force a specific connected school.)
$school = pp_demo_resolve_school($_GET['school'] ?? null);
$schoolReady = $school !== null;
$schoolLabel = $school ?? 'Demo School';
$buyerEmail = ''; // e.g. $_SESSION['user']['email']
$cartItems = [
['name' => 'Monthly Lunch Plan — October', 'qty' => 1, 'price' => 95.00, 'emoji' => '🍱'],
['name' => 'Morning Snack Pack × 20 days', 'qty' => 1, 'price' => 28.00, 'emoji' => '🥐'],
['name' => 'Juice Box Bundle × 20 days', 'qty' => 1, 'price' => 14.00, 'emoji' => '🧃'],
];
$currency = 'USD';
// ── End of real-app variables ─────────────────────────────────────────────────
// Calculate total + build PayPal line items
$total = 0.0;
$ppItems = [];
foreach ($cartItems as $item) {
$lineTotal = $item['price'] * $item['qty'];
$total += $lineTotal;
$ppItems[] = [
'name' => $item['name'],
'quantity' => (string)$item['qty'],
'unit_amount' => ['currency_code' => $currency, 'value' => number_format($item['price'], 2, '.', '')],
];
}
$ppCheckout = [
'school_name' => $schoolLabel,
'amount' => number_format($total, 2, '.', ''),
'currency' => $currency,
'items' => $ppItems,
'buyer_email' => $buyerEmail,
'page_type' => 'cart', // tells PayPal this is a cart page
'order_api_url' => './order-api.php',
'success_url' => './demo-success.php?school=' . urlencode($schoolLabel),
'cancel_url' => './demo-cart.php',
];
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Your Cart — <?= htmlspecialchars($schoolLabel) ?></title>
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: #f7f8fa;
color: #1a202c;
}
/* ── Top bar ── */
.topbar {
background: #fff;
border-bottom: 1px solid #e2e8f0;
padding: 14px 24px;
display: flex;
align-items: center;
gap: 12px;
}
.topbar-logo { font-size: 22px; }
.topbar-name { font-weight: 700; font-size: 17px; color: #003087; }
.topbar-school { font-size: 13px; color: #718096; margin-left: auto; }
.topbar-back {
font-size: 13px; color: #003087; text-decoration: none;
padding: 6px 14px; border: 1px solid #bee3f8; border-radius: 6px;
background: #ebf8ff;
}
/* ── Layout ── */
.page { max-width: 960px; margin: 32px auto; padding: 0 20px; display: grid; grid-template-columns: 1fr 400px; gap: 28px; align-items: start; }
@media (max-width: 700px) { .page { grid-template-columns: 1fr; } }
/* ── Cart items ── */
.cart-card {
background: #fff;
border-radius: 12px;
border: 1px solid #e2e8f0;
overflow: hidden;
}
.cart-header {
padding: 18px 24px;
border-bottom: 1px solid #e2e8f0;
display: flex;
justify-content: space-between;
align-items: center;
}
.cart-header h2 { font-size: 17px; font-weight: 700; }
.cart-count { font-size: 13px; color: #718096; }
.cart-item {
display: flex;
align-items: center;
gap: 16px;
padding: 16px 24px;
border-bottom: 1px solid #f0f0f0;
}
.cart-item:last-child { border-bottom: none; }
.cart-item-emoji { font-size: 32px; flex-shrink: 0; }
.cart-item-name { font-size: 15px; font-weight: 600; margin-bottom: 3px; }
.cart-item-sub { font-size: 13px; color: #718096; }
.cart-item-price { margin-left: auto; font-size: 16px; font-weight: 700; white-space: nowrap; }
/* ── Order summary panel ── */
.summary-panel {
background: #fff;
border-radius: 12px;
border: 1px solid #e2e8f0;
padding: 24px;
position: sticky;
top: 24px;
}
.summary-title { font-size: 16px; font-weight: 700; margin-bottom: 18px; }
.summary-row {
display: flex;
justify-content: space-between;
font-size: 14px;
color: #4a5568;
padding: 6px 0;
}
.summary-row.total {
border-top: 2px solid #e2e8f0;
margin-top: 8px;
padding-top: 14px;
font-size: 18px;
font-weight: 700;
color: #1a202c;
}
.summary-divider { margin: 20px 0; }
/* ── Card payment fallback ── */
.card-section h4 { font-size: 14px; font-weight: 600; color: #4a5568; margin-bottom: 14px; }
.card-field {
border: 1.5px solid #e2e8f0; border-radius: 8px;
padding: 11px 14px; font-size: 15px; width: 100%;
margin-bottom: 12px; color: #a0aec0;
}
.card-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.btn-card {
width: 100%; padding: 13px;
background: #2d3748; color: #fff;
border: none; border-radius: 8px;
font-size: 15px; font-weight: 600; cursor: pointer; margin-top: 4px;
}
.btn-card:hover { background: #1a202c; }
.secure-note {
text-align: center; font-size: 12px; color: #a0aec0; margin-top: 14px;
display: flex; align-items: center; justify-content: center; gap: 4px;
}
</style>
</head>
<body>
<nav class="topbar">
<span class="topbar-logo">🍽️</span>
<span class="topbar-name">HotLunches</span>
<a href="demo-product.php?school=<?= urlencode($schoolLabel) ?>" class="topbar-back">← Continue shopping</a>
<span class="topbar-school"><?= htmlspecialchars($schoolLabel) ?></span>
</nav>
<div class="page">
<!-- Left: cart items -->
<div>
<div class="cart-card">
<div class="cart-header">
<h2>Your Order</h2>
<span class="cart-count"><?= count($cartItems) ?> item<?= count($cartItems) > 1 ? 's' : '' ?></span>
</div>
<?php foreach ($cartItems as $item): ?>
<div class="cart-item">
<div class="cart-item-emoji"><?= $item['emoji'] ?></div>
<div>
<div class="cart-item-name"><?= htmlspecialchars($item['name']) ?></div>
<div class="cart-item-sub">Qty: <?= $item['qty'] ?></div>
</div>
<div class="cart-item-price">$<?= number_format($item['price'], 2) ?></div>
</div>
<?php endforeach; ?>
</div>
</div>
<!-- Right: checkout panel -->
<div>
<div class="summary-panel">
<div class="summary-title">Order Summary</div>
<?php foreach ($cartItems as $item): ?>
<div class="summary-row">
<span><?= htmlspecialchars($item['name']) ?></span>
<span>$<?= number_format($item['price'], 2) ?></span>
</div>
<?php endforeach; ?>
<div class="summary-row total">
<span>Total</span>
<span>$<?= number_format($total, 2) ?></span>
</div>
<?php
/* Pay Later message below cart total — shows "Pay later with PayPal" (placement: cart) */
$ppMessage = [
'school_name' => $schoolLabel,
'amount' => number_format($total, 2, '.', ''),
'currency' => $currency,
'placement' => 'cart',
'page_type' => 'cart',
];
require_once __DIR__ . '/paypal-paylater-message.php';
?>
<div class="summary-divider"></div>
<?php if (!$schoolReady): ?>
<div style="background:#fffaf0;border:1px solid #feebc8;color:#9c4221;border-radius:10px;padding:14px 16px;font-size:13px;line-height:1.6;margin-bottom:16px;">
<strong>No PayPal-connected school found.</strong><br>
The checkout buttons appear once a school has completed PayPal onboarding.
Connect one in <a href="index.php" style="color:#9c4221;font-weight:600;">School Merchant Setup</a>,
or open this page as <code>?school=&lt;connected school name&gt;</code>.
</div>
<?php endif; ?>
<?php
/*
* ══════════════════════════════════════════════════════
* PAYPAL WIDGET — rendered FIRST, above card payment.
* page_type='cart' is passed so PayPal can apply
* cart-specific optimisations (e.g. express checkout).
* ══════════════════════════════════════════════════════
*/
require_once __DIR__ . '/paypal-checkout-widget.php';
?>
<!-- Card payment — shown below the widget divider -->
<div class="card-section">
<h4>Pay with card</h4>
<input class="card-field" type="text" placeholder="Card number" disabled>
<div class="card-row">
<input class="card-field" type="text" placeholder="MM / YY" disabled>
<input class="card-field" type="text" placeholder="CVV" disabled>
</div>
<button class="btn-card" disabled>Pay $<?= number_format($total, 2) ?></button>
<p class="secure-note">🔒 Secured by PayPal</p>
</div>
</div>
</div>
</div>
</body>
</html>