Compare commits

..

No commits in common. "f7fcc1614d792d6935412ed8fc88a19d88faed71" and "e8d33cb0bd4902b0abdbfafff984e23455e89e1b" have entirely different histories.

22 changed files with 554 additions and 775 deletions

View File

@ -2,12 +2,12 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/png" href="/Finals_Icon.png" /> <link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>FortivaNet</title> <title>Vite + React</title>
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>
<script type="module" src="/src/main.jsx"></script> <script type="module" src="/src/main.jsx"></script>
</body> </body>
</html> </html>

619
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
{ {
"name": "FortivaNet-landing", "name": "walanja-landing",
"private": true, "private": true,
"version": "0.0.0", "version": "0.0.0",
"type": "module", "type": "module",
@ -14,8 +14,7 @@
"lucide-react": "^0.541.0", "lucide-react": "^0.541.0",
"react": "^19.1.1", "react": "^19.1.1",
"react-dom": "^19.1.1", "react-dom": "^19.1.1",
"react-router-dom": "^7.8.2", "react-router-dom": "^7.8.2"
"react-router-hash-link": "^2.4.3"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.33.0", "@eslint/js": "^9.33.0",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 660 KiB

After

Width:  |  Height:  |  Size: 917 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 917 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

Binary file not shown.

View File

@ -1,32 +1,16 @@
import { BrowserRouter as Router, Routes, Route, useLocation } from "react-router-dom"; import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import { useEffect } from "react";
import Navbar from "./components/Navbar";
import Home from "./pages/Home"; import Home from "./pages/Home";
import About from "./pages/About"; import About from "./pages/About";
import Portfolio from "./pages/Portfolio"; import Portfolio from "./pages/Portfolio";
function ScrollHandler() {
const { pathname } = useLocation();
useEffect(() => {
// tiap kali route berubah, scroll ke atas
window.scrollTo(0, 0);
}, [pathname]);
return null;
}
export default function App() { export default function App() {
return ( return (
<Router> <Router>
<ScrollHandler />
<Navbar />
<Routes> <Routes>
<Route path="/" element={<Home />} /> <Route path="/" element={<Home />} />
<Route path="/about" element={<About />} /> <Route path="/about" element={<About />} />
<Route path="/portofolio" element={<Portfolio />} /> <Route path="/portfolio" element={<Portfolio />} />
</Routes> </Routes>
</Router> </Router>
); );
} }

View File

@ -1,27 +1,28 @@
import { motion } from "framer-motion"; import { motion } from "framer-motion";
import { MapPin } from "lucide-react";
export default function Cakupan() { export default function Cakupan() {
return ( return (
<section id="cakupan" className="relative py-20 bg-gray-50 overflow-hidden"> <section id="cakupan" className="relative py-20 bg-gray-50 overflow-hidden">
{/* Animated Overlay */} {/* Animated Gradient Background */}
<div className="absolute inset-0 bg-gradient-to-r from-blue-50 via-white to-blue-50 animate-gradient bg-[length:300%_300%]"></div> <div className="absolute inset-0 bg-gradient-to-br from-blue-50 via-white to-blue-100 animate-gradient bg-[length:300%_300%]"></div>
<div className="relative z-10"> <div className="relative z-10">
{/* Title */} {/* Title */}
<div className="text-center mb-12"> <div className="text-center mb-12">
<h2 className="text-3xl md:text-4xl font-bold flex items-center justify-center gap-2 text-blue-900"> <h2 className="text-3xl md:text-4xl font-extrabold text-blue-900 drop-shadow-md">
Cakupan Area Cakupan Area
</h2> </h2>
<p className="mt-3 text-gray-600 max-w-2xl mx-auto"> <p className="mt-3 text-gray-700 max-w-2xl mx-auto leading-relaxed">
Saat ini jaringan dan layanan{" "} Saat ini jaringan dan layanan{" "}
<span className="font-semibold">FortivaNet</span> telah berhasil <span className="font-semibold text-blue-600">WTELL</span> telah
menghadirkan internet di berbagai daerah di Kota Bandung hingga berhasil menghadirkan internet di berbagai daerah di Kota Bandung
Desa 3T (Tertinggal, Terdepan, Terluar). hingga Desa 3T (Tertinggal, Terdepan, Terluar).
</p> </p>
</div> </div>
{/* Content */} {/* Content */}
<div className="max-w-6xl mx-auto flex flex-col md:flex-row items-stretch gap-12 px-6"> <div className="max-w-6xl mx-auto flex flex-col md:flex-row items-center gap-12 px-6">
{/* Map */} {/* Map */}
<motion.div <motion.div
whileHover={{ scale: 1.05 }} whileHover={{ scale: 1.05 }}
@ -30,25 +31,38 @@ export default function Cakupan() {
<img <img
src="/map-bandung.jpg" src="/map-bandung.jpg"
alt="Map Bandung" alt="Map Bandung"
className="w-full max-w-md rounded-2xl shadow-xl border-4 border-blue-100 object-cover" className="w-full max-w-xl rounded-2xl shadow-xl border-4 border-blue-100"
/> />
</motion.div> </motion.div>
{/* List Area */} {/* List Area */}
<div className="flex-1 bg-white/70 p-12 rounded-2xl shadow-lg flex flex-col justify-center"> <motion.div
<h3 className="text-2xl text-center font-semibold mb-6 text-blue-600"> whileHover={{ y: -5 }}
className="flex-1 bg-white/80 p-8 rounded-2xl shadow-xl backdrop-blur-md border border-blue-100"
>
<h3 className="text-xl font-bold mb-6 text-blue-700 border-b pb-3">
Fokus Layanan Fokus Layanan
</h3> </h3>
<ul className="space-y-3 text-gray-700"> <ul className="space-y-4 text-gray-700">
<li>📍 Bandung Kota</li> {[
<li>📍 Cimahi</li> "Bandung Kota",
<li>📍 Cileunyi</li> "Cimahi",
<li>📍 Ngamprah</li> "Cileunyi",
<li>📍 Desa 3T sekitar Bandung</li> "Ngamprah",
"Desa 3T sekitar Bandung",
].map((area, index) => (
<li
key={index}
className="flex items-center gap-3 hover:bg-blue-50 p-3 rounded-lg transition"
>
<MapPin className="w-5 h-5 text-red-500" />
<span className="font-medium">{area}</span>
</li>
))}
</ul> </ul>
</div> </motion.div>
</div> </div>
</div> </div>
</section> </section>
); );
} }

View File

@ -1,94 +0,0 @@
import { Phone, Mail, Earth, Link as LinkIcon } from "lucide-react";
import { Link } from "react-router-dom"; // ini untuk routing
export default function Footer({ footerRef }) {
return (
<footer
id="footer"
ref={footerRef}
className="bg-[#2c415e] text-white py-10 px-6">
<div className="max-w-7xl mx-auto grid grid-cols-1 md:grid-cols-12 gap-8">
{/* Logo + Deskripsi */}
<div className="md:col-span-4">
<img src="/Finals_Profile.png" alt="FortivaNet Logo" className="w-32 mb-4" />
<p className="text-sm leading-relaxed">
PT. Jaringan Citra Mandiri adalah Perusahaan Swasta yang bergerak di bidang Penyedia
Layanan Teknologi Telekomunikasi Berbasis fiber optik.
</p>
</div>
{/* Alamat */}
<div className="md:col-span-4">
<h3 className="font-bold text-lg mb-4 relative inline-block">
Alamat
</h3>
<p className="text-sm leading-relaxed">
Kantor Administrasi:
<br />
Jl. Paledang No. 236, Kec. Campaka, Kel. Andir Bandung 40184
</p>
<br />
<p className="text-sm leading-relaxed">
Kantor Teknis:
<br />
Parahyangan Business Park, The Suites Blok E5-E7
Jl. Soekarno Hatta No. 693, Bandung,
Jawa Barat 40286, Indonesia
</p>
</div>
{/* Explore */}
<div className="md:col-span-2">
<h3 className="font-bold text-lg mb-2 relative inline-block">
Explore
</h3>
<ul className="space-y-3 text-sm">
<li className="flex items-center gap-2">
<LinkIcon className="w-4 h-4" />
<Link to="/">Home</Link>
</li>
<li className="flex items-center gap-2">
<LinkIcon className="w-4 h-4" />
<Link to="/portofolio">Portofolio</Link>
</li>
<li className="flex items-center gap-2">
<LinkIcon className="w-4 h-4" />
<Link to="/about">About Us</Link>
</li>
<li className="flex items-center gap-2">
<LinkIcon className="w-4 h-4" />
<Link to="/#footer">Contact Us</Link>
</li>
</ul>
</div>
{/* Kontak Kami */}
<div className="md:col-span-2">
<h3 className="font-bold text-lg mb-2 relative inline-block">
Kontak Kami
</h3>
<ul className="space-y-2 text-sm">
<li className="flex items-center gap-2">
<Phone className="w-4 h-4"/> 0821 2062 3712
</li>
<li className="flex items-center gap-2">
<Mail className="w-4 h-4"/> cs@fortiva.net.id
</li>
<li className="flex items-center gap-2">
<Earth className="w-4 h-4"/> https://www.fortiva.net.id/
</li>
</ul>
</div>
</div>
{/* Copyright */}
<div className="border-t border-gray-400 mt-8 pt-4 text-center text-sm">
© 2025 Fortiva Networking.
</div>
</footer>
);
}

View File

@ -8,18 +8,19 @@ export default function Hero() {
playsInline playsInline
className="absolute inset-0 w-full h-full object-cover" className="absolute inset-0 w-full h-full object-cover"
> >
<source src="/bg-video2.mp4" type="video/mp4" /> <source src="/bg-video.mp4" type="video/mp4" />
</video> </video>
<div className="absolute inset-0 bg-black/50"></div> <div className="absolute inset-0 bg-black/50"></div>
<div className="relative z-10 flex flex-col justify-center h-full px-6 lg:px-20 text-white max-w-3xl"> <div className="relative z-10 flex flex-col justify-center h-full px-6 lg:px-20 text-white max-w-3xl">
<header className="text-4xl md:text-6xl font-bold leading-tight mt-2"> <p className="text-lg">Mari menjadi bagian dari kami</p>
FORTIVA <br /> NETWORKING <h1 className="text-4xl md:text-6xl font-bold leading-tight mt-2">
</header> WALANJA <br /> TELEKOMUNIKASI
<h1 className="mt-4 text-2xl md:text-3xl>">
Connected Everywhere
</h1> </h1>
<p className="mt-4 text-lg">
Bergabung bersama kami untuk mewujudkan Indonesia Emas 2045
</p>
</div> </div>
</section> </section>
); );
} }

View File

@ -1,24 +1,19 @@
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { Menu, X } from "lucide-react";
import { NavLink, useLocation, useNavigate } from "react-router-dom"; import { NavLink, useLocation, useNavigate } from "react-router-dom";
import { HashLink } from "react-router-hash-link";
export default function Navbar() { export default function Navbar() {
const [mobileMenu, setMobileMenu] = useState(false);
const [scrolled, setScrolled] = useState(false); const [scrolled, setScrolled] = useState(false);
const location = useLocation(); const location = useLocation();
const navigate = useNavigate(); const navigate = useNavigate();
// Deteksi scroll untuk ubah background navbar // Deteksi scroll untuk ubah background navbar
useEffect(() => { useEffect(() => {
const handleScroll = () => { const handleScroll = () => setScrolled(window.scrollY > 50);
setScrolled(window.scrollY > 50);
};
window.addEventListener("scroll", handleScroll); window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll); return () => window.removeEventListener("scroll", handleScroll);
}, []); }, []);
// Scroll otomatis kalau ada hash (#footer, dll) // Scroll otomatis kalau ada hash (#sdm, dll)
useEffect(() => { useEffect(() => {
if (location.hash) { if (location.hash) {
const id = location.hash.replace("#", ""); const id = location.hash.replace("#", "");
@ -31,9 +26,10 @@ export default function Navbar() {
} }
}, [location]); }, [location]);
// Dasar class link const linkClass = ({ isActive }) =>
const baseLink = `relative pb-1 transition-colors duration-300 hover:text-yellow-400 ${
"block px-4 py-2 transition-colors hover:text-[#00CAFF]"; isActive ? "text-yellow-400 font-semibold" : ""
}`;
// Klik About Us scroll atau pindah halaman // Klik About Us scroll atau pindah halaman
const handleAboutClick = (e) => { const handleAboutClick = (e) => {
@ -54,154 +50,55 @@ export default function Navbar() {
<nav className="max-w-7xl mx-auto flex items-center justify-between px-6 lg:px-12 py-4 relative"> <nav className="max-w-7xl mx-auto flex items-center justify-between px-6 lg:px-12 py-4 relative">
{/* Logo */} {/* Logo */}
<div className="flex items-center space-x-2"> <div className="flex items-center space-x-2">
<img <img src="/WTell.png" alt="logo" className="h-12 w-auto object-contain" />
src="/Finals_Icon.png"
alt="logo"
className="h-7 w-auto object-contain"
/>
<span <span
className={`text-lg font-bold transition-colors duration-300 ${ className={`text-lg font-bold transition-colors duration-300 ${
scrolled ? "text-black" : "text-white" scrolled ? "text-black" : "text-white"
}`} }`}
> >
FortivaNet WALANJA TELEKOMUNIKASI
</span> </span>
</div> </div>
{/* Menu Desktop */} {/* Menu */}
<ul <ul
className={`hidden md:flex items-center space-x-8 font-medium transition-colors duration-300 ${ className={`flex items-center space-x-8 font-medium transition-colors duration-300 ${
scrolled ? "text-black" : "text-white" scrolled ? "text-black" : "text-white"
}`} }`}
> >
{/* Home */}
<li> <li>
<HashLink <NavLink to="/" className={linkClass}>
smooth
to="/#"
className={`${baseLink} ${
location.pathname === "/" && !location.hash
? "text-[#00CAFF] font-semibold"
: ""
}`}
>
Home Home
</HashLink>
</li>
<li>
<NavLink
to="/portofolio"
className={({ isActive }) =>
`${baseLink} ${isActive ? "text-[#00CAFF] font-semibold" : ""}`
}
>
Portofolio
</NavLink> </NavLink>
</li> </li>
{/* Portfolio (tanpa dropdown) */}
<li>
<NavLink to="/portfolio" className={linkClass}>
Portfolio
</NavLink>
</li>
{/* About Us */}
<li> <li>
<NavLink <NavLink
to="/about" to="/about"
className={linkClass}
onClick={handleAboutClick} onClick={handleAboutClick}
className={({ isActive }) =>
`${baseLink} ${isActive ? "text-[#00CAFF] font-semibold" : ""}`
}
> >
About Us About Us
</NavLink> </NavLink>
</li> </li>
{/* Contact Us */}
<li> <li>
<HashLink <NavLink to="/contact" className={linkClass}>
smooth
to="/#footer"
className={`${baseLink} ${
location.hash === "#footer" ? "text-[#00CAFF] font-semibold" : ""
}`}
>
Contact Us Contact Us
</HashLink> </NavLink>
</li> </li>
</ul> </ul>
{/* Hamburger Mobile */}
<button
onClick={() => setMobileMenu(!mobileMenu)}
className={`md:hidden text-2xl focus:outline-none transition-colors duration-300 ${
scrolled ? "text-black" : "text-white"
}`}
>
{mobileMenu ? <X /> : <Menu />}
</button>
</nav> </nav>
{/* Menu Mobile */}
{mobileMenu && (
<div
className={`md:hidden fixed top-0 right-0 w-2/3 h-screen bg-white shadow-lg z-30 transform transition-transform duration-300 ${
mobileMenu ? "translate-x-0" : "translate-x-full"
}`}
>
<div className="flex justify-end p-4">
<button onClick={() => setMobileMenu(false)}>
<X size={28} />
</button>
</div>
<ul className="flex flex-col space-y-4 px-6 font-medium text-gray-800">
<li>
<HashLink
smooth
to="/#"
onClick={() => setMobileMenu(false)}
className={`${baseLink} ${
location.pathname === "/" && !location.hash
? "text-[#00CAFF] font-semibold"
: ""
}`}
>
Home
</HashLink>
</li>
<li>
<NavLink
to="/portofolio"
onClick={() => setMobileMenu(false)}
className={({ isActive }) =>
`${baseLink} ${isActive ? "text-[#00CAFF] font-semibold" : ""}`
}
>
Portofolio
</NavLink>
</li>
<li>
<NavLink
to="/about"
onClick={(e) => {
handleAboutClick(e);
setMobileMenu(false);
}}
className={({ isActive }) =>
`${baseLink} ${isActive ? "text-[#00CAFF] font-semibold" : ""}`
}
>
About Us
</NavLink>
</li>
<li>
<HashLink
smooth
to="/#footer"
onClick={() => setMobileMenu(false)}
className={`${baseLink} ${
location.hash === "#footer"
? "text-[#00CAFF] font-semibold"
: ""
}`}
>
Contact Us
</HashLink>
</li>
</ul>
</div>
)}
</header> </header>
); );
} }

View File

@ -4,41 +4,38 @@ import { motion } from "framer-motion";
export default function Produk() { export default function Produk() {
const products = [ const products = [
{ {
icon: <Wifi className="w-8 h-8 text-[#145BB5]" />, icon: <Wifi className="w-8 h-8 text-blue-600" />,
title: "FNET LastMile Connection", title: "WTELL LastMile Connection",
desc: "Solusi bagi penyedia layanan internet untuk melayani pelanggan Last Mile tanpa harus membangun jaringan fiber optic sendiri.", desc: "Solusi bagi penyedia layanan internet untuk melayani pelanggan Last Mile tanpa harus membangun jaringan fiber optic sendiri.",
gradient: "from-[#00BFFF]/20 to-[#145BB5]/20", gradient: "from-blue-500/20 to-blue-100/40"
whiteBox: false
}, },
{ {
icon: <Network className="w-8 h-8 text-[#00BFFF]" />, icon: <Network className="w-8 h-8 text-yellow-500" />,
title: "FNET Metro Link", title: "WTELL Metro Link",
desc: "Layanan jaringan serat optik Point to Point dan Point to Multi Point dengan kapasitas tinggi dan infrastruktur handal.", desc: "Layanan jaringan serat optik Point to Point dan Point to Multi Point dengan kapasitas tinggi dan infrastruktur handal.",
// tidak pakai gradient putih polos gradient: "from-yellow-400/30 to-yellow-100/40"
gradient: "",
whiteBox: true
}, },
{ {
icon: <Cog className="w-8 h-8 text-[#145BB5]" />, icon: <Cog className="w-8 h-8 text-blue-700" />,
title: "FNET EPC Solution", title: "WTELL EPC Solution",
desc: "Menyediakan layanan Engineering, Procurement, Construction: Survey, Design, Deployment, Operation & Maintenance, FTIX.", desc: "Menyediakan layanan Engineering, Procurement, Construction: Survey, Design, Deployment, Operation & Maintenance, FTIX.",
gradient: "from-[#00BFFF]/20 to-[#145BB5]/20", gradient: "from-blue-300/40 to-blue-100/30"
whiteBox: false
} }
]; ];
return ( return (
<section id="produk" className="relative py-20 overflow-hidden text-center"> <section id="produk" className="relative py-20 overflow-hidden text-center">
{/* Background animasi biru */} {/* Animated Background Gradient */}
<motion.div <motion.div
className="absolute inset-0 bg-gradient-to-r from-[#145BB5] via-[#00BFFF] to-[#145BB5] bg-[length:400%_400%]" className="absolute inset-0 bg-gradient-to-r from-blue-900 via-blue-700 to-blue-900 bg-[length:400%_400%]"
animate={{ backgroundPosition: ["0% 50%", "100% 50%", "0% 50%"] }} animate={{ backgroundPosition: ["0% 50%", "100% 50%", "0% 50%"] }}
transition={{ duration: 20, repeat: Infinity, ease: "linear" }} transition={{ duration: 20, repeat: Infinity, ease: "linear" }}
></motion.div> ></motion.div>
{/* Overlay biar teks tetap jelas */}
<div className="absolute inset-0 bg-white/95"></div> <div className="absolute inset-0 bg-white/95"></div>
<div className="relative z-10"> <div className="relative z-10">
<h2 className="text-3xl md:text-4xl font-bold mb-4 text-[#145BB5]"> <h2 className="text-3xl md:text-4xl font-bold mb-4 text-blue-900">
Produk Produk
</h2> </h2>
<p className="text-gray-700 max-w-3xl mx-auto mb-12 px-4"> <p className="text-gray-700 max-w-3xl mx-auto mb-12 px-4">
@ -53,15 +50,13 @@ export default function Produk() {
key={i} key={i}
whileHover={{ y: -8, scale: 1.03 }} whileHover={{ y: -8, scale: 1.03 }}
transition={{ duration: 0.4, ease: "easeOut" }} transition={{ duration: 0.4, ease: "easeOut" }}
className="bg-white text-blue-900 rounded-2xl shadow-lg relative overflow-hidden p-8 border border-[#145BB5]/10 hover:border-[#00BFFF]/40" className={`bg-white text-blue-900 rounded-2xl shadow-lg relative overflow-hidden p-8 border border-gray-100 hover:border-blue-300`}
> >
{/* gradient overlay hanya kalau whiteBox = false */} {/* Gradient overlay per-card */}
{!item.whiteBox && ( <div
<div className={`absolute inset-0 bg-gradient-to-br ${item.gradient} opacity-30`}
className={`absolute inset-0 bg-gradient-to-br ${item.gradient} opacity-30`} ></div>
></div> {/* Icon Circle */}
)}
<div className="relative z-10 w-16 h-16 mx-auto mb-5 rounded-full flex items-center justify-center bg-white shadow-md"> <div className="relative z-10 w-16 h-16 mx-auto mb-5 rounded-full flex items-center justify-center bg-white shadow-md">
{item.icon} {item.icon}
</div> </div>

View File

@ -7,4 +7,4 @@ createRoot(document.getElementById('root')).render(
<StrictMode> <StrictMode>
<App /> <App />
</StrictMode>, </StrictMode>,
) )

View File

@ -1,122 +1,147 @@
"use client";
import Navbar from "../components/Navbar"; import Navbar from "../components/Navbar";
import Hero from "../components/Hero"; import Hero from "../components/Hero";
import Footer from "../components/Footer";
import { motion } from "framer-motion"; import { motion } from "framer-motion";
import { CheckCircle } from "lucide-react"; import { BadgeCheck } from "lucide-react";
import { useState } from "react";
export default function About() { export default function About() {
const cardHover = { const [activeCard, setActiveCard] = useState(null);
scale: 1.03,
y: -4,
boxShadow: "0 15px 25px rgba(0,0,0,0.1)",
transition: { type: "spring", stiffness: 200, damping: 20 },
};
return ( return (
<div className="font-sans"> <div className="font-sans">
<Navbar /> {/* Navbar + Hero */}
<div className="relative">
{/* Hero Section */} <Navbar />
<Hero <Hero
title="Tentang Kami" title="Tentang Kami"
subtitle="Kenali lebih dekat siapa kami dan visi misi kami" subtitle="Kenali lebih dekat siapa kami dan visi misi kami"
background="/bg-video.mp4" background="/bg-video.mp4"
/> />
</div>
{/* About Section */} {/* About Section */}
{/* Ganti warna bg jadi sama seperti halaman Produk */} <section className="relative py-20 bg-gradient-to-br from-blue-50 via-white to-yellow-50 min-h-screen overflow-hidden">
<section className="py-20 bg-[#eaf2ff] min-h-screen"> {/* Dekorasi background blur */}
<div className="max-w-6xl mx-auto px-6 lg:px-20 space-y-16"> <div className="absolute top-0 left-0 w-72 h-72 bg-blue-200 rounded-full mix-blend-multiply filter blur-3xl opacity-40 animate-pulse"></div>
<div className="absolute bottom-0 right-0 w-96 h-96 bg-yellow-200 rounded-full mix-blend-multiply filter blur-3xl opacity-40 animate-pulse"></div>
{/* Card Deskripsi Perusahaan */} <div className="relative max-w-6xl mx-auto px-6 lg:px-20">
{/* Logo & Deskripsi */}
<motion.div <motion.div
className="bg-white rounded-3xl shadow-xl border border-gray-200 p-10 flex flex-col md:flex-row items-center gap-8" initial={{ opacity: 0, y: 40 }}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }} whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.7 }} transition={{ duration: 0.7 }}
viewport={{ once: true }} viewport={{ once: true }}
whileHover={cardHover} className="bg-white/60 backdrop-blur-lg rounded-3xl shadow-2xl border border-white/20 p-10 relative z-10"
> >
{/* Logo */} <div className="grid grid-cols-1 md:grid-cols-2 gap-10 items-center">
<div className="flex justify-center md:justify-start flex-shrink-0"> {/* Logo di kiri */}
<img src="/Finals_Profile.png" alt="Logo Fortiva" className="w-44 md:w-56" /> <div className="flex justify-center">
</div> <img
src="/WTell.png"
alt="Logo Walanja"
className="w-64 md:w-80 drop-shadow-2xl hover:scale-105 transition-transform duration-500"
/>
</div>
{/* Deskripsi */} {/* Deskripsi di kanan */}
<div className="text-center md:text-left"> <div className="text-left">
<h2 className="text-3xl font-bold text-blue-700"> <p className="text-gray-700 leading-relaxed text-lg">
PT. Jaringan Citra Mandiri <span className="font-semibold text-blue-700 underline decoration-blue-400 decoration-2 underline-offset-4">
</h2> PT. Jaringan Citra Mandiri
<p className="text-gray-700 leading-relaxed mb-4"> </span>{" "}
Adalah Perusahaan Swasta yang bergerak di bidang Penyedia adalah Perusahaan Swasta yang bergerak di bidang Penyedia
Layanan Teknologi Telekomunikasi Berbasis Fiber Optic. Layanan Teknologi Telekomunikasi Berbasis Fiber Optic.
</p> </p>
<p className="text-gray-700 leading-relaxed"> <p className="mt-4 leading-relaxed text-lg text-gray-900">
Berdiri sejak tahun 2018,{" "} Berdiri sejak tahun 2018,{" "}
<span className="font-semibold text-blue-700"> <span className="font-bold text-black-700 drop-shadow-sm">
Fortiva Networking WTELL
</span>{" "} </span>{" "}
berkomitmen menjadi Penyedia Layanan Teknologi Telekomunikasi berkomitmen menjadi{" "}
Berbasis Fiber Optic yang Handal dan Profesional. <span className="font-bold bg-gradient-to-r from-blue-600 to-indigo-600 bg-clip-text text-transparent">
</p> Penyedia Layanan Teknologi Telekomunikasi Berbasis Fiber
Optic yang Handal dan Profesional
</span>
.
</p>
</div>
</div> </div>
</motion.div> </motion.div>
{/* Visi & Misi */} {/* Visi & Misi */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-10"> <div className="grid grid-cols-1 md:grid-cols-2 gap-10 mt-16 relative z-10">
<motion.section {/* Visi */}
className="bg-white rounded-2xl p-8 cursor-pointer" <motion.div
whileHover={cardHover} whileHover={{ scale: 1.04 }}
initial={{ opacity: 0, x: -30 }} initial={{ opacity: 0, x: -50 }}
whileInView={{ opacity: 1, x: 0 }} whileInView={{ opacity: 1, x: 0 }}
transition={{ duration: 0.7 }} transition={{ duration: 0.5 }}
viewport={{ once: true }} viewport={{ once: true }}
onClick={() => setActiveCard("visi")}
className={`relative rounded-3xl bg-white p-10 overflow-hidden flex flex-col items-center text-center cursor-pointer transition-all duration-200 ease-out hover:shadow-2xl hover:-translate-y-2 hover:rotate-[1deg] ${
activeCard === "visi"
? "border-4 border-blue-500 shadow-blue-300"
: "border border-gray-200"
}`}
> >
<h3 className="text-2xl font-bold text-center mb-6 text-blue-700"> <div className="relative flex flex-col items-center">
VISI <h3 className="text-3xl font-extrabold text-blue-700 tracking-wide drop-shadow-md border-b-4 border-blue-400 pb-1">
</h3> VISI
<p className="text-gray-700 text-center leading-relaxed"> </h3>
Menjadi Penyedia Jaringan Kabel Serat Optik Terbaik yang <p className="mt-6 leading-relaxed text-gray-800 text-lg max-w-md">
Menghubungkan Seluruh Wilayah di Indonesia. Menjadi Penyedia Jaringan Kabel Serat Optik Terbaik yang
</p> Menghubungkan Seluruh Wilayah di Indonesia.
</motion.section> </p>
</div>
</motion.div>
<motion.section {/* Misi */}
className="bg-white rounded-2xl p-8 cursor-pointer" <motion.div
whileHover={cardHover} whileHover={{ scale: 1.04 }}
initial={{ opacity: 0, x: 30 }} initial={{ opacity: 0, x: 50 }}
whileInView={{ opacity: 1, x: 0 }} whileInView={{ opacity: 1, x: 0 }}
transition={{ duration: 0.7 }} transition={{ duration: 0.5 }}
viewport={{ once: true }} viewport={{ once: true }}
onClick={() => setActiveCard("misi")}
className={`relative rounded-3xl bg-white p-10 overflow-hidden flex flex-col items-center text-center cursor-pointer transition-all duration-200 ease-out hover:shadow-2xl hover:-translate-y-2 hover:rotate-[1deg] ${
activeCard === "misi"
? "border-4 border-blue-500 shadow-blue-300"
: "border border-gray-200"
}`}
> >
<h3 className="text-2xl font-bold text-center mb-6 text-blue-700"> <div className="relative flex flex-col items-center">
MISI <h3 className="text-3xl font-extrabold text-yellow-500 tracking-wide drop-shadow-md border-b-4 border-yellow-400 pb-1">
</h3> MISI
<ul className="space-y-4 text-gray-700"> </h3>
<li className="flex items-start gap-2"> <ul className="mt-6 space-y-4 text-gray-800 text-lg max-w-md text-left">
<CheckCircle className="text-green-500 w-6 h-6 shrink-0 mt-1" /> <li className="flex items-start gap-3">
Menyediakan kebutuhan infrastruktur Kabel Serat Optik yang <span className="bg-green-100 p-2 rounded-full">
Handal, Terpercaya dan Up To Date dengan Tenaga Profesional. <BadgeCheck className="text-green-600 w-6 h-6 shrink-0" />
</li> </span>
<li className="flex items-start gap-2"> Menyediakan kebutuhan infrastruktur Kabel Serat Optik yang
<CheckCircle className="text-green-500 w-6 h-6 shrink-0 mt-1" /> Handal, Terpercaya dan Up To Date dengan Tenaga Profesional.
Berkomitmen untuk berinovasi dalam teknologi jaringan Fiber </li>
Optic di seluruh Indonesia. <li className="flex items-start gap-3">
</li> <span className="bg-green-100 p-2 rounded-full">
<li className="flex items-start gap-2"> <BadgeCheck className="text-green-600 w-6 h-6 shrink-0" />
<CheckCircle className="text-green-500 w-6 h-6 shrink-0 mt-1" /> </span>
Memberikan nilai tambah dan sinergi dalam industri jaringan Berkomitmen untuk berinovasi dalam teknologi jaringan Fiber
Fiber Optic. Optic di seluruh Indonesia.
</li> </li>
</ul> <li className="flex items-start gap-3">
</motion.section> <span className="bg-green-100 p-2 rounded-full">
<BadgeCheck className="text-green-600 w-6 h-6 shrink-0" />
</span>
Memberikan nilai tambah dan sinergi dalam industri jaringan
Fiber Optic.
</li>
</ul>
</div>
</motion.div>
</div> </div>
</div> </div>
</section> </section>
<Footer />
</div> </div>
); );
} }

View File

@ -2,11 +2,7 @@ import Navbar from "../components/Navbar";
import Hero from "../components/Hero"; import Hero from "../components/Hero";
import Produk from "../components/Produk"; import Produk from "../components/Produk";
import Cakupan from "../components/Cakupan"; import Cakupan from "../components/Cakupan";
import Footer from "../components/Footer";
import { useEffect, useRef } from "react";
import { useLocation } from "react-router-dom";
import { motion } from "framer-motion"; import { motion } from "framer-motion";
import { MapPin, Wifi, Network, Cog } from "lucide-react";
const sectionVariant = { const sectionVariant = {
hidden: { opacity: 0, y: 40 }, hidden: { opacity: 0, y: 40 },
@ -22,52 +18,52 @@ const sectionVariant = {
}; };
export default function Home() { export default function Home() {
const footerRef = useRef(null);
const location = useLocation();
useEffect(() => {
if (location.hash === "#footer") {
footerRef.current?.scrollIntoView({ behavior: "smooth" });
}
}, [location]);
return ( return (
<div className="font-sans"> <motion.div
{/* Navbar */} className="font-sans"
<Navbar /> initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
{/* Hero Section */} transition={{ duration: 0.6 }}
<motion.section >
{/* Navbar muncul pertama */}
<motion.div
variants={sectionVariant} variants={sectionVariant}
initial="hidden" initial="hidden"
animate="visible" animate="visible"
custom={0.1} custom={0.1}
> >
<Hero /> <Navbar />
</motion.section> </motion.div>
{/* Produk Section */} {/* Hero muncul kedua */}
<motion.section <motion.section
variants={sectionVariant} variants={sectionVariant}
initial="hidden" initial="hidden"
animate="visible" animate="visible"
custom={0.3} custom={0.3}
> >
<Produk /> <Hero />
</motion.section> </motion.section>
{/* Cakupan Section */} {/* Produk muncul ketiga */}
<motion.section <motion.section
variants={sectionVariant} variants={sectionVariant}
initial="hidden" initial="hidden"
animate="visible" animate="visible"
custom={0.6} custom={0.6}
> >
<Cakupan /> <Produk />
</motion.section> </motion.section>
{/* Footer */} {/* Cakupan muncul terakhir */}
<Footer ref={footerRef} /> <motion.section
</div> variants={sectionVariant}
initial="hidden"
animate="visible"
custom={0.9}
>
<Cakupan />
</motion.section>
</motion.div>
); );
} }

View File

@ -1,5 +1,4 @@
import Navbar from "../components/Navbar"; import Navbar from "../components/Navbar";
import Footer from "../components/Footer";
import { motion } from "framer-motion"; import { motion } from "framer-motion";
import { useState } from "react"; import { useState } from "react";
@ -48,7 +47,7 @@ export default function Portfolio() {
</p> </p>
</> </>
), ),
extraImages: ["/fujikura.jpg", "/yokogwa.jpg", "/exfo.jpg"], extraImages: ["/fujikura.jpg", "/yokogwa.jpg", "/exfo.jpg"], // tambahan
}, },
{ {
id: 3, id: 3,
@ -57,6 +56,7 @@ export default function Portfolio() {
shortDesc: "Pabrikasi tiang telco berkualitas dengan standar industri terbaik.", shortDesc: "Pabrikasi tiang telco berkualitas dengan standar industri terbaik.",
detail: ( detail: (
<div className="space-y-10"> <div className="space-y-10">
{/* Bagian 1 */}
<div className="grid md:grid-cols-2 gap-6 items-center"> <div className="grid md:grid-cols-2 gap-6 items-center">
<img <img
src="/tiang1.jpg" src="/tiang1.jpg"
@ -74,6 +74,7 @@ export default function Portfolio() {
</div> </div>
</div> </div>
{/* Bagian 2 */}
<div className="grid md:grid-cols-2 gap-6 items-center"> <div className="grid md:grid-cols-2 gap-6 items-center">
<div className="order-2 md:order-1"> <div className="order-2 md:order-1">
<h3 className="font-semibold text-gray-800 mb-2"> <h3 className="font-semibold text-gray-800 mb-2">
@ -111,27 +112,33 @@ export default function Portfolio() {
Beberapa proyek utama mencakup wilayah strategis di Jawa Barat. Beberapa proyek utama mencakup wilayah strategis di Jawa Barat.
</p> </p>
{/* Grid Lokasi */}
<div className="grid grid-cols-2 gap-4 mt-4"> <div className="grid grid-cols-2 gap-4 mt-4">
<div> <div>
<img src="/subang.jpg" alt="Subang" className="w-full h-36 object-cover rounded-lg border" /> <img src="/subang.jpg" alt="Subang" className="w-full h-36 object-cover rounded-lg border" />
<p className="text-xs mt-1 text-center font-semibold">Subang 50 Km</p> <p className="text-xs mt-1 text-center font-semibold">Subang 50 Km</p>
</div> </div>
<div> <div>
<img src="/pangandaran.jpg" alt="Pangandaran" className="w-full h-36 object-cover rounded-lg border" /> <img src="/pangandaran.jpg" alt="Pangandaran" className="w-full h-36 object-cover rounded-lg border" />
<p className="text-xs mt-1 text-center font-semibold">Pangandaran 225 Km</p> <p className="text-xs mt-1 text-center font-semibold">Pangandaran 225 Km</p>
</div> </div>
<div> <div>
<img src="/bandungraya.jpg" alt="Bandung Raya" className="w-full h-36 object-cover rounded-lg border" /> <img src="/bandungraya.jpg" alt="Bandung Raya" className="w-full h-36 object-cover rounded-lg border" />
<p className="text-xs mt-1 text-center font-semibold">Bandung Raya 800 Km</p> <p className="text-xs mt-1 text-center font-semibold">Bandung Raya 800 Km</p>
</div> </div>
<div> <div>
<img src="/garut.jpg" alt="Garut" className="w-full h-36 object-cover rounded-lg border" /> <img src="/garut.jpg" alt="Garut" className="w-full h-36 object-cover rounded-lg border" />
<p className="text-xs mt-1 text-center font-semibold">Garut 1000 Km</p> <p className="text-xs mt-1 text-center font-semibold">Garut 1000 Km</p>
</div> </div>
<div> <div>
<img src="/ciamis.jpg" alt="Ciamis" className="w-full h-36 object-cover rounded-lg border" /> <img src="/ciamis.jpg" alt="Ciamis" className="w-full h-36 object-cover rounded-lg border" />
<p className="text-xs mt-1 text-center font-semibold">Ciamis 100 Km</p> <p className="text-xs mt-1 text-center font-semibold">Ciamis 100 Km</p>
</div> </div>
<div> <div>
<img src="/tasik.jpg" alt="Tasik" className="w-full h-36 object-cover rounded-lg border" /> <img src="/tasik.jpg" alt="Tasik" className="w-full h-36 object-cover rounded-lg border" />
<p className="text-xs mt-1 text-center font-semibold">Tasik 100 Km</p> <p className="text-xs mt-1 text-center font-semibold">Tasik 100 Km</p>
@ -144,26 +151,34 @@ export default function Portfolio() {
return ( return (
<div className="font-sans"> <div className="font-sans">
{/* Navbar */}
<Navbar /> <Navbar />
<section className="relative w-full h-[400px] flex items-center justify-center text-center text-white overflow-hidden"> {/* Header Section dengan background video */}
<video <section className="relative w-full h-[400px] flex items-center justify-center text-center text-white overflow-hidden">
className="absolute inset-0 w-full h-full object-cover" {/* Video background */}
src="/port2.mp4" <video
autoPlay className="absolute inset-0 w-full h-full object-cover"
loop src="/port.mp4" // taruh video kamu di public/bg-portfolio.mp4
muted autoPlay
playsInline loop
/> muted
<div className="absolute inset-0 bg-black/50"></div> playsInline
<div className="relative z-10 px-4"> />
<h1 className="text-4xl font-bold mb-8">Portofolio Kami</h1>
<p className="text-lg opacity-90">
Lihat karya dan layanan terbaik yang sudah kami bangun
</p>
</div>
</section>
{/* Overlay gelap biar teksnya jelas */}
<div className="absolute inset-0 bg-black/50"></div>
{/* Konten teks */}
<div className="relative z-10 px-4">
<h1 className="text-4xl font-bold mb-8">Portfolio Kami</h1>
<p className="text-lg opacity-90">
Lihat karya dan layanan terbaik yang sudah kami bangun
</p>
</div>
</section>
{/* Portfolio Section */}
<section className="relative py-20 bg-gradient-to-br from-indigo-50 via-white to-pink-50 min-h-screen overflow-hidden"> <section className="relative py-20 bg-gradient-to-br from-indigo-50 via-white to-pink-50 min-h-screen overflow-hidden">
<div className="relative max-w-6xl mx-auto px-6 lg:px-20"> <div className="relative max-w-6xl mx-auto px-6 lg:px-20">
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 relative z-10"> <div className="grid grid-cols-1 md:grid-cols-2 gap-8 relative z-10">
@ -180,6 +195,7 @@ export default function Portfolio() {
</div> </div>
</section> </section>
{/* Modal */}
{selectedPortfolio && ( {selectedPortfolio && (
<div className="fixed inset-0 bg-black/70 flex items-center justify-center z-50 px-4"> <div className="fixed inset-0 bg-black/70 flex items-center justify-center z-50 px-4">
<motion.div <motion.div
@ -189,6 +205,7 @@ export default function Portfolio() {
transition={{ duration: 0.4, ease: "easeOut" }} transition={{ duration: 0.4, ease: "easeOut" }}
className="relative bg-white/90 backdrop-blur-xl rounded-3xl max-w-5xl w-full h-[85vh] flex flex-col shadow-2xl overflow-hidden" className="relative bg-white/90 backdrop-blur-xl rounded-3xl max-w-5xl w-full h-[85vh] flex flex-col shadow-2xl overflow-hidden"
> >
{/* Tombol Close */}
<button <button
onClick={() => setSelectedPortfolio(null)} onClick={() => setSelectedPortfolio(null)}
className="absolute top-4 right-4 z-50 bg-white/80 hover:bg-red-500 hover:text-white rounded-full shadow-md p-2 transition" className="absolute top-4 right-4 z-50 bg-white/80 hover:bg-red-500 hover:text-white rounded-full shadow-md p-2 transition"
@ -196,6 +213,7 @@ export default function Portfolio() {
</button> </button>
{/* Gambar Header */}
<div className="relative"> <div className="relative">
<img <img
src={selectedPortfolio.image} src={selectedPortfolio.image}
@ -210,9 +228,11 @@ export default function Portfolio() {
</div> </div>
</div> </div>
{/* Konten */}
<div className="p-6 overflow-y-auto flex-1 text-gray-800 space-y-4 text-sm leading-relaxed custom-scrollbar"> <div className="p-6 overflow-y-auto flex-1 text-gray-800 space-y-4 text-sm leading-relaxed custom-scrollbar">
{selectedPortfolio.detail} {selectedPortfolio.detail}
{/* Extra Images */}
{selectedPortfolio.extraImages && ( {selectedPortfolio.extraImages && (
<div className="grid grid-cols-2 md:grid-cols-3 gap-4 mt-6"> <div className="grid grid-cols-2 md:grid-cols-3 gap-4 mt-6">
{selectedPortfolio.extraImages.map((img, idx) => ( {selectedPortfolio.extraImages.map((img, idx) => (
@ -230,8 +250,6 @@ export default function Portfolio() {
</motion.div> </motion.div>
</div> </div>
)} )}
<Footer />
</div> </div>
); );
} }
@ -253,8 +271,7 @@ function PortfolioCard({ image, title, shortDesc, onClick }) {
</div> </div>
<div className="p-6 flex flex-col flex-grow"> <div className="p-6 flex flex-col flex-grow">
{/* ==== WARNA JUDUL DIBUAT BIRU NAVBAR ==== */} <h3 className="text-lg font-bold bg-gradient-to-r from-indigo-600 to-blue-500 bg-clip-text text-transparent">
<h3 className="text-lg font-bold bg-gradient-to-r from-blue-700 to-blue-500 bg-clip-text text-transparent">
{title} {title}
</h3> </h3>