Compare commits

..

2 Commits

Author SHA1 Message Date
Flatlogic Bot
3d8da9a26a Auto commit: 2025-10-06T00:57:03.276Z 2025-10-06 00:57:03 +00:00
Flatlogic Bot
8dd1b311f8 Si-Apon Versi Demo 2025-10-05 06:17:51 +00:00
11 changed files with 1245 additions and 145 deletions

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

@ -0,0 +1,396 @@
/* Add your custom styles here */
.alert {
padding: 1rem;
margin-bottom: 1rem;
border-radius: 0.5rem;
border: 1px solid transparent;
}
.alert-danger {
color: #721c24;
background-color: #f8d7da;
border-color: #f5c6cb;
}
.alert-success {
color: #155724;
background-color: #d4edda;
border-color: #c3e6cb;
}
/* Login & Register Page */
.login-container {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background-color: #f4f4f4;
}
.login-box {
background: #fff;
padding: 2.5rem;
border-radius: 0.5rem;
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
width: 100%;
max-width: 420px;
}
.login-header {
text-align: center;
margin-bottom: 2rem;
}
.login-header h2 {
margin: 0;
font-size: 1.8rem;
color: #264653;
}
.login-header p {
color: #6c757d;
}
.logo-link {
text-decoration: none;
}
.login-form .form-group {
margin-bottom: 1.5rem;
}
.login-form label {
display: block;
margin-bottom: 0.5rem;
font-weight: bold;
color: #264653;
}
.login-form input {
width: 100%;
padding: 0.75rem;
border: 1px solid #ccc;
border-radius: 0.25rem;
}
.btn-login {
width: 100%;
padding: 0.85rem;
border: none;
border-radius: 0.25rem;
background-color: #2A9D8F;
color: white;
font-size: 1.1rem;
cursor: pointer;
transition: background-color 0.3s;
}
.btn-login:hover {
background-color: #248a7e;
}
.login-footer {
text-align: center;
margin-top: 1.5rem;
}
.login-footer p {
margin: 0.5rem 0;
color: #6c757d;
}
.login-footer a {
color: #2A9D8F;
text-decoration: none;
}
.login-footer a:hover {
text-decoration: underline;
}
body {
font-family: 'Lato', sans-serif;
color: #264653;
background-color: #F4F4F4;
margin: 0;
}
h1, h2, h3, h4, h5, h6 {
font-family: 'Merriweather', serif;
}
.navbar {
background-color: #FFFFFF;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.hero {
background: url('https://picsum.photos/seed/hero/1600/900') no-repeat center center;
background-size: cover;
color: white;
padding: 100px 0;
text-align: center;
}
.hero h1 {
font-size: 3.5rem;
font-weight: 700;
}
.hero p {
font-size: 1.25rem;
}
.btn-primary {
background-color: #2A9D8F;
border-color: #2A9D8F;
padding: 10px 20px;
border-radius: 0.5rem;
color: white;
text-decoration: none;
display: inline-block;
}
.btn-secondary {
background-color: #E9C46A;
border-color: #E9C46A;
padding: 10px 20px;
border-radius: 0.5rem;
}
section {
padding: 60px 0;
}
.card {
background: #fff;
padding: 2rem;
border: none;
border-radius: 0.5rem;
box-shadow: 0 4px 8px rgba(0,0,0,0.05);
margin-bottom: 2rem;
}
/* Dashboard Layout */
.dashboard-wrapper {
display: flex;
min-height: 100vh;
}
.sidebar {
width: 260px;
background: #264653;
color: #fff;
display: flex;
flex-direction: column;
}
.sidebar-header {
padding: 1.5rem;
text-align: center;
border-bottom: 1px solid #3a5e6c;
}
.sidebar-header h3 {
margin: 0;
color: #fff;
}
.sidebar-header a {
text-decoration: none;
}
.sidebar-nav {
flex-grow: 1;
padding-top: 1rem;
}
.sidebar-nav a {
display: block;
padding: 1rem 1.5rem;
color: #e0e0e0;
text-decoration: none;
transition: background 0.3s, color 0.3s;
}
.sidebar-nav a:hover, .sidebar-nav a.active {
background: #2A9D8F;
color: #fff;
}
.sidebar-footer {
padding: 1.5rem;
border-top: 1px solid #3a5e6c;
}
.sidebar-footer a {
display: block;
text-align: center;
color: #e0e0e0;
text-decoration: none;
}
.main-content {
flex-grow: 1;
background: #f4f4f4;
}
.main-header {
background: #fff;
padding: 1rem 2rem;
border-bottom: 1px solid #ddd;
display: flex;
justify-content: space-between;
align-items: center;
}
.content-area {
padding: 2rem;
}
/* Dashboard Table */
.table-responsive {
overflow-x: auto;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 1rem;
}
thead {
background-color: #f8f9fa;
}
th, td {
padding: 0.9rem 1rem;
text-align: left;
border-bottom: 1px solid #dee2e6;
}
tbody tr:hover {
background-color: #f1f1f1;
}
/* Badges */
.badge {
padding: 0.3em 0.6em;
border-radius: 0.25rem;
font-size: 0.85em;
font-weight: 700;
color: #fff;
}
.role-admin {
background-color: #d9534f;
}
.role-petugas-pajak {
background-color: #f0ad4e;
}
.role-wajib-pajak {
background-color: #5bc0de;
}
/* Status Badges */
.status-pending {
background-color: #f0ad4e; /* Orange */
}
.status-approved {
background-color: #5cb85c; /* Green */
}
.status-rejected {
background-color: #d9534f; /* Red */
}
/* Form Card for Lapor Pajak */
.form-card {
max-width: 800px;
margin: 0 auto;
}
.form-group {
margin-bottom: 1.5rem;
}
.form-group label {
display: block;
margin-bottom: .5rem;
font-weight: bold;
}
.form-group input,
.form-group select {
width: 100%;
padding: .75rem;
border: 1px solid #ccc;
border-radius: .25rem;
box-sizing: border-box; /* Add this */
}
.period-group {
display: flex;
gap: 1rem;
}
.period-group select {
flex: 1;
}
.btn-block {
width: 100%;
}
/* Dashboard card header */
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1.5rem;
padding-bottom: 1rem;
border-bottom: 1px solid #eee;
}
.card-header h3 {
margin: 0;
}
/* General Dashboard Container */
.dashboard-container {
display: flex;
min-height: 100vh;
}
.logo {
text-decoration: none;
color: #fff;
font-family: 'Merriweather', serif;
font-size: 1.5rem;
}
.user-info {
display: flex;
align-items: center;
gap: 1rem;
}
/* Action Buttons in Tables */
.actions {
white-space: nowrap;
}
.actions .btn {
margin-right: 0.5rem;
}
.btn-sm {
padding: 0.25rem 0.5rem;
font-size: 0.875rem;
border-radius: 0.2rem;
}
.btn-success {
background-color: #5cb85c;
border-color: #5cb85c;
color: white;
}
.btn-danger {
background-color: #d9534f;
border-color: #d9534f;
color: white;
}

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

