diff --git a/assets/css/custom.css b/assets/css/custom.css index e0187d8..004c0c6 100644 --- a/assets/css/custom.css +++ b/assets/css/custom.css @@ -904,3 +904,427 @@ textarea:focus { grid-template-columns: 44px minmax(72px, 1fr) 44px; } } + +.diagram-showcase, +.actor-panel, +.documentation-note, +.code-panel { + background: var(--surface); + border: 1px solid var(--line); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-sm); +} + +.documentation-note { + padding: 1rem 1.15rem; + background: linear-gradient(180deg, #ffffff 0%, #f8f7f4 100%); +} + +.documentation-note strong { + display: block; + margin-bottom: 0.35rem; +} + +.documentation-note p { + margin: 0; + color: var(--muted); + line-height: 1.7; +} + +.diagram-showcase { + padding: clamp(1rem, 2vw, 1.5rem); + background: linear-gradient(180deg, #fffcf7 0%, #f6f4ef 100%); +} + +.diagram-scroll { + overflow-x: auto; +} + +.diagram-scroll svg { + display: block; + width: 100%; + height: auto; + min-width: 960px; +} + +.diagram-boundary { + fill: rgba(255, 255, 255, 0.92); + stroke: #2b2927; + stroke-width: 2; +} + +.diagram-node { + fill: #ffffff; + stroke: #2b2927; + stroke-width: 2.25; +} + +.diagram-connector { + fill: none; + stroke: #a8a29e; + stroke-width: 2; + stroke-linecap: round; +} + +.diagram-actor { + fill: none; + stroke: #2b2927; + stroke-width: 2.75; + stroke-linecap: round; +} + +.diagram-title { + font: 700 24px 'Inter', sans-serif; + fill: #171717; +} + +.diagram-actor-label, +.diagram-node-label { + font: 600 18px 'Inter', sans-serif; + fill: #171717; +} + +.diagram-node-label--small, +.diagram-boundary-label { + font: 500 16px 'Inter', sans-serif; + fill: #57534e; +} + +.actor-panel { + padding: 1.4rem; + height: 100%; +} + +.actor-panel__head { + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; + margin-bottom: 1rem; +} + +.actor-badge { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 5rem; + padding: 0.45rem 0.8rem; + border-radius: 999px; + background: var(--accent-soft); + border: 1px solid var(--line); + font-size: 0.8rem; + font-weight: 700; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.actor-panel h2, +.actor-panel h3 { + font-size: 1.2rem; + margin: 0; +} + +.actor-panel p { + color: var(--muted); + line-height: 1.7; +} + +.usecase-list { + list-style: none; + padding: 0; + margin: 1rem 0 0; + display: grid; + gap: 0.75rem; +} + +.usecase-list li { + display: flex; + gap: 0.8rem; + align-items: flex-start; + padding: 0.9rem 1rem; + border: 1px solid var(--line); + border-radius: var(--radius-md); + background: var(--surface-alt); +} + +.usecase-list span { + display: inline-flex; + align-items: center; + justify-content: center; + width: 1.8rem; + height: 1.8rem; + flex-shrink: 0; + border-radius: 999px; + background: var(--surface); + border: 1px solid var(--line); + font-size: 0.8rem; + font-weight: 700; +} + +.code-panel { + overflow: hidden; +} + +.code-panel summary { + cursor: pointer; + padding: 1rem 1.15rem; + font-weight: 600; + list-style: none; +} + +.code-panel summary::-webkit-details-marker { + display: none; +} + +.code-panel pre { + margin: 0; + padding: 0 1.15rem 1.15rem; + white-space: pre-wrap; + word-break: break-word; + font-size: 0.92rem; + line-height: 1.65; + color: var(--text); + background: transparent; +} + +.code-panel code { + font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', monospace; +} + + +.payment-info-card, +.auth-side-card, +.auth-panel, +.account-stat { + background: var(--surface); + border: 1px solid var(--line); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-sm); +} + +.payment-info-card { + padding: 1.35rem; + background: linear-gradient(180deg, #ffffff 0%, #f8f7f4 100%); +} + +.payment-info-card__label { + display: inline-flex; + align-items: center; + padding: 0.4rem 0.7rem; + margin-bottom: 0.85rem; + border-radius: 999px; + background: var(--accent-soft); + color: var(--text); + font-size: 0.8rem; + font-weight: 700; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.payment-info-card__copy, +.payment-info-card__instruction { + color: var(--muted); + line-height: 1.7; +} + +.payment-info-card__instruction { + padding-top: 0.85rem; + margin-top: 0.85rem; + border-top: 1px solid var(--line); +} + +.contact-panel { + height: 100%; +} + +.contact-checklist { + display: grid; + gap: 0.85rem; +} + +.contact-checklist__item { + display: grid; + gap: 0.25rem; + padding: 0.95rem 1rem; + border: 1px solid var(--line); + border-radius: var(--radius-md); + background: var(--surface-alt); +} + +.contact-checklist__item span { + color: var(--muted); + line-height: 1.65; +} + +.auth-sidebar { + display: grid; + gap: 1rem; + position: sticky; + top: 6rem; +} + +.auth-side-card { + padding: 1.25rem; +} + +.sidebar-link-list { + list-style: none; + padding: 0; + margin: 0; + display: grid; + gap: 0.75rem; +} + +.sidebar-link-list li a { + display: block; + padding: 0.95rem 1rem; + border: 1px solid var(--line); + border-radius: var(--radius-md); + background: var(--surface-alt); + transition: all 0.2s ease; +} + +.sidebar-link-list li a:hover { + border-color: var(--text); + background: var(--surface); + transform: translateY(-1px); +} + +.sidebar-link-list strong { + display: block; + margin-bottom: 0.2rem; +} + +.sidebar-link-list span { + display: block; + color: var(--muted); + font-size: 0.9rem; + line-height: 1.6; +} + +.sidebar-metric { + font-size: clamp(2.1rem, 4vw, 2.8rem); + line-height: 1; + font-weight: 800; + letter-spacing: -0.05em; + margin: 0.3rem 0 0.75rem; +} + +.auth-shell { + padding: clamp(1.2rem, 2vw, 2rem); +} + +.auth-toggle { + display: inline-flex; + gap: 0.4rem; + padding: 0.35rem; + border: 1px solid var(--line); + border-radius: 999px; + background: var(--surface-alt); +} + +.toggle-pill { + display: inline-flex; + align-items: center; + justify-content: center; + padding: 0.65rem 1rem; + border-radius: 999px; + color: var(--muted); + font-weight: 600; + transition: all 0.2s ease; +} + +.toggle-pill:hover, +.toggle-pill.is-active { + color: var(--text); + background: var(--surface); + box-shadow: var(--shadow-sm); +} + +.auth-panel { + display: flex; + flex-direction: column; + gap: 0.75rem; + padding: 1.35rem; + height: 100%; +} + +.auth-panel--active { + border-color: var(--line-strong); + box-shadow: inset 0 0 0 1px rgba(23, 23, 23, 0.08), var(--shadow-sm); +} + +.auth-panel__head { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 1rem; +} + +.auth-note { + margin-top: 1rem; + color: var(--muted); +} + +.auth-note a { + text-decoration: underline; + text-underline-offset: 0.15em; +} + +.auth-state-chip { + display: inline-flex; + align-items: center; + justify-content: center; + width: fit-content; + padding: 0.45rem 0.75rem; + margin-bottom: 0.8rem; + border-radius: 999px; + background: #ecfdf3; + border: 1px solid #bbf7d0; + color: #166534; + font-size: 0.82rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.08em; +} + +.account-stat { + padding: 1rem 1.1rem; + height: 100%; + background: linear-gradient(180deg, #ffffff 0%, #f8f7f4 100%); +} + +.account-stat__label { + display: block; + margin-bottom: 0.35rem; + color: var(--muted); + font-size: 0.78rem; + text-transform: uppercase; + letter-spacing: 0.08em; +} + +@media (max-width: 991.98px) { + .auth-sidebar { + position: static; + } +} + +@media (max-width: 767.98px) { + .auth-shell, + .auth-panel, + .auth-side-card, + .payment-info-card, + .account-stat { + padding: 1rem; + } + + .auth-toggle { + display: flex; + width: 100%; + } + + .toggle-pill { + flex: 1; + text-align: center; + } +} diff --git a/assets/pasted-20260526-080054-2f870e73.png b/assets/pasted-20260526-080054-2f870e73.png new file mode 100644 index 0000000..cdee8da Binary files /dev/null and b/assets/pasted-20260526-080054-2f870e73.png differ diff --git a/assets/pasted-20260526-080630-6e52341a.png b/assets/pasted-20260526-080630-6e52341a.png new file mode 100644 index 0000000..0db1c30 Binary files /dev/null and b/assets/pasted-20260526-080630-6e52341a.png differ diff --git a/auth.php b/auth.php new file mode 100644 index 0000000..c1b6085 --- /dev/null +++ b/auth.php @@ -0,0 +1,239 @@ + '']; +$registerForm = ['full_name' => '', 'email' => '']; +$loginErrors = []; +$registerErrors = []; +$loginMessage = ''; +$registerMessage = ''; + +if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST') { + $action = (string)($_POST['action'] ?? ''); + + if ($action === 'login') { + $result = store_login_user($_POST); + if (!empty($result['success'])) { + store_flash('success', (string)($result['message'] ?? 'Login berhasil.')); + header('Location: ' . $redirectTo); + exit; + } + + $mode = 'login'; + $loginForm = $result['form'] ?? $loginForm; + $loginErrors = $result['errors'] ?? []; + $loginMessage = (string)($result['message'] ?? 'Login belum berhasil diproses.'); + } + + if ($action === 'register') { + $result = store_register_user($_POST); + if (!empty($result['success'])) { + store_flash('success', (string)($result['message'] ?? 'Akun berhasil dibuat.')); + header('Location: ' . $redirectTo); + exit; + } + + $mode = 'register'; + $registerForm = $result['form'] ?? $registerForm; + $registerErrors = $result['errors'] ?? []; + $registerMessage = (string)($result['message'] ?? 'Pendaftaran belum berhasil diproses.'); + } +} + +$currentUser = store_current_user(); +$summary = store_cart_summary(); +$categories = store_categories(); +$accountTitle = $currentUser ? 'Akun Saya' : 'Login / Register'; +$accountDescription = $currentUser + ? 'Ringkasan akun user untuk melanjutkan belanja, checkout, dan melacak pesanan.' + : 'Halaman login dan registrasi user untuk masuk ke sistem menggunakan email dan password.'; + +store_page_start($accountTitle, $accountDescription, ['noindex' => true]); +?> +
+
+ Login User +

+ +

+

+ +

+
+ +
+
+ +
+ +
+ +
+
Login aktif
+

Halo, .

+

Akun Anda sudah tersimpan di sesi browser ini dan siap digunakan untuk melanjutkan aktivitas belanja.

+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ + +
+ +
+
+ Login + Register +
+ +
+
+
+
+
+
Login User
+

Masuk dengan email dan password

+
+
+

Gunakan akun yang sudah terdaftar untuk mengakses alur pemesanan dengan lebih cepat.

+ + + + + +
+ + +
+ + +
+
+
+ + +
+
+ +
+ +

Belum punya akun? Buat akun sekarang.

+
+
+
+
+
+
+
Register
+

Daftarkan akun pengguna

+
+
+

Setelah registrasi berhasil, akun akan langsung aktif pada sesi browser ini.

+ + + + + +
+ + +
+ + +
+
+
+ + +
+
+
+ + +
+
+
+ + +
+
+ +
+
+
+
+
+ +
+
+
+ diff --git a/checkout.php b/checkout.php index d6f7069..f5d6e02 100644 --- a/checkout.php +++ b/checkout.php @@ -12,6 +12,7 @@ if (!$summary['lines']) { $formData = store_checkout_defaults(); $errors = []; +$currentUser = store_current_user(); if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST') { $result = store_create_order($_POST); @@ -34,6 +35,12 @@ store_page_start('Checkout', 'Lengkapi data pelanggan, alamat, dan metode pembay

Status awal pesanan adalah Menunggu Pembayaran. Instruksi pembayaran akan tampil setelah order berhasil dibuat.

+ + + +