Das Dreamcodes OmniFood OS definiert digitales Bestellen neu. Als leistungsstarke PHP Singel Application bietet es dir alles, was ein moderner Gastronomiebetrieb benötigt, von der sicheren Paypal Bezahlung bis zur Live Verfolgung der Bestellung.
- Integrierte PayPal Zahlung: Schließen Sie Verkäufe sofort ab. Die nahtlose Einbindung des PayPal SDK sorgt für Vertrauen und eine reibungslose User Experience.
- Passwortgeschützter Admin Bereich: Schützen Sie Ihre Geschäftsdaten. Die neue Admin Konsole ist durch eine Passwort Abfrage und Session Validierung gesichert.
- Echtzeit Tracking 2.0: Nach der Bezahlung verfolgt der Kunde seinen Status live. Das System kommuniziert ohne Neuladen direkt mit Ihrer Küche.
- Plug and Play Architektur: Dank SQLite Technologie ist das System sofort einsatzbereit. Datei hochladen, Passwort festlegen und der Verkauf beginnt.
- Premium Design: Ein modernes, responsives Interface im Glassmorphism Look, das auf jedem Endgerät, vom iPhone bis zum Desktop, überzeugt.
<?php
session_start();
$admin_password = "admin123"; // ÄNDERE DIES
$db_file = 'food_order.db';
$db = new SQLite3($db_file);
$db->exec("CREATE TABLE IF NOT EXISTS products (id INTEGER PRIMARY KEY, name TEXT, price REAL, img TEXT, desc TEXT)");
$db->exec("CREATE TABLE IF NOT EXISTS orders (id INTEGER PRIMARY KEY, total REAL, customer TEXT, address TEXT, status TEXT, payment_id TEXT, created_at DATETIME)");
if ($db->querySingle("SELECT count(*) FROM products") == 0) {
$db->exec("INSERT INTO products (name, price, img, desc) VALUES
('Cyber Steakhouse', 14.50, '🍔', 'Gereiftes Rindfleisch & Trüffel-Mayo.'),
('Pizza Truffle Dream', 16.20, '🍕', 'Frischer Trüffel & Fior di Latte.')");
}
if (isset($_GET['action'])) {
header('Content-Type: application/json');
if ($_GET['action'] == 'admin_login') {
$input = json_decode(file_get_contents('php://input'), true);
if ($input['password'] === $admin_password) {
$_SESSION['admin_auth'] = true;
echo json_encode(['success' => true]);
} else {
echo json_encode(['success' => false]);
}
exit;
}
if ($_GET['action'] == 'get_products') {
$res = $db->query("SELECT * FROM products");
$data = [];
while($row = $res->fetchArray(SQLITE3_ASSOC)) $data[] = $row;
echo json_encode($data);
exit;
}
if ($_GET['action'] == 'place_order') {
$input = json_decode(file_get_contents('php://input'), true);
$stmt = $db->prepare("INSERT INTO orders (total, customer, address, status, payment_id, created_at) VALUES (:t, :c, :a, 'Bezahlt', :pid, DATETIME('now', 'localtime'))");
$stmt->bindValue(':t', $input['total'], SQLITE3_FLOAT);
$stmt->bindValue(':c', $input['name'], SQLITE3_TEXT);
$stmt->bindValue(':a', $input['address'], SQLITE3_TEXT);
$stmt->bindValue(':pid', $input['payment_id'], SQLITE3_TEXT);
$stmt->execute();
echo json_encode(['success' => true, 'order_id' => $db->lastInsertRowID()]);
exit;
}
if ($_GET['action'] == 'get_status') {
$id = (int)$_GET['id'];
$res = $db->querySingle("SELECT status FROM orders WHERE id = $id", true);
echo json_encode($res);
exit;
}
if (!isset($_SESSION['admin_auth']) || $_SESSION['admin_auth'] !== true) {
echo json_encode(['error' => 'Unauthorized']); exit;
}
if ($_GET['action'] == 'admin_get_orders') {
$res = $db->query("SELECT * FROM orders ORDER BY id DESC LIMIT 50");
$orders = [];
while($row = $res->fetchArray(SQLITE3_ASSOC)) $orders[] = $row;
echo json_encode($orders);
exit;
}
if ($_GET['action'] == 'admin_update_status') {
$input = json_decode(file_get_contents('php://input'), true);
$stmt = $db->prepare("UPDATE orders SET status = :s WHERE id = :id");
$stmt->bindValue(':s', $input['status'], SQLITE3_TEXT);
$stmt->bindValue(':id', $input['id'], SQLITE3_INTEGER);
$stmt->execute();
echo json_encode(['success' => true]);
exit;
}
}
?>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>OmniFood OS | Premium Order</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;600;800&display=swap" rel="stylesheet">
<script src="https://www.paypal.com/sdk/js?client-id=test¤cy=EUR"></script>
<style>
body { font-family: 'Plus Jakarta Sans', sans-serif; background: #020617; color: #f1f5f9; }
.glass { background: rgba(15, 23, 42, 0.75); backdrop-filter: blur(20px); border: 1px solid rgba(255,255,255,0.08); }
.tracking-pulse { animation: pulse 2s infinite; }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: .4; } }
.custom-scrollbar::-webkit-scrollbar { width: 4px; }
.custom-scrollbar::-webkit-scrollbar-thumb { background: #1e293b; border-radius: 10px; }
</style>
</head>
<body class="min-h-screen">
<header class="sticky top-0 z-50 glass px-6 py-4 flex justify-between items-center">
<div class="flex items-center gap-3">
<div class="w-10 h-10 bg-gradient-to-tr from-cyan-500 to-blue-600 rounded-xl flex items-center justify-center font-bold">O</div>
<h1 class="text-xl font-800 tracking-tighter uppercase">OmniFood <span class="text-cyan-500 italic text-sm">OS</span></h1>
</div>
<div class="flex items-center gap-6">
<button onclick="checkAdminAuth()" class="text-[10px] uppercase text-slate-500 font-bold hover:text-white transition-colors">Admin</button>
<div class="cursor-pointer relative" onclick="toggleCart()">
<span id="cart-count" class="absolute -top-2 -right-2 bg-cyan-500 text-[10px] w-5 h-5 flex items-center justify-center rounded-full font-bold">0</span>
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-slate-300" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z" /></svg>
</div>
</div>
</header>
<div id="tracking-bar" class="hidden glass mx-6 mt-6 p-5 rounded-2xl flex justify-between items-center border border-cyan-500/20">
<div class="flex items-center gap-4">
<div class="w-2 h-2 bg-cyan-500 rounded-full tracking-pulse"></div>
<span class="text-[10px] uppercase font-bold tracking-[0.2em]">Bestellung #<span id="track-id">0</span>: <span id="track-status" class="text-cyan-400 italic font-800">Prüfung...</span></span>
</div>
<button onclick="closeTracking()" class="text-slate-600 text-xs">✕</button>
</div>
<main class="max-w-7xl mx-auto px-6 py-12 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6" id="products"></main>
<div id="cart-sidebar" class="fixed inset-y-0 right-0 w-full md:w-[450px] glass z-[60] translate-x-full transition-transform duration-500 p-8 flex flex-col shadow-2xl">
<div class="flex justify-between items-center mb-8 pb-4 border-b border-slate-800">
<h3 class="text-2xl font-bold italic tracking-tighter uppercase">Kasse</h3>
<button onclick="toggleCart()" class="text-slate-500 hover:text-white">✕</button>
</div>
<div id="cart-items" class="flex-1 overflow-y-auto custom-scrollbar space-y-4 mb-6"></div>
<div class="mt-auto border-t border-slate-800 pt-6">
<div class="flex justify-between text-2xl font-bold mb-6">
<span class="text-[10px] uppercase tracking-widest text-slate-500 pt-3 font-800">Gesamt</span>
<span class="text-cyan-400" id="cart-total">0.00 €</span>
</div>
<div class="space-y-3 mb-6">
<input type="text" id="cust-name" placeholder="Dein Name" class="w-full bg-slate-900/50 border border-slate-800 rounded-xl px-4 py-3 focus:border-cyan-500 outline-none transition-all text-sm">
<input type="text" id="cust-address" placeholder="Tischnummer oder Adresse" class="w-full bg-slate-900/50 border border-slate-800 rounded-xl px-4 py-3 focus:border-cyan-500 outline-none transition-all text-sm">
</div>
<div id="paypal-button-container"></div>
</div>
</div>
<div id="admin-panel" class="fixed inset-0 z-[70] hidden bg-slate-950/98 p-6 flex flex-col items-center">
<div class="w-full max-w-5xl glass rounded-3xl p-8 h-full flex flex-col overflow-hidden shadow-2xl">
<div class="flex justify-between items-center mb-10">
<h2 class="text-3xl font-800 tracking-tighter uppercase italic">Bestellungen <span class="text-cyan-500 text-sm tracking-widest">LIVE</span></h2>
<button onclick="closeAdmin()" class="bg-slate-800 px-5 py-2 rounded-xl text-xs font-bold uppercase hover:bg-slate-700 transition-all">Schließen</button>
</div>
<div id="admin-orders" class="flex-1 overflow-y-auto custom-scrollbar space-y-4 pr-2"></div>
</div>
</div>
<footer class="mt-20 py-16 border-t border-slate-900 px-6">
<div class="max-w-7xl mx-auto flex flex-col md:flex-row justify-between items-center gap-10">
<div class="text-center md:text-left">
<p class="text-[10px] text-slate-600 uppercase font-bold tracking-[0.3em] mb-2">© 2026 OmniFood Architecture</p>
<p class="text-slate-800 text-[10px] font-bold italic">High-Performance Dining Solution</p>
</div>
<a href="https://www.dreamcodes.net" target="_blank" class="group flex flex-col items-end">
<span class="text-[9px] text-slate-600 uppercase font-bold tracking-widest mb-1">Official Provider</span>
<div class="flex items-center gap-3">
<span class="text-2xl font-800 tracking-tighter text-slate-400 group-hover:text-white transition-all">DREAMCODES</span>
<div class="w-8 h-8 border border-slate-800 rounded-full flex items-center justify-center group-hover:border-cyan-500 group-hover:rotate-12 transition-all">
<div class="w-1.5 h-1.5 bg-cyan-500 rounded-full shadow-[0_0_10px_#06b6d4]"></div>
</div>
</div>
</a>
</div>
</footer>
<script>
let cart = [];
let prods = [];
let trackingId = null;
async function init() {
const res = await fetch('?action=get_products');
prods = await res.json();
document.getElementById('products').innerHTML = prods.map(p => `
<div class="glass p-8 rounded-[2rem] flex flex-col border border-transparent hover:border-cyan-500/20 transition-all duration-500 group">
<div class="text-6xl mb-8 transform transition-transform group-hover:scale-110 group-hover:-rotate-3">${p.img}</div>
<h3 class="text-xl font-bold mb-2 uppercase tracking-tight">${p.name}</h3>
<p class="text-xs text-slate-500 mb-8 italic leading-relaxed">${p.desc}</p>
<div class="mt-auto flex justify-between items-center">
<span class="font-800 text-2xl tracking-tighter">${p.price.toFixed(2)} €</span>
<button onclick="add(${p.id})" class="bg-slate-800 hover:bg-cyan-600 p-4 rounded-2xl transition-all active:scale-90 shadow-lg">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M12 4v16m8-8H4" /></svg>
</button>
</div>
</div>
`).join('');
renderPayPal();
}
function toggleCart() { document.getElementById('cart-sidebar').classList.toggle('translate-x-full'); }
function add(id) {
cart.push(prods.find(p => p.id === id));
updateCart();
document.getElementById('cart-sidebar').classList.remove('translate-x-full');
}
function updateCart() {
const list = document.getElementById('cart-items');
document.getElementById('cart-count').innerText = cart.length;
if(cart.length === 0) { list.innerHTML = '<div class="text-center py-20 text-slate-800 uppercase font-bold text-[10px] tracking-widest italic">Warenkorb ist leer</div>'; return; }
let total = 0;
list.innerHTML = cart.map((item, i) => {
total += item.price;
return `<div class="bg-slate-900/40 p-5 rounded-2xl flex justify-between items-center border border-slate-800/50 group">
<span class="text-sm font-bold tracking-tight uppercase">${item.name}</span>
<button onclick="cart.splice(${i},1);updateCart();" class="text-slate-600 hover:text-red-500 transition-colors">✕</button>
</div>`;
}).join('');
document.getElementById('cart-total').innerText = total.toFixed(2) + " €";
}
function renderPayPal() {
paypal.Buttons({
createOrder: function(data, actions) {
const total = cart.reduce((a, b) => a + b.price, 0).toFixed(2);
if(total <= 0 || !document.getElementById('cust-name').value || !document.getElementById('cust-address').value) {
alert("Bitte Name und Adresse/Tisch eingeben!");
return;
}
return actions.order.create({
purchase_units: [{
description: "Bestellung bei OmniFood",
amount: { currency_code: 'EUR', value: total }
}]
});
},
onApprove: function(data, actions) {
return actions.order.capture().then(function(details) {
const name = document.getElementById('cust-name').value;
const address = document.getElementById('cust-address').value;
const total = cart.reduce((a, b) => a + b.price, 0);
fetch('?action=place_order', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({ name, address, total, payment_id: details.id })
}).then(r => r.json()).then(res => {
trackingId = res.order_id;
cart = []; updateCart(); toggleCart(); startTracking();
});
});
}
}).render('#paypal-button-container');
}
function startTracking() {
document.getElementById('tracking-bar').classList.remove('hidden');
document.getElementById('track-id').innerText = trackingId;
const tracker = setInterval(async () => {
if(!trackingId) { clearInterval(tracker); return; }
const r = await fetch(`?action=get_status&id=${trackingId}`);
const d = await r.json();
document.getElementById('track-status').innerText = d.status;
}, 5000);
}
async function checkAdminAuth() {
const pass = prompt("Passwort:");
if (!pass) return;
const res = await fetch('?action=admin_login', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({ password: pass })
});
const data = await res.json();
if (data.success) openAdmin(); else alert("Falsch!");
}
async function openAdmin() {
document.getElementById('admin-panel').classList.remove('hidden');
const res = await fetch('?action=admin_get_orders');
const orders = await res.json();
document.getElementById('admin-orders').innerHTML = orders.map(o => `
<div class="glass p-6 rounded-2xl flex justify-between items-center gap-6 border-l-4 border-cyan-500">
<div class="flex-1">
<p class="font-800 text-cyan-400 uppercase tracking-widest text-xs mb-1">#${o.id} - ${o.customer}</p>
<p class="text-white text-sm font-bold mb-1">${o.address}</p>
<p class="text-[10px] text-slate-500 uppercase">${o.created_at} | Pay-ID: ${o.payment_id}</p>
</div>
<div class="flex flex-col items-end gap-3">
<span class="text-xl font-800 tracking-tighter">${o.total.toFixed(2)} €</span>
<select onchange="updateStatus(${o.id}, this.value)" class="bg-slate-900 text-[10px] rounded-lg p-2 border-none outline-none font-bold uppercase tracking-widest cursor-pointer">
<option ${o.status == 'Bezahlt' ? 'selected' : ''}>Bezahlt</option>
<option ${o.status == 'Wird zubereitet' ? 'selected' : ''}>Zubereitung</option>
<option ${o.status == 'Unterwegs' ? 'selected' : ''}>Unterwegs</option>
<option ${o.status == 'Geliefert' ? 'selected' : ''}>Geliefert</option>
</select>
</div>
</div>
`).join('');
}
async function updateStatus(id, status) {
await fetch('?action=admin_update_status', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({ id, status })
});
}
function closeAdmin() { document.getElementById('admin-panel').classList.add('hidden'); }
function closeTracking() { trackingId = null; document.getElementById('tracking-bar').classList.add('hidden'); }
window.onload = init;
</script>
</body>
</html>
