From e0c7ffca2c88791147286e97499fbb9d78362333 Mon Sep 17 00:00:00 2001 From: Vassshhhh Date: Mon, 15 Sep 2025 11:46:19 +0700 Subject: [PATCH] ok --- package-lock.json | 54 ++ package.json | 1 + src/App copy.js | 767 ++++++++++++++++++++++++++++ src/App.js | 771 +---------------------------- src/components/AddDocumentModal.js | 136 +++++ src/components/LandingPage.js | 29 ++ src/index.js | 26 +- src/pages/DashboardPage.js | 64 +++ src/pages/InputDataPage.js | 152 ++++++ src/pages/LoginPage.js | 29 ++ src/pages/OrganizationPage.js | 44 ++ src/pages/browser.html | 19 + 12 files changed, 1317 insertions(+), 775 deletions(-) create mode 100644 src/App copy.js create mode 100644 src/components/AddDocumentModal.js create mode 100644 src/components/LandingPage.js create mode 100644 src/pages/DashboardPage.js create mode 100644 src/pages/InputDataPage.js create mode 100644 src/pages/LoginPage.js create mode 100644 src/pages/OrganizationPage.js create mode 100644 src/pages/browser.html diff --git a/package-lock.json b/package-lock.json index 40d6bfa..b480f8a 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.7.1", "react-scripts": "5.0.1", "web-vitals": "^2.1.4" }, @@ -12866,6 +12867,53 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.7.1.tgz", + "integrity": "sha512-jVKHXoWRIsD/qS6lvGveckwb862EekvapdHJN/cGmzw40KnJH5gg53ujOJ4qX6EKIK9LSBfFed/xiQ5yeXNrUA==", + "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.7.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.7.1.tgz", + "integrity": "sha512-bavdk2BA5r3MYalGKZ01u8PGuDBloQmzpBZVhDLrOOv1N943Wq6dcM9GhB3x8b7AbqPMEezauv4PeGkAJfy7FQ==", + "license": "MIT", + "dependencies": { + "react-router": "7.7.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..225d615 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.7.1", "react-scripts": "5.0.1", "web-vitals": "^2.1.4" }, diff --git a/src/App copy.js b/src/App copy.js new file mode 100644 index 0000000..c1cba04 --- /dev/null +++ b/src/App copy.js @@ -0,0 +1,767 @@ +import React, { useState, useEffect, useRef } from 'react'; +import './index.css'; // Pastikan untuk mengimpor file CSS Anda + +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); + + // State untuk fungsionalitas Image Generation + const [imagePrompt, setImagePrompt] = useState(''); + const [generatedImageUrl, setGeneratedImageUrl] = useState(''); + const [isImageLoading, setImageLoading] = useState(false); + + // 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' }, + ]; + + return ( +
+ {/* Sidebar */} + + + {/* Main Content */} +
+ {activeDashboardSection === 'chatbot' && ( +
+

Chatbot AI

+

Ajukan pertanyaan atau mulai percakapan dengan AI kami.

+
+
+ {messages.map((msg, index) => ( +
+ {msg.text} +
+ ))} +
+
+ {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

+
+
+
+ +
+

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'} + +
+
+ +
+
+
+ +
+

Instagram

+ + {socialConnections.instagram ? 'Terhubung' : 'Belum Terhubung'} + +
+
+ +
+
+
+ + +
+
+
+ )} +
+
+ ); + }; + + + return ( + <> +
+ {view === 'landing' && } + {view === 'dashboard' && } + {isAuthModalOpen && } + + ); +} + +export default App; \ No newline at end of file diff --git a/src/App.js b/src/App.js index c1cba04..2181c94 100644 --- a/src/App.js +++ b/src/App.js @@ -1,766 +1,17 @@ -import React, { useState, useEffect, useRef } from 'react'; -import './index.css'; // Pastikan untuk mengimpor file CSS Anda +import { Routes, Route } from 'react-router-dom'; +import LoginPage from './pages/LoginPage'; +import OrganizationPage from './pages/OrganizationPage'; +import DashboardPage from './pages/DashboardPage'; +import InputDataPage from './pages/InputDataPage'; 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); - - // State untuk fungsionalitas Image Generation - const [imagePrompt, setImagePrompt] = useState(''); - const [generatedImageUrl, setGeneratedImageUrl] = useState(''); - const [isImageLoading, setImageLoading] = useState(false); - - // 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' }, - ]; - - return ( -
- {/* Sidebar */} - - - {/* Main Content */} -
- {activeDashboardSection === 'chatbot' && ( -
-

Chatbot AI

-

Ajukan pertanyaan atau mulai percakapan dengan AI kami.

-
-
- {messages.map((msg, index) => ( -
- {msg.text} -
- ))} -
-
- {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

-
-
-
- -
-

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'} - -
-
- -
-
-
- -
-

Instagram

- - {socialConnections.instagram ? 'Terhubung' : 'Belum Terhubung'} - -
-
- -
-
-
- - -
-
-
- )} -
-
- ); - }; - - return ( - <> -
- {view === 'landing' && } - {view === 'dashboard' && } - {isAuthModalOpen && } - + + } /> + } /> + } /> + } /> + ); } diff --git a/src/components/AddDocumentModal.js b/src/components/AddDocumentModal.js new file mode 100644 index 0000000..028650e --- /dev/null +++ b/src/components/AddDocumentModal.js @@ -0,0 +1,136 @@ +import { useState } from 'react'; + +// --- ICONS (no changes) --- +const CloseIcon = () => ( ); +const PlusIcon = () => ( ); +const TrashIcon = () => ( ); + +// --- Objek Templates (no changes) --- +const templates = { + 'KTP':{icon:'👤',fields:[{name:'NIK',type:'Number'},{name:'Nama',type:'Text'},{name:'Jenis Kelamin',type:'Selection',options:[{value:'Laki-laki'},{value:'Perempuan'}]},{name:'Tempat Lahir',type:'Text'},{name:'Tanggal Lahir',type:'Date'},]}, + 'KK':{icon:'👨‍👩‍👧‍👦',fields:[{name:'Nomor KK',type:'Number'},{name:'Nama Kepala Keluarga',type:'Text'},{name:'Alamat',type:'Text'},{name:'RT/RW',type:'Text'},{name:'Desa/Kelurahan',type:'Text'},{name:'Kecamatan',type:'Text'},{name:'Kabupaten/Kota',type:'Text'},{name:'Provinsi',type:'Text'},{name:'Tanggal Dikeluarkan',type:'Date'},]}, + 'Akta Kelahiran':{icon:'📜',fields:[{name:'Nomor Akta',type:'Text'},{name:'Nama Lengkap',type:'Text'},{name:'Jenis Kelamin',type:'Selection',options:[{value:'Laki-laki'},{value:'Perempuan'}]},{name:'Tempat Lahir',type:'Text'},{name:'Tanggal Lahir',type:'Date'},{name:'Nama Ayah',type:'Text'},{name:'Nama Ibu',type:'Text'},]}, + 'Custom':{icon:'⚙️',fields:[]} +}; +const templateNames = Object.keys(templates); + +export default function AddDocumentModal({ isOpen, onClose }) { + // --- State and handlers (no changes) --- + const [selectedTemplate, setSelectedTemplate] = useState(null); + const [docTypeName, setDocTypeName] = useState(''); + const [fields, setFields] = useState([]); + const handleSelectTemplate = (templateName) => { + setSelectedTemplate(templateName); + const templateData = templates[templateName]; + setDocTypeName(templateName === 'Custom' ? '' : templateName); + if (templateData.fields && templateData.fields.length > 0) { + const newFields = templateData.fields.map(field => ({ + id: Date.now() + Math.random(), + name: field.name, + type: field.type, + options: field.options ? field.options.map(opt => ({ id: Date.now() + Math.random(), value: opt.value })) : [] + })); + setFields(newFields); + } else { + setFields([{ id: Date.now(), name: '', type: 'Text', options: [] }]); + } + }; + const handleAddField = () => {setFields([...fields, { id: Date.now(), name: '', type: 'Text', options: [] }]);}; + const handleRemoveField = (id) => {setFields(fields.filter(field => field.id !== id));}; + const handleFieldChange = (id, event) => {const { name, value } = event.target; setFields(fields.map(field => field.id === id ? { ...field, [name]: value } : field));}; + const handleAddOption = (fieldId) => {setFields(fields.map(field =>field.id === fieldId? { ...field, options: [...field.options, { id: Date.now(), value: '' }] }: field));}; + const handleOptionChange = (fieldId, optionId, event) => {const { value } = event.target;setFields(fields.map(field =>field.id === fieldId? { ...field, options: field.options.map(opt => opt.id === optionId ? { ...opt, value } : opt) }: field));}; + const handleRemoveOption = (fieldId, optionId) => {setFields(fields.map(field =>field.id === fieldId? { ...field, options: field.options.filter(opt => opt.id !== optionId) }: field));}; + const handleSave = () => { + const newDocumentType = { + template: selectedTemplate, + name: docTypeName, + fields: fields.map(({ id, name, type, options }) => ({ + name, + type, + ...(type === 'Selection' && { options: options.map(opt => opt.value) }) + })) + }; + console.log("Menyimpan data JSON:", JSON.stringify(newDocumentType, null, 2)); + onClose(); + setSelectedTemplate(null); + }; + + if (!isOpen) return null; + + return ( +
+
+ +

