First Commit
This commit is contained in:
+22
@@ -0,0 +1,22 @@
|
||||
// @project
|
||||
import { Clientele3 } from '@/blocks/clientele';
|
||||
import { DynamicComponentType } from '@/enum';
|
||||
|
||||
/*************************** CLIENTELE 3 - DATA ***************************/
|
||||
|
||||
const data = {
|
||||
title: '4,000+ companies already growing',
|
||||
clienteleList: [
|
||||
{ image: { component: 'clientele/Techlify', type: DynamicComponentType.IMAGE } },
|
||||
{ image: { component: 'clientele/Marketly', type: DynamicComponentType.IMAGE } },
|
||||
{ image: { component: 'clientele/Realtor', type: DynamicComponentType.IMAGE } },
|
||||
{ image: { component: 'clientele/Financely', type: DynamicComponentType.IMAGE } },
|
||||
{ image: { component: 'clientele/Realtor', type: DynamicComponentType.IMAGE } }
|
||||
]
|
||||
};
|
||||
|
||||
/*************************** BLOCK - CLIENTELE 3 ***************************/
|
||||
|
||||
export default function BlockClientele3() {
|
||||
return <Clientele3 {...data} />;
|
||||
}
|
||||
Vendored
+35
@@ -0,0 +1,35 @@
|
||||
// @project
|
||||
import { ContactUs4 } from '@/blocks/contact-us';
|
||||
|
||||
/*************************** CONTACT US 4 - DATA ***************************/
|
||||
|
||||
const data = {
|
||||
heading: 'We’d love to hear from you',
|
||||
caption: 'Explore key statistics and trends shaping our understanding of the current landscape.',
|
||||
list: [
|
||||
{
|
||||
icon: 'tabler-phone',
|
||||
title: 'Contact Sale',
|
||||
content: 'Speak to someone from our sales team.',
|
||||
link: { children: 'Contact Sales' }
|
||||
},
|
||||
{
|
||||
icon: 'tabler-help-circle',
|
||||
title: 'Have a Question',
|
||||
content: 'See our frequently asked question',
|
||||
link: { children: 'Get Answers' }
|
||||
},
|
||||
{
|
||||
icon: 'tabler-folder-check',
|
||||
title: 'Press & Media',
|
||||
content: 'Get in touch with our PR team',
|
||||
link: { children: 'Press Contact' }
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
/*************************** BLOCK - CONTACT US 4 ***************************/
|
||||
|
||||
export default function BlockContactUs4() {
|
||||
return <ContactUs4 {...data} />;
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
// @mui
|
||||
import Typography from '@mui/material/Typography';
|
||||
|
||||
// @project
|
||||
import branding from '@/branding.json';
|
||||
import { Cta4 } from '@/blocks/cta';
|
||||
|
||||
/*************************** CALL TO ACTION 4 - HEADLINE ***************************/
|
||||
|
||||
function HeadlineText() {
|
||||
return (
|
||||
<Typography variant="h2">
|
||||
Enhance performance{' '}
|
||||
<Typography variant="h2" component="span" sx={{ color: 'text.secondary' }}>
|
||||
and efficiency. Dive into {branding.brandName} for a{' '}
|
||||
</Typography>
|
||||
better cloud experience.
|
||||
</Typography>
|
||||
);
|
||||
}
|
||||
|
||||
/*************************** CALL TO ACTION 4 - DATA ***************************/
|
||||
|
||||
const data = {
|
||||
headLine: <HeadlineText />,
|
||||
primaryBtn: { children: 'Get Started' },
|
||||
profileGroups: {
|
||||
avatarGroups: [
|
||||
{ avatar: '/assets/images/user/avatar1.png' },
|
||||
{ avatar: '/assets/images/user/avatar2.png' },
|
||||
{ avatar: '/assets/images/user/avatar3.png' },
|
||||
{ avatar: '/assets/images/user/avatar4.png' },
|
||||
{ avatar: '/assets/images/user/avatar5.png' }
|
||||
],
|
||||
review: '10k+ Reviews (4.5 out of 5)'
|
||||
},
|
||||
list: [{ primary: `Automated Scaling for Efficiency` }, { primary: 'Real-time Performance Insights' }],
|
||||
clientContent: '300+ Client Trust Us'
|
||||
};
|
||||
|
||||
/*************************** BLOCK - CALL TO ACTION 4 ***************************/
|
||||
|
||||
export default function BlockCta4() {
|
||||
return <Cta4 {...data} />;
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
// @project
|
||||
import branding from '@/branding.json';
|
||||
import { Cta5 } from '@/blocks/cta';
|
||||
|
||||
/*************************** CALL TO ACTION 5 - DATA ***************************/
|
||||
|
||||
const data = {
|
||||
heading: `${branding.brandName} Community`,
|
||||
caption: 'Collaborate confidently with granular access controls and regulatory compliance. ',
|
||||
label: 'Join Community',
|
||||
input: {
|
||||
adornmentBtn: { children: 'Get Started' },
|
||||
helpertext: '1 email per week. No spam. Ever. Unsubscribe anytime'
|
||||
},
|
||||
saleData: { count: 10, defaultUnit: 'X', caption: 'Achieving faster sales through streamlined' },
|
||||
profileGroups: {
|
||||
avatarGroups: [
|
||||
{ avatar: '/assets/images/user/avatar1.png' },
|
||||
{ avatar: '/assets/images/user/avatar2.png' },
|
||||
{ avatar: '/assets/images/user/avatar3.png' },
|
||||
{ avatar: '/assets/images/user/avatar4.png' },
|
||||
{ avatar: '/assets/images/user/avatar5.png' }
|
||||
],
|
||||
review: '10k+ Reviews (4.5 out of 5)'
|
||||
}
|
||||
};
|
||||
|
||||
/*************************** BLOCK - CALL TO ACTION 5 ***************************/
|
||||
|
||||
export default function BlockCta5() {
|
||||
return <Cta5 {...data} />;
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// @project
|
||||
import { Error404Page } from '@/blocks/maintenance';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
/*************************** METADATA - ERROR 404 ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.error404Page };
|
||||
|
||||
/*************************** ERROR 404 - DATA ***************************/
|
||||
|
||||
const data = {
|
||||
primaryBtn: { children: 'Back to Home Page', href: '/' },
|
||||
heading: `Looks like you've taken a wrong turn. Lets get you back on track!`
|
||||
};
|
||||
|
||||
/*************************** BLOCK - ERROR 404 ***************************/
|
||||
|
||||
export default function BlockError404Page() {
|
||||
return <Error404Page {...data} />;
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// @project
|
||||
import { Error500Page } from '@/blocks/maintenance';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
/*************************** METADATA - ERROR 500 ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.error500Page };
|
||||
|
||||
/*************************** ERROR 500 - DATA ***************************/
|
||||
|
||||
const data = {
|
||||
primaryBtn: { children: 'Back to Home Page', href: '/' },
|
||||
heading: 'Please try again later or feel free to contact us if the problem persists.'
|
||||
};
|
||||
|
||||
/*************************** BLOCK - ERROR 500 ***************************/
|
||||
|
||||
export default function BlockError500Page() {
|
||||
return <Error500Page {...data} />;
|
||||
}
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
// @project
|
||||
import branding from '@/branding.json';
|
||||
import { Faq6 } from '@/blocks/faq';
|
||||
|
||||
/*************************** FAQ 6 - DATA ***************************/
|
||||
|
||||
const data = {
|
||||
heading: 'Frequently Asked Questions',
|
||||
caption: `Answers to common queries about ${branding.brandName}.`,
|
||||
defaultExpanded: 'Fees & Charges',
|
||||
faqList: [
|
||||
{
|
||||
question: `Is ${branding.brandName} only for SaaS web apps?`,
|
||||
answer: `While ${branding.brandName} is designed with SaaS applications in mind, it’s not limited to SaaS products. ${branding.brandName} is multipurpose and can be used for a variety of websites and applications, whether it’s for an agency, digital product, CRM, blog, AI platform, or any other system. ${branding.brandName} is versatile and adaptable to fit any use case, SaaS or not. It’s built for all types of projects!`,
|
||||
category: 'General'
|
||||
},
|
||||
{
|
||||
question: `What makes ${branding.brandName} different from other UI Kits?`,
|
||||
answer: `${branding.brandName} offers industry-specific templates, a React Material UI Kit, Figma UI Kit, and flexible customization options that cater to both front-end marketing and admin interfaces.`,
|
||||
category: 'General'
|
||||
},
|
||||
{
|
||||
question: `Is ${branding.brandName} suitable for both developers and designers?`,
|
||||
answer: {
|
||||
content: `Yes, ${branding.brandName} is built for both, with a Figma UI kit for designers and React code for developers.`,
|
||||
type: 'list',
|
||||
data: [
|
||||
{ primary: 'Figma UI Kit for Designers.' },
|
||||
{ primary: 'React Material UI Code for Developers.' },
|
||||
{ primary: 'Seamless Collaboration.' }
|
||||
]
|
||||
},
|
||||
category: 'General'
|
||||
},
|
||||
{
|
||||
question: `What is the difference between the Figma and codebase versions?`,
|
||||
answer:
|
||||
'The Figma version is for design and prototyping, while the codebase version provides ready-to-use React components for development.',
|
||||
category: 'General'
|
||||
},
|
||||
{
|
||||
question: 'How can I download the template after purchase?',
|
||||
answer: 'You will receive the template in a .zip format immediately after successfully purchasing the template.',
|
||||
category: 'General'
|
||||
},
|
||||
{
|
||||
question: `What's included in the ${branding.brandName} license?`,
|
||||
answer: {
|
||||
content: 'It includes the Figma UI kit, React Material UI codebase, regular updates, and customer support.',
|
||||
type: 'list',
|
||||
data: [
|
||||
{ primary: `One License = One End Product` },
|
||||
{ primary: `Separate License for Each Product` },
|
||||
{ primary: `Comply with License Terms` }
|
||||
]
|
||||
},
|
||||
category: 'Pricing & Licenses'
|
||||
},
|
||||
{
|
||||
question: `Can I use ${branding.brandName} for multiple projects?`,
|
||||
answer: {
|
||||
content:
|
||||
'No, one license allows usage in a single end product. For each new product or project, you are required to purchase a separate license. This ensures compliance with the licensing terms and provides ongoing support for each individual product. Make sure to obtain the appropriate license for every new project you work on.',
|
||||
type: 'list',
|
||||
data: [
|
||||
{ primary: `One License = One End Product` },
|
||||
{ primary: `Separate License for Each Product` },
|
||||
{ primary: `Comply with License Terms` }
|
||||
]
|
||||
},
|
||||
category: 'Pricing & Licenses'
|
||||
},
|
||||
|
||||
{
|
||||
question: 'Do you offer refunds?',
|
||||
answer:
|
||||
'Yes, we offer refunds, but only if you provide a valid reason to support your claim. For more details, please review our MUI Store Refund Policy.',
|
||||
category: 'Pricing'
|
||||
},
|
||||
{
|
||||
question: 'Do I get access to future updates?',
|
||||
answer: {
|
||||
content:
|
||||
'Yes, you will receive future updates for 1 year from the date of purchase. If you need updates after 1 year, you will need to purchase the license again. However, this is not a renewal—your license is valid for a lifetime, but updates are limited to the 1-year period.',
|
||||
type: 'list',
|
||||
data: [{ primary: `1 Year Free Updates` }, { primary: `License validity is lifetime` }]
|
||||
},
|
||||
category: 'Support & Updates'
|
||||
},
|
||||
{
|
||||
question: 'Is support included with the template purchase?',
|
||||
answer: {
|
||||
content:
|
||||
'Support is included for 6 months, but it is limited to resolving issues within the template itself. We do not provide support for installation, customization queries, or troubleshooting unrelated issues. For ongoing support beyond 6 months, you will need to extend the support period with an additional purchase.',
|
||||
type: 'list',
|
||||
data: [{ primary: `6 Months Support` }, { primary: `No Installation Support` }, { primary: `No Customization Support` }]
|
||||
},
|
||||
category: 'Support & Updates'
|
||||
}
|
||||
],
|
||||
getInTouch: { link: { children: 'Get in Touch' } },
|
||||
categories: ['General', 'Pricing & Licenses', 'Support & Updates'],
|
||||
activeCategory: 'General'
|
||||
};
|
||||
|
||||
/*************************** FAQ - 6 ***************************/
|
||||
|
||||
export default function BlockFaq6() {
|
||||
return <Faq6 {...data} />;
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
// @project
|
||||
import { Feature18 } from '@/blocks/feature';
|
||||
|
||||
/*************************** FEATURE 18 - DATA ***************************/
|
||||
|
||||
const data = {
|
||||
heading: 'Dynamic Task Automation',
|
||||
caption: 'Gain insights into performance metrics and proactively address issues for uninterrupted operations.',
|
||||
topics: [
|
||||
{
|
||||
icon: 'tabler-sparkles',
|
||||
title: 'AI Assistant',
|
||||
title2: 'Advanced AI Integration',
|
||||
description: 'Leverage cutting-edge AI to enhance decision-making and streamline operations.',
|
||||
image: '/assets/images/graphics/ai/graphics12-light.svg',
|
||||
list: [
|
||||
{ primary: 'Intelligent Decision Support' },
|
||||
{ primary: 'Predictive Analytics' },
|
||||
{ primary: 'Natural Language Processing' },
|
||||
{ primary: 'Real-time Insights' }
|
||||
],
|
||||
actionBtn: { children: 'Explore all Features' },
|
||||
actionBtn2: { children: 'Customize' }
|
||||
},
|
||||
{
|
||||
icon: 'tabler-chart-histogram',
|
||||
title: 'Simple Analysis',
|
||||
title2: 'Data Lifecycle Management',
|
||||
description: 'Process data in parallel, significantly boosting data processing speed.',
|
||||
image: '/assets/images/graphics/ai/graphics7-light.svg',
|
||||
list: [{ primary: 'Fortress for Your Data' }, { primary: 'Granular Access Controls' }, { primary: 'Automated Backup Solutions' }],
|
||||
actionBtn: { children: 'Explore all Features' },
|
||||
actionBtn2: { children: 'Customize' }
|
||||
},
|
||||
{
|
||||
icon: 'tabler-users',
|
||||
title: 'Easy Collaboration',
|
||||
title2: 'Seamless Teamwork',
|
||||
description: 'Foster collaboration with intuitive tools designed for team success.',
|
||||
image: '/assets/images/graphics/ai/graphics4-light.svg',
|
||||
list: [{ primary: 'Shared Workspaces' }, { primary: 'Real-time Collaboration' }, { primary: 'Task Assignment and Tracking' }],
|
||||
actionBtn: { children: 'Explore all Features' },
|
||||
actionBtn2: { children: 'Customize' }
|
||||
},
|
||||
{
|
||||
icon: 'tabler-settings-up',
|
||||
title: 'Smart Automation',
|
||||
title2: 'Intelligent Task Management',
|
||||
description: 'Automate repetitive tasks and focus on what truly matters with smart solutions.',
|
||||
image: '/assets/images/graphics/ai/graphics9-light.svg',
|
||||
list: [{ primary: 'Workflow Automation' }, { primary: 'Trigger-based Actions' }, { primary: 'Scalable Solutions' }],
|
||||
actionBtn: { children: 'Explore all Features' },
|
||||
actionBtn2: { children: 'Customize' }
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
/*************************** BLOCK - FEATURE 18 ***************************/
|
||||
|
||||
export default function BlockFeature18() {
|
||||
return <Feature18 {...data} />;
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
// @project
|
||||
import { Feature20 } from '@/blocks/feature';
|
||||
|
||||
/*************************** FEATURE 20 - DATA ***************************/
|
||||
|
||||
const data = {
|
||||
heading: 'Intelligent Data Compression',
|
||||
caption: 'Process data faster, enhance system, and gain quicker insights.',
|
||||
image: '/assets/images/graphics/ai/graphics4-light.svg',
|
||||
actionBtn: { children: 'Explore all Features' },
|
||||
features: [
|
||||
{
|
||||
icon: 'tabler-chart-histogram',
|
||||
title: 'Parallel Processing',
|
||||
content: 'Process data in parallel, significantly boosting data processing speed.'
|
||||
},
|
||||
{
|
||||
icon: 'tabler-artboard',
|
||||
title: 'Scalable Data Pipelines',
|
||||
content: 'Build and manage scalable and efficient data processing pipelines.'
|
||||
},
|
||||
{
|
||||
icon: 'tabler-database',
|
||||
title: 'Data Quality Assurance',
|
||||
content: 'Tools to ensure and maintain high data quality and integrity.'
|
||||
},
|
||||
{
|
||||
icon: 'tabler-settings-up',
|
||||
title: 'Dynamic Task Automation',
|
||||
content: 'Automate dynamic tasks to enhance workflow efficiency.'
|
||||
},
|
||||
{
|
||||
icon: 'tabler-devices-code',
|
||||
title: 'Cross-Platform ',
|
||||
content: 'Compatibility with various platforms for versatile data processing.'
|
||||
},
|
||||
{
|
||||
icon: 'tabler-route',
|
||||
title: 'Workflow Optimization',
|
||||
content: 'Optimize workflows for increased productivity and efficiency.'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
/*************************** BLOCK - FEATURE 20 ***************************/
|
||||
|
||||
export default function BlockFeature20() {
|
||||
return <Feature20 {...data} />;
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
// @project
|
||||
import branding from '@/branding.json';
|
||||
import { Feature21 } from '@/blocks/feature';
|
||||
|
||||
/*************************** FEATURE 21 - DATA ***************************/
|
||||
|
||||
const data = {
|
||||
heading: `Unlock the Power of ${branding.brandName}`,
|
||||
caption: 'Discover the myriad benefits that come with our innovative platform.',
|
||||
image: '/assets/images/graphics/ai/desktop1-light.svg',
|
||||
primaryBtn: { children: 'Buy Now' },
|
||||
secondaryBtn: { children: 'Get free figma' },
|
||||
features: [
|
||||
{
|
||||
icon: 'tabler-app-window',
|
||||
title: 'Tested in multiple browsers'
|
||||
},
|
||||
{
|
||||
icon: 'tabler-box-model',
|
||||
title: 'Ready to use template'
|
||||
},
|
||||
{
|
||||
icon: 'tabler-folder-check',
|
||||
title: 'Always updated package'
|
||||
},
|
||||
{
|
||||
icon: 'tabler-code',
|
||||
title: 'Optimised code structure'
|
||||
},
|
||||
{
|
||||
icon: 'tabler-lock',
|
||||
title: 'Pre Define Authentication'
|
||||
},
|
||||
{
|
||||
icon: 'tabler-git-branch',
|
||||
title: 'Clean folder structure to adapt'
|
||||
},
|
||||
{
|
||||
icon: 'tabler-toggle-right',
|
||||
title: 'Easy to switch themes'
|
||||
},
|
||||
{
|
||||
icon: 'tabler-components',
|
||||
title: 'Pluggable components'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
/*************************** BLOCK - FEATURE 21 ***************************/
|
||||
|
||||
export default function BlockFeature21() {
|
||||
return <Feature21 {...data} />;
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// @project
|
||||
import { Footer7 } from '@/blocks/footer';
|
||||
|
||||
/*************************** BLOCK - FOOTER 7 ***************************/
|
||||
|
||||
export default function BlockFooter7() {
|
||||
return <Footer7 />;
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
// @mui
|
||||
import CardMedia from '@mui/material/CardMedia';
|
||||
import Chip from '@mui/material/Chip';
|
||||
import Typography from '@mui/material/Typography';
|
||||
|
||||
// @project
|
||||
import { Hero17 } from '@/blocks/hero';
|
||||
|
||||
/*************************** HERO 17 - DATA ***************************/
|
||||
|
||||
const data = {
|
||||
chip: {
|
||||
label: (
|
||||
<>
|
||||
<Typography variant="caption" sx={{ color: 'text.secondary' }}>
|
||||
Over 200+
|
||||
</Typography>
|
||||
<Chip
|
||||
label={
|
||||
<Typography variant="caption" sx={{ color: 'primary.main' }}>
|
||||
Design Blocks
|
||||
</Typography>
|
||||
}
|
||||
sx={{ height: 24, bgcolor: 'primary.lighter', mr: -1, ml: 0.75, '& .MuiChip-label': { px: 1.25 } }}
|
||||
icon={
|
||||
<CardMedia
|
||||
component="img"
|
||||
image="/assets/images/shared/celebration.svg"
|
||||
sx={{ width: 16, height: 16 }}
|
||||
alt="celebration"
|
||||
loading="lazy"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
},
|
||||
headLine: 'Real-time Performance Monitoring',
|
||||
captionLine: 'Identify and resolve issues proactively for uninterrupted operations.',
|
||||
primaryBtn: { children: 'Try Predictive Cost Analytics' },
|
||||
videoSrc: 'https://d2elhhoq00m1pj.cloudfront.net/saasable-intro.mp4',
|
||||
videoThumbnail: '/assets/videos/thumbnails/intro-thumbnail.png',
|
||||
listData: [
|
||||
{ image: '/assets/images/shared/react.svg', title: 'React 19' },
|
||||
{ image: '/assets/images/shared/next-js.svg', title: 'Next.js' },
|
||||
{ image: '/assets/images/shared/material-ui.svg', title: 'Material UI v7' },
|
||||
{ image: '/assets/images/shared/typescript.svg', title: 'TypeScript' },
|
||||
{ image: '/assets/images/shared/javascript.svg', title: 'JavaScript' },
|
||||
{ image: '/assets/images/shared/m3.svg', title: 'Material 3' },
|
||||
{ image: '/assets/images/shared/figma.svg', title: 'Figma' }
|
||||
]
|
||||
};
|
||||
|
||||
/*************************** BLOCK - HERO 17 ***************************/
|
||||
|
||||
export default function BlockHero17() {
|
||||
return <Hero17 {...data} />;
|
||||
}
|
||||
Vendored
+29
@@ -0,0 +1,29 @@
|
||||
// @project
|
||||
import { Integration2 } from '@/blocks/integration';
|
||||
|
||||
/*************************** INTEGRATION 2 - DATA ***************************/
|
||||
|
||||
const data = {
|
||||
headLine: 'Connect with top-tier tools available Interface',
|
||||
captionLine: 'Discover the features that will transform your customer relationships',
|
||||
primaryBtn: { children: 'See All Integration' },
|
||||
tagList: [
|
||||
{ label: 'Slack', icon: 'tabler-brand-slack' },
|
||||
{ label: 'Abstract', icon: 'tabler-brand-abstract' },
|
||||
{ label: 'Asana', icon: 'tabler-brand-asana' },
|
||||
{ label: 'Back Bone', icon: 'tabler-brand-backbone' },
|
||||
{ label: 'Intercom', icon: 'tabler-brand-intercom' },
|
||||
{ label: 'Master Card', icon: 'tabler-brand-mastercard' },
|
||||
{ label: 'Skype', icon: 'tabler-brand-skype' },
|
||||
{ label: 'Google Drive', icon: 'tabler-brand-google-drive' },
|
||||
{ label: 'Tripadvisor', icon: 'tabler-brand-tripadvisor' },
|
||||
{ label: 'Facebook Messenger', icon: 'tabler-brand-messenger' },
|
||||
{ label: 'Paypal', icon: 'tabler-brand-paypal' }
|
||||
]
|
||||
};
|
||||
|
||||
/*************************** BLOCK - INTEGRATION 2 ***************************/
|
||||
|
||||
export default function BlockIntegration2() {
|
||||
return <Integration2 {...data} />;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
'use client';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
// @mui
|
||||
import Box from '@mui/material/Box';
|
||||
|
||||
/*************************** LAYOUT - BLOCKS ***************************/
|
||||
|
||||
export default function Blocks({ children }) {
|
||||
|
||||
return <Box sx={{ '& :focus-visible': { outline: 'none' } }}>{children}</Box>;
|
||||
}
|
||||
|
||||
Blocks.propTypes = { children: PropTypes.any };
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
// @mui
|
||||
import Button from '@mui/material/Button';
|
||||
import CardMedia from '@mui/material/CardMedia';
|
||||
import Chip from '@mui/material/Chip';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import Box from '@mui/material/Box';
|
||||
|
||||
// @project
|
||||
import branding from '@/branding.json';
|
||||
import { MegaMenu4 } from '@/blocks/mega-menu';
|
||||
import { MenuPopper } from '@/components/navbar';
|
||||
import { landings } from '@/data/landings';
|
||||
import { BUY_NOW_URL } from '@/path';
|
||||
|
||||
/*************************** MEGAMENU 4 - FOOTER ***************************/
|
||||
|
||||
function footerData() {
|
||||
return (
|
||||
<Stack direction={{ sm: 'row' }} sx={{ gap: 1.5, justifyContent: 'space-between', alignItems: { xs: 'flex-start', sm: 'center' } }}>
|
||||
<Stack sx={{ gap: 1 }}>
|
||||
<Stack direction="row" sx={{ alignItems: 'center', gap: 1 }}>
|
||||
<Typography variant="h5">Explore our range of landing demos tailored to suit your needs</Typography>
|
||||
<Chip
|
||||
label={<Typography variant="caption">Featured</Typography>}
|
||||
size="small"
|
||||
sx={{
|
||||
bgcolor: 'background.default',
|
||||
'& .MuiChip-label': { px: 1.5, py: 0.5 },
|
||||
display: { xs: 'none', sm: 'inline-flex' }
|
||||
}}
|
||||
icon={
|
||||
<CardMedia
|
||||
component="img"
|
||||
image="/assets/images/shared/celebration.svg"
|
||||
sx={{ width: 16, height: 16 }}
|
||||
alt="celebration"
|
||||
loading="lazy"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Stack>
|
||||
<Typography variant="body2" sx={{ color: 'text.secondary' }}>
|
||||
{branding.brandName} offers 200+ customizable blocks, empowering you to effortlessly design and build landing pages tailored to
|
||||
your product or service needs.
|
||||
</Typography>
|
||||
</Stack>
|
||||
<Button
|
||||
variant="contained"
|
||||
sx={{ display: { xs: 'none', sm: 'inline-flex' }, minWidth: 100, px: { xs: 2 }, py: 1.25 }}
|
||||
href={BUY_NOW_URL}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Buy Now
|
||||
</Button>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
/*************************** MEGAMENU 4 - DATA ***************************/
|
||||
|
||||
const data = {
|
||||
menuItems: landings,
|
||||
footerData: footerData()
|
||||
};
|
||||
|
||||
/*************************** BLOCK - MEGAMENU 4 ***************************/
|
||||
|
||||
export default function BlockMegamenu4() {
|
||||
return (
|
||||
<Stack sx={{ alignItems: 'center' }}>
|
||||
<Box sx={{ my: 4 }}>
|
||||
<MenuPopper toggleProps={{ children: 'Mega Menu 4' }} defaultOpen popperWidth={936} offset={8}>
|
||||
<MegaMenu4 {...data} />
|
||||
</MenuPopper>
|
||||
</Box>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
// @mui
|
||||
import Button from '@mui/material/Button';
|
||||
import CardMedia from '@mui/material/CardMedia';
|
||||
import Chip from '@mui/material/Chip';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import Box from '@mui/material/Box';
|
||||
|
||||
// @project
|
||||
import { MegaMenu5 } from '@/blocks/mega-menu';
|
||||
import { MenuPopper } from '@/components/navbar';
|
||||
import { BUY_NOW_URL, DOCS_URL } from '@/path';
|
||||
|
||||
/*************************** MEGAMENU 5 - BANNER ***************************/
|
||||
|
||||
function bannerData() {
|
||||
return (
|
||||
<Stack sx={{ alignItems: 'flex-start', gap: 3, height: 1, justifyContent: 'center' }}>
|
||||
<Stack sx={{ gap: 1 }}>
|
||||
<Stack sx={{ alignItems: 'flex-start', gap: 1.5 }}>
|
||||
<Chip
|
||||
label={<Typography variant="subtitle2">Coming Soon</Typography>}
|
||||
icon={
|
||||
<CardMedia
|
||||
component="img"
|
||||
image="/assets/images/shared/celebration.svg"
|
||||
sx={{ width: 16, height: 16 }}
|
||||
alt="celebration"
|
||||
loading="lazy"
|
||||
/>
|
||||
}
|
||||
size="small"
|
||||
sx={{ bgcolor: 'background.default', '& .MuiChip-label': { px: 1.5, py: 0.5 }, '& .MuiChip-icon': { ml: 1.25 } }}
|
||||
/>
|
||||
<Typography variant="h5">We are coming with many more landings</Typography>
|
||||
</Stack>
|
||||
<Typography variant="body2" sx={{ color: 'text.secondary' }}>
|
||||
Discover tailored solutions to elevate your business. Stay ahead with our latest updates and insights.
|
||||
</Typography>
|
||||
</Stack>
|
||||
<Button
|
||||
variant="contained"
|
||||
sx={{ minWidth: 92, px: { xs: 2 }, py: 1.25 }}
|
||||
href={BUY_NOW_URL}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Buy Now
|
||||
</Button>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
/*************************** MEGAMENU 5 - DATA ***************************/
|
||||
|
||||
const data = {
|
||||
menuItems: [
|
||||
{
|
||||
title: 'General',
|
||||
itemsList: [
|
||||
{ title: 'About', status: 'Pro' },
|
||||
{ title: 'Career', status: 'Pro' },
|
||||
{ title: 'FAQs', status: 'Pro' },
|
||||
{ title: 'Privacy Policy', link: { href: '/privacy-policy', target: '_blank' } },
|
||||
{ title: 'Contact Us', link: { href: '/contact', target: '_blank' } },
|
||||
{ title: 'Coming Soon', status: 'Pro' },
|
||||
{ title: 'Error 404', link: { href: '/blocks/error404', target: '_blank' } }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'External',
|
||||
itemsList: [
|
||||
{ title: 'Blog', link: { href: 'https://blog.saasable.io/', target: '_blank' } },
|
||||
{ title: 'Documentation', link: { href: DOCS_URL, target: '_blank' } },
|
||||
{ title: 'Support', link: { href: 'https://codedthemes.support-hub.io/', target: '_blank' } },
|
||||
{
|
||||
title: 'Discord',
|
||||
link: { href: 'https://discord.com/invite/2WpeGsQH98', target: '_blank' }
|
||||
},
|
||||
{ title: 'Terms & Conditions', link: { href: 'https://mui.com/store/terms/', target: '_blank' } }
|
||||
]
|
||||
}
|
||||
],
|
||||
bannerData: bannerData()
|
||||
};
|
||||
|
||||
/*************************** BLOCK - MEGAMENU 5 ***************************/
|
||||
|
||||
export default function BlockMegamenu5() {
|
||||
return (
|
||||
<Stack sx={{ alignItems: 'center' }}>
|
||||
<Box sx={{ my: 4 }}>
|
||||
<MenuPopper toggleProps={{ children: 'Mega Menu 5' }} defaultOpen popperWidth={750} offset={8}>
|
||||
<MegaMenu5 {...data} />
|
||||
</MenuPopper>
|
||||
</Box>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// @project
|
||||
import branding from '@/branding.json';
|
||||
import { Metrics5 } from '@/blocks/metrics';
|
||||
|
||||
/*************************** BENEFIT 5 - DATA ***************************/
|
||||
|
||||
const data = {
|
||||
heading: 'Data Processing at its Peak',
|
||||
caption: `See the success stories of organizations scaling with ${branding.brandName}`,
|
||||
blockDetail: [
|
||||
{ counter: 99, defaultUnit: '%', caption: 'Compression Efficiency Achieved' },
|
||||
{ counter: 40, defaultUnit: '%', caption: 'Reduction in Storage Costs' },
|
||||
{ counter: 80, defaultUnit: '%', caption: 'Reduction in Over-Provisioning' },
|
||||
{ counter: 4.5, defaultUnit: '/5', caption: 'Average User Satisfaction Rating' }
|
||||
]
|
||||
};
|
||||
|
||||
/*************************** BLOCK - METRICS 5 ***************************/
|
||||
|
||||
export default function BlockMetrics5() {
|
||||
return <Metrics5 {...data} />;
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
// @project
|
||||
import { Other2 } from '@/blocks/other';
|
||||
import { Navbar10 } from '@/blocks/navbar';
|
||||
import { NavbarContent10 } from '@/blocks/navbar/navbar-content';
|
||||
import { MegaMenuType } from '@/enum';
|
||||
|
||||
/*************************** NAVBAR 10 - DATA ***************************/
|
||||
|
||||
const navbar = {
|
||||
primaryBtn: { children: 'Get Started' },
|
||||
secondaryBtn: { children: 'Sign in' },
|
||||
navItems: [
|
||||
{ id: 'overview', title: 'Overview' },
|
||||
{ id: 'products', title: 'Products' },
|
||||
{ id: 'pricing', title: 'Pricing' },
|
||||
{
|
||||
id: 'resource',
|
||||
title: 'Resource',
|
||||
megaMenu: {
|
||||
type: MegaMenuType.MEGAMENU2,
|
||||
toggleBtn: { children: 'Resource', size: 'small', sx: { color: 'text.primary', py: 1.5 } },
|
||||
menuItems: [
|
||||
{
|
||||
title: 'Blog',
|
||||
content: 'Explore our latest articles and insights.'
|
||||
},
|
||||
{
|
||||
title: 'Help Center',
|
||||
content: 'Find answers to common questions and support topics.',
|
||||
selected: true
|
||||
},
|
||||
{
|
||||
title: 'Guides',
|
||||
content: 'Follow our comprehensive guides to get started.'
|
||||
},
|
||||
{
|
||||
title: 'Events',
|
||||
content: 'Stay informed about upcoming events and webinars.'
|
||||
},
|
||||
{
|
||||
title: 'Security',
|
||||
content: 'Learn about our security measures to protect your data.'
|
||||
},
|
||||
{
|
||||
title: 'Payments',
|
||||
content: 'Get help with billing and payment options.'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{ id: 'help', title: 'Help', icon: 'tabler-help' }
|
||||
]
|
||||
};
|
||||
|
||||
/*************************** BLOCK - NAVBAR 10 ***************************/
|
||||
|
||||
export default function BlockNavbar10() {
|
||||
return (
|
||||
<>
|
||||
<Navbar10>
|
||||
<NavbarContent10 {...navbar} />
|
||||
</Navbar10>
|
||||
<Other2 />
|
||||
</>
|
||||
);
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
// @project
|
||||
import Other1 from '@/blocks/other/Other1';
|
||||
import { PAGE_PATH, SECTION_PATH } from '@/path';
|
||||
|
||||
// @asssets
|
||||
const imagePrefix = '/assets/images/presentation';
|
||||
|
||||
/*************************** OTHER 1 - DATA ***************************/
|
||||
|
||||
const data = {
|
||||
heading: 'Customizable Building Blocks',
|
||||
description: 'Kickstart your SaaS landing page design with pre-designed templates featuring versatile components.',
|
||||
primaryBtn: { children: 'Explore all Blocks', href: SECTION_PATH },
|
||||
sections: [
|
||||
{
|
||||
title: 'Hero',
|
||||
subTitle: '17 Different Variants',
|
||||
image: `${imagePrefix}/hero-light.svg`,
|
||||
link: PAGE_PATH.hero
|
||||
},
|
||||
{
|
||||
title: 'Call to Action',
|
||||
subTitle: '12 Different Variants',
|
||||
image: `${imagePrefix}/cta-light.svg`,
|
||||
link: PAGE_PATH.cta
|
||||
},
|
||||
{
|
||||
title: 'Feature',
|
||||
subTitle: '23 Different Variants',
|
||||
image: `${imagePrefix}/feature-light.svg`,
|
||||
link: PAGE_PATH.feature
|
||||
},
|
||||
{
|
||||
title: 'Metrics',
|
||||
subTitle: '9 Different Variants',
|
||||
image: `${imagePrefix}/metrics-light.svg`,
|
||||
link: PAGE_PATH.metrics
|
||||
},
|
||||
{
|
||||
title: 'Process',
|
||||
subTitle: '7 Different Variants',
|
||||
image: `${imagePrefix}/process-light.svg`,
|
||||
link: PAGE_PATH.process
|
||||
},
|
||||
{
|
||||
title: 'Integration',
|
||||
subTitle: '8 Different Variants',
|
||||
image: `${imagePrefix}/integration-light.svg`,
|
||||
link: PAGE_PATH.integration
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
/*************************** BLOCK - OTHER 1 ***************************/
|
||||
|
||||
export default function BlockOther1() {
|
||||
return <Other1 {...data} />;
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// @project
|
||||
import Other2 from '@/blocks/other/Other2';
|
||||
|
||||
/*************************** BLOCK - OTHER 2 ***************************/
|
||||
|
||||
export default function BlockOther2() {
|
||||
return <Other2 />;
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
// @project
|
||||
import { Pricing9 } from '@/blocks/pricing';
|
||||
|
||||
/*************************** PRICING 9 - DATA ***************************/
|
||||
|
||||
const data = {
|
||||
heading: 'The Affordable Unfair Advantage',
|
||||
caption: 'Choose the plan that aligns with your cloud management requirements.',
|
||||
features: [
|
||||
{ id: 1, label: '1 Demo Landing' },
|
||||
{ id: 2, label: '7 Demo Landing' },
|
||||
{ id: 3, label: '25 Components Blocks' },
|
||||
{ id: 4, label: '193+ Component Blocks' },
|
||||
{ id: 5, label: 'Dark/Light Mode' },
|
||||
{ id: 6, label: 'Typescript Version' },
|
||||
{ id: 7, label: 'Design File (Figma)' },
|
||||
{ id: 8, label: 'Multiple Color Options' },
|
||||
{ id: 9, label: 'RTL' },
|
||||
{ id: 10, label: 'Supbase Authentication' }
|
||||
],
|
||||
plans: [
|
||||
{
|
||||
title: 'Free',
|
||||
price: 0,
|
||||
active: false,
|
||||
featureTitle: 'Features',
|
||||
exploreLink: { children: 'Get Started With Free' },
|
||||
featuresID: [1, 3]
|
||||
},
|
||||
{
|
||||
title: 'Pro',
|
||||
active: false,
|
||||
price: 69,
|
||||
featureTitle: 'Features',
|
||||
exploreLink: { children: 'Get Started With Pro' },
|
||||
featuresID: [2, 4, 5, 6, 7, 8, 9, 10]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
/*************************** BLOCK - PRICING 9 ***************************/
|
||||
|
||||
export default function BlockPricing9() {
|
||||
return <Pricing9 {...data} />;
|
||||
}
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
// @project
|
||||
import { PrivacyPolicy1 } from '@/blocks/privacy-policy';
|
||||
|
||||
/*************************** BLOCK - PRIVACY POLICY 1 ***************************/
|
||||
|
||||
export default function BlockPrivacyPolicy1() {
|
||||
return <PrivacyPolicy1 />;
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
//@project
|
||||
import { ProPage } from '@/blocks/pro-page';
|
||||
|
||||
/*************************** PRO PAGE - DATA ***************************/
|
||||
|
||||
const data = {
|
||||
image: '/assets/images/pro-page/Lock.svg'
|
||||
};
|
||||
|
||||
/*************************** BLOCK - PRO PAGE ***************************/
|
||||
|
||||
export default function BlockProPage() {
|
||||
return <ProPage {...data} />;
|
||||
}
|
||||
Vendored
+46
@@ -0,0 +1,46 @@
|
||||
// @mui
|
||||
import Typography from '@mui/material/Typography';
|
||||
|
||||
// @project
|
||||
import { SmallHero3 } from '@/blocks/small-hero';
|
||||
import GraphicsImage from '@/components/GraphicsImage';
|
||||
|
||||
/*************************** SMALL HERO 3 - HEADLINE ***************************/
|
||||
|
||||
function HeadlineText() {
|
||||
return (
|
||||
<Typography variant="h1" sx={{ width: { lg: '90%' } }}>
|
||||
Effortless CRM Management, Seamless Business
|
||||
<GraphicsImage
|
||||
sx={{
|
||||
display: 'inline-block',
|
||||
height: { xs: 32, sm: 45, md: 57 },
|
||||
width: { xs: 61, sm: 86, md: 109 },
|
||||
backgroundSize: 'contain',
|
||||
mx: { xs: 0.5, sm: 1, md: 1.5 },
|
||||
verticalAlign: 'sub'
|
||||
}}
|
||||
image="/assets/images/graphics/ai/rocket.svg"
|
||||
/>
|
||||
Growth
|
||||
</Typography>
|
||||
);
|
||||
}
|
||||
|
||||
/*************************** SMALL HERO 3 - DATA ***************************/
|
||||
|
||||
const data = {
|
||||
chip: {
|
||||
label: 'New Beta Version is Release ',
|
||||
link: { children: 'explore now', href: '#' }
|
||||
},
|
||||
captionLine: 'Empowering Businesses with a Customizable, Data-Driven CRM Solution.',
|
||||
headLine: <HeadlineText />,
|
||||
exploreBtn: { children: 'Explore More' }
|
||||
};
|
||||
|
||||
/*************************** BLOCK - SMALL HERO 3 ***************************/
|
||||
|
||||
export default function BlockSmallHero3() {
|
||||
return <SmallHero3 {...data} />;
|
||||
}
|
||||
Vendored
+71
@@ -0,0 +1,71 @@
|
||||
// @project
|
||||
import { Testimonial10 } from '@/blocks/testimonial';
|
||||
|
||||
/*************************** TESTIMONIAL 10 - DATA ***************************/
|
||||
|
||||
const data = {
|
||||
heading: 'Hear From Our Satisfied Users',
|
||||
caption: `Discover why users love our platform and how it's making a positive impact on their work and businesses.`,
|
||||
testimonials: [
|
||||
{
|
||||
title: 'Strongly endorsed!',
|
||||
ratings: 5,
|
||||
review: 'This platform exceeded my expectations! The features are robust, and the user interface is incredibly intuitive.',
|
||||
profile: { avatar: '', name: 'Sarah T.', role: 'Business Owner' }
|
||||
},
|
||||
{
|
||||
title: 'Top pick!',
|
||||
ratings: 4,
|
||||
review: `I've tried several platforms, and this one stands out for its reliability and user-friendly.`,
|
||||
profile: { avatar: '', name: 'Alex M.', role: 'Project Manager' }
|
||||
},
|
||||
{
|
||||
title: 'Widely praised!',
|
||||
ratings: 2,
|
||||
review: `Outstanding customer support! They're responsive and go above and beyond to ensure a smooth experience. Highly satisfied.`,
|
||||
profile: { avatar: '', name: 'Emily P.', role: 'Freelancer' }
|
||||
},
|
||||
{
|
||||
title: 'Hugely endorsed!',
|
||||
ratings: 5,
|
||||
review: `I've recommended this platform to colleagues, and they've all been impressed. It's versatile, efficient, and simply fantastic.`,
|
||||
profile: { avatar: '', name: 'Maria S', role: 'Marketing Specialist' }
|
||||
},
|
||||
{
|
||||
title: 'Outstanding choice!',
|
||||
ratings: 2,
|
||||
review: `This platform transformed the way we work. It's flexible, scalable, and adapts seamlessly to our evolving needs.`,
|
||||
profile: { avatar: '', name: 'James L.', role: 'IT Professional' }
|
||||
},
|
||||
{
|
||||
title: 'A must-consider!',
|
||||
ratings: 3,
|
||||
review: `As a tech enthusiast, I appreciate the innovation behind this platform. It's modern, sleek, and delivers on its promises.`,
|
||||
profile: { avatar: '', name: 'Kevin R.', role: 'Software Developer' }
|
||||
},
|
||||
{
|
||||
title: 'Highly recommended!',
|
||||
ratings: 5,
|
||||
review: `I've used many platforms in my career, and this one is a standout. The functionality is unmatched, making it a joy to work with.`,
|
||||
profile: { avatar: '', name: 'Jessica W.', role: 'UX/UI Designer' }
|
||||
},
|
||||
{
|
||||
title: 'Exceptional suggestion!',
|
||||
ratings: 1,
|
||||
review: `Our team's productivity soared after adopting this platform. It's a reliable solution that brings tangible results.`,
|
||||
profile: { avatar: '', name: 'Eric H.', role: 'Operations Manager' }
|
||||
},
|
||||
{
|
||||
title: 'Superbly recommended!',
|
||||
ratings: 3,
|
||||
review: 'What I love most is the seamless integration with other tools. It streamlines our workflow and saves us valuable time.',
|
||||
profile: { avatar: '', name: 'Brian C.', role: 'Content Creator' }
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
/*************************** BLOCK - TESTIMONIAL 10 ***************************/
|
||||
|
||||
export default function BlockTestimonial10() {
|
||||
return <Testimonial10 {...data} />;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
'use client';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
// @project
|
||||
import ThemeProviders from '@/components/ThemeProvider';
|
||||
|
||||
/*************************** LAYOUT - COMMON ***************************/
|
||||
|
||||
export default function CommonLayout({ children }) {
|
||||
return <ThemeProviders>{children}</ThemeProviders>;
|
||||
}
|
||||
|
||||
CommonLayout.propTypes = { children: PropTypes.any };
|
||||
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const About = dynamic(() => import('@/views/sections/About'));
|
||||
|
||||
/*************************** METADATA - ABOUT ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.about, openGraph: { ...SEO_CONTENT.about, url: PAGE_PATH.about } };
|
||||
|
||||
/*************************** PAGE - ABOUT ***************************/
|
||||
|
||||
export default function AboutPage() {
|
||||
return <About />;
|
||||
}
|
||||
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const ForgotPassword = dynamic(() => import('@/views/sections/ForgotPassword'));
|
||||
|
||||
/*************************** METADATA - FORGOT PASSWORD ***************************/
|
||||
|
||||
export const metadata = {
|
||||
...SEO_CONTENT.forgotPassword,
|
||||
openGraph: { ...SEO_CONTENT.forgotPassword, url: PAGE_PATH.forgotPassword }
|
||||
};
|
||||
|
||||
/*************************** PAGE - FORGOT PASSWORD ***************************/
|
||||
|
||||
export default function ForgotPasswordPage() {
|
||||
return <ForgotPassword />;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const Login = dynamic(() => import('@/views/sections/Login'));
|
||||
|
||||
/*************************** METADATA - LOGIN ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.login, openGraph: { ...SEO_CONTENT.login, url: PAGE_PATH.login } };
|
||||
|
||||
/*************************** PAGE - LOGIN ***************************/
|
||||
|
||||
export default function LoginPage() {
|
||||
return <Login />;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const NewPassword = dynamic(() => import('@/views/sections/NewPassword'));
|
||||
|
||||
/*************************** METADATA - NEW PASSWORD ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.newPassword, openGraph: { ...SEO_CONTENT.newPassword, url: PAGE_PATH.newPassword } };
|
||||
|
||||
/*************************** PAGE - NEW PASSWORD ***************************/
|
||||
|
||||
export default function NewPasswordPage() {
|
||||
return <NewPassword />;
|
||||
}
|
||||
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const OtpVerification = dynamic(() => import('@/views/sections/OtpVerification'));
|
||||
|
||||
/*************************** METADATA - OTP VERIFICATION ***************************/
|
||||
|
||||
export const metadata = {
|
||||
...SEO_CONTENT.otpVerification,
|
||||
openGraph: { ...SEO_CONTENT.otpVerification, url: PAGE_PATH.otpVerification }
|
||||
};
|
||||
|
||||
/*************************** PAGE - OTP VERIFICATION ***************************/
|
||||
|
||||
export default function OtpVerificationPage() {
|
||||
return <OtpVerification />;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const Register = dynamic(() => import('@/views/sections/Register'));
|
||||
|
||||
/*************************** METADATA - REGISTER ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.register, openGraph: { ...SEO_CONTENT.register, url: PAGE_PATH.register } };
|
||||
|
||||
/*************************** PAGE - REGISTER ***************************/
|
||||
|
||||
export default function RegisterPage() {
|
||||
return <Register />;
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// @next
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const BlogDetails = dynamic(() => import('@/views/sections/BlogDetails'));
|
||||
|
||||
/*************************** METADATA - BLOG DETAILS ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.blogDetails, openGraph: { ...SEO_CONTENT.blogDetails, url: PAGE_PATH.blogDetails } };
|
||||
|
||||
/*************************** PAGE - BLOG DETAILS ***************************/
|
||||
|
||||
export default function BlogDetailsPage() {
|
||||
return <BlogDetails />;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const Blog = dynamic(() => import('@/views/sections/Blog'));
|
||||
|
||||
/*************************** METADATA - BLOG ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.blog, openGraph: { ...SEO_CONTENT.blog, url: PAGE_PATH.blog } };
|
||||
|
||||
/*************************** PAGE - BLOG ***************************/
|
||||
|
||||
export default function BlogPage() {
|
||||
return <Blog />;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const Clientele = dynamic(() => import('@/views/sections/Clientele'));
|
||||
|
||||
/*************************** METADATA - CLIENTELE ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.clientele, openGraph: { ...SEO_CONTENT.clientele, url: PAGE_PATH.clientele } };
|
||||
|
||||
/*************************** PAGE - CLIENTELE ***************************/
|
||||
|
||||
export default function ClientelePage() {
|
||||
return <Clientele />;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const Color = dynamic(() => import('@/views/sections/Color'));
|
||||
|
||||
/*************************** METADATA - COLOR ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.color, openGraph: { ...SEO_CONTENT.color, url: PAGE_PATH.color } };
|
||||
|
||||
/*************************** PAGE - COLOR ***************************/
|
||||
|
||||
export default function ColorPage() {
|
||||
return <Color />;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const ComingSoon = dynamic(() => import('@/views/sections/ComingSoon'));
|
||||
|
||||
/*************************** METADATA - COMING SOON ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.comingSoon, openGraph: { ...SEO_CONTENT.comingSoon, url: PAGE_PATH.comingSoon } };
|
||||
|
||||
/*************************** PAGE - COMING SOON ***************************/
|
||||
|
||||
export default function ComingSoonPage() {
|
||||
return <ComingSoon />;
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const ContactUs = dynamic(() => import('@/views/sections/ContactUs'));
|
||||
|
||||
/*************************** METADATA - CONTACT US ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.contactUs };
|
||||
|
||||
/*************************** PAGE - CONTACT US ***************************/
|
||||
|
||||
export default function ContactUsPage() {
|
||||
return <ContactUs />;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const Cookie = dynamic(() => import('@/views/sections/Cookie'));
|
||||
|
||||
/*************************** METADATA - COOKIE ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.cookie, openGraph: { ...SEO_CONTENT.cookie, url: PAGE_PATH.cookie } };
|
||||
|
||||
/*************************** PAGE - COOKIE ***************************/
|
||||
|
||||
export default function CookiePage() {
|
||||
return <Cookie />;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const Cta = dynamic(() => import('@/views/sections/Cta'));
|
||||
|
||||
/*************************** METADATA - CALL TO ACTION ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.cta, openGraph: { ...SEO_CONTENT.cta, url: PAGE_PATH.cta } };
|
||||
|
||||
/*************************** PAGE - CALL TO ACTION ***************************/
|
||||
|
||||
export default function CtaPage() {
|
||||
return <Cta />;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const EarlyAccess = dynamic(() => import('@/views/sections/EarlyAccess'));
|
||||
|
||||
/*************************** METADATA - EARLY ACCCESS ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.earlyAccess, openGraph: { ...SEO_CONTENT.earlyAccess, url: PAGE_PATH.earlyAccess } };
|
||||
|
||||
/*************************** PAGE - EARLY ACCCESS ***************************/
|
||||
|
||||
export default function EarlyAccessPage() {
|
||||
return <EarlyAccess />;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const Error404 = dynamic(() => import('@/views/sections/Error404'));
|
||||
|
||||
/*************************** METADATA - ERROR 404 ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.error404, openGraph: { ...SEO_CONTENT.error404, url: PAGE_PATH.error404 } };
|
||||
|
||||
/*************************** PAGE - ERROR 404 ***************************/
|
||||
|
||||
export default function Error404Page() {
|
||||
return <Error404 />;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const Error500 = dynamic(() => import('@/views/sections/Error500'));
|
||||
|
||||
/*************************** METADATA - ERROR 500 ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.error500, openGraph: { ...SEO_CONTENT.error500, url: PAGE_PATH.error500 } };
|
||||
|
||||
/*************************** PAGE - ERROR 500 ***************************/
|
||||
|
||||
export default function Error500Page() {
|
||||
return <Error500 />;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const Faq = dynamic(() => import('@/views/sections/Faq'));
|
||||
|
||||
/*************************** METADATA - FAQ ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.faq, openGraph: { ...SEO_CONTENT.faq, url: PAGE_PATH.faq } };
|
||||
|
||||
/*************************** PAGE - FAQ ***************************/
|
||||
|
||||
export default function FaqPage() {
|
||||
return <Faq />;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const Feature = dynamic(() => import('@/views/sections/Feature'));
|
||||
|
||||
/*************************** METADATA - FEATURE ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.feature, openGraph: { ...SEO_CONTENT.feature, url: PAGE_PATH.feature } };
|
||||
|
||||
/*************************** PAGE - FEATURE ***************************/
|
||||
|
||||
export default function FeaturePage() {
|
||||
return <Feature />;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const Footer = dynamic(() => import('@/views/sections/Footer'));
|
||||
|
||||
/*************************** METADATA - FOOTER ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.footer, openGraph: { ...SEO_CONTENT.footer, url: PAGE_PATH.footer } };
|
||||
|
||||
/*************************** PAGE - FOOTER ***************************/
|
||||
|
||||
export default function FooterPage() {
|
||||
return <Footer />;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const Gallery = dynamic(() => import('@/views/sections/Gallery'));
|
||||
|
||||
/*************************** METADATA - GALLERY ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.gallery, openGraph: { ...SEO_CONTENT.gallery, url: PAGE_PATH.gallery } };
|
||||
|
||||
/*************************** PAGE - GALLERY ***************************/
|
||||
|
||||
export default function GalleryPage() {
|
||||
return <Gallery />;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const Hero = dynamic(() => import('@/views/sections/Hero'));
|
||||
|
||||
/*************************** METADATA - HERO ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.hero, openGraph: { ...SEO_CONTENT.hero, url: PAGE_PATH.hero } };
|
||||
|
||||
/*************************** PAGE - HERO ***************************/
|
||||
|
||||
export default function HeroPage() {
|
||||
return <Hero />;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const Icon = dynamic(() => import('@/views/sections/Icon'));
|
||||
|
||||
/*************************** METADATA - ICON ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.icon, openGraph: { ...SEO_CONTENT.icon, url: PAGE_PATH.icon } };
|
||||
|
||||
/*************************** PAGE - ICON ***************************/
|
||||
|
||||
export default function IconPage() {
|
||||
return <Icon />;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const Integration = dynamic(() => import('@/views/sections/Integration'));
|
||||
|
||||
/*************************** METADATA - INTEGRATION ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.integration, openGraph: { ...SEO_CONTENT.integration, url: PAGE_PATH.integration } };
|
||||
|
||||
/*************************** PAGE - INTEGRATION ***************************/
|
||||
|
||||
export default function IntegrationPage() {
|
||||
return <Integration />;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
'use client';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
// @next
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
const ScrollFab = dynamic(() => import('@/components/ScrollFab'));
|
||||
const SectionsLayout = dynamic(() => import('@/views/sections/layout'));
|
||||
|
||||
/*************************** LAYOUT - SECTIONS ***************************/
|
||||
|
||||
export default function Sections({ children }) {
|
||||
|
||||
return (
|
||||
<SectionsLayout>
|
||||
<>
|
||||
{children}
|
||||
|
||||
{/* scroll to top section */}
|
||||
<ScrollFab />
|
||||
</>
|
||||
</SectionsLayout>
|
||||
);
|
||||
}
|
||||
|
||||
Sections.propTypes = { children: PropTypes.any };
|
||||
@@ -0,0 +1,8 @@
|
||||
// @project
|
||||
import Loader from '@/components/Loader';
|
||||
|
||||
/*************************** LOADER ***************************/
|
||||
|
||||
export default function Loading() {
|
||||
return <Loader />;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const MegaMenu = dynamic(() => import('@/views/sections/MegaMenu'));
|
||||
|
||||
/*************************** METADATA - MEGA MENU ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.megaMenu, openGraph: { ...SEO_CONTENT.megaMenu, url: PAGE_PATH.megaMenu } };
|
||||
|
||||
/*************************** PAGE - MEGA MENU ***************************/
|
||||
|
||||
export default function MegaMenuPage() {
|
||||
return <MegaMenu />;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const Metrics = dynamic(() => import('@/views/sections/metrics'));
|
||||
|
||||
/*************************** METADATA - METRICS ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.metrics, openGraph: { ...SEO_CONTENT.metrics, url: PAGE_PATH.metrics } };
|
||||
|
||||
/*************************** PAGE - METRICS ***************************/
|
||||
|
||||
export default function MetricsPage() {
|
||||
return <Metrics />;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const Navbar = dynamic(() => import('@/views/sections/Navbar'));
|
||||
|
||||
/*************************** METADATA - NAVBAR ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.navbar, openGraph: { ...SEO_CONTENT.navbar, url: PAGE_PATH.navbar } };
|
||||
|
||||
/*************************** PAGE - NAVBAR ***************************/
|
||||
|
||||
export default function NavbarPage() {
|
||||
return <Navbar />;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const OnBoard = dynamic(() => import('@/views/sections/OnBoard'));
|
||||
|
||||
/*************************** METADATA - ONBOARD ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.onBoard, openGraph: { ...SEO_CONTENT.onBoard, url: PAGE_PATH.onboard } };
|
||||
|
||||
/*************************** PAGE - ONBOARD ***************************/
|
||||
|
||||
export default function OnBoardPage() {
|
||||
return <OnBoard />;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const Other = dynamic(() => import('@/views/sections/Other'));
|
||||
|
||||
/*************************** METADATA - OTHER ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.other, openGraph: { ...SEO_CONTENT.other, url: PAGE_PATH.other } };
|
||||
|
||||
/*************************** PAGE - OTHER ***************************/
|
||||
|
||||
export default function OtherPage() {
|
||||
return <Other />;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const Sections = dynamic(() => import('@/views/sections'));
|
||||
|
||||
/*************************** METADATA - SECTIONS ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.section };
|
||||
|
||||
/*************************** PAGE - SECTIONS ***************************/
|
||||
|
||||
export default function SectionsPage() {
|
||||
return <Sections />;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const Pricing = dynamic(() => import('@/views/sections/Pricing'));
|
||||
|
||||
/*************************** METADATA - PRICING ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.pricing, openGraph: { ...SEO_CONTENT.pricing, url: PAGE_PATH.pricing } };
|
||||
|
||||
/*************************** PAGE - PRICING ***************************/
|
||||
|
||||
export default function PricingPage() {
|
||||
return <Pricing />;
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const PrivacyPolicy = dynamic(() => import('@/views/sections/PrivacyPolicy'));
|
||||
|
||||
/*************************** METADATA - PRIVACY POLICY ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.privacyPolicy };
|
||||
|
||||
/*************************** PAGE - PRIVACY POLICY ***************************/
|
||||
|
||||
export default function PrivacyPolicyPage() {
|
||||
return <PrivacyPolicy />;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const ProPages = dynamic(() => import('@/views/sections/ProPage'));
|
||||
|
||||
/*************************** METADATA - PRO PAGE ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.pricing, openGraph: { ...SEO_CONTENT.pricing, url: PAGE_PATH.pricing } };
|
||||
|
||||
/*************************** PAGE - PRICING ***************************/
|
||||
|
||||
export default function ProPage() {
|
||||
return <ProPages />;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const Process = dynamic(() => import('@/views/sections/Process'));
|
||||
|
||||
/*************************** METADATA - PROCESS ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.process, openGraph: { ...SEO_CONTENT.process, url: PAGE_PATH.process } };
|
||||
|
||||
/*************************** PAGE - PROCESS ***************************/
|
||||
|
||||
export default function ProcessPage() {
|
||||
return <Process />;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const SmallHero = dynamic(() => import('@/views/sections/SmallHero'));
|
||||
|
||||
/*************************** METADATA - SMALL HERO ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.smallHero, openGraph: { ...SEO_CONTENT.smallHero, url: PAGE_PATH.smallHero } };
|
||||
|
||||
/*************************** PAGE - SMALL HERO ***************************/
|
||||
|
||||
export default function SmallHeroPage() {
|
||||
return <SmallHero />;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const Team = dynamic(() => import('@/views/sections/Team'));
|
||||
|
||||
/*************************** METADATA - TEAM ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.team, openGraph: { ...SEO_CONTENT.team, url: PAGE_PATH.team } };
|
||||
|
||||
/*************************** PAGE - TEAM ***************************/
|
||||
|
||||
export default function TeamPage() {
|
||||
return <Team />;
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const TermsCondition = dynamic(() => import('@/views/sections/TermsCondition'));
|
||||
|
||||
/*************************** METADATA - TERMS CONDITION ***************************/
|
||||
|
||||
export const metadata = {
|
||||
...SEO_CONTENT.termsCondition,
|
||||
openGraph: { ...SEO_CONTENT.termsCondition, url: PAGE_PATH.termsCondition }
|
||||
};
|
||||
|
||||
/*************************** PAGE - TERMS CONDITION ***************************/
|
||||
|
||||
export default function TermsConditionPage() {
|
||||
return <TermsCondition />;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const Testimonial = dynamic(() => import('@/views/sections/Testimonial'));
|
||||
|
||||
/*************************** METADATA - TESTIMONIAL ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.testimonial, openGraph: { ...SEO_CONTENT.testimonial, url: PAGE_PATH.testimonial } };
|
||||
|
||||
/*************************** PAGE - TESTIMONIAL ***************************/
|
||||
|
||||
export default function TestimonialPage() {
|
||||
return <Testimonial />;
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
import TopOffer from '@/views/sections/TopOffer';
|
||||
|
||||
/*************************** METADATA - TOP OFFER ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.topOffer, openGraph: { ...SEO_CONTENT.topOffer, url: PAGE_PATH.topOffer } };
|
||||
|
||||
/*************************** PAGE - TOP OFFER ***************************/
|
||||
|
||||
export default function TopOfferPage() {
|
||||
return <TopOffer />;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const Typography = dynamic(() => import('@/views/sections/Typography'));
|
||||
|
||||
/*************************** METADATA - TYPOGRAPHY ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.typography, openGraph: { ...SEO_CONTENT.typography, url: PAGE_PATH.typography } };
|
||||
|
||||
/*************************** PAGE - TYPOGRAPHY ***************************/
|
||||
|
||||
export default function TypographyPage() {
|
||||
return <Typography />;
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const UnderMaintenance = dynamic(() => import('@/views/sections/UnderMaintenance'));
|
||||
|
||||
/*************************** METADATA - UNDER MAINTENANCE ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.underMaintenance };
|
||||
|
||||
/*************************** PAGE - UNDER MAINTENANCE ***************************/
|
||||
|
||||
export default function UnderMaintenancePage() {
|
||||
return <UnderMaintenance />;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const Contact = dynamic(() => import('@/views/landings/default/contact'));
|
||||
|
||||
/*************************** METADATA - CONTACT ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.contactUs };
|
||||
|
||||
/*************************** PAGE - CONTACT ***************************/
|
||||
|
||||
export default function ContactPage() {
|
||||
return <Contact />;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import PropTypes from 'prop-types';
|
||||
// @next
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
const ScrollFab = dynamic(() => import('@/components/ScrollFab'));
|
||||
// const ThemeAI = dynamic(() => import('@/views/landings/ai/theme'));
|
||||
const MainLayout = dynamic(() => import('@/views/landings/default/layout'));
|
||||
|
||||
/*************************** LAYOUT - AI ***************************/
|
||||
|
||||
export default function AI({ children }) {
|
||||
return (
|
||||
// <ThemeAI>
|
||||
<MainLayout>
|
||||
<>
|
||||
{children}
|
||||
|
||||
{/* scroll to top section */}
|
||||
<ScrollFab />
|
||||
</>
|
||||
</MainLayout>
|
||||
// </ThemeAI>
|
||||
);
|
||||
}
|
||||
|
||||
AI.propTypes = { children: PropTypes.any };
|
||||
@@ -0,0 +1,19 @@
|
||||
// @next
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
const ScrollFab = dynamic(() => import('@/components/ScrollFab'));
|
||||
const Main = dynamic(() => import('@/views/landings/default'));
|
||||
|
||||
/*************************** PAGE - ROOT ***************************/
|
||||
|
||||
export default function HomePage() {
|
||||
return (
|
||||
<>
|
||||
<Main />
|
||||
|
||||
{/* scroll to top section */}
|
||||
<ScrollFab />
|
||||
</>
|
||||
);
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const PrivacyPolicy = dynamic(() => import('@/views/landings/default/privacy-policy'));
|
||||
|
||||
/*************************** METADATA - PRIVACY POLICY ***************************/
|
||||
|
||||
export const metadata = { ...SEO_CONTENT.privacyPolicy };
|
||||
|
||||
/*************************** PAGE - PRIVACY POLICY ***************************/
|
||||
|
||||
export default function PrivacyPolicyPage() {
|
||||
return <PrivacyPolicy />;
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// @project
|
||||
import { PAGE_PATH } from '@/path';
|
||||
import { SEO_CONTENT } from '@/metadata';
|
||||
|
||||
const TermsCondition = dynamic(() => import('@/views/landings/default/terms-condition'));
|
||||
|
||||
/*************************** METADATA - TERMS CONDITION ***************************/
|
||||
|
||||
export const metadata = {
|
||||
...SEO_CONTENT.termsCondition,
|
||||
openGraph: { ...SEO_CONTENT.termsCondition, url: PAGE_PATH.termsConditionPage }
|
||||
};
|
||||
|
||||
/*************************** PAGE - TERMS CONDITION ***************************/
|
||||
|
||||
export default function TermsConditionPage() {
|
||||
return <TermsCondition />;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
'use client';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
// @project
|
||||
import Loader from '@/components/Loader';
|
||||
import ThemeProvider from '@/components/ThemeProvider';
|
||||
import { ConfigProvider } from '@/contexts/ConfigContext';
|
||||
|
||||
/*************************** COMMON - CONFIG, THEME ***************************/
|
||||
|
||||
export default function ProviderWrapper({ children }) {
|
||||
const [loader, setLoader] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
setLoader(false);
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* A loader is needed here to initialize the configuration from localStorage and set the default theme.
|
||||
* Without a loader,
|
||||
* the theme palette and fontFamily don't match, resulting in an error like:
|
||||
* "Warning: Prop className did not match".
|
||||
*/
|
||||
|
||||
return (
|
||||
<ConfigProvider>
|
||||
<ThemeProvider>
|
||||
<main>{loader ? <Loader /> : children}</main>
|
||||
</ThemeProvider>
|
||||
</ConfigProvider>
|
||||
);
|
||||
}
|
||||
|
||||
ProviderWrapper.propTypes = { children: PropTypes.any };
|
||||
@@ -0,0 +1,38 @@
|
||||
// @next
|
||||
import { NextResponse } from 'next/server';
|
||||
|
||||
// @third-party
|
||||
import axios from 'axios';
|
||||
|
||||
/*************************** API - MAILERLITE SUBSCRIBE ***************************/
|
||||
|
||||
// POST handler for /api/subscribe
|
||||
export async function POST(request) {
|
||||
try {
|
||||
const { email } = await request.json();
|
||||
if (!email) {
|
||||
return NextResponse.json({ error: 'Email is required' }, { status: 400 });
|
||||
}
|
||||
// Example: MailerLite API endpoint (replace with your actual MailerLite API URL)
|
||||
const mailerLiteUrl = `${process.env.MAILERLITE_API_ENDPOINT}/subscribers`;
|
||||
|
||||
// Make the Axios POST request to MailerLite (replace 'YOUR_API_KEY' with your actual API key)
|
||||
await axios.post(
|
||||
mailerLiteUrl,
|
||||
{ email, groups: process.env.MAILERLITE_GROUP?.trim().replaceAll(' ', '').split(',') },
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${process.env.MAILERLITE_API_KEY}` // Authorization header with MailerLite API key
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Handle successful response
|
||||
return NextResponse.json({ message: 'Subscribed successfully!' }, { status: 200 });
|
||||
} catch (error) {
|
||||
// Handle failure response
|
||||
console.error('Error subscribing:', error);
|
||||
return NextResponse.json({ error }, { status: 500 });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
'use client';
|
||||
|
||||
// @project
|
||||
import { Error500Page } from '@/blocks/maintenance';
|
||||
import ThemeProviders from '@/components/ThemeProvider';
|
||||
|
||||
/*************************** ERROR 500 - DATA ***************************/
|
||||
|
||||
const data = {
|
||||
primaryBtn: { children: 'Back to Home Page' },
|
||||
heading: 'Please try again later or feel free to contact us if the problem persists.'
|
||||
};
|
||||
|
||||
/*************************** ERROR - 500 ***************************/
|
||||
|
||||
export default function InternalServerError() {
|
||||
return (
|
||||
<ThemeProviders>
|
||||
<Error500Page {...data} />
|
||||
</ThemeProviders>
|
||||
);
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 9.5 KiB |
@@ -0,0 +1,18 @@
|
||||
/* slick-carousel slider */
|
||||
@import 'slick-carousel/slick/slick.css';
|
||||
@import 'slick-carousel/slick/slick-theme.css';
|
||||
|
||||
/* scrollbar */
|
||||
@import '../styles/scrollbar.css';
|
||||
|
||||
/* to remove default browser focus-visible */
|
||||
body * {
|
||||
&:focus-visible,
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import Script from 'next/script';
|
||||
|
||||
// @style
|
||||
import './globals.css';
|
||||
|
||||
// @mui
|
||||
import { AppRouterCacheProvider } from '@mui/material-nextjs/v15-appRouter';
|
||||
|
||||
// @project
|
||||
import ProviderWrapper from './ProviderWrapper';
|
||||
import { mainMetadata } from '@/metadata';
|
||||
|
||||
const gaId = process.env.NEXT_PUBLIC_ANALYTICS_ID || '';
|
||||
|
||||
/*************************** METADATA - MAIN ***************************/
|
||||
|
||||
export const metadata = { ...mainMetadata };
|
||||
|
||||
/*************************** LAYOUT - MAIN ***************************/
|
||||
|
||||
// Root layout component that wraps the entire application
|
||||
export default function RootLayout({ children }) {
|
||||
return (
|
||||
<html lang="en" suppressHydrationWarning>
|
||||
<head>
|
||||
{/* Preconnect and DNS Prefetch */}
|
||||
<link rel="preconnect" href="https://www.googletagmanager.com" />
|
||||
<link rel="dns-prefetch" href="https://www.googletagmanager.com" />
|
||||
<script src="https://fomo.codedthemes.com/pixel/gkPddwTcjNYydfr7v3FcZuToUb9ZAevo" defer data-nscript="lazyOnload"></script>
|
||||
</head>
|
||||
<body>
|
||||
<AppRouterCacheProvider options={{ enableCssLayer: true }}>
|
||||
<ProviderWrapper>{children}</ProviderWrapper>
|
||||
</AppRouterCacheProvider>
|
||||
{gaId && <Script strategy="lazyOnload" src={`https://www.googletagmanager.com/gtag/js?id=${gaId}`} />}
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
||||
RootLayout.propTypes = { children: PropTypes.any };
|
||||
@@ -0,0 +1,13 @@
|
||||
// @project
|
||||
import Loader from '@/components/Loader';
|
||||
import ThemeProviders from '@/components/ThemeProvider';
|
||||
|
||||
/*************************** LOADER ***************************/
|
||||
|
||||
export default function Loading() {
|
||||
return (
|
||||
<ThemeProviders>
|
||||
<Loader />
|
||||
</ThemeProviders>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
'use client';
|
||||
|
||||
// @project
|
||||
import { Error404Page } from '@/blocks/maintenance';
|
||||
import ThemeProviders from '@/components/ThemeProvider';
|
||||
|
||||
/*************************** ERROR 404 - DATA ***************************/
|
||||
|
||||
const data = {
|
||||
primaryBtn: { children: 'Back to Home Page', onClick: () => window.history.back() },
|
||||
heading: `Looks like you've taken a wrong turn. Lets get you back on track!`
|
||||
};
|
||||
|
||||
/*************************** ERROR - 404 ***************************/
|
||||
|
||||
export default function notfound() {
|
||||
return (
|
||||
<ThemeProviders>
|
||||
<Error404Page {...data} />
|
||||
</ThemeProviders>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
'use client';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
// @mui
|
||||
import Divider from '@mui/material/Divider';
|
||||
import Grid from '@mui/material/Grid';
|
||||
import List from '@mui/material/List';
|
||||
import ListItemButton from '@mui/material/ListItemButton';
|
||||
import ListItemText from '@mui/material/ListItemText';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import Typography from '@mui/material/Typography';
|
||||
|
||||
// @project
|
||||
import ContainerWrapper from '@/components/ContainerWrapper';
|
||||
import { SECTION_COMMON_PY } from '@/utils/constant';
|
||||
|
||||
// Helper functions for scrollspy
|
||||
const clamp = (value) => Math.max(0, value);
|
||||
const isBetween = (value, floor, ceil) => value >= floor && value <= ceil;
|
||||
|
||||
/*************************** HOOKS - SCROLLSPY ***************************/
|
||||
|
||||
function useScrollspy(ids, offset = 0) {
|
||||
const [activeId, setActiveId] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
const listener = () => {
|
||||
const scroll = window.scrollY;
|
||||
|
||||
const position = ids
|
||||
.map((id) => {
|
||||
const element = document.getElementById(id);
|
||||
if (!element) return { id, top: -1, bottom: -1 };
|
||||
|
||||
const rect = element.getBoundingClientRect();
|
||||
const top = clamp(rect.top + scroll - offset);
|
||||
const bottom = clamp(rect.bottom + scroll - offset);
|
||||
|
||||
return { id, top, bottom };
|
||||
})
|
||||
.find(({ top, bottom }) => isBetween(scroll, top, bottom));
|
||||
|
||||
setActiveId(position?.id || '');
|
||||
};
|
||||
|
||||
window.addEventListener('scroll', listener);
|
||||
window.addEventListener('resize', listener);
|
||||
listener(); // Initial call to set the activeId
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('scroll', listener);
|
||||
window.removeEventListener('resize', listener);
|
||||
};
|
||||
}, [ids, offset]);
|
||||
|
||||
return activeId;
|
||||
}
|
||||
|
||||
/*************************** TERMS CONDITION - DATA ***************************/
|
||||
|
||||
const menuItems = [
|
||||
{
|
||||
id: 'acceptance-of-terms',
|
||||
heading: 'Acceptance of terms',
|
||||
caption:
|
||||
'By accessing and using this website, you agree to be bound by these Terms and Conditions of Use. If you do not agree with any part of these terms, you must not use the website. shares information about you when you use our website or services. By accessing or using our website, you consent to the practices described in this policy.'
|
||||
},
|
||||
{
|
||||
id: 'changes-to-terms',
|
||||
heading: 'Changes to terms',
|
||||
caption:
|
||||
'We reserve the right to modify or replace these terms at our sole discretion. It is your responsibility to check these terms periodically for changes. Your continued use of the website after the posting of any changes constitutes acceptance of those changes.'
|
||||
},
|
||||
{
|
||||
id: 'user-conduct',
|
||||
heading: 'User conduct',
|
||||
caption:
|
||||
'You agree to use this website only for lawful purposes and in a manner consistent with all applicable local, national, and international laws and regulations.'
|
||||
},
|
||||
{
|
||||
id: 'intellectual-property',
|
||||
heading: 'Intellectual property',
|
||||
caption:
|
||||
'All content on this website, including but not limited to text, graphics, logos, images, audio clips, video clips, digital downloads, and data compilations, is the property of [Your Company Name] or its content suppliers and protected by international copyright laws.'
|
||||
},
|
||||
{
|
||||
id: 'privacy-policy',
|
||||
heading: 'Privacy policy',
|
||||
caption:
|
||||
'We do not sell, trade, or otherwise transfer your personal information to third parties. We may share information with trusted service providers who assist us in operating our website, conducting our business, or servicing you.'
|
||||
},
|
||||
{
|
||||
id: 'user-generated-content',
|
||||
heading: 'User-generated content',
|
||||
caption:
|
||||
'If you submit any material to this website, you grant [Your Company Name] a perpetual, royalty-free, worldwide license to use, reproduce, modify, adapt, publish, translate, create derivative works from, distribute, and display such material.'
|
||||
},
|
||||
{
|
||||
id: 'limitation-of-liability',
|
||||
heading: 'Limitation of liability',
|
||||
caption:
|
||||
'In no event shall [Your Company Name] or its affiliates be liable for any direct, indirect, incidental, special, or consequential damages resulting from the use or inability to use this website.'
|
||||
},
|
||||
{
|
||||
id: 'indemnity',
|
||||
heading: 'Indemnity',
|
||||
caption:
|
||||
"You agree to indemnify and hold harmless [Your Company Name] and its affiliates from any claims, actions, demands, damages, liabilities, costs, or expenses, including reasonable attorneys' fees, arising out of or related to your use of the website or any violation of these terms."
|
||||
},
|
||||
{
|
||||
id: 'governing-law',
|
||||
heading: 'Governing law',
|
||||
caption:
|
||||
'These terms are governed by and construed in accordance with the laws of [Your Country/State], without regard to its conflict of law principles.'
|
||||
}
|
||||
];
|
||||
|
||||
/*************************** SECTIONS - TERMS CONDITION ***************************/
|
||||
|
||||
/**
|
||||
*
|
||||
* Demos:
|
||||
* - [Terms Condition](https://www.saasable.io/sections/terms-condition)
|
||||
*/
|
||||
|
||||
export default function TermsConditionPage() {
|
||||
const ids = menuItems.map((item) => item.id);
|
||||
|
||||
// Adjust offset as per header height
|
||||
const activeId = useScrollspy(ids, 60);
|
||||
const [selectedID, setSelectedID] = useState(activeId);
|
||||
|
||||
useEffect(() => {
|
||||
if (activeId) {
|
||||
setSelectedID(activeId);
|
||||
}
|
||||
}, [activeId]);
|
||||
|
||||
return (
|
||||
<ContainerWrapper sx={{ pb: SECTION_COMMON_PY }}>
|
||||
<Grid container spacing={{ xs: 2, md: 3 }}>
|
||||
<Grid size={{ xs: 12, sm: 4, md: 3 }}>
|
||||
<List component="div" sx={{ position: 'sticky', top: 20 }} disablePadding>
|
||||
{menuItems.map((item, index) => (
|
||||
<ListItemButton
|
||||
key={index}
|
||||
href={`#${item.id}`}
|
||||
sx={{
|
||||
py: 1.25,
|
||||
px: 1.5,
|
||||
borderRadius: 3,
|
||||
mb: 0.75,
|
||||
...(selectedID === item.id && { color: 'primary.main', bgcolor: 'grey.100' }),
|
||||
'&:hover': { bgcolor: 'grey.50' }
|
||||
}}
|
||||
onClick={() => setSelectedID(item.id)}
|
||||
>
|
||||
<ListItemText primary={item.heading} sx={{ my: 0 }} slotProps={{ primary: { variant: 'subtitle1' } }} />
|
||||
</ListItemButton>
|
||||
))}
|
||||
</List>
|
||||
<Divider sx={{ display: { xs: 'block', sm: 'none' } }} />
|
||||
</Grid>
|
||||
<Grid size={{ xs: 12, sm: 8, md: 9 }}>
|
||||
{menuItems.map((item, index) => (
|
||||
<Stack
|
||||
key={index}
|
||||
id={item.id}
|
||||
sx={{ py: { xs: 1, sm: 1.5, md: 3 }, px: { md: 3 }, gap: 1, '&:first-of-type': { pt: { sm: 0 } } }}
|
||||
>
|
||||
<Typography variant="h4">{item.heading}</Typography>
|
||||
<Typography variant="body1" sx={{ color: 'text.secondary' }}>
|
||||
{item.caption}
|
||||
</Typography>
|
||||
</Stack>
|
||||
))}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</ContainerWrapper>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
import PropTypes from 'prop-types';
|
||||
// @mui
|
||||
import Grid from '@mui/material/Grid';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import Box from '@mui/material/Box';
|
||||
|
||||
// @project
|
||||
import { GraphicsCard } from '@/components/cards';
|
||||
import Typeset from '@/components/Typeset';
|
||||
|
||||
/*************************** TYPOGRAPHY - DATA ***************************/
|
||||
|
||||
const typographyData = [
|
||||
{
|
||||
heading: 'Headings',
|
||||
items: [
|
||||
{
|
||||
title: 'Heading 01',
|
||||
sizeValue: { desktop: '57px', tablet: '45px', mobile: '36px' },
|
||||
lineHeight: { desktop: '64px', tablet: '52px', mobile: '44px' },
|
||||
letterSpacing: { desktop: '-0.25px', tablet: '0px', mobile: '0px' },
|
||||
variant: 'h1',
|
||||
label: 'h1 - Heading Large',
|
||||
fontWeight: 'Regular (400)'
|
||||
},
|
||||
{
|
||||
title: 'Heading 02',
|
||||
sizeValue: { desktop: '45px', tablet: '36px', mobile: '24px' },
|
||||
lineHeight: { desktop: '52px', tablet: '44px', mobile: '32px' },
|
||||
letterSpacing: { desktop: '0px', tablet: '0px', mobile: '0px' },
|
||||
variant: 'h2',
|
||||
label: 'h2 - Heading Medium',
|
||||
fontWeight: 'Regular (400)'
|
||||
},
|
||||
{
|
||||
title: 'Heading 03',
|
||||
sizeValue: { desktop: '28px', tablet: '24px', mobile: '20px' },
|
||||
lineHeight: { desktop: '36px', tablet: '32px', mobile: '28px' },
|
||||
letterSpacing: { desktop: '0px', tablet: '0px', mobile: '0px' },
|
||||
variant: 'h3',
|
||||
label: 'h3 - Display Medium',
|
||||
fontWeight: 'Regular (400)'
|
||||
},
|
||||
{
|
||||
title: 'Heading 04',
|
||||
sizeValue: { desktop: '24px', tablet: '20px', mobile: '16px' },
|
||||
lineHeight: { desktop: '32px', tablet: '28px', mobile: '24px' },
|
||||
letterSpacing: { desktop: '0px', tablet: '0px', mobile: '0px' },
|
||||
variant: 'h4',
|
||||
label: 'h4 - Display Small',
|
||||
fontWeight: 'Regular (400)'
|
||||
},
|
||||
{
|
||||
title: 'Heading 05',
|
||||
sizeValue: { desktop: '22px', tablet: '16px', mobile: '16px' },
|
||||
lineHeight: { desktop: '28px', tablet: '24px', mobile: '24px' },
|
||||
letterSpacing: { desktop: '0px', tablet: '0.15px', mobile: '0.15px' },
|
||||
variant: 'h5',
|
||||
label: 'h5 - Label Large',
|
||||
fontWeight: 'Medium (500)'
|
||||
},
|
||||
{
|
||||
title: 'Heading 06',
|
||||
sizeValue: { desktop: '22px', tablet: '16px', mobile: '16px' },
|
||||
lineHeight: { desktop: '30px', tablet: '24px', mobile: '24px' },
|
||||
letterSpacing: { desktop: '0px', tablet: '0.5px', mobile: '0.5px' },
|
||||
variant: 'h6',
|
||||
label: 'h6 - Paragraph Large',
|
||||
fontWeight: 'Regular (400)'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
heading: 'Body / Paragraph',
|
||||
items: [
|
||||
{
|
||||
title: 'Body 01',
|
||||
sizeValue: { desktop: '16px', tablet: '14px', mobile: '14px' },
|
||||
lineHeight: { desktop: '24px', tablet: '20px', mobile: '20px' },
|
||||
letterSpacing: { desktop: '0.5px', tablet: '0.25px', mobile: '0.25px' },
|
||||
variant: 'body1',
|
||||
label: 'body1 - Paragraph Medium',
|
||||
fontWeight: 'Regular (400)'
|
||||
},
|
||||
{
|
||||
title: 'Body 02',
|
||||
sizeValue: { desktop: '14px', tablet: '12px', mobile: '12px' },
|
||||
lineHeight: { desktop: '20px', tablet: '18px', mobile: '18px' },
|
||||
letterSpacing: { desktop: '0.25px', tablet: '0.25px', mobile: '0.25px' },
|
||||
variant: 'body2',
|
||||
label: 'body2 - Paragraph Small',
|
||||
fontWeight: 'Regular (400)'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
heading: 'Subtitle',
|
||||
items: [
|
||||
{
|
||||
title: 'Subtitle 01',
|
||||
sizeValue: { desktop: '16px', tablet: '14px', mobile: '14px' },
|
||||
lineHeight: { desktop: '24px', tablet: '20px', mobile: '20px' },
|
||||
letterSpacing: { desktop: '0.15px', tablet: '0.1px', mobile: '0.1px' },
|
||||
variant: 'subtitle1',
|
||||
label: 'subtitle1 - Label Medium',
|
||||
fontWeight: 'Medium (500)'
|
||||
},
|
||||
{
|
||||
title: 'Subtitle 02',
|
||||
sizeValue: { desktop: '14px', tablet: '12px', mobile: '12px' },
|
||||
lineHeight: { desktop: '20px', tablet: '18px', mobile: '18px' },
|
||||
letterSpacing: { desktop: '0.1px', tablet: '0.1px', mobile: '0.1 px' },
|
||||
variant: 'subtitle2',
|
||||
label: 'subtitle2 - Label Small',
|
||||
fontWeight: 'Semibold (600)'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
heading: 'Caption',
|
||||
items: [
|
||||
{
|
||||
title: 'Caption',
|
||||
sizeValue: { desktop: '12px', tablet: '12px', mobile: '12px' },
|
||||
lineHeight: { desktop: '16px', tablet: '16px', mobile: '16px' },
|
||||
letterSpacing: { desktop: '0px', tablet: '0px', mobile: '0 px' },
|
||||
variant: 'caption',
|
||||
label: 'caption - Hyperlink Small',
|
||||
fontWeight: 'Semibold (600)'
|
||||
},
|
||||
{
|
||||
title: 'Caption 01',
|
||||
sizeValue: { desktop: '16px', tablet: '16px', mobile: '16px' },
|
||||
lineHeight: { desktop: '24px', tablet: '24px', mobile: '24px' },
|
||||
letterSpacing: { desktop: '0.5px', tablet: '0.5px', mobile: '0.5px' },
|
||||
variant: 'caption1',
|
||||
label: 'caption1 - Hyperlink Large',
|
||||
fontWeight: 'Regular (400)'
|
||||
},
|
||||
{
|
||||
title: 'Caption 02',
|
||||
sizeValue: { desktop: '14px', tablet: '14px', mobile: '14px' },
|
||||
lineHeight: { desktop: '20px', tablet: '20px', mobile: '20px' },
|
||||
letterSpacing: { desktop: '0.1px', tablet: '0.1 px', mobile: '0.1px' },
|
||||
variant: 'caption2',
|
||||
label: 'caption2 - Hyperlink Medium',
|
||||
fontWeight: 'Medium (500)'
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
/*************************** TYPOGRAPHY - BLOCK ***************************/
|
||||
|
||||
function FontSizeBlock({ desktop, tablet, mobile, type }) {
|
||||
let label1 = 'Desktop';
|
||||
let label2 = 'Tablet';
|
||||
let label3 = 'Mobile';
|
||||
|
||||
if (type === 'letter-spacing') {
|
||||
label1 = label2 = label3 = 'Letter Spacing';
|
||||
}
|
||||
|
||||
if (type === 'line-height') {
|
||||
label1 = label2 = label3 = 'Line Height';
|
||||
}
|
||||
|
||||
return (
|
||||
<Grid container spacing={1}>
|
||||
<Grid size={4}>
|
||||
<Stack sx={{ gap: 0.5 }}>
|
||||
<Typography variant="body2" sx={{ color: 'grey.700' }}>
|
||||
{label1}
|
||||
</Typography>
|
||||
<Typography variant="subtitle1">{desktop}</Typography>
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid size={4}>
|
||||
<Stack sx={{ gap: 0.5 }}>
|
||||
<Typography variant="body2" sx={{ color: 'grey.700' }}>
|
||||
{label2}
|
||||
</Typography>
|
||||
<Typography variant="subtitle1">{tablet}</Typography>
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid size={4}>
|
||||
<Stack sx={{ gap: 0.5 }}>
|
||||
<Typography variant="body2" sx={{ color: 'grey.700' }}>
|
||||
{label3}
|
||||
</Typography>
|
||||
<Typography variant="subtitle1">{mobile}</Typography>
|
||||
</Stack>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
|
||||
/*************************** SECTIONS - TYPOGRAPHY ***************************/
|
||||
|
||||
/**
|
||||
*
|
||||
* Demos:
|
||||
* - [Typography](https://www.saasable.io/sections/typography)
|
||||
*/
|
||||
|
||||
export default function TypographyPage() {
|
||||
return (
|
||||
<Grid container spacing={{ xs: 2.5, sm: 3, md: 4 }}>
|
||||
{typographyData.map((item, index) => (
|
||||
<Grid key={index} size={12}>
|
||||
<Stack sx={{ gap: { xs: 1.5 } }}>
|
||||
<Typeset {...{ heading: item.heading, stackProps: { sx: { mb: 1 } } }} />
|
||||
{item.items.map((block, index) => (
|
||||
<GraphicsCard key={index}>
|
||||
<Box sx={{ p: { xs: 3, sm: 4, md: 5 } }}>
|
||||
<Grid container spacing={2.5}>
|
||||
<Grid size={{ xs: 12, sm: 3, md: 2 }}>
|
||||
<Typography variant="h4">{block.title}</Typography>
|
||||
<Typography variant="body2" sx={{ color: 'grey.700' }}>
|
||||
{block.label}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid size={{ xs: 11, sm: 6, md: 4 }}>
|
||||
<Stack sx={{ gap: 2.5 }}>
|
||||
<Typography variant="subtitle1">{block.fontWeight}</Typography>
|
||||
<FontSizeBlock {...block.sizeValue} type="font-size" />
|
||||
<FontSizeBlock {...block.lineHeight} type="line-height" />
|
||||
<FontSizeBlock {...block.letterSpacing} type="letter-spacing" />
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid size={{ xs: 12, md: 6 }}>
|
||||
<Typography variant={block.variant}>Quick brown fox jumps!</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
</GraphicsCard>
|
||||
))}
|
||||
</Stack>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
|
||||
FontSizeBlock.propTypes = { desktop: PropTypes.string, tablet: PropTypes.string, mobile: PropTypes.string, type: PropTypes.string };
|
||||
@@ -0,0 +1,125 @@
|
||||
'use client';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
// @mui
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import Chip from '@mui/material/Chip';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import Box from '@mui/material/Box';
|
||||
|
||||
// @third-party
|
||||
import { motion } from 'motion/react';
|
||||
import Slider from 'react-slick';
|
||||
|
||||
// @project
|
||||
import ContainerWrapper from '@/components/ContainerWrapper';
|
||||
import GraphicsImage from '@/components/GraphicsImage';
|
||||
|
||||
import { withAlpha } from '@/utils/colorUtils';
|
||||
import { SECTION_COMMON_PY } from '@/utils/constant';
|
||||
|
||||
/*************************** CLIENTELE - 3 ***************************/
|
||||
|
||||
/**
|
||||
*
|
||||
* Demos:
|
||||
* - [Clientele3](https://www.saasable.io/blocks/clientele/clientele3)
|
||||
*
|
||||
* API:
|
||||
* - [Clientele3 API](https://phoenixcoded.gitbook.io/saasable/ui-kit/development/components/clientele/clientele3#props-details)
|
||||
*/
|
||||
|
||||
export default function Clientele3({ title, clienteleList }) {
|
||||
const theme = useTheme();
|
||||
|
||||
const settings = {
|
||||
autoplay: true,
|
||||
arrows: false,
|
||||
dots: false,
|
||||
infinite: true,
|
||||
speed: 500,
|
||||
slidesToShow: 5,
|
||||
swipeToSlide: true,
|
||||
initialSlide: 0,
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: theme.breakpoints.values.md,
|
||||
settings: { slidesToShow: 4 }
|
||||
},
|
||||
{
|
||||
breakpoint: theme.breakpoints.values.sm,
|
||||
settings: { slidesToShow: 2, centerMode: true }
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const shade = {
|
||||
content: `' '`,
|
||||
zIndex: 1,
|
||||
position: 'absolute',
|
||||
width: { sm: 60, xs: 40 },
|
||||
height: 1,
|
||||
top: 0,
|
||||
background: `linear-gradient(90deg, ${theme.vars.palette.background.default} -8.54%, ${withAlpha(theme.vars.palette.background.default, 0)} 100%)`,
|
||||
transform: null
|
||||
};
|
||||
|
||||
return (
|
||||
<ContainerWrapper sx={{ py: SECTION_COMMON_PY }}>
|
||||
<Stack sx={{ gap: 2.5 }}>
|
||||
{title && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.5, delay: 0.3 }}
|
||||
>
|
||||
<Typography variant="subtitle2" align="center" sx={{ color: 'text.secondary' }}>
|
||||
{title}
|
||||
</Typography>
|
||||
</motion.div>
|
||||
)}
|
||||
<Box sx={{ position: 'relative', '&:before': { ...shade, left: 0 }, '&:after': { ...shade, right: 0, rotate: '180deg' } }}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
whileInView={{ opacity: 1 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{
|
||||
duration: 0.5,
|
||||
delay: 0.4
|
||||
}}
|
||||
>
|
||||
<Slider {...settings}>
|
||||
{clienteleList.map((item, index) => (
|
||||
<motion.div
|
||||
key={index}
|
||||
initial={{ opacity: 0, scale: 0.5 }}
|
||||
whileInView={{ opacity: 1, scale: 1 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.6, ease: 'easeOut', delay: index * 0.2 }}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
px: { xs: 0.25, sm: 0.5, md: 0.75 },
|
||||
'& svg': { opacity: 0.4, transition: ' all 0.5s ease-in-out' },
|
||||
'&:hover svg': { opacity: 1, transition: ' all 0.5s ease-in-out' }
|
||||
}}
|
||||
>
|
||||
<Chip
|
||||
label={<GraphicsImage {...item} />}
|
||||
slotProps={{ label: { sx: { p: 0 } } }}
|
||||
sx={{ bgcolor: 'grey.100', height: { xs: 40, sm: 46, md: 60 }, width: 1 }}
|
||||
/>
|
||||
</Box>
|
||||
</motion.div>
|
||||
))}
|
||||
</Slider>
|
||||
</motion.div>
|
||||
</Box>
|
||||
</Stack>
|
||||
</ContainerWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
Clientele3.propTypes = { title: PropTypes.string, clienteleList: PropTypes.array };
|
||||
@@ -0,0 +1 @@
|
||||
export { default as Clientele3 } from './Clientele3';
|
||||
@@ -0,0 +1,131 @@
|
||||
'use client';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
// @mui
|
||||
import Avatar from '@mui/material/Avatar';
|
||||
import Button from '@mui/material/Button';
|
||||
import Grid from '@mui/material/Grid';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import Box from '@mui/material/Box';
|
||||
|
||||
// @third-party
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
// @project
|
||||
import ButtonAnimationWrapper from '@/components/ButtonAnimationWrapper';
|
||||
import { GraphicsCard } from '@/components/cards';
|
||||
import { ContactUsForm2 } from '@/components/contact-us';
|
||||
import ContainerWrapper from '@/components/ContainerWrapper';
|
||||
import SvgIcon from '@/components/SvgIcon';
|
||||
import Typeset from '@/components/Typeset';
|
||||
import { SECTION_COMMON_PY } from '@/utils/constant';
|
||||
|
||||
/*************************** CONTACT US - CARD ***************************/
|
||||
|
||||
function ContactCard({ icon, title, content, link }) {
|
||||
return (
|
||||
<GraphicsCard sx={{ height: 1 }}>
|
||||
<Stack direction={{ xs: 'row', sm: 'column' }} sx={{ gap: { xs: 2, sm: 4, md: 5 }, height: 1, p: { xs: 2, sm: 3, md: 4 } }}>
|
||||
<Avatar sx={{ width: 60, height: 60, bgcolor: 'grey.300' }}>
|
||||
<SvgIcon {...(typeof icon === 'string' ? { name: icon } : { ...icon })} />
|
||||
</Avatar>
|
||||
<Stack sx={{ gap: { xs: 2, md: 3 }, height: 1, alignItems: 'flex-start', justifyContent: 'space-between' }}>
|
||||
<Typeset
|
||||
{...{
|
||||
heading: title,
|
||||
caption: content,
|
||||
stackProps: { sx: { gap: 1 } },
|
||||
headingProps: { variant: 'h4' },
|
||||
captionProps: { variant: 'body1' }
|
||||
}}
|
||||
/>
|
||||
{link && (
|
||||
<ButtonAnimationWrapper>
|
||||
<Button color="primary" variant="outlined" {...link} />
|
||||
</ButtonAnimationWrapper>
|
||||
)}
|
||||
</Stack>
|
||||
</Stack>
|
||||
</GraphicsCard>
|
||||
);
|
||||
}
|
||||
|
||||
/*************************** CONTACT US - 4 ***************************/
|
||||
|
||||
/**
|
||||
*
|
||||
* Demos:
|
||||
* - [ContactUs4](https://www.saasable.io/blocks/contact-us/contact-us4)
|
||||
*
|
||||
* API:
|
||||
* - [ContactUs4 API](https://phoenixcoded.gitbook.io/saasable/ui-kit/development/components/contact-us/contactus4#props-details)
|
||||
*/
|
||||
|
||||
export default function ContactUs4({ heading, caption, list, showForm = true }) {
|
||||
const sectionPadding = { xs: 2, sm: 3, md: 5 };
|
||||
const cardRadius = { xs: 6, sm: 8 };
|
||||
|
||||
return (
|
||||
<ContainerWrapper sx={{ py: SECTION_COMMON_PY }}>
|
||||
<Stack sx={{ gap: { xs: 3, sm: 4 } }}>
|
||||
<Grid container spacing={1.5}>
|
||||
{showForm && (
|
||||
<Grid size={12}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{
|
||||
duration: 0.4,
|
||||
delay: 0.4
|
||||
}}
|
||||
style={{ height: '100%' }}
|
||||
>
|
||||
<GraphicsCard sx={{ height: 1, borderRadius: cardRadius }}>
|
||||
<GraphicsCard sx={{ bgcolor: 'grey.200', borderRadius: cardRadius }}>
|
||||
<Box sx={{ p: { xs: 2, sm: 4, md: 5 } }}>
|
||||
{heading && (
|
||||
<Typeset
|
||||
{...{
|
||||
heading,
|
||||
caption,
|
||||
stackProps: { sx: { alignItems: 'center', textAlign: 'center' } },
|
||||
headingProps: { sx: { maxWidth: { xs: '85%', sm: '80%' } } },
|
||||
captionProps: { sx: { maxWidth: { sm: '60%' } } }
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
</GraphicsCard>
|
||||
<Box sx={{ p: sectionPadding, px: { md: 24 } }}>
|
||||
<ContactUsForm2 />
|
||||
</Box>
|
||||
</GraphicsCard>
|
||||
</motion.div>
|
||||
</Grid>
|
||||
)}
|
||||
{list?.map((item, index) => (
|
||||
<Grid key={index} size={{ xs: 12, sm: 4 }}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{
|
||||
duration: 0.4,
|
||||
delay: item.animationDelay
|
||||
}}
|
||||
style={{ height: '100%' }}
|
||||
>
|
||||
<ContactCard {...{ ...item }} />
|
||||
</motion.div>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
</Stack>
|
||||
</ContainerWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
ContactCard.propTypes = { icon: PropTypes.any, title: PropTypes.any, content: PropTypes.any, link: PropTypes.any };
|
||||
|
||||
ContactUs4.propTypes = { heading: PropTypes.any, caption: PropTypes.any, list: PropTypes.any, showForm: PropTypes.bool };
|
||||
@@ -0,0 +1 @@
|
||||
export { default as ContactUs4 } from './ContactUs4';
|
||||
@@ -0,0 +1,122 @@
|
||||
'use client';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
// @mui
|
||||
import Button from '@mui/material/Button';
|
||||
import Grid from '@mui/material/Grid';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import Box from '@mui/material/Box';
|
||||
|
||||
// @third-party
|
||||
import { motion } from 'motion/react';
|
||||
|
||||
// @project
|
||||
import ButtonAnimationWrapper from '@/components/ButtonAnimationWrapper';
|
||||
import ContainerWrapper from '@/components/ContainerWrapper';
|
||||
import { GraphicsCard } from '@/components/cards';
|
||||
import { ProfileGroup } from '@/components/cards/profile-card';
|
||||
import SvgIcon from '@/components/SvgIcon';
|
||||
|
||||
import { SECTION_COMMON_PY } from '@/utils/constant';
|
||||
|
||||
// @assets
|
||||
import Arrow from '@/images/graphics/Arrow';
|
||||
|
||||
/*************************** CALL TO ACTION - 4 ***************************/
|
||||
|
||||
/**
|
||||
*
|
||||
* Demos:
|
||||
* - [CTA4](https://www.saasable.io/blocks/cta/cta4)
|
||||
*
|
||||
* API:
|
||||
* - [CTA4 API](https://phoenixcoded.gitbook.io/saasable/ui-kit/development/components/cta/cta4#props-details)
|
||||
*/
|
||||
|
||||
export default function Cta4({ headLine, primaryBtn, profileGroups, list, clientContent }) {
|
||||
const transformValues = { xs: 'rotate(45deg)', sm: 'rotate(320deg)', md: 'unset' };
|
||||
|
||||
return (
|
||||
<ContainerWrapper sx={{ py: SECTION_COMMON_PY }}>
|
||||
<GraphicsCard>
|
||||
<Box sx={{ p: { xs: 3, sm: 4, md: 5 } }}>
|
||||
<Grid container spacing={{ xs: 5, sm: 0, md: 3 }} sx={{ alignItems: 'flex-end' }}>
|
||||
<Grid size={{ xs: 12, sm: 9, md: 8 }}>
|
||||
<Stack sx={{ gap: 5 }}>
|
||||
<ProfileGroup {...profileGroups} />
|
||||
<Stack sx={{ gap: { xs: 2, sm: 5 } }}>
|
||||
{typeof headLine === 'string' ? <Typography variant="h2">{headLine}</Typography> : headLine}
|
||||
{list && (
|
||||
<Stack direction={{ sm: 'row' }} sx={{ columnGap: { xs: 1, sm: 3 }, rowGap: 1, flexWrap: 'wrap' }}>
|
||||
{list.map((item, index) => (
|
||||
<motion.div
|
||||
key={index}
|
||||
initial={{ opacity: 0, x: -30 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ duration: 0.2, ease: 'easeInOut', delay: index * 0.6 }}
|
||||
>
|
||||
<Stack direction="row" sx={{ gap: 1, alignItems: 'center' }}>
|
||||
<SvgIcon name="tabler-rosette-discount-check" color="text.secondary" stroke={1} />
|
||||
<Typography variant="body2" sx={{ color: 'text.secondary' }}>
|
||||
{item.primary}
|
||||
</Typography>
|
||||
</Stack>
|
||||
</motion.div>
|
||||
))}
|
||||
</Stack>
|
||||
)}
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid sx={{ position: 'relative', pl: { md: 3 }, pt: { md: 3 } }} size={{ sm: 3, md: 4 }}>
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: { xs: -36, sm: -98, md: -68 },
|
||||
right: { xs: -70, sm: 40, md: 100 },
|
||||
transform: transformValues
|
||||
}}
|
||||
>
|
||||
<Arrow />
|
||||
</Box>
|
||||
<Typography
|
||||
variant="subtitle1"
|
||||
sx={{
|
||||
color: 'primary.main',
|
||||
width: 94,
|
||||
position: 'absolute',
|
||||
top: { xs: 6, sm: -160, md: -82 },
|
||||
right: { xs: -160, sm: 0 }
|
||||
}}
|
||||
>
|
||||
{clientContent}
|
||||
</Typography>
|
||||
<Box sx={{ textAlign: 'right' }}>
|
||||
<motion.div
|
||||
initial={{ scale: 0.9 }}
|
||||
animate={{ opacity: 1, y: 0, scale: [1, 1.05, 1] }}
|
||||
transition={{ duration: 1.1, delay: 0.1, ease: 'easeInOut', repeat: Infinity }}
|
||||
whileHover={{ scale: 1, transition: { duration: 0.3 } }}
|
||||
whileTap={{ scale: 0.95 }}
|
||||
>
|
||||
<ButtonAnimationWrapper>
|
||||
<Button color="primary" size="large" variant="contained" sx={{ minWidth: { md: 263 } }} {...primaryBtn} />
|
||||
</ButtonAnimationWrapper>
|
||||
</motion.div>
|
||||
</Box>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
</GraphicsCard>
|
||||
</ContainerWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
Cta4.propTypes = {
|
||||
headLine: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
||||
primaryBtn: PropTypes.any,
|
||||
profileGroups: PropTypes.object,
|
||||
list: PropTypes.array,
|
||||
clientContent: PropTypes.string
|
||||
};
|
||||
@@ -0,0 +1,200 @@
|
||||
'use client';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
// @mui
|
||||
import Button from '@mui/material/Button';
|
||||
import Chip from '@mui/material/Chip';
|
||||
import Divider from '@mui/material/Divider';
|
||||
import Grid from '@mui/material/Grid';
|
||||
import OutlinedInput from '@mui/material/OutlinedInput';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import Box from '@mui/material/Box';
|
||||
|
||||
// @third-party
|
||||
import { motion } from 'motion/react';
|
||||
|
||||
// @project
|
||||
import ButtonAnimationWrapper from '@/components/ButtonAnimationWrapper';
|
||||
import ContainerWrapper from '@/components/ContainerWrapper';
|
||||
import { GraphicsCard } from '@/components/cards';
|
||||
import { ProfileGroup } from '@/components/cards/profile-card';
|
||||
import LogoWatermark from '@/components/logo/LogoWatermark';
|
||||
import Typeset from '@/components/Typeset';
|
||||
|
||||
import { SECTION_COMMON_PY } from '@/utils/constant';
|
||||
|
||||
// @assets
|
||||
import Wave from '@/images/graphics/Wave';
|
||||
|
||||
/*************************** CALL TO ACTION - 5 ***************************/
|
||||
|
||||
/**
|
||||
*
|
||||
* Demos:
|
||||
* - [CTA5](https://www.saasable.io/blocks/cta/cta5)
|
||||
*
|
||||
* API:
|
||||
* - [CTA5 API](https://phoenixcoded.gitbook.io/saasable/ui-kit/development/components/cta/cta5#props-details)
|
||||
*/
|
||||
|
||||
export default function Cta5({ heading, caption, label, input = false, primaryBtn, secondaryBtn, description, saleData, profileGroups }) {
|
||||
return (
|
||||
<ContainerWrapper sx={{ py: SECTION_COMMON_PY }}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{
|
||||
duration: 0.5,
|
||||
delay: 0.4
|
||||
}}
|
||||
>
|
||||
<Grid container spacing={1.5}>
|
||||
<Grid size={{ xs: 12, sm: 8, md: 9 }}>
|
||||
<motion.div initial={{ opacity: 0, y: -100 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.8, delay: 0.6 }}>
|
||||
<GraphicsCard sx={{ position: 'relative' }}>
|
||||
<Stack
|
||||
sx={{ alignItems: 'flex-start', gap: { xs: 5.75, sm: 10 }, p: { xs: 3, sm: 4, md: 8 }, position: 'relative', zIndex: 1 }}
|
||||
>
|
||||
<Stack sx={{ gap: 5 }}>
|
||||
<Stack direction="row" sx={{ alignItems: 'center', gap: 1 }}>
|
||||
<Chip
|
||||
label={label}
|
||||
variant="outlined"
|
||||
slotProps={{ label: { sx: { py: 0.75, px: 2, typography: 'caption', color: 'secondary.main' } } }}
|
||||
sx={{ borderColor: 'grey.600' }}
|
||||
/>
|
||||
<Divider sx={{ width: 63, borderBottomWidth: 2 }} />
|
||||
</Stack>
|
||||
<Typeset {...{ heading, caption, captionProps: { sx: { maxWidth: 478 } } }} />
|
||||
</Stack>
|
||||
{input && typeof input === 'object' && (
|
||||
<Stack sx={{ gap: 0.75, width: { sm: '100%', md: 'unset' } }}>
|
||||
<OutlinedInput
|
||||
placeholder={input.placeholder || 'Enter your email address'}
|
||||
endAdornment={
|
||||
<Button
|
||||
color="primary"
|
||||
variant="contained"
|
||||
sx={{ px: 4, minWidth: { xs: 110, md: 120 } }}
|
||||
{...input.adornmentBtn}
|
||||
/>
|
||||
}
|
||||
slotProps={{
|
||||
input: { 'aria-label': 'Email address', sx: { px: 2.5, py: 0.75 } },
|
||||
notchedOutline: { sx: { borderRadius: 25 } }
|
||||
}}
|
||||
sx={{ typography: 'caption2', color: 'secondary.main', p: 0.5, whiteSpace: 'nowrap' }}
|
||||
/>
|
||||
{input.helpertext && (
|
||||
<Typography variant="body2" sx={{ color: 'text.secondary' }}>
|
||||
{input.helpertext}
|
||||
</Typography>
|
||||
)}
|
||||
</Stack>
|
||||
)}
|
||||
{(primaryBtn || secondaryBtn || description) && (
|
||||
<Stack sx={{ alignItems: 'flex-start', gap: 1.5, width: { sm: '100%', md: '60%' }, ...(input && { mt: -6 }) }}>
|
||||
{(primaryBtn || secondaryBtn) && (
|
||||
<Stack direction="row" spacing={1.5} sx={{ alignItems: 'flex-start', justifyContent: 'center' }}>
|
||||
{secondaryBtn && (
|
||||
<ButtonAnimationWrapper>
|
||||
<Button variant="outlined" sx={{ minWidth: { sm: 170 } }} {...secondaryBtn} />
|
||||
</ButtonAnimationWrapper>
|
||||
)}
|
||||
{primaryBtn && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.3, ease: 'easeInOut' }}
|
||||
whileHover={{ scale: 1.06 }}
|
||||
>
|
||||
<ButtonAnimationWrapper>
|
||||
<Button variant="contained" sx={{ minWidth: { sm: 170 } }} {...primaryBtn} />
|
||||
</ButtonAnimationWrapper>
|
||||
</motion.div>
|
||||
)}
|
||||
</Stack>
|
||||
)}
|
||||
{description && typeof description === 'string' ? (
|
||||
<Typography variant="body2" sx={{ color: 'text.secondary' }}>
|
||||
{description}
|
||||
</Typography>
|
||||
) : (
|
||||
description
|
||||
)}
|
||||
</Stack>
|
||||
)}
|
||||
</Stack>
|
||||
<Box
|
||||
sx={{ position: 'absolute', right: -160, bottom: -160, display: { xs: 'none', md: 'block' }, transform: 'scaleX(-1)' }}
|
||||
>
|
||||
<LogoWatermark />
|
||||
</Box>
|
||||
</GraphicsCard>
|
||||
</motion.div>
|
||||
</Grid>
|
||||
<Grid size={{ xs: 12, sm: 4, md: 3 }}>
|
||||
<Grid container sx={{ height: 1, position: 'relative' }}>
|
||||
<Grid size={{ xs: 6, sm: 12 }} sx={{ minHeight: { sm: '50%' } }}>
|
||||
<GraphicsCard sx={{ height: 1 }}>
|
||||
<Stack sx={{ alignItems: 'center', gap: 1, py: { xs: 2, sm: 6, md: 7.5 }, px: { xs: 2, sm: 3.5 }, textAlign: 'center' }}>
|
||||
<Typography component="div" variant="h1">
|
||||
{saleData.count}
|
||||
<Typography variant="h2" component="span" sx={{ color: 'text.secondary' }}>
|
||||
{saleData.defaultUnit}
|
||||
</Typography>
|
||||
</Typography>
|
||||
<Typography sx={{ color: 'text.secondary' }}>{saleData.caption}</Typography>
|
||||
</Stack>
|
||||
</GraphicsCard>
|
||||
</Grid>
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
left: '50%',
|
||||
top: '50%',
|
||||
transform: { xs: 'translate(-50%,-50%) rotate(90deg)', sm: 'translate(-50%,-50%)' },
|
||||
'& .wave svg': { width: { xs: 70, sm: 122 } }
|
||||
}}
|
||||
>
|
||||
<Wave />
|
||||
</Box>
|
||||
<Grid size={{ xs: 6, sm: 12 }} sx={{ minHeight: { sm: '50%' } }}>
|
||||
<GraphicsCard sx={{ height: 1 }}>
|
||||
<ProfileGroup
|
||||
{...profileGroups}
|
||||
sx={{
|
||||
py: { xs: 2, sm: 4, md: 6.75 },
|
||||
px: { xs: 2, sm: 1.5 },
|
||||
height: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
textAlign: 'center',
|
||||
'& .MuiAvatarGroup-root': { mb: 0.5 },
|
||||
'& .MuiAvatar-root': { width: { xs: 40, sm: 58 }, height: { xs: 40, sm: 58 } },
|
||||
'& .wave': { display: 'none' }
|
||||
}}
|
||||
/>
|
||||
</GraphicsCard>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</motion.div>
|
||||
</ContainerWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
Cta5.propTypes = {
|
||||
heading: PropTypes.string,
|
||||
caption: PropTypes.string,
|
||||
label: PropTypes.string,
|
||||
input: PropTypes.oneOfType([PropTypes.bool, PropTypes.any]),
|
||||
primaryBtn: PropTypes.any,
|
||||
secondaryBtn: PropTypes.any,
|
||||
description: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
||||
saleData: PropTypes.any,
|
||||
profileGroups: PropTypes.object
|
||||
};
|
||||
@@ -0,0 +1,2 @@
|
||||
export { default as Cta4 } from './Cta4';
|
||||
export { default as Cta5 } from './Cta5';
|
||||
@@ -0,0 +1,211 @@
|
||||
'use client';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { useState } from 'react';
|
||||
|
||||
// @next
|
||||
import NextLink from 'next/link';
|
||||
|
||||
// @mui
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import Accordion from '@mui/material/Accordion';
|
||||
import AccordionDetails from '@mui/material/AccordionDetails';
|
||||
import AccordionSummary from '@mui/material/AccordionSummary';
|
||||
import Button from '@mui/material/Button';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import Typography from '@mui/material/Typography';
|
||||
|
||||
// @third-party
|
||||
import { motion } from 'motion/react';
|
||||
import Slider from 'react-slick';
|
||||
|
||||
// @project
|
||||
import ButtonAnimationWrapper from '@/components/ButtonAnimationWrapper';
|
||||
import ContainerWrapper from '@/components/ContainerWrapper';
|
||||
import FaqDetails from '@/components/faq/FaqDetails';
|
||||
import SvgIcon from '@/components/SvgIcon';
|
||||
import Typeset from '@/components/Typeset';
|
||||
|
||||
import useFocusWithin from '@/hooks/useFocusWithin';
|
||||
import { generateFocusVisibleStyles } from '@/utils/CommonFocusStyle';
|
||||
import { SECTION_COMMON_PY } from '@/utils/constant';
|
||||
|
||||
/*************************** FAQ - 6 ***************************/
|
||||
|
||||
/**
|
||||
*
|
||||
* Demos:
|
||||
* - [FAQ6](https://www.saasable.io/blocks/faq/faq6)
|
||||
*
|
||||
* API:
|
||||
* - [FAQ6 API](https://phoenixcoded.gitbook.io/saasable/ui-kit/development/components/faq/faq6#props-details)
|
||||
*/
|
||||
|
||||
export default function Faq6({ heading, caption, defaultExpanded, faqList, getInTouch, categories, activeCategory }) {
|
||||
const theme = useTheme();
|
||||
const isFocusWithin = useFocusWithin();
|
||||
const [expanded, setExpanded] = useState(defaultExpanded || false);
|
||||
const [activeTopic, setActiveTopic] = useState(activeCategory || '');
|
||||
const [filterFaqList, setFilterFaqList] = useState(activeCategory ? faqList.filter((item) => item.category === activeCategory) : faqList);
|
||||
|
||||
const cardRadius = { xs: 4, sm: 6 };
|
||||
const accordionRadius = { xs: cardRadius.xs * 4, sm: cardRadius.sm * 4 };
|
||||
const accordionPX = { xs: 2, sm: 3 };
|
||||
const iconProps = { color: 'text.primary' };
|
||||
|
||||
// Handles the expansion of accordion panels
|
||||
const handleChange = (panel) => (event, isExpanded) => setExpanded(isExpanded ? panel : false);
|
||||
|
||||
const slickStyle = { '& .slick-slide': { ' > div': { px: { xs: 0.5, md: 0.75 } } } };
|
||||
|
||||
const settings = {
|
||||
arrows: false,
|
||||
dots: false,
|
||||
infinite: false,
|
||||
speed: 500,
|
||||
swipeToSlide: true,
|
||||
initialSlide: 0,
|
||||
variableWidth: true
|
||||
};
|
||||
|
||||
return (
|
||||
<ContainerWrapper sx={{ py: SECTION_COMMON_PY }}>
|
||||
<Stack sx={{ gap: { xs: 3, sm: 4 } }}>
|
||||
{heading && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.5, delay: 0.1 }}
|
||||
>
|
||||
<Stack direction={{ sm: 'row' }} sx={{ gap: 4, justifyContent: 'space-between', alignItems: { xs: 'flex-start', sm: 'end' } }}>
|
||||
<Typeset {...{ heading, caption }} />
|
||||
{getInTouch?.link && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.3, ease: 'easeInOut' }}
|
||||
whileHover={{ scale: 1.06 }}
|
||||
>
|
||||
<ButtonAnimationWrapper>
|
||||
<Button
|
||||
variant="contained"
|
||||
size="large"
|
||||
{...getInTouch.link}
|
||||
{...(getInTouch.link && getInTouch.link.href && { component: NextLink })}
|
||||
sx={{ minWidth: 215, ...getInTouch.link.sx }}
|
||||
/>
|
||||
</ButtonAnimationWrapper>
|
||||
</motion.div>
|
||||
)}
|
||||
</Stack>
|
||||
</motion.div>
|
||||
)}
|
||||
<Stack sx={{ gap: 2 }}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{
|
||||
duration: 0.5,
|
||||
delay: 0.4
|
||||
}}
|
||||
>
|
||||
<Stack sx={slickStyle}>
|
||||
<Slider {...settings}>
|
||||
<Button
|
||||
sx={{
|
||||
minHeight: { xs: 40, sm: 48 },
|
||||
color: 'text.primary',
|
||||
borderColor: 'divider',
|
||||
bgcolor: activeTopic === '' ? 'grey.100' : 'inherit',
|
||||
'&.MuiButton-root:hover': { bgcolor: 'grey.100', borderColor: 'divider' }
|
||||
}}
|
||||
variant="outlined"
|
||||
onClick={() => {
|
||||
setActiveTopic('');
|
||||
setFilterFaqList(faqList);
|
||||
}}
|
||||
>
|
||||
All
|
||||
</Button>
|
||||
{categories.map((item, index) => (
|
||||
<Button
|
||||
key={index}
|
||||
sx={{
|
||||
minHeight: { xs: 40, sm: 48 },
|
||||
color: 'text.primary',
|
||||
borderColor: 'divider',
|
||||
bgcolor: activeTopic === item ? 'grey.100' : 'inherit',
|
||||
'&.MuiButton-root:hover': { bgcolor: 'grey.100', borderColor: 'divider' }
|
||||
}}
|
||||
variant="outlined"
|
||||
onClick={() => {
|
||||
setActiveTopic(item);
|
||||
setFilterFaqList(faqList.filter((list) => list.category === item));
|
||||
}}
|
||||
>
|
||||
{item}
|
||||
</Button>
|
||||
))}
|
||||
</Slider>
|
||||
</Stack>
|
||||
</motion.div>
|
||||
<Stack
|
||||
sx={{
|
||||
gap: 1.5,
|
||||
'& .MuiAccordion-root:first-of-type': { borderTopLeftRadius: accordionRadius, borderTopRightRadius: accordionRadius },
|
||||
'& .MuiAccordion-root:last-of-type': { borderBottomLeftRadius: accordionRadius, borderBottomRightRadius: accordionRadius }
|
||||
}}
|
||||
>
|
||||
{filterFaqList.map((item, index) => (
|
||||
<motion.div
|
||||
key={index}
|
||||
initial={{ y: 20, opacity: 0 }}
|
||||
whileInView={{ y: 0, opacity: 1 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.2, delay: index * 0.2 }}
|
||||
>
|
||||
<Accordion
|
||||
key={index}
|
||||
expanded={expanded === `panel${index}`}
|
||||
onChange={handleChange(`panel${index}`)}
|
||||
sx={{
|
||||
borderRadius: cardRadius,
|
||||
backgroundColor: 'grey.100',
|
||||
...(isFocusWithin && { '&:focus-within': generateFocusVisibleStyles(theme.vars.palette.primary.main) })
|
||||
}}
|
||||
>
|
||||
<AccordionSummary
|
||||
expandIcon={<SvgIcon name={expanded === `panel${index}` ? 'tabler-minus' : 'tabler-plus'} {...iconProps} size={20} />}
|
||||
sx={{
|
||||
p: accordionPX,
|
||||
'&.Mui-focusVisible': { bgcolor: 'transparent' },
|
||||
'&:hover, &:hover svg': { color: 'primary.dark' }
|
||||
}}
|
||||
slotProps={{ content: { sx: { my: 0 } } }}
|
||||
>
|
||||
<Typography variant="h4">{item.question}</Typography>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails sx={{ px: accordionPX, pt: 0, pb: accordionPX }} key={index}>
|
||||
<FaqDetails answer={item.answer} />
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
</motion.div>
|
||||
))}
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</ContainerWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
Faq6.propTypes = {
|
||||
heading: PropTypes.any,
|
||||
caption: PropTypes.any,
|
||||
defaultExpanded: PropTypes.any,
|
||||
faqList: PropTypes.any,
|
||||
getInTouch: PropTypes.any,
|
||||
categories: PropTypes.array,
|
||||
activeCategory: PropTypes.string
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export { default as Faq6 } from './Faq6';
|
||||
@@ -0,0 +1,268 @@
|
||||
'use client';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { useState } from 'react';
|
||||
|
||||
// @mui
|
||||
import Button from '@mui/material/Button';
|
||||
import Grid from '@mui/material/Grid';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import Tab from '@mui/material/Tab';
|
||||
import TabContext from '@mui/lab/TabContext';
|
||||
import TabList from '@mui/lab/TabList';
|
||||
import TabPanel from '@mui/lab/TabPanel';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import Box from '@mui/material/Box';
|
||||
|
||||
// @third-party
|
||||
import { motion } from 'motion/react';
|
||||
|
||||
// @project
|
||||
import ContainerWrapper from '@/components/ContainerWrapper';
|
||||
import { GraphicsCard } from '@/components/cards';
|
||||
import SvgIcon from '@/components/SvgIcon';
|
||||
import Typeset from '@/components/Typeset';
|
||||
import { SECTION_COMMON_PY } from '@/utils/constant';
|
||||
|
||||
// @assets
|
||||
import ButtonAnimationWrapper from '@/components/ButtonAnimationWrapper';
|
||||
import GraphicsImage from '@/components/GraphicsImage';
|
||||
|
||||
/*************************** FEATURE - 18 ***************************/
|
||||
|
||||
/**
|
||||
*
|
||||
* Demos:
|
||||
* - [Feature18](https://www.saasable.io/blocks/feature/feature18)
|
||||
*
|
||||
* API
|
||||
* - [Feature18 API](https://phoenixcoded.gitbook.io/saasable/ui-kit/development/components/feature/feature18#props-details)
|
||||
*/
|
||||
|
||||
export default function Feature18({ heading, caption, topics }) {
|
||||
const boxPadding = { xs: 3, md: 5 };
|
||||
const imagePadding = { xs: 3, sm: 4, md: 5 };
|
||||
|
||||
const [value, setValue] = useState('1');
|
||||
|
||||
// Handle tab change
|
||||
const handleChange = (event, newValue) => {
|
||||
setValue(newValue);
|
||||
};
|
||||
|
||||
return (
|
||||
<ContainerWrapper sx={{ py: SECTION_COMMON_PY }}>
|
||||
<Stack sx={{ gap: { xs: 3, sm: 4 } }}>
|
||||
<Typeset
|
||||
{...{
|
||||
heading,
|
||||
caption,
|
||||
stackProps: { sx: { alignItems: 'center', textAlign: 'center', maxWidth: { sm: 470, md: 615 }, mx: 'auto' } }
|
||||
}}
|
||||
/>
|
||||
<Stack sx={{ gap: 1.5, alignItems: 'center' }}>
|
||||
<TabContext value={value}>
|
||||
<GraphicsCard sx={{ width: { xs: 1, sm: 'unset' } }}>
|
||||
<Box sx={{ p: 0.25 }}>
|
||||
<TabList
|
||||
onChange={handleChange}
|
||||
sx={{ minHeight: 'unset', p: 0.25 }}
|
||||
slotProps={{ indicator: { sx: { display: 'none' } } }}
|
||||
variant="scrollable"
|
||||
>
|
||||
{topics.map((item, index) => (
|
||||
<Tab
|
||||
label={item.title}
|
||||
disableFocusRipple
|
||||
{...(item.icon && {
|
||||
icon: (
|
||||
<SvgIcon
|
||||
{...(typeof item.icon === 'string' ? { name: item.icon } : { ...item.icon })}
|
||||
size={16}
|
||||
stroke={2}
|
||||
color="text.secondary"
|
||||
/>
|
||||
)
|
||||
})}
|
||||
value={String(index + 1)}
|
||||
key={index}
|
||||
iconPosition="start"
|
||||
tabIndex={0}
|
||||
sx={{
|
||||
minHeight: 44,
|
||||
minWidth: { xs: 112, md: 160, sm: 156 },
|
||||
borderRadius: 10,
|
||||
borderWidth: 1,
|
||||
borderStyle: 'solid',
|
||||
borderColor: 'transparent',
|
||||
'& svg ': { mr: 1 },
|
||||
'&.Mui-selected': {
|
||||
bgcolor: 'grey.200',
|
||||
borderColor: 'grey.400',
|
||||
minWidth: { xs: 112, md: 160, sm: 156 },
|
||||
color: 'text.primary',
|
||||
'& svg': { stroke: 'text.primary' }
|
||||
},
|
||||
'&.Mui-focusVisible': { bgcolor: 'grey.300' },
|
||||
'&:hover': { bgcolor: 'grey.200' }
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</TabList>
|
||||
</Box>
|
||||
</GraphicsCard>
|
||||
{topics.map((item, index) => (
|
||||
<TabPanel value={String(index + 1)} key={index} sx={{ p: 0, width: 1 }}>
|
||||
<Grid container spacing={1.5}>
|
||||
<Grid size={{ xs: 12, sm: 5 }}>
|
||||
<GraphicsCard>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, x: 100, y: 100 }}
|
||||
whileInView={{ opacity: 1, x: 0, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.5, delay: 0.1 }}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
pl: item.isCoverImage ? 0 : imagePadding,
|
||||
pt: item.isCoverImage ? 0 : imagePadding,
|
||||
height: { xs: 260, sm: 396, md: 434 }
|
||||
}}
|
||||
>
|
||||
<GraphicsImage
|
||||
sx={{
|
||||
height: 1,
|
||||
backgroundPositionX: 'left',
|
||||
backgroundPositionY: 'top',
|
||||
...(item.isImageBorder && { borderTop: '5px solid', borderLeft: '5px solid', borderColor: 'grey.200' }),
|
||||
...(item.isCoverImage && { backgroundSize: 'cover', border: 'none' }),
|
||||
borderTopLeftRadius: { xs: 12 },
|
||||
borderBottomRightRadius: { xs: 20, sm: 32, md: 40 }
|
||||
}}
|
||||
image={item.image}
|
||||
/>
|
||||
</Box>
|
||||
</motion.div>
|
||||
</GraphicsCard>
|
||||
</Grid>
|
||||
<Grid size={{ xs: 12, sm: 7 }} sx={{ display: 'flex' }}>
|
||||
<GraphicsCard>
|
||||
<Stack
|
||||
sx={{
|
||||
justifyContent: 'space-between',
|
||||
gap: 5,
|
||||
height: item.actionBtn || item.actionBtn2 ? { sm: 'calc(100% - 98px)', md: 'calc(100% - 114px)' } : 1,
|
||||
pt: boxPadding,
|
||||
px: boxPadding
|
||||
}}
|
||||
>
|
||||
<motion.div
|
||||
key={index}
|
||||
initial={{ opacity: 0, x: -30 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
exit={{ opacity: 0, x: -30 }}
|
||||
transition={{ duration: 0.2, ease: 'linear', delay: index * 0.1 }}
|
||||
>
|
||||
<Stack direction="row" sx={{ gap: 1 }}>
|
||||
{item.icon && (
|
||||
<SvgIcon
|
||||
{...(typeof item.icon === 'string' ? { name: item.icon } : { ...item.icon })}
|
||||
size={16}
|
||||
stroke={2}
|
||||
color="text.primary"
|
||||
/>
|
||||
)}
|
||||
<Typography variant="subtitle2" sx={{ color: 'text.secondary' }}>
|
||||
{item.title}
|
||||
</Typography>
|
||||
</Stack>
|
||||
</motion.div>
|
||||
<Stack sx={{ gap: { xs: 2, md: 3 }, pb: boxPadding }}>
|
||||
<Stack sx={{ gap: 0.5 }}>
|
||||
<Typography variant="h4">{item.title2}</Typography>
|
||||
{item.description && <Typography sx={{ color: 'text.secondary' }}>{item.description}</Typography>}
|
||||
</Stack>
|
||||
{item.list && (
|
||||
<Grid container spacing={{ xs: 0.75, md: 1 }}>
|
||||
{item.list.map((list, index) => (
|
||||
<Grid key={index} size={{ xs: 12, md: 6 }}>
|
||||
<motion.div
|
||||
key={index}
|
||||
initial={{ opacity: 0, x: -30 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
exit={{ opacity: 0, x: -30 }}
|
||||
transition={{ duration: 0.2, ease: 'linear', delay: index * 0.1 }}
|
||||
>
|
||||
<Stack
|
||||
direction="row"
|
||||
sx={{
|
||||
gap: 0.5,
|
||||
alignItems: 'center',
|
||||
'& svg.tabler-rosette-discount-check': { width: { xs: 16, md: 24 }, height: { xs: 16, md: 24 } }
|
||||
}}
|
||||
>
|
||||
<SvgIcon name="tabler-rosette-discount-check" stroke={1} color="text.secondary" />
|
||||
<Typography variant="body2" sx={{ color: 'text.secondary' }}>
|
||||
{list.primary}
|
||||
</Typography>
|
||||
</Stack>
|
||||
</motion.div>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
)}
|
||||
</Stack>
|
||||
</Stack>
|
||||
{(item.actionBtn || item.actionBtn2) && (
|
||||
<GraphicsCard sx={{ bgcolor: 'grey.200' }}>
|
||||
<Stack direction="row" sx={{ alignItems: 'flex-start', gap: 1.5, p: { xs: 2, sm: 3, md: 4 } }}>
|
||||
{item.actionBtn2 && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.3, ease: 'easeInOut' }}
|
||||
whileHover={{ scale: 1.06 }}
|
||||
>
|
||||
<ButtonAnimationWrapper>
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
startIcon={<SvgIcon name="tabler-help" size={16} stroke={3} />}
|
||||
{...item.actionBtn2}
|
||||
/>
|
||||
</ButtonAnimationWrapper>
|
||||
</motion.div>
|
||||
)}
|
||||
{item.actionBtn && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.3, ease: 'easeInOut' }}
|
||||
whileHover={{ scale: 1.06 }}
|
||||
>
|
||||
<ButtonAnimationWrapper>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
startIcon={<SvgIcon name="tabler-link" size={16} stroke={3} color="background.default" />}
|
||||
{...item.actionBtn}
|
||||
/>
|
||||
</ButtonAnimationWrapper>
|
||||
</motion.div>
|
||||
)}
|
||||
</Stack>
|
||||
</GraphicsCard>
|
||||
)}
|
||||
</GraphicsCard>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</TabPanel>
|
||||
))}
|
||||
</TabContext>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</ContainerWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
Feature18.propTypes = { heading: PropTypes.string, caption: PropTypes.string, topics: PropTypes.array };
|
||||
@@ -0,0 +1,248 @@
|
||||
'use client';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
// @mui
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import useMediaQuery from '@mui/material/useMediaQuery';
|
||||
import Avatar from '@mui/material/Avatar';
|
||||
import Button from '@mui/material/Button';
|
||||
import Grid from '@mui/material/Grid';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import Box from '@mui/material/Box';
|
||||
|
||||
// @third-party
|
||||
import { motion } from 'motion/react';
|
||||
|
||||
// @project
|
||||
import ButtonAnimationWrapper from '@/components/ButtonAnimationWrapper';
|
||||
import ContainerWrapper from '@/components/ContainerWrapper';
|
||||
import { GraphicsCard } from '@/components/cards';
|
||||
import GraphicsImage from '@/components/GraphicsImage';
|
||||
import SvgIcon from '@/components/SvgIcon';
|
||||
import Typeset from '@/components/Typeset';
|
||||
import { withAlpha } from '@/utils/colorUtils';
|
||||
import { SECTION_COMMON_PY } from '@/utils/constant';
|
||||
|
||||
// @assets
|
||||
import Star from '@/images/graphics/Star';
|
||||
|
||||
/*************************** FEATURE - 20 ***************************/
|
||||
|
||||
/**
|
||||
*
|
||||
* Demos:
|
||||
* - [Feature20](https://www.saasable.io/blocks/feature/feature20)
|
||||
*
|
||||
* API
|
||||
* - [Feature20 API](https://phoenixcoded.gitbook.io/saasable/ui-kit/development/components/feature/feature20#props-details)
|
||||
*/
|
||||
|
||||
export default function Feature20({ heading, caption, image, features, actionBtn, secondaryBtn }) {
|
||||
const theme = useTheme();
|
||||
const downSM = useMediaQuery(theme.breakpoints.down('sm'));
|
||||
const downMD = useMediaQuery(theme.breakpoints.down('md'));
|
||||
|
||||
const partitionInExtraSmall = 1;
|
||||
const partitionInSmall = 2;
|
||||
const partitionInLarge = 3;
|
||||
|
||||
const columns = downSM ? partitionInExtraSmall : downMD ? partitionInSmall : partitionInLarge;
|
||||
|
||||
const calculateElementsInLastRow = (dataArray, columns) => {
|
||||
const totalItems = dataArray.length;
|
||||
const elementsInLastRow = totalItems % columns || columns;
|
||||
return elementsInLastRow;
|
||||
};
|
||||
|
||||
const calculateIndexOfFirstElementInLastRow = (dataArray, elementsInLastRow) => {
|
||||
const totalItems = dataArray.length;
|
||||
const indexOfFirstElementInLastRow = totalItems - elementsInLastRow;
|
||||
return indexOfFirstElementInLastRow;
|
||||
};
|
||||
|
||||
const elementsInLastRow = calculateElementsInLastRow(features, columns);
|
||||
const indexOfFirstElementInLastRow = calculateIndexOfFirstElementInLastRow(features, elementsInLastRow);
|
||||
|
||||
const calculateIndexOfLastElementOfEachRow = (dataArray, columns) => {
|
||||
const indices = [];
|
||||
const totalItems = dataArray.length;
|
||||
const rows = Math.ceil(totalItems / columns);
|
||||
|
||||
for (let i = 1; i <= rows; i++) {
|
||||
const lastIndexInRow = i * columns - 1;
|
||||
indices.push(lastIndexInRow < totalItems ? lastIndexInRow : totalItems - 1);
|
||||
}
|
||||
|
||||
return indices;
|
||||
};
|
||||
|
||||
const indicesOfLastElements = calculateIndexOfLastElementOfEachRow(features, columns);
|
||||
const gc = theme.vars.palette.background.default;
|
||||
|
||||
return (
|
||||
<ContainerWrapper sx={{ py: SECTION_COMMON_PY }}>
|
||||
<Stack sx={{ gap: { xs: 3, sm: 4, md: 5 } }}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{
|
||||
duration: 0.5,
|
||||
delay: 0.3
|
||||
}}
|
||||
>
|
||||
<Typeset {...{ heading, stackProps: { sx: { maxWidth: { md: 500 }, ...(!image && { maxWidth: 1, textAlign: 'center' }) } } }} />
|
||||
</motion.div>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 25 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{
|
||||
duration: 0.5,
|
||||
delay: 0.4
|
||||
}}
|
||||
>
|
||||
<GraphicsCard sx={{ position: 'relative', overflow: 'visible' }}>
|
||||
{image && (
|
||||
<GraphicsCard
|
||||
sx={{
|
||||
height: { md: 267 },
|
||||
width: { md: 456 },
|
||||
bgcolor: 'transparent',
|
||||
position: 'absolute',
|
||||
top: -190,
|
||||
right: 45,
|
||||
zIndex: -1,
|
||||
display: { xs: 'none', md: 'block' }
|
||||
}}
|
||||
>
|
||||
<GraphicsImage sx={{ height: 1, backgroundPositionX: 'right', backgroundPositionY: 'top' }} image={image}>
|
||||
<Box
|
||||
sx={{ width: 1, height: 1, background: `linear-gradient(180deg, ${withAlpha(gc, 0)} 0%, ${withAlpha(gc, 0.6)} 100%)` }}
|
||||
/>
|
||||
</GraphicsImage>
|
||||
</GraphicsCard>
|
||||
)}
|
||||
<Box sx={{ p: 3 }}>
|
||||
<Grid container>
|
||||
{features.map((item, index) => (
|
||||
<Grid
|
||||
key={index}
|
||||
size={{ xs: 12 / partitionInExtraSmall, sm: 12 / partitionInSmall, md: 12 / partitionInLarge }}
|
||||
sx={{
|
||||
position: 'relative',
|
||||
...(index < indexOfFirstElementInLastRow && { borderBottom: `1px solid ${theme.vars.palette.grey[300]}` }),
|
||||
...(!indicesOfLastElements.includes(index) && { borderRight: `1px solid ${theme.vars.palette.grey[300]}` })
|
||||
}}
|
||||
>
|
||||
<Stack sx={{ gap: { xs: 3, sm: 4 }, height: 1, py: { xs: 1.5, sm: 3, md: 4 }, px: { xs: 0, sm: 3, md: 4 } }}>
|
||||
<Avatar sx={{ width: 60, height: 60, bgcolor: 'grey.300' }}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, scale: 0.6 }}
|
||||
whileInView={{ opacity: 1, scale: 1 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 2, delay: index * 0.1 }}
|
||||
>
|
||||
<SvgIcon {...(typeof item.icon === 'string' ? { name: item.icon } : { ...item.icon })} />
|
||||
</motion.div>
|
||||
</Avatar>
|
||||
<Stack sx={{ gap: { xs: 0.5, md: 1 } }}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 25 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.5, delay: index * 0.2 }}
|
||||
>
|
||||
{item.title && <Typography variant="h4">{item.title}</Typography>}
|
||||
</motion.div>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 25 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.5, delay: index * 0.3 }}
|
||||
>
|
||||
{item.content && <Typography sx={{ color: 'text.secondary' }}>{item.content}</Typography>}
|
||||
</motion.div>
|
||||
</Stack>
|
||||
</Stack>
|
||||
{index < indexOfFirstElementInLastRow && !indicesOfLastElements.includes(index) && (
|
||||
<Stack sx={{ position: 'absolute', bottom: -9, right: -9 }}>
|
||||
<Star />
|
||||
</Stack>
|
||||
)}
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
</Box>
|
||||
</GraphicsCard>
|
||||
</motion.div>
|
||||
<Stack sx={{ alignItems: 'center', gap: 3 }}>
|
||||
<Typography variant="h6" sx={{ color: 'text.secondary', maxWidth: { xs: '75%', sm: '45%' }, textAlign: 'center' }}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 15 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{
|
||||
duration: 0.5,
|
||||
delay: 0.4
|
||||
}}
|
||||
>
|
||||
{caption}
|
||||
</motion.div>
|
||||
</Typography>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{
|
||||
duration: 0.5,
|
||||
delay: 0.5
|
||||
}}
|
||||
>
|
||||
<Stack direction="row" sx={{ alignItems: 'center', justifyContent: 'center', gap: 1.5 }}>
|
||||
{secondaryBtn && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.3, ease: 'easeInOut' }}
|
||||
whileHover={{ scale: 1.06 }}
|
||||
>
|
||||
<ButtonAnimationWrapper>
|
||||
<Button variant="outlined" {...secondaryBtn} />
|
||||
</ButtonAnimationWrapper>
|
||||
</motion.div>
|
||||
)}
|
||||
{actionBtn && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.3, ease: 'easeInOut' }}
|
||||
whileHover={{ scale: 1.06 }}
|
||||
>
|
||||
<ButtonAnimationWrapper>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
startIcon={<SvgIcon name="tabler-sparkles" size={16} stroke={3} color="background.default" />}
|
||||
{...actionBtn}
|
||||
/>
|
||||
</ButtonAnimationWrapper>
|
||||
</motion.div>
|
||||
)}
|
||||
</Stack>
|
||||
</motion.div>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</ContainerWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
Feature20.propTypes = {
|
||||
heading: PropTypes.string,
|
||||
caption: PropTypes.string,
|
||||
image: PropTypes.any,
|
||||
features: PropTypes.array,
|
||||
actionBtn: PropTypes.any,
|
||||
secondaryBtn: PropTypes.any
|
||||
};
|
||||
@@ -0,0 +1,153 @@
|
||||
'use client';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
// @mui
|
||||
import Button from '@mui/material/Button';
|
||||
import Grid from '@mui/material/Grid';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import Box from '@mui/material/Box';
|
||||
|
||||
// @third-party
|
||||
import { motion } from 'motion/react';
|
||||
|
||||
// @project
|
||||
import ButtonAnimationWrapper from '@/components/ButtonAnimationWrapper';
|
||||
import { GraphicsCard, IconCard } from '@/components/cards';
|
||||
import ContainerWrapper from '@/components/ContainerWrapper';
|
||||
import GraphicsImage from '@/components/GraphicsImage';
|
||||
import Typeset from '@/components/Typeset';
|
||||
import SvgIcon from '@/components/SvgIcon';
|
||||
import { SECTION_COMMON_PY } from '@/utils/constant';
|
||||
|
||||
/*************************** FEATURE - 21 ***************************/
|
||||
|
||||
/**
|
||||
*
|
||||
* Demos:
|
||||
* - [Feature21](https://www.saasable.io/blocks/feature/feature21)
|
||||
*
|
||||
* API
|
||||
* - [Feature21 API](https://phoenixcoded.gitbook.io/saasable/ui-kit/development/components/feature/feature21#props-details)
|
||||
*/
|
||||
|
||||
export default function Feature21({ heading, caption, image, features, primaryBtn, secondaryBtn }) {
|
||||
const imagePadding = { xs: 3, sm: 4, md: 5 };
|
||||
const iconProps = { color: 'text.primary', stroke: 1 };
|
||||
|
||||
return (
|
||||
<ContainerWrapper sx={{ py: SECTION_COMMON_PY }}>
|
||||
<Stack sx={{ gap: { xs: 3, sm: 4 } }}>
|
||||
{(heading || caption) && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 5 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.3, delay: 0.3 }}
|
||||
>
|
||||
<Typeset {...{ heading, caption, stackProps: { sx: { textAlign: 'center' } } }} />
|
||||
</motion.div>
|
||||
)}
|
||||
<Stack sx={{ gap: 1.5 }}>
|
||||
{image && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{
|
||||
duration: 0.3,
|
||||
delay: 0.3
|
||||
}}
|
||||
>
|
||||
<GraphicsCard>
|
||||
<Box sx={{ pl: imagePadding, pt: imagePadding, height: { xs: 204, sm: 300, md: 360 } }}>
|
||||
<GraphicsImage
|
||||
image={image}
|
||||
sx={{
|
||||
height: 1,
|
||||
backgroundPositionX: 'left',
|
||||
backgroundPositionY: 'top',
|
||||
borderTopLeftRadius: { xs: 12 },
|
||||
borderBottomRightRadius: { xs: 20, sm: 32, md: 40 },
|
||||
border: '5px solid',
|
||||
borderColor: 'grey.200',
|
||||
borderBottom: 'none',
|
||||
borderRight: 'none'
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</GraphicsCard>
|
||||
</motion.div>
|
||||
)}
|
||||
<Grid container spacing={1.5}>
|
||||
{features.map((item, index) => (
|
||||
<Grid key={index} size={{ xs: 12, sm: 6, md: 3 }}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.3, delay: index * 0.2 }}
|
||||
style={{ height: '100%' }}
|
||||
>
|
||||
<IconCard
|
||||
icon={{ ...(typeof item.icon === 'string' ? { name: item.icon, ...iconProps } : { ...iconProps, ...item.icon }) }}
|
||||
title={item.title}
|
||||
stackProps={{ sx: { gap: 2, height: 1 } }}
|
||||
cardPadding={{ xs: 2, sm: 3 }}
|
||||
/>
|
||||
</motion.div>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
</Stack>
|
||||
{(primaryBtn || secondaryBtn) && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.3, delay: 0.4 }}
|
||||
>
|
||||
<Stack direction="row" sx={{ alignItems: 'center', justifyContent: 'center', gap: 1.5 }}>
|
||||
{secondaryBtn && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.3, ease: 'easeInOut' }}
|
||||
whileHover={{ scale: 1.06 }}
|
||||
>
|
||||
<ButtonAnimationWrapper>
|
||||
<Button variant="outlined" startIcon={<SvgIcon name="tabler-eye" size={16} stroke={3} />} {...secondaryBtn} />
|
||||
</ButtonAnimationWrapper>
|
||||
</motion.div>
|
||||
)}
|
||||
{primaryBtn && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.3, ease: 'easeInOut' }}
|
||||
whileHover={{ scale: 1.06 }}
|
||||
>
|
||||
<ButtonAnimationWrapper>
|
||||
<Button
|
||||
variant="contained"
|
||||
startIcon={<SvgIcon name="tabler-download" size={16} stroke={3} color="background.default" />}
|
||||
{...primaryBtn}
|
||||
/>
|
||||
</ButtonAnimationWrapper>
|
||||
</motion.div>
|
||||
)}
|
||||
</Stack>
|
||||
</motion.div>
|
||||
)}
|
||||
</Stack>
|
||||
</ContainerWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
Feature21.propTypes = {
|
||||
heading: PropTypes.string,
|
||||
caption: PropTypes.string,
|
||||
image: PropTypes.any,
|
||||
features: PropTypes.array,
|
||||
primaryBtn: PropTypes.any,
|
||||
secondaryBtn: PropTypes.any
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
export { default as Feature18 } from './Feature18';
|
||||
export { default as Feature20 } from './Feature20';
|
||||
export { default as Feature21 } from './Feature21';
|
||||
@@ -0,0 +1,205 @@
|
||||
'use client';
|
||||
|
||||
// @next
|
||||
import NextLink from 'next/link';
|
||||
|
||||
// @mui
|
||||
import Grid from '@mui/material/Grid';
|
||||
import Link from '@mui/material/Link';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import Typography from '@mui/material/Typography';
|
||||
|
||||
// @third-party
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
// @project
|
||||
import branding from '@/branding.json';
|
||||
import { GraphicsCard } from '@/components/cards';
|
||||
import ContainerWrapper from '@/components/ContainerWrapper';
|
||||
import { Copyright, FollowUS, Sitemap } from '@/components/footer';
|
||||
import LogoSection from '@/components/logo';
|
||||
import SvgIcon from '@/components/SvgIcon';
|
||||
|
||||
import { CopyrightType } from '@/enum';
|
||||
import { DOCS_URL, FREEBIES_URL } from '@/path';
|
||||
import { SECTION_COMMON_PY } from '@/utils/constant';
|
||||
|
||||
/*************************** FOOTER - 7 DATA ***************************/
|
||||
|
||||
/**
|
||||
*
|
||||
* Demos:
|
||||
* - [Footer7](https://www.saasable.io/blocks/footer/footer7)
|
||||
*/
|
||||
|
||||
const linkProps = { target: '_blank', rel: 'noopener noreferrer' };
|
||||
const data = [
|
||||
{
|
||||
id: 'resources',
|
||||
grid: { size: { xs: 12, sm: 'auto' } },
|
||||
title: 'Resources',
|
||||
menu: [
|
||||
{
|
||||
label: 'Freebies',
|
||||
link: { href: FREEBIES_URL, ...linkProps }
|
||||
},
|
||||
{
|
||||
label: 'Documentation',
|
||||
link: { href: DOCS_URL, ...linkProps }
|
||||
},
|
||||
{
|
||||
label: 'Blog',
|
||||
link: { href: 'https://blog.saasable.io/', ...linkProps }
|
||||
},
|
||||
{
|
||||
label: 'Refund Policy',
|
||||
link: { href: 'https://mui.com/store/customer-refund-policy/', ...linkProps }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'support',
|
||||
grid: { size: { xs: 6, sm: 'auto' } },
|
||||
title: 'Support',
|
||||
menu: [
|
||||
{
|
||||
label: 'Pricing',
|
||||
link: { href: 'https://mui.com/store/items/saasable-multipurpose-ui-kit-and-dashboard/', ...linkProps }
|
||||
},
|
||||
{
|
||||
label: 'FAQs',
|
||||
link: { href: 'https://phoenixcoded.gitbook.io/saasable/faq', ...linkProps }
|
||||
},
|
||||
{
|
||||
label: 'Support',
|
||||
link: { href: branding.company.socialLink.support, ...linkProps }
|
||||
},
|
||||
{
|
||||
label: 'License Terms',
|
||||
link: { href: 'https://mui.com/store/license/', ...linkProps }
|
||||
},
|
||||
{
|
||||
label: 'Discord',
|
||||
link: { href: branding.company.socialLink.discord, ...linkProps }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'company',
|
||||
grid: { size: { xs: 6, sm: 'auto' } },
|
||||
title: 'Company',
|
||||
menu: [
|
||||
{
|
||||
label: 'Why Phoenixcoded?',
|
||||
link: {
|
||||
href: 'https://blog.saasable.io/a-decade-of-expertise-the-phoenixcoded-story-and-why-you-should-trust-us',
|
||||
...linkProps
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'About',
|
||||
link: { href: 'https://saasable.io/about', ...linkProps }
|
||||
},
|
||||
{
|
||||
label: 'Contact Us',
|
||||
link: { href: '/contact', ...linkProps }
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
const iconProps = { color: 'text.secondary' };
|
||||
|
||||
const usefullLinks = [
|
||||
{
|
||||
icon: <SvgIcon name="tabler-brand-figma" {...iconProps} />,
|
||||
title: 'Figma Version 1.1.0',
|
||||
href: 'https://www.figma.com/community/file/1425095061180549847'
|
||||
},
|
||||
{
|
||||
icon: <SvgIcon name="tabler-route" {...iconProps} />,
|
||||
title: 'React Material UI v7',
|
||||
href: 'https://mui.com/material-ui/getting-started'
|
||||
},
|
||||
{
|
||||
icon: <SvgIcon name="tabler-sparkles" {...iconProps} />,
|
||||
title: 'Documentation',
|
||||
href: DOCS_URL
|
||||
}
|
||||
];
|
||||
|
||||
/*************************** FOOTER - 7 ***************************/
|
||||
|
||||
export default function Footer7() {
|
||||
const logoFollowContent = (
|
||||
<Stack sx={{ alignItems: 'flex-start', gap: { xs: 1.5, sm: 3 } }}>
|
||||
<LogoSection />
|
||||
<Typography variant="h6" sx={{ maxWidth: { sm: 280 }, mb: { xs: -1, sm: -2.5 } }}>
|
||||
{process.env.NEXT_PUBLIC_VERSION}
|
||||
</Typography>
|
||||
<Typography variant="body2" sx={{ maxWidth: { sm: 280 } }}>
|
||||
Explore the different versions of our {branding.brandName} template.
|
||||
</Typography>
|
||||
</Stack>
|
||||
);
|
||||
|
||||
return (
|
||||
<ContainerWrapper sx={{ py: SECTION_COMMON_PY }}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{
|
||||
duration: 0.5,
|
||||
delay: 0.4
|
||||
}}
|
||||
>
|
||||
<Stack id="footer-7" role="contentinfo" rel="noopener noreferrer" aria-label="Footer 7" sx={{ gap: { xs: 3, sm: 4, md: 5 } }}>
|
||||
<Grid container spacing={{ xs: 4, md: 3 }}>
|
||||
<Grid size={{ xs: 12, md: 6 }}>
|
||||
<Stack direction={{ sm: 'row', md: 'column' }} sx={{ gap: 3, justifyContent: 'space-between', height: 1 }}>
|
||||
{logoFollowContent}
|
||||
<Stack sx={{ gap: { xs: 2, sm: 2.5, md: 3 } }}>
|
||||
{usefullLinks.map((item, index) => (
|
||||
<Stack direction="row" sx={{ gap: 1, alignItems: 'center' }} key={index}>
|
||||
{item.icon}
|
||||
<Link
|
||||
component={NextLink}
|
||||
variant="body2"
|
||||
color="text.secondary"
|
||||
href={item.href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
aria-label="Usefull Links"
|
||||
>
|
||||
{item.title}
|
||||
</Link>
|
||||
</Stack>
|
||||
))}
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid size={{ xs: 12, md: 6 }}>
|
||||
<Sitemap list={data} isMenuDesign />
|
||||
</Grid>
|
||||
</Grid>
|
||||
<GraphicsCard sx={{ borderRadius: { xs: 6, sm: 8 } }}>
|
||||
<Stack
|
||||
direction={{ sm: 'row' }}
|
||||
sx={{
|
||||
alignItems: 'center',
|
||||
justifyContent: { xs: 'center', sm: 'space-between' },
|
||||
gap: 1.5,
|
||||
py: { xs: 2, sm: 1.5 },
|
||||
px: { xs: 2, sm: 3 }
|
||||
}}
|
||||
>
|
||||
<Copyright type={CopyrightType.TYPE3} />
|
||||
<FollowUS heading={false} color="grey.100" />
|
||||
</Stack>
|
||||
</GraphicsCard>
|
||||
</Stack>
|
||||
</motion.div>
|
||||
</ContainerWrapper>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { default as Footer7 } from './Footer7';
|
||||
@@ -0,0 +1,250 @@
|
||||
'use client';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
|
||||
// @mui
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import Button from '@mui/material/Button';
|
||||
import Chip from '@mui/material/Chip';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import Box from '@mui/material/Box';
|
||||
|
||||
// @third-party
|
||||
import { motion, useScroll, useTransform } from 'motion/react';
|
||||
|
||||
// @project
|
||||
import ButtonAnimationWrapper from '@/components/ButtonAnimationWrapper';
|
||||
import { GraphicsCard } from '@/components/cards';
|
||||
import ContainerWrapper from '@/components/ContainerWrapper';
|
||||
import GraphicsImage from '@/components/GraphicsImage';
|
||||
import SvgIcon from '@/components/SvgIcon';
|
||||
import { SECTION_COMMON_PY } from '@/utils/constant';
|
||||
import { getBackgroundDots } from '@/utils/getBackgroundDots';
|
||||
import { withAlpha } from '@/utils/colorUtils';
|
||||
|
||||
// @assets
|
||||
import Wave from '@/images/graphics/Wave';
|
||||
|
||||
// threshold - adjust threshold as needed
|
||||
const options = { root: null, rootMargin: '0px', threshold: 0.6 };
|
||||
|
||||
/*************************** HERO - 17 ***************************/
|
||||
|
||||
/**
|
||||
*
|
||||
* Demos:
|
||||
* - [Hero17](https://www.saasable.io/blocks/hero/hero17)
|
||||
*
|
||||
* API:
|
||||
* - [Hero17 API](https://phoenixcoded.gitbook.io/saasable/ui-kit/development/components/hero/hero17#props-details)
|
||||
*/
|
||||
|
||||
export default function Hero17({ chip, headLine, captionLine, primaryBtn, videoSrc, videoThumbnail, listData }) {
|
||||
const theme = useTheme();
|
||||
const boxRadius = { xs: 24, sm: 32, md: 40 };
|
||||
|
||||
const containerRef = useRef(null);
|
||||
|
||||
const { scrollYProgress } = useScroll({
|
||||
target: containerRef,
|
||||
offset: ['start start', 'end start']
|
||||
});
|
||||
|
||||
const scale = useTransform(scrollYProgress, [0, 0.1, 0.2, 0.4, 0.6], [0.9, 0.92, 0.94, 0.96, 1]);
|
||||
|
||||
const videoRef = useRef(null);
|
||||
const [isPlaying, setIsPlaying] = useState(false);
|
||||
|
||||
// Handle video play/pause based on intersection with the viewport
|
||||
useEffect(() => {
|
||||
const handleIntersection = (entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
if (videoRef.current && !isPlaying) {
|
||||
videoRef.current
|
||||
.play()
|
||||
.then(() => {
|
||||
setIsPlaying(true);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Autoplay was prevented:', error);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (videoRef.current && isPlaying) {
|
||||
videoRef.current.pause();
|
||||
setIsPlaying(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const observer = new IntersectionObserver(handleIntersection, options);
|
||||
const videoElement = videoRef.current;
|
||||
|
||||
if (videoElement) {
|
||||
observer.observe(videoElement);
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (videoElement) {
|
||||
observer.unobserve(videoElement);
|
||||
}
|
||||
};
|
||||
}, [isPlaying]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
sx={{
|
||||
height: { xs: 592, sm: 738, md: 878 },
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: 1,
|
||||
zIndex: -1,
|
||||
borderBottomLeftRadius: boxRadius,
|
||||
borderBottomRightRadius: boxRadius,
|
||||
...getBackgroundDots(theme.vars.palette.grey[300], 2, 35),
|
||||
bgcolor: 'grey.100'
|
||||
}}
|
||||
/>
|
||||
<ContainerWrapper sx={{ py: SECTION_COMMON_PY }}>
|
||||
<Box ref={containerRef}>
|
||||
<Box sx={{ pb: { xs: 3, sm: 4, md: 5 } }}>
|
||||
<Stack sx={{ alignItems: 'center', gap: 1.5 }}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, scale: 0.6 }}
|
||||
whileInView={{ opacity: 1, scale: [0.6, 1.15, 0.95, 1] }}
|
||||
animate={{
|
||||
boxShadow: [
|
||||
`0 0 0px ${withAlpha(theme.vars.palette.primary.dark, 0)}`,
|
||||
`0 0 20px ${withAlpha(theme.vars.palette.primary.main, 0.8)}`,
|
||||
`0 0 0px ${withAlpha(theme.vars.palette.primary.dark, 0)}`
|
||||
],
|
||||
borderRadius: '74px'
|
||||
}}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.6, delay: 0.8, ease: 'linear' }}
|
||||
>
|
||||
<Chip
|
||||
variant="outlined"
|
||||
label={chip.label}
|
||||
slotProps={{
|
||||
label: {
|
||||
sx: { py: 0.5, px: 1.5, ...(typeof chip.label === 'string' && { typography: 'caption', color: 'text.secondary' }) }
|
||||
}
|
||||
}}
|
||||
sx={{ bgcolor: 'grey.100' }}
|
||||
/>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, scale: 0.6 }}
|
||||
whileInView={{ opacity: 1, scale: 1 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.6, delay: 0.2, ease: 'linear' }}
|
||||
>
|
||||
<Typography variant="h1" align="center" sx={{ maxWidth: 800 }}>
|
||||
{headLine}
|
||||
</Typography>
|
||||
</motion.div>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 1, delay: 0.2, ease: [0.215, 0.61, 0.355, 1] }}
|
||||
>
|
||||
<Box sx={{ pt: 0.5, pb: 0.75 }}>
|
||||
<Wave />
|
||||
</Box>
|
||||
</motion.div>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 1, delay: 0.3, ease: [0.215, 0.61, 0.355, 1] }}
|
||||
>
|
||||
<Typography variant="h6" align="center" sx={{ color: 'text.secondary', maxWidth: 650 }}>
|
||||
{captionLine}
|
||||
</Typography>
|
||||
</motion.div>
|
||||
</Stack>
|
||||
<Stack sx={{ alignItems: 'center', gap: 2, mt: { xs: 3, sm: 4, md: 5 } }}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.3, ease: 'easeInOut' }}
|
||||
whileHover={{ scale: 1.06 }}
|
||||
>
|
||||
<ButtonAnimationWrapper>
|
||||
<Button
|
||||
color="primary"
|
||||
variant="contained"
|
||||
startIcon={<SvgIcon name="tabler-sparkles" size={16} stroke={3} color="background.default" />}
|
||||
{...primaryBtn}
|
||||
/>
|
||||
</ButtonAnimationWrapper>
|
||||
</motion.div>
|
||||
<Stack direction="row" sx={{ gap: 1, flexWrap: 'wrap', justifyContent: 'center' }}>
|
||||
{listData.map((item, index) => (
|
||||
<motion.div
|
||||
key={index}
|
||||
initial={{ opacity: 0, scale: 0.6 }}
|
||||
whileInView={{ opacity: 1, scale: 1 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.9, delay: index * 0.08, ease: 'linear' }}
|
||||
>
|
||||
<Chip
|
||||
label={item.title}
|
||||
variant="outlined"
|
||||
icon={<GraphicsImage image={item.image} sx={{ width: 16, height: 16 }} />}
|
||||
slotProps={{ label: { sx: { py: 0.75, px: 1, typography: 'caption2' } } }}
|
||||
sx={{ height: 32, px: 1, bgcolor: 'grey.100' }}
|
||||
/>
|
||||
</motion.div>
|
||||
))}
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Box>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, scale: 0.6 }}
|
||||
whileInView={{ opacity: 1, scale: 0.9 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.9, delay: 0.3 }}
|
||||
style={{ scale }}
|
||||
>
|
||||
<GraphicsCard sx={{ border: '5px solid', borderColor: 'grey.300' }}>
|
||||
<video
|
||||
playsInline
|
||||
ref={videoRef}
|
||||
width="100%"
|
||||
height="100%"
|
||||
style={{ display: 'flex', objectFit: 'cover' }}
|
||||
preload="metadata"
|
||||
autoPlay={false}
|
||||
loop={true}
|
||||
muted={true}
|
||||
poster={videoThumbnail}
|
||||
>
|
||||
<source src={videoSrc} type="video/mp4" />
|
||||
</video>
|
||||
</GraphicsCard>
|
||||
</motion.div>
|
||||
</Box>
|
||||
</ContainerWrapper>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Hero17.propTypes = {
|
||||
chip: PropTypes.object,
|
||||
headLine: PropTypes.string,
|
||||
captionLine: PropTypes.string,
|
||||
primaryBtn: PropTypes.any,
|
||||
videoSrc: PropTypes.string,
|
||||
videoThumbnail: PropTypes.string,
|
||||
listData: PropTypes.array
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user