Commit 06379f89 by sujata

new project

0 parents
Showing 125 changed files with 2394 additions and 0 deletions
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# env files (can opt-in for committing if needed)
.env*
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/pages/api-reference/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.
[API routes](https://nextjs.org/docs/pages/building-your-application/routing/api-routes) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`.
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/pages/building-your-application/routing/api-routes) instead of React pages.
This project uses [`next/font`](https://nextjs.org/docs/pages/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn-pages-router) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/pages/building-your-application/deploying) for more details.
import { motion } from "framer-motion";
const containerVariant = {
hidden: {},
visible: {
transition: {
staggerChildren: 0.2,
},
},
};
// Utility to generate different variants
const getVariant = ({ direction = "up", distance = 20, duration = 0.6 }) => {
let x = 0, y = 0;
if (direction === "up") y = distance;
else if (direction === "down") y = -distance;
else if (direction === "left") x = distance;
else if (direction === "right") x = -distance;
return {
hidden: { opacity: 0, x, y },
visible: {
opacity: 1,
x: 0,
y: 0,
transition: {
duration,
ease: "easeOut",
},
},
};
};
const FadeInStagger = ({
children,
direction = "up", // "up", "down", "left", "right"
distance = 20, // pixel distance of movement
duration = 0.6, // seconds
className,
stagger = 0.2, // stagger timing for children
once = false,
amount = 0.3 // how much of the component needs to be visible to trigger
}) => {
const itemVariant = getVariant({ direction, distance, duration });
return (
<motion.div
className={className}
variants={{
...containerVariant,
visible: {
...containerVariant.visible,
transition: { staggerChildren: stagger },
},
}}
initial="hidden"
whileInView="visible"
viewport={{ once, amount }}
>
{Array.isArray(children)
? children.map((child, index) => (
<motion.div key={index} variants={itemVariant}>
{child}
</motion.div>
))
: <motion.div variants={itemVariant}>{children}</motion.div>}
</motion.div>
);
};
export default FadeInStagger;
import React, { useRef } from "react";
import { motion, useInView } from "framer-motion";
const splitText = (text) =>
(text || "").toString().split("").map((char, index) => ({
char,
key: `${char}-${index}`,
}));
const Heading = ({
el: Wrapper = "h2",
subheading = "",
heading = [],
className = "",
}) => {
const headingArray = Array.isArray(heading) ? heading : [heading];
const headingVariants = {
hidden: { opacity: 0.2, y: 0 },
visible: (i) => ({
opacity: 1,
y: 0,
transition: {
delay: i * 0.05,
},
}),
};
return (
<div className={`headings mb-3 ${className}`}>
<Wrapper className="subheading">{subheading}</Wrapper>
<div className="heading-container">
{headingArray.length > 0 &&
headingArray.map((item, index) => (
<InViewWrapper key={index}>
{splitText(item).map((char, i) => (
<motion.span
key={char.key}
custom={i}
initial="hidden"
animate="visible"
variants={headingVariants}
className="heading"
style={{ display: "inline-block" }} // No whiteSpace or word-wrap styles here
>
{char.char === " " ? "\u00A0" : char.char}
</motion.span>
))}
</InViewWrapper>
))}
</div>
</div>
);
};
const InViewWrapper = ({ children }) => {
const ref = useRef(null);
const isInView = useInView(ref, { triggerOnce: true, threshold: 0.1 });
return (
<div ref={ref}>
{React.Children.map(children, (child) =>
React.cloneElement(child, { animate: isInView ? "visible" : "hidden" })
)}
</div>
);
};
export default Heading;
import React from "react";
import { Container, Row, Col } from "react-bootstrap";
import Image from "next/image";
import Link from "next/link";
const Footer = () => {
return (
<footer className="footer">
<Container className="custom_container py-5">
<Row className="gy-4">
{/* Left - Logo + Contact Info */}
<Col lg={3} md={6} className="footer-cotent">
<Image
src="/image/footer-logo.png"
alt="logo"
width={180}
height={40}
className="mb-3"
/>
<ul className="list-unstyled">
<li className="d-flex mb-3 gap-2">
<i className="fa-solid fa-location-dot"></i>
<span>
9th Floor, Nirmal Building, Nariman Point,
<br /> Mumbai 400021, Maharashtra, India
</span>
</li>
<li className="d-flex align-items-center mb-3 gap-2">
<i className="fa-solid fa-envelope"></i>
<a href="mailto:support@akruti.luxe.com">
support@akruti.luxe.com
</a>
</li>
<li className="d-flex align-items-center gap-2">
<i className="fa-solid fa-phone"></i>
<a href="tel:+919236546126">
+91 92365 46126
</a>
</li>
</ul>
</Col>
{/* Quick Links */}
<Col lg={3} md={6} className="footer-cotent ps-md-4">
<h6 className="fw-bold mb-3">Quick Links</h6>
<ul className="list-unstyled">
<li className="mb-3">
<Link href="/about">
About
</Link>
</li>
<li className="mb-3">
<Link href="/collections">
Collections
</Link>
</li>
<li className="mb-3">
<Link href="/brands">
Brands
</Link>
</li>
<li className="mb-3">
<Link href="/products">
Products
</Link>
</li>
<li>
<Link href="/projects">
Projects
</Link>
</li>
</ul>
</Col>
{/* Collections */}
<Col lg={3} md={6} className="footer-cotent ps-md-4">
<h6 className="fw-bold mb-3">Collections</h6>
<ul className="list-unstyled">
<li className="mb-3">
<Link href="/collections/kitchens">
Kitchens
</Link>
</li>
<li className="mb-3">
<Link href="/collections/wardrobes">
Wardrobes and Systems
</Link>
</li>
<li>
<Link href="/collections/surface">
Surface
</Link>
</li>
</ul>
</Col>
{/* Policies */}
<Col lg={3} md={6} className="ps-md-4">
<h6 className="fw-bold mb-3">Policies</h6>
<ul className="list-unstyled">
<li className="mb-3">
<Link href="/privacy-policy">
Privacy Policy
</Link>
</li>
<li className="mb-3">
<Link href="/terms">
Terms and Conditions
</Link>
</li>
<li className="mb-3">
<Link href="/cookie-policy">
Cookie Policy
</Link>
</li>
<li>
<Link href="/sitemap">
Sitemap
</Link>
</li>
</ul>
</Col>
</Row>
</Container>
{/* Bottom bar */}
<div className="footer-bottom py-3">
<Container className="d-flex flex-column flex-md-row justify-content-between align-items-center">
<span>Copyright ©2025 Akruti Luxe. All rights reserved.</span>
<div className="social-icons d-flex gap-3 mt-3 mt-md-0">
<Link href="https://linkedin.com" target="_blank">
<i class="fa-brands fa-linkedin"></i>
</Link>
<Link href="https://instagram.com" target="_blank">
<i class="fa-brands fa-instagram"></i>
</Link>
<Link href="https://youtube.com" target="_blank">
<i class="fa-brands fa-youtube"></i>
</Link>
<Link href="https://x.com" target="_blank">
<i class="fa-brands fa-square-twitter"></i>
</Link>
<Link href="https://facebook.com" target="_blank">
<i class="fa-brands fa-square-facebook"></i>
</Link>
</div>
</Container>
</div>
</footer>
);
};
export default Footer;
"use client";
import { useState, useEffect } from "react";
import {
Navbar,
Nav,
Container,
Offcanvas,
Button,
Row,
Col,
Dropdown,
} from "react-bootstrap";
import Link from "next/link";
import { usePathname } from "next/navigation";
import Image from "next/image";
import { SubMenu } from "./SubMenu";
import { useDispatch, useSelector } from "react-redux";
import { fetchHeader } from "@/redux/slices/headerSlice";
export default function Navigation() {
const [scrolled, setScrolled] = useState(false);
const [show, setShow] = useState(false);
const [activeMenu, setActiveMenu] = useState(null);
const pathname = usePathname();
const isActive = (path) => pathname === path;
useEffect(() => {
const onScroll = () => setScrolled(window.scrollY > 50);
window.addEventListener("scroll", onScroll);
return () => window.removeEventListener("scroll", onScroll);
}, []);
const handleMenuClick = (menu) => {
setActiveMenu((prev) => (prev === menu ? null : menu));
};
const dispatch = useDispatch();
useEffect(() => {
dispatch(fetchHeader());
}, []);
const headerData = useSelector((state) => state.header.data);
return (
<>
<Navbar
fixed="top"
expand="lg"
className={`custom-navbar ${scrolled ? "scrolled" : ""}`}
>
<Container className="custom_container d-flex justify-content-between align-items-center">
{/* Left side: Logo + Nav */}
<div className="d-flex align-items-center">
<Navbar.Brand href="/">
<Image
src="/image/logo.png"
alt="logo"
width={140}
height={60}
className="img-fluid"
/>
</Navbar.Brand>
<Nav className="d-none d-lg-flex ms-4 gap-4">
<Nav.Link as={Link} href="/" onClick={() => setShow(false)}>
Collection
</Nav.Link>
<Nav.Link
as={Link}
href="/brands"
className={isActive("/brands") ? "active" : ""}
>
Brands
</Nav.Link>
<Nav.Link
as={Link}
href="/products"
className={isActive("/products") ? "active" : ""}
>
Products
</Nav.Link>
<Nav.Link
as={Link}
href="/projects"
className={isActive("/projects") ? "active" : ""}
>
Projects
</Nav.Link>
</Nav>
</div>
{/* Right side */}
<div className="d-none d-lg-flex align-items-center gap-4">
<Nav.Link as={Link} href="/" onClick={() => setShow(false)}>
About
</Nav.Link>
<Nav.Link as={Link} href="/" onClick={() => setShow(false)}>
Catalogue
</Nav.Link>
<Nav.Link as={Link} href="/" onClick={() => setShow(false)}>
Contacts
</Nav.Link>
{/* Language Dropdown */}
<Dropdown>
<Dropdown.Toggle variant="link" id="language-dropdown">
English
</Dropdown.Toggle>
<Dropdown.Menu>
<Dropdown.Item href="#/en">English</Dropdown.Item>
<Dropdown.Item href="#/fr">Français</Dropdown.Item>
<Dropdown.Item href="#/de">Deutsch</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
</div>
{/* Mobile Toggle */}
<Navbar.Toggle onClick={() => setShow(true)} />
</Container>
</Navbar>
{/* Mobile Offcanvas */}
<Offcanvas
show={show}
onHide={() => setShow(false)}
placement="end"
className="custom-offcanvas"
>
<Offcanvas.Header closeButton>
<Offcanvas.Title>
<Image
src="/image/logo.png"
alt="logo"
width={140}
height={50}
className="img-fluid"
/>
</Offcanvas.Title>
</Offcanvas.Header>
<Offcanvas.Body>
<Nav className="flex-column gap-1">
<Nav.Link as={Link} href="/" onClick={() => setShow(false)}>
Collection
</Nav.Link>
<Nav.Link as={Link} href="/brands" onClick={() => setShow(false)}>
Brands
</Nav.Link>
<Nav.Link as={Link} href="/products" onClick={() => setShow(false)}>
Products
</Nav.Link>
<Nav.Link as={Link} href="/projects" onClick={() => setShow(false)}>
Projects
</Nav.Link>
<Nav.Link as={Link} href="/about" onClick={() => setShow(false)}>
About
</Nav.Link>
<Nav.Link
as={Link}
href="/catalogue"
onClick={() => setShow(false)}
>
Catalogue
</Nav.Link>
<Nav.Link as={Link} href="/contacts" onClick={() => setShow(false)}>
Contacts
</Nav.Link>
<Dropdown className="lang-btn">
<Dropdown.Toggle>English</Dropdown.Toggle>
<Dropdown.Menu>
<Dropdown.Item>English</Dropdown.Item>
<Dropdown.Item>Français</Dropdown.Item>
<Dropdown.Item>Deutsch</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
</Nav>
</Offcanvas.Body>
</Offcanvas>
</>
);
}
import Image from 'next/image'
import Link from 'next/link'
import React from 'react'
import { Col, Row } from 'react-bootstrap'
import { cleanImage } from '../imageHandling'
export const SubMenu = ({ data, menuTitle }) => {
// console.log(data, 'menudata');
const { classname, headerLeft, headerRight } = data;
return (
<section className='submenu_header_desktop'>
<div className='custom_container'>
<Row className='justify-content-between'>
<div className={classname}>
<Row>
<p className='nav_title'>{menuTitle}</p>
{
headerLeft && headerLeft.map((item, index) => (
<div className={`nav_item ${item?.classname}`} key={index}>
<a className='text-decoration-none' href={item?.btnTextUrl}>
<h4>{item?.title}</h4>
<p>{item?.description}</p>
{
item?.btnText && (
<a className='btn btn-primary' href={item?.btnTextUrl}>{item?.btnText}</a>
)
}
</a>
</div>
))
}
</Row>
</div>
{
!headerRight?.hideRightSection && (
<>
<Col md={1}>
<div className='border_right'></div>
</Col>
<div className={`best_seller ${headerRight?.classname}`}>
<a href={headerRight?.btnTextUrl}>
<Image src={cleanImage(headerRight?.image?.url)} width={1000} height={1000} className='img-fluid position-relative' alt='header image' />
<Row>
<div className='col-xxl-6 col-md-8 best_seller_card'>
<h3>{headerRight?.title}</h3>
<span className='badge bg-white'>
<strong>{headerRight?.tag.split(' ')[0]}</strong> {headerRight?.tag.split(' ').slice(1).join(' ')}
</span>
<p>{headerRight?.description}</p>
</div>
</Row>
<h4>{headerRight?.subTitle}</h4>
<p>{headerRight?.subDescription}</p>
</a>
</div>
</>
)
}
</Row>
</div>
</section>
)
}
import React from "react";
const SwiperBtn = () => {
return (
<>
<button className="hm-swpr-btn cust-swiper-button-prev">
<svg
width="15"
height="13"
viewBox="0 0 15 13"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M14.9688 7C14.9688 7.5625 14.5312 8 14 8H4.40625L7.6875 11.3125C8.09375 11.6875 8.09375 12.3438 7.6875 12.7188C7.5 12.9062 7.25 13 7 13C6.71875 13 6.46875 12.9062 6.28125 12.7188L1.28125 7.71875C0.875 7.34375 0.875 6.6875 1.28125 6.3125L6.28125 1.3125C6.65625 0.90625 7.3125 0.90625 7.6875 1.3125C8.09375 1.6875 8.09375 2.34375 7.6875 2.71875L4.40625 6H14C14.5312 6 14.9688 6.46875 14.9688 7Z"
fill="white"
/>
</svg>
</button>
<button className="hm-swpr-btn cust-swiper-button-next">
<svg
width="15"
height="13"
viewBox="0 0 15 13"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M0.03125 7C0.03125 7.5625 0.46875 8 1 8H10.5938L7.3125 11.3125C6.90625 11.6875 6.90625 12.3438 7.3125 12.7188C7.5 12.9062 7.75 13 8 13C8.28125 13 8.53125 12.9062 8.71875 12.7188L13.7188 7.71875C14.125 7.34375 14.125 6.6875 13.7188 6.3125L8.71875 1.3125C8.34375 0.90625 7.6875 0.90625 7.3125 1.3125C6.90625 1.6875 6.90625 2.34375 7.3125 2.71875L10.5938 6H1C0.46875 6 0.03125 6.46875 0.03125 7Z"
fill="white"
/>
</svg>
</button>
</>
);
};
export default SwiperBtn;
import React from 'react';
import { Modal, Placeholder } from 'react-bootstrap';
import { useForm } from 'react-hook-form';
import qs from "qs";
import axios from "axios";
import { useRouter } from 'next/router';
const PopupForm = ({ show, handleClose }) => {
const {
handleSubmit,
control,
formState: { errors },
register,
reset,
} = useForm({
mode: "onBlur",
});
const router = useRouter();
const onSubmit = async (data) => {
const finaldata = new FormData();
const strapiData = {
data: {
name: data.name,
email: data.email,
mobile: data.mobile,
message: data.Message,
company: data.Company,
organization: data.organization,
},
};
// console.log("strapiData", strapiData);
finaldata.append("data", JSON.stringify(strapiData));
// console.log("formvalue", finaldata);
// console.log(leadData, "form-data");
// strapi
const config = {
headers: {
"Content-Type": "multipart/form-data",
},
};
try {
const response = await axios.post(
`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/website-leads`,
strapiData,
config
);
if (response.status === 200) {
// router.push("/thankyou");
}
} catch (error) {
console.error(error);
}
const emailData = {
...data,
FormSource: "Popup form",
maillist: ["gaurav.logicloop@gmail.com"],
};
const sendEmaill = (emailData) => {
fetch("/api/sendEmail", {
method: "POST",
headers: {
Accept: "application/json, text/plain, */*",
"Content-Type": "application/json",
},
body: JSON.stringify(emailData),
})
.then((response) => {
console.log("response received", response);
if (response.status === 200) {
console.log("response succeeded");
} else {
console.log("response failed");
}
})
.catch((error) => {
console.error(error);
});
};
sendEmaill(emailData);
router.push("/thankyou");
reset();
};
return (
<Modal className='popupform' show={show} onHide={handleClose} centered>
<Modal.Header closeButton>
<div>
<h5 className="modal-title">Contact us now,
</h5>
<p>Our team is ready to support you.</p>
</div>
</Modal.Header>
<Modal.Body>
<form onSubmit={handleSubmit(onSubmit)}>
<div className="modal-body">
<div className="mb-3">
{/* <label className="form-label">Name</label> */}
<input
className="form-control" Placeholder="Your Full Name*"
{...register("name", { required: "Name is required" })}
/>
{errors.name && (
<small className="text-danger">
{errors.name.message}
</small>
)}
</div>
<div className="mb-3">
{/* <label className="form-label">Email</label> */}
<input
className="form-control"
type="email"
placeholder='Email*'
{...register("email", { required: "Email is required" })}
/>
{errors.email && (
<small className="text-danger">
{errors.email.message}
</small>
)}
</div>
<div className="mb-3">
{/* <label className="form-label">Mobile</label> */}
<input
className="form-control"
type="tel"
placeholder='Phone No.*'
{...register("mobile", {
required: "Mobile number is required",
})}
/>
{errors.mobile && (
<small className="text-danger">
{errors.mobile.message}
</small>
)}
</div>
<div className="mb-3">
<input
className="form-control"
type="text"
name='Company'
placeholder='Company Name'
{...register("Company", {
required: "Company Name is required",
})}
/>
{errors.Company && (
<small className="text-danger">
{errors.Company.message}
</small>
)}
</div>
{/* <div className="mb-3">
<select className="form-control custom-select"
name="organization"
{...register("organization", {
required: "Select Your Organization",
})}>
<option disabled selected value className="option-popup">
Business / Organization
</option>
<option className="option-popup">Business / Organization</option>
<option className="option-popup">Business / Organization</option>
</select>
{errors.organization && (
<small className="text-danger">
{errors.organization.message}
</small>
)}
</div> */}
<div className='mb-3'>
<textarea
id="message"
rows="3"
name="Message"
className="form-control"
placeholder="Message"
{...register("Message", {
required: "Enter Your Message",
maxLength: {
value: 250,
message: "Message is too long",
},
})}
></textarea>
{errors.Message && (
<span className="error">{errors.Message.message}</span>
)}
</div>
</div>
<div className="modal-footer d-flex justify-content-start align-items-center">
<button type="submit" className="btn btn-primary">
Submit
</button>
</div>
</form>
</Modal.Body>
</Modal>
);
};
export default PopupForm;
import { cleanImage } from "../../components/imageHandling";
import Head from "next/head";
import React from "react";
const Seo = (props) => {
const imgUrl = cleanImage(props?.seo?.metaImage?.data?.attributes?.url);
const schema = props?.seo?.schema;
const Bschema = props?.seo?.BodySchema;
return (
<>
<Head>
<meta name="robots" content="index, follow" />
<meta name="googlebot" content="index, follow" />
<title>
{props?.seo?.metaTitle == null
? props?.seo?.metaTitle
: props?.seo?.metaTitle}
</title>
<meta
name="keywords"
content={props?.seo?.keywords == null ? "" : props?.seo?.keywords}
/>
<meta
name="description"
content={
props?.seo?.metaDescription == null
? ""
: props?.seo?.metaDescription
}
/>
<link
rel="canonical"
href={
props?.seo?.canonicalURL == null ? "" : props?.seo?.canonicalURL
}
/>
<link
rel="alternate"
href={
props?.seo?.canonicalURL == null ? "" : props?.seo?.canonicalURL
}
hreflang="en-in"
/>
{/* <meta
name="robots"
content={props?.seo?.metaRobots == null ? "" : props?.seo?.metaRobots}
/>
<meta
name="googlebot"
content={props?.seo?.googlebots == null ? "" : props?.seo?.googlebots}
/> */}
<meta
property="og:title"
content={props?.seo?.metaTitle == null ? "" : props?.seo?.metaTitle}
/>
<meta
property="og:description"
content={
props?.seo?.metaDescription == null
? ""
: props?.seo?.metaDescription
}
/>
{/*twitter card*/}
<meta
name="twitter:title"
content={props?.seo?.metaTitle == null ? "" : props?.seo?.metaTitle}
/>
<meta
name="twitter:description"
content={
props?.seo?.metaDescription == null
? ""
: props?.seo?.metaDescription
}
/>
{/*twitter card*/}
<meta property="og:type" content="website" />
<meta
property="og:url"
content={
props?.seo?.canonicalURL == null ? "" : props?.seo?.canonicalURL
}
/>
<meta property="og:image" content={imgUrl == null ? "" : imgUrl} />
{/* <script type="application/ld+json">{JSON.stringify(props?.seo?.structuredData) == null ? "" : JSON.stringify(props?.seo?.structuredData)}</script> */}
{schema &&
schema.map((item, index) => {
// console.log("item", item);
return (
<script
key={"websiteJSON" + index}
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify(item?.jsonSchema, null, 2)
? JSON.stringify(item?.jsonSchema, null, 2)
: "",
}}
></script>
);
})}
</Head>
<>
{Bschema &&
Bschema.map((item, index) => {
// console.log("item", item);
return (
<script
key={"websiteJSON" + index}
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify(item?.jsonSchema, null, 2)
? JSON.stringify(item?.jsonSchema, null, 2)
: "",
}}
></script>
);
})}
</>
</>
);
};
export default Seo;
import { useEffect } from 'react'
import Lenis from '@studio-freight/lenis'
export default function SmoothScroll({ children }) {
useEffect(() => {
window.scrollTo(0, 0);
const lenis = new Lenis()
function raf(time) {
lenis.raf(time)
requestAnimationFrame(raf)
}
requestAnimationFrame(raf)
}, [])
return children
}
\ No newline at end of file
import React from 'react'
const SwiperButton = (props) => {
const stringifiedProps = JSON.stringify(props);
return (
<>
<button className={(stringifiedProps === "{}") ? `cust-swiper-button-prev relative border-0` : `${props?.prevEl} relative`} aria-label="Prev">
<svg width="60" height="60" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M30 60C13.4315 60 0 46.5685 0 30C0 13.4315 13.4315 0 30 0C46.5685 0 60 13.4315 60 30C60 46.5685 46.5685 60 30 60Z" fill="#074E96" />
<path d="M23.3125 30.7185L28.3125 35.7185C28.5 35.906 28.75 35.9998 29 35.9998C29.2812 35.9998 29.5312 35.906 29.7188 35.7185C30.125 35.3435 30.125 34.6873 29.7188 34.3123L26.4375 30.9998H36C36.5625 30.9998 37 30.5623 37 29.9998C37 29.4685 36.5625 28.9998 36 28.9998H26.4375L29.7188 25.7185C30.125 25.3435 30.125 24.6873 29.7188 24.3123C29.3438 23.906 28.6875 23.906 28.3125 24.3123L23.3125 29.3123C22.9062 29.6873 22.9062 30.3435 23.3125 30.7185Z" fill="white" />
</svg>
</button>
<button className={(stringifiedProps === "{}") ? `cust-swiper-button-next relative` : `${props?.nextEl} relative`} aria-label="Next">
<svg width="60" height="60" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M30 60C46.5685 60 60 46.5685 60 30C60 13.4315 46.5685 0 30 0C13.4315 0 0 13.4315 0 30C0 46.5685 13.4315 60 30 60Z" fill="#074E96" />
<path d="M36.6875 30.7185L31.6875 35.7185C31.5 35.906 31.25 35.9998 31 35.9998C30.7188 35.9998 30.4688 35.906 30.2812 35.7185C29.875 35.3435 29.875 34.6873 30.2812 34.3123L33.5625 30.9998H24C23.4375 30.9998 23 30.5623 23 29.9998C23 29.4685 23.4375 28.9998 24 28.9998H33.5625L30.2812 25.7185C29.875 25.3435 29.875 24.6873 30.2812 24.3123C30.6562 23.906 31.3125 23.906 31.6875 24.3123L36.6875 29.3123C37.0938 29.6873 37.0938 30.3435 36.6875 30.7185Z" fill="white" />
</svg>
</button>
</>
)
}
export default SwiperButton
export const cleanImage = (originalImage) => {
let imageUrl = "/image/default.svg";
if (originalImage) {
// /** When the AWS S3 plugin is activated, images are uploaded to S3 rather than local file system. */
// if (originalImage.url.startsWith("http")) {
// imageUrl = originalImage.url;
// } else {
// /** If now S3, then images are stored under the public/uploads directory of Strapi */
// imageUrl = `${process.env.NEXT_PUBLIC_BACKEND_API_URL}${originalImage.url}`;
// }
// If CDN specified then we serve from there...
// imageUrl = `https://d2edd7fnfghsl3.cloudfront.net${originalImage}`
if (process.env.NEXT_PUBLIC_CDN_URL) {
imageUrl = `${process.env.NEXT_PUBLIC_CDN_URL}${originalImage}`;
}
else {
imageUrl = `${process.env.NEXT_PUBLIC_BACKEND_API_URL}${originalImage}`;
}
}
return imageUrl;
};
export const webFullurl = (originalImage) => {
let homeUrl = `${process.env.NEXT_PUBLIC_WEBSITE_HOME_URL}`;
if (originalImage) {
homeUrl = `${process.env.NEXT_PUBLIC_WEBSITE_HOME_URL}${originalImage}`;
}
// console.log("homeUrl", homeUrl);
return homeUrl;
};
\ No newline at end of file
import FadeInStagger from "@/components/FadeInStagger";
import Image from "next/image";
import React from "react";
import { Col, Container, Row } from "react-bootstrap";
const BlogHome = () => {
const rightBlogs = [
{
image: "/image/blog1.png",
date: "News | 04.06.25",
title: "Design Heritage In Harmony",
desc: "the picturesque coastal town of La Baule-Escoublac. This innovative space showcases a blend of modern aesthetics and timeless elegance",
},
{
image: "/image/blog1.png",
date: "News | 04.06.25",
title: "Design Heritage In Harmony",
desc: "the picturesque coastal town of La Baule-Escoublac. This innovative space showcases a blend of modern aesthetics and timeless elegance",
},
];
return (
<section className="sec_padd">
<Container className="custom_container">
{/* Heading Row */}
<Row className="align-items-center justify-content-between mb-4">
<Col lg={8} md={8}>
<h2 className="heading mb-2">Blogs / News</h2>
</Col>
<Col lg={4} md={4} className="d-flex justify-content-md-end">
<button className="btn3">Explore More</button>
</Col>
</Row>
<Row className="g-4">
{/* Left Blog (large) */}
<Col lg={7} md={12}>
<div className="blog-large">
<FadeInStagger direction="right">
<Image
src="/image/blog.png"
alt="About"
width={1000}
height={400}
className="img-fluid rounded"
/>
<div className="d-flex flex-column-reverse flex-md-row align-items-start align-items-md-center justify-content-between mt-2">
<h5 className="mb-1">Design Heritage In Harmony</h5>
<p className="blog-date mb-1">Blogs | 07.04.25</p>
</div>
<p className="pt-2 blog_desc">
In the historic heart of Moscow, overlooking the Cathedral of
Christ the Saviour, an apartment appears as a reinterpretation
of Parisian charm viewed through a contemporary lens.
</p>
<button className="read-more-btn">
Read More <i className="fa-solid fa-arrow-right"></i>
</button>
</FadeInStagger>
</div>
</Col>
{/* Right Blogs (list) */}
<Col lg={5} md={12}>
<FadeInStagger direction="right">
{rightBlogs.map((blog, index) => (
<div
key={index}
className="d-flex flex-column flex-md-row mb-4"
>
<Image
src={blog.image}
alt={blog.title}
width={350}
height={400}
className="blog-img img-fluid rounded"
/>
<div className="blog-content ms-md-3 mt-2 mt-md-0">
<p className="blog-date mb-1">{blog.date}</p>
<h5 className="mb-1">{blog.title}</h5>
<p className="blog_desc">{blog.desc}</p>
<button className="read-more-btn">
Read More <i className="fa-solid fa-arrow-right"></i>
</button>
</div>
</div>
))}
</FadeInStagger>
</Col>
</Row>
</Container>
</section>
);
};
export default BlogHome;
import React from "react";
import { Col, Container, Row } from "react-bootstrap";
import { Swiper, SwiperSlide } from "swiper/react";
import "swiper/css";
import "swiper/css/navigation";
import "swiper/css/pagination";
import { Navigation, Pagination } from "swiper/modules";
import SwiperBtn from "@/components/Layout/SwiperBtn";
import FadeInStagger from "@/components/FadeInStagger";
import Heading from "@/components/Heading";
const CollectionData = [
{ image: "/image/img1.png", title: "Design Studio" },
{ image: "/image/img2.png", title: "Kitchen" },
{ image: "/image/img3.png", title: "Micro Creatices" },
{ image: "/image/img1.png", title: "Design Studio" },
];
const Catalogues = () => {
return (
<>
<div className="catalogues-sec sec_padd position-relative">
<Container className="custom_container">
{/* Heading + Nav Row */}
<Row className="text-center mb-4">
<Col lg={12} md={12}>
<FadeInStagger direction="top">
<Heading el="h2" heading="Catalogues" />
{/* <h2 className="heading mb-2">Catalogues </h2> */}
<p className="mb-0 gray-text">
Browse through our exclusive catalogues to find ideas for your
next masterpiece.
</p>
</FadeInStagger>
</Col>
</Row>
{/* Swiper */}
</Container>
<Container>
<Row>
<Col md={12}>
<FadeInStagger direction="top">
<Swiper
slidesPerView={4}
spaceBetween={30}
navigation={{
nextEl: ".cust-swiper-button-next",
prevEl: ".cust-swiper-button-prev",
}}
pagination={{ clickable: true }}
loop={true}
modules={[Navigation, Pagination]}
className="collectionSwiper pb-5"
breakpoints={{
320: { slidesPerView: 1, spaceBetween: 15 },
640: { slidesPerView: 2, spaceBetween: 20 },
992: { slidesPerView: 3, spaceBetween: 25 },
1200: { slidesPerView: 3, spaceBetween: 30 },
}}
>
{CollectionData.map((item, index) => (
<SwiperSlide key={index}>
<div className="collection-card">
<img
src={item.image}
alt={item.title}
className="img-fluid rounded-lg"
/>
<p className="mt-3">{item.title}</p>
</div>
</SwiperSlide>
))}
</Swiper>
</FadeInStagger>
<div className="text-center mt-5">
<button className="btn3">Explore More</button>
</div>
</Col>
</Row>
</Container>
<div className="position-absolute swiperbtn1 d-lg-flex d-none justify-content-between px-5 align-items-center w-100 ">
<button className="hm-swpr-btn cust-swiper-button-prev">
<svg
width="15"
height="13"
viewBox="0 0 15 13"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M14.9688 7C14.9688 7.5625 14.5312 8 14 8H4.40625L7.6875 11.3125C8.09375 11.6875 8.09375 12.3438 7.6875 12.7188C7.5 12.9062 7.25 13 7 13C6.71875 13 6.46875 12.9062 6.28125 12.7188L1.28125 7.71875C0.875 7.34375 0.875 6.6875 1.28125 6.3125L6.28125 1.3125C6.65625 0.90625 7.3125 0.90625 7.6875 1.3125C8.09375 1.6875 8.09375 2.34375 7.6875 2.71875L4.40625 6H14C14.5312 6 14.9688 6.46875 14.9688 7Z"
fill="white"
/>
</svg>
</button>
<button className="hm-swpr-btn cust-swiper-button-next">
<svg
width="15"
height="13"
viewBox="0 0 15 13"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M0.03125 7C0.03125 7.5625 0.46875 8 1 8H10.5938L7.3125 11.3125C6.90625 11.6875 6.90625 12.3438 7.3125 12.7188C7.5 12.9062 7.75 13 8 13C8.28125 13 8.53125 12.9062 8.71875 12.7188L13.7188 7.71875C14.125 7.34375 14.125 6.6875 13.7188 6.3125L8.71875 1.3125C8.34375 0.90625 7.6875 0.90625 7.3125 1.3125C6.90625 1.6875 6.90625 2.34375 7.3125 2.71875L10.5938 6H1C0.46875 6 0.03125 6.46875 0.03125 7Z"
fill="white"
/>
</svg>
</button>
</div>
</div>
</>
);
};
export default Catalogues;
import React from "react";
import { Swiper, SwiperSlide } from "swiper/react";
import "swiper/css";
import "swiper/css/navigation";
import "swiper/css/pagination";
import { Autoplay, Navigation, Pagination } from "swiper/modules";
import { Container, Row, Col } from "react-bootstrap";
import FadeInStagger from "@/components/FadeInStagger";
import Heading from "@/components/Heading";
const CollectionData = [
{ image: "/image/collection/kurti1.png", title: "Kitchen" },
{ image: "/image/collection/Wardrobes.png", title: "Wardrobes" },
{ image: "/image/collection/kurti1.png", title: "Surface" },
{ image: "/image/collection/Wardrobes.png", title: "Doors" },
{ image: "/image/collection/kurti1.png", title: "Living Room" },
];
const CollectionSlider = () => {
return (
<div className="collection-section sec_padd">
<Container className="custom_container">
{/* Heading + Nav Row */}
<Row className="align-items-center justify-content-md-between mb-4">
<Col lg={8} md={8}>
<Heading el="h2" heading="COLLECTION" />
{/* <h2 className="heading mb-2">COLLECTION</h2> */}
<FadeInStagger direction="up" stagger={0.3} once={true}>
<p className="mb-0 gray-text">
Our Exclusive Collections Blend Creativity, Comfort, And
Craftsmanship For Your Perfect Home.
</p>
</FadeInStagger>
</Col>
<Col lg={4} md={4} className="d-flex justify-content-md-around mt-2">
<div className="d-flex gap-2">
<button className="cust-swiper-button-prev">
<svg
xmlns="http://www.w3.org/2000/svg"
width="48"
height="48"
viewBox="0 0 48 48"
fill="none"
>
<rect
y="48"
width="48"
height="48"
rx="24"
transform="rotate(-90 0 48)"
fill="white"
fill-opacity="0.25"
/>
<rect
x="0.5"
y="47.5"
width="47"
height="47"
rx="23.5"
transform="rotate(-90 0.5 47.5)"
stroke="black"
stroke-opacity="0.2"
/>
<path
d="M20.6667 31L22.4375 29.1406L18.7917 25.3125H34V22.6875H18.7917L22.4375 18.8594L20.6667 17L14 24L20.6667 31Z"
fill="black"
/>
</svg>
</button>
<button className="cust-swiper-button-next">
<svg
xmlns="http://www.w3.org/2000/svg"
width="48"
height="48"
viewBox="0 0 48 48"
fill="none"
>
<rect
width="48"
height="48"
rx="24"
transform="matrix(0 -1 -1 0 48 48)"
fill="white"
fill-opacity="0.25"
/>
<rect
x="-0.5"
y="-0.5"
width="47"
height="47"
rx="23.5"
transform="matrix(0 -1 -1 0 47 47)"
stroke="black"
stroke-opacity="0.2"
/>
<path
d="M27.3333 31L25.5625 29.1406L29.2083 25.3125H14V22.6875H29.2083L25.5625 18.8594L27.3333 17L34 24L27.3333 31Z"
fill="black"
/>
</svg>
</button>
</div>
</Col>
</Row>
{/* Swiper */}
<Swiper
slidesPerView={4}
spaceBetween={30}
loop={true}
allowTouchMove={true}
autoplay={{
delay: 0,
disableOnInteraction: false,
pauseOnMouseEnter: true,
}}
speed={6000}
navigation={{
nextEl: ".cust-swiper-button-next",
prevEl: ".cust-swiper-button-prev",
}}
modules={[Navigation, Autoplay]}
className="collectionSwiper"
breakpoints={{
320: { slidesPerView: 1, spaceBetween: 15 },
640: { slidesPerView: 2, spaceBetween: 20 },
992: { slidesPerView: 3, spaceBetween: 25 },
1200: { slidesPerView: 3.7, spaceBetween: 30 },
}}
>
{CollectionData.map((item, index) => (
<SwiperSlide key={index}>
<div className="collection-card">
<img
src={item.image}
alt={item.title}
className="img-fluid rounded-lg hover-zoom"
/>
<p className="mt-3">{item.title}</p>
</div>
</SwiperSlide>
))}
</Swiper>
</Container>
</div>
);
};
export default CollectionSlider;
import FadeInStagger from "@/components/FadeInStagger";
import React from "react";
import { Col, Container, Row } from "react-bootstrap";
export const Contact = () => {
return (
<>
<section className="contact_sec sec_padd">
<Container>
<Row>
<Col md={12}>
<div className="text-center">
<FadeInStagger direction="top">
<h2 className="heading">Contact Us</h2>
<p>
Every great space starts with a conversation. From luxurious
homes to bespoke workspaces,
<br />
were here to bring your vision to life.
</p>
<p>
Reach out today, and lets turn your ideas into a masterpiece.
</p>
</FadeInStagger>
</div>
<div className="d-flex justify-content-center gap-3">
<button className="btn2">Get in Touch</button>
<button className="btn1">Book a Consultation</button>
</div>
</Col>
</Row>
</Container>
</section>
</>
);
};
import React, { useState, useEffect } from "react";
import { Swiper, SwiperSlide } from "swiper/react";
import "swiper/css";
import "swiper/css/navigation";
import "swiper/css/pagination";
import { Navigation, Pagination, Autoplay } from "swiper/modules";
import SwiperBtn from "@/components/Layout/SwiperBtn";
const BannerData = [
{
desktopImage: "/image/banner/banner1.png",
mobileImage: "/image/banner/mb2.png",
title: "KITCHENS",
description:
"Transform your cooking space into a modern kitchen oasis. With sleek cabinetry and state-of-the-art appliances, you can create a functional yet stylish environment.",
},
{
desktopImage: "/image/banner/banner1.png",
mobileImage: "/image/banner/mb2.png",
title: "LIVING ROOMS",
description:
"Experience comfort and elegance in your living space. Designed with premium furniture and modern décor to elevate your lifestyle.",
},
{
desktopImage: "/image/banner/banner1.png",
mobileImage: "/image/banner/mb2.png",
title: "BEDROOMS",
description:
"Create your dream retreat with cozy and stylish bedroom designs. A perfect balance of comfort, elegance, and tranquility.",
},
];
const HomeBanner = () => {
const [isMobile, setIsMobile] = useState(false);
// Detect screen width
useEffect(() => {
const handleResize = () => setIsMobile(window.innerWidth <= 767);
handleResize();
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []);
return (
<Swiper
navigation={{
nextEl: ".cust-swiper-button-next",
prevEl: ".cust-swiper-button-prev",
}}
pagination={{ clickable: true }}
autoplay={{ delay: 5000 }}
loop
modules={[Navigation, Pagination, Autoplay]}
className="homeBannerSwiper"
>
<div className="position-absolute swiperbtn1 d-lg-flex d-none justify-content-md-between px-5 align-items-center w-100">
<SwiperBtn />
</div>
{BannerData.map((item, index) => (
<SwiperSlide key={index}>
<div className="slide-container">
<img
src={isMobile ? item.mobileImage : item.desktopImage}
alt={item.title}
className="slide-bg"
/>
<div className="slide-overlay">
<div className="slide-content">
<h2>{item.title}</h2>
<div className="text-btn-row">
<p>{item.description}</p>
<button className="btn1">Explore More</button>
</div>
</div>
</div>
</div>
</SwiperSlide>
))}
</Swiper>
);
};
export default HomeBanner;
import FadeInStagger from "@/components/FadeInStagger";
import Heading from "@/components/Heading";
import Image from "next/image";
import React from "react";
import { Col, Container, Row } from "react-bootstrap";
const Overview = () => {
return (
<section className="overview_sec sec_padd ">
<Container className="custom_container">
{/* Make row full height and align items center */}
<Row className="align-items-center">
<Col md={7} className="d-flex flex-column justify-content-center">
<Heading el="h2" heading="About" />
<FadeInStagger direction="left">
{/* <h2 className="heading mb-2">About</h2> */}
<p className="gray-text">
We believe luxury is not just a style its an experience.{" "}
<br />
An experience that begins the moment you step into a space and
feel its presence, its character, its soul.
<br />
We are creators of exceptional interiors, crafting environments
where elegance meets comfort, and design meets purpose. From
palatial residences to statement-making offices, from grand
hospitality venues to bespoke retail boutiques our work speaks
the language of refinement.
<br />
Every project begins with a vision yours. We listen, we
understand, and we translate your aspirations into tangible
beauty. Our team of designers, architects, and artisans work in
harmony, blending creativity with precision.
<br />
Our philosophy is simple timeless design, flawless execution,
and an unwavering commitment to excellence. We source the finest
materials from around the world and collaborate with master
craftsmen who share our dedication to perfection.
<br />
Beyond aesthetics, we design for living. Spaces that are not
only beautiful, but functional. Environments that enhance
lifestyles, elevate brands, and create lasting impressions.
</p>
</FadeInStagger>
</Col>
<Col md={5} className="d-flex justify-content-center">
<div className="shine-wrapper">
<Image
src="/image/about.png"
alt="About"
width={600}
height={600}
className="img-fluid"
/>
<div className="shine-overlay"></div>
</div>
</Col>
</Row>
</Container>
</section>
);
};
export default Overview;
import React, { useRef } from "react";
import { Swiper, SwiperSlide } from "swiper/react";
import "swiper/css";
import "swiper/css/navigation";
import "swiper/css/pagination";
import { Autoplay, Navigation, Pagination } from "swiper/modules";
import { Container, Row, Col } from "react-bootstrap";
import FadeInStagger from "@/components/FadeInStagger";
import Heading from "@/components/Heading";
const CollectionData = [
{ image: "/image/project.png", title: "The Imperial – Mumbai" },
{ image: "/image/project.png", title: "Azure Heights – Bengaluru" },
{ image: "/image/project.png", title: "The Imperial – Mumbai" },
{ image: "/image/project.png", title: "Azure Heights – Bengaluru" },
];
const ProjectSlider = () => {
const prevRef = useRef(null);
const nextRef = useRef(null);
return (
<div className="project-section py-5 position-relative">
<Container className="custom_container">
{/* Heading */}
<Row className="text-md-center mb-4">
<Col lg={12} md={12}>
<FadeInStagger direction="top">
<Heading el="h2" heading="Projects" />
{/* <h2 className="heading mb-2">Projects</h2> */}
<p className="mb-0 gray-text">
Our Exclusive Collections Blend Creativity, Comfort, And
Craftsmanship For Your Perfect Home.
</p>
</FadeInStagger>
</Col>
</Row>
{/* Swiper */}
<Swiper
slidesPerView={4}
spaceBetween={30}
autoplay={{ delay: 5000, disableOnInteraction: false }}
speed={1000}
loop={true}
pagination={{ clickable: true }}
navigation={{
prevEl: prevRef.current,
nextEl: nextRef.current,
}}
onBeforeInit={(swiper) => {
swiper.params.navigation.prevEl = prevRef.current;
swiper.params.navigation.nextEl = nextRef.current;
}}
modules={[Navigation, Pagination, Autoplay]}
className="projectSwiper pb-5"
breakpoints={{
320: { slidesPerView: 1, spaceBetween: 15 },
640: { slidesPerView: 1.5, spaceBetween: 20 },
992: { slidesPerView: 1.5, spaceBetween: 25 },
1200: { slidesPerView: 1.5, spaceBetween: 30 },
}}
>
{CollectionData.map((item, index) => (
<SwiperSlide key={index}>
<div className="project-card">
<img
src={item.image}
alt={item.title}
className="img-fluid rounded-lg hover-zoom"
/>
<p className="mt-3">{item.title}</p>
</div>
</SwiperSlide>
))}
</Swiper>
</Container>
{/* Swiper buttons outside container */}
<div className="position-absolute swiperbtn1 d-lg-flex d-none justify-content-between px-5 align-items-center w-100">
{/* Attach refs to buttons */}
<button ref={prevRef} className="hm-swpr-btn cust-swiper-button-prev">
<svg
width="15"
height="13"
viewBox="0 0 15 13"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M14.9688 7C14.9688 7.5625 14.5312 8 14 8H4.40625L7.6875 11.3125C8.09375 11.6875 8.09375 12.3438 7.6875 12.7188C7.5 12.9062 7.25 13 7 13C6.71875 13 6.46875 12.9062 6.28125 12.7188L1.28125 7.71875C0.875 7.34375 0.875 6.6875 1.28125 6.3125L6.28125 1.3125C6.65625 0.90625 7.3125 0.90625 7.6875 1.3125C8.09375 1.6875 8.09375 2.34375 7.6875 2.71875L4.40625 6H14C14.5312 6 14.9688 6.46875 14.9688 7Z"
fill="white"
/>
</svg>
</button>
<button ref={nextRef} className="hm-swpr-btn cust-swiper-button-next">
<svg
width="15"
height="13"
viewBox="0 0 15 13"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M0.03125 7C0.03125 7.5625 0.46875 8 1 8H10.5938L7.3125 11.3125C6.90625 11.6875 6.90625 12.3438 7.3125 12.7188C7.5 12.9062 7.75 13 8 13C8.28125 13 8.53125 12.9062 8.71875 12.7188L13.7188 7.71875C14.125 7.34375 14.125 6.6875 13.7188 6.3125L8.71875 1.3125C8.34375 0.90625 7.6875 0.90625 7.3125 1.3125C6.90625 1.6875 6.90625 2.34375 7.3125 2.71875L10.5938 6H1C0.46875 6 0.03125 6.46875 0.03125 7Z"
fill="white"
/>
</svg>
</button>
</div>
</div>
);
};
export default ProjectSlider;
import React, { useRef, useEffect, useState } from "react";
import { Container } from "react-bootstrap";
const Video = () => {
const videoRef = useRef(null);
const [isVisible, setIsVisible] = useState(false);
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
setIsVisible(entry.isIntersecting);
},
{ threshold: 0.5 }
);
if (videoRef.current) observer.observe(videoRef.current);
return () => {
if (videoRef.current) observer.unobserve(videoRef.current);
};
}, []);
return (
<section className="video_sec sec_padd">
<Container className="custom_container">
<video
ref={videoRef}
autoPlay
muted
loop
playsInline
className={`w-100 video-animate ${isVisible ? "video-visible" : ""}`}
>
<source src="/image/dummy.mp4" type="video/mp4" />
Your browser does not support the video tag.
</video>
</Container>
</section>
);
};
export default Video;
git pull
npm run build
pm2 stop alphion_frontend
pm2 start alphion_frontend
module.exports = {
apps: [
{
name: 'alphion_frontend',
script: 'npm',
args: 'run start',
},
],
};
{
"compilerOptions": {
"paths": {
"@/*": ["./*"]
}
}
}
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
images: {
remotePatterns: [
{
protocol: "http",
hostname: "localhost",
},
{
protocol: "http",
hostname: "168.231.102.2",
},
],
},
};
export default nextConfig;
{
"name": "alphion-frontend",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev -p 3026",
"build": "next build",
"start": "next start -p 3026",
"lint": "next lint"
},
"dependencies": {
"@fancyapps/ui": "^5.0.36",
"@reduxjs/toolkit": "^2.3.0",
"@studio-freight/lenis": "^1.0.42",
"axios": "^1.7.7",
"bootstrap": "^5.3.5",
"formidable": "^3.5.2",
"framer-motion": "^12.7.4",
"marked": "^15.0.12",
"next": "^13.4.19",
"nodemailer": "^6.9.15",
"qs": "^6.13.0",
"react": "^19.0.0",
"react-bootstrap": "^2.10.9",
"react-countup": "^6.5.3",
"react-dom": "^19.0.0",
"react-hook-form": "^7.56.3",
"react-paginate": "^8.2.0",
"react-redux": "^9.1.2",
"swiper": "^11.2.6"
}
}
import "bootstrap/dist/css/bootstrap.min.css";
import "@/styles/globals.css";
import "@/styles/style.css";
import Header from "@/components/Layout/Header";
import Head from "next/head";
import Footer from "@/components/Layout/Footer";
import Providers from "@/redux/providers";
import { store } from "@/redux/store";
import SmoothScroll from "@/components/SmoothScroll";
export default function App({ Component, pageProps }) {
return (
<>
<Providers store={store}>
{/* <SmoothScroll> */}
<Header />
<Component {...pageProps} />
<Footer />
{/* </SmoothScroll> */}
</Providers>
</>
);
}
import { Html, Head, Main, NextScript } from "next/document";
export default function Document() {
return (
<Html lang="en">
<Head>
<title>Alphion</title>
<meta charSet="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<meta name="description" content="Alphion" />
<meta property="og:title" content="Alphion" />
<meta property="og:description" content="Alphion" />
<link rel="apple-touch-icon" sizes="180x180" href="/favicon.svg" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon.svg" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon.svg" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet" />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
export default function handler(req, res) {
res.status(200).json({ name: "John Doe" });
}
import nodemailer from "nodemailer";
export default function (req, res) {
const transporter = nodemailer.createTransport({
host: "smtp.gmail.com",
port: 587,
secure: false,
auth: {
user: process.env.EMAIL_USER,
pass: process.env.EMAIL_PASS,
},
});
const maillist =
Array.isArray(req.body?.maillist) && req.body?.maillist.length
? req.body.maillist
: ["gaurav.logicloop@gmail.com"];
const parsedData = req.body || {};
const buildRow = (label, value) => {
return `<tr>
<td style="width:30%;"><b>${label}:</b></td>
<td style="width:70%;">${value}</td>
</tr>`;
};
// Build table rows dynamically if data exists
let personalDetailsRows = "";
if (parsedData.name) personalDetailsRows += buildRow("Name", parsedData.name);
if (parsedData.email) personalDetailsRows += buildRow("Email", parsedData.email);
if (parsedData.mobile) personalDetailsRows += buildRow("Mobile", parsedData.mobile);
if (parsedData.jobTitle) personalDetailsRows += buildRow("Designation", parsedData.jobTitle);
if (parsedData.experience) personalDetailsRows += buildRow("Experience", parsedData.experience);
if (parsedData.Location) personalDetailsRows += buildRow("Job Location", parsedData.Location);
if (parsedData.organization) personalDetailsRows += buildRow("Current Company", parsedData.organization);
if (parsedData.jobType) personalDetailsRows += buildRow("Job Type", parsedData.jobType);
if (req.body?.resumeBase64?.name) {
personalDetailsRows += buildRow(
"Resume",
"✅ Resume Attached (" + req.body.resumeBase64.name + ")"
);
}
// build attachments if a resume was sent from the client
const attachments = [];
if (req.body?.resumeBase64) {
const file = req.body.resumeBase64;
attachments.push({
filename: file.name || "resume.pdf",
content: file.content,
encoding: "base64",
contentType: file.type || "application/pdf",
});
}
const mailData = {
from: "gaurav.logicloop@gmail.com",
to: maillist,
subject: `Alphion ${req.body?.FormSource || ""} Leads`,
html: `
<table border="0" cellpadding="0" cellspacing="0" style="padding-top:35px; background-color:#f1f1f1; font-family:Verdana,Arial,sans-serif; color:#454748; width:100%; border-collapse:separate;">
<tbody>
<tr>
<td align="center">
<table border="0" cellpadding="16" cellspacing="0" width="590" style="background-color:white; border-collapse:separate;">
<tbody>
<tr>
<td align="center">
<strong style="font-size:16px;">Welcome to Alphion</strong>
</td>
</tr>
<tr>
<td colspan="2">
<hr style="border-top:1px solid rgba(0,0,0,0.1); margin:16px 0;">
</td>
</tr>
<tr>
<td style="font-size:13px;">
<div style="margin-bottom:10px;">
Details below are enquiry from website!
</div>
<table border="0" cellpadding="5" cellspacing="0" width="100%">
<tr><td colspan="2"><b>Personal Details:</b></td></tr>
${personalDetailsRows}
</table>
</td>
</tr>
<tr>
<td colspan="2">
<hr style="border-top:1px solid rgba(0,0,0,0.1); margin:16px 0;">
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td align="center">
<table border="0" cellpadding="8" cellspacing="0" width="590" style="background-color:#f1f1f1; color:#454748;">
<tbody>
<tr>
<td style="text-align:center; font-size:13px;"><br></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
`,
attachments,
};
transporter.sendMail(mailData, function (err, info) {
if (err) {
console.log("Error:", err);
return res.status(500).send("Error sending email");
}
console.log("Email sent:", info.response);
return res.send("success");
});
}
import nodemailer from "nodemailer";
export default function (req, res) {
const transporter = nodemailer.createTransport({
host: "smtp.gmail.com",
port: 587,
secure: false,
auth: {
user: process.env.EMAIL_USER,
pass: process.env.EMAIL_PASS,
},
});
// var maillist = ["gaurav.logicloop@gmail.com"];
var maillist = req.body.maillist || ["gaurav.logicloop@gmail.com"];
const generateFieldRow = (label, value) => {
return value ? `<tr><td style="width: 30%;"><b>${label}:</b></td><td style="width: 70%;">${value}</td></tr>` : '';
};
const mailData = {
from: "gaurav.logicloop@gmail.com",
to: maillist,
subject: `Alphion ${req.body.FormSource} Leads`,
html: `
<table border="0" cellpadding="0" cellspacing="0" style="padding-top:35px; background-color:#f1f1f1; font-family:Verdana,Arial,sans-serif; color:#454748; width:100%; border-collapse:separate;">
<tbody>
<tr>
<td align="center">
<table border="0" cellpadding="0" cellspacing="0" width="590" style="padding:16px; background-color:white; color:#454748; border-collapse:separate;">
<tbody>
<tr>
<td align="center" style="min-width:590px;">
<table border="0" cellpadding="0" cellspacing="0" width="590" style="min-width:590px; background-color:white; padding:0px 8px 0px 8px; border-collapse:separate;">
<tbody>
<tr>
<td valign="middle">
<strong style="font-size:16px; margin: 0;">Welcome to Alphion</strong>
</td>
</tr>
<tr>
<td colspan="2" style="text-align:center;">
<hr width="100%" style="border-top-color:rgba(0,0,0,0.1); border-top-style:solid; border-top-width:1px;">
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td align="center" style="min-width:590px;">
<table border="0" cellpadding="0" cellspacing="0" width="590" style="min-width:590px; background-color:white; padding:0px 8px 0px 8px; border-collapse:separate;">
<tbody>
<tr>
<td colspan="2" valign="top" style="font-size:13px;">
<div style="font-size:13px; font-family:'Lucida Grande',Helvetica,Verdana,Arial,sans-serif;">
Details below are enquiry from website!<br><br>
</div>
</td>
</tr>
<tr>
<td valign="top" style="font-size:13px;">
<div style="font-size:13px; font-family:'Lucida Grande',Helvetica,Verdana,Arial,sans-serif;">
<table>
${generateFieldRow('Name', req.body.name)}
${generateFieldRow('Email', req.body.email)}
${generateFieldRow('Mobile', req.body.mobile)}
${generateFieldRow('Company', req.body.Company)}
${generateFieldRow('Organization', req.body.organization)}
${generateFieldRow('Message', req.body.Message)}
</table>
<br><br>
</div>
</td>
</tr>
<tr>
<td colspan="2" style="text-align:center;">
<hr width="100%" style="border-top-color:rgba(0,0,0,0.1); border-top-style:solid; border-top-width:1px;">
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td align="center" style="min-width:590px;">
<table border="0" cellpadding="0" cellspacing="0" width="590" style="min-width:590px; background-color:#f1f1f1; color:#454748; padding:8px; border-collapse:separate;">
<tbody>
<tr>
<td style="text-align:center; font-size:13px;"><br></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>`,
};
transporter.sendMail(mailData, function (err, info) {
if (err) console.log(err);
else console.log(info);
});
console.log(req.body);
res.send("success");
}
"use client";
import Head from "next/head";
import HomeBanner from "@/container/Home/HomeBanner";
import CollectionSlider from "@/container/Home/Collection";
import Video from "@/container/Home/Video";
import Overview from "@/container/Home/Overview";
import ProjectSlider from "@/container/Home/ProjectSlider";
import { Contact } from "@/container/Home/Contact";
import BlogHome from "@/container/Home/BlogHome";
import Catalogues from "@/container/Home/Catalogues";
const Home = ({ homepage }) => {
return (
<>
<Head>
<title>Akruti </title>
<meta name="description" content="Alphion" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
</Head>
<HomeBanner />
<CollectionSlider />
<Video />
<Overview />
<ProjectSlider />
<Contact />
<BlogHome />
<Catalogues />
</>
);
};
export default Home;
<svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg>
\ No newline at end of file
Copyright 2011 The Roboto Project Authors (https://github.com/googlefonts/roboto-classic)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
Roboto Variable Font
====================
This download contains Roboto as both variable fonts and static fonts.
Roboto is a variable font with these axes:
wdth
wght
This means all the styles are contained in these files:
Roboto-VariableFont_wdth,wght.ttf
Roboto-Italic-VariableFont_wdth,wght.ttf
If your app fully supports variable fonts, you can now pick intermediate styles
that aren’t available as static fonts. Not all apps support variable fonts, and
in those cases you can use the static font files for Roboto:
static/Roboto_Condensed-Thin.ttf
static/Roboto_Condensed-ExtraLight.ttf
static/Roboto_Condensed-Light.ttf
static/Roboto_Condensed-Regular.ttf
static/Roboto_Condensed-Medium.ttf
static/Roboto_Condensed-SemiBold.ttf
static/Roboto_Condensed-Bold.ttf
static/Roboto_Condensed-ExtraBold.ttf
static/Roboto_Condensed-Black.ttf
static/Roboto_SemiCondensed-Thin.ttf
static/Roboto_SemiCondensed-ExtraLight.ttf
static/Roboto_SemiCondensed-Light.ttf
static/Roboto_SemiCondensed-Regular.ttf
static/Roboto_SemiCondensed-Medium.ttf
static/Roboto_SemiCondensed-SemiBold.ttf
static/Roboto_SemiCondensed-Bold.ttf
static/Roboto_SemiCondensed-ExtraBold.ttf
static/Roboto_SemiCondensed-Black.ttf
static/Roboto-Thin.ttf
static/Roboto-ExtraLight.ttf
static/Roboto-Light.ttf
static/Roboto-Regular.ttf
static/Roboto-Medium.ttf
static/Roboto-SemiBold.ttf
static/Roboto-Bold.ttf
static/Roboto-ExtraBold.ttf
static/Roboto-Black.ttf
static/Roboto_Condensed-ThinItalic.ttf
static/Roboto_Condensed-ExtraLightItalic.ttf
static/Roboto_Condensed-LightItalic.ttf
static/Roboto_Condensed-Italic.ttf
static/Roboto_Condensed-MediumItalic.ttf
static/Roboto_Condensed-SemiBoldItalic.ttf
static/Roboto_Condensed-BoldItalic.ttf
static/Roboto_Condensed-ExtraBoldItalic.ttf
static/Roboto_Condensed-BlackItalic.ttf
static/Roboto_SemiCondensed-ThinItalic.ttf
static/Roboto_SemiCondensed-ExtraLightItalic.ttf
static/Roboto_SemiCondensed-LightItalic.ttf
static/Roboto_SemiCondensed-Italic.ttf
static/Roboto_SemiCondensed-MediumItalic.ttf
static/Roboto_SemiCondensed-SemiBoldItalic.ttf
static/Roboto_SemiCondensed-BoldItalic.ttf
static/Roboto_SemiCondensed-ExtraBoldItalic.ttf
static/Roboto_SemiCondensed-BlackItalic.ttf
static/Roboto-ThinItalic.ttf
static/Roboto-ExtraLightItalic.ttf
static/Roboto-LightItalic.ttf
static/Roboto-Italic.ttf
static/Roboto-MediumItalic.ttf
static/Roboto-SemiBoldItalic.ttf
static/Roboto-BoldItalic.ttf
static/Roboto-ExtraBoldItalic.ttf
static/Roboto-BlackItalic.ttf
Get started
-----------
1. Install the font files you want to use
2. Use your app's font picker to view the font family and all the
available styles
Learn more about variable fonts
-------------------------------
https://developers.google.com/web/fundamentals/design-and-ux/typography/variable-fonts
https://variablefonts.typenetwork.com
https://medium.com/variable-fonts
In desktop apps
https://theblog.adobe.com/can-variable-fonts-illustrator-cc
https://helpx.adobe.com/nz/photoshop/using/fonts.html#variable_fonts
Online
https://developers.google.com/fonts/docs/getting_started
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fonts/Variable_Fonts_Guide
https://developer.microsoft.com/en-us/microsoft-edge/testdrive/demos/variable-fonts
Installing fonts
MacOS: https://support.apple.com/en-us/HT201749
Linux: https://www.google.com/search?q=how+to+install+a+font+on+gnu%2Blinux
Windows: https://support.microsoft.com/en-us/help/314960/how-to-install-or-remove-a-font-in-windows
Android Apps
https://developers.google.com/fonts/docs/android
https://developer.android.com/guide/topics/ui/look-and-feel/downloadable-fonts
License
-------
Please read the full license text (OFL.txt) to understand the permissions,
restrictions and requirements for usage, redistribution, and modification.
You can use them in your products & projects – print or digital,
commercial or otherwise.
This isn't legal advice, please consider consulting a lawyer and see the full
license for all details.
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect y="48" width="48" height="48" rx="24" transform="rotate(-90 0 48)" fill="white" fill-opacity="0.25"/>
<rect x="0.5" y="47.5" width="47" height="47" rx="23.5" transform="rotate(-90 0.5 47.5)" stroke="black" stroke-opacity="0.2"/>
<path d="M20.6667 31L22.4375 29.1406L18.7917 25.3125H34V22.6875H18.7917L22.4375 18.8594L20.6667 17L14 24L20.6667 31Z" fill="black"/>
</svg>
This file is too large to display.
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!