Skip to main content
// Online Pharmacy Website in HopeScript (HS + HSON + TDMLTK + T-Code)
// - Single-file example demonstrating components, routing, state, mock backend, prescription upload,
// cart, checkout flow, search & filters, admin CRUD, and a small ML-driven recommendation pipeline.
// - This is a practical, runnable blueprint for a Hope AI ecosystem app.
///////////////////////
// App Configuration //
///////////////////////
const APP_TITLE = "HopePharm - Online Pharmacy"
const API_PREFIX = "/api" // In a real deployment, point to your backend URL
const STORAGE_CART_KEY = "hopepharm_cart"
const STORAGE_USER_KEY = "hopepharm_user"
///////////////////////
// HSON: Sample Data //
///////////////////////
// Use HSON-like objects for initial dataset and schema declarations
const PRODUCTS = [
{
id: "p001",
name: "AcetaClear 500mg",
description: "Pain relief & fever reducer. 20 tablets.",
price: 7.99,
image: "https://hopeaihub.info/images/acetaclear.png",
category: "Analgesic",
requiresPrescription: false,
stock: 120
},
{
id: "p002",
name: "CardioSafe 10mg",
description: "Blood pressure control. 30 tablets.",
price: 19.5,
image: "https://hopeaihub.info/images/cardiosafe.png",
category: "Cardiovascular",
requiresPrescription: true,
stock: 45
},
{
id: "p003",
name: "AllerGone Syrup",
description: "Allergy relief, children-friendly syrup, 100ml.",
price: 12.25,
image: "https://hopeaihub.info/images/allergone.png",
category: "Antihistamine",
requiresPrescription: false,
stock: 80
}
]
// HSON schema (lightweight)
const PRODUCT_SCHEMA = {
id: "string",
name: "string",
description: "string",
price: "number",
image: "string",
category: "string",
requiresPrescription: "boolean",
stock: "number"
}
/////////////////////////
// Utility & Validators //
/////////////////////////
function validate(schema, obj) {
for (let k in schema) {
if (!(k in obj)) return false
const t = typeof obj[k]
if (schema[k] === "number" && t !== "number") return false
if (schema[k] === "string" && t !== "string") return false
if (schema[k] === "boolean" && t !== "boolean") return false
}
return true
}
function formatCurrency(n) {
return "$" + n.toFixed(2)
}
function saveCart(cart) {
localStorage.setItem(STORAGE_CART_KEY, JSON.stringify(cart))
}
function loadCart() {
const raw = localStorage.getItem(STORAGE_CART_KEY)
return raw ? JSON.parse(raw) : []
}
function saveUser(user) {
localStorage.setItem(STORAGE_USER_KEY, JSON.stringify(user))
}
function loadUser() {
const raw = localStorage.getItem(STORAGE_USER_KEY)
return raw ? JSON.parse(raw) : null
}
/////////////////////////
// Mock Backend Server //
/////////////////////////
// T-Code activation + mock DB registration (illustrative)
TCode.db("T-Code activated for HopePharm")
// Mock DB using in-memory store (for demo)
const DB = {
products: PRODUCTS.slice(),
orders: [],
users: [
{ id: "u_admin", email: "admin@hopepharm.example", name: "Admin", role: "admin", password: "adminpass" }
]
}
// Minimal API router
function apiGetProducts(query = {}) {
// filter by search, category, prescription flag
let list = DB.products.slice()
if (query.search) {
const s = query.search.toLowerCase()
list = list.filter(p => p.name.toLowerCase().includes(s) || p.description.toLowerCase().includes(s))
}
if (query.category) {
list = list.filter(p => p.category === query.category)
}
if (query.requiresPrescription !== undefined) {
list = list.filter(p => p.requiresPrescription === query.requiresPrescription)
}
return Promise.resolve(list)
}
function apiGetProductById(id) {
const p = DB.products.find(x => x.id === id)
return Promise.resolve(p ? Object.assign({}, p) : null)
}
function apiCreateOrder(order) {
// Basic validation; ensure items exist and stock available
for (let item of order.items) {
const prod = DB.products.find(p => p.id === item.productId)
if (!prod) return Promise.reject("Product not found: " + item.productId)
if (prod.stock < item.quantity) return Promise.reject("Insufficient stock for " + prod.name)
}
// Deduct stock
for (let item of order.items) {
const prod = DB.products.find(p => p.id === item.productId)
prod.stock -= item.quantity
}
const orderId = "ord_" + Date.now()
const newOrder = Object.assign({ id: orderId, createdAt: new Date().toISOString(), status: "pending" }, order)
DB.orders.push(newOrder)
return Promise.resolve(newOrder)
}
function apiCreateProduct(product) {
if (!validate(PRODUCT_SCHEMA, product)) return Promise.reject("Invalid product schema")
if (DB.products.find(p => p.id === product.id)) return Promise.reject("Product ID exists")
DB.products.push(product)
return Promise.resolve(product)
}
function apiUpdateProduct(product) {
const idx = DB.products.findIndex(p => p.id === product.id)
if (idx < 0) return Promise.reject("Product not found")
DB.products[idx] = product
return Promise.resolve(product)
}
function apiDeleteProduct(id) {
const idx = DB.products.findIndex(p => p.id === id)
if (idx < 0) return Promise.reject("Product not found")
DB.products.splice(idx, 1)
return Promise.resolve(true)
}
function apiAuthenticate(email, password) {
const u = DB.users.find(x => x.email === email && x.password === password)
if (!u) return Promise.reject("Invalid credentials")
// Return sanitized user object
const { password: _pw, ...san } = u
return Promise.resolve(san)
}
//////////////////////
// TDMLTK: Recommender
//////////////////////
// Simple item-based co-occurrence recommender using TDMLTK-style pipeline
const Recommender = {
// update model from order history
buildModel: function(orders) {
// co-occurrence counts
const co = {}
for (let order of orders) {
const ids = order.items.map(i => i.productId)
for (let i = 0; i < ids.length; i++) {
for (let j = 0; j < ids.length; j++) {
if (i === j) continue
const a = ids[i], b = ids[j]
co[a] = co[a] || {}
co[a][b] = (co[a][b] || 0) + 1
}
}
}
this.model = co
return co
},
recommend: function(productId, topK = 3) {
if (!this.model || !this.model[productId]) return []
const arr = Object.entries(this.model[productId])
arr.sort((a, b) => b[1] - a[1])
return arr.slice(0, topK).map(x => x[0])
},
model: {}
}
Recommender.buildModel(DB.orders)
/////////////////////////
// UI Components (HS) //
/////////////////////////
// Very light component system: render functions returning DOM nodes
// In HopeScript runtime, assume document and element creation utilities exist.
function App() {
document.title = APP_TITLE
const root = document.getElementById("app")
root.innerHTML = "" // clear
root.appendChild(Header())
root.appendChild(MainRouter())
root.appendChild(Footer())
}
// Header with search and cart indicator
function Header() {
const header = el("header", { class: "hp-header" })
header.appendChild(el("h1", { class: "hp-title" }, APP_TITLE))
// Search
const searchInput = el("input", { type: "search", placeholder: "Search products..." })
searchInput.addEventListener("keydown", (e) => {
if (e.key === "Enter") {
navigateTo("/?search=" + encodeURIComponent(searchInput.value))
}
})
header.appendChild(searchInput)
// Cart summary
const cartBtn = el("button", { class: "hp-cart-btn" }, `Cart (${loadCart().length})`)
cartBtn.addEventListener("click", () => navigateTo("/cart"))
header.appendChild(cartBtn)
// User / Auth
const user = loadUser()
const userBtn = el("button", { class: "hp-user-btn" }, user ? user.name : "Sign In")
userBtn.addEventListener("click", () => {
if (user) navigateTo("/account")
else navigateTo("/login")
})
header.appendChild(userBtn)
return header
}
// Footer
function Footer() {
const f = el("footer", { class: "hp-footer" }, "© HopePharm 2026 — Trusted online pharmacy")
return f
}
// Router (very small)
function MainRouter() {
const container = el("main", { class: "hp-main" })
const path = window.location.pathname || "/"
const q = new URLSearchParams(window.location.search)
// Simple route switch
if (path === "/" || path === "/home") {
renderHome(container, q)
} else if (path.startsWith("/product/")) {
const id = path.split("/")[2]
renderProductPage(container, id)
} else if (path === "/cart") {
renderCart(container)
} else if (path === "/checkout") {
renderCheckout(container)
} else if (path === "/login") {
renderLogin(container)
} else if (path === "/account") {
renderAccount(container)
} else if (path === "/admin") {
renderAdmin(container)
} else {
container.appendChild(el("p", {}, "Page not found"))
}
return container
}
/////////////////////////
// Page Renderers //
/////////////////////////
function renderHome(root, query) {
const qSearch = query.get("search") || ""
const category = query.get("category") || null
const section = el("section", { class: "hp-section" })
const h = el("h2", {}, "Shop Medicines & Health Products")
section.appendChild(h)
// Filters
const filters = el("div", { class: "hp-filters" })
const allCats = Array.from(new Set(DB.products.map(p => p.category)))
const catSelect = el("select")
catSelect.appendChild(el("option", { value: "" }, "All Categories"))
for (let c of allCats) {
const opt = el("option", { value: c }, c)
if (c === category) opt.selected = true
catSelect.appendChild(opt)
}
catSelect.addEventListener("change", () => {
const c = catSelect.value
const url = c ? "/?category=" + encodeURIComponent(c) : "/"
navigateTo(url)
})
filters.appendChild(catSelect)
section.appendChild(filters)
// Product grid (async fetch)
apiGetProducts({ search: qSearch, category: category ? category : undefined })
.then(list => {
const grid = el("div", { class: "hp-grid" })
for (let p of list) {
const card = el("div", { class: "hp-card" })
const img = el("img", { src: p.image, alt: p.name, class: "hp-card-img" })
card.appendChild(img)
card.appendChild(el("h3", {}, p.name))
card.appendChild(el("p", { class: "hp-price" }, formatCurrency(p.price)))
card.appendChild(el("p", { class: "hp-desc" }, p.description))
const btn = el("button", {}, "View")
btn.addEventListener("click", () => navigateTo("/product/" + p.id))
card.appendChild(btn)
grid.appendChild(card)
}
section.appendChild(grid)
})
root.appendChild(section)
}
function renderProductPage(root, productId) {
const section = el("section", { class: "hp-section" })
apiGetProductById(productId)
.then(p => {
if (!p) {
section.appendChild(el("p", {}, "Product not found"))
root.appendChild(section)
return
}
const container = el("div", { class: "hp-product" })
container.appendChild(el("img", { src: p.image, alt: p.name, class: "hp-product-img" }))
const info = el("div", { class: "hp-product-info" })
info.appendChild(el("h2", {}, p.name))
info.appendChild(el("p", { class: "hp-price" }, formatCurrency(p.price)))
info.appendChild(el("p", {}, p.description))
info.appendChild(el("p", {}, "Category: " + p.category))
if (p.requiresPrescription) info.appendChild(el("p", { class: "hp-warning" }, "Prescription required"))
info.appendChild(el("p", {}, "In stock: " + p.stock))
// Quantity + Add to cart
const qty = el("input", { type: "number", min: 1, value: 1 })
const addBtn = el("button", {}, "Add to Cart")
addBtn.addEventListener("click", () => {
const q = Math.max(1, parseInt(qty.value) || 1)
const cart = loadCart()
cart.push({ productId: p.id, quantity: q })
saveCart(cart)
showToast("Added to cart")
navigateTo("/") // refresh header cart count via full re-render
})
info.appendChild(el("div", {}, qty, addBtn))
// Prescription upload if required
if (p.requiresPrescription) {
const prescForm = el("div", { class: "hp-presc" })
prescForm.appendChild(el("label", {}, "Upload prescription (PDF/JPG): "))
const fileInput = el("input", { type: "file", accept: ".pdf,image/*" })
prescForm.appendChild(fileInput)
prescForm.appendChild(el("p", { class: "hp-note" }, "Our pharmacist will review your prescription during checkout."))
info.appendChild(prescForm)
}
container.appendChild(info)
section.appendChild(container)
// Recommendations (TDMLTK)
const recIds = Recommender.recommend(p.id, 3)
if (recIds.length > 0) {
const recSection = el("div", { class: "hp-recs" })
recSection.appendChild(el("h3", {}, "Customers also bought"))
const recGrid = el("div", { class: "hp-grid" })
for (let rid of recIds) {
const prod = DB.products.find(x => x.id === rid)
if (!prod) continue
const card = el("div", { class: "hp-card" })
card.appendChild(el("img", { src: prod.image, alt: prod.name, class: "hp-card-img" }))
card.appendChild(el("h4", {}, prod.name))
const vbtn = el("button", {}, "View")
vbtn.addEventListener("click", () => navigateTo("/product/" + prod.id))
card.appendChild(vbtn)
recGrid.appendChild(card)
}
recSection.appendChild(recGrid)
section.appendChild(recSection)
}
root.appendChild(section)
})
}
function renderCart(root) {
const section = el("section", { class: "hp-section" })
section.appendChild(el("h2", {}, "Your Cart"))
const cart = loadCart()
if (!cart.length) {
section.appendChild(el("p", {}, "Your cart is empty."))
section.appendChild(el("button", {}, "Continue shopping").addEventListener("click", () => navigateTo("/")))
root.appendChild(section)
return
}
const table = el("table", { class: "hp-cart-table" })
for (let item of cart) {
const prod = DB.products.find(p => p.id === item.productId)
if (!prod) continue
const row = el("tr")
row.appendChild(el("td", {}, prod.name))
row.appendChild(el("td", {}, formatCurrency(prod.price)))
row.appendChild(el("td", {}, "x" + item.quantity))
row.appendChild(el("td", {}, formatCurrency(prod.price * item.quantity)))
table.appendChild(row)
}
section.appendChild(table)
const checkoutBtn = el("button", {}, "Proceed to Checkout")
checkoutBtn.addEventListener("click", () => navigateTo("/checkout"))
section.appendChild(checkoutBtn)
root.appendChild(section)
}
function renderCheckout(root) {
const section = el("section", { class: "hp-section" })
section.appendChild(el("h2", {}, "Checkout"))
const cart = loadCart()
if (!cart.length) {
section.appendChild(el("p", {}, "Your cart is empty."))
root.appendChild(section)
return
}
// Order summary
const summary = el("div", { class: "hp-order-summary" })
let total = 0
for (let item of cart) {
const prod = DB.products.find(p => p.id === item.productId)
if (!prod) continue
summary.appendChild(el("p", {}, `${prod.name} x${item.quantity} — ${formatCurrency(prod.price * item.quantity)}`))
total += prod.price * item.quantity
}
summary.appendChild(el("h3", {}, "Total: " + formatCurrency(total)))
section.appendChild(summary)
// Shipping / Payment stub
const form = el("form")
form.appendChild(el("label", {}, "Full Name"))
const nameInput = el("input", { type: "text", required: true })
form.appendChild(nameInput)
form.appendChild(el("label", {}, "Shipping Address"))
const addrInput = el("textarea", { required: true })
form.appendChild(addrInput)
form.appendChild(el("label", {}, "Prescription file (if any medicines require it)"))
const prescInput = el("input", { type: "file", accept: ".pdf,image/*" })
form.appendChild(prescInput)
const payBtn = el("button", { type: "submit" }, "Place Order (Pay)")
form.addEventListener("submit", (evt) => {
evt.preventDefault()
const order = {
user: loadUser(),
items: cart.map(i => ({ productId: i.productId, quantity: i.quantity })),
shipping: { name: nameInput.value, address: addrInput.value },
total: total
// payment flow would be integrated here
}
apiCreateOrder(order)
.then(created => {
// clear cart
saveCart([])
// update recommender model
Recommender.buildModel(DB.orders)
showToast("Order placed: " + created.id)
navigateTo("/home")
})
.catch(err => showToast("Checkout error: " + err))
})
section.appendChild(form)
root.appendChild(section)
}
function renderLogin(root) {
const section = el("section", { class: "hp-section" })
section.appendChild(el("h2", {}, "Sign In"))
const form = el("form")
form.appendChild(el("label", {}, "Email"))
const email = el("input", { type: "email", required: true })
form.appendChild(email)
form.appendChild(el("label", {}, "Password"))
const password = el("input", { type: "password", required: true })
form.appendChild(password)
const submit = el("button", { type: "submit" }, "Sign In")
form.addEventListener("submit", (evt) => {
evt.preventDefault()
apiAuthenticate(email.value, password.value)
.then(user => {
saveUser(user)
showToast("Signed in as " + user.name)
navigateTo("/account")
})
.catch(err => showToast("Auth error: " + err))
})
form.appendChild(submit)
section.appendChild(form)
root.appendChild(section)
}
function renderAccount(root) {
const user = loadUser()
const section = el("section", { class: "hp-section" })
if (!user) {
section.appendChild(el("p", {}, "Not signed in."))
section.appendChild(el("button", {}, "Sign In").addEventListener("click", () => navigateTo("/login")))
root.appendChild(section)
return
}
section.appendChild(el("h2", {}, "Account"))
section.appendChild(el("p", {}, "Name: " + user.name))
section.appendChild(el("p", {}, "Email: " + user.email))
const signout = el("button", {}, "Sign Out")
signout.addEventListener("click", () => {
localStorage.removeItem(STORAGE_USER_KEY)
showToast("Signed out")
navigateTo("/")
})
section.appendChild(signout)
root.appendChild(section)
}
function renderAdmin(root) {
const user = loadUser()
if (!user || user.role !== "admin") {
root.appendChild(el("p", {}, "Admin access required."))
return
}
const section = el("section", { class: "hp-section" })
section.appendChild(el("h2", {}, "Admin Dashboard"))
section.appendChild(el("h3", {}, "Products"))
const prodList = el("div", { class: "hp-admin-list" })
for (let p of DB.products) {
const row = el("div", { class: "hp-admin-row" })
row.appendChild(el("span", {}, p.name))
const edit = el("button", {}, "Edit")
edit.addEventListener("click", () => {
const newName = prompt("New name", p.name)
if (newName) {
p.name = newName
apiUpdateProduct(p).then(() => {
showToast("Product updated")
navigateTo("/admin")
})
}
})
const del = el("button", {}, "Delete")
del.addEventListener("click", () => {
if (confirm("Delete " + p.name + "?")) {
apiDeleteProduct(p.id).then(() => {
showToast("Deleted")
navigateTo("/admin")
})
}
})
row.appendChild(edit); row.appendChild(del)
prodList.appendChild(row)
}
section.appendChild(prodList)
const createBtn = el("button", {}, "Create New Product")
createBtn.addEventListener("click", () => {
const id = "p" + Math.floor(Math.random() * 10000)
const name = prompt("Product name")
if (!name) return
const price = parseFloat(prompt("Price", "0"))
const category = prompt("Category", "General")
const p = { id, name, description: "", price: price || 0, image: "", category, requiresPrescription: false, stock: 0 }
apiCreateProduct(p).then(() => {
showToast("Created")
navigateTo("/admin")
})
})
section.appendChild(createBtn)
root.appendChild(section)
}
//////////////////////
// Small UI Helpers //
//////////////////////
// create element helper (simple)
function el(tag, attrs = {}, ...children) {
const node = document.createElement(tag)
for (let k in attrs) {
if (k === "class") node.className = attrs[k]
else if (k === "html") node.innerHTML = attrs[k]
else node.setAttribute(k, attrs[k])
}
for (let ch of children) {
if (!ch) continue
if (typeof ch === "string") node.appendChild(document.createTextNode(ch))
else node.appendChild(ch)
}
return node
}
function navigateTo(path) {
history.pushState({}, "", path)
// re-render entire app for simplicity
App()
}
window.addEventListener("popstate", () => App())
function showToast(msg) {
const t = el("div", { class: "hp-toast" }, msg)
document.body.appendChild(t)
setTimeout(() => t.classList.add("show"), 20)
setTimeout(() => t.classList.remove("show"), 4000)
setTimeout(() => t.remove(), 4500)
}
//////////////////////
// Initial Boot //
//////////////////////
// Minimal CSS injection for presentation
const css = `
.hp-header{display:flex;gap:12px;align-items:center;padding:12px;background:#0b5; color:#003}
.hp-title{margin:0}
.hp-main{padding:16px}
.hp-section{margin-bottom:24px}
.hp-grid{display:flex;gap:12px;flex-wrap:wrap}
.hp-card{border:1px solid #ddd;padding:12px;width:200px}
.hp-card-img{width:100%;height:120px;object-fit:contain}
.hp-product{display:flex;gap:16px}
.hp-product-img{width:200px;height:200px;object-fit:contain}
.hp-recs{margin-top:16px}
.hp-footer{padding:12px;text-align:center;background:#f3f3f3}
.hp-cart-btn, .hp-user-btn{padding:8px}
.hp-toast{position:fixed;bottom:20px;right:20px;background:#222;color:#fff;padding:12px;border-radius:6px;opacity:0;transition:all .3s}
.hp-toast.show{opacity:1;transform:translateY(-6px)}
.hp-warning{color:#b00;font-weight:bold}
.hp-admin-row{display:flex;gap:8px;align-items:center}
`
const style = document.createElement("style")
style.appendChild(document.createTextNode(css))
document.head.appendChild(style)
// Ensure root exists
if (!document.getElementById("app")) {
const rootDiv = document.createElement("div")
rootDiv.id = "app"
document.body.appendChild(rootDiv)
}
// Boot the app
App()
// Expose API for testing in console (dev convenience)
window.HopePharmAPI = {
db: DB,
apiGetProducts,
apiGetProductById,
apiCreateOrder,
apiCreateProduct,
apiUpdateProduct,
apiDeleteProduct,
Recommender
}