Compare commits

...

2 Commits

Author SHA1 Message Date
Flatlogic Bot
b2397c87b9 Masakan Nusantara 2026-02-17 17:13:31 +00:00
Flatlogic Bot
5336cb2bd9 masakan nusantara Ibu tini 2026-02-17 17:10:18 +00:00
17 changed files with 1592 additions and 146 deletions

6
admin/footer.php Normal file
View File

@ -0,0 +1,6 @@
</main>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

58
admin/header.php Normal file
View File

@ -0,0 +1,58 @@
<?php
session_start();
if (!isset($_SESSION['admin_logged_in'])) {
header('Location: login.php');
exit;
}
require_once __DIR__ . '/../includes/koneksi.php';
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Panel Admin - Masakan Nusantara Ibu Tini</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/combine/npm/font-awesome@4.7.0/css/font-awesome.min.css">
<style>
:root { --primary-color: #D97706; --secondary-color: #065F46; }
.navbar-brand { font-weight: bold; color: var(--primary-color) !important; }
.sidebar { min-height: calc(100vh - 56px); background: #343a40; color: white; }
.sidebar a { color: rgba(255,255,255,0.8); text-decoration: none; padding: 10px 20px; display: block; border-bottom: 1px solid rgba(255,255,255,0.1); }
.sidebar a:hover, .sidebar a.active { background: rgba(255,255,255,0.1); color: white; }
.main-content { padding: 20px; background: #f8f9fa; min-height: calc(100vh - 56px); }
.card-stat { border: none; border-radius: 10px; box-shadow: 0 4px 6px rgba(0,0,0,0.05); }
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-white border-bottom sticky-top">
<div class="container-fluid">
<a class="navbar-brand" href="index.php">Admin Ibu Tini</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<span class="nav-link">Halo, <?php echo htmlspecialchars($_SESSION['admin_name']); ?></span>
</li>
<li class="nav-item">
<a class="nav-link text-danger" href="logout.php">Keluar</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container-fluid">
<div class="row">
<nav class="col-md-3 col-lg-2 d-md-block sidebar collapse p-0">
<div class="position-sticky">
<a href="index.php" class="<?php echo basename($_SERVER['PHP_SELF']) == 'index.php' ? 'active' : ''; ?>">Dashboard</a>
<a href="pesanan.php" class="<?php echo basename($_SERVER['PHP_SELF']) == 'pesanan.php' ? 'active' : ''; ?>">Daftar Pesanan</a>
<a href="menu.php" class="<?php echo basename($_SERVER['PHP_SELF']) == 'menu.php' ? 'active' : ''; ?>">Kelola Menu</a>
<a href="kategori.php" class="<?php echo basename($_SERVER['PHP_SELF']) == 'kategori.php' ? 'active' : ''; ?>">Kelola Kategori</a>
<a href="profil.php" class="<?php echo basename($_SERVER['PHP_SELF']) == 'profil.php' ? 'active' : ''; ?>">Profil Usaha</a>
</div>
</nav>
<main class="col-md-9 ms-sm-auto col-lg-10 main-content">

139
admin/index.php Normal file
View File

@ -0,0 +1,139 @@
<?php
require_once 'header.php';
// Stats
$total_menu = fetch_one("SELECT COUNT(*) as count FROM menu")['count'];
$total_kategori = fetch_one("SELECT COUNT(*) as count FROM kategori_menu")['count'];
$total_pesanan = fetch_one("SELECT COUNT(*) as count FROM pesanan")['count'];
$pesanan_baru = fetch_one("SELECT COUNT(*) as count FROM pesanan WHERE status = 'Baru'")['count'];
$recent_orders = fetch_all("SELECT * FROM pesanan ORDER BY id DESC LIMIT 5");
?>
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">Dashboard</h1>
</div>
<div class="row">
<div class="col-md-3 mb-4">
<div class="card card-stat bg-primary text-white p-3">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="mb-0">Total Menu</h6>
<h2 class="mb-0"><?php echo $total_menu; ?></h2>
</div>
<div class="h1 mb-0 opacity-50">🍱</div>
</div>
</div>
</div>
<div class="col-md-3 mb-4">
<div class="card card-stat bg-success text-white p-3">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="mb-0">Kategori</h6>
<h2 class="mb-0"><?php echo $total_kategori; ?></h2>
</div>
<div class="h1 mb-0 opacity-50">📁</div>
</div>
</div>
</div>
<div class="col-md-3 mb-4">
<div class="card card-stat bg-info text-white p-3">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="mb-0">Total Pesanan</h6>
<h2 class="mb-0"><?php echo $total_pesanan; ?></h2>
</div>
<div class="h1 mb-0 opacity-50">🛒</div>
</div>
</div>
</div>
<div class="col-md-3 mb-4">
<div class="card card-stat bg-warning text-white p-3">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="mb-0">Pesanan Baru</h6>
<h2 class="mb-0"><?php echo $pesanan_baru; ?></h2>
</div>
<div class="h1 mb-0 opacity-50">🔔</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-8">
<div class="card shadow-sm">
<div class="card-header bg-white d-flex justify-content-between align-items-center">
<h5 class="mb-0">Pesanan Terbaru</h5>
<a href="pesanan.php" class="btn btn-sm btn-outline-primary">Lihat Semua</a>
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover mb-0">
<thead class="table-light">
<tr>
<th>ID</th>
<th>Pelanggan</th>
<th>WA</th>
<th>Status</th>
<th>Waktu</th>
</tr>
</thead>
<tbody>
<?php if (count($recent_orders) > 0): ?>
<?php foreach ($recent_orders as $row): ?>
<tr>
<td>#<?php echo $row['id']; ?></td>
<td><?php echo htmlspecialchars($row['nama_pelanggan']); ?></td>
<td><?php echo htmlspecialchars($row['whatsapp']); ?></td>
<td>
<?php
$badge = [
'Baru' => 'bg-info',
'Proses' => 'bg-warning',
'Selesai' => 'bg-success',
'Batal' => 'bg-danger'
];
?>
<span class="badge <?php echo $badge[$row['status']] ?? 'bg-secondary'; ?>">
<?php echo $row['status']; ?>
</span>
</td>
<td class="small"><?php echo date('d/m/y H:i', strtotime($row['created_at'])); ?></td>
</tr>
<?php endforeach; ?>
<?php else: ?>
<tr>
<td colspan="5" class="text-center py-4">Belum ada pesanan masuk.</td>
</tr>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card shadow-sm">
<div class="card-header bg-white">
<h5 class="mb-0">Aksi Cepat</h5>
</div>
<div class="card-body">
<div class="d-grid gap-2">
<a href="menu.php?action=tambah" class="btn btn-outline-primary text-start">
<i class="fa fa-plus me-2"></i> Tambah Menu Baru
</a>
<a href="kategori.php?action=tambah" class="btn btn-outline-primary text-start">
<i class="fa fa-plus me-2"></i> Tambah Kategori
</a>
<a href="profil.php" class="btn btn-outline-secondary text-start">
<i class="fa fa-edit me-2"></i> Update Profil Usaha
</a>
</div>
</div>
</div>
</div>
</div>
<?php require_once 'footer.php'; ?>

146
admin/kategori.php Normal file
View File

@ -0,0 +1,146 @@
<?php
require_once 'header.php';
$action = $_GET['action'] ?? 'tampil';
$id = $_GET['id'] ?? null;
// Handle Delete
if ($action === 'hapus' && $id) {
// Check if category is used in menu
$check = fetch_one("SELECT COUNT(*) as total FROM menu WHERE kategori_id = ?", [$id]);
if ($check['total'] > 0) {
header('Location: kategori.php?msg=Kategori tidak bisa dihapus karena masih digunakan di menu&type=danger');
exit;
}
$stmt = db()->prepare("DELETE FROM kategori_menu WHERE id = ?");
$stmt->execute([$id]);
header('Location: kategori.php?msg=Kategori berhasil dihapus');
exit;
}
// Handle Form Submit (Add/Edit)
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$nama_kategori = $_POST['nama_kategori'];
$deskripsi = $_POST['deskripsi'];
$urutan = $_POST['urutan'] ?? 0;
$status = isset($_POST['status']) ? 1 : 0;
// Simple slug generator
$slug = strtolower(trim(preg_replace('/[^A-Za-z0-9-]+/', '-', $nama_kategori)));
if ($id) {
// Edit
$stmt = db()->prepare("UPDATE kategori_menu SET nama_kategori=?, slug=?, deskripsi=?, urutan=?, status=? WHERE id=?");
$stmt->execute([$nama_kategori, $slug, $deskripsi, $urutan, $status, $id]);
$msg = "Kategori berhasil diperbarui";
} else {
// Add
$stmt = db()->prepare("INSERT INTO kategori_menu (nama_kategori, slug, deskripsi, urutan, status) VALUES (?, ?, ?, ?, ?)");
$stmt->execute([$nama_kategori, $slug, $deskripsi, $urutan, $status]);
$msg = "Kategori berhasil ditambahkan";
}
header('Location: kategori.php?msg=' . $msg);
exit;
}
// Fetch data for form
$edit_data = null;
if (($action === 'edit' || $action === 'tambah') && $id) {
$edit_data = fetch_one("SELECT * FROM kategori_menu WHERE id = ?", [$id]);
}
$kategori_list = fetch_all("SELECT * FROM kategori_menu ORDER BY urutan ASC, nama_kategori ASC");
?>
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">Kelola Kategori</h1>
<?php if ($action === 'tampil'): ?>
<a href="kategori.php?action=tambah" class="btn btn-primary">Tambah Kategori Baru</a>
<?php else: ?>
<a href="kategori.php" class="btn btn-outline-secondary">Kembali ke Daftar</a>
<?php endif; ?>
</div>
<?php if (isset($_GET['msg'])): ?>
<div class="alert alert-<?php echo $_GET['type'] ?? 'success'; ?>"><?php echo htmlspecialchars($_GET['msg']); ?></div>
<?php endif; ?>
<?php if ($action === 'tambah' || $action === 'edit'): ?>
<div class="card shadow-sm">
<div class="card-body">
<h5 class="card-title mb-4"><?php echo $id ? 'Edit Kategori' : 'Tambah Kategori Baru'; ?></h5>
<form method="POST">
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label">Nama Kategori</label>
<input type="text" name="nama_kategori" class="form-control" value="<?php echo $edit_data['nama_kategori'] ?? ''; ?>" required>
</div>
<div class="col-md-3 mb-3">
<label class="form-label">Urutan</label>
<input type="number" name="urutan" class="form-control" value="<?php echo $edit_data['urutan'] ?? '0'; ?>">
</div>
<div class="col-md-3 mb-3 d-flex align-items-end">
<div class="form-check mb-2">
<input class="form-check-input" type="checkbox" name="status" id="status" <?php echo (!isset($edit_data['status']) || $edit_data['status']) ? 'checked' : ''; ?>>
<label class="form-check-label" for="status">
Aktif
</label>
</div>
</div>
<div class="col-md-12 mb-3">
<label class="form-label">Deskripsi</label>
<textarea name="deskripsi" class="form-control" rows="3"><?php echo $edit_data['deskripsi'] ?? ''; ?></textarea>
</div>
</div>
<button type="submit" class="btn btn-primary px-5">Simpan Kategori</button>
</form>
</div>
</div>
<?php else: ?>
<div class="card shadow-sm">
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover mb-0">
<thead class="table-light">
<tr>
<th>Urutan</th>
<th>Nama Kategori</th>
<th>Slug</th>
<th>Status</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
<?php foreach ($kategori_list as $row): ?>
<tr>
<td><?php echo $row['urutan']; ?></td>
<td><?php echo htmlspecialchars($row['nama_kategori']); ?></td>
<td><code><?php echo htmlspecialchars($row['slug']); ?></code></td>
<td>
<?php if ($row['status']): ?>
<span class="badge bg-success">Aktif</span>
<?php else: ?>
<span class="badge bg-secondary">Non-aktif</span>
<?php endif; ?>
</td>
<td>
<a href="kategori.php?action=edit&id=<?php echo $row['id']; ?>" class="btn btn-sm btn-outline-info">Edit</a>
<a href="kategori.php?action=hapus&id=<?php echo $row['id']; ?>" class="btn btn-sm btn-outline-danger" onclick="return confirm('Hapus kategori ini?')">Hapus</a>
</td>
</tr>
<?php endforeach; ?>
<?php if (empty($kategori_list)): ?>
<tr>
<td colspan="5" class="text-center py-4 text-muted">Belum ada kategori.</td>
</tr>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
<?php endif; ?>
<?php require_once 'footer.php'; ?>

68
admin/login.php Normal file
View File

@ -0,0 +1,68 @@
<?php
session_start();
require_once __DIR__ . '/../includes/koneksi.php';
if (isset($_SESSION['admin_logged_in'])) {
header('Location: index.php');
exit;
}
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';
if ($username && $password) {
$admin = fetch_one("SELECT * FROM admins WHERE username = ?", [$username]);
if ($admin && password_verify($password, $admin['password'])) {
$_SESSION['admin_logged_in'] = true;
$_SESSION['admin_id'] = $admin['id'];
$_SESSION['admin_name'] = $admin['nama_lengkap'];
header('Location: index.php');
exit;
} else {
$error = 'Username atau password salah.';
}
} else {
$error = 'Silakan isi username dan password.';
}
}
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login Admin - Masakan Nusantara Ibu Tini</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body { background-color: #f8f9fa; height: 100vh; display: flex; align-items: center; justify-content: center; }
.login-card { width: 100%; max-width: 400px; padding: 2rem; border-radius: 1rem; box-shadow: 0 0.5rem 1rem rgba(0,0,0,0.1); background: white; }
.btn-primary { background-color: #D97706; border-color: #D97706; }
.btn-primary:hover { background-color: #B45309; border-color: #B45309; }
</style>
</head>
<body>
<div class="login-card">
<h3 class="text-center mb-4">Admin Login</h3>
<?php if ($error): ?>
<div class="alert alert-danger"><?php echo $error; ?></div>
<?php endif; ?>
<form method="POST">
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" name="username" id="username" class="form-control" required autofocus>
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" name="password" id="password" class="form-control" required>
</div>
<button type="submit" class="btn btn-primary w-100 py-2">Login</button>
</form>
<div class="text-center mt-3">
<a href="../index.php" class="text-muted text-decoration-none small">&larr; Kembali ke Situs</a>
</div>
</div>
</body>
</html>

5
admin/logout.php Normal file
View File

@ -0,0 +1,5 @@
<?php
session_start();
session_destroy();
header('Location: login.php');
exit;

190
admin/menu.php Normal file
View File

@ -0,0 +1,190 @@
<?php
require_once 'header.php';
$action = $_GET['action'] ?? 'tampil';
$id = $_GET['id'] ?? null;
// Handle Delete
if ($action === 'hapus' && $id) {
// Get old foto to delete file
$old = fetch_one("SELECT foto FROM menu WHERE id = ?", [$id]);
if ($old && $old['foto'] && file_exists("../assets/uploads/" . $old['foto'])) {
unlink("../assets/uploads/" . $old['foto']);
}
$stmt = db()->prepare("DELETE FROM menu WHERE id = ?");
$stmt->execute([$id]);
header('Location: menu.php?msg=Menu berhasil dihapus');
exit;
}
// Handle Form Submit (Add/Edit)
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$nama_menu = $_POST['nama_menu'];
$kategori_id = $_POST['kategori_id'];
$deskripsi = $_POST['deskripsi'];
$harga = $_POST['harga'];
$is_rekomendasi = isset($_POST['is_rekomendasi']) ? 1 : 0;
$foto = $_POST['old_foto'] ?? '';
// Handle Upload Foto
if (isset($_FILES['foto']) && $_FILES['foto']['error'] === UPLOAD_ERR_OK) {
$tmp_name = $_FILES['foto']['tmp_name'];
$name = basename($_FILES['foto']['name']);
$ext = pathinfo($name, PATHINFO_EXTENSION);
$new_name = uniqid() . '.' . $ext;
$target = "../assets/uploads/" . $new_name;
if (move_uploaded_file($tmp_name, $target)) {
// Delete old file if exists
if ($foto && file_exists("../assets/uploads/" . $foto)) {
unlink("../assets/uploads/" . $foto);
}
$foto = $new_name;
}
}
if ($id) {
// Edit
$stmt = db()->prepare("UPDATE menu SET nama_menu=?, kategori_id=?, deskripsi=?, harga=?, is_rekomendasi=?, foto=? WHERE id=?");
$stmt->execute([$nama_menu, $kategori_id, $deskripsi, $harga, $is_rekomendasi, $foto, $id]);
$msg = "Menu berhasil diperbarui";
} else {
// Add
$stmt = db()->prepare("INSERT INTO menu (nama_menu, kategori_id, deskripsi, harga, is_rekomendasi, foto) VALUES (?, ?, ?, ?, ?, ?)");
$stmt->execute([$nama_menu, $kategori_id, $deskripsi, $harga, $is_rekomendasi, $foto]);
$msg = "Menu berhasil ditambahkan";
}
header('Location: menu.php?msg=' . $msg);
exit;
}
// Fetch data for form
$edit_data = null;
if (($action === 'edit' || $action === 'tambah') && $id) {
$edit_data = fetch_one("SELECT * FROM menu WHERE id = ?", [$id]);
}
$kategori_list = fetch_all("SELECT * FROM kategori_menu ORDER BY nama_kategori");
$menu_list = fetch_all("SELECT m.*, k.nama_kategori FROM menu m JOIN kategori_menu k ON m.kategori_id = k.id ORDER BY m.id DESC");
?>
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">Kelola Menu</h1>
<?php if ($action === 'tampil'): ?>
<a href="menu.php?action=tambah" class="btn btn-primary">Tambah Menu Baru</a>
<?php else: ?>
<a href="menu.php" class="btn btn-outline-secondary">Kembali ke Daftar</a>
<?php endif; ?>
</div>
<?php if (isset($_GET['msg'])): ?>
<div class="alert alert-success"><?php echo htmlspecialchars($_GET['msg']); ?></div>
<?php endif; ?>
<?php if ($action === 'tambah' || $action === 'edit'): ?>
<div class="card shadow-sm">
<div class="card-body">
<h5 class="card-title mb-4"><?php echo $id ? 'Edit Menu' : 'Tambah Menu Baru'; ?></h5>
<form method="POST" enctype="multipart/form-data">
<input type="hidden" name="old_foto" value="<?php echo $edit_data['foto'] ?? ''; ?>">
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label">Nama Menu</label>
<input type="text" name="nama_menu" class="form-control" value="<?php echo $edit_data['nama_menu'] ?? ''; ?>" required>
</div>
<div class="col-md-6 mb-3">
<label class="form-label">Kategori</label>
<select name="kategori_id" class="form-select" required>
<option value="">Pilih Kategori</option>
<?php foreach ($kategori_list as $kat): ?>
<option value="<?php echo $kat['id']; ?>" <?php echo (isset($edit_data['kategori_id']) && $edit_data['kategori_id'] == $kat['id']) ? 'selected' : ''; ?>>
<?php echo htmlspecialchars($kat['nama_kategori']); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-12 mb-3">
<label class="form-label">Deskripsi</label>
<textarea name="deskripsi" class="form-control" rows="3"><?php echo $edit_data['deskripsi'] ?? ''; ?></textarea>
</div>
<div class="col-md-4 mb-3">
<label class="form-label">Harga (Rp)</label>
<input type="number" name="harga" class="form-control" value="<?php echo $edit_data['harga'] ?? ''; ?>" required>
</div>
<div class="col-md-4 mb-3">
<label class="form-label">Foto Menu</label>
<input type="file" name="foto" class="form-control">
<?php if (isset($edit_data['foto']) && $edit_data['foto']): ?>
<div class="mt-2">
<small class="text-muted">Foto saat ini:</small><br>
<img src="../assets/uploads/<?php echo $edit_data['foto']; ?>" width="100" class="img-thumbnail" alt="">
</div>
<?php endif; ?>
</div>
<div class="col-md-4 mb-4 d-flex align-items-end">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="is_rekomendasi" id="is_rekomendasi" <?php echo (isset($edit_data['is_rekomendasi']) && $edit_data['is_rekomendasi']) ? 'checked' : ''; ?>>
<label class="form-check-label" for="is_rekomendasi">
Tampilkan sebagai Menu Rekomendasi
</label>
</div>
</div>
</div>
<button type="submit" class="btn btn-primary px-5">Simpan Menu</button>
</form>
</div>
</div>
<?php else: ?>
<div class="card shadow-sm">
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover mb-0">
<thead class="table-light">
<tr>
<th>Foto</th>
<th>Nama Menu</th>
<th>Kategori</th>
<th>Harga</th>
<th>Rekomendasi</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
<?php foreach ($menu_list as $row): ?>
<tr>
<td>
<?php if ($row['foto']): ?>
<img src="../assets/uploads/<?php echo $row['foto']; ?>" class="rounded" width="50" height="50" style="object-fit: cover;" alt="">
<?php else: ?>
<img src="https://images.pexels.com/photos/2097090/pexels-photo-2097090.jpeg?auto=compress&cs=tinysrgb&w=50" class="rounded" width="50" height="50" style="object-fit: cover;" alt="">
<?php endif; ?>
</td>
<td><?php echo htmlspecialchars($row['nama_menu']); ?></td>
<td><?php echo htmlspecialchars($row['nama_kategori']); ?></td>
<td><?php echo rupiah($row['harga']); ?></td>
<td>
<?php if ($row['is_rekomendasi']): ?>
<span class="badge bg-success">Ya</span>
<?php else: ?>
<span class="badge bg-light text-dark">Tidak</span>
<?php endif; ?>
</td>
<td>
<a href="menu.php?action=edit&id=<?php echo $row['id']; ?>" class="btn btn-sm btn-outline-info">Edit</a>
<a href="menu.php?action=hapus&id=<?php echo $row['id']; ?>" class="btn btn-sm btn-outline-danger" onclick="return confirm('Hapus menu ini?')">Hapus</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
<?php endif; ?>
<?php require_once 'footer.php'; ?>

199
admin/pesanan.php Normal file
View File

@ -0,0 +1,199 @@
<?php
require_once 'header.php';
$action = $_GET['action'] ?? 'tampil';
$id = $_GET['id'] ?? null;
// Handle Status Change
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['update_status'])) {
$new_status = $_POST['status'];
$stmt = db()->prepare("UPDATE pesanan SET status = ? WHERE id = ?");
$stmt->execute([$new_status, $id]);
header("Location: pesanan.php?action=detail&id=$id&msg=Status pesanan berhasil diperbarui");
exit;
}
// Handle Delete
if ($action === 'hapus' && $id) {
// Delete items first
$stmt = db()->prepare("DELETE FROM pesanan_item WHERE pesanan_id = ?");
$stmt->execute([$id]);
// Delete order
$stmt = db()->prepare("DELETE FROM pesanan WHERE id = ?");
$stmt->execute([$id]);
header('Location: pesanan.php?msg=Pesanan berhasil dihapus');
exit;
}
// Fetch Data
if ($action === 'detail' && $id) {
$order = fetch_one("SELECT * FROM pesanan WHERE id = ?", [$id]);
$items = fetch_all("SELECT pi.*, m.nama_menu FROM pesanan_item pi JOIN menu m ON pi.menu_id = m.id WHERE pi.pesanan_id = ?", [$id]);
}
$pesanan_list = fetch_all("SELECT * FROM pesanan ORDER BY id DESC");
?>
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">Kelola Pesanan</h1>
</div>
<?php if (isset($_GET['msg'])): ?>
<div class="alert alert-success"><?php echo htmlspecialchars($_GET['msg']); ?></div>
<?php endif; ?>
<?php if ($action === 'detail' && $order): ?>
<div class="row">
<div class="col-md-8">
<div class="card shadow-sm mb-4">
<div class="card-header bg-white">
<h5 class="mb-0">Detail Pesanan #<?php echo $order['id']; ?></h5>
</div>
<div class="card-body">
<table class="table table-bordered">
<tr>
<th width="30%">Nama Pelanggan</th>
<td><?php echo htmlspecialchars($order['nama_pelanggan']); ?></td>
</tr>
<tr>
<th>WhatsApp</th>
<td>
<a href="https://wa.me/<?php echo $order['whatsapp']; ?>" target="_blank" class="text-decoration-none">
<?php echo htmlspecialchars($order['whatsapp']); ?> <i class="fa fa-external-link small"></i>
</a>
</td>
</tr>
<tr>
<th>Alamat Pengiriman</th>
<td><?php echo nl2br(htmlspecialchars($order['alamat_pengiriman'])); ?></td>
</tr>
<tr>
<th>Tanggal Kirim</th>
<td><?php echo date('d F Y', strtotime($order['tanggal_kirim'])); ?></td>
</tr>
<tr>
<th>Catatan</th>
<td><?php echo nl2br(htmlspecialchars($order['catatan'] ?? '-')); ?></td>
</tr>
<tr>
<th>Waktu Pesan</th>
<td><?php echo date('d/m/Y H:i', strtotime($order['created_at'])); ?></td>
</tr>
</table>
<h6 class="mt-4 mb-3">Item Pesanan</h6>
<div class="table-responsive">
<table class="table table-sm">
<thead class="table-light">
<tr>
<th>Menu</th>
<th class="text-center">Qty</th>
<th class="text-end">Harga Satuan</th>
<th class="text-end">Subtotal</th>
</tr>
</thead>
<tbody>
<?php foreach ($items as $item): ?>
<tr>
<td><?php echo htmlspecialchars($item['nama_menu']); ?></td>
<td class="text-center"><?php echo $item['qty']; ?></td>
<td class="text-end"><?php echo rupiah($item['harga_saat_pesan']); ?></td>
<td class="text-end"><?php echo rupiah($item['qty'] * $item['harga_saat_pesan']); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
<tfoot>
<tr>
<th colspan="3" class="text-end">Total</th>
<th class="text-end h5"><?php echo rupiah($order['total_harga']); ?></th>
</tr>
</tfoot>
</table>
</div>
</div>
<div class="card-footer bg-white">
<a href="pesanan.php" class="btn btn-outline-secondary">Kembali</a>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card shadow-sm">
<div class="card-header bg-white">
<h5 class="mb-0">Update Status</h5>
</div>
<div class="card-body">
<form method="POST">
<input type="hidden" name="update_status" value="1">
<div class="mb-3">
<label class="form-label">Status Saat Ini</label>
<select name="status" class="form-select">
<option value="Baru" <?php echo $order['status'] == 'Baru' ? 'selected' : ''; ?>>Baru</option>
<option value="Proses" <?php echo $order['status'] == 'Proses' ? 'selected' : ''; ?>>Proses</option>
<option value="Selesai" <?php echo $order['status'] == 'Selesai' ? 'selected' : ''; ?>>Selesai</option>
<option value="Batal" <?php echo $order['status'] == 'Batal' ? 'selected' : ''; ?>>Batal</option>
</select>
</div>
<button type="submit" class="btn btn-primary w-100">Update Status</button>
</form>
</div>
</div>
</div>
</div>
<?php else: ?>
<div class="card shadow-sm">
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover mb-0">
<thead class="table-light">
<tr>
<th>ID</th>
<th>Pelanggan</th>
<th>WA</th>
<th>Total</th>
<th>Status</th>
<th>Waktu</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
<?php foreach ($pesanan_list as $row): ?>
<tr>
<td>#<?php echo $row['id']; ?></td>
<td><?php echo htmlspecialchars($row['nama_pelanggan']); ?></td>
<td><?php echo htmlspecialchars($row['whatsapp']); ?></td>
<td><?php echo rupiah($row['total_harga']); ?></td>
<td>
<?php
$badge = [
'Baru' => 'bg-info',
'Proses' => 'bg-warning',
'Selesai' => 'bg-success',
'Batal' => 'bg-danger'
];
?>
<span class="badge <?php echo $badge[$row['status']] ?? 'bg-secondary'; ?>">
<?php echo $row['status']; ?>
</span>
</td>
<td class="small"><?php echo date('d/m/y H:i', strtotime($row['created_at'])); ?></td>
<td>
<a href="pesanan.php?action=detail&id=<?php echo $row['id']; ?>" class="btn btn-sm btn-outline-info">Detail</a>
<a href="pesanan.php?action=hapus&id=<?php echo $row['id']; ?>" class="btn btn-sm btn-outline-danger" onclick="return confirm('Hapus pesanan ini?')">Hapus</a>
</td>
</tr>
<?php endforeach; ?>
<?php if (empty($pesanan_list)): ?>
<tr>
<td colspan="7" class="text-center py-4 text-muted">Belum ada pesanan.</td>
</tr>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
<?php endif; ?>
<?php require_once 'footer.php'; ?>

119
admin/profil.php Normal file
View File

@ -0,0 +1,119 @@
<?php
require_once 'header.php';
// Fetch current profil
$profil = fetch_one("SELECT * FROM profil_usaha LIMIT 1");
// Handle Form Submit
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$nama_usaha = $_POST['nama_usaha'];
$tagline = $_POST['tagline'];
$deskripsi = $_POST['deskripsi'];
$alamat = $_POST['alamat'];
$whatsapp = $_POST['whatsapp'];
$email = $_POST['email'];
$instagram = $_POST['instagram'];
$logo = $profil['logo'] ?? '';
// Handle Logo Upload
if (isset($_FILES['logo']) && $_FILES['logo']['error'] === UPLOAD_ERR_OK) {
$tmp_name = $_FILES['logo']['tmp_name'];
$name = basename($_FILES['logo']['name']);
$ext = pathinfo($name, PATHINFO_EXTENSION);
$new_name = 'logo_' . uniqid() . '.' . $ext;
$target = "../assets/uploads/" . $new_name;
if (move_uploaded_file($tmp_name, $target)) {
// Delete old logo if exists
if ($logo && file_exists("../assets/uploads/" . $logo)) {
unlink("../assets/uploads/" . $logo);
}
$logo = $new_name;
}
}
if ($profil) {
// Update
$stmt = db()->prepare("UPDATE profil_usaha SET nama_usaha=?, tagline=?, deskripsi=?, alamat=?, whatsapp=?, email=?, instagram=?, logo=? WHERE id=?");
$stmt->execute([$nama_usaha, $tagline, $deskripsi, $alamat, $whatsapp, $email, $instagram, $logo, $profil['id']]);
} else {
// Insert
$stmt = db()->prepare("INSERT INTO profil_usaha (nama_usaha, tagline, deskripsi, alamat, whatsapp, email, instagram, logo) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
$stmt->execute([$nama_usaha, $tagline, $deskripsi, $alamat, $whatsapp, $email, $instagram, $logo]);
}
header('Location: profil.php?msg=Profil usaha berhasil diperbarui');
exit;
}
?>
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">Profil Usaha</h1>
</div>
<?php if (isset($_GET['msg'])): ?>
<div class="alert alert-success"><?php echo htmlspecialchars($_GET['msg']); ?></div>
<?php endif; ?>
<div class="row">
<div class="col-md-8">
<div class="card shadow-sm">
<div class="card-body">
<form method="POST" enctype="multipart/form-data">
<div class="mb-3">
<label class="form-label">Nama Usaha</label>
<input type="text" name="nama_usaha" class="form-control" value="<?php echo $profil['nama_usaha'] ?? ''; ?>" required>
</div>
<div class="mb-3">
<label class="form-label">Tagline</label>
<input type="text" name="tagline" class="form-control" value="<?php echo $profil['tagline'] ?? ''; ?>">
</div>
<div class="mb-3">
<label class="form-label">Deskripsi Singkat</label>
<textarea name="deskripsi" class="form-control" rows="3"><?php echo $profil['deskripsi'] ?? ''; ?></textarea>
</div>
<div class="mb-3">
<label class="form-label">Alamat Lengkap</label>
<textarea name="alamat" class="form-control" rows="2"><?php echo $profil['alamat'] ?? ''; ?></textarea>
</div>
<div class="row">
<div class="col-md-4 mb-3">
<label class="form-label">WhatsApp</label>
<input type="text" name="whatsapp" class="form-control" value="<?php echo $profil['whatsapp'] ?? ''; ?>">
</div>
<div class="col-md-4 mb-3">
<label class="form-label">Email</label>
<input type="email" name="email" class="form-control" value="<?php echo $profil['email'] ?? ''; ?>">
</div>
<div class="col-md-4 mb-3">
<label class="form-label">Instagram</label>
<input type="text" name="instagram" class="form-control" value="<?php echo $profil['instagram'] ?? ''; ?>">
</div>
</div>
<div class="mb-4">
<label class="form-label">Logo Usaha</label>
<input type="file" name="logo" class="form-control">
<?php if (isset($profil['logo']) && $profil['logo']): ?>
<div class="mt-2">
<img src="../assets/uploads/<?php echo $profil['logo']; ?>" width="120" class="img-thumbnail" alt="Logo">
</div>
<?php endif; ?>
</div>
<button type="submit" class="btn btn-primary px-5">Simpan Perubahan</button>
</form>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card shadow-sm border-0 bg-light">
<div class="card-body">
<h5>Tips Profil</h5>
<p class="small text-muted">Pastikan nomor WhatsApp diawali dengan 62 (contoh: 628123456789) agar fitur tombol pesan di halaman depan berfungsi dengan baik.</p>
<p class="small text-muted">Logo yang diunggah sebaiknya memiliki latar belakang transparan (PNG) untuk tampilan terbaik di website.</p>
</div>
</div>
</div>
</div>
<?php require_once 'footer.php'; ?>

243
assets/css/custom.css Normal file
View File

@ -0,0 +1,243 @@
/* Custom Styles */
.hero {
padding: 6rem 0;
background: linear-gradient(rgba(0,0,0,0.5), rgba(0,0,0,0.5)), url('https://images.pexels.com/photos/1640777/pexels-photo-1640777.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2');
background-size: cover;
background-position: center;
color: white;
text-align: center;
}
.hero-badge {
display: inline-block;
padding: 0.5rem 1rem;
background: rgba(217, 119, 6, 0.9);
border-radius: 2rem;
font-size: 0.875rem;
font-weight: 600;
margin-bottom: 1.5rem;
}
.hero h1 {
font-size: 3.5rem;
font-weight: 800;
margin-bottom: 1rem;
letter-spacing: -0.025em;
}
.hero-tagline {
font-size: 1.5rem;
font-weight: 500;
margin-bottom: 2rem;
opacity: 0.9;
}
.hero-desc {
max-width: 700px;
margin: 0 auto 2.5rem;
font-size: 1.125rem;
opacity: 0.8;
}
.btn-primary {
background-color: var(--primary-color);
border-color: var(--primary-color);
padding: 0.75rem 2rem;
font-weight: 600;
border-radius: var(--border-radius);
}
.btn-primary:hover {
background-color: #B45309;
border-color: #B45309;
}
.btn-outline {
border: 2px solid white;
color: white;
padding: 0.75rem 2rem;
font-weight: 600;
border-radius: var(--border-radius);
text-decoration: none;
transition: all 0.3s;
}
.btn-outline:hover {
background: white;
color: var(--text-color);
}
.section {
padding: 5rem 0;
}
.section-header {
text-align: center;
margin-bottom: 4rem;
}
.section-header h2 {
font-weight: 700;
font-size: 2.25rem;
margin-bottom: 1rem;
}
.section-header p {
color: #6B7280;
font-size: 1.125rem;
}
.kategori-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1.5rem;
}
.kategori-card {
background: white;
padding: 2.5rem 1.5rem;
text-align: center;
border-radius: var(--border-radius);
text-decoration: none;
color: inherit;
transition: transform 0.3s, box-shadow 0.3s;
border: 1px solid #E5E7EB;
}
.kategori-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
color: var(--primary-color);
}
.kategori-icon {
font-size: 3rem;
margin-bottom: 1.5rem;
}
.kategori-card h3 {
font-size: 1.25rem;
font-weight: 700;
margin-bottom: 0.5rem;
}
.kategori-card p {
font-size: 0.875rem;
color: #6B7280;
margin-bottom: 0;
}
.menu-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
}
.menu-card {
background: white;
border-radius: var(--border-radius);
overflow: hidden;
border: 1px solid #E5E7EB;
transition: box-shadow 0.3s;
}
.menu-card:hover {
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
}
.menu-card-img {
height: 200px;
position: relative;
}
.menu-card-img img {
width: 100%;
height: 100%;
object-fit: cover;
}
.menu-badge {
position: absolute;
top: 1rem;
right: 1rem;
padding: 0.25rem 0.75rem;
border-radius: 1rem;
font-size: 0.75rem;
font-weight: 600;
}
.rekomendasi {
background: var(--primary-color);
color: white;
}
.menu-card-body {
padding: 1.5rem;
}
.menu-kategori {
font-size: 0.75rem;
font-weight: 600;
color: var(--primary-color);
text-transform: uppercase;
letter-spacing: 0.05em;
margin-bottom: 0.5rem;
display: block;
}
.menu-card h3 {
font-size: 1.25rem;
font-weight: 700;
margin-bottom: 0.75rem;
}
.menu-card p {
font-size: 0.875rem;
color: #6B7280;
margin-bottom: 1.5rem;
}
.menu-harga {
display: flex;
justify-content: space-between;
align-items: center;
}
.harga {
font-weight: 700;
font-size: 1.125rem;
color: var(--text-color);
}
.btn-whatsapp {
background-color: #25D366;
color: white;
border: none;
}
.btn-whatsapp:hover {
background-color: #128C7E;
color: white;
}
.keunggulan-item {
display: flex;
gap: 1.5rem;
margin-bottom: 2rem;
}
.keunggulan-icon {
font-size: 2rem;
flex-shrink: 0;
}
.keunggulan-item h4 {
font-weight: 700;
margin-bottom: 0.5rem;
}
.keunggulan-item p {
color: #6B7280;
margin-bottom: 0;
}