Tambah Jenis Dokumen Baru

+ + {!selectedTemplate && +
+ +
+ {templateNames.map(name => ( +
handleSelectTemplate(name)} className={`p-4 border-2 rounded-xl text-center cursor-pointer transition-all duration-200 ${selectedTemplate === name ? 'border-yellow-400 ring-2 ring-yellow-200' : 'border-gray-200 hover:border-blue-500'}`}> + {templates[name].icon} +

{name}

+
+ ))} +
+
+ } + + {selectedTemplate && ( +
+
+ + setDocTypeName(e.target.value)} placeholder="Contoh: KTP, KK, Ijazah, dll" className="w-full mt-2 p-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 transition"/> +
+
+ +
+ {fields.map((field) => ( + // PERUBAHAN: Menambahkan class `relative` dan `pt-4` pada container field +
+ + {/* PERUBAHAN: Tombol hapus dipindah ke sini dan diubah gayanya */} + + +
+ handleFieldChange(field.id, e)} className="flex-grow p-3 border border-gray-300 rounded-lg"/> + + {/* Tombol hapus yang lama sudah dihapus dari sini */} +
+ {field.type === 'Selection' && ( +
+
+ {field.options.map(option => ( +
+ handleOptionChange(field.id, option.id, e)} className="flex-grow p-2 text-sm border border-gray-200 rounded-md"/> + +
+ ))} +
+ +
+ )} +
+ ))} +
+ +
+
+ + +
+
+ )} +
+
+ ); +} \ No newline at end of file diff --git a/src/components/LandingPage.js b/src/components/LandingPage.js new file mode 100644 index 0000000..11155c5 --- /dev/null +++ b/src/components/LandingPage.js @@ -0,0 +1,29 @@ +import { Link } from 'react-router-dom'; + +const DocumentIcon = () => ( + + + +); + +export default function LoginPage() { + return ( +
+
+
+
+ +
+
+

SOLID DATA

+

Kelola data dokumen Anda dengan mudah

+ + Masuk + +
+
+ ); +} \ No newline at end of file diff --git a/src/index.js b/src/index.js index d563c0f..f332564 100644 --- a/src/index.js +++ b/src/index.js @@ -1,17 +1,13 @@ -import React from 'react'; -import ReactDOM from 'react-dom/client'; -import './index.css'; -import App from './App'; -import reportWebVitals from './reportWebVitals'; +import React from 'react' +import ReactDOM from 'react-dom/client' +import App from './App.js' +import './index.css' +import { BrowserRouter } from 'react-router-dom' -const root = ReactDOM.createRoot(document.getElementById('root')); -root.render( +ReactDOM.createRoot(document.getElementById('root')).render( - - -); - -// If you want to start measuring performance in your app, pass a function -// to log results (for example: reportWebVitals(console.log)) -// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals -reportWebVitals(); + + + + , +) \ No newline at end of file diff --git a/src/pages/DashboardPage.js b/src/pages/DashboardPage.js new file mode 100644 index 0000000..5b518de --- /dev/null +++ b/src/pages/DashboardPage.js @@ -0,0 +1,64 @@ +import { useState } from 'react'; +import { Link } from 'react-router-dom'; +import AddDocumentModal from '../components/AddDocumentModal'; // Kita akan buat ini + +// Data dummy +const documentTypes = [ + { name: 'Akta Kelahiran', count: 0 }, + { name: 'Ijazah', count: 0 }, + { name: 'KK', count: 0 }, + { name: 'KTP', count: 6 }, + { name: 'Polinema', count: 3 }, + { name: 'Sampul Buku', count: 1 }, +]; + +const StatCard = ({ title, value }) => ( +
+

{title}

+

{value}

+
+); + +export default function DashboardPage() { + const [isModalOpen, setIsModalOpen] = useState(false); + + return ( +
+
+ {/* Statistik */} +
+ + + +
+ + {/* Daftar Jenis Dokumen */} +
+
+

Daftar Jenis Dokumen

+ +
+
+ {documentTypes.map((doc, index) => ( + +
{index + 1}
+
+

{doc.name}

+

{doc.count} data tersedia

+
+ {/* Arrow Icon */} + + ))} +
+
+
+ + setIsModalOpen(false)} /> +
+ ); +} \ No newline at end of file diff --git a/src/pages/InputDataPage.js b/src/pages/InputDataPage.js new file mode 100644 index 0000000..ba4288c --- /dev/null +++ b/src/pages/InputDataPage.js @@ -0,0 +1,152 @@ +import { useState, useRef } from 'react'; +import { useParams, Link } from 'react-router-dom'; + +// Ikon (tidak ada perubahan) +const BackIcon = () => (); +const UploadIcon = () => (); +const CameraIcon = () => (); +const ImageIcon = () => (); +const TrashIcon = () => (); + + +export default function InputDataPage() { + const { docType } = useParams(); + const [filesToUpload, setFilesToUpload] = useState([]); + const [isUploading, setIsUploading] = useState(false); + const fileInputRef = useRef(null); + const cameraInputRef = useRef(null); + const [isDragging, setIsDragging] = useState(false); + + // --- PERUBAHAN: State baru untuk progress upload --- + const [uploadProgress, setUploadProgress] = useState(0); + + const handleFiles = (newFiles) => { + const imageFiles = Array.from(newFiles).filter(file => file.type.startsWith('image/')); + setFilesToUpload(prevFiles => { + const uniqueNewFiles = imageFiles.filter(newFile => + !prevFiles.some(existingFile => existingFile.name === newFile.name && existingFile.size === newFile.size) + ); + return [...prevFiles, ...uniqueNewFiles]; + }); + }; + + const removeFile = (index) => { + setFilesToUpload(prevFiles => prevFiles.filter((_, i) => i !== index)); + }; + + // --- PERUBAHAN: Fungsi handleUpload diubah total --- + const handleUpload = async () => { + if (filesToUpload.length === 0) return; + + setIsUploading(true); + setUploadProgress(0); + + const totalFiles = filesToUpload.length; + const successfulUploads = []; + const failedUploads = []; + + for (let i = 0; i < totalFiles; i++) { + const file = filesToUpload[i]; + setUploadProgress(i + 1); // Update progress sebelum upload + + const formData = new FormData(); + formData.append('document', file); // Kirim satu file + + try { + console.log(`Mengupload file ${i + 1}/${totalFiles}: ${file.name}`); + const response = await fetch('https://api.kedaimaster.com/scan-documents', { + method: 'POST', + body: formData, + }); + + if (!response.ok) { + // Lemparkan error agar ditangkap oleh catch block + throw new Error(`Gagal mengupload ${file.name}`); + } + + const resultJson = await response.json(); + successfulUploads.push({ file: file.name, result: resultJson }); + console.log(`Sukses mengupload ${file.name}:`, resultJson); + + } catch (error) { + failedUploads.push(file.name); + console.error(`Error saat mengupload ${file.name}:`, error); + } + } + + setIsUploading(false); + setUploadProgress(0); + + // Beri ringkasan hasil upload + alert(`Selesai! Berhasil: ${successfulUploads.length}, Gagal: ${failedUploads.length}`); + + // Reset daftar file setelah semua proses selesai + setFilesToUpload([]); + }; + + return ( +
+
+ +

