Commit 37a17b24 by Ravindra Kanojiya

updated layout type

1 parent 1d1d2075
...@@ -33,6 +33,7 @@ function splitAfterParagraphs(html = "", count = 2) { ...@@ -33,6 +33,7 @@ function splitAfterParagraphs(html = "", count = 2) {
} }
const AboutInfo = ({ productData }) => { const AboutInfo = ({ productData }) => {
console.log("productData-333", productData)
const [expanded, setExpanded] = useState(false); const [expanded, setExpanded] = useState(false);
const { preview, rest } = splitAfterParagraphs(productData?.description, 2); const { preview, rest } = splitAfterParagraphs(productData?.description, 2);
...@@ -40,7 +41,7 @@ const AboutInfo = ({ productData }) => { ...@@ -40,7 +41,7 @@ const AboutInfo = ({ productData }) => {
return ( return (
<> <>
<section className="about-section about-info-section pb-0"> <section className="about-section about-info-section">
<div className="custom_container container"> <div className="custom_container container">
<Row className="text-center justify-content-center"> <Row className="text-center justify-content-center">
<Col md={8}> <Col md={8}>
......
...@@ -5,7 +5,7 @@ import Image from "next/image"; ...@@ -5,7 +5,7 @@ import Image from "next/image";
import { cleanImage } from "../services/imageHandling"; import { cleanImage } from "../services/imageHandling";
const CompanyOverview = ({ companyOverviewData }) => { const CompanyOverview = ({ companyOverviewData }) => {
console.log(companyOverviewData,"companyOverviewData")
return ( return (
<> <>
<section className="about-section about-info-section p-0"> <section className="about-section about-info-section p-0">
......
...@@ -15,6 +15,7 @@ const galleryData = [ ...@@ -15,6 +15,7 @@ const galleryData = [
]; ];
const Gallery = ({ productData }) => { const Gallery = ({ productData }) => {
console.log(productData,"productData-gallery")
useEffect(() => { useEffect(() => {
Fancybox.bind("[data-fancybox='gallery']", { Fancybox.bind("[data-fancybox='gallery']", {
......
import React, { useRef, useEffect, useState } from "react"; import React, { useRef, useEffect, useState } from "react";
import Image from "next/image";
import { cleanImage } from "../services/imageHandling"; import { cleanImage } from "../services/imageHandling";
const Video = ({ productData }) => { const Video = ({ productData }) => {
const mediaRef = useRef(null); const videoRef = useRef(null);
const [isVisible, setIsVisible] = useState(false); const [isVisible, setIsVisible] = useState(false);
const media = productData?.video; const media = productData?.video;
const isVideo = media?.mime?.startsWith("video/"); // ✅ 1. Hide component if no video
const isImage = media?.mime?.startsWith("image/"); if (!media?.url) return null;
// ✅ Strapi default image path
const defaultImage = "/image/default.svg";
useEffect(() => { useEffect(() => {
// ✅ 2. Guard for SSR (Next.js safety)
if (typeof window === "undefined") return;
const observer = new IntersectionObserver( const observer = new IntersectionObserver(
([entry]) => { ([entry]) => {
if (entry.isIntersecting) { if (entry.isIntersecting) {
setIsVisible(true); setIsVisible(true);
observer.unobserve(entry.target);
// ✅ Stop observing after first trigger
if (videoRef.current) {
observer.unobserve(videoRef.current);
}
} }
}, },
{ threshold: 0.5 } { threshold: 0.5 }
); );
if (mediaRef.current) observer.observe(mediaRef.current); if (videoRef.current) {
observer.observe(videoRef.current);
}
return () => { return () => {
if (mediaRef.current) observer.unobserve(mediaRef.current); if (videoRef.current) {
observer.unobserve(videoRef.current);
}
}; };
}, []); }, []);
return ( return (
<section className="video_sec"> <section className="video_sec">
<div className="custom_containers"> <div className="custom_containers">
{/* VIDEO */}
{isVideo && (
<video <video
ref={mediaRef} ref={videoRef}
autoPlay autoPlay
muted muted
loop loop
playsInline playsInline
className={`w-100 video-animate ${isVisible ? "video-visible" : ""}`} className={`w-100 video-animate ${
isVisible ? "video-visible" : ""
}`}
> >
<source src={cleanImage(media?.url)} type={media?.mime || "video/mp4"} /> <source
</video> src={cleanImage(media.url)}
)} type={media.mime || "video/mp4"}
{/* IMAGE */}
{isImage && (
<div
ref={mediaRef}
className={`w-100 video-animate ${isVisible ? "video-visible" : ""}`}
>
<Image
src={cleanImage(media?.url)}
alt={media?.alternativeText || "Media"}
width={media?.width || 868}
height={media?.height || 560}
className="w-100"
/>
</div>
)}
{/* DEFAULT IMAGE */}
{!media && (
<div
ref={mediaRef}
className={`w-100 video-animate ${isVisible ? "video-visible" : ""}`}
>
<Image
src={cleanImage()}
alt="Default Image"
width={868}
height={560}
className="w-100"
/> />
</div> Your browser does not support the video tag.
)} </video>
</div> </div>
</section> </section>
); );
......
import React, { useState } from "react";
import { Col, Row } from "react-bootstrap";
import Heading from "@/components/Heading";
import Link from "next/link";
/**
* Splits an HTML string into:
* - the first `count` <p>…</p> blocks
* - everything that comes after them
*/
function splitAfterParagraphs(html = "", count = 2) {
if (!html) return { preview: "", rest: "" };
// Match each <p …>…</p> block (handles multiline content)
const regex = /<p[\s\S]*?<\/p>/gi;
const matches = [];
let match;
while ((match = regex.exec(html)) !== null) {
matches.push({ start: match.index, end: match.index + match[0].length });
}
if (matches.length <= count) {
// Not enough paragraphs to hide anything
return { preview: html, rest: "" };
}
const splitIndex = matches[count - 1].end;
return {
preview: html.slice(0, splitIndex),
rest: html.slice(splitIndex),
};
}
const AboutInfo = ({ productData }) => {
const [expanded, setExpanded] = useState(false);
const { preview, rest } = splitAfterParagraphs(productData?.description, 2);
const hasMore = rest.trim().length > 0;
return (
<>
<section className="about-section about-info-section">
<div className="custom_container container">
<Row className="text-center justify-content-center">
<Col md={8}>
<Heading el="h2" heading={productData?.title || ""} isHtml />
{/* Always-visible first 2 paragraphs */}
<div
className="mb-0 gray-text"
dangerouslySetInnerHTML={{ __html: preview }}
/>
{/* Hidden/shown extra content */}
{hasMore && (
<>
<div className={`expandable-content ${expanded ? "expanded" : ""}`}>
<div className="inner-content">
<div
className="mb-0 gray-text"
dangerouslySetInnerHTML={{ __html: rest }}
/>
</div>
</div>
<Link
href="#!"
onClick={(e) => {
e.preventDefault();
setExpanded((prev) => !prev);
}}
className="btn4 mt-3"
>
{expanded ? "Read Less" : "Read More"} <i className="fa-solid fa-arrow-right"></i>
</Link>
</>
)}
</Col>
</Row>
</div>
</section>
<style jsx>{`
.expandable-content {
display: grid;
grid-template-rows: 0fr;
transition: grid-template-rows 0.4s ease-in-out;
}
.expandable-content .inner-content {
overflow: hidden;
}
.expandable-content.expanded {
grid-template-rows: 1fr;
}
`}</style>
</>
);
};
export default AboutInfo;
import React from 'react'
import { Col, Row } from 'react-bootstrap'
import { cleanImage } from '../services/imageHandling'
const DetailsData = [
{
title: "",
description: "Thanks to the special technology of Valcucine’s Artematica® door, composed of an anodized aluminum structural frame and an aesthetic panel just 5 mm thick, we are able to offer the lightest natural stone kitchen on the market. The integration of a composite honeycomb panel with carbon fiber also ensures its solidity, increasing resistance to impacts.",
image:"/image/stain-resistance/01.png",
},
{
title: "Continuity of veining",
description: "For all surfaces of natural stone kitchens, an acceptance check is carried out to ensure integrity and, for all adjacent faces, vein continuity where possible. This check is repeated at the end of all processing stages to ensure full conformity of the product shipped",
image:"/image/stain-resistance/02.png",
},
{
title: "Care in the handling of materials",
description: "All the materials in Valcucine, including the natural stone doors, from the moment they are received to the moment they are packed, are handled with the utmost care and with special surfaces that preserve their integrity and aesthetic qualities.",
image:"/image/stain-resistance/03.png",
},
{
title: "Packaging and shipping",
description: "To ensure integrity during each stage of handling and shipping. All natural stone tops and doors are packed with special protective cages made of wood or chipboard, depending on the destination. The doors are additionally protected with perimeter protection and wrapped in bubble wrap.",
image:"/image/stain-resistance/04.png",
},
]
const Details = ({DetailsItem,bottomInfo}) => {
return (
<>
<section className="about-section about-info-section">
<div className="container">
<Row className="justify-content-center">
<Col md={12}>
{DetailsItem?.map((item, index) => {
const isEven = index % 2 === 0;
return (
<div className='stain-Details-item'>
<div className='row' key={index}>
{/* Content */}
<div className={`col-md-5 ${!isEven ? 'order-md-2' : ''}`}>
<div className='stain-Details-content'>
<h3>{item.title}</h3>
<div dangerouslySetInnerHTML={{ __html: item?.description || "" }} />
</div>
</div>
{/* Image */}
<div className={`col-md-7 ${!isEven ? 'order-md-1' : ''}`}>
<div className='stain-Details-image'>
<img className='img-fluid' src={cleanImage(item?.image?.url)} alt={item?.title || ''} />
</div>
</div>
</div>
</div>
);
})}
</Col>
</Row>
</div>
</section>
<section className="about-section about-info-section pt-0 mt-0">
<div className="container">
<Row className="justify-content-center text-center">
<Col md={12}>
<div className='mb-2 text-transform-uppercase'><strong>{bottomInfo?.title}</strong></div>
<div dangerouslySetInnerHTML={{ __html: bottomInfo?.description }} />
</Col>
</Row>
</div>
</section>
</>
)
}
export default Details
\ No newline at end of file \ No newline at end of file
import React from 'react'
import { Col, Row } from 'react-bootstrap'
import AboutInfo from './AboutInfo'
import Details from './Details'
const StoneFinishCabinet = ({ StoneFinishCabinet }) => {
console.log(StoneFinishCabinet, "StoneFinishCabinet")
return (
<>
<AboutInfo productData={StoneFinishCabinet?.aboutInfo} />
{StoneFinishCabinet?.detailsItem?.length > 0 && (
<Details
DetailsItem={StoneFinishCabinet.detailsItem}
bottomInfo={StoneFinishCabinet.bottomInfo}
/>
)}
</>
)
}
export default StoneFinishCabinet
\ No newline at end of file \ No newline at end of file
...@@ -13,9 +13,10 @@ import TechnicalDetails from "@/components/Collection/TechnicalDetails"; ...@@ -13,9 +13,10 @@ import TechnicalDetails from "@/components/Collection/TechnicalDetails";
import Explore from "@/components/Collection/Explore"; import Explore from "@/components/Collection/Explore";
import { Tab, Tabs } from "react-bootstrap"; import { Tab, Tabs } from "react-bootstrap";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import StoneFinishCabinet from "@/components/StoneFinishCabinet/StoneFinishCabinet";
const ProductPage = ({ productData, cataloguesData }) => { const ProductPage = ({ productData, cataloguesData }) => {
console.log("productData-new", productData)
const router = useRouter(); const router = useRouter();
const { category, subCategory: subCategorySlug, productSlug } = router.query; const { category, subCategory: subCategorySlug, productSlug } = router.query;
...@@ -46,13 +47,20 @@ const ProductPage = ({ productData, cataloguesData }) => { ...@@ -46,13 +47,20 @@ const ProductPage = ({ productData, cataloguesData }) => {
setActiveTab(productTabs[0].title); setActiveTab(productTabs[0].title);
} }
}, [productTabs]); }, [productTabs]);
const layoutType = productData?.LayoutsType;
const isDoorLayout =
layoutType === "Tabs Products" || layoutType === true;
const isStoneLayout =
layoutType === "Stone Finish Cabinet";
return ( return (
<> <>
<Breadcrumb breadcrumbData={breadcrumbData} /> <Breadcrumb breadcrumbData={breadcrumbData} />
<InnerBannerproduct productData={productData} /> <InnerBannerproduct productData={productData} />
{isDoorLayout ? (
{productData?.isDoorAndPartitionsLayouts == true ? (
<section className="details-tab-section"> <section className="details-tab-section">
<div className="custom_containers"> <div className="custom_containers">
<div className="details-tab"> <div className="details-tab">
...@@ -63,11 +71,7 @@ const ProductPage = ({ productData, cataloguesData }) => { ...@@ -63,11 +71,7 @@ const ProductPage = ({ productData, cataloguesData }) => {
className="tab-01" className="tab-01"
> >
{productTabs?.map((tab) => ( {productTabs?.map((tab) => (
<Tab <Tab key={tab.id} eventKey={tab.title} title={tab.title}>
key={tab.id}
eventKey={tab.title}
title={tab.title}
>
<AboutInfo productData={tab?.aboutInfo} /> <AboutInfo productData={tab?.aboutInfo} />
<CompanyOverview <CompanyOverview
...@@ -89,24 +93,37 @@ const ProductPage = ({ productData, cataloguesData }) => { ...@@ -89,24 +93,37 @@ const ProductPage = ({ productData, cataloguesData }) => {
</div> </div>
</div> </div>
</section> </section>
) : (<> ) : (
<>
<AboutInfo productData={productData?.aboutInfo} /> {
!isStoneLayout && <AboutInfo productData={productData?.aboutInfo} />
}
{productData?.aboutInfo?.length > 0 && (
<CompanyOverview companyOverviewData={productData?.companyOverview} /> <CompanyOverview companyOverviewData={productData?.companyOverview} />
<Video productData={productData?.video} /> )}
{isStoneLayout && (
<StoneFinishCabinet StoneFinishCabinet={productData?.aboutInfoStone} />
)}
{productData?.video && (
<Video productData={productData.video} />
)}
{productData?.technicalDetails?.length > 0 && ( {productData?.technicalDetails?.length > 0 && (
<TechnicalDetails productData={productData?.technicalDetails} /> <TechnicalDetails productData={productData?.technicalDetails} />
)} )}
{productData?.gallery?.length > 0 && (
<Gallery productData={productData?.gallery} /> <Gallery productData={productData?.gallery} />
)}
{/* <Explore productData={productData?.explore} /> */} {/* <Explore productData={productData?.explore} /> */}
</>)} </>
)}
{productData?.isDoorAndPartitionsLayouts && ( {isDoorLayout && (
<Explore productData={productData?.exploreProducts} /> <Explore productData={productData.exploreProducts} />
)} )}
{!productData?.isDoorAndPartitionsLayouts && ( {!isDoorLayout && (
<Catalogues cataloguesData={cataloguesData} /> <Catalogues cataloguesData={cataloguesData} />
)} )}
...@@ -128,8 +145,6 @@ const ProductPage = ({ productData, cataloguesData }) => { ...@@ -128,8 +145,6 @@ const ProductPage = ({ productData, cataloguesData }) => {
<Gallery productData={productData?.gallery} /> <Gallery productData={productData?.gallery} />
)} */} )} */}
<Contact /> <Contact />
</> </>
); );
...@@ -142,8 +157,6 @@ export async function getServerSideProps({ params }) { ...@@ -142,8 +157,6 @@ export async function getServerSideProps({ params }) {
try { try {
const { productSlug } = params; const { productSlug } = params;
const productData = await getCollectionDetailCategoryData(productSlug); const productData = await getCollectionDetailCategoryData(productSlug);
const cataloguesData = await getCataloguesBySlug(); const cataloguesData = await getCataloguesBySlug();
......
...@@ -56,12 +56,19 @@ const SubCategoryOrProductPage = ({ ...@@ -56,12 +56,19 @@ const SubCategoryOrProductPage = ({
setActiveTab(productTabs[0].title); setActiveTab(productTabs[0].title);
} }
}, [productTabs]); }, [productTabs]);
const layoutType = productData?.LayoutsType;
const isDoorLayout =
layoutType === "Tabs Products" || layoutType === true;
const isStoneLayout =
layoutType === "Stone Finish Cabinet";
return ( return (
<> <>
<Breadcrumb breadcrumbData={breadcrumbData} /> <Breadcrumb breadcrumbData={breadcrumbData} />
<InnerBannerproduct productData={productData} /> <InnerBannerproduct productData={productData} />
{productData?.isDoorAndPartitionsLayouts == true ? ( {isDoorLayout ? (
<section className="details-tab-section"> <section className="details-tab-section">
<div className="custom_containers"> <div className="custom_containers">
<div className="details-tab"> <div className="details-tab">
...@@ -74,7 +81,6 @@ const SubCategoryOrProductPage = ({ ...@@ -74,7 +81,6 @@ const SubCategoryOrProductPage = ({
{productTabs?.map((tab) => ( {productTabs?.map((tab) => (
<Tab key={tab.id} eventKey={tab.title} title={tab.title}> <Tab key={tab.id} eventKey={tab.title} title={tab.title}>
<AboutInfo productData={tab?.aboutInfo} /> <AboutInfo productData={tab?.aboutInfo} />
<CompanyOverview <CompanyOverview
companyOverviewData={tab?.companyOverview?.items} companyOverviewData={tab?.companyOverview?.items}
/> />
...@@ -96,12 +102,20 @@ const SubCategoryOrProductPage = ({ ...@@ -96,12 +102,20 @@ const SubCategoryOrProductPage = ({
</section> </section>
) : ( ) : (
<> <>
{/* {
productData?.aboutInfo?.length > 0 && (
<AboutInfo productData={productData?.aboutInfo} />
)
} */}
<AboutInfo productData={productData?.aboutInfo} /> <AboutInfo productData={productData?.aboutInfo} />
<CompanyOverview <CompanyOverview
companyOverviewData={productData?.companyOverview} companyOverviewData={productData?.companyOverview}
/> />
{/* <Video productData={productData?.video} /> */} {/* <Video productData={productData?.video} /> */}
<Video productData={productData?.video} /> <Video productData={productData?.video} />
{isStoneLayout && (
<StoneFinishCabinet StoneFinishCabinet={productData?.aboutInfoStone} />
)}
{productData?.technicalDetails?.length > 0 && ( {productData?.technicalDetails?.length > 0 && (
<TechnicalDetails productData={productData?.technicalDetails} /> <TechnicalDetails productData={productData?.technicalDetails} />
)} )}
...@@ -110,11 +124,11 @@ const SubCategoryOrProductPage = ({ ...@@ -110,11 +124,11 @@ const SubCategoryOrProductPage = ({
</> </>
)} )}
{productData?.isDoorAndPartitionsLayouts && ( {isDoorLayout && (
<Explore productData={productData?.exploreProducts} /> <Explore productData={productData.exploreProducts} />
)} )}
{!productData?.isDoorAndPartitionsLayouts && ( {!isDoorLayout && (
<Catalogues cataloguesData={cataloguesData} /> <Catalogues cataloguesData={cataloguesData} />
)} )}
......
...@@ -16,26 +16,26 @@ export async function getCollectionDetailCategoryData(productSlug) { ...@@ -16,26 +16,26 @@ export async function getCollectionDetailCategoryData(productSlug) {
}, },
gallery: { gallery: {
populate:{ populate: {
image: true, image: true,
}, },
}, },
aboutInfo: { aboutInfo: {
populate:true populate: true,
}, },
video: { video: {
populate:{ populate: {
video:true video: true,
} },
},
exploreProducts: {
populate: {
item: {
populate: {
image: true,
},
},
}, },
exploreProducts:{
populate:{
item:{
populate:{
image:true
}
}
}
}, },
productTabs: { productTabs: {
...@@ -43,22 +43,22 @@ export async function getCollectionDetailCategoryData(productSlug) { ...@@ -43,22 +43,22 @@ export async function getCollectionDetailCategoryData(productSlug) {
companyOverview: { companyOverview: {
populate: { populate: {
items: { items: {
populate:{ populate: {
image:true image: true,
} },
}, },
}, },
}, },
videoSection: { videoSection: {
populate: { populate: {
video:true video: true,
} },
}, },
aboutInfo: true, aboutInfo: true,
technicalDetails: { technicalDetails: {
populate: { populate: {
image: true, image: true,
details:true details: true,
}, },
}, },
gallery: { gallery: {
...@@ -66,7 +66,19 @@ export async function getCollectionDetailCategoryData(productSlug) { ...@@ -66,7 +66,19 @@ export async function getCollectionDetailCategoryData(productSlug) {
image: true, image: true,
}, },
}, },
},
},
aboutInfoStone: {
populate: {
aboutInfo: {
populate: "*",
},
detailsItem: {
populate: "*",
},
bottomInfo: {
populate: "*",
},
}, },
}, },
...@@ -85,7 +97,7 @@ export async function getCollectionDetailCategoryData(productSlug) { ...@@ -85,7 +97,7 @@ export async function getCollectionDetailCategoryData(productSlug) {
const response = await fetchFromStrapi( const response = await fetchFromStrapi(
"/api/collection-detail-categories", "/api/collection-detail-categories",
query query,
); );
return response?.data || []; return response?.data || [];
......
...@@ -1213,6 +1213,17 @@ footer a:hover { ...@@ -1213,6 +1213,17 @@ footer a:hover {
width: 100%; width: 100%;
object-fit: cover; object-fit: cover;
} }
.stain-Details-item{
background: #F5F5F5;
padding: 2rem;
margin-bottom: 2rem;
}
.stain-Details-content h3{
font-size: 1.04vw;
font-weight: 400;
color: #000;
padding-bottom: 0.2rem;
}
@media only screen and (max-width: 1023px) { @media only screen and (max-width: 1023px) {
body { body {
...@@ -1320,6 +1331,13 @@ footer a:hover { ...@@ -1320,6 +1331,13 @@ footer a:hover {
} }
/* ===Media query==== */ /* ===Media query==== */
@media (max-width: 767px) { @media (max-width: 767px) {
.about-section.about-info-section {
padding-bottom: 2rem;
padding-top: 2rem;
}
.stain-Details-content h3 {
font-size: 21px;
}
.we-care-section .img-banner img{ .we-care-section .img-banner img{
max-height: 300px; max-height: 300px;
} }
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!