17
assets/js/main.js Normal file
View File

@ -0,0 +1,17 @@
// Main Interactivity
document.addEventListener('DOMContentLoaded', function() {
console.log('Masakan Nusantara Ibu Tini - Ready');
// Smooth scroll for anchor links
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
target.scrollIntoView({
behavior: 'smooth'
});
}
});
});
});

View File

@ -0,0 +1,56 @@
CREATE TABLE IF NOT EXISTS profil_usaha (
id INT AUTO_INCREMENT PRIMARY KEY,
nama_usaha VARCHAR(255) NOT NULL,
tagline VARCHAR(255),
deskripsi TEXT,
alamat TEXT,
whatsapp VARCHAR(20),
email VARCHAR(100),
instagram VARCHAR(100),
logo VARCHAR(255)
);
CREATE TABLE IF NOT EXISTS kategori_menu (
id INT AUTO_INCREMENT PRIMARY KEY,
nama_kategori VARCHAR(100) NOT NULL,
slug VARCHAR(100) NOT NULL UNIQUE,
deskripsi TEXT,
urutan INT DEFAULT 0,
status TINYINT(1) DEFAULT 1
);
CREATE TABLE IF NOT EXISTS menu (
id INT AUTO_INCREMENT PRIMARY KEY,
kategori_id INT,
nama_menu VARCHAR(255) NOT NULL,
deskripsi TEXT,
harga DECIMAL(10, 2) NOT NULL,
harga_diskon DECIMAL(10, 2),
foto VARCHAR(255),
is_rekomendasi TINYINT(1) DEFAULT 0,
status TINYINT(1) DEFAULT 1,
FOREIGN KEY (kategori_id) REFERENCES kategori_menu(id)
);
CREATE TABLE IF NOT EXISTS galeri (
id INT AUTO_INCREMENT PRIMARY KEY,
judul VARCHAR(255),
foto VARCHAR(255),
status TINYINT(1) DEFAULT 1
);
-- Seed Data
INSERT INTO profil_usaha (nama_usaha, tagline, deskripsi, whatsapp)
VALUES ('MASAKAN NUSANTARA IBU TINI', 'Melayani Catering Harian, Acara, Nasi Box & Snack Box', 'Nikmati cita rasa autentik masakan Nusantara dengan bahan-bahan segar dan bumbu tradisional.', '6285714955640');
INSERT INTO kategori_menu (nama_kategori, slug, deskripsi, urutan) VALUES
('Nasi Box', 'nasi-box', 'Paket nasi lengkap dalam kemasan praktis.', 1),
('Prasmanan', 'prasmanan', 'Layanan prasmanan untuk acara besar.', 2),
('Tumpeng', 'tumpeng', 'Tumpeng nasi kuning/putih untuk syukuran.', 3),
('Snack Box', 'snack-box', 'Aneka kue dan jajanan pasar.', 4),
('Menu Harian', 'menu-harian', 'Katering harian untuk rumah dan kantor.', 5);
INSERT INTO menu (kategori_id, nama_menu, deskripsi, harga, is_rekomendasi) VALUES
(1, 'Nasi Ayam Bakar Madu', 'Nasi putih, ayam bakar madu, sambal, lalapan, tahu & tempe.', 25000, 1),
(1, 'Nasi Rendang Padang', 'Nasi putih, rendang daging sapi, sayur nangka, sambal ijo.', 30000, 1),
(4, 'Paket Snack Manis', 'Kue sus, risoles, lemper ayam.', 15000, 1);