Input Data untuk {docType.replace('-', ' ')}

+
+ +
+
+
+
setIsDragging(true)} + onDragLeave={() => setIsDragging(false)} + onDragOver={(e) => e.preventDefault()} + onDrop={(e) => { e.preventDefault(); setIsDragging(false); handleFiles(e.dataTransfer.files); }} + > + handleFiles(e.target.files)}/> + handleFiles(e.target.files)}/> +

Upload Dokumen

+

Pilih file atau ambil gambar dari kamera.

+
+ + +
+

Atau, seret & lepas file di area ini.

+
+ +
+

Pratinjau

+ {filesToUpload.length > 0 ? ( +
+ {filesToUpload.map((file, index) => ( +
+ {file.name} +
+ +
+
+ ))} +
+ ) : ( +
+ +

Pratinjau gambar akan muncul di sini.

+
+ )} +
+
+ + {filesToUpload.length > 0 && ( +
+ +
+ )} +
+
+
+ ); +} \ No newline at end of file diff --git a/src/pages/LoginPage.js b/src/pages/LoginPage.js new file mode 100644 index 0000000..11155c5 --- /dev/null +++ b/src/pages/LoginPage.js @@ -0,0 +1,29 @@ +import { Link } from 'react-router-dom'; + +const DocumentIcon = () => ( + + + +); + +export default function LoginPage() { + return ( +
+
+
+
+ +
+
+

SOLID DATA

+

Kelola data dokumen Anda dengan mudah

+ + Masuk + +
+
+ ); +} \ No newline at end of file diff --git a/src/pages/OrganizationPage.js b/src/pages/OrganizationPage.js new file mode 100644 index 0000000..51fa27e --- /dev/null +++ b/src/pages/OrganizationPage.js @@ -0,0 +1,44 @@ +import { Link } from 'react-router-dom'; + +const OrgIcon = () => ( + +); + +const ArrowIcon = () => ( + +); + +const organizations = [ + { name: 'psi', id: 'BLWR-XDU-QRUV' }, + { name: 'managemen', id: 'NFTJ-POX-ZYOB' }, + { name: 'solid', id: 'TCKQ-ZNF-UFTW' }, +]; + +export default function OrganizationPage() { + return ( +
+
+

Pilih Organisasi

+

Silakan pilih organisasi yang ingin Anda kelola.

+
+ {organizations.map((org) => ( + +
+
+
+

{org.name}

+

ID: {org.id}

+
+
+ + + ))} +
+
+
+ ); +} \ No newline at end of file diff --git a/src/pages/browser.html b/src/pages/browser.html new file mode 100644 index 0000000..bd89d9e --- /dev/null +++ b/src/pages/browser.html @@ -0,0 +1,19 @@ + + + + Bypass Situs + + + +

🔓 Akses Situs Lain dari File Lokal

+ +

Tips: Kalau tidak bisa dibuka, coba salin link-nya lalu tempel di tab baru.

+ +