@ -0,0 +1,34 @@
// Custom JS for Si-Apon
document.addEventListener('DOMContentLoaded', function () {
// Smooth scrolling for anchor links
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
document.querySelector(this.getAttribute('href')).scrollIntoView({
behavior: 'smooth'
});
});
});
// Contact form validation
const contactForm = document.getElementById('contactForm');
if (contactForm) {
contactForm.addEventListener('submit', function (e) {
e.preventDefault();
// Basic validation
const name = document.getElementById('name').value;
const email = document.getElementById('email').value;
const message = document.getElementById('message').value;
if (name === '' || email === '' || message === '') {
alert('Please fill in all fields.');
} else {
// Here you would typically send the form data to the server
alert('Thank you for your message!');
contactForm.reset();
}
});
}
});

197
dashboard.php Normal file
View File

@ -0,0 +1,197 @@
<?php
session_start();
require_once 'db/config.php';
if (!isset($_SESSION['user_id'])) {
header("Location: login.php");
exit();
}
$user_id = $_SESSION['user_id'];
$userName = $_SESSION['user_name'] ?? 'Pengguna';
$userRole = $_SESSION['user_role'] ?? 'Tidak Dikenal';
$pdo = db();
$users = [];
$tax_reports = [];
// Fetch data based on user role
if ($userRole === 'Super Administrator') {
$stmt = $pdo->query("SELECT id, name, email, role, created_at FROM users ORDER BY created_at DESC");
$users = $stmt->fetchAll();
} elseif ($userRole === 'Wajib Pajak') {
$stmt = $pdo->prepare("SELECT * FROM tax_reports WHERE user_id = :user_id ORDER BY created_at DESC");
$stmt->execute([':user_id' => $user_id]);
$tax_reports = $stmt->fetchAll();
} elseif ($userRole === 'Petugas Pajak') {
$stmt = $pdo->query("SELECT tr.*, u.name AS taxpayer_name FROM tax_reports tr JOIN users u ON tr.user_id = u.id ORDER BY tr.created_at DESC");
$tax_reports = $stmt->fetchAll();
}
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dashboard - Si-Apon</title>
<link href="https://fonts.googleapis.com/css2?family=Merriweather:wght@700&family=Lato:wght@400;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
</head>
<body>
<div class="dashboard-container">
<aside class="sidebar">
<div class="sidebar-header">
<a href="index.php" class="logo">Si-Apon</a>
</div>
<nav class="sidebar-nav">
<a href="dashboard.php" class="active">Dashboard</a>
<?php if ($userRole === 'Wajib Pajak'): ?>
<a href="lapor-pajak.php">Lapor Pajak</a>
<?php endif; ?>
<?php if ($userRole === 'Petugas Pajak'): ?>
<a href="dashboard.php" class="active">Verifikasi Laporan</a>
<?php endif; ?>
<?php if ($userRole === 'Super Administrator'): ?>
<a href="#">Manajemen Pengguna</a>
<?php endif; ?>
</nav>
<div class="sidebar-footer">
<a href="logout.php">Logout</a>
</div>
</aside>
<main class="main-content">
<header class="main-header">
<h1>Selamat Datang, <?php echo htmlspecialchars($userName); ?>!</h1>
<div class="user-info">
<span class="role-badge role-<?php echo strtolower(str_replace(' ', '-', $userRole)); ?>"><?php echo htmlspecialchars($userRole); ?></span>
</div>
</header>
<section class="content-section">
<?php if ($userRole === 'Super Administrator'): ?>
<div class="card">
<div class="card-header">
<h3>Manajemen Pengguna</h3>
</div>
<div class="card-body">
<div class="table-responsive">
<table>
<thead>
<tr>
<th>Nama</th>
<th>Email</th>
<th>Peran</th>
<th>Tanggal Terdaftar</th>
</tr>
</thead>
<tbody>
<?php if (empty($users)): ?>
<tr><td colspan="4">Tidak ada pengguna untuk ditampilkan.</td></tr>
<?php else: ?>
<?php foreach ($users as $user): ?>
<tr>
<td><?php echo htmlspecialchars($user['name']); ?></td>
<td><?php echo htmlspecialchars($user['email']); ?></td>
<td><span class="badge role-<?php echo strtolower(str_replace(' ', '-', htmlspecialchars($user['role']))); ?>"><?php echo htmlspecialchars($user['role']); ?></span></td>
<td><?php echo date("d M Y", strtotime($user['created_at'])); ?></td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
<?php elseif ($userRole === 'Petugas Pajak'): ?>
<div class="card">
<div class="card-header">
<h3>Verifikasi Laporan Pajak</h3>
</div>
<div class="card-body">
<div class="table-responsive">
<table>
<thead>
<tr>
<th>Wajib Pajak</th>
<th>Tanggal Lapor</th>
<th>Jenis Pajak</th>
<th>Total Pajak</th>
<th>Status</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
<?php if (empty($tax_reports)):
?>
<tr><td colspan="6" style="text-align: center;">Tidak ada laporan untuk diverifikasi.</td></tr>
<?php else: ?>
<?php foreach ($tax_reports as $report): ?>
<tr>
<td><?php echo htmlspecialchars($report['taxpayer_name']); ?></td>
<td><?php echo date("d M Y", strtotime($report['created_at'])); ?></td>
<td><?php echo htmlspecialchars($report['tax_type']); ?></td>
<td>Rp <?php echo number_format($report['tax_amount'], 2, ',', '.'); ?></td>
<td><span class="badge status-<?php echo strtolower(htmlspecialchars($report['status'])); ?>"><?php echo htmlspecialchars($report['status']); ?></span></td>
<td class="actions">
<?php if ($report['status'] === 'Pending'): ?>
<a href="verifikasi-laporan.php?id=<?php echo $report['id']; ?>&action=approve" class="btn btn-success btn-sm">Setuju</a>
<a href="verifikasi-laporan.php?id=<?php echo $report['id']; ?>&action=reject" class="btn btn-danger btn-sm">Tolak</a>
<?php else: ?>
-
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
<?php elseif ($userRole === 'Wajib Pajak'): ?>
<div class="card">
<div class="card-header">
<h3>Riwayat Laporan Pajak Anda</h3>
<a href="lapor-pajak.php" class="btn btn-primary">Lapor Pajak Baru</a>
</div>
<div class="card-body">
<div class="table-responsive">
<table>
<thead>
<tr>
<th>Jenis Pajak</th>
<th>Periode</th>
<th>Omzet Kotor</th>
<th>Total Pajak</th>
<th>Status</th>
<th>Tanggal Lapor</th>
</tr>
</thead>
<tbody>
<?php if (empty($tax_reports)): ?>
<tr><td colspan="6" style="text-align: center;">Anda belum memiliki riwayat laporan.</td></tr>
<?php else: ?>
<?php foreach ($tax_reports as $report): ?>
<tr>
<td><?php echo htmlspecialchars($report['tax_type']); ?></td>
<td><?php echo date('F', mktime(0, 0, 0, $report['period_month'], 10)) . ' ' . $report['period_year']; ?></td>
<td>Rp <?php echo number_format($report['gross_revenue'], 2, ',', '.'); ?></td>
<td>Rp <?php echo number_format($report['tax_amount'], 2, ',', '.'); ?></td>
<td><span class="badge status-<?php echo strtolower(htmlspecialchars($report['status'])); ?>"><?php echo htmlspecialchars($report['status']); ?></span></td>
<td><?php echo date("d M Y", strtotime($report['created_at'])); ?></td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
<?php endif; ?>
</section>
</main>
</div>
</body>
</html>