View File

@ -0,0 +1,33 @@
CREATE TABLE IF NOT EXISTS admins (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
nama_lengkap VARCHAR(100),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS pesanan (
id INT AUTO_INCREMENT PRIMARY KEY,
nama_pelanggan VARCHAR(100) NOT NULL,
whatsapp VARCHAR(20) NOT NULL,
alamat_pengiriman TEXT,
tanggal_kirim DATE,
total_harga DECIMAL(10, 2),
status ENUM('Baru', 'Proses', 'Selesai', 'Batal') DEFAULT 'Baru',
catatan TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS pesanan_item (
id INT AUTO_INCREMENT PRIMARY KEY,
pesanan_id INT,
menu_id INT,
qty INT NOT NULL,
harga_saat_pesan DECIMAL(10, 2) NOT NULL,
FOREIGN KEY (pesanan_id) REFERENCES pesanan(id) ON DELETE CASCADE,
FOREIGN KEY (menu_id) REFERENCES menu(id)
);
-- Default Admin: admin / admin123
INSERT INTO admins (username, password, nama_lengkap)
VALUES ('admin', '$2y$10$2WEIuzHnD1ZJYg4WzJ9Wt.kfha4lyP3APX/LRki9OhnYf1T5yixjq', 'Administrator Ibu Tini');

46
includes/footer.php Normal file
View File

@ -0,0 +1,46 @@
<footer class="bg-dark text-white py-5 mt-5">
<div class="container">
<div class="row g-4">
<div class="col-md-4">
<h5 class="fw-bold mb-4" style="color: var(--primary-color);">Masakan Nusantara Ibu Tini</h5>
<p class="text-muted">Nikmati cita rasa autentik masakan Nusantara dengan bahan-bahan segar dan bumbu tradisional. Cocok untuk berbagai acara Anda.</p>
</div>
<div class="col-md-2 offset-md-1">
<h6 class="fw-bold mb-3">Tautan</h6>
<ul class="list-unstyled">
<li><a href="index.php" class="text-muted text-decoration-none">Beranda</a></li>
<li><a href="#menu" class="text-muted text-decoration-none">Menu</a></li>
<li><a href="#about" class="text-muted text-decoration-none">Tentang Kami</a></li>
</ul>
</div>
<div class="col-md-2">
<h6 class="fw-bold mb-3">Layanan</h6>
<ul class="list-unstyled">
<li><span class="text-muted">Nasi Box</span></li>
<li><span class="text-muted">Prasmanan</span></li>
<li><span class="text-muted">Tumpeng</span></li>
<li><span class="text-muted">Snack Box</span></li>
</ul>
</div>
<div class="col-md-3">
<h6 class="fw-bold mb-3">Kontak</h6>
<ul class="list-unstyled text-muted">
<li><i class="bi bi-geo-alt me-2"></i> Jakarta, Indonesia</li>
<li><i class="bi bi-whatsapp me-2"></i> +62 857 1495 5640</li>
</ul>
</div>
</div>
<hr class="my-4 border-secondary">
<div class="text-center text-muted small">
&copy; <?php echo date('Y'); ?> Masakan Nusantara Ibu Tini. All rights reserved.
<div class="mt-2">
<a href="admin/login.php" class="text-muted text-decoration-none" style="opacity: 0.5;">Admin Login</a>
</div>
</div>
</div>
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
</body>
</html>

66
includes/header.php Normal file
View File

@ -0,0 +1,66 @@
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php echo isset($page_title) ? $page_title . " - " : ""; ?>Masakan Nusantara Ibu Tini</title>
<!-- Meta Tags -->
<meta name="description" content="<?php echo $_SERVER['PROJECT_DESCRIPTION'] ?? 'Catering Masakan Nusantara Ibu Tini - Melayani Catering Harian, Acara, Nasi Box & Snack Box'; ?>">
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<!-- Bootstrap 5 -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- Custom CSS -->
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
<style>
:root {
--primary-color: #D97706; /* Amber-600 */
--secondary-color: #065F46; /* Emerald-800 */
--bg-color: #F9FAFB;
--text-color: #1F2937;
--border-radius: 0.5rem;
}
body {
font-family: 'Inter', sans-serif;
background-color: var(--bg-color);
color: var(--text-color);
line-height: 1.6;
}
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-white border-bottom sticky-top">
<div class="container">
<a class="navbar-brand fw-bold text-primary" href="index.php">
<span style="color: var(--primary-color);">IBU TINI</span>
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link" href="index.php">Beranda</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#menu">Menu</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#about">Tentang Kami</a>
</li>
<li class="nav-item">
<a class="nav-link btn btn-primary text-white ms-lg-3 px-4" href="https://wa.me/6285714955640" target="_blank">Pesan Sekarang</a>
</li>
</ul>
</div>
</div>
</nav>

18
includes/koneksi.php Normal file
View File

@ -0,0 +1,18 @@
<?php
require_once __DIR__ . '/../db/config.php';
function fetch_one($sql, $params = []) {
$stmt = db()->prepare($sql);
$stmt->execute($params);
return $stmt->fetch();
}
function fetch_all($sql, $params = []) {
$stmt = db()->prepare($sql);
$stmt->execute($params);
return $stmt->fetchAll();
}
function rupiah($angka) {
return "Rp " . number_format($angka, 0, ',', '.');
}

329
index.php
View File

@ -1,150 +1,187 @@
<?php
declare(strict_types=1);
@ini_set('display_errors', '1');
@error_reporting(E_ALL);
@date_default_timezone_set('UTC');
/**
* Halaman Beranda
* MASAKAN NUSANTARA IBU TINI
*/
$phpVersion = PHP_VERSION;
$now = date('Y-m-d H:i:s');
require_once 'includes/koneksi.php';
$page_title = 'Beranda';
// Get profile data
$profil = fetch_one("SELECT * FROM profil_usaha LIMIT 1");
// Get recommended menus
$menu_rekomendasi = fetch_all("SELECT m.*, k.nama_kategori, k.slug as kategori_slug
FROM menu m
JOIN kategori_menu k ON m.kategori_id = k.id
WHERE m.status = 1 AND m.is_rekomendasi = 1
ORDER BY m.id DESC LIMIT 6");
// Get all categories
$kategori = fetch_all("SELECT * FROM kategori_menu WHERE status = 1 ORDER BY urutan");
// Get gallery images
$galeri = fetch_all("SELECT * FROM galeri WHERE status = 1 ORDER BY id DESC LIMIT 6");
include 'includes/header.php';
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>New Style</title>
<?php
// Read project preview data from environment
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? '';
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
?>
<?php if ($projectDescription): ?>
<!-- Meta description -->
<meta name="description" content='<?= htmlspecialchars($projectDescription) ?>' />
<!-- Open Graph meta tags -->
<meta property="og:description" content="<?= htmlspecialchars($projectDescription) ?>" />
<!-- Twitter meta tags -->
<meta property="twitter:description" content="<?= htmlspecialchars($projectDescription) ?>" />
<?php endif; ?>
<?php if ($projectImageUrl): ?>
<!-- Open Graph image -->
<meta property="og:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
<!-- Twitter image -->
<meta property="twitter:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
<?php endif; ?>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
<style>
:root {
--bg-color-start: #6a11cb;
--bg-color-end: #2575fc;
--text-color: #ffffff;
--card-bg-color: rgba(255, 255, 255, 0.01);
--card-border-color: rgba(255, 255, 255, 0.1);
}
body {
margin: 0;
font-family: 'Inter', sans-serif;
background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end));
color: var(--text-color);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
text-align: center;
overflow: hidden;
position: relative;
}
body::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><path d="M-10 10L110 10M10 -10L10 110" stroke-width="1" stroke="rgba(255,255,255,0.05)"/></svg>');
animation: bg-pan 20s linear infinite;
z-index: -1;
}
@keyframes bg-pan {
0% { background-position: 0% 0%; }
100% { background-position: 100% 100%; }
}
main {
padding: 2rem;
}
.card {
background: var(--card-bg-color);
border: 1px solid var(--card-border-color);
border-radius: 16px;
padding: 2rem;
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.1);
}
.loader {
margin: 1.25rem auto 1.25rem;
width: 48px;
height: 48px;
border: 3px solid rgba(255, 255, 255, 0.25);
border-top-color: #fff;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.hint {
opacity: 0.9;
}
.sr-only {
position: absolute;
width: 1px; height: 1px;
padding: 0; margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap; border: 0;
}
h1 {
font-size: 3rem;
font-weight: 700;
margin: 0 0 1rem;
letter-spacing: -1px;
}
p {
margin: 0.5rem 0;
font-size: 1.1rem;
}
code {
background: rgba(0,0,0,0.2);
padding: 2px 6px;
border-radius: 4px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
footer {
position: absolute;
bottom: 1rem;
font-size: 0.8rem;
opacity: 0.7;
}
</style>
</head>
<body>
<main>
<div class="card">
<h1>Analyzing your requirements and generating your website…</h1>
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes">
<span class="sr-only">Loading…</span>
</div>
<p class="hint"><?= ($_SERVER['HTTP_HOST'] ?? '') === 'appwizzy.com' ? 'AppWizzy' : 'Flatlogic' ?> AI is collecting your requirements and applying the first changes.</p>
<p class="hint">This page will update automatically as the plan is implemented.</p>
<p>Runtime: PHP <code><?= htmlspecialchars($phpVersion) ?></code> — UTC <code><?= htmlspecialchars($now) ?></code></p>
<!-- Hero Section -->
<section class="hero">
<div class="container">
<div class="hero-content">
<span class="hero-badge"> Catering Masakan Rumahan</span>
<h1><?php echo $profil ? htmlspecialchars($profil['nama_usaha']) : 'MASAKAN NUSANTARA IBU TINI'; ?></h1>
<p class="hero-tagline"><?php echo $profil ? htmlspecialchars($profil['tagline']) : 'Melayani Catering Harian, Acara, Nasi Box & Snack Box'; ?></p>
<p class="hero-desc">
<?php echo $profil ? htmlspecialchars($profil['deskripsi']) : 'Nikmati cita rasa autentik masakan Nusantara dengan bahan-bahan segar dan bumbu tradisional. Cocok untuk acara keluarga, kantor, dan berbagai acara spesial Anda.'; ?>
</p>
<div class="hero-buttons d-flex justify-content-center gap-3 mt-4">
<a href="https://wa.me/<?php echo $profil['whatsapp'] ?? '6285714955640'; ?>" class="btn btn-primary btn-lg px-5" target="_blank">
🛒 Pesan Sekarang
</a>
<a href="#menu" class="btn btn-outline btn-lg px-5">
📋 Lihat Menu
</a>
</div>
</div>
</div>
</main>
<footer>
Page updated: <?= htmlspecialchars($now) ?> (UTC)
</footer>
</body>
</html>
</section>
<!-- Kategori Section -->
<section class="section" id="categories">
<div class="container">
<div class="section-header">
<h2>Kategori Menu Kami</h2>
<p>Pilih kategori catering sesuai kebutuhan acara Anda</p>
</div>
<div class="kategori-grid">
<?php foreach ($kategori as $kat): ?>
<a href="#menu" class="kategori-card">
<div class="kategori-icon">
<?php
$icons = [
'nasi-box' => '🍱',
'prasmanan' => '🍽️',
'tumpeng' => '🎉',
'snack-box' => '🥐',
'menu-harian' => '🍛'
];
echo $icons[$kat['slug']] ?? '🍴';
?>
</div>
<h3><?php echo htmlspecialchars($kat['nama_kategori']); ?></h3>
<p><?php echo htmlspecialchars($kat['deskripsi']); ?></p>
</a>
<?php endforeach; ?>
</div>
</div>
</section>
<!-- Menu Rekomendasi Section -->
<section class="section bg-light" id="menu">
<div class="container">
<div class="section-header">
<h2>Menu Rekomendasi</h2>
<p>Pilihan menu terbaik dan favorit pelanggan kami</p>
</div>
<?php if (count($menu_rekomendasi) > 0): ?>
<div class="menu-grid">
<?php foreach ($menu_rekomendasi as $menu): ?>
<div class="menu-card">
<div class="menu-card-img">
<?php if ($menu['foto'] && file_exists('assets/uploads/' . $menu['foto'])): ?>
<img src="assets/uploads/<?php echo htmlspecialchars($menu['foto']); ?>" alt="<?php echo htmlspecialchars($menu['nama_menu']); ?>">
<?php else: ?>
<img src="https://images.pexels.com/photos/2097090/pexels-photo-2097090.jpeg?auto=compress&cs=tinysrgb&w=800" alt="<?php echo htmlspecialchars($menu['nama_menu']); ?>">
<?php endif; ?>
<?php if ($menu['is_rekomendasi']): ?>
<span class="menu-badge rekomendasi"> Rekomendasi</span>
<?php endif; ?>
</div>
<div class="menu-card-body">
<span class="menu-kategori"><?php echo htmlspecialchars($menu['nama_kategori']); ?></span>
<h3><?php echo htmlspecialchars($menu['nama_menu']); ?></h3>
<p><?php echo htmlspecialchars($menu['deskripsi']); ?></p>
<div class="menu-harga">
<div>
<span class="harga"><?php echo rupiah($menu['harga']); ?></span>
</div>
<a href="https://wa.me/<?php echo $profil['whatsapp'] ?? '6285714955640'; ?>?text=<?php echo urlencode('Halo MASAKAN NUSANTARA IBU TINI, saya ingin memesan ' . $menu['nama_menu']); ?>"
class="btn btn-whatsapp btn-sm px-4 py-2 rounded-pill" target="_blank">
Pesan
</a>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
<div class="text-center mt-5">
<a href="#menu" class="btn btn-primary">Lihat Semua Menu</a>
</div>
<?php else: ?>
<div class="text-center py-5">
<div class="display-1 mb-4">🍽️</div>
<h3>Belum ada menu rekomendasi</h3>
<p class="text-muted">Silakan hubungi kami untuk informasi menu lengkap</p>
</div>
<?php endif; ?>
</div>
</section>
<!-- Keunggulan Section -->
<section class="section" id="about">
<div class="container">
<div class="section-header">
<h2>Mengapa Memilih Kami?</h2>
<p>Keunggulan layanan catering MASAKAN NUSANTARA IBU TINI</p>
</div>
<div class="row align-items-center">
<div class="col-lg-6 mb-4 mb-lg-0">
<img src="https://images.pexels.com/photos/2284166/pexels-photo-2284166.jpeg?auto=compress&cs=tinysrgb&w=800" alt="Catering Service" class="img-fluid rounded-3 shadow">
</div>
<div class="col-lg-6 ps-lg-5">
<div class="keunggulan-list">
<div class="keunggulan-item">
<div class="keunggulan-icon">🥘</div>
<div>
<h4>Rasa Autentik Nusantara</h4>
<p>Masakan dibuat dengan resep tradisional turun-temurun yang menjaga cita rasa asli Indonesia.</p>
</div>
</div>
<div class="keunggulan-item">
<div class="keunggulan-icon">🥬</div>
<div>
<h4>Bahan Segar Berkualitas</h4>
<p>Kami hanya menggunakan bahan-bahan segar dan berkualitas untuk setiap hidangan.</p>
</div>
</div>
<div class="keunggulan-item">
<div class="keunggulan-icon"></div>
<div>
<h4>Higienis & Bersih</h4>
<p>Proses pengolahan makanan mengikuti standar kebersihan yang ketat untuk kesehatan Anda.</p>
</div>
</div>
<div class="keunggulan-item">
<div class="keunggulan-icon">🚚</div>
<div>
<h4>Pengiriman Tepat Waktu</h4>
<p>Kami menjamin pesanan Anda sampai di lokasi tepat waktu untuk menjaga kesegaran hidangan.</p>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<?php include 'includes/footer.php'; ?>