Compare commits

..

13 Commits

Author SHA1 Message Date
adelyaou f7fcc1614d Contact Address CS 2025-09-16 15:52:26 +07:00
adelyaou cb7659f291 Contact Address 2025-09-16 15:48:18 +07:00
Syifa d45732c935 feat: update for changing color palette 2025-09-16 09:57:19 +07:00
adelyaou 1a31d8dd76 Fortiva Landing Page 2025-09-15 23:58:45 +07:00
Syifa ee7540a820 Revisi 3 Title WTell 2025-08-27 12:11:53 +07:00
Syifa 27a91c1840 Revisi 2 Title WTell 2025-08-27 12:05:46 +07:00
Syifa 92705cb78b Revisi Title WTell 2025-08-27 11:46:28 +07:00
Syifa 2b1586d919 Revisi Navbar 2025-08-27 08:27:32 +07:00
Syifa 4406dad9f8 Revisi Hero 2025-08-27 08:24:35 +07:00
Syifa 3d4709493b Walanja landing-page revisi 2025-08-26 22:10:17 +07:00
syifa 9f9c2ec14c Merge pull request 'adel' (#1) from adel into main
Reviewed-on: internship/landingpage-wtell#1
2025-08-26 14:03:49 +00:00
adelyaou 1309840e6f Revisi about, footer, hero 2025-08-26 20:12:42 +07:00
adelyaou d5fad3c82d Footer, Mobile 2025-08-26 14:42:55 +07:00
22 changed files with 773 additions and 552 deletions

View File

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

619
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
{ {
"name": "walanja-landing", "name": "FortivaNet-landing",
"private": true, "private": true,
"version": "0.0.0", "version": "0.0.0",
"type": "module", "type": "module",
@ -14,7 +14,8 @@
"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.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
public/Finals_Icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
public/Finals_Profile.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 917 KiB

After

Width:  |  Height:  |  Size: 660 KiB

BIN
public/WTell_logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 917 KiB

BIN
public/Wtell2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

BIN
public/Wtell2r.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

BIN
public/bg-video2.mp4 Normal file

Binary file not shown.

BIN
public/port2.mp4 Normal file

Binary file not shown.

View File

@ -1,15 +1,31 @@
import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; import { BrowserRouter as Router, Routes, Route, useLocation } 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="/portfolio" element={<Portfolio />} /> <Route path="/portofolio" element={<Portfolio />} />
</Routes> </Routes>
</Router> </Router>
); );

View File

@ -1,28 +1,27 @@
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 Gradient Background */} {/* Animated Overlay */}
<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="absolute inset-0 bg-gradient-to-r from-blue-50 via-white to-blue-50 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-extrabold text-blue-900 drop-shadow-md"> <h2 className="text-3xl md:text-4xl font-bold flex items-center justify-center gap-2 text-blue-900">
Cakupan Area Cakupan Area
</h2> </h2>
<p className="mt-3 text-gray-700 max-w-2xl mx-auto leading-relaxed"> <p className="mt-3 text-gray-600 max-w-2xl mx-auto">
Saat ini jaringan dan layanan{" "} Saat ini jaringan dan layanan{" "}
<span className="font-semibold text-blue-600">WTELL</span> telah <span className="font-semibold">FortivaNet</span> telah berhasil
berhasil menghadirkan internet di berbagai daerah di Kota Bandung menghadirkan internet di berbagai daerah di Kota Bandung hingga
hingga Desa 3T (Tertinggal, Terdepan, Terluar). 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-center gap-12 px-6"> <div className="max-w-6xl mx-auto flex flex-col md:flex-row items-stretch gap-12 px-6">
{/* Map */} {/* Map */}
<motion.div <motion.div
whileHover={{ scale: 1.05 }} whileHover={{ scale: 1.05 }}
@ -31,36 +30,23 @@ 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-xl rounded-2xl shadow-xl border-4 border-blue-100" className="w-full max-w-md rounded-2xl shadow-xl border-4 border-blue-100 object-cover"
/> />
</motion.div> </motion.div>
{/* List Area */} {/* List Area */}
<motion.div <div className="flex-1 bg-white/70 p-12 rounded-2xl shadow-lg flex flex-col justify-center">
whileHover={{ y: -5 }} <h3 className="text-2xl text-center font-semibold mb-6 text-blue-600">
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-4 text-gray-700"> <ul className="space-y-3 text-gray-700">
{[ <li>📍 Bandung Kota</li>
"Bandung Kota", <li>📍 Cimahi</li>
"Cimahi", <li>📍 Cileunyi</li>
"Cileunyi", <li>📍 Ngamprah</li>
"Ngamprah", <li>📍 Desa 3T sekitar Bandung</li>
"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>
</motion.div> </div>
</div> </div>
</div> </div>
</section> </section>

94
src/components/Footer.jsx Normal file
View File

@ -0,0 +1,94 @@
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,17 @@ 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-video.mp4" type="video/mp4" /> <source src="/bg-video2.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">
<p className="text-lg">Mari menjadi bagian dari kami</p> <header className="text-4xl md:text-6xl font-bold leading-tight mt-2">
<h1 className="text-4xl md:text-6xl font-bold leading-tight mt-2"> FORTIVA <br /> NETWORKING
WALANJA <br /> TELEKOMUNIKASI </header>
<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,19 +1,24 @@
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 = () => setScrolled(window.scrollY > 50); const handleScroll = () => {
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 (#sdm, dll) // Scroll otomatis kalau ada hash (#footer, dll)
useEffect(() => { useEffect(() => {
if (location.hash) { if (location.hash) {
const id = location.hash.replace("#", ""); const id = location.hash.replace("#", "");
@ -26,10 +31,9 @@ export default function Navbar() {
} }
}, [location]); }, [location]);
const linkClass = ({ isActive }) => // Dasar class link
`relative pb-1 transition-colors duration-300 hover:text-yellow-400 ${ const baseLink =
isActive ? "text-yellow-400 font-semibold" : "" "block px-4 py-2 transition-colors hover:text-[#00CAFF]";
}`;
// Klik About Us scroll atau pindah halaman // Klik About Us scroll atau pindah halaman
const handleAboutClick = (e) => { const handleAboutClick = (e) => {
@ -50,55 +54,154 @@ 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 src="/WTell.png" alt="logo" className="h-12 w-auto object-contain" /> <img
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"
}`} }`}
> >
WALANJA TELEKOMUNIKASI FortivaNet
</span> </span>
</div> </div>
{/* Menu */} {/* Menu Desktop */}
<ul <ul
className={`flex items-center space-x-8 font-medium transition-colors duration-300 ${ className={`hidden md: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>
<NavLink to="/" className={linkClass}> <HashLink
smooth
to="/#"
className={`${baseLink} ${
location.pathname === "/" && !location.hash
? "text-[#00CAFF] font-semibold"
: ""
}`}
>
Home Home
</NavLink> </HashLink>
</li> </li>
{/* Portfolio (tanpa dropdown) */}
<li> <li>
<NavLink to="/portfolio" className={linkClass}> <NavLink
Portfolio to="/portofolio"
className={({ isActive }) =>
`${baseLink} ${isActive ? "text-[#00CAFF] font-semibold" : ""}`
}
>
Portofolio
</NavLink> </NavLink>
</li> </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>
<NavLink to="/contact" className={linkClass}> <HashLink
smooth
to="/#footer"
className={`${baseLink} ${
location.hash === "#footer" ? "text-[#00CAFF] font-semibold" : ""
}`}
>
Contact Us Contact Us
</NavLink> </HashLink>
</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,38 +4,41 @@ 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-blue-600" />, icon: <Wifi className="w-8 h-8 text-[#145BB5]" />,
title: "WTELL LastMile Connection", title: "FNET 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-blue-500/20 to-blue-100/40" gradient: "from-[#00BFFF]/20 to-[#145BB5]/20",
whiteBox: false
}, },
{ {
icon: <Network className="w-8 h-8 text-yellow-500" />, icon: <Network className="w-8 h-8 text-[#00BFFF]" />,
title: "WTELL Metro Link", title: "FNET 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.",
gradient: "from-yellow-400/30 to-yellow-100/40" // tidak pakai gradient putih polos
gradient: "",
whiteBox: true
}, },
{ {
icon: <Cog className="w-8 h-8 text-blue-700" />, icon: <Cog className="w-8 h-8 text-[#145BB5]" />,
title: "WTELL EPC Solution", title: "FNET 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-blue-300/40 to-blue-100/30" gradient: "from-[#00BFFF]/20 to-[#145BB5]/20",
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">
{/* Animated Background Gradient */} {/* Background animasi biru */}
<motion.div <motion.div
className="absolute inset-0 bg-gradient-to-r from-blue-900 via-blue-700 to-blue-900 bg-[length:400%_400%]" className="absolute inset-0 bg-gradient-to-r from-[#145BB5] via-[#00BFFF] to-[#145BB5] 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-blue-900"> <h2 className="text-3xl md:text-4xl font-bold mb-4 text-[#145BB5]">
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">
@ -50,13 +53,15 @@ 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-gray-100 hover:border-blue-300`} className="bg-white text-blue-900 rounded-2xl shadow-lg relative overflow-hidden p-8 border border-[#145BB5]/10 hover:border-[#00BFFF]/40"
> >
{/* Gradient overlay per-card */} {/* gradient overlay hanya kalau whiteBox = false */}
{!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

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

View File

@ -2,7 +2,11 @@ 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 },
@ -18,52 +22,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 (
<motion.div <div className="font-sans">
className="font-sans" {/* Navbar */}
initial={{ opacity: 0 }} <Navbar />
animate={{ opacity: 1 }}
transition={{ duration: 0.6 }} {/* Hero Section */}
> <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}
> >
<Navbar /> <Hero />
</motion.div> </motion.section>
{/* Hero muncul kedua */} {/* Produk Section */}
<motion.section <motion.section
variants={sectionVariant} variants={sectionVariant}
initial="hidden" initial="hidden"
animate="visible" animate="visible"
custom={0.3} custom={0.3}
> >
<Hero /> <Produk />
</motion.section> </motion.section>
{/* Produk muncul ketiga */} {/* Cakupan Section */}
<motion.section <motion.section
variants={sectionVariant} variants={sectionVariant}
initial="hidden" initial="hidden"
animate="visible" animate="visible"
custom={0.6} custom={0.6}
>
<Produk />
</motion.section>
{/* Cakupan muncul terakhir */}
<motion.section
variants={sectionVariant}
initial="hidden"
animate="visible"
custom={0.9}
> >
<Cakupan /> <Cakupan />
</motion.section> </motion.section>
</motion.div>
{/* Footer */}
<Footer ref={footerRef} />
</div>
); );
} }

View File

@ -1,4 +1,5 @@
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";
@ -47,7 +48,7 @@ export default function Portfolio() {
</p> </p>
</> </>
), ),
extraImages: ["/fujikura.jpg", "/yokogwa.jpg", "/exfo.jpg"], // tambahan extraImages: ["/fujikura.jpg", "/yokogwa.jpg", "/exfo.jpg"],
}, },
{ {
id: 3, id: 3,
@ -56,7 +57,6 @@ 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,7 +74,6 @@ 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">
@ -112,33 +111,27 @@ 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>
@ -151,34 +144,26 @@ export default function Portfolio() {
return ( return (
<div className="font-sans"> <div className="font-sans">
{/* Navbar */}
<Navbar /> <Navbar />
{/* Header Section dengan background video */} <section className="relative w-full h-[400px] flex items-center justify-center text-center text-white overflow-hidden">
<section className="relative w-full h-[400px] flex items-center justify-center text-center text-white overflow-hidden">
{/* Video background */}
<video <video
className="absolute inset-0 w-full h-full object-cover" className="absolute inset-0 w-full h-full object-cover"
src="/port.mp4" // taruh video kamu di public/bg-portfolio.mp4 src="/port2.mp4"
autoPlay autoPlay
loop loop
muted muted
playsInline playsInline
/> />
{/* Overlay gelap biar teksnya jelas */}
<div className="absolute inset-0 bg-black/50"></div> <div className="absolute inset-0 bg-black/50"></div>
{/* Konten teks */}
<div className="relative z-10 px-4"> <div className="relative z-10 px-4">
<h1 className="text-4xl font-bold mb-8">Portfolio Kami</h1> <h1 className="text-4xl font-bold mb-8">Portofolio Kami</h1>
<p className="text-lg opacity-90"> <p className="text-lg opacity-90">
Lihat karya dan layanan terbaik yang sudah kami bangun Lihat karya dan layanan terbaik yang sudah kami bangun
</p> </p>
</div> </div>
</section> </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">
@ -195,7 +180,6 @@ 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
@ -205,7 +189,6 @@ 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"
@ -213,7 +196,6 @@ export default function Portfolio() {
</button> </button>
{/* Gambar Header */}
<div className="relative"> <div className="relative">
<img <img
src={selectedPortfolio.image} src={selectedPortfolio.image}
@ -228,11 +210,9 @@ 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) => (
@ -250,6 +230,8 @@ export default function Portfolio() {
</motion.div> </motion.div>
</div> </div>
)} )}
<Footer />
</div> </div>
); );
} }
@ -271,7 +253,8 @@ 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">
<h3 className="text-lg font-bold bg-gradient-to-r from-indigo-600 to-blue-500 bg-clip-text text-transparent"> {/* ==== WARNA JUDUL DIBUAT BIRU NAVBAR ==== */}
<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>