86
db/setup.php Normal file
View File

@ -0,0 +1,86 @@
<?php
require_once 'config.php';
try {
$pdo = db();
// Create users table
$sql_users = "
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
role ENUM('Wajib Pajak', 'Petugas Pajak', 'Pimpinan', 'Super Administrator') NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=INNODB;
";
$pdo->exec($sql_users);
echo "Table 'users' created successfully (if it didn't exist).<br>";
// Inser dummy users
$users = [
[
'name' => 'Admin',
'email' => 'admin@sarmikab.go.id',
'password' => password_hash('admin123', PASSWORD_DEFAULT),
'role' => 'Super Administrator'
],
[
'name' => 'Petugas Pajak',
'email' => 'petugas@sarmikab.go.id',
'password' => password_hash('petugas123', PASSWORD_DEFAULT),
'role' => 'Petugas Pajak'
],
[
'name' => 'Wajib Pajak Contoh',
'email' => 'wajibpajak@example.com',
'password' => password_hash('wajibpajak123', PASSWORD_DEFAULT),
'role' => 'Wajib Pajak'
],
[
'name' => 'Pimpinan',
'email' => 'pimpinan@sarmikab.go.id',
'password' => password_hash('pimpinan123', PASSWORD_DEFAULT),
'role' => 'Pimpinan'
]
];
$stmt = $pdo->prepare("INSERT INTO users (name, email, password, role) VALUES (:name, :email, :password, :role)");
foreach ($users as $user) {
// Check if user exists
$check_stmt = $pdo->prepare("SELECT id FROM users WHERE email = :email");
$check_stmt->execute(['email' => $user['email']]);
if ($check_stmt->fetch()) {
echo "User with email {$user['email']} already exists. Skipping.<br>";
} else {
$stmt->execute($user);
echo "User with email {$user['email']} inserted successfully.<br>";
}
}
// Create tax_reports table
$sql_tax_reports = "
CREATE TABLE IF NOT EXISTS tax_reports (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
tax_type VARCHAR(100) NOT NULL,
period_month INT NOT NULL,
period_year INT NOT NULL,
gross_revenue DECIMAL(15, 2) NOT NULL,
tax_amount DECIMAL(15, 2) NOT NULL,
status ENUM('pending', 'approved', 'rejected') NOT NULL DEFAULT 'pending',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=INNODB;
";
$pdo->exec($sql_tax_reports);
echo "Table 'tax_reports' created successfully (if it didn't exist).<br>";
echo "<hr>Database setup complete!";
} catch (PDOException $e) {
die("DB ERROR: " . $e->getMessage());
}

273
index.php
View File

@ -1,150 +1,135 @@
<?php
declare(strict_types=1);
@ini_set('display_errors', '1');
@error_reporting(E_ALL);
@date_default_timezone_set('UTC');
$phpVersion = PHP_VERSION;
$now = date('Y-m-d H:i:s');
?>
<!doctype html>
<!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>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Si-Apon - Sistem Informasi Pajak Online</title>
<meta name="description" content="Si-Apon streamlines and enhances transparency in tax management for Sarmi Regency's e-government system.">
<meta name="keywords" content="pajak online, sarmi, e-government, pajak daerah, retribusi daerah, lapor pajak, spptd, pbb-p2, pad sarmi">
<meta property="og:title" content="Si-Apon">
<meta property="og:description" content="Si-Apon streamlines and enhances transparency in tax management for Sarmi Regency's e-government system.">
<meta property="og:image" content="https://project-screens.s3.amazonaws.com/screenshots/34683/app-hero-20251005-060858.png">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="https://project-screens.s3.amazonaws.com/screenshots/34683/app-hero-20251005-060858.png">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="assets/css/custom.css">
<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=Lato:wght@400;700&family=Merriweather:wght@400;700&display=swap" rel="stylesheet">
</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>
</div>
</main>
<footer>
Page updated: <?= htmlspecialchars($now) ?> (UTC)
</footer>
<!-- Header -->
<nav class="navbar navbar-expand-lg navbar-light sticky-top">
<div class="container">
<a class="navbar-brand" href="#">Si-Apon</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<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="#hero">Home</a></li>
<li class="nav-item"><a class="nav-link" href="#about">Tentang</a></li>
<li class="nav-item"><a class="nav-link" href="#taxes">Pajak & Retribusi</a></li>
<li class="nav-item"><a class="nav-link" href="#contact">Kontak</a></li>
<a href="login.php" class="btn btn-primary">Login</a>
</ul>
</div>
</div>
</nav>
<!-- Hero Section -->
<section id="hero" class="hero">
<div class="container">
<h1>Selamat Datang di Si-Apon</h1>
<p>Sistem Informasi Pajak Online Kabupaten Sarmi. Modernisasi Pelaporan Pajak untuk Pembangunan Daerah.</p>
<a href="#" class="btn btn-primary btn-lg">Lapor Pajak Sekarang</a>
</div>
</section>
<!-- About Section -->
<section id="about" class="container">
<div class="row align-items-center">
<div class="col-md-6">
<img src="https://picsum.photos/seed/about/800/600" alt="Masyarakat Sarmi tersenyum" class="img-fluid rounded">
</div>
<div class="col-md-6">
<h2>Tentang Si-Apon</h2>
<p>Si-Apon adalah sebuah inovasi digital yang dirancang untuk merevolusi cara pengelolaan pajak dan retribusi daerah di Kabupaten Sarmi. Dengan platform yang terintegrasi dan mudah diakses, kami berkomitmen untuk menyederhanakan proses pelaporan, meningkatkan transparansi, dan mengoptimalkan Pendapatan Asli Daerah (PAD) demi kemajuan bersama.</p>
</div>
</div>
</section>
<!-- Taxes Section -->
<section id="taxes" class="bg-light">
<div class="container">
<div class="text-center mb-5">
<h2>Jenis Pajak & Retribusi</h2>
<p>Berbagai jenis pajak dan retribusi daerah yang dapat dilaporkan melalui Si-Apon.</p>
</div>
<div class="row">
<div class="col-md-4 mb-4">
<div class="card text-center p-4">
<img src="https://picsum.photos/seed/hotel/200/200" alt="Ikon Pajak Hotel" class="rounded-circle mx-auto mb-3" style="width: 100px; height: 100px;">
<h4>Pajak Hotel</h4>
<p>Pelaporan pajak untuk penginapan dan hotel.</p>
</div>
</div>
<div class="col-md-4 mb-4">
<div class="card text-center p-4">
<img src="https://picsum.photos/seed/resto/200/200" alt="Ikon Pajak Restoran" class="rounded-circle mx-auto mb-3" style="width: 100px; height: 100px;">
<h4>Pajak Restoran</h4>
<p>Pelaporan pajak untuk usaha restoran dan rumah makan.</p>
</div>
</div>
<div class="col-md-4 mb-4">
<div class="card text-center p-4">
<img src="https://picsum.photos/seed/pbb/200/200" alt="Ikon PBB" class="rounded-circle mx-auto mb-3" style="width: 100px; height: 100px;">
<h4>PBB-P2</h4>
<p>Pajak Bumi dan Bangunan Perdesaan dan Perkotaan.</p>
</div>
</div>
</div>
</div>
</section>
<!-- Contact Section -->
<section id="contact" class="container">
<div class="text-center mb-5">
<h2>Hubungi Kami</h2>
<p>Punya pertanyaan atau butuh bantuan? Jangan ragu untuk menghubungi kami.</p>
</div>
<div class="row">
<div class="col-md-8 mx-auto">
<form id="contactForm">
<div class="mb-3">
<label for="name" class="form-label">Nama</label>
<input type="text" class="form-control" id="name" required>
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control" id="email" required>
</div>
<div class="mb-3">
<label for="message" class="form-label">Pesan</label>
<textarea class="form-control" id="message" rows="5" required></textarea>
</div>
<button type="submit" class="btn btn-primary">Kirim Pesan</button>
</form>
</div>
</div>
</section>
<!-- Footer -->
<footer class="bg-dark text-white text-center p-4">
<div class="container">
<p>&copy; 2025 Si-Apon Kabupaten Sarmi. All Rights Reserved.</p>
<a href="/privacy.php">Privacy Policy</a>
</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"></script>
</body>
</html>

145
lapor-pajak.php Normal file
View File

@ -0,0 +1,145 @@
<?php
session_start();
require_once 'db/config.php';
// Pastikan pengguna sudah login dan merupakan Wajib Pajak
if (!isset($_SESSION['user_id']) || $_SESSION['user_role'] !== 'Wajib Pajak') {
header("Location: login.php");
exit;
}
$user_id = $_SESSION['user_id'];
$notification = '';
$error = '';
// Daftar jenis pajak yang tersedia
$tax_types = [
'Pajak Hotel',
'Pajak Restoran',
'Pajak Hiburan',
'Pajak Reklame',
'Pajak Parkir',
'Pajak Air Tanah'
];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$tax_type = $_POST['tax_type'] ?? '';
$period_month = $_POST['period_month'] ?? '';
$period_year = $_POST['period_year'] ?? '';
$gross_revenue = $_POST['gross_revenue'] ?? '';
// Validasi sederhana
if (empty($tax_type) || empty($period_month) || empty($period_year) || empty($gross_revenue)) {
$error = 'Semua field wajib diisi.';
} elseif (!is_numeric($gross_revenue) || $gross_revenue < 0) {
$error = 'Omzet kotor harus berupa angka positif.';
} else {
try {
// Asumsi tarif pajak 10% untuk semua jenis
$tax_rate = 0.10;
$tax_amount = (float)$gross_revenue * $tax_rate;
$pdo = db();
$stmt = $pdo->prepare(
"INSERT INTO tax_reports (user_id, tax_type, period_month, period_year, gross_revenue, tax_amount)
VALUES (:user_id, :tax_type, :period_month, :period_year, :gross_revenue, :tax_amount)"
);
$stmt->execute([
':user_id' => $user_id,
':tax_type' => $tax_type,
':period_month' => $period_month,
':period_year' => $period_year,
':gross_revenue' => $gross_revenue,
':tax_amount' => $tax_amount
]);
$notification = 'Laporan pajak Anda telah berhasil diserahkan. Tarif pajak yang dikenakan adalah 10%.';
} catch (PDOException $e) {
$error = "Gagal menyimpan laporan: " . $e->getMessage();
}
}
}
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lapor Pajak - Si-Apon</title>
<link href="https://fonts.googleapis.com/css2?family=Merriweather:wght@700&family=Lato:wght@400;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="assets/css/custom.css">
</head>
<body>
<div class="dashboard-container">
<aside class="sidebar">
<div class="sidebar-header">
<a href="index.php" class="logo">Si-Apon</a>
</div>
<nav class="sidebar-nav">
<a href="dashboard.php">Dashboard</a>
<a href="lapor-pajak.php" class="active">Lapor Pajak</a>
<a href="logout.php">Logout</a>
</nav>
</aside>
<main class="main-content">
<header class="main-header">
<h1>Formulir Pelaporan Pajak</h1>
<div class="user-info">
<span><?php echo htmlspecialchars($_SESSION['user_name']); ?></span>
<span class="role-badge"><?php echo htmlspecialchars($_SESSION['user_role']); ?></span>
</div>
</header>
<section class="content-section">
<div class="card form-card">
<div class="card-body">
<?php if ($notification): ?>
<div class="alert alert-success"><?php echo $notification; ?></div>
<?php endif; ?>
<?php if ($error): ?>
<div class="alert alert-danger"><?php echo $error; ?></div>
<?php endif; ?>
<form action="lapor-pajak.php" method="POST">
<div class="form-group">
<label for="tax_type">Jenis Pajak</label>
<select id="tax_type" name="tax_type" required>
<option value="" disabled selected>-- Pilih Jenis Pajak --</option>
<?php foreach ($tax_types as $type): ?>
<option value="<?php echo htmlspecialchars($type); ?>"><?php echo htmlspecialchars($type); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="form-group">
<label for="period_month">Periode Pajak</label>
<div class="period-group">
<select id="period_month" name="period_month" required>
<option value="" disabled selected>Bulan</option>
<?php for ($i = 1; $i <= 12; $i++): ?>
<option value="<?php echo $i; ?>"><?php echo date('F', mktime(0, 0, 0, $i, 10)); ?></option>
<?php endfor; ?>
</select>
<select id="period_year" name="period_year" required>
<option value="" disabled selected>Tahun</option>
<?php for ($i = date('Y'); $i >= date('Y') - 5; $i--): ?>
<option value="<?php echo $i; ?>"><?php echo $i; ?></option>
<?php endfor; ?>
</select>
</div>
</div>
<div class="form-group">
<label for="gross_revenue">Total Omzet Kotor (Rupiah)</label>
<input type="number" id="gross_revenue" name="gross_revenue" placeholder="Contoh: 5000000" required>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary btn-block">Kirim Laporan</button>
</div>
</form>
</div>
</div>
</section>
</main>
</div>
</body>
</html>

