update api landing page

This commit is contained in:
Anang Yusman 2026-02-02 21:43:15 +08:00
parent a9b4aab886
commit 9c3b082c7e
23 changed files with 399 additions and 373 deletions

View File

@ -1,6 +1,7 @@
import ExteriorShs from "@/components/landing-page/exterior-shs";
import FeaturesAndSpecificationsShs from "@/components/landing-page/features-and-specifications-shs";
import Footer from "@/components/landing-page/footer";
import HeaderProductJ5Ev from "@/components/landing-page/header-product-j7-shs";
import HeaderProductJ7Shs from "@/components/landing-page/header-product-j7-shs";
import InteriorShs from "@/components/landing-page/interior-shs";
import Navbar from "@/components/landing-page/navbar";
@ -10,7 +11,7 @@ export default function ProductJ7ShsPage() {
<div className="relative min-h-screen font-[family-name:var(--font-geist-sans)]">
<div className="relative z-10 bg-white w-full mx-auto">
<Navbar />
<HeaderProductJ7Shs />
<HeaderProductJ5Ev />
<ExteriorShs />
<InteriorShs />
<FeaturesAndSpecificationsShs />

View File

@ -2,42 +2,68 @@
import Image from "next/image";
import { motion } from "framer-motion";
import { useEffect, useState } from "react";
import { getAgentData } from "@/service/agent";
const agents = [
{
name: "Johny Nugroho",
title: "Branch Manager Jaecoo Cihampelas Bandung",
image: "/johny.png",
},
{
name: "Basuki Pamungkas",
title: "Spv Jaecoo Cihampelas Bandung",
image: "/basuki.png",
},
{
name: "Deni Tihayar",
title: "Spv Jaecoo Cihampelas Bandung",
image: "/deni.png",
},
];
type Agent = {
id: number;
name: string;
job_title: string;
status_id: number;
profile_picture_url: string;
created_at: string;
};
export default function BestAgent() {
const [agents, setAgents] = useState<Agent[]>([]);
useEffect(() => {
const fetchAgents = async () => {
try {
const req = {
limit: "10",
page: 1,
search: "",
};
const res = await getAgentData(req);
const agentsData: Agent[] = res?.data?.data || [];
const latestApprovedAgents = agentsData
.filter((agent) => agent.status_id === 2) // ✅ approved only
.sort(
(a, b) =>
new Date(b.created_at).getTime() -
new Date(a.created_at).getTime(),
) // ✅ newest first
.slice(0, 5); // ✅ max 5
setAgents(latestApprovedAgents);
} catch (error) {
console.error("Failed to fetch agents:", error);
}
};
fetchAgents();
}, []);
return (
<section className="py-16 px-4 sm:px-6 md:px-12 bg-[#f9f9f9] text-center mt-0">
<section className="py-16 px-6 md:px-5 bg-[#FAFDFF] text-center mt-0">
<motion.h2
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
viewport={{ once: true }}
className="text-2xl sm:text-3xl md:text-4xl font-semibold text-gray-900 mb-10"
className="text-3xl md:text-6xl font-semibold text-gray-900 mb-2"
>
Our Teams
</motion.h2>
<div className="flex flex-col md:flex-row flex-wrap items-center justify-center gap-6">
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-4 gap-2 place-items-center mt-10">
{agents.map((agent, index) => (
<motion.div
key={index}
key={agent.id}
initial={{ opacity: 0, y: 40 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{
@ -46,19 +72,21 @@ export default function BestAgent() {
ease: "easeOut",
}}
viewport={{ once: true, amount: 0.3 }}
className="bg-white shadow-md p-4 flex flex-col items-center w-full max-w-[224px] h-[340px] sm:h-[300px]"
className="bg-white shadow-md py-4 gap-2 flex flex-col items-center h-[300px] w-[250px]"
>
<div className="relative w-28 h-36 mb-3">
<div className="relative w-44 h-48 mb-3">
<Image
src={agent.image}
src={agent.profile_picture_url}
alt={agent.name}
fill
className="rounded-full object-cover"
/>
</div>
<h3 className="text-lg text-gray-900 text-center">{agent.name}</h3>
<p className="text-xs text-gray-600 text-center mt-1">
{agent.title}
<p className="text-sm text-gray-600 text-center mt-1">
{agent.job_title}
</p>
</motion.div>
))}

View File

@ -1,80 +1,89 @@
"use client";
import { useState } from "react";
import { useEffect, useState } from "react";
import Image from "next/image";
import { ChevronLeft, ChevronRight } from "lucide-react";
const imagesPerPage = 6;
const galleryImages = [
"/gl1.png",
"/gl2-new.png",
"/gl3.png",
"/gl4.png",
"/gl5.png",
"/gl6.png",
"/gl7.png",
"/gl8.png",
"/gl9.png",
];
import {
getAllGaleryFiles,
getGaleryData,
getGaleryFileData,
} from "@/service/galery";
export default function GallerySection() {
const [currentPage, setCurrentPage] = useState(1);
const totalPages = Math.ceil(galleryImages.length / imagesPerPage);
const [data, setData] = useState<any[]>([]);
const [loading, setLoading] = useState(false);
const paginatedImages = galleryImages.slice(
(currentPage - 1) * imagesPerPage,
currentPage * imagesPerPage
);
const fetchData = async () => {
try {
setLoading(true);
// 1⃣ Ambil gallery (ada status_id)
const galleryRes = await getGaleryData({
limit: "100",
page: 1,
search: "",
});
const galleries = galleryRes?.data?.data ?? [];
// hanya approved
const approvedGalleries = galleries.filter((g: any) => g.status_id === 2);
// 2⃣ Ambil SEMUA files
const filesRes = await getAllGaleryFiles();
const files = filesRes?.data?.data ?? [];
// 3⃣ Mapping gallery + file berdasarkan gallery_id
const merged = approvedGalleries.map((gallery: any) => {
const file = files.find((f: any) => f.gallery_id === gallery.id);
return {
...gallery,
image_url: file?.image_url ?? null,
};
});
setData(merged);
} catch (err) {
console.error("Error fetch galeri:", err);
} finally {
setLoading(false);
}
};
useEffect(() => {
fetchData();
}, []);
return (
<section className="py-16 px-4 max-w-[1400px] mx-auto">
<h2 className="text-4xl font-bold mb-8">Galeri Kami</h2>
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4">
{paginatedImages.map((img, index) => (
<div key={index} className="relative w-full aspect-[3/2]">
<Image
src={img}
alt={`gallery-${index}`}
fill
className="object-cover"
/>
</div>
))}
</div>
<div className="flex items-center justify-center gap-2 mt-10">
<button
onClick={() => setCurrentPage((prev) => Math.max(prev - 1, 1))}
disabled={currentPage === 1}
className="p-2 rounded-md hover:bg-gray-200 disabled:opacity-30"
>
<ChevronLeft />
</button>
{[...Array(totalPages)].map((_, i) => (
<button
key={i}
onClick={() => setCurrentPage(i + 1)}
className={`w-8 h-8 rounded-md border text-sm ${
currentPage === i + 1
? "bg-[#1F6779] text-white"
: "text-gray-700 hover:bg-gray-100"
}`}
>
{i + 1}
</button>
))}
<button
onClick={() =>
setCurrentPage((prev) => Math.min(prev + 1, totalPages))
}
disabled={currentPage === totalPages}
className="p-2 rounded-md hover:bg-gray-200 disabled:opacity-30"
>
<ChevronRight />
</button>
</div>
{loading ? (
<p className="text-center">Loading...</p>
) : (
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4">
{data.map((item: any) => (
<div
key={`gallery-${item.id}`} // 🔥 WAJIB unik
className="relative w-full aspect-[3/2] bg-gray-100 rounded overflow-hidden"
>
{item.image_url ? (
<Image
src={item.image_url}
alt={item.title}
fill
className="object-cover"
unoptimized
/>
) : (
<div className="flex items-center justify-center h-full text-gray-400">
No Image
</div>
)}
</div>
))}
</div>
)}
</section>
);
}

View File

@ -144,6 +144,42 @@ export default function HeaderAbout() {
/>
</motion.div>
</div>
{/* ===== Static Gallery Section ===== */}
<div className="max-w-[1400px] mx-auto mt-32">
<motion.h2
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
viewport={{ once: true }}
className="text-3xl sm:text-4xl font-bold text-center mb-12"
>
Best Sales of The Month & SPV of The Month
</motion.h2>
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-4 gap-6">
{["/Asset18.png", "/Asset19.png", "/Asset20.png", "/Asset21.png"].map(
(src, index) => (
<motion.div
key={src}
initial={{ opacity: 0, scale: 0.95 }}
whileInView={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.5, delay: index * 0.1 }}
viewport={{ once: true }}
className="relative w-full overflow-hidden rounded-xl"
>
<Image
src={src}
alt={`static-gallery-${index}`}
width={800}
height={1000}
className="w-full h-[auto] rounded-xl hover:scale-105 transition-transform duration-500"
sizes="(max-width: 768px) 100vw, 400px"
/>
</motion.div>
),
)}
</div>
</div>
</section>
);
}

View File

@ -14,6 +14,7 @@ import {
import { motion } from "framer-motion";
import { useState } from "react";
import { Download } from "lucide-react";
import Link from "next/link";
export default function HeaderProductJ7Awd() {
const [open, setOpen] = useState(false);
@ -57,81 +58,25 @@ export default function HeaderProductJ7Awd() {
/>
{/* Tombol di dalam gambar, posisi bawah tengah */}
<div className="absolute bottom-4 left-1/2 transform -translate-x-1/2 flex items-center gap-3">
<Dialog open={openBrosur} onOpenChange={setOpenBrosur}>
<DialogTrigger asChild>
<Button className="bg-white text-black border w-[100px] h-[30px] md:w-[200px] md:h-[40px] rounded-xl hover:bg-amber-50 hover:cursor-pointer">
BROSUR
</Button>
</DialogTrigger>
<Link
href="https://cms.jaecoo.id/uploads/Flyer_J7_SHS_6db27c3a25.pdf"
target="_blank"
rel="noopener noreferrer"
>
<Button className="bg-white text-black border w-[100px] h-[30px] md:w-[200px] md:h-[40px] rounded-xl hover:bg-amber-50 hover:cursor-pointer">
BROSUR
</Button>
</Link>
<DialogContent className=" w-full p-0 overflow-hidden">
{/* Download Button */}
<div className="flex justify-end p-4 bg-white z-50">
<a
href={downloadLink}
target="_blank"
rel="noopener noreferrer"
className="absolute top-2 right-3 z-50 bg-black text-white p-2 rounded hover:bg-gray-800 mb-3"
>
<Download size={18} />
</a>
</div>
{/* Iframe Preview */}
<iframe
src={embedLink}
className="w-full h-[70vh] border-t"
allow="autoplay"
></iframe>
</DialogContent>
</Dialog>
{/* Trigger untuk modal */}
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Button className="bg-[#1F6779] text-white h-[30px] md:w-[200px] md:h-[40px] rounded-xl hover:cursor-pointer">
TEST DRIVE
</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-[1400px] h-[600px]">
<div className="flex items-center gap-4">
<Image
src="/masjaecoonav.png"
alt="MAS JAECOO Logo"
width={300}
height={30}
className=" object-fill"
/>
</div>
<DialogHeader>
<DialogTitle className="text-4xl text-center mb-4 font-bold">
FORM TEST DRIVE
</DialogTitle>
</DialogHeader>
{/* Form */}
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4 px-10">
<Input placeholder="Nama" />
<Input placeholder="Email" />
<Input placeholder="Mobile Number" />
<Input placeholder="Location" />
</div>
<div className="mt-3 px-10">
<Textarea placeholder="Full Message" rows={4} />
</div>
<div className="mt-6 text-left ml-10">
<Button
onClick={() => setOpen(false)}
className="bg-[#1F6779] text-white rounded-full"
>
SEND INQUIRY
</Button>
</div>
</DialogContent>
</Dialog>
<Link
href={`mailto:jaecookelapagading@gmail.com?subject=Test Drive J7 SHS-P &body=Halo Jaecoo,%0D%0A%0D%0ASaya tertarik untuk melakukan test drive kendaraan J7 SHS-P.%0D%0A%0D%0ANama:%0D%0ANomor HP:%0D%0ALokasi:%0D%0A%0D%0ATerima kasih.`}
>
<Button className="bg-[#1F6779] text-white h-[30px] md:h-[40px] rounded-full hover:cursor-pointer">
TEST DRIVE
</Button>
</Link>
</div>
</div>
</motion.div>

View File

@ -14,28 +14,31 @@ import {
import { motion } from "framer-motion";
import { useState } from "react";
import { Download } from "lucide-react";
import Link from "next/link";
export default function HeaderProductJ7Shs() {
export default function HeaderProductJ5Ev() {
const [open, setOpen] = useState(false);
const [selectedColorIndex, setSelectedColorIndex] = useState(0);
const [openBrosur, setOpenBrosur] = useState(false);
const fileId = "1Nici3bdjUG524sUYQgHfbeO63xW6f1_o";
const fileLink = `https://drive.google.com/file/d/${fileId}/view`;
const embedLink = `https://drive.google.com/file/d/${fileId}/preview`;
const downloadLink = `https://drive.google.com/uc?export=download&id=${fileId}`;
// const fileId = "1Nici3bdjUG524sUYQgHfbeO63xW6f1_o";
// const fileLink = `https://drive.google.com/file/d/${fileId}/view`;
// const embedLink = `https://drive.google.com/file/d/${fileId}/preview`;
// const downloadLink = `https://drive.google.com/uc?export=download&id=${fileId}`;
const images = [
"/jj7-blue.png", // index 0
"/jj7-white.png", // index 1
"/jj7-silver.png", // index 2
"/jj7-black.png", // index 3
"/j5-putih.png",
"/j5-hitam.png",
"/j5-silver.png",
"/j5-biru.png",
"/j5-hijau.png",
];
const gradients = [
"linear-gradient(to bottom, #527D97, #527D97)", // Hijau
"linear-gradient(to bottom, #FFFFFF, #FFFFFF)", // Silver
"linear-gradient(to bottom, #E1ECF4, #FFFFFF)", // Putih
"linear-gradient(to bottom, #1A1A1A, #3A3A3A)", // Hitam
"linear-gradient(to bottom, #FFFFFF, #FFFFFF)",
"linear-gradient(to bottom, #1A1A1A, #3A3A3A)",
"linear-gradient(to bottom, #B0B5C2, #B0B5C2)",
"linear-gradient(to bottom, #233a77, #233a77)",
"linear-gradient(to bottom, #5D6B4F, #5D6B4F)",
];
return (
<>
@ -46,9 +49,9 @@ export default function HeaderProductJ7Shs() {
transition={{ duration: 0.8 }}
className="flex flex-col items-center gap-6"
>
<div className="relative w-full h-[300px] sm:h-[400px] md:h-[700px] overflow-hidden">
<div className="relative w-full h-[300px] sm:h-[400px] md:h-[640px] overflow-hidden">
<Image
src="/shs-header.png"
src="/j5-new1.jpg"
alt="about-header"
fill
className="object-cover"
@ -56,88 +59,29 @@ export default function HeaderProductJ7Shs() {
priority
/>
{/* Tombol di dalam gambar, posisi bawah tengah */}
<div className="absolute bottom-4 left-1/2 transform -translate-x-1/2 flex items-center gap-3">
<Dialog open={openBrosur} onOpenChange={setOpenBrosur}>
<DialogTrigger asChild>
<Button className="bg-white text-black border w-[100px] h-[30px] md:w-[200px] md:h-[40px] rounded-xl hover:bg-amber-50 hover:cursor-pointer">
BROSUR
</Button>
</DialogTrigger>
<Link
href="https://cms.jaecoo.id/uploads/Flyer_J5_EV_Ver3_smaller_file_size_d81b0f960c.pdf"
target="_blank"
rel="noopener noreferrer"
>
<Button className="bg-white text-black border w-[100px] h-[30px] md:w-[200px] md:h-[40px] rounded-xl hover:bg-amber-50 hover:cursor-pointer">
BROSUR
</Button>
</Link>
<DialogContent className=" w-full p-0 overflow-hidden">
{/* Download Button */}
<div className="flex justify-end p-4 bg-white z-50">
<a
href={downloadLink}
target="_blank"
rel="noopener noreferrer"
className="absolute top-2 right-3 z-50 bg-black text-white p-2 rounded hover:bg-gray-800 mb-3"
>
<Download size={18} />
</a>
</div>
{/* Iframe Preview */}
<iframe
src={embedLink}
className="w-full h-[70vh] border-t"
allow="autoplay"
></iframe>
</DialogContent>
</Dialog>
{/* Trigger untuk modal */}
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Button className="bg-[#1F6779] text-white h-[30px] md:w-[200px] md:h-[40px] rounded-xl hover:cursor-pointer">
TEST DRIVE
</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-[1400px] h-[600px]">
<div className="flex items-center gap-4">
<Image
src="/masjaecoonav.png"
alt="MAS JAECOO Logo"
width={300}
height={30}
className=" object-fill"
/>
</div>
<DialogHeader>
<DialogTitle className="text-4xl text-center mb-4 font-bold">
FORM TEST DRIVE
</DialogTitle>
</DialogHeader>
{/* Form */}
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4 px-10">
<Input placeholder="Nama" />
<Input placeholder="Email" />
<Input placeholder="Mobile Number" />
<Input placeholder="Location" />
</div>
<div className="mt-3 px-10">
<Textarea placeholder="Full Message" rows={4} />
</div>
<div className="mt-6 text-left ml-10">
<Button
onClick={() => setOpen(false)}
className="bg-[#1F6779] text-white rounded-full"
>
SEND INQUIRY
</Button>
</div>
</DialogContent>
</Dialog>
<Link
href={`mailto:jaecookelapagading@gmail.com?subject=Test Drive J5 EV &body=Halo Jaecoo,%0D%0A%0D%0ASaya tertarik untuk melakukan test drive kendaraan J5 EV.%0D%0A%0D%0ANama:%0D%0ANomor HP:%0D%0ALokasi:%0D%0A%0D%0ATerima kasih.`}
>
<Button className="bg-[#1F6779] text-white h-[30px] md:h-[40px] rounded-full hover:cursor-pointer">
TEST DRIVE
</Button>
</Link>
</div>
</div>
</motion.div>
</section>
{/* Section warna */}
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}

View File

@ -14,28 +14,24 @@ import {
import { motion } from "framer-motion";
import { useState } from "react";
import { Download } from "lucide-react";
import Link from "next/link";
export default function HeaderProductJ8Awd() {
const [open, setOpen] = useState(false);
const [selectedColorIndex, setSelectedColorIndex] = useState(0);
const [openBrosur, setOpenBrosur] = useState(false);
const fileId = "1Nici3bdjUG524sUYQgHfbeO63xW6f1_o";
const fileLink = `https://drive.google.com/file/d/${fileId}/view`;
const embedLink = `https://drive.google.com/file/d/${fileId}/preview`;
const downloadLink = `https://drive.google.com/uc?export=download&id=${fileId}`;
// const fileId = "1Nici3bdjUG524sUYQgHfbeO63xW6f1_o";
// const fileLink = `https://drive.google.com/file/d/${fileId}/view`;
// const embedLink = `https://drive.google.com/file/d/${fileId}/preview`;
// const downloadLink = `https://drive.google.com/uc?export=download&id=${fileId}`;
const images = [
"/green.png", // index 0
"/silver.png", // index 1
"/white.png", // index 3
"/black.png", // index 2
];
const images = ["/green.png", "/silver.png", "/white.png", "/black.png"];
const gradients = [
"linear-gradient(to bottom, #527D97, #1F6779)", // Hijau
"linear-gradient(to bottom, #FFFFFF, #FFFFFF)", // Silver
"linear-gradient(to bottom, #E1ECF4, #FFFFFF)", // Putih
"linear-gradient(to bottom, #1A1A1A, #3A3A3A)", // Hitam
"linear-gradient(to bottom, #527D97, #1F6779)",
"linear-gradient(to bottom, #FFFFFF, #FFFFFF)",
"linear-gradient(to bottom, #E1ECF4, #FFFFFF)",
"linear-gradient(to bottom, #1A1A1A, #3A3A3A)",
];
return (
<>
@ -56,9 +52,8 @@ export default function HeaderProductJ8Awd() {
priority
/>
{/* Tombol di dalam gambar, posisi bawah tengah */}
<div className="absolute bottom-4 left-1/2 transform -translate-x-1/2 flex items-center gap-3">
<Dialog open={openBrosur} onOpenChange={setOpenBrosur}>
{/* <Dialog open={openBrosur} onOpenChange={setOpenBrosur}>
<DialogTrigger asChild>
<Button className="bg-white text-black border w-[100px] h-[30px] md:w-[200px] md:h-[40px] rounded-xl hover:bg-amber-50 hover:cursor-pointer">
BROSUR
@ -66,7 +61,6 @@ export default function HeaderProductJ8Awd() {
</DialogTrigger>
<DialogContent className=" w-full p-0 overflow-hidden">
{/* Download Button */}
<div className="flex justify-end p-4 bg-white z-50">
<a
href={downloadLink}
@ -78,66 +72,34 @@ export default function HeaderProductJ8Awd() {
</a>
</div>
{/* Iframe Preview */}
<iframe
src={embedLink}
className="w-full h-[70vh] border-t"
allow="autoplay"
></iframe>
</DialogContent>
</Dialog>
{/* Trigger untuk modal */}
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Button className="bg-[#1F6779] text-white h-[30px] md:w-[200px] md:h-[40px] rounded-xl hover:cursor-pointer">
TEST DRIVE
</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-[1400px] h-[600px]">
<div className="flex items-center gap-4">
<Image
src="/masjaecoonav.png"
alt="MAS JAECOO Logo"
width={300}
height={30}
className=" object-fill"
/>
</div>
<DialogHeader>
<DialogTitle className="text-4xl text-center mb-4 font-bold">
FORM TEST DRIVE
</DialogTitle>
</DialogHeader>
{/* Form */}
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4 px-10">
<Input placeholder="Nama" />
<Input placeholder="Email" />
<Input placeholder="Mobile Number" />
<Input placeholder="Location" />
</div>
<div className="mt-3 px-10">
<Textarea placeholder="Full Message" rows={4} />
</div>
<div className="mt-6 text-left ml-10">
<Button
onClick={() => setOpen(false)}
className="bg-[#1F6779] text-white rounded-full"
>
SEND INQUIRY
</Button>
</div>
</DialogContent>
</Dialog>
</Dialog> */}
<Link
href="https://cms.jaecoo.id/uploads/J8_SHS_ARDIS_Flyer_cbf280ea77.pdf"
target="_blank"
rel="noopener noreferrer"
>
<Button className="bg-white text-black border w-[100px] h-[30px] md:w-[200px] md:h-[40px] rounded-xl hover:bg-amber-50 hover:cursor-pointer">
BROSUR
</Button>
</Link>
<Link
href={`mailto:jaecookelapagading@gmail.com?subject=Test Drive J8 SHS-P ARDIS &body=Halo Jaecoo,%0D%0A%0D%0ASaya tertarik untuk melakukan test drive kendaraan J8 SHS-P ARDIS.%0D%0A%0D%0ANama:%0D%0ANomor HP:%0D%0ALokasi:%0D%0A%0D%0ATerima kasih.`}
>
<Button className="bg-[#1F6779] text-white h-[30px] md:h-[40px] rounded-full hover:cursor-pointer">
TEST DRIVE
</Button>
</Link>
</div>
</div>
</motion.div>
</section>
{/* Section warna */}
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}

View File

@ -20,13 +20,13 @@ const items = [
image: "/new-car2.png",
title: "JAECOO J7 SHS-P",
description: "DELICATE OFF-ROAD SUV",
link: "/product/j7-awd",
link: "/product/j7-shs-p",
},
{
image: "/new-car1.png",
image: "/j5-ev-new.png",
title: "JAECOO J5 EV",
description: "SUPER HYBRID SYSTEM = SUPER HEV + EV",
link: "/product/j7-shs",
link: "/product/j5-ev",
},
{
image: "/new-car3.png",
@ -87,7 +87,7 @@ export default function Items() {
animate={{ opacity: 1, y: 0 }}
transition={{ delay: index * 0.25 + 0.6, duration: 0.6 }}
>
<Dialog open={open} onOpenChange={setOpen}>
{/* <Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Button className="bg-[#1F6779] text-white h-[30px] md:h-[40px] rounded-full hover:cursor-pointer">
TEST DRIVE
@ -109,7 +109,7 @@ export default function Items() {
</DialogTitle>
</DialogHeader>
{/* Form */}
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4 px-10">
<Input placeholder="Nama" />
<Input placeholder="Email" />
@ -130,7 +130,15 @@ export default function Items() {
</Button>
</div>
</DialogContent>
</Dialog>
</Dialog> */}
<Link
href={`mailto:jaecookelapagading@gmail.com?subject=Test Drive ${item.title}&body=Halo Jaecoo,%0D%0A%0D%0ASaya tertarik untuk melakukan test drive kendaraan ${item.title}.%0D%0A%0D%0ANama:%0D%0ANomor HP:%0D%0ALokasi:%0D%0A%0D%0ATerima kasih.`}
>
<Button className="bg-[#1F6779] text-white h-[30px] md:h-[40px] rounded-full hover:cursor-pointer">
TEST DRIVE
</Button>
</Link>
<Link href={item?.link}>
<Button
variant="outline"

View File

@ -195,50 +195,13 @@ export default function Navbar() {
/>
<p className="font-bold mt-4 text-center">{car.name}</p>
<div className="flex flex-col sm:flex-row gap-2 mt-2 items-center">
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Button className="bg-[#1F6779] text-white h-[30px] md:w-[200px] md:h-[40px] rounded-full hover:cursor-pointer">
TEST DRIVE
</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-[1400px] h-[600px]">
<div className="flex items-center gap-4">
<Image
src="/masjaecoonav.png"
alt="MAS JAECOO Logo"
width={300}
height={30}
className=" object-fill"
/>
</div>
<DialogHeader>
<DialogTitle className="text-4xl text-center mb-4 font-bold">
FORM TEST DRIVE
</DialogTitle>
</DialogHeader>
{/* Form */}
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4 px-10">
<Input placeholder="Nama" />
<Input placeholder="Email" />
<Input placeholder="Mobile Number" />
<Input placeholder="Location" />
</div>
<div className="mt-3 px-10">
<Textarea placeholder="Full Message" rows={4} />
</div>
<div className="mt-6 text-left ml-10">
<Button
onClick={() => setOpen(false)}
className="bg-[#1F6779] text-white rounded-full"
>
SEND INQUIRY
</Button>
</div>
</DialogContent>
</Dialog>
<Link
href={`mailto:jaecookelapagading@gmail.com?subject=Test Drive ${car?.name} &body=Halo Jaecoo,%0D%0A%0D%0ASaya tertarik untuk melakukan test drive kendaraan ${car?.name}.%0D%0A%0D%0ANama:%0D%0ANomor HP:%0D%0ALokasi:%0D%0A%0D%0ATerima kasih.`}
>
<Button className="bg-[#1F6779] text-white h-[30px] md:h-[40px] rounded-full hover:cursor-pointer">
TEST DRIVE
</Button>
</Link>
<Link href={car.link} className="w-[200px]">
<Button
variant="outline"

View File

@ -5,7 +5,7 @@ import Image from "next/image";
import { ArrowRight } from "lucide-react";
import Link from "next/link";
const tabs = ["INSTAGRAM", "TIKTOK", "FACEBOOK", "YOUTUBE"];
const tabs = ["INSTAGRAM", "TIKTOK"];
const instagramPosts = ["/ig1-new.png", "/ig2-new.png", "/ig3-new.png"];
const tiktokPosts = ["/tk1.png", "/tk2.png", "/tk3.png"];

BIN
public/Asset18.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

BIN
public/Asset19.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 MiB

BIN
public/Asset20.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

BIN
public/Asset21.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 MiB

View File

@ -0,0 +1,125 @@
"use client";
import Image from "next/image";
import { Button } from "../ui/button";
import { Input } from "../ui/input";
import { Textarea } from "../ui/textarea";
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "../ui/dialog";
import { motion } from "framer-motion";
import { useState } from "react";
import { Download } from "lucide-react";
import Link from "next/link";
export default function HeaderProductJ5Ev() {
const [open, setOpen] = useState(false);
const [selectedColorIndex, setSelectedColorIndex] = useState(0);
const [openBrosur, setOpenBrosur] = useState(false);
// const fileId = "1Nici3bdjUG524sUYQgHfbeO63xW6f1_o";
// const fileLink = `https://drive.google.com/file/d/${fileId}/view`;
// const embedLink = `https://drive.google.com/file/d/${fileId}/preview`;
// const downloadLink = `https://drive.google.com/uc?export=download&id=${fileId}`;
const images = [
"/j5-putih.png",
"/j5-hitam.png",
"/j5-silver.png",
"/j5-biru.png",
"/j5-hijau.png",
];
const gradients = [
"linear-gradient(to bottom, #FFFFFF, #FFFFFF)",
"linear-gradient(to bottom, #1A1A1A, #3A3A3A)",
"linear-gradient(to bottom, #B0B5C2, #B0B5C2)",
"linear-gradient(to bottom, #233a77, #233a77)",
"linear-gradient(to bottom, #5D6B4F, #5D6B4F)",
];
return (
<>
<section className="py-10 px-4 sm:px-6 md:px-10 bg-white">
<motion.div
initial={{ opacity: 0, y: 50 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8 }}
className="flex flex-col items-center gap-6"
>
<div className="relative w-full h-[300px] sm:h-[400px] md:h-[640px] overflow-hidden">
<Image
src="/j5-new1.jpg"
alt="about-header"
fill
className="object-cover"
sizes="(max-width: 768px) 100vw, 640px"
priority
/>
<div className="absolute bottom-4 left-1/2 transform -translate-x-1/2 flex items-center gap-3">
<Link
href="https://cms.jaecoo.id/uploads/Flyer_J5_EV_Ver3_smaller_file_size_d81b0f960c.pdf"
target="_blank"
rel="noopener noreferrer"
>
<Button className="bg-white text-black border w-[100px] h-[30px] md:w-[200px] md:h-[40px] rounded-xl hover:bg-amber-50 hover:cursor-pointer">
BROSUR
</Button>
</Link>
<Link
href={`mailto:jaecookelapagading@gmail.com?subject=Test Drive J5 EV &body=Halo Jaecoo,%0D%0A%0D%0ASaya tertarik untuk melakukan test drive kendaraan J5 EV.%0D%0A%0D%0ANama:%0D%0ANomor HP:%0D%0ALokasi:%0D%0A%0D%0ATerima kasih.`}
>
<Button className="bg-[#1F6779] text-white h-[30px] md:h-[40px] rounded-full hover:cursor-pointer">
TEST DRIVE
</Button>
</Link>
</div>
</div>
</motion.div>
</section>
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 0.5, duration: 0.8 }}
className="relative w-full h-[200px] sm:h-[400px] md:h-[740px] overflow-hidden"
>
<div className="relative w-full h-[200px] sm:h-[300px] md:h-[740px] lg:h-[740px]">
<Image
src={images[selectedColorIndex]}
alt="about-header"
fill
className="object-cover"
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 100vw, 1400px"
priority
/>
</div>
<motion.div
initial={{ opacity: 0, x: -40 }}
animate={{ opacity: 1, x: 0 }}
transition={{ delay: 0.8, duration: 0.6 }}
className="absolute top-32 md:top-1/2 left-14 md:left-56 transform -translate-y-1/2 flex flex-col gap-4 z-10"
>
{gradients.map((bg, index) => (
<motion.button
key={index}
onClick={() => setSelectedColorIndex(index)}
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.95 }}
className={`w-4 h-4 md:w-6 md:h-6 rounded-full border-2 ${
selectedColorIndex === index ? "border-black" : "border-white"
} shadow-md hover:cursor-pointer`}
style={{ background: bg }}
aria-label={`Pilih warna ${index + 1}`}
/>
))}
</motion.div>
</motion.div>
</>
);
}

BIN
public/j5-biru.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 523 KiB

BIN
public/j5-ev-new.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

BIN
public/j5-hijau.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 KiB

BIN
public/j5-hitam.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 520 KiB

BIN
public/j5-new1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 MiB

BIN
public/j5-putih.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 519 KiB

BIN
public/j5-silver.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 525 KiB

View File

@ -17,6 +17,11 @@ export async function getGaleryFileData(props: PaginationRequest) {
return await httpGetInterceptor(`/gallery-files`);
}
// untuk list files
export async function getAllGaleryFiles() {
return await httpGetInterceptor(`/gallery-files`);
}
export async function getGaleryById(id: any) {
const headers = {
"content-type": "application/json",