ok
This commit is contained in:
23
.gitignore
vendored
Normal file
23
.gitignore
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
.env.local
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
71
README.md
71
README.md
@@ -1 +1,70 @@
|
|||||||
# maragen
|
# Getting Started with Create React App
|
||||||
|
|
||||||
|
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
|
||||||
|
|
||||||
|
## Available Scripts
|
||||||
|
|
||||||
|
In the project directory, you can run:
|
||||||
|
|
||||||
|
### `npm start`
|
||||||
|
|
||||||
|
Runs the app in the development mode.\
|
||||||
|
Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
|
||||||
|
|
||||||
|
The page will reload when you make changes.\
|
||||||
|
You may also see any lint errors in the console.
|
||||||
|
|
||||||
|
### `npm test`
|
||||||
|
|
||||||
|
Launches the test runner in the interactive watch mode.\
|
||||||
|
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
|
||||||
|
|
||||||
|
### `npm run build`
|
||||||
|
|
||||||
|
Builds the app for production to the `build` folder.\
|
||||||
|
It correctly bundles React in production mode and optimizes the build for the best performance.
|
||||||
|
|
||||||
|
The build is minified and the filenames include the hashes.\
|
||||||
|
Your app is ready to be deployed!
|
||||||
|
|
||||||
|
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
|
||||||
|
|
||||||
|
### `npm run eject`
|
||||||
|
|
||||||
|
**Note: this is a one-way operation. Once you `eject`, you can't go back!**
|
||||||
|
|
||||||
|
If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
|
||||||
|
|
||||||
|
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
|
||||||
|
|
||||||
|
You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
|
||||||
|
|
||||||
|
## Learn More
|
||||||
|
|
||||||
|
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
|
||||||
|
|
||||||
|
To learn React, check out the [React documentation](https://reactjs.org/).
|
||||||
|
|
||||||
|
### Code Splitting
|
||||||
|
|
||||||
|
This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
|
||||||
|
|
||||||
|
### Analyzing the Bundle Size
|
||||||
|
|
||||||
|
This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
|
||||||
|
|
||||||
|
### Making a Progressive Web App
|
||||||
|
|
||||||
|
This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
|
||||||
|
|
||||||
|
### Advanced Configuration
|
||||||
|
|
||||||
|
This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
|
||||||
|
|
||||||
|
### Deployment
|
||||||
|
|
||||||
|
This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
|
||||||
|
|
||||||
|
### `npm run build` fails to minify
|
||||||
|
|
||||||
|
This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
|
||||||
|
|||||||
16202
package-lock.json
generated
Normal file
16202
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
44
package.json
Normal file
44
package.json
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"name": "maragen",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@testing-library/dom": "^10.4.1",
|
||||||
|
"@testing-library/jest-dom": "^6.7.0",
|
||||||
|
"@testing-library/react": "^16.3.0",
|
||||||
|
"@testing-library/user-event": "^13.5.0",
|
||||||
|
"react": "^19.1.1",
|
||||||
|
"react-dom": "^19.1.1",
|
||||||
|
"react-scripts": "5.0.1",
|
||||||
|
"web-vitals": "^2.1.4"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"start": "react-scripts start",
|
||||||
|
"build": "react-scripts build",
|
||||||
|
"test": "react-scripts test",
|
||||||
|
"eject": "react-scripts eject"
|
||||||
|
},
|
||||||
|
"eslintConfig": {
|
||||||
|
"extends": [
|
||||||
|
"react-app",
|
||||||
|
"react-app/jest"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"browserslist": {
|
||||||
|
"production": [
|
||||||
|
">0.2%",
|
||||||
|
"not dead",
|
||||||
|
"not op_mini all"
|
||||||
|
],
|
||||||
|
"development": [
|
||||||
|
"last 1 chrome version",
|
||||||
|
"last 1 firefox version",
|
||||||
|
"last 1 safari version"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"autoprefixer": "^10.4.21",
|
||||||
|
"postcss": "^8.5.6",
|
||||||
|
"tailwindcss": "3.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
6
postcss.config.js
Normal file
6
postcss.config.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
module.exports = {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
autoprefixer: {},
|
||||||
|
},
|
||||||
|
}
|
||||||
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.8 KiB |
16
public/index.html
Normal file
16
public/index.html
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<title>Otomatisasi Cerdas untuk Bisnismu</title>
|
||||||
|
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@300;400;600;700;800&display=swap" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
<div id="root"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
BIN
public/logo192.png
Normal file
BIN
public/logo192.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.2 KiB |
BIN
public/logo512.png
Normal file
BIN
public/logo512.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.4 KiB |
25
public/manifest.json
Normal file
25
public/manifest.json
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"short_name": "React App",
|
||||||
|
"name": "Create React App Sample",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "favicon.ico",
|
||||||
|
"sizes": "64x64 32x32 24x24 16x16",
|
||||||
|
"type": "image/x-icon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "logo192.png",
|
||||||
|
"type": "image/png",
|
||||||
|
"sizes": "192x192"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "logo512.png",
|
||||||
|
"type": "image/png",
|
||||||
|
"sizes": "512x512"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"start_url": ".",
|
||||||
|
"display": "standalone",
|
||||||
|
"theme_color": "#000000",
|
||||||
|
"background_color": "#ffffff"
|
||||||
|
}
|
||||||
3
public/robots.txt
Normal file
3
public/robots.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# https://www.robotstxt.org/robotstxt.html
|
||||||
|
User-agent: *
|
||||||
|
Disallow:
|
||||||
38
src/App.css
Normal file
38
src/App.css
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
.App {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.App-logo {
|
||||||
|
height: 40vmin;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: no-preference) {
|
||||||
|
.App-logo {
|
||||||
|
animation: App-logo-spin infinite 20s linear;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.App-header {
|
||||||
|
background-color: #282c34;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: calc(10px + 2vmin);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.App-link {
|
||||||
|
color: #61dafb;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes App-logo-spin {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
767
src/App.js
Normal file
767
src/App.js
Normal file
@@ -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 = () => (
|
||||||
|
<header className="header-bg py-4 px-6 flex justify-between items-center fixed top-0 left-0 w-full z-10">
|
||||||
|
<div className="flex items-center">
|
||||||
|
<img src="https://placehold.co/40x40/142F32/E5FFCC?text=M" alt="Logo Maragen" className="h-8 w-8 mr-2 rounded-full" />
|
||||||
|
<span className="text-2xl font-bold text-gray-800">Maragen</span>
|
||||||
|
</div>
|
||||||
|
<nav className="hidden md:flex space-x-8">
|
||||||
|
<a href="#beranda" className="text-gray-600 hover:text-gray-900 font-medium">Beranda</a>
|
||||||
|
<a href="#tentang" className="text-gray-600 hover:text-gray-900 font-medium">Tentang</a>
|
||||||
|
<a href="#layanan" className="text-gray-600 hover:text-gray-900 font-medium">Layanan</a>
|
||||||
|
<a href="#kontak" className="text-gray-600 hover:text-gray-900 font-medium">Kontak</a>
|
||||||
|
</nav>
|
||||||
|
<button onClick={() => setAuthModalOpen(true)} className="button-sign-up px-6 py-2 rounded-lg font-semibold hidden md:block">
|
||||||
|
Daftar
|
||||||
|
</button>
|
||||||
|
<button className="md:hidden text-gray-600 hover:text-gray-900 focus:outline-none">
|
||||||
|
<i className="fas fa-bars text-2xl"></i>
|
||||||
|
</button>
|
||||||
|
</header>
|
||||||
|
);
|
||||||
|
|
||||||
|
const LandingPage = () => (
|
||||||
|
<div id="landingPage" className="landing-page-content">
|
||||||
|
{/* Hero Section */}
|
||||||
|
<section className="hero-section pt-24 pb-12">
|
||||||
|
<div className="max-w-4xl mx-auto">
|
||||||
|
<h1 className="text-4xl sm:text-5xl lg:text-6xl font-extrabold mb-4 leading-tight text-gray-900">
|
||||||
|
Masa Depan Otomatisasi dengan <span className="text-142F32">Teknologi Terbaru</span>
|
||||||
|
</h1>
|
||||||
|
<p className="text-lg sm:text-xl mb-8 text-gray-600">
|
||||||
|
Ahli teknologi untuk meningkatkan bisnis Anda. Mari bawa bisnis Anda lebih jauh.
|
||||||
|
</p>
|
||||||
|
<div className="flex flex-col sm:flex-row gap-4 justify-center">
|
||||||
|
<button
|
||||||
|
onClick={() => setAuthModalOpen(true)}
|
||||||
|
className="button-primary px-8 py-4 text-lg sm:text-xl font-semibold rounded-lg focus:outline-none focus:ring-4 focus:ring-blue-300 focus:ring-opacity-50"
|
||||||
|
>
|
||||||
|
Mulai Sekarang
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={showDashboard}
|
||||||
|
className="button-secondary px-8 py-4 text-lg sm:text-xl font-semibold rounded-lg focus:outline-none focus:ring-4 focus:ring-gray-300 focus:ring-opacity-50"
|
||||||
|
>
|
||||||
|
Coba Demo
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="mt-6 flex items-center justify-center text-gray-600">
|
||||||
|
<i className="fas fa-star text-yellow-400 mr-1"></i>
|
||||||
|
<i className="fas fa-star text-yellow-400 mr-1"></i>
|
||||||
|
<i className="fas fa-star text-yellow-400 mr-1"></i>
|
||||||
|
<i className="fas fa-star text-yellow-400 mr-1"></i>
|
||||||
|
<i className="fas fa-star-half-alt text-yellow-400 mr-2"></i>
|
||||||
|
<span>5.0</span>
|
||||||
|
<span className="ml-2">dari 80+ ulasan</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Stat Cards Grid */}
|
||||||
|
<div className="max-w-6xl mx-auto stats-grid mt-16 px-4">
|
||||||
|
<div className="stat-card overflow-hidden">
|
||||||
|
<img src="https://placehold.co/400x300/142F32/E5FFCC?text=Otomatisasi" alt="Otomatisasi Visual" className="card-image" />
|
||||||
|
<div className="p-4 text-center">
|
||||||
|
<p className="text-gray-700 font-semibold">Visual Otomatisasi</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="stat-card p-6 dark-bg">
|
||||||
|
<div className="flex items-center mb-2">
|
||||||
|
<i className="fas fa-users text-E5FFCC text-2xl mr-3"></i>
|
||||||
|
<p className="text-3xl font-bold text-white">100+</p>
|
||||||
|
</div>
|
||||||
|
<p className="text-gray-400 text-sm">Klien & Mitra Terhormat Kami</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="stat-card p-6">
|
||||||
|
<div className="flex items-center mb-2">
|
||||||
|
<i className="fas fa-project-diagram text-142F32 text-2xl mr-3"></i>
|
||||||
|
<p className="text-3xl font-bold text-gray-800">1951+</p>
|
||||||
|
</div>
|
||||||
|
<p className="text-gray-600 text-sm">Total Proyek <span className="text-green-500">↑126 bulan ini</span></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="stat-card p-6 dark-bg">
|
||||||
|
<div className="flex items-center mb-2">
|
||||||
|
<i className="fas fa-calendar-alt text-E5FFCC text-2xl mr-3"></i>
|
||||||
|
<p className="text-3xl font-bold text-white">6+</p>
|
||||||
|
</div>
|
||||||
|
<p className="text-gray-400 text-sm">Tahun Layanan Khusus</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Bottom Section (Layanan Otomatisasi) */}
|
||||||
|
<section className="bottom-section">
|
||||||
|
<div className="max-w-6xl mx-auto">
|
||||||
|
<h2 className="text-3xl sm:text-4xl font-extrabold mb-4 text-white">
|
||||||
|
Layanan Otomatisasi yang Efisien dan Terintegrasi
|
||||||
|
</h2>
|
||||||
|
<p className="text-lg sm:text-xl mb-12 opacity-80">
|
||||||
|
Sederhanakan operasi Anda dengan layanan berkualitas dan berorientasi efisiensi.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="bottom-grid">
|
||||||
|
<div className="bottom-card">
|
||||||
|
<div className="flex items-center justify-between mb-4">
|
||||||
|
<i className="fas fa-robot text-E5FFCC text-3xl"></i>
|
||||||
|
<i className="fas fa-arrow-up-right-from-square text-gray-500 hover:text-E5FFCC cursor-pointer"></i>
|
||||||
|
</div>
|
||||||
|
<h3 className="text-xl font-semibold mb-2 text-white">Alur Kerja Otomatis</h3>
|
||||||
|
<p className="text-gray-400 text-sm">
|
||||||
|
Detail tentang proses otomatisasi, kemampuan integrasi, dan jenis alur kerja yang didukung.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="bottom-card">
|
||||||
|
<div className="flex items-center justify-between mb-4">
|
||||||
|
<i className="fas fa-cogs text-E5FFCC text-3xl"></i>
|
||||||
|
<i className="fas fa-arrow-up-right-from-square text-gray-500 hover:text-E5FFCC cursor-pointer"></i>
|
||||||
|
</div>
|
||||||
|
<h3 className="text-xl font-semibold mb-2 text-white">Kustomisasi Solusi</h3>
|
||||||
|
<p className="text-gray-400 text-sm">
|
||||||
|
Pembuatan solusi otomatisasi khusus dengan opsi desain dan kustomisasi.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="bottom-card">
|
||||||
|
<div className="flex items-center justify-between mb-4">
|
||||||
|
<i className="fas fa-chart-line text-E5FFCC text-3xl"></i>
|
||||||
|
<i className="fas fa-arrow-up-right-from-square text-gray-500 hover:text-E5FFCC cursor-pointer"></i>
|
||||||
|
</div>
|
||||||
|
<h3 className="text-xl font-semibold mb-2 text-white">Pemantauan & Analisis</h3>
|
||||||
|
<p className="text-gray-400 text-sm">
|
||||||
|
Prosedur dan sistem untuk memastikan kualitas output otomatisasi yang tinggi.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Key Benefits Section */}
|
||||||
|
<section className="key-benefits-section">
|
||||||
|
<div className="benefits-image-card">
|
||||||
|
<div className="flex items-center justify-between mb-4">
|
||||||
|
<span className="text-gray-800 font-semibold">Total Proyek</span>
|
||||||
|
<span className="text-green-500 text-sm">↑56%</span>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2 text-sm text-gray-600 mb-6">
|
||||||
|
<div className="flex justify-between">
|
||||||
|
<span>Selesai</span>
|
||||||
|
<span>10%</span>
|
||||||
|
</div>
|
||||||
|
<div className="w-full bg-gray-200 rounded-full h-2.5">
|
||||||
|
<div className="bg-blue-600 h-2.5 rounded-full" style={{width: '10%'}}></div>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-between">
|
||||||
|
<span>Sedang Berjalan</span>
|
||||||
|
<span>13%</span>
|
||||||
|
</div>
|
||||||
|
<div className="w-full bg-gray-200 rounded-full h-2.5">
|
||||||
|
<div className="bg-yellow-500 h-2.5 rounded-full" style={{width: '13%'}}></div>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-between">
|
||||||
|
<span>Ditolak</span>
|
||||||
|
<span>11%</span>
|
||||||
|
</div>
|
||||||
|
<div className="w-full bg-gray-200 rounded-full h-2.5">
|
||||||
|
<div className="bg-red-500 h-2.5 rounded-full" style={{width: '11%'}}></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="stat-card p-6 dark-bg p-4 mt-4">
|
||||||
|
<div className="flex items-center mb-2">
|
||||||
|
<i className="fas fa-project-diagram text-E5FFCC text-2xl mr-3"></i>
|
||||||
|
<p className="text-3xl font-bold text-white">1951+</p>
|
||||||
|
</div>
|
||||||
|
<p className="text-gray-400 text-sm">Peningkatan <span className="text-green-500">↑126 bulan ini</span></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="benefits-content">
|
||||||
|
<h2 className="text-3xl sm:text-4xl font-extrabold mb-6 text-gray-900">
|
||||||
|
Manfaat Utama Sistem Kami untuk <span className="text-142F32">Efisiensi Bisnis Anda</span>
|
||||||
|
</h2>
|
||||||
|
<p className="text-lg sm:text-xl mb-8 text-gray-600">
|
||||||
|
Sistem kami meningkatkan produktivitas, mengurangi biaya, dan mendorong pertumbuhan bisnis.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="space-y-6">
|
||||||
|
<div className="benefit-item">
|
||||||
|
<i className="fas fa-check-circle text-142F32"></i>
|
||||||
|
<div>
|
||||||
|
<h3 className="text-xl font-semibold text-gray-800">Meningkatkan Kualitas dengan Teknologi</h3>
|
||||||
|
<p className="text-gray-600 text-base">
|
||||||
|
Dengan teknologi canggih, kami membantu Anda mencapai kualitas produk terbaik. Pelajari bagaimana kami dapat meningkatkan standar Anda.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="benefit-item">
|
||||||
|
<i className="fas fa-check-circle text-142F32"></i>
|
||||||
|
<div>
|
||||||
|
<h3 className="text-xl font-semibold text-gray-800">Optimasi Proses Produksi</h3>
|
||||||
|
<p className="text-gray-600 text-base">
|
||||||
|
Meningkatkan efisiensi dan produktivitas pabrik dengan solusi inovatif kami. Lihat bagaimana teknologi terbaru dapat memaksimalkan output Anda.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="benefit-item">
|
||||||
|
<i className="fas fa-check-circle text-142F32"></i>
|
||||||
|
<div>
|
||||||
|
<h3 className="text-xl font-semibold text-gray-800">Produksi Berbasis AI</h3>
|
||||||
|
<p className="text-gray-600 text-base">
|
||||||
|
Manfaatkan kekuatan AI untuk mengubah proses manufaktur Anda, mencapai hasil yang lebih cepat dan efektif.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Tailored Plans Section */}
|
||||||
|
<section className="tailored-plans-section">
|
||||||
|
<div className="max-w-4xl mx-auto mb-12">
|
||||||
|
<h2 className="text-3xl sm:text-4xl font-extrabold mb-4 text-white">
|
||||||
|
Paket yang Disesuaikan untuk <span className="text-E5FFCC">Skala Bisnis Anda</span>
|
||||||
|
</h2>
|
||||||
|
<p className="text-lg sm:text-xl opacity-80">
|
||||||
|
Harga fleksibel untuk setiap ukuran bisnis.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="pricing-grid">
|
||||||
|
<div className="pricing-card">
|
||||||
|
<h3 className="text-2xl font-semibold mb-2 text-white">Starter</h3>
|
||||||
|
<p className="text-gray-400 text-base mb-4">
|
||||||
|
Paket ini menawarkan fitur dasar yang Anda butuhkan untuk memulai.
|
||||||
|
</p>
|
||||||
|
<div className="flex items-baseline mb-6">
|
||||||
|
<span className="price">$39</span>
|
||||||
|
<span className="price-per-month">/ bulan</span>
|
||||||
|
</div>
|
||||||
|
<button className="button-primary w-full py-3 rounded-lg font-semibold text-lg">
|
||||||
|
Mulai Sekarang
|
||||||
|
</button>
|
||||||
|
<div className="feature-list mt-6">
|
||||||
|
<div className="feature-item"><i className="fas fa-check-circle text-E5FFCC"></i><span>Produksi hingga 10.000 unit per bulan</span></div>
|
||||||
|
<div className="feature-item"><i className="fas fa-check-circle text-E5FFCC"></i><span>Dukungan teknis 24/7</span></div>
|
||||||
|
<div className="feature-item"><i className="fas fa-check-circle text-E5FFCC"></i><span>Akses ke dasbor produksi</span></div>
|
||||||
|
<div className="feature-item"><i className="fas fa-check-circle text-E5FFCC"></i><span>Pengaturan awal</span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="pricing-card">
|
||||||
|
<h3 className="text-2xl font-semibold mb-2 text-white">Enterprise</h3>
|
||||||
|
<p className="text-gray-400 text-base mb-4">
|
||||||
|
Paket ini menyediakan akses penuh ke semua fitur premium.
|
||||||
|
</p>
|
||||||
|
<div className="flex items-baseline mb-6">
|
||||||
|
<span className="price">$99</span>
|
||||||
|
<span className="price-per-month">/ bulan</span>
|
||||||
|
</div>
|
||||||
|
<button className="button-primary w-full py-3 rounded-lg font-semibold text-lg">
|
||||||
|
Mulai Sekarang
|
||||||
|
</button>
|
||||||
|
<div className="feature-list mt-6">
|
||||||
|
<div className="feature-item"><i className="fas fa-check-circle text-E5FFCC"></i><span>Unit produksi tak terbatas</span></div>
|
||||||
|
<div className="feature-item"><i className="fas fa-check-circle text-E5FFCC"></i><span>Manajer akun khusus</span></div>
|
||||||
|
<div className="feature-item"><i className="fas fa-check-circle text-E5FFCC"></i><span>Solusi manufaktur yang disesuaikan</span></div>
|
||||||
|
<div className="feature-item"><i className="fas fa-check-circle text-E5FFCC"></i><span>Optimalisasi produksi prediktif</span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Seamless Integrations Section */}
|
||||||
|
<section className="integrations-section">
|
||||||
|
<div className="integrations-content">
|
||||||
|
<h2 className="text-3xl sm:text-4xl font-extrabold mb-6 text-gray-900">
|
||||||
|
Memberdayakan Perusahaan Top dengan <span className="text-142F32">Integrasi Tanpa Batas</span>
|
||||||
|
</h2>
|
||||||
|
<p className="text-lg sm:text-xl mb-8 text-gray-600">
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
<button className="button-primary px-8 py-4 text-lg sm:text-xl font-semibold rounded-lg focus:outline-none focus:ring-4 focus:ring-blue-300 focus:ring-opacity-50">
|
||||||
|
Bekerja Bersama Kami
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="integrations-visual">
|
||||||
|
<div className="integration-icon-grid">
|
||||||
|
<div className="integration-icon"><i className="fab fa-slack"></i></div>
|
||||||
|
<div className="integration-icon"><i className="fab fa-google-drive"></i></div>
|
||||||
|
<div className="integration-icon"><i className="fab fa-dropbox"></i></div>
|
||||||
|
<div className="integration-icon"><i className="fab fa-jira"></i></div>
|
||||||
|
<div className="integration-icon"><i className="fab fa-github"></i></div>
|
||||||
|
<div className="integration-icon"><i className="fab fa-trello"></i></div>
|
||||||
|
<div className="integration-icon"><i className="fab fa-salesforce"></i></div>
|
||||||
|
<div className="integration-icon"><i className="fab fa-microsoft"></i></div>
|
||||||
|
<div className="integration-icon"><i className="fab fa-aws"></i></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* From Idea to Production Section */}
|
||||||
|
<section className="idea-to-production-section">
|
||||||
|
<div className="max-w-4xl mx-auto">
|
||||||
|
<h2 className="text-3xl sm:text-4xl font-extrabold mb-4 text-white">
|
||||||
|
Dari Ide ke Produksi dalam Hitungan Hari
|
||||||
|
</h2>
|
||||||
|
<p className="text-lg sm:text-xl mb-8 opacity-80">
|
||||||
|
Percepat produksi Anda dengan teknologi kami. Kurangi waktu henti dan optimalkan biaya. Dapatkan penawaran spesial sekarang!
|
||||||
|
</p>
|
||||||
|
<button className="button-primary px-8 py-4 text-lg sm:text-xl font-semibold rounded-lg focus:outline-none focus:ring-4 focus:ring-blue-300 focus:ring-opacity-50">
|
||||||
|
Bekerja Bersama Kami
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<Footer />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
const Footer = () => (
|
||||||
|
<footer className="footer-section">
|
||||||
|
<div className="max-w-6xl mx-auto footer-grid">
|
||||||
|
<div className="footer-col">
|
||||||
|
<div className="flex items-center mb-4">
|
||||||
|
<img src="https://placehold.co/40x40/142F32/E5FFCC?text=P" alt="Logo Maragen" className="h-8 w-8 mr-2 rounded-full"/>
|
||||||
|
<span className="text-2xl font-bold text-white">Maragen</span>
|
||||||
|
</div>
|
||||||
|
<p className="mb-4">
|
||||||
|
Solusi kami membuat produksi lebih cepat dan lebih murah. Hubungi kami untuk informasi lebih lanjut.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="footer-col">
|
||||||
|
<h3>Perusahaan</h3>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#">Tentang Kami</a></li>
|
||||||
|
<li><a href="#">Pelanggan</a></li>
|
||||||
|
<li><a href="#">Berita</a></li>
|
||||||
|
<li><a href="#">Acara</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className="footer-col">
|
||||||
|
<h3>Industri</h3>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#">Manufaktur Logam Presisi</a></li>
|
||||||
|
<li><a href="#">Manufaktur Industri</a></li>
|
||||||
|
<li><a href="#">Teknologi Tinggi & Elektronik</a></li>
|
||||||
|
<li><a href="#">Dirgantara</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className="footer-col">
|
||||||
|
<h3>Produk</h3>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#">Sistem Eksekusi Manufaktur</a></li>
|
||||||
|
<li><a href="#">Perencanaan Sumber Daya Perusahaan</a></li>
|
||||||
|
<li><a href="#">Sistem Manajemen Kualitas</a></li>
|
||||||
|
<li><a href="#">Perencanaan Rantai Pasokan</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className="footer-col">
|
||||||
|
<h3>Hubungi Kami</h3>
|
||||||
|
<p className="mb-4">halo@maragen.com</p>
|
||||||
|
<div className="social-icons">
|
||||||
|
<a href="#"><i className="fab fa-linkedin"></i></a>
|
||||||
|
<a href="#"><i className="fab fa-instagram"></i></a>
|
||||||
|
<a href="#"><i className="fab fa-facebook"></i></a>
|
||||||
|
<a href="#"><i className="fab fa-twitter"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="text-center mt-8 pt-8 border-t border-gray-700">
|
||||||
|
<p>© 2024 Maragen. Semua hak dilindungi undang-undang.</p>
|
||||||
|
<div className="flex justify-center space-x-4 mt-2">
|
||||||
|
<a href="#" className="hover:text-white">Syarat & Ketentuan</a>
|
||||||
|
<a href="#" className="hover:text-white">Kebijakan Privasi</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
);
|
||||||
|
|
||||||
|
const AuthModal = () => (
|
||||||
|
<div className={`modal ${isAuthModalOpen ? 'show' : ''}`}>
|
||||||
|
<div className="modal-content">
|
||||||
|
<span className="close-button" onClick={() => setAuthModalOpen(false)}>×</span>
|
||||||
|
<h2 className="text-3xl font-extrabold mb-6 text-gray-900">Masuk atau Daftar</h2>
|
||||||
|
|
||||||
|
{authForm === 'login' ? (
|
||||||
|
<>
|
||||||
|
<form onSubmit={handleLogin} className="space-y-4">
|
||||||
|
<input type="email" name="loginEmail" placeholder="Email" className="w-full p-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-142F32" required defaultValue="user@example.com"/>
|
||||||
|
<input type="password" name="loginPassword" placeholder="Kata Sandi" className="w-full p-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-142F32" required defaultValue="password123"/>
|
||||||
|
<button type="submit" className="button-primary w-full py-3 rounded-lg font-semibold">Masuk</button>
|
||||||
|
</form>
|
||||||
|
<p className="mt-4 text-gray-600">
|
||||||
|
Belum punya akun? <a href="#" onClick={(e) => { e.preventDefault(); setAuthForm('register'); }} className="text-142F32 font-semibold hover:underline">Daftar di sini</a>
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<form onSubmit={handleRegister} className="space-y-4">
|
||||||
|
<input type="email" name="registerEmail" placeholder="Email" className="w-full p-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-142F32" required/>
|
||||||
|
<input type="password" name="registerPassword" placeholder="Kata Sandi" className="w-full p-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-142F32" required/>
|
||||||
|
<input type="password" name="confirmPassword" placeholder="Konfirmasi Kata Sandi" className="w-full p-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-142F32" required/>
|
||||||
|
<button type="submit" className="button-primary w-full py-3 rounded-lg font-semibold">Daftar</button>
|
||||||
|
</form>
|
||||||
|
<p className="mt-4 text-gray-600">
|
||||||
|
Sudah punya akun? <a href="#" onClick={(e) => { e.preventDefault(); setAuthForm('login'); }} className="text-142F32 font-semibold hover:underline">Masuk di sini</a>
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
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 (
|
||||||
|
<div id="userDashboard" className="dashboard-container">
|
||||||
|
{/* Sidebar */}
|
||||||
|
<aside className="dashboard-sidebar">
|
||||||
|
<h2 className="text-3xl font-bold mb-8 text-E5FFCC">Dashboard</h2>
|
||||||
|
<div className="w-full">
|
||||||
|
{sidebarItems.map(item => (
|
||||||
|
<div
|
||||||
|
key={item.id}
|
||||||
|
className={`dashboard-sidebar-item ${activeDashboardSection === item.id ? 'active' : ''}`}
|
||||||
|
onClick={() => setActiveDashboardSection(item.id)}
|
||||||
|
>
|
||||||
|
<i className={`fas ${item.icon} mr-3`}></i> {item.label}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<button onClick={handleLogout} className="button-secondary mt-auto w-full py-2 rounded-lg text-E5FFCC border-E5FFCC hover:bg-E5FFCC hover:text-142F32">
|
||||||
|
<i className="fas fa-sign-out-alt mr-2"></i> Keluar
|
||||||
|
</button>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
{/* Main Content */}
|
||||||
|
<main className="dashboard-main-content">
|
||||||
|
{activeDashboardSection === 'chatbot' && (
|
||||||
|
<section className="dashboard-section-content">
|
||||||
|
<h2 className="text-142F32">Chatbot AI</h2>
|
||||||
|
<p className="mb-6">Ajukan pertanyaan atau mulai percakapan dengan AI kami.</p>
|
||||||
|
<div className="chat-container">
|
||||||
|
<div className="chat-messages">
|
||||||
|
{messages.map((msg, index) => (
|
||||||
|
<div key={index} className={`chat-message ${msg.sender}`}>
|
||||||
|
{msg.text}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
<div ref={chatMessagesEndRef} />
|
||||||
|
</div>
|
||||||
|
{isChatLoading && <div className="loading-indicator show">Mengetik...</div>}
|
||||||
|
<div className="chat-input-area">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Ketik pesan Anda..."
|
||||||
|
value={chatInput}
|
||||||
|
onChange={(e) => setChatInput(e.target.value)}
|
||||||
|
onKeyPress={(e) => e.key === 'Enter' && handleSendMessage()}
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
<button onClick={handleSendMessage}>Kirim</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)}
|
||||||
|
{activeDashboardSection === 'imageGen' && (
|
||||||
|
<section className="dashboard-section-content">
|
||||||
|
<h2 className="text-142F32">Buat Gambar AI</h2>
|
||||||
|
<p className="mb-6">Masukkan deskripsi untuk membuat gambar.</p>
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Deskripsikan gambar yang ingin Anda buat (mis: 'seekor kucing di luar angkasa')"
|
||||||
|
className="w-full p-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-142F32"
|
||||||
|
value={imagePrompt}
|
||||||
|
onChange={(e) => setImagePrompt(e.target.value)}
|
||||||
|
/>
|
||||||
|
<button onClick={handleGenerateImage} className="button-primary py-3 rounded-lg font-semibold" disabled={isImageLoading}>
|
||||||
|
{isImageLoading ? 'Membuat...' : 'Buat Gambar'}
|
||||||
|
</button>
|
||||||
|
{isImageLoading && <div className="loading-indicator show">Membuat gambar...</div>}
|
||||||
|
{generatedImageUrl && (
|
||||||
|
<div className="text-center">
|
||||||
|
<img src={generatedImageUrl} className="image-gen-preview" alt="Gambar yang Dihasilkan" />
|
||||||
|
<div className="flex justify-center gap-4 mt-4">
|
||||||
|
<button className="button-secondary py-2 px-4 rounded-lg">Jadwalkan</button>
|
||||||
|
<button className="button-primary py-2 px-4 rounded-lg">Posting Langsung</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)}
|
||||||
|
{activeDashboardSection === 'scheduling' && (
|
||||||
|
<section className="dashboard-section-content">
|
||||||
|
<h2 className="text-142F32">Penjadwalan Konten</h2>
|
||||||
|
<p className="mb-6">Kelola konten yang akan dipublikasikan di masa mendatang.</p>
|
||||||
|
<div>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<span>Postingan Blog: "Masa Depan Otomatisasi"</span>
|
||||||
|
<span className="text-gray-500 text-sm">2025-08-15 10:00 AM</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span>Gambar AI: "Pemandangan Kota Futuristik"</span>
|
||||||
|
<span className="text-gray-500 text-sm">2025-08-18 02:30 PM</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<button className="button-primary mt-6 py-2 px-4 rounded-lg">Tambah Jadwal Baru</button>
|
||||||
|
</section>
|
||||||
|
)}
|
||||||
|
{activeDashboardSection === 'monitoring' && (
|
||||||
|
<section className="dashboard-section-content">
|
||||||
|
<h2>Pemantauan & Analisis Tren</h2>
|
||||||
|
<p className="mb-6">Pantau kinerja konten Anda dan temukan tren viral berikutnya.</p>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3>Kinerja Konten Saya</h3>
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||||
|
<div className="stat-card p-6 p-4">
|
||||||
|
<p className="text-gray-600 text-sm">Total Penayangan</p>
|
||||||
|
<p className="text-2xl font-bold text-gray-800">1.2M</p>
|
||||||
|
<p className="text-green-500 text-xs">↑15% bulan ini</p>
|
||||||
|
</div>
|
||||||
|
<div className="stat-card p-6 p-4">
|
||||||
|
<p className="text-gray-600 text-sm">Total Suka</p>
|
||||||
|
<p className="text-2xl font-bold text-gray-800">89K</p>
|
||||||
|
<p className="text-green-500 text-xs">↑12% bulan ini</p>
|
||||||
|
</div>
|
||||||
|
<div className="stat-card p-6 p-4">
|
||||||
|
<p className="text-gray-600 text-sm">Pengikut Baru</p>
|
||||||
|
<p className="text-2xl font-bold text-gray-800">5,210</p>
|
||||||
|
<p className="text-green-500 text-xs">↑8% bulan ini</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-8">
|
||||||
|
<h3>Konten yang Sedang Tren</h3>
|
||||||
|
<div className="space-y-4">
|
||||||
|
{/* Konten tren akan diisi oleh data dari API */}
|
||||||
|
<p className="text-gray-500">Fitur ini sedang dalam pengembangan.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)}
|
||||||
|
{activeDashboardSection === 'notifications' && (
|
||||||
|
<section className="dashboard-section-content">
|
||||||
|
<h2>Notifikasi</h2>
|
||||||
|
<p className="mb-6">Pembaruan terkini tentang akun dan konten Anda.</p>
|
||||||
|
<ul className="space-y-3">
|
||||||
|
{/* Notifikasi akan diisi oleh data dari API */}
|
||||||
|
<li>Postingan Anda "Masa Depan Otomatisasi" telah dijadwalkan.</li>
|
||||||
|
<li>Selamat! Anda mendapatkan 50 pengikut baru minggu ini.</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
)}
|
||||||
|
{activeDashboardSection === 'profile' && (
|
||||||
|
<section className="dashboard-section-content">
|
||||||
|
<h2>Pengaturan Profil</h2>
|
||||||
|
<p className="mb-6">Kelola informasi akun dan koneksi media sosial Anda.</p>
|
||||||
|
<div className="space-y-6 max-w-lg mx-auto text-left">
|
||||||
|
<div>
|
||||||
|
<label htmlFor="profileName" className="block text-sm font-medium text-gray-700">Nama Pengguna</label>
|
||||||
|
<input type="text" id="profileName" defaultValue="Pengguna Maragen"
|
||||||
|
className="mt-1 w-full p-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-142F32" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label htmlFor="profileEmail" className="block text-sm font-medium text-gray-700">Email</label>
|
||||||
|
<input type="email" id="profileEmail" defaultValue="user@example.com" disabled
|
||||||
|
className="mt-1 w-full p-3 border border-gray-300 rounded-lg bg-gray-100 cursor-not-allowed" />
|
||||||
|
</div>
|
||||||
|
<div className="pt-4 border-t">
|
||||||
|
<h3 className="text-lg font-semibold text-gray-800 mb-4">Autentikasi Media Sosial</h3>
|
||||||
|
<div className="flex justify-between items-center p-3 bg-gray-50 rounded-lg mb-3">
|
||||||
|
<div className="flex items-center">
|
||||||
|
<i className="fab fa-twitter text-2xl text-blue-400 mr-4"></i>
|
||||||
|
<div>
|
||||||
|
<p className="font-semibold text-gray-700">Twitter</p>
|
||||||
|
<span className={`connection-status ${socialConnections.twitter ? 'connected' : 'not-connected'}`}>
|
||||||
|
{socialConnections.twitter ? 'Terhubung' : 'Belum Terhubung'}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button onClick={() => handleConnectSocial('twitter')} className="button-primary py-2 px-4 rounded-lg text-sm">
|
||||||
|
{socialConnections.twitter ? 'Putuskan' : 'Hubungkan'}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-between items-center p-3 bg-gray-50 rounded-lg">
|
||||||
|
<div className="flex items-center">
|
||||||
|
<i className="fab fa-instagram text-2xl text-pink-500 mr-4"></i>
|
||||||
|
<div>
|
||||||
|
<p className="font-semibold text-gray-700">Instagram</p>
|
||||||
|
<span className={`connection-status ${socialConnections.instagram ? 'connected' : 'not-connected'}`}>
|
||||||
|
{socialConnections.instagram ? 'Terhubung' : 'Belum Terhubung'}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button onClick={() => handleConnectSocial('instagram')} className="button-primary py-2 px-4 rounded-lg text-sm">
|
||||||
|
{socialConnections.instagram ? 'Putuskan' : 'Hubungkan'}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="pt-4">
|
||||||
|
<button className="button-primary py-3 px-6 rounded-lg font-semibold">Simpan Perubahan</button>
|
||||||
|
<button onClick={handleLogout} className="button-secondary py-3 px-6 rounded-lg font-semibold ml-4">
|
||||||
|
Keluar
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)}
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Header />
|
||||||
|
{view === 'landing' && <LandingPage />}
|
||||||
|
{view === 'dashboard' && <Dashboard />}
|
||||||
|
{isAuthModalOpen && <AuthModal />}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App;
|
||||||
8
src/App.test.js
Normal file
8
src/App.test.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import App from './App';
|
||||||
|
|
||||||
|
test('renders learn react link', () => {
|
||||||
|
render(<App />);
|
||||||
|
const linkElement = screen.getByText(/learn react/i);
|
||||||
|
expect(linkElement).toBeInTheDocument();
|
||||||
|
});
|
||||||
614
src/index.css
Normal file
614
src/index.css
Normal file
@@ -0,0 +1,614 @@
|
|||||||
|
/* 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;
|
||||||
|
}
|
||||||
17
src/index.js
Normal file
17
src/index.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom/client';
|
||||||
|
import './index.css';
|
||||||
|
import App from './App';
|
||||||
|
import reportWebVitals from './reportWebVitals';
|
||||||
|
|
||||||
|
const root = ReactDOM.createRoot(document.getElementById('root'));
|
||||||
|
root.render(
|
||||||
|
<React.StrictMode>
|
||||||
|
<App />
|
||||||
|
</React.StrictMode>
|
||||||
|
);
|
||||||
|
|
||||||
|
// 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();
|
||||||
1
src/logo.svg
Normal file
1
src/logo.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 2.6 KiB |
13
src/reportWebVitals.js
Normal file
13
src/reportWebVitals.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
const reportWebVitals = onPerfEntry => {
|
||||||
|
if (onPerfEntry && onPerfEntry instanceof Function) {
|
||||||
|
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
|
||||||
|
getCLS(onPerfEntry);
|
||||||
|
getFID(onPerfEntry);
|
||||||
|
getFCP(onPerfEntry);
|
||||||
|
getLCP(onPerfEntry);
|
||||||
|
getTTFB(onPerfEntry);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default reportWebVitals;
|
||||||
5
src/setupTests.js
Normal file
5
src/setupTests.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
// jest-dom adds custom jest matchers for asserting on DOM nodes.
|
||||||
|
// allows you to do things like:
|
||||||
|
// expect(element).toHaveTextContent(/react/i)
|
||||||
|
// learn more: https://github.com/testing-library/jest-dom
|
||||||
|
import '@testing-library/jest-dom';
|
||||||
10
tailwind.config.js
Normal file
10
tailwind.config.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
module.exports = {
|
||||||
|
content: [
|
||||||
|
"./src/**/*.{js,jsx,ts,tsx}",
|
||||||
|
],
|
||||||
|
theme: {
|
||||||
|
extend: {},
|
||||||
|
},
|
||||||
|
plugins: [],
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user