96
login.php Normal file
View File

@ -0,0 +1,96 @@
<?php
session_start();
require_once 'db/config.php';
$error_message = '';
$success_message = '';
// Check for success message from registration
if (isset($_SESSION['success_message'])) {
$success_message = $_SESSION['success_message'];
unset($_SESSION['success_message']);
}
// Redirect if already logged in
if (isset($_SESSION['user_id'])) {
header("Location: dashboard.php");
exit();
}
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$email = $_POST['email'] ?? '';
$password = $_POST['password'] ?? '';
if (empty($email) || empty($password)) {
$error_message = "Email dan password tidak boleh kosong.";
} else {
try {
$pdo = db();
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = :email");
$stmt->execute(['email' => $email]);
$user = $stmt->fetch();
if ($user && password_verify($password, $user['password'])) {
// Password is correct, start session
$_SESSION['user_id'] = $user['id'];
$_SESSION['user_name'] = $user['name'];
$_SESSION['user_role'] = $user['role'];
header("Location: dashboard.php");
exit();
} else {
$error_message = "Email atau password salah.";
}
} catch (PDOException $e) {
$error_message = "Terjadi kesalahan koneksi database.";
// For development: error_log($e->getMessage());
}
}
}
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login - Si-Apon</title>
<link href="https://fonts.googleapis.com/css2?family=Merriweather:wght@700&family=Lato:wght@400;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
</head>
<body>
<div class="login-container">
<div class="login-box">
<div class="login-header">
<a href="index.php" class="logo-link"><h2>Si-Apon</h2></a>
<p>Silakan masuk untuk melanjutkan.</p>
</div>
<?php if (!empty($error_message)): ?>
<div class="alert alert-danger"><?php echo htmlspecialchars($error_message); ?></div>
<?php endif; ?>
<?php if (!empty($success_message)): ?>
<div class="alert alert-success"><?php echo htmlspecialchars($success_message); ?></div>
<?php endif; ?>
<form action="login.php" method="post" class="login-form">
<div class="form-group">
<label for="email">Email</label>
<input type="email" id="email" name="email" required>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" id="password" name="password" required>
</div>
<div class="form-group">
<button type="submit" class="btn-login">Login</button>
</div>
</form>
<div class="login-footer">
<p>Belum punya akun? <a href="register.php">Daftar di sini</a></p>
<p><a href="#">Lupa Password?</a></p>
</div>
</div>
</div>
</body>
</html>

22
logout.php Normal file
View File

@ -0,0 +1,22 @@
<?php
session_start();
// Unset all of the session variables.
$_SESSION = array();
// If it's desired to kill the session, also delete the session cookie.
// Note: This will destroy the session, and not just the session data!
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
}
// Finally, destroy the session.
session_destroy();
// Redirect to login page
header("Location: login.php");
exit();

17
privacy.php Normal file
View File

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Privacy Policy - Si-Apon</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="assets/css/custom.css">
</head>
<body>
<div class="container mt-5">
<h1>Privacy Policy</h1>
<p>This is a placeholder for the privacy policy.</p>
<a href="/">Go back to Home</a>
</div>
</body>
</html>

92
register.php Normal file
View File

@ -0,0 +1,92 @@
<?php
session_start();
require_once 'db/config.php';
$error = '';
$success = '';
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$name = trim($_POST['name']);
$email = trim($_POST['email']);
$password = trim($_POST['password']);
$role = 'Wajib Pajak'; // Default role for new registrations
if (empty($name) || empty($email) || empty($password)) {
$error = 'Semua field harus diisi.';
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$error = 'Format email tidak valid.';
} else {
try {
$pdo = db();
// Check if email already exists
$stmt = $pdo->prepare("SELECT id FROM users WHERE email = ?");
$stmt->execute([$email]);
if ($stmt->fetch()) {
$error = 'Email sudah terdaftar.';
} else {
// Hash the password
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
// Insert new user
$stmt = $pdo->prepare("INSERT INTO users (name, email, password, role) VALUES (?, ?, ?, ?)");
if ($stmt->execute([$name, $email, $hashed_password, $role])) {
$_SESSION['success_message'] = "Registrasi berhasil! Silakan login.";
header("Location: login.php");
exit;
} else {
$error = 'Terjadi kesalahan. Gagal mendaftar.';
}
}
} catch (PDOException $e) {
// In production, you should log this error instead of showing it to the user.
$error = "Database error: " . $e->getMessage();
}
}
}
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Registrasi - Si-Apon</title>
<link href="https://fonts.googleapis.com/css2?family=Merriweather:wght@700&family=Lato:wght@400;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
</head>
<body>
<div class="login-container">
<div class="login-box">
<div class="login-header">
<h2>Registrasi Akun</h2>
<p>Buat akun baru untuk memulai.</p>
</div>
<?php if ($error): ?>
<div class="alert alert-danger"><?php echo htmlspecialchars($error); ?></div>
<?php endif; ?>
<form action="register.php" method="post" class="login-form">
<div class="form-group">
<label for="name">Nama Lengkap</label>
<input type="text" id="name" name="name" required>
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" id="email" name="email" required>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" id="password" name="password" required>
</div>
<div class="form-group">
<button type="submit" class="btn-login">Daftar</button>
</div>
</form>
<div class="login-footer">
<p>Sudah punya akun? <a href="login.php">Login di sini</a></p>
</div>
</div>
</div>
</body>
</html>

30
verifikasi-laporan.php Normal file
View File

@ -0,0 +1,30 @@
<?php
session_start();
require_once 'db/config.php';
// Proteksi halaman: hanya untuk Petugas Pajak
if (!isset($_SESSION['user_id']) || $_SESSION['user_role'] !== 'Petugas Pajak') {
header("Location: login.php");
exit();
}
$report_id = $_GET['id'] ?? null;
$action = $_GET['action'] ?? null;
if ($report_id && ($action === 'approve' || $action === 'reject')) {
$new_status = ($action === 'approve') ? 'Approved' : 'Rejected';
try {
$pdo = db();
$stmt = $pdo->prepare("UPDATE tax_reports SET status = :status WHERE id = :id");
$stmt->execute([':status' => $new_status, ':id' => $report_id]);
} catch (PDOException $e) {
// Sebaiknya log error ini di production
die("Database error: " . $e->getMessage());
}
}
// Redirect kembali ke dashboard
header("Location: dashboard.php");
exit();
?>