diff --git a/package-lock.json b/package-lock.json
index c037948..d0a2720 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,7 +12,8 @@
"lucide-react": "^0.541.0",
"react": "^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": {
"@eslint/js": "^9.33.0",
@@ -2690,7 +2691,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
- "dev": true,
"license": "MIT"
},
"node_modules/js-yaml": {
@@ -2820,6 +2820,18 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "license": "MIT",
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
"node_modules/lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
@@ -2990,7 +3002,6 @@
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -3327,6 +3338,17 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
@@ -3379,6 +3401,12 @@
"react": "^19.1.1"
}
},
+ "node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+ "license": "MIT"
+ },
"node_modules/react-refresh": {
"version": "0.17.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz",
@@ -3427,6 +3455,19 @@
"react-dom": ">=18"
}
},
+ "node_modules/react-router-hash-link": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/react-router-hash-link/-/react-router-hash-link-2.4.3.tgz",
+ "integrity": "sha512-NU7GWc265m92xh/aYD79Vr1W+zAIXDWp3L2YZOYP4rCqPnJ6LI6vh3+rKgkidtYijozHclaEQTAHaAaMWPVI4A==",
+ "license": "MIT",
+ "dependencies": {
+ "prop-types": "^15.7.2"
+ },
+ "peerDependencies": {
+ "react": ">=15",
+ "react-router-dom": ">=4"
+ }
+ },
"node_modules/read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
diff --git a/package.json b/package.json
index 7fafcbd..01413f2 100644
--- a/package.json
+++ b/package.json
@@ -14,7 +14,8 @@
"lucide-react": "^0.541.0",
"react": "^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": {
"@eslint/js": "^9.33.0",
diff --git a/public/WTell.png b/public/WTell.png
index db262e9..f57d06e 100644
Binary files a/public/WTell.png and b/public/WTell.png differ
diff --git a/public/WTell_logo.png b/public/WTell_logo.png
new file mode 100644
index 0000000..db262e9
Binary files /dev/null and b/public/WTell_logo.png differ
diff --git a/src/App.jsx b/src/App.jsx
index 63012ce..1acd92d 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -1,16 +1,32 @@
-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 About from "./pages/About";
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() {
return (
+
+
} />
} />
- } />
+ } />
);
-}
+}
\ No newline at end of file
diff --git a/src/components/Cakupan.jsx b/src/components/Cakupan.jsx
index 8441a55..41b4feb 100644
--- a/src/components/Cakupan.jsx
+++ b/src/components/Cakupan.jsx
@@ -1,28 +1,27 @@
import { motion } from "framer-motion";
-import { MapPin } from "lucide-react";
export default function Cakupan() {
return (
- {/* Animated Gradient Background */}
-
+ {/* Animated Overlay */}
+
{/* Title */}
-
+
Cakupan Area
-
+
Saat ini jaringan dan layanan{" "}
- WTELL telah
- berhasil menghadirkan internet di berbagai daerah di Kota Bandung
- hingga Desa 3T (Tertinggal, Terdepan, Terluar).
+ WTELL telah berhasil
+ menghadirkan internet di berbagai daerah di Kota Bandung hingga
+ Desa 3T (Tertinggal, Terdepan, Terluar).
{/* Content */}
-
+
{/* Map */}
{/* List Area */}
-
-
+
+
Fokus Layanan
-
- {[
- "Bandung Kota",
- "Cimahi",
- "Cileunyi",
- "Ngamprah",
- "Desa 3T sekitar Bandung",
- ].map((area, index) => (
-
-
- {area}
-
- ))}
+
+ 📍 Bandung Kota
+ 📍 Cimahi
+ 📍 Cileunyi
+ 📍 Ngamprah
+ 📍 Desa 3T sekitar Bandung
-
+
);
-}
+}
\ No newline at end of file
diff --git a/src/components/Footer.jsx b/src/components/Footer.jsx
new file mode 100644
index 0000000..25c71d7
--- /dev/null
+++ b/src/components/Footer.jsx
@@ -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 (
+
+ );
+}
\ No newline at end of file
diff --git a/src/components/Hero.jsx b/src/components/Hero.jsx
index 4b28cac..50f79a8 100644
--- a/src/components/Hero.jsx
+++ b/src/components/Hero.jsx
@@ -23,4 +23,4 @@ export default function Hero() {
);
-}
+}
\ No newline at end of file
diff --git a/src/components/Navbar.jsx b/src/components/Navbar.jsx
index d487e3c..714e0a3 100644
--- a/src/components/Navbar.jsx
+++ b/src/components/Navbar.jsx
@@ -1,19 +1,24 @@
import { useState, useEffect } from "react";
+import { Menu, X } from "lucide-react";
import { NavLink, useLocation, useNavigate } from "react-router-dom";
+import { HashLink } from "react-router-hash-link";
export default function Navbar() {
+ const [mobileMenu, setMobileMenu] = useState(false); // toggle mobile
const [scrolled, setScrolled] = useState(false);
const location = useLocation();
const navigate = useNavigate();
// Deteksi scroll untuk ubah background navbar
useEffect(() => {
- const handleScroll = () => setScrolled(window.scrollY > 50);
+ const handleScroll = () => {
+ setScrolled(window.scrollY > 50);
+ };
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
}, []);
- // Scroll otomatis kalau ada hash (#sdm, dll)
+ // Scroll otomatis kalau ada hash (#footer, dll)
useEffect(() => {
if (location.hash) {
const id = location.hash.replace("#", "");
@@ -26,10 +31,7 @@ export default function Navbar() {
}
}, [location]);
- const linkClass = ({ isActive }) =>
- `relative pb-1 transition-colors duration-300 hover:text-yellow-400 ${
- isActive ? "text-yellow-400 font-semibold" : ""
- }`;
+ const linkClass = `block px-4 py-2 hover:text-yellow-400 transition-colors`;
// Klik About Us → scroll atau pindah halaman
const handleAboutClick = (e) => {
@@ -56,31 +58,29 @@ export default function Navbar() {
scrolled ? "text-black" : "text-white"
}`}
>
- WALANJA TELEKOMUNIKASI
+ WTELL
- {/* Menu */}
+ {/* Menu Desktop */}
- {/* Home */}
-
+
Home
-
+
- {/* Portfolio (tanpa dropdown) */}
+ {/* Portofolio link biasa */}
-
- Portfolio
+
+ Portofolio
- {/* About Us */}
-
- {/* Contact Us */}
-
+
Contact Us
-
+
+
+ {/* Hamburger Mobile */}
+ setMobileMenu(!mobileMenu)}
+ className={`md:hidden text-2xl focus:outline-none transition-colors duration-300 ${
+ scrolled ? "text-black" : "text-white"
+ }`}
+ >
+ {mobileMenu ? : }
+
+
+ {/* Menu Mobile */}
+ {mobileMenu && (
+
+
+ setMobileMenu(false)}>
+
+
+
+
+
+
+ setMobileMenu(false)}
+ className={linkClass}
+ >
+ Home
+
+
+
+ {/* Portofolio link biasa mobile */}
+
+ setMobileMenu(false)}
+ className={linkClass}
+ >
+ Portofolio
+
+
+
+
+
+ About Us
+
+
+
+ setMobileMenu(false)}
+ className={linkClass}
+ >
+ Contact Us
+
+
+
+
+ )}
);
-}
+}
\ No newline at end of file
diff --git a/src/components/Produk.jsx b/src/components/Produk.jsx
index 13a5016..d9be363 100644
--- a/src/components/Produk.jsx
+++ b/src/components/Produk.jsx
@@ -70,4 +70,4 @@ export default function Produk() {
);
-}
+}
\ No newline at end of file
diff --git a/src/main.jsx b/src/main.jsx
index b9a1a6d..9347e15 100644
--- a/src/main.jsx
+++ b/src/main.jsx
@@ -7,4 +7,4 @@ createRoot(document.getElementById('root')).render(
,
-)
+)
\ No newline at end of file
diff --git a/src/pages/About.jsx b/src/pages/About.jsx
index 59037a4..a6ef1e7 100644
--- a/src/pages/About.jsx
+++ b/src/pages/About.jsx
@@ -1,147 +1,126 @@
+"use client";
+
import Navbar from "../components/Navbar";
import Hero from "../components/Hero";
+import Footer from "../components/Footer";
import { motion } from "framer-motion";
-import { BadgeCheck } from "lucide-react";
-import { useState } from "react";
+import { CheckCircle } from "lucide-react";
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 (
- {/* Navbar + Hero */}
-
-
-
-
+ {/* Navbar */}
+
+
+ {/* Hero Section */}
+
{/* About Section */}
-
- {/* Dekorasi background blur */}
-
-
-
-
- {/* Logo & Deskripsi */}
+
+
+ {/* Card Deskripsi Perusahaan dengan Logo */}
-
- {/* Logo di kiri */}
-
-
-
+ {/* Logo di kiri */}
+
+
+
- {/* Deskripsi di kanan */}
-
-
-
- PT. Jaringan Citra Mandiri
- {" "}
- adalah Perusahaan Swasta yang bergerak di bidang Penyedia
- Layanan Teknologi Telekomunikasi Berbasis Fiber Optic.
-
-
- Berdiri sejak tahun 2018,{" "}
-
- WTELL
- {" "}
- berkomitmen menjadi{" "}
-
- Penyedia Layanan Teknologi Telekomunikasi Berbasis Fiber
- Optic yang Handal dan Profesional
-
- .
-
-
+ {/* Deskripsi di kanan */}
+
+
+ PT. Jaringan Citra Mandiri
+
+
+ Adalah Perusahaan Swasta yang bergerak di bidang Penyedia Layanan
+ Teknologi Telekomunikasi Berbasis Fiber Optic.
+
+
+ Berdiri sejak tahun 2018, WTELL {" "}
+ berkomitmen menjadi Penyedia Layanan Teknologi Telekomunikasi
+ Berbasis Fiber Optic yang Handal dan Profesional.
+
{/* Visi & Misi */}
-
+
{/* Visi */}
-
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"
- }`}
>
-
-
- VISI
-
-
- Menjadi Penyedia Jaringan Kabel Serat Optik Terbaik yang
- Menghubungkan Seluruh Wilayah di Indonesia.
-
-
-
+
VISI
+
+ Menjadi Penyedia Jaringan Kabel Serat Optik Terbaik yang
+ Menghubungkan Seluruh Wilayah di Indonesia.
+
+
{/* Misi */}
-
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"
- }`}
>
-
-
- MISI
-
-
-
-
-
-
- Menyediakan kebutuhan infrastruktur Kabel Serat Optik yang
- Handal, Terpercaya dan Up To Date dengan Tenaga Profesional.
-
-
-
-
-
- Berkomitmen untuk berinovasi dalam teknologi jaringan Fiber
- Optic di seluruh Indonesia.
-
-
-
-
-
- Memberikan nilai tambah dan sinergi dalam industri jaringan
- Fiber Optic.
-
-
-
-
+
MISI
+
+
+
+ Menyediakan kebutuhan infrastruktur Kabel Serat Optik yang
+ Handal, Terpercaya dan Up To Date dengan Tenaga Profesional.
+
+
+
+ Berkomitmen untuk berinovasi dalam teknologi jaringan Fiber
+ Optic di seluruh Indonesia.
+
+
+
+ Memberikan nilai tambah dan sinergi dalam industri jaringan
+ Fiber Optic.
+
+
+
+
+ {/* Footer */}
+
);
-}
+}
\ No newline at end of file
diff --git a/src/pages/Home.jsx b/src/pages/Home.jsx
index 73d3658..cb73b64 100644
--- a/src/pages/Home.jsx
+++ b/src/pages/Home.jsx
@@ -2,7 +2,11 @@ import Navbar from "../components/Navbar";
import Hero from "../components/Hero";
import Produk from "../components/Produk";
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 { MapPin, Wifi, Network, Cog } from "lucide-react";
const sectionVariant = {
hidden: { opacity: 0, y: 40 },
@@ -18,52 +22,52 @@ const sectionVariant = {
};
export default function Home() {
+ const footerRef = useRef(null);
+ const location = useLocation();
+
+ useEffect(() => {
+ if (location.hash === "#footer") {
+ footerRef.current?.scrollIntoView({ behavior: "smooth" });
+ }
+ }, [location]);
+
return (
-
- {/* Navbar muncul pertama */}
-
+ {/* Navbar */}
+
+
+ {/* Hero Section */}
+
-
-
+
+
- {/* Hero muncul kedua */}
+ {/* Produk Section */}
-
+
- {/* Produk muncul ketiga */}
+ {/* Cakupan Section */}
-
-
-
- {/* Cakupan muncul terakhir */}
-
-
+
+ {/* Footer */}
+
+
);
}
\ No newline at end of file
diff --git a/src/pages/Portfolio.jsx b/src/pages/Portfolio.jsx
index d478c72..4e19162 100644
--- a/src/pages/Portfolio.jsx
+++ b/src/pages/Portfolio.jsx
@@ -1,4 +1,5 @@
import Navbar from "../components/Navbar";
+import Footer from "../components/Footer";
import { motion } from "framer-motion";
import { useState } from "react";
@@ -47,7 +48,7 @@ export default function Portfolio() {
>
),
- extraImages: ["/fujikura.jpg", "/yokogwa.jpg", "/exfo.jpg"], // tambahan
+ extraImages: ["/fujikura.jpg", "/yokogwa.jpg", "/exfo.jpg"],
},
{
id: 3,
@@ -56,7 +57,6 @@ export default function Portfolio() {
shortDesc: "Pabrikasi tiang telco berkualitas dengan standar industri terbaik.",
detail: (
- {/* Bagian 1 */}
- {/* Bagian 2 */}
@@ -112,33 +111,27 @@ export default function Portfolio() {
Beberapa proyek utama mencakup wilayah strategis di Jawa Barat.
- {/* Grid Lokasi */}
Subang – 50 Km
-
Pangandaran – 225 Km
-
Bandung Raya – 800 Km
-
Garut – 1000 Km
-
Ciamis – 100 Km
-
Tasik – 100 Km
@@ -151,34 +144,26 @@ export default function Portfolio() {
return (
- {/* Navbar */}
- {/* Header Section dengan background video */}
-
- {/* Video background */}
-
+
+
+
+
+
Portofolio Kami
+
+ Lihat karya dan layanan terbaik yang sudah kami bangun
+
+
+
- {/* Overlay gelap biar teksnya jelas */}
-
-
- {/* Konten teks */}
-
-
Portfolio Kami
-
- Lihat karya dan layanan terbaik yang sudah kami bangun
-
-
-
-
- {/* Portfolio Section */}
@@ -195,7 +180,6 @@ export default function Portfolio() {
- {/* Modal */}
{selectedPortfolio && (
- {/* Tombol Close */}
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"
@@ -213,7 +196,6 @@ export default function Portfolio() {
✕
- {/* Gambar Header */}
- {/* Konten */}
{selectedPortfolio.detail}
- {/* Extra Images */}
{selectedPortfolio.extraImages && (
{selectedPortfolio.extraImages.map((img, idx) => (
@@ -250,6 +230,9 @@ export default function Portfolio() {
)}
+
+ {/* Tambahkan Footer */}
+
);
}
@@ -288,4 +271,4 @@ function PortfolioCard({ image, title, shortDesc, onClick }) {
);
-}
+}
\ No newline at end of file