First Commit
This commit is contained in:
@@ -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';
|
||||
Reference in New Issue
Block a user