static sites for ODOO

This commit is contained in:
oliver
2026-08-22 09:37:27 -03:00
parent b34e001c46
commit 7245e47cac
2 changed files with 750 additions and 0 deletions
+447
View File
@@ -0,0 +1,447 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Your Plan</title>
<style>
body {
font-family: "Inter", "Segoe UI", Arial, sans-serif;
background-color: #f4f5f7;
color: #333;
margin: 0;
padding: 32px 16px;
}
.page-title {
text-align: center;
color: #262626;
font-size: 1.45em;
font-weight: 700;
margin-bottom: 6px;
}
.page-subtitle {
text-align: center;
font-size: 1.05em;
color: #444;
margin-bottom: 32px;
letter-spacing: 0.01em;
line-height: 1.7;
font-weight: 400;
}
.plans-row {
display: flex;
flex-wrap: wrap;
gap: 18px;
justify-content: center;
align-items: stretch;
}
.plan-card {
background: #fff;
border: 1px solid #e0e0e0;
border-radius: 14px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
padding: 26px 22px 20px;
width: 200px;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
position: relative;
transition:
box-shadow 0.2s,
border-color 0.2s,
transform 0.2s;
}
.plan-card:hover {
box-shadow: 0 6px 22px rgba(0, 0, 0, 0.11);
transform: scale(1.03);
}
#card-ontherise {
border: 3px dotted #e0e0e0;
}
.plan-card.current {
border-color: #4caf50;
box-shadow:
0 0 0 3px rgba(76, 175, 80, 0.2),
0 4px 16px rgba(76, 175, 80, 0.15);
}
.plan-badge {
position: absolute;
top: -13px;
left: 50%;
transform: translateX(-50%);
background: #4caf50;
color: #fff;
font-size: 0.68em;
font-weight: 700;
padding: 3px 11px;
border-radius: 20px;
white-space: nowrap;
box-shadow: 0 2px 6px rgba(76, 175, 80, 0.35);
letter-spacing: 0.01em;
}
.plan-name {
font-size: 1.05em;
font-weight: 700;
color: #262626;
margin-bottom: 14px;
letter-spacing: 0.02em;
text-transform: uppercase;
}
.plan-price {
font-size: 1.55em;
font-weight: 800;
color: #875a7b;
line-height: 1.1;
margin-bottom: 2px;
}
.plan-price-period {
font-size: 0.75em;
color: #aaa;
margin-bottom: 14px;
}
.plan-tagline {
font-size: 0.8em;
color: #666;
font-style: italic;
margin-bottom: 16px;
line-height: 1.5;
min-height: 52px;
display: flex;
align-items: center;
justify-content: center;
}
.plan-btn {
background-color: #875a7b;
color: #fff;
border: none;
border-radius: 7px;
padding: 9px 0;
font-size: 0.88em;
font-weight: 600;
cursor: pointer;
width: 100%;
margin-bottom: 18px;
transition:
background-color 0.2s,
transform 0.1s;
letter-spacing: 0.01em;
}
.plan-btn:hover:not(:disabled) {
background-color: #744e6a;
transform: translateY(-1px);
}
.plan-btn:disabled {
background-color: #bdbdbd;
color: #fff;
cursor: not-allowed;
transform: none;
}
.plan-btn.is-current-plan:disabled {
background-color: #4caf50;
}
.plan-features {
list-style: none;
padding: 0;
margin: 0;
width: 100%;
text-align: left;
}
.plan-features li {
font-size: 0.78em;
color: #555;
padding: 5px 0 5px 18px;
border-top: 1px solid #f2f2f2;
position: relative;
line-height: 1.4;
}
.plan-features li:first-child {
border-top: none;
}
.plan-features li::before {
content: "";
position: absolute;
left: 0;
color: #875a7b;
font-weight: 700;
}
.plan-guarantee {
font-size: 0.68em;
color: #bbb;
margin-top: auto;
padding-top: 14px;
font-style: italic;
min-height: 18px;
}
.footer-uuid {
text-align: center;
font-size: 0.75em;
color: #ccc;
margin-top: 40px;
user-select: all;
}
</style>
</head>
<body>
<div class="page-subtitle">
You <b>immediately</b> unlock all new features and higher limits.<br />
Any extra time is <b>added</b> to your existing subscription.
</div>
<div class="plans-row" id="plansRow">
<!-- ── Trial ─────────────────────────────────────────────────── -->
<div class="plan-card" id="card-trial">
<div class="plan-name">Trial</div>
<div class="plan-price">4 weeks free</div>
<div class="plan-price-period">&nbsp;</div>
<div class="plan-tagline">
"I want to see what ODOO can do for my company."
</div>
<button
class="plan-btn is-current-plan"
id="btn-trial"
disabled
>
Trial
</button>
<ul class="plan-features">
<li>ODOO CE hosting</li>
<li>0 Backup Slots</li>
<li>No Domain Mapping</li>
<li>No module installation</li>
</ul>
<div class="plan-guarantee">&nbsp;</div>
</div>
<!-- ── Side Hustle ───────────────────────────────────────────── -->
<div class="plan-card" id="card-sidehustle">
<div class="plan-name">Side Hustle</div>
<div class="plan-price">$214.00</div>
<div class="plan-price-period">/ year</div>
<div class="plan-tagline">
"ODOO Standard .. that is all my business needs"
</div>
<button class="plan-btn" id="btn-sidehustle">
Upgrade Now
</button>
<ul class="plan-features">
<li>ODOO CE hosting</li>
<li>Space for 1 Backup</li>
<li>Connect 1 domain with SSL</li>
<li>No module installation</li>
<li>One Year of Sercice</li>
</ul>
</div>
<!-- ── On the Rise ───────────────────────────────────────────── -->
<div class="plan-card" id="card-ontherise">
<div class="plan-name">On the Rise</div>
<div class="plan-price">$395.00</div>
<div class="plan-price-period">/ year</div>
<div class="plan-tagline">
"I need some modules and professional reports"
</div>
<button class="plan-btn" id="btn-ontherise">Upgrade Now</button>
<ul class="plan-features">
<li>ODOO CE hosting</li>
<li>Space for 4 Backups</li>
<li>Connect 3 domain with SSL</li>
<li>Install custom modules</li>
<li>One Year of Sercice</li>
</ul>
</div>
<!-- ── Powerhouse ────────────────────────────────────────────── -->
<div class="plan-card" id="card-powerhouse">
<div class="plan-name">Powerhouse</div>
<div class="plan-price">$595.00</div>
<div class="plan-price-period">/ year</div>
<div class="plan-tagline">
"ODOO Enterprise is a must have!"
</div>
<button class="plan-btn" id="btn-powerhouse">
Upgrade Now
</button>
<ul class="plan-features">
<li>All of On the Rise</li>
<li>ODOO Enterprise Ready</li>
<li>2 Workers</li>
<li>One Year of Sercice</li>
</ul>
</div>
</div>
<div class="footer-uuid">UUID: <span id="uuidText"></span></div>
<script>
// ── Webhooks ─────────────────────────────────────────────────────────────
const getContract_Webhook =
"https://002-001-5dd6e535-4d1c-46bc-9bd9-42ad4bc5f082.odoo4projects.com/webhook/0c8536be-d175-4740-8e78-123159193b23";
const buy_webhook =
"https://002-001-5dd6e535-4d1c-46bc-9bd9-42ad4bc5f082.odoo4projects.com/webhook/2366cc41-bfd9-41c0-b9b4-bea1e60726f1";
// ── Plan hierarchy (index = tier, lower = cheaper) ────────────────────────
const PLAN_ORDER = [
"Trial",
"Side Hustle",
"On the Rise",
"Powerhouse",
];
const PLAN_META = {
Trial: {
cardId: "card-trial",
btnId: "btn-trial",
productId: null,
},
"Side Hustle": {
cardId: "card-sidehustle",
btnId: "btn-sidehustle",
productId: "sidehustle",
},
"On the Rise": {
cardId: "card-ontherise",
btnId: "btn-ontherise",
productId: "ontherise",
},
Powerhouse: {
cardId: "card-powerhouse",
btnId: "btn-powerhouse",
productId: "powerhouse",
},
};
// ── UUID from URL ─────────────────────────────────────────────────────────
const params = new URLSearchParams(window.location.search);
const uuid = params.get("uuid") || "";
document.getElementById("uuidText").textContent = uuid || "";
// ── Buy handler ───────────────────────────────────────────────────────────
async function buyProduct(productId) {
if (!uuid) {
alert("Missing uuid parameter in URL.");
return;
}
try {
const res = await fetch(buy_webhook, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ uuid, product_id: productId }),
});
if (!res.ok) throw new Error("HTTP " + res.status);
document.body.innerHTML = `
<div style="text-align:center;padding:80px 20px;background:#fff;border-radius:14px;
max-width:560px;margin:60px auto;box-shadow:0 4px 20px rgba(0,0,0,0.1);
font-family:'Inter','Segoe UI',Arial,sans-serif;">
<div style="font-size:3em;margin-bottom:16px;">&#x2705;</div>
<h2 style="color:#262626;font-weight:700;margin-bottom:10px;">Request sent!</h2>
<p style="color:#777;line-height:1.6;">
Please check your email for the payment link and confirmation.<br>
New features will be active as soon as the payment is complete.
</p>
</div>`;
} catch (err) {
console.error(err);
alert(
"Something went wrong. Please try again or contact support.",
);
}
}
// ── Wire buy buttons ──────────────────────────────────────────────────────
document
.getElementById("btn-sidehustle")
.addEventListener("click", () => buyProduct("sidehustle"));
document
.getElementById("btn-ontherise")
.addEventListener("click", () => buyProduct("ontherise"));
document
.getElementById("btn-powerhouse")
.addEventListener("click", () => buyProduct("powerhouse"));
// ── Apply current-plan state ──────────────────────────────────────────────
function applyPlanState(contractName, expires) {
const currentIdx = PLAN_ORDER.indexOf(contractName);
if (currentIdx === -1) return; // unknown plan leave defaults
const badgeLabel = expires ? "✅ " + expires : "✅";
PLAN_ORDER.forEach(function (plan, idx) {
var meta = PLAN_META[plan];
if (!meta) return;
var btn = document.getElementById(meta.btnId);
var card = document.getElementById(meta.cardId);
if (!btn || !card) return;
if (idx === currentIdx) {
// Current plan green frame, badge with expiry date
card.classList.add("current");
var badge = document.createElement("div");
badge.className = "plan-badge";
badge.textContent = badgeLabel;
card.insertBefore(badge, card.firstChild);
// Trial is always green with no text skip button changes
if (plan !== "Trial") {
btn.textContent = "Add 1 Year";
btn.disabled = false;
btn.classList.add("is-current-plan");
}
} else if (idx < currentIdx) {
// Lower tier hide entirely
card.style.display = "none";
}
// Higher tiers: leave as "Upgrade Now" (enabled)
});
}
// ── Load contract from webhook ────────────────────────────────────────────
async function loadContract() {
if (!uuid) return;
try {
const res = await fetch(getContract_Webhook, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ uuid }),
});
if (!res.ok) throw new Error("HTTP " + res.status);
const payload = await res.json();
// Webhook returns: [{ "expires": "YYYY-MM-DD", "contractName": "Trial" }]
const record = Array.isArray(payload)
? payload[0]
: payload;
if (record && record.contract_name) {
applyPlanState(record.contract_name, record.expires);
}
} catch (err) {
console.error("Could not load contract data:", err);
// Graceful degradation: page remains usable with default button states
}
}
loadContract();
</script>
</body>
</html>