summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiqdad <ahmadmiqdad27@gmail.com>2025-10-18 08:06:52 +0700
committerMiqdad <ahmadmiqdad27@gmail.com>2025-10-18 08:06:52 +0700
commit99cd996a1580e92097f4050c417cbf99597b2d5e (patch)
tree8808cf4445c9a139369ca313a35685ab3193826e
parentac06a21307d120ba7ac5318f1b1e54380a41fbce (diff)
parent6ece17db36fe86c91d560c2bc5921bf60d5b7694 (diff)
Merge branch 'new-release' of https://bitbucket.org/altafixco/next-indoteknik into cr_prod_card
merge
-rw-r--r--public/robots.txt13
-rw-r--r--src/lib/brand/components/BrandCard.jsx1
-rw-r--r--src/lib/brand/components/MediaCard.jsx42
-rw-r--r--src/lib/home/api/mediaNews.js0
-rw-r--r--src/lib/home/components/MediaNews.jsx82
-rw-r--r--src/lib/home/components/Skeleton/MediaNewsSkeleton.jsx21
-rw-r--r--src/pages/index.jsx3
7 files changed, 155 insertions, 7 deletions
diff --git a/public/robots.txt b/public/robots.txt
index 3972ad17..957708ad 100644
--- a/public/robots.txt
+++ b/public/robots.txt
@@ -2,6 +2,7 @@
# User-agent: *
# Version 1.0
+User-agent: /
User-agent: Googlebot
User-agent: Googlebot-mobile
Disallow: /shop/product/pdf/*
@@ -9,24 +10,22 @@ Disallow: /shop/product/wishlist/*
Disallow: /shop/product/https://*
Disallow: /v1/*
Disallow: /shop/search?*=*
-Disallow: /shop/cart/
-Disallow: /shop/checkout/
+Disallow: /shop/cart
+Disallow: /shop/checkout
Disallow: /my/*
Disallow: /shop/search/*
Disallow: /promo/*
Disallow: /shop/brands/*?*
Disallow: /shop/category/*?*
-Disallow: /login?*
-Disallow: /register?*
+Disallow: /shop/product/*?*
User-agent: Adsbot-Google
Allow: /my/*
Allow: /shop/search/*
User-agent: *
-Disallow: /sentral.indoteknik.com/
-Disallow: /erp.indoteknik.com/
-Disallow: /development.indoteknik.com/
+Disallow: sentral.indoteknik.com/*
+Disallow: erp.indoteknik.com/*
Sitemap: https://indoteknik.com/sitemap/products.xml
Sitemap: https://indoteknik.com/sitemap/brands.xml
diff --git a/src/lib/brand/components/BrandCard.jsx b/src/lib/brand/components/BrandCard.jsx
index dff61b24..411e2669 100644
--- a/src/lib/brand/components/BrandCard.jsx
+++ b/src/lib/brand/components/BrandCard.jsx
@@ -5,6 +5,7 @@ import { createSlug } from '@/core/utils/slug';
const BrandCard = ({ brand }) => {
const { isMobile } = useDevice();
+ // console.log("Brand logo:", brand.logo);
return (
<Link
href={createSlug('/shop/brands/', brand.name, brand.id)}
diff --git a/src/lib/brand/components/MediaCard.jsx b/src/lib/brand/components/MediaCard.jsx
new file mode 100644
index 00000000..4a298e15
--- /dev/null
+++ b/src/lib/brand/components/MediaCard.jsx
@@ -0,0 +1,42 @@
+import NextImage from 'next/image';
+import Link from '@/core/components/elements/Link/Link';
+import useDevice from '@/core/hooks/useDevice';
+import { createSlug } from '@/core/utils/slug';
+
+const MediaCard = ({ media }) => {
+ const { isMobile } = useDevice();
+
+ console.log("Media logo:", media);
+
+ return (
+ <Link
+ href={media.url || '#'}
+ className={`
+ py-1 px-2 border-gray_r-6 flex justify-center items-center
+ hover:scale-110 transition duration-500 ease-in-out
+ ${isMobile ? 'h-16' : 'h-24'}
+ `}
+ aria-label={media.name}
+ >
+ {media.image ? (
+ <NextImage
+ src={media.image}
+ alt={media.name}
+ width={500}
+ height={500}
+ quality={85}
+ className="h-full w-[122px] object-contain object-center"
+ />
+ ) : (
+ <span
+ className="text-center"
+ style={{ fontSize: `${16 - media.name.length * 0.5}px` }}
+ >
+ {media.name}
+ </span>
+ )}
+ </Link>
+ );
+};
+
+export default MediaCard;
diff --git a/src/lib/home/api/mediaNews.js b/src/lib/home/api/mediaNews.js
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/lib/home/api/mediaNews.js
diff --git a/src/lib/home/components/MediaNews.jsx b/src/lib/home/components/MediaNews.jsx
new file mode 100644
index 00000000..7c587b23
--- /dev/null
+++ b/src/lib/home/components/MediaNews.jsx
@@ -0,0 +1,82 @@
+import { Swiper, SwiperSlide } from 'swiper/react';
+import { Navigation, Pagination, Autoplay } from 'swiper';
+import { useEffect, useState, useCallback } from 'react';
+import MediaNewsSkeleton from './Skeleton/MediaNewsSkeleton';
+import MediaCard from '@/lib/brand/components/MediaCard';
+import useDevice from '@/core/hooks/useDevice';
+import Link from '@/core/components/elements/Link/Link';
+
+const MediaNews = () => {
+ const [isLoading, setIsLoading] = useState(true);
+ const [media, setMedia] = useState([]);
+ const { isMobile, isDesktop } = useDevice();
+
+ const loadMedia = useCallback(async () => {
+ try {
+ setIsLoading(true);
+ const res = await fetch(`/api/hero-banner?type=media-berita`);
+ const result = await res.json();
+ const data = result.data || [];
+ data.sort((a, b) => (a.sequence || 0) - (b.sequence || 0));
+ setMedia(data);
+ } catch (err) {
+ console.error('Failed to load media:', err);
+ } finally {
+ setIsLoading(false);
+ }
+ }, []);
+
+ useEffect(() => {
+ loadMedia();
+ }, [loadMedia]);
+
+ const swiperConfig = {
+ modules: [Navigation, Pagination, Autoplay],
+ autoplay: { delay: 4000, disableOnInteraction: false },
+ loop: true,
+ className: 'h-[70px] md:h-[100px] w-full',
+ slidesPerView: isMobile ? 4 : 8,
+ spaceBetween: isMobile ? 12 : 0,
+ pagination: { dynamicBullets: true, dynamicMainBullets: isMobile ? 6 : 8, clickable: true },
+ };
+
+ const preferredMediaData = media.slice(0, 20);
+
+ const shouldUseSlider = isMobile || (isDesktop && preferredMediaData.length > 8);
+
+ if (!isLoading && preferredMediaData.length === 0) {
+ return null;
+ }
+
+ return (
+ <div className="px-4 sm:px-0">
+ <div className="flex justify-between items-center mb-4">
+ <h1 className="font-semibold text-[14px] sm:text-h-lg">
+ <Link href="/" className="!text-black font-semibold">
+ Telah Diliput Media
+ </Link>
+ </h1>
+ </div>
+
+ {isLoading ? (
+ <MediaNewsSkeleton />
+ ) : shouldUseSlider ? (
+ <Swiper {...swiperConfig}>
+ {preferredMediaData.map((item) => (
+ <SwiperSlide key={item.id}>
+ <MediaCard media={item} />
+ </SwiperSlide>
+ ))}
+ </Swiper>
+ ) : (
+ <div className="flex flex-wrap justify-center gap-4">
+ {preferredMediaData.map((item) => (
+ <MediaCard key={item.id} media={item} />
+ ))}
+ </div>
+ )}
+ </div>
+ );
+};
+
+export default MediaNews;
diff --git a/src/lib/home/components/Skeleton/MediaNewsSkeleton.jsx b/src/lib/home/components/Skeleton/MediaNewsSkeleton.jsx
new file mode 100644
index 00000000..c0151efd
--- /dev/null
+++ b/src/lib/home/components/Skeleton/MediaNewsSkeleton.jsx
@@ -0,0 +1,21 @@
+import useDevice from '@/core/hooks/useDevice'
+import Skeleton from 'react-loading-skeleton'
+
+const MediaNewsSkeleton = () => {
+ const { isDesktop } = useDevice()
+
+ return (
+ <div className="grid grid-cols-4 md:grid-cols-8 gap-x-3">
+ {Array.from({ length: isDesktop ? 8 : 4 }, (_, index) => (
+ <Skeleton
+ key={index}
+ count={1}
+ height={isDesktop ? 84 : 56}
+ className="rounded-lg"
+ />
+ ))}
+ </div>
+ )
+}
+
+export default MediaNewsSkeleton
diff --git a/src/pages/index.jsx b/src/pages/index.jsx
index 809f00ae..28db4d3e 100644
--- a/src/pages/index.jsx
+++ b/src/pages/index.jsx
@@ -9,6 +9,7 @@ import PagePopupInformation from '@/lib/home/components/PopupBannerPromotion';
import dynamic from 'next/dynamic';
import { useRef } from 'react';
import { getAuth } from '~/libs/auth';
+import MediaNews from '../lib/home/components/MediaNews';
const BasicLayout = dynamic(() =>
import('@/core/components/layouts/BasicLayout')
@@ -139,6 +140,7 @@ export default function Home({ categoryId }) {
<div className='my-16 flex flex-col gap-y-8'>
<ServiceList />
+ <MediaNews />
<div id='flashsale'>
<PreferredBrand />
</div>
@@ -169,6 +171,7 @@ export default function Home({ categoryId }) {
<div className='flex flex-col gap-y-4 my-6'>
<DelayRender renderAfter={400}>
<ServiceList />
+ <MediaNews />
</DelayRender>
<DelayRender renderAfter={400}>
<div id='flashsale'>