From c03cf59f86748036ff7f5e9f2f52900dfd8880ea Mon Sep 17 00:00:00 2001 From: kediritechnopark Date: Fri, 22 Aug 2025 18:27:47 +0700 Subject: [PATCH] ok --- package-lock.json | 54 ++ package.json | 1 + src/App.js | 1034 ++++++++++------------------------- src/LandingPage.js | 409 ++++++++++++++ src/helpers/formatRupiah.js | 8 + src/index.css | 643 ++-------------------- tailwind.config.js | 17 +- 7 files changed, 806 insertions(+), 1360 deletions(-) create mode 100644 src/LandingPage.js create mode 100644 src/helpers/formatRupiah.js diff --git a/package-lock.json b/package-lock.json index 40d6bfa..2d2417e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "@testing-library/user-event": "^13.5.0", "react": "^19.1.1", "react-dom": "^19.1.1", + "react-router-dom": "^7.6.2", "react-scripts": "5.0.1", "web-vitals": "^2.1.4" }, @@ -12866,6 +12867,53 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.8.1.tgz", + "integrity": "sha512-5cy/M8DHcG51/KUIka1nfZ2QeylS4PJRs6TT8I4PF5axVsI5JUxp0hC0NZ/AEEj8Vw7xsEoD7L/6FY+zoYaOGA==", + "license": "MIT", + "dependencies": { + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-router-dom": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.8.1.tgz", + "integrity": "sha512-NkgBCF3sVgCiAWIlSt89GR2PLaksMpoo3HDCorpRfnCEfdtRPLiuTf+CNXvqZMI5SJLZCLpVCvcZrTdtGW64xQ==", + "license": "MIT", + "dependencies": { + "react-router": "7.8.1" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/react-router/node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/react-scripts": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", @@ -13703,6 +13751,12 @@ "node": ">= 0.8.0" } }, + "node_modules/set-cookie-parser": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", + "license": "MIT" + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", diff --git a/package.json b/package.json index fdfb489..bc31586 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "@testing-library/user-event": "^13.5.0", "react": "^19.1.1", "react-dom": "^19.1.1", + "react-router-dom": "^7.6.2", "react-scripts": "5.0.1", "web-vitals": "^2.1.4" }, diff --git a/src/App.js b/src/App.js index c1cba04..d5c17e3 100644 --- a/src/App.js +++ b/src/App.js @@ -1,767 +1,307 @@ -import React, { useState, useEffect, useRef } from 'react'; -import './index.css'; // Pastikan untuk mengimpor file CSS Anda +import { useState, useEffect } from 'react'; +import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; +import LandingPage from './LandingPage'; -function App() { - // State untuk mengontrol tampilan: 'landing' atau 'dashboard' - const [view, setView] = useState('landing'); - // State untuk modal login/register - const [isAuthModalOpen, setAuthModalOpen] = useState(false); - const [authForm, setAuthForm] = useState('login'); // 'login' atau 'register' - // State untuk bagian aktif di dashboard - const [activeDashboardSection, setActiveDashboardSection] = useState('chatbot'); - - // State untuk fungsionalitas Chatbot - const [messages, setMessages] = useState([ - { sender: 'bot', text: 'Halo! Ada yang bisa saya bantu hari ini?' } - ]); - const [chatInput, setChatInput] = useState(''); - const [isChatLoading, setChatLoading] = useState(false); - const chatMessagesEndRef = useRef(null); +const Dashboard = () => { + const [organizations, setOrganizations] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); - // State untuk fungsionalitas Image Generation - const [imagePrompt, setImagePrompt] = useState(''); - const [generatedImageUrl, setGeneratedImageUrl] = useState(''); - const [isImageLoading, setImageLoading] = useState(false); + // Fungsi untuk membuat slug dari nama organisasi + const makeSlug = (name) => + name.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, ""); - // State untuk koneksi media sosial di profil - const [socialConnections, setSocialConnections] = useState({ - twitter: false, - instagram: false, - }); - - // Fungsi untuk scroll otomatis ke pesan terbaru - const scrollToBottom = () => { - chatMessagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); - }; - - useEffect(() => { - if (view === 'dashboard' && activeDashboardSection === 'chatbot') { - scrollToBottom(); - } - }, [messages, view, activeDashboardSection]); - - - // --- Fungsi Handler --- - - const showDashboard = () => { - setAuthModalOpen(false); - setView('dashboard'); - }; - - const showLanding = () => { - setView('landing'); - }; - - const handleLogin = (e) => { - e.preventDefault(); - // Logika login simulasi - const email = e.target.loginEmail.value; - const password = e.target.loginPassword.value; - if (email === "user@example.com" && password === "password123") { - alert("Login berhasil!"); - showDashboard(); - } else { - alert("Email atau kata sandi salah."); - } - }; - - const handleRegister = (e) => { - e.preventDefault(); - // Logika registrasi simulasi - const password = e.target.registerPassword.value; - const confirmPassword = e.target.confirmPassword.value; - if (password !== confirmPassword) { - alert("Kata sandi tidak cocok."); - return; - } - alert("Registrasi berhasil! Silakan masuk."); - setAuthForm('login'); - }; - - const handleSendMessage = async () => { - const userMessage = chatInput.trim(); - if (userMessage === "") return; - - // Tambahkan pesan pengguna ke state - setMessages(prev => [...prev, { sender: 'user', text: userMessage }]); - setChatInput(''); - setChatLoading(true); - - // Simulasi panggilan API ke Gemini - setTimeout(() => { - // Ini adalah respons palsu. Ganti dengan panggilan fetch API asli Anda. - const botResponse = `Ini adalah respons AI untuk: "${userMessage}". Dalam aplikasi nyata, ini akan datang dari API.`; - setMessages(prev => [...prev, { sender: 'bot', text: botResponse }]); - setChatLoading(false); - }, 1500); - }; - - const handleGenerateImage = async () => { - if (imagePrompt.trim() === "") { - alert("Mohon masukkan deskripsi gambar."); - return; - } - setImageLoading(true); - setGeneratedImageUrl(''); - - // Simulasi panggilan API pembuatan gambar - setTimeout(() => { - // Ganti URL ini dengan hasil dari API Anda - const mockImageUrl = `https://placehold.co/512x512/142F32/E5FFCC?text=Hasil:+${encodeURIComponent(imagePrompt.substring(0, 20))}`; - setGeneratedImageUrl(mockImageUrl); - setImageLoading(false); - }, 2000); - }; - - const handleConnectSocial = (platform) => { - setSocialConnections(prev => ({ - ...prev, - [platform]: !prev[platform] - })); - }; - - const handleLogout = () => { - // Logika logout - showLanding(); - alert("Anda telah berhasil keluar."); - }; - - // --- Komponen-Komponen Kecil --- - - const Header = () => ( -
-
- Logo Maragen - Maragen -
- - - -
- ); - - const LandingPage = () => ( -
- {/* Hero Section */} -
-
-

- Masa Depan Otomatisasi dengan Teknologi Terbaru -

-

- Ahli teknologi untuk meningkatkan bisnis Anda. Mari bawa bisnis Anda lebih jauh. -

-
- - -
-
- - - - - - 5.0 - dari 80+ ulasan -
-
- - {/* Stat Cards Grid */} -
-
- Otomatisasi Visual -
-

Visual Otomatisasi

-
-
- -
-
- -

100+

-
-

Klien & Mitra Terhormat Kami

-
- -
-
- -

1951+

-
-

Total Proyek ↑126 bulan ini

-
- -
-
- -

6+

-
-

Tahun Layanan Khusus

-
-
-
- - {/* Bottom Section (Layanan Otomatisasi) */} -
-
-

- Layanan Otomatisasi yang Efisien dan Terintegrasi -

-

- Sederhanakan operasi Anda dengan layanan berkualitas dan berorientasi efisiensi. -

- -
-
-
- - -
-

Alur Kerja Otomatis

-

- Detail tentang proses otomatisasi, kemampuan integrasi, dan jenis alur kerja yang didukung. -

-
-
-
- - -
-

Kustomisasi Solusi

-

- Pembuatan solusi otomatisasi khusus dengan opsi desain dan kustomisasi. -

-
-
-
- - -
-

Pemantauan & Analisis

-

- Prosedur dan sistem untuk memastikan kualitas output otomatisasi yang tinggi. -

-
-
-
-
- - {/* Key Benefits Section */} -
-
-
- Total Proyek - ↑56% -
-
-
- Selesai - 10% -
-
-
-
-
- Sedang Berjalan - 13% -
-
-
-
-
- Ditolak - 11% -
-
-
-
-
-
-
- -

1951+

-
-

Peningkatan ↑126 bulan ini

-
-
- -
-

- Manfaat Utama Sistem Kami untuk Efisiensi Bisnis Anda -

-

- Sistem kami meningkatkan produktivitas, mengurangi biaya, dan mendorong pertumbuhan bisnis. -

- -
-
- -
-

Meningkatkan Kualitas dengan Teknologi

-

- Dengan teknologi canggih, kami membantu Anda mencapai kualitas produk terbaik. Pelajari bagaimana kami dapat meningkatkan standar Anda. -

-
-
-
- -
-

Optimasi Proses Produksi

-

- Meningkatkan efisiensi dan produktivitas pabrik dengan solusi inovatif kami. Lihat bagaimana teknologi terbaru dapat memaksimalkan output Anda. -

-
-
-
- -
-

Produksi Berbasis AI

-

- Manfaatkan kekuatan AI untuk mengubah proses manufaktur Anda, mencapai hasil yang lebih cepat dan efektif. -

-
-
-
-
-
- - {/* Tailored Plans Section */} -
-
-

- Paket yang Disesuaikan untuk Skala Bisnis Anda -

-

- Harga fleksibel untuk setiap ukuran bisnis. -

-
- -
-
-

Starter

-

- Paket ini menawarkan fitur dasar yang Anda butuhkan untuk memulai. -

-
- $39 - / bulan -
- -
-
Produksi hingga 10.000 unit per bulan
-
Dukungan teknis 24/7
-
Akses ke dasbor produksi
-
Pengaturan awal
-
-
- -
-

Enterprise

-

- Paket ini menyediakan akses penuh ke semua fitur premium. -

-
- $99 - / bulan -
- -
-
Unit produksi tak terbatas
-
Manajer akun khusus
-
Solusi manufaktur yang disesuaikan
-
Optimalisasi produksi prediktif
-
-
-
-
- - {/* Seamless Integrations Section */} -
-
-

- Memberdayakan Perusahaan Top dengan Integrasi Tanpa Batas -

-

- Rasakan koneksi tanpa batas dengan solusi inovatif kami, dirancang untuk berintegrasi dengan mudah dengan sistem Anda yang ada, meningkatkan produktivitas, dan mendorong bisnis Anda menuju kesuksesan yang lebih besar. -

- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - {/* From Idea to Production Section */} -
-
-

- Dari Ide ke Produksi dalam Hitungan Hari -

-

- Percepat produksi Anda dengan teknologi kami. Kurangi waktu henti dan optimalkan biaya. Dapatkan penawaran spesial sekarang! -

- -
-
- -
-
- ); - - const Footer = () => ( - - ); - - const AuthModal = () => ( -
-
- setAuthModalOpen(false)}>× -

Masuk atau Daftar

- - {authForm === 'login' ? ( - <> -
- - - -
-

- Belum punya akun? { e.preventDefault(); setAuthForm('register'); }} className="text-142F32 font-semibold hover:underline">Daftar di sini -

- - ) : ( - <> -
- - - - -
-

- Sudah punya akun? { e.preventDefault(); setAuthForm('login'); }} className="text-142F32 font-semibold hover:underline">Masuk di sini -

- - )} -
-
- ); - - const Dashboard = () => { - const sidebarItems = [ - { id: 'chatbot', icon: 'fa-comments', label: 'Chatbot' }, - { id: 'imageGen', icon: 'fa-image', label: 'Buat Gambar' }, - { id: 'scheduling', icon: 'fa-calendar-alt', label: 'Penjadwalan' }, - { id: 'monitoring', icon: 'fa-chart-line', label: 'Pemantauan Konten' }, - { id: 'notifications', icon: 'fa-bell', label: 'Notifikasi' }, - { id: 'profile', icon: 'fa-user-circle', label: 'Pengaturan Profil' }, - ]; + useEffect(() => { + async function fetchOrgs() { + try { + const res = await fetch( + "https://auto.apps.kediritechnopark.com/webhook/eo-get-organization" + ); + if (!res.ok) { + throw new Error(`HTTP error! status: ${res.status}`); + } + const data = await res.json(); + if (Array.isArray(data)) { + setOrganizations(data); + } else { + console.warn("API response for organizations was not an array:", data); + setOrganizations([]); + } + } catch (err) { + console.error("Gagal ambil organisasi:", err); + setError("Gagal memuat organisasi. Silakan coba lagi nanti."); + } finally { + setLoading(false); + } + } + fetchOrgs(); + }, []); return ( -
- {/* Sidebar */} - +
+ {/* Header */} +
+ +
- {/* Main Content */} -
- {activeDashboardSection === 'chatbot' && ( -
-

Chatbot AI

-

Ajukan pertanyaan atau mulai percakapan dengan AI kami.

-
-
- {messages.map((msg, index) => ( -
- {msg.text} +
+ {/* Hero Section */} +
+
+

+ Kelola Acara dan Jual Tiket Tanpa Ribet +

+

+ Platform manajemen acara all-in-one untuk konser, seminar, dan workshop Anda. Fokus pada acara, kami urus sisanya. +

+ - ))} -
-
- {isChatLoading &&
Mengetik...
} -
- setChatInput(e.target.value)} - onKeyPress={(e) => e.key === 'Enter' && handleSendMessage()} - autoFocus - /> - -
-
-
- )} - {activeDashboardSection === 'imageGen' && ( -
-

Buat Gambar AI

-

Masukkan deskripsi untuk membuat gambar.

-
- setImagePrompt(e.target.value)} - /> - - {isImageLoading &&
Membuat gambar...
} - {generatedImageUrl && ( -
- Gambar yang Dihasilkan -
- - -
-
- )} -
-
- )} - {activeDashboardSection === 'scheduling' && ( -
-

Penjadwalan Konten

-

Kelola konten yang akan dipublikasikan di masa mendatang.

-
-
    -
  • - Postingan Blog: "Masa Depan Otomatisasi" - 2025-08-15 10:00 AM -
  • -
  • - Gambar AI: "Pemandangan Kota Futuristik" - 2025-08-18 02:30 PM -
  • -
-
- -
- )} - {activeDashboardSection === 'monitoring' && ( -
-

Pemantauan & Analisis Tren

-

Pantau kinerja konten Anda dan temukan tren viral berikutnya.

- -
-

Kinerja Konten Saya

-
-
-

Total Penayangan

-

1.2M

-

↑15% bulan ini

-
-
-

Total Suka

-

89K

-

↑12% bulan ini

-
-
-

Pengikut Baru

-

5,210

-

↑8% bulan ini

+
+ {[ + ['500+', 'Acara Dikelola'], + ['100k+', 'Tiket Terjual'], + ['99%', 'Uptime Server'], + ['24/7', 'Dukungan Pelanggan'], + ].map(([angka, label], idx) => ( +
+

{angka}

+

{label}

+
+ ))}
-
+
-
-

Konten yang Sedang Tren

-
- {/* Konten tren akan diisi oleh data dari API */} -

Fitur ini sedang dalam pengembangan.

-
-
-
- )} - {activeDashboardSection === 'notifications' && ( -
-

Notifikasi

-

Pembaruan terkini tentang akun dan konten Anda.

-
    - {/* Notifikasi akan diisi oleh data dari API */} -
  • Postingan Anda "Masa Depan Otomatisasi" telah dijadwalkan.
  • -
  • Selamat! Anda mendapatkan 50 pengikut baru minggu ini.
  • -
-
- )} - {activeDashboardSection === 'profile' && ( -
-

Pengaturan Profil

-

Kelola informasi akun dan koneksi media sosial Anda.

-
-
- - -
-
- - -
-
-

Autentikasi Media Sosial

-
-
- -
-

Twitter

- - {socialConnections.twitter ? 'Terhubung' : 'Belum Terhubung'} - + {/* Fitur */} +
+
+

Fitur Unggulan untuk Sukseskan Acara Anda

+

Dari pembuatan halaman hingga laporan penjualan, semua ada di sini.

+
+ {[ + ['Manajemen Acara Mudah', 'Buat halaman acara yang menarik dengan branding kustom hanya dalam beberapa menit.'], + ['Gerbang Pembayaran Aman', 'Terima pembayaran dari berbagai metode dengan aman dan pencairan dana yang cepat.'], + ['Laporan & Analitik', 'Pantau penjualan tiket secara real-time dan dapatkan wawasan dari data pengunjung.'], + ].map(([judul, deskripsi], idx) => ( +
+

{judul}

+

{deskripsi}

-
- -
-
-
- -
-

Instagram

- - {socialConnections.instagram ? 'Terhubung' : 'Belum Terhubung'} - -
-
- + ))}
-
- - +
+ + {/* Section Screenshot + Fitur */} +
+
+
+ Dashboard Screenshot +
+
+

Semua yang Anda Butuhkan dalam Satu Platform

+

Sederhanakan alur kerja Anda dengan alat yang terintegrasi penuh.

+
    + {[ + ['Check-in Cepat dengan QR Code:', 'Kurangi antrean di lokasi dengan pemindaian tiket digital yang instan.'], + ['Promosi & Pemasaran:', 'Jangkau audiens yang lebih luas dengan alat pemasaran email dan media sosial bawaan.'], + ['Halaman Acara Kustom:', 'Tampilkan identitas brand Anda dengan halaman acara yang bisa disesuaikan sepenuhnya.'], + ].map(([judul, detail], idx) => ( +
  • + + + + {judul} {detail} +
  • + ))} +
+
+
+
+ + {/* Harga */} +
+
+

Paket Harga yang Fleksibel

+

Pilih paket yang paling sesuai dengan skala acara Anda. Tanpa biaya tersembunyi.

+
+ {/* Starter */} +
+

Starter

+

Ideal untuk acara komunitas dan skala kecil.

+

+ $29 + /bulan +

+ + Pilih Starter + +
    + {['1 Acara Aktif', 'Hingga 100 Peserta', 'Biaya Transaksi 2.5%', 'Laporan Dasar'].map((item, i) => ( +
  • + + + + {item} +
  • + ))} +
+
+ + {/* Pro */} +
+ PALING POPULER +

Pro

+

Untuk event organizer profesional dan bisnis.

+

+ $79 + /bulan +

+ + Pilih Pro + +
    + {[ + 'Acara Tanpa Batas', + 'Peserta Tanpa Batas', + 'Biaya Transaksi 1%', + 'Laporan Lengkap & Analitik', + 'Dukungan Prioritas' + ].map((item, i) => ( +
  • + + + + {item} +
  • + ))} +
+
+
+
+
+
+
+

+ Partner +

+ + {loading ? ( +

Memuat organisasi...

+ ) : error ? ( +

{error}

+ ) : organizations.length === 0 ? ( +

Belum ada organisasi tersedia.

+ ) : ( +
+ {/* Marquee content */} +
+ {[...organizations, ...organizations].map((org, index) => ( + + {org.nama_organization} + + ))} +
+ + {/* Fading edges */} +
+
+
+ )} +
+
+ + + {/* CTA */} +
+
+

Siap Menggelar Acara Spektakuler Anda?

+

Mulai dalam hitungan menit. Tidak perlu kartu kredit untuk mencoba.

+ +
+
+
+ + {/* Footer */} +
+
+
+
+

Produk

+
    + {['Fitur', 'Harga', 'Integrasi'].map((item, i) => ( +
  • {item}
  • + ))} +
+
+
+

Perusahaan

+
    + {['Tentang Kami', 'Karir', 'Hubungi Kami'].map((item, i) => ( +
  • {item}
  • + ))} +
+
+
+

Bantuan

+
    + {['Pusat Bantuan', 'Dokumentasi', 'Status Layanan'].map((item, i) => ( +
  • {item}
  • + ))} +
+
+
+
+

© 2025 Tiketify. Semua Hak Cipta Dilindungi.

+
+ {['FB', 'TW', 'IG'].map((sosial, i) => ( + {sosial} + ))} +
- - )} - -
+ +
); - }; - +}; +const App = () => { return ( - <> -
- {view === 'landing' && } - {view === 'dashboard' && } - {isAuthModalOpen && } - + + + } /> + } /> + + ); -} +}; -export default App; \ No newline at end of file +export default App; diff --git a/src/LandingPage.js b/src/LandingPage.js new file mode 100644 index 0000000..5c78c7c --- /dev/null +++ b/src/LandingPage.js @@ -0,0 +1,409 @@ +import React, { useState, useEffect } from "react"; +import { useParams } from "react-router-dom"; +import formatRupiah from './helpers/formatRupiah'; + +export default function App() { + const { organizationId } = useParams(); + const [organization, setOrganization] = useState([]); + const [tickets, setTickets] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + const [isLoggedIn, setIsLoggedIn] = useState(false); + const [showModal, setShowModal] = useState(false); + const [modalTab, setModalTab] = useState("login"); // "login" or "register" + const [selectedTicket, setSelectedTicket] = useState(null); + const [formData, setFormData] = useState({}); + + useEffect(() => { + if (!organizationId) { + setError("Parameter organization tidak ditemukan di URL."); + setLoading(false); + return; + } + + fetch( + `https://auto.apps.kediritechnopark.com/webhook/mayagen/organization?organization=${organizationId}` + ) + .then((res) => { + if (!res.ok) throw new Error("Gagal mengambil data tiket"); + return res.json(); + }) + .then((data) => { + setTickets(data[0].tickets); + setOrganization(data[0]); + setLoading(false); + }) + .catch((err) => { + setError(err.message); + setLoading(false); + }); + }, [organizationId]); + + // Dummy login handler + function handleLogin(e) { + e.preventDefault(); + // Kamu bisa validasi di sini + setIsLoggedIn(true); + } + + // Dummy register handler + function handleRegister(e) { + e.preventDefault(); + // Kamu bisa validasi dan buat user di sini + setIsLoggedIn(true); + } + + // Form tiket submit + function handleSubmitTicket(e) { + e.preventDefault(); + alert(`Form tiket untuk ${selectedTicket.nama_tiket} submitted:\n` + JSON.stringify(formData, null, 2)); + setShowModal(false); + setSelectedTicket(null); + setFormData({}); + } + + // Handle klik beli tiket + function handleBuyClick(ticket) { + if (!isLoggedIn) { + setModalTab("login"); + setShowModal(true); + setSelectedTicket(ticket); + } else { + setSelectedTicket(ticket); + setShowModal(true); + } + } + + // Handle form input change untuk tiket form + function handleFormChange(e) { + const { name, value } = e.target; + setFormData((prev) => ({ ...prev, [name]: value })); + } + + if (loading) return
Loading...
; + if (error) return
Error: {error}
; + + return ( +
+
+ {/* Hero Section */} +
+
+
+
+

+ {organization.nama_organization} +

+

+ {organization.deskripsi} +

+
+
+ + {/* Acara Section */} +
+
+
+

+ Acara Mendatang +

+
+ +
+ {tickets.map((ticket, i) => { + const isSoldOut = ticket.sold_out || false; + + return ( +
+ {isSoldOut && ( +
+ + TIKET HABIS + +
+ )} + Poster Acara +
+

+ {ticket.nama_tiket} +

+
+ 📅 {ticket.tanggal || "Tanggal belum tersedia"} + 📍 {ticket.lokasi || "Lokasi belum tersedia"} +
+

+ {ticket.price === "0.00" ? "Gratis" : formatRupiah(ticket.price)} +

+
+ {isSoldOut ? ( + + ) : ( + + )} +
+
+
+ ); + })} +
+
+
+ + {organization.about && +
+
+
+ Tim SoundVibes Production +
+
+

+ Tentang {organization.nama_organization} +

+

+ Didirikan pada tahun 2020, SoundVibes Production adalah promotor musik + yang berdedikasi untuk menciptakan acara live yang tak terlupakan. + Misi kami adalah menghubungkan penggemar dengan artis favorit mereka + melalui produksi acara yang berkualitas tinggi, aman, dan nyaman. +

+

+ Kami percaya bahwa musik memiliki kekuatan untuk menyatukan, dan + kami bangga menjadi jembatan antara panggung dan penonton. +

+
+
+
+ } +
+ + {/* Footer */} +
+
+

+ {organization.nama_organization} +

+

Ikuti kami untuk update acara terbaru!

+ +

+ Data dalam situs ini mungkin dilindungi hak cipta oleh {organization.nama_organization}. +

+
+
+ + {/* Modal */} + {showModal && ( +
+
+ + + {!isLoggedIn && ( + <> + {/* Tabs */} +
+ + +
+ + {/* Login Form */} + {modalTab === "login" && ( +
+ + + +
+ )} + + {/* Register Form */} + {modalTab === "register" && ( +
+ + + + +
+ )} + + )} + + {/* Jika sudah login, tampilkan form tiket */} + {isLoggedIn && selectedTicket && ( +
+

+ Formulir {selectedTicket.nama_tiket} +

+ {Object.entries(selectedTicket.form).map(([key, type]) => { + if (type === "text") { + return ( +
+ + +
+ ); + } + if (type === "selection") { + // Contoh opsi metode pembayaran (bisa disesuaikan) + const options = [ + "Transfer Bank", + "Kartu Kredit", + "Cash", + "E-Wallet", + ]; + return ( +
+ + +
+ ); + } + return null; + })} + +
+ )} +
+
+ )} +
+ ); +} diff --git a/src/helpers/formatRupiah.js b/src/helpers/formatRupiah.js new file mode 100644 index 0000000..56b7508 --- /dev/null +++ b/src/helpers/formatRupiah.js @@ -0,0 +1,8 @@ +export default function formatRupiah(number) { + return new Intl.NumberFormat('id-ID', { + style: 'currency', + currency: 'IDR', + minimumFractionDigits: 0, + maximumFractionDigits: 0 + }).format(number); +} diff --git a/src/index.css b/src/index.css index 6f9cae4..51cba18 100644 --- a/src/index.css +++ b/src/index.css @@ -1,614 +1,37 @@ -/* Direktif Tailwind */ @tailwind base; @tailwind components; @tailwind utilities; - body { - font-family: 'Manrope', sans-serif; - background-color: #f8fafc; /* Background utama, mirip dengan brand guide */ - color: #282930; /* Teks gelap utama */ - margin: 0; - overflow-x: hidden; /* Mencegah scroll horizontal */ - } - - /* Custom styles for sections and elements */ - .header-bg { - background-color: #ffffff; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); - } - - .hero-section { - background-color: #ffffff; - /* padding: 4rem 2rem; */ - text-align: center; - } - - .stats-grid { - display: grid; - grid-template-columns: repeat(1, minmax(0, 1fr)); /* 1 kolom di layar kecil */ - gap: 1.5rem; - margin-top: 3rem; - } - - @media (min-width: 640px) { /* sm breakpoint */ - .stats-grid { - grid-template-columns: repeat(2, minmax(0, 1fr)); /* 2 kolom di layar sedang */ - } - } - - @media (min-width: 1024px) { /* lg breakpoint */ - .stats-grid { - grid-template-columns: repeat(4, minmax(0, 1fr)); /* 4 kolom di layar besar */ - } - } - - .stat-card { - background-color: #ffffff; - border-radius: 1rem; - text-align: left; - box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); - transition: transform 0.2s ease-in-out; - } - - .stat-card.dark-bg { - background-color: #282930; /* Menggunakan warna gelap dari brand guide */ - color: #e2e8f0; - } - - .stat-card.light-green-bg { - background-color: #E5FFCC; /* Menggunakan warna hijau terang dari brand guide */ - color: #142F32; /* Teks gelap di atas hijau terang */ - } - - .stat-card:hover { - transform: translateY(-5px); - } - - .bottom-section { - background-color: #282930; /* Menggunakan warna gelap dari brand guide */ - padding: 4rem 2rem; - color: #e2e8f0; - text-align: center; - } - - .bottom-grid { - display: grid; - grid-template-columns: repeat(1, minmax(0, 1fr)); /* 1 kolom di layar kecil */ - gap: 1.5rem; - margin-top: 3rem; - } - - @media (min-width: 768px) { /* md breakpoint */ - .bottom-grid { - grid-template-columns: repeat(3, minmax(0, 1fr)); /* 3 kolom di layar sedang */ - } - } - - .bottom-card { - background-color: #142F32; /* Menggunakan warna hijau gelap dari brand guide */ - border-radius: 1rem; - padding: 2rem; - text-align: left; - box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.2), 0 4px 6px -2px rgba(0, 0, 0, 0.1); - transition: transform 0.2s ease-in-out; - } - - .bottom-card:hover { - transform: translateY(-5px); - } - - .button-primary { - background-color: #142F32; /* Menggunakan warna hijau gelap dari brand guide */ - color: white; - transition: all 0.3s ease; - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); - } - - .button-primary:hover { - background-color: #0d1e20; /* Hijau gelap lebih gelap */ - transform: translateY(-2px); - box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15); - } - - .button-secondary { - background-color: transparent; - border: 1px solid #9ca3af; /* Gray border */ - color: #4b5563; /* Dark gray text */ - transition: all 0.3s ease; - } - - .button-secondary:hover { - background-color: #f3f4f6; /* Light gray background */ - transform: translateY(-2px); - } - - .button-sign-up { - background-color: #142F32; /* Menggunakan warna hijau gelap dari brand guide */ - color: white; - transition: all 0.3s ease; - } - - .button-sign-up:hover { - background-color: #0d1e20; /* Hijau gelap lebih gelap */ - } - - /* Responsive image for the first card */ - .card-image { - width: 100%; - height: auto; - border-radius: 0.75rem; /* Sudut membulat untuk gambar */ - object-fit: cover; /* Memastikan gambar menutupi area */ - } - - /* Styles for Key Benefits Section */ - .key-benefits-section { - background-color: #f8fafc; - padding: 4rem 2rem; - text-align: center; - display: flex; - flex-direction: column; - align-items: center; - } - - @media (min-width: 768px) { - .key-benefits-section { - flex-direction: row; - text-align: left; - justify-content: center; - gap: 4rem; - } - } - - .benefits-content { - flex: 1; - max-width: 600px; - } - - .benefits-image-card { - flex: 1; - background-color: #ffffff; - border-radius: 1rem; - padding: 1.5rem; - box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); - margin-top: 2rem; - max-width: 400px; - } - - @media (min-width: 768px) { - .benefits-image-card { - margin-top: 0; - } - } - - .benefit-item { - display: flex; - align-items: flex-start; - margin-bottom: 1rem; - } - - .benefit-item i { - color: #22c55e; /* Hijau centang */ - margin-right: 0.75rem; - font-size: 1.25rem; - margin-top: 0.25rem; - } - - /* Styles for Tailored Plans Section */ - .tailored-plans-section { - background-color: #282930; /* Menggunakan warna gelap dari brand guide */ - padding: 4rem 2rem; - color: #e2e8f0; - text-align: center; - } - - .pricing-grid { - display: grid; - grid-template-columns: repeat(1, minmax(0, 1fr)); - gap: 2rem; - margin-top: 3rem; - max-width: 900px; - margin-left: auto; - margin-right: auto; - } - - @media (min-width: 768px) { - .pricing-grid { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - } - - .pricing-card { - background-color: #142F32; /* Menggunakan warna hijau gelap dari brand guide */ - border-radius: 1rem; - padding: 2.5rem; - text-align: left; - box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.2), 0 4px 6px -2px rgba(0, 0, 0, 0.1); - } - - .pricing-card .price { - font-size: 3rem; - font-weight: 800; - color: #ffffff; - margin-bottom: 0.5rem; - } - - .pricing-card .price-per-month { - color: #9ca3af; - font-size: 1rem; - } - - .pricing-card .feature-list { - margin-top: 1.5rem; - margin-bottom: 2rem; - } - - .pricing-card .feature-item { - display: flex; - align-items: center; - margin-bottom: 0.75rem; - color: #cbd5e0; - } - - .pricing-card .feature-item i { - color: #22c55e; /* Hijau centang */ - margin-right: 0.5rem; - } - - /* New styles for Seamless Integrations Section */ - .integrations-section { - background-color: #f8fafc; - padding: 4rem 2rem; - text-align: center; - display: flex; - flex-direction: column; - align-items: center; - } - - @media (min-width: 768px) { - .integrations-section { - flex-direction: row; - text-align: left; - justify-content: center; - gap: 4rem; - } - } - - .integrations-content { - flex: 1; - max-width: 600px; - } - - .integrations-visual { - flex: 1; - background-color: #E5FFCC; /* Menggunakan warna hijau terang dari brand guide */ - border-radius: 1rem; - padding: 2rem; - margin-top: 2rem; - max-width: 500px; - position: relative; - overflow: hidden; - display: flex; - justify-content: center; - align-items: center; - min-height: 300px; - } - - @media (min-width: 768px) { - .integrations-visual { - margin-top: 0; - } - } - - .integration-icon-grid { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 1.5rem; - width: 100%; - height: 100%; - position: relative; - justify-items: center; - align-items: center; - } - - .integration-icon { - background-color: #ffffff; - border-radius: 50%; - width: 60px; - height: 60px; - display: flex; - justify-content: center; - align-items: center; - box-shadow: 0 5px 10px rgba(0, 0, 0, 0.1); - font-size: 1.5rem; - color: #4a5568; - } - - /* From Idea to Production Section */ - .idea-to-production-section { - background-color: #282930; /* Menggunakan warna gelap dari brand guide */ - padding: 4rem 2rem; - color: #e2e8f0; - text-align: center; - } - - /* Footer Section */ - .footer-section { - background-color: #282930; /* Menggunakan warna gelap dari brand guide */ - padding: 4rem 2rem; - color: #a0aec0; /* Teks abu-abu lebih terang */ - font-size: 0.9rem; - } - - .footer-grid { - display: grid; - grid-template-columns: repeat(1, minmax(0, 1fr)); - gap: 2rem; - } - - @media (min-width: 640px) { - .footer-grid { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - } - - @media (min-width: 1024px) { - .footer-grid { - grid-template-columns: repeat(5, minmax(0, 1fr)); - } - } - - .footer-col h3 { - font-weight: 600; - color: #ffffff; - margin-bottom: 1rem; - } - - .footer-col ul li { - margin-bottom: 0.5rem; - } - - .footer-col ul li a { - color: #a0aec0; - transition: color 0.2s ease; - } - - .footer-col ul li a:hover { - color: #ffffff; - } - - .social-icons a { - color: #a0aec0; - font-size: 1.25rem; - margin-right: 1rem; - transition: color 0.2s ease; - } - - .social-icons a:hover { - color: #ffffff; - } - - /* Modal Styles */ - .modal { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - background-color: rgba(0, 0, 0, 0.7); - display: flex; - justify-content: center; - align-items: center; - z-index: 1000; - opacity: 0; - visibility: hidden; - transition: opacity 0.3s ease, visibility 0.3s ease; - } - - .modal.show { - opacity: 1; - visibility: visible; - } - - .modal-content { - background-color: #ffffff; - padding: 2.5rem; - border-radius: 1rem; - box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2); - max-width: 450px; - width: 90%; - text-align: center; - position: relative; - transform: translateY(-20px); - transition: transform 0.3s ease; - } - - .modal.show .modal-content { - transform: translateY(0); - } - - .close-button { - position: absolute; - top: 1rem; - right: 1rem; - font-size: 1.5rem; - cursor: pointer; - color: #4b5563; - } - - /* Dashboard Styles */ - .dashboard-container { - display: none; /* Hidden by default */ - grid-template-columns: 250px 1fr; /* Sidebar fixed width, content fills */ - min-height: 100vh; - background-color: #f8fafc; - color: #282930; - } - - @media (max-width: 768px) { - .dashboard-container { - grid-template-columns: 1fr; /* Stack on small screens */ - } - .dashboard-sidebar { - width: 100%; - position: relative; - box-shadow: none; - } - } - - .dashboard-sidebar { - background-color: #142F32; /* Hijau gelap */ - color: #E5FFCC; - padding: 2rem 1rem; - display: flex; - flex-direction: column; - align-items: center; - box-shadow: 2px 0 5px rgba(0, 0, 0, 0.1); - } - - .dashboard-sidebar-item { - width: 100%; - padding: 0.75rem 1rem; - margin-bottom: 0.5rem; - border-radius: 0.5rem; - display: flex; - align-items: center; - cursor: pointer; - transition: background-color 0.2s ease, color 0.2s ease; - } - - .dashboard-sidebar-item:hover { - background-color: rgba(229, 255, 204, 0.1); /* Hijau terang transparan */ - color: #E5FFCC; - } - - .dashboard-sidebar-item.active { - background-color: #E5FFCC; - color: #142F32; - font-weight: 600; - } - - .dashboard-main-content { - padding: 2rem; - background-color: #f8fafc; - overflow-y: auto; - } - - .chat-container { - display: flex; - flex-direction: column; - height: calc(100vh - 4rem); /* Adjust for padding */ - background-color: #ffffff; - border-radius: 1rem; - box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05); - overflow: hidden; - } - - .chat-messages { - flex-grow: 1; - padding: 1.5rem; - overflow-y: auto; - display: flex; - flex-direction: column; - gap: 1rem; - } - - .chat-message { - max-width: 80%; - padding: 0.75rem 1rem; - border-radius: 0.75rem; - word-wrap: break-word; - } - - .chat-message.user { - background-color: #E5FFCC; - align-self: flex-end; - color: #142F32; - } - - .chat-message.bot { - background-color: #f1f5f9; - align-self: flex-start; - color: #282930; - } - - .chat-input-area { - display: flex; - padding: 1rem; - border-top: 1px solid #e2e8f0; - background-color: #ffffff; - } - - .chat-input-area input { - flex-grow: 1; - padding: 0.75rem 1rem; - border: 1px solid #cbd5e0; - border-radius: 0.5rem; - margin-right: 0.75rem; - font-size: 1rem; - } - - .chat-input-area button { - background-color: #142F32; - color: white; - padding: 0.75rem 1.25rem; - border-radius: 0.5rem; - transition: background-color 0.2s ease; - } - - .chat-input-area button:hover { - background-color: #0d1e20; - } - - .loading-indicator { - display: none; - text-align: center; - padding: 1rem; - color: #777C90; - } - - .loading-indicator.show { - display: block; - } - - .image-gen-preview { - max-width: 100%; - height: auto; - border-radius: 0.75rem; - margin-top: 1.5rem; - box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); - } - - .dashboard-section-content { - background-color: #ffffff; - padding: 2rem; - border-radius: 1rem; - box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05); - min-height: calc(100vh - 8rem); /* Adjust for header/footer/padding */ - } - - .dashboard-section-content h2 { - font-size: 2.25rem; - font-weight: 800; - margin-bottom: 1.5rem; - color: #282930; - } - - .dashboard-section-content p { - color: #4b5563; - margin-bottom: 1rem; - } - - .dashboard-section-content ul { - list-style: none; - padding: 0; - } - - .dashboard-section-content ul li { - background-color: #f1f5f9; - padding: 1rem; - border-radius: 0.75rem; - margin-bottom: 0.75rem; - display: flex; - justify-content: space-between; - align-items: center; - } \ No newline at end of file +/* Tambahan untuk font */ +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap'); + +/* Custom Theme Overrides */ +:root { + --color-brand-dark: #0D1117; + --color-brand-card: #161B22; + --color-brand-accent: #10B981; + --color-brand-accent-hover: #059669; + --color-brand-subtle: #30363D; +} + +body { + @apply bg-[var(--color-brand-dark)] text-gray-300 font-sans antialiased; +} + +/* Font override for Inter */ +* { + font-family: 'Inter', sans-serif; +} + +@keyframes marquee { + 0% { + transform: translateX(0%); + } + 100% { + transform: translateX(-50%); + } +} + +.animate-marquee { + animation: marquee 40s linear infinite; +} diff --git a/tailwind.config.js b/tailwind.config.js index 1490793..5728ca0 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,10 +1,21 @@ -/** @type {import('tailwindcss').Config} */ +// tailwind.config.js module.exports = { content: [ - "./src/**/*.{js,jsx,ts,tsx}", + "./src/**/*.{js,jsx,ts,tsx}", // pastikan path sesuai struktur project kamu ], theme: { - extend: {}, + extend: { + fontFamily: { + sans: ['Inter', 'sans-serif'], + }, + colors: { + 'brand-dark': '#0D1117', + 'brand-card': '#161B22', + 'brand-accent': '#10B981', + 'brand-accent-hover': '#059669', + 'brand-subtle': '#30363D', + }, + }, }, plugins: [], }