move to Donetick Org, First commit frontend
This commit is contained in:
commit
2657469964
105 changed files with 21572 additions and 0 deletions
139
src/views/Landing/FeaturesSection.jsx
Normal file
139
src/views/Landing/FeaturesSection.jsx
Normal file
|
@ -0,0 +1,139 @@
|
|||
import {
|
||||
AutoAwesomeMosaicOutlined,
|
||||
AutoAwesomeRounded,
|
||||
CodeRounded,
|
||||
GroupRounded,
|
||||
HistoryRounded,
|
||||
Webhook,
|
||||
} from '@mui/icons-material'
|
||||
import Card from '@mui/joy/Card'
|
||||
import Container from '@mui/joy/Container'
|
||||
import Typography from '@mui/joy/Typography'
|
||||
import { styled } from '@mui/system'
|
||||
|
||||
const FeatureIcon = styled('div')({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
backgroundColor: '#f0f0f0', // Adjust the background color as needed
|
||||
borderRadius: '50%',
|
||||
minWidth: '60px',
|
||||
height: '60px',
|
||||
marginRight: '16px',
|
||||
})
|
||||
|
||||
const CardData = [
|
||||
{
|
||||
title: 'Open Source & Transparent',
|
||||
headline: 'Built for the Community',
|
||||
description:
|
||||
'Donetick is a community-driven, open-source project. Contribute, customize, and make task management truly yours.',
|
||||
icon: CodeRounded,
|
||||
},
|
||||
{
|
||||
title: 'Circles: Your Task Hub',
|
||||
headline: 'Share & Conquer Together',
|
||||
description:
|
||||
'Create circles for your family, friends, or team. Easily share tasks and track progress within each group.',
|
||||
icon: GroupRounded,
|
||||
},
|
||||
{
|
||||
title: 'Track Your Progress',
|
||||
headline: "See Who's Done What",
|
||||
description:
|
||||
'View a history of task completion for each member of your circles. Celebrate successes and stay on top of your goals.',
|
||||
icon: HistoryRounded,
|
||||
},
|
||||
{
|
||||
title: 'Automated Chore Scheduling',
|
||||
headline: 'Fully Customizable Recurring Tasks',
|
||||
description:
|
||||
'Set up chores to repeat daily, weekly, or monthly. Donetick will automatically assign and track each task for you.',
|
||||
icon: AutoAwesomeMosaicOutlined,
|
||||
},
|
||||
{
|
||||
title: 'Automated Task Assignment',
|
||||
headline: 'Share Responsibilities Equally',
|
||||
description:
|
||||
'can automatically assigns tasks to each member of your circle. Randomly or based on past completion.',
|
||||
icon: AutoAwesomeRounded,
|
||||
},
|
||||
{
|
||||
title: 'Integrations & Webhooks',
|
||||
headline: 'API & 3rd Party Integrations',
|
||||
description:
|
||||
'Connect Donetick with your favorite apps and services. Trigger tasks based on events from other platforms.',
|
||||
icon: Webhook,
|
||||
},
|
||||
]
|
||||
|
||||
function Feature2({ icon: Icon, title, headline, description, index }) {
|
||||
return (
|
||||
<Card
|
||||
variant='plain'
|
||||
sx={{ textAlign: 'left', p: 2 }}
|
||||
data-aos-delay={100 * index}
|
||||
data-aos-anchor='[data-aos-id-features2-blocks]'
|
||||
data-aos='fade-up'
|
||||
>
|
||||
<div style={{ display: 'flex', alignItems: 'center' }}>
|
||||
<FeatureIcon>
|
||||
<Icon
|
||||
color='primary'
|
||||
style={{ Width: '30px', height: '30px' }}
|
||||
stroke={1.5}
|
||||
/>
|
||||
</FeatureIcon>
|
||||
<div>
|
||||
{/* Changes are within this div */}
|
||||
<Typography level='h4' mt={1} mb={0.5}>
|
||||
{title}
|
||||
</Typography>
|
||||
<Typography level='body-sm' color='neutral' lineHeight={1.4}>
|
||||
{headline}
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
<Typography level='body-md' color='neutral' lineHeight={1.6}>
|
||||
{description}
|
||||
</Typography>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
function FeaturesSection() {
|
||||
const features = CardData.map((feature, index) => (
|
||||
<Feature2
|
||||
icon={feature.icon}
|
||||
title={feature.title}
|
||||
headline={feature.headline}
|
||||
description={feature.description}
|
||||
index={index}
|
||||
key={index}
|
||||
/>
|
||||
))
|
||||
|
||||
return (
|
||||
<Container sx={{ textAlign: 'center' }}>
|
||||
<Typography level='h4' mt={2} mb={4}>
|
||||
Donetick
|
||||
</Typography>
|
||||
|
||||
<Container maxWidth={'lg'} sx={{ mb: 8 }}>
|
||||
<Typography level='body-md' color='neutral'>
|
||||
Navigate personal growth with genuine insights, thoughtful privacy,
|
||||
and actionable steps tailored just for you.
|
||||
</Typography>
|
||||
</Container>
|
||||
|
||||
<div
|
||||
className='align-center mt-8 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3'
|
||||
data-aos-id-features2-blocks
|
||||
>
|
||||
{features}
|
||||
</div>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
export default FeaturesSection
|
186
src/views/Landing/HomeHero.jsx
Normal file
186
src/views/Landing/HomeHero.jsx
Normal file
|
@ -0,0 +1,186 @@
|
|||
/* eslint-disable tailwindcss/no-custom-classname */
|
||||
// import { StyledButton } from '@/components/styled-button'
|
||||
import { Button } from '@mui/joy'
|
||||
import Typography from '@mui/joy/Typography'
|
||||
import Box from '@mui/material/Box'
|
||||
import Grid from '@mui/material/Grid'
|
||||
import React from 'react'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
|
||||
import Logo from '@/assets/logo.svg'
|
||||
import screenShotMyChore from '@/assets/screenshot-my-chore.png'
|
||||
import { GitHub } from '@mui/icons-material'
|
||||
|
||||
const HomeHero = () => {
|
||||
const navigate = useNavigate()
|
||||
const HERO_TEXT_THAT = [
|
||||
// 'Donetick simplifies the entire process, from scheduling and reminders to automatic task assignment and progress tracking.',
|
||||
// 'Donetick is the intuitive task and chore management app designed for groups. Take charge of shared responsibilities, automate your workflow, and achieve more together.',
|
||||
'An open-source, user-friendly app for managing tasks and chores, featuring customizable options to help you and others stay organized',
|
||||
]
|
||||
|
||||
const [heroTextIndex, setHeroTextIndex] = React.useState(0)
|
||||
|
||||
React.useEffect(() => {
|
||||
// const intervalId = setInterval(
|
||||
// () => setHeroTextIndex(index => index + 1),
|
||||
// 4000, // every 4 seconds
|
||||
// )
|
||||
// return () => clearTimeout(intervalId)
|
||||
}, [])
|
||||
|
||||
const Title = () => (
|
||||
<Box
|
||||
sx={{
|
||||
textAlign: 'center',
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<img src={Logo} width={'100px'} />
|
||||
<Typography level='h1' fontSize={58} fontWeight={800}>
|
||||
<span
|
||||
data-aos-delay={50 * 1}
|
||||
data-aos-anchor='[data-aos-id-hero]'
|
||||
data-aos='fade-up'
|
||||
>
|
||||
Done
|
||||
</span>
|
||||
<span
|
||||
data-aos-delay={100 * 3}
|
||||
data-aos-anchor='[data-aos-id-hero]'
|
||||
data-aos='fade-up'
|
||||
style={{
|
||||
color: '#06b6d4',
|
||||
}}
|
||||
>
|
||||
tick
|
||||
</span>
|
||||
</Typography>
|
||||
</Box>
|
||||
)
|
||||
|
||||
const Subtitle = () => (
|
||||
<Typography
|
||||
level='h2'
|
||||
fontWeight={500}
|
||||
textAlign={'center'}
|
||||
className='opacity-70'
|
||||
data-aos-delay={100 * 5}
|
||||
data-aos-anchor='[data-aos-id-hero]'
|
||||
data-aos='zoom-in'
|
||||
>
|
||||
Simplify Tasks & Chores, Together.
|
||||
</Typography>
|
||||
)
|
||||
|
||||
const CTAButton = () => (
|
||||
<Button
|
||||
data-aos-delay={100 * 2}
|
||||
data-aos-anchor='[data-aos-id-hero]'
|
||||
data-aos='fade-up'
|
||||
variant='solid'
|
||||
size='lg'
|
||||
sx={{
|
||||
py: 1.25,
|
||||
px: 5,
|
||||
fontSize: 20,
|
||||
mt: 2,
|
||||
borderWidth: 3,
|
||||
// boxShadow: '0px 0px 24px rgba(81, 230, 221, 0.5)',
|
||||
transition: 'all 0.20s',
|
||||
}}
|
||||
className='hover:scale-105'
|
||||
onClick={() => {
|
||||
// if the url is donetick.com then navigate to app.donetick.com/my/chores
|
||||
// else navigate to /my/chores
|
||||
if (window.location.hostname === 'donetick.com') {
|
||||
window.location.href = 'https://app.donetick.com/my/chores'
|
||||
} else {
|
||||
navigate('/my/chores')
|
||||
}
|
||||
}}
|
||||
>
|
||||
Get started
|
||||
</Button>
|
||||
)
|
||||
|
||||
return (
|
||||
// <Box
|
||||
// id='hero'
|
||||
// className='grid min-h-[90vh] w-full place-items-center px-4 py-12'
|
||||
// data-aos-id-hero
|
||||
// >
|
||||
<Grid container spacing={16} sx={{ py: 12 }}>
|
||||
<Grid item xs={12} md={7}>
|
||||
<Title />
|
||||
<div className='flex flex-col gap-6'>
|
||||
<Subtitle />
|
||||
|
||||
<Typography
|
||||
level='title-lg'
|
||||
textAlign={'center'}
|
||||
fontSize={28}
|
||||
// textColor={'#06b6d4'}
|
||||
color='primary'
|
||||
data-aos-delay={100 * 1}
|
||||
data-aos-anchor='[data-aos-id-hero]'
|
||||
data-aos='fade-up'
|
||||
>
|
||||
{`"${HERO_TEXT_THAT[heroTextIndex % HERO_TEXT_THAT.length]}"`}
|
||||
</Typography>
|
||||
|
||||
<Box className='flex w-full justify-center'>
|
||||
<CTAButton />
|
||||
<Button
|
||||
data-aos-delay={100 * 2.5}
|
||||
data-aos-anchor='[data-aos-id-hero]'
|
||||
data-aos='fade-up'
|
||||
variant='soft'
|
||||
size='lg'
|
||||
sx={{
|
||||
py: 1.25,
|
||||
px: 5,
|
||||
ml: 2,
|
||||
fontSize: 20,
|
||||
mt: 2,
|
||||
borderWidth: 3,
|
||||
// boxShadow: '0px 0px 24px rgba(81, 230, 221, 0.5)',
|
||||
transition: 'all 0.20s',
|
||||
}}
|
||||
className='hover:scale-105'
|
||||
onClick={() => {
|
||||
// new window open to https://github.com/Donetick:
|
||||
window.open('https://github.com/donetick', '_blank')
|
||||
}}
|
||||
startDecorator={<GitHub />}
|
||||
>
|
||||
Github
|
||||
</Button>
|
||||
</Box>
|
||||
</div>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} md={5}>
|
||||
<div className='flex justify-center'>
|
||||
<img
|
||||
src={screenShotMyChore}
|
||||
width={'100%'}
|
||||
style={{
|
||||
maxWidth: 300,
|
||||
}}
|
||||
height={'auto'}
|
||||
alt='Hero img'
|
||||
data-aos-delay={100 * 2}
|
||||
data-aos-anchor='[data-aos-id-hero]'
|
||||
data-aos='fade-left'
|
||||
/>
|
||||
</div>
|
||||
</Grid>
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
|
||||
export default HomeHero
|
32
src/views/Landing/Landing.jsx
Normal file
32
src/views/Landing/Landing.jsx
Normal file
|
@ -0,0 +1,32 @@
|
|||
import { Container } from '@mui/joy'
|
||||
import AOS from 'aos'
|
||||
import 'aos/dist/aos.css'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import FeaturesSection from './FeaturesSection'
|
||||
import HomeHero from './HomeHero'
|
||||
import PricingSection from './PricingSection'
|
||||
const Landing = () => {
|
||||
const Navigate = useNavigate()
|
||||
const getCurrentUser = () => {
|
||||
return JSON.parse(localStorage.getItem('user'))
|
||||
}
|
||||
const [users, setUsers] = useState([])
|
||||
const [currentUser, setCurrentUser] = useState(getCurrentUser())
|
||||
|
||||
useEffect(() => {
|
||||
AOS.init({
|
||||
once: false, // whether animation should happen only once - while scrolling down
|
||||
})
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<Container className='flex h-full items-center justify-center'>
|
||||
<HomeHero />
|
||||
<FeaturesSection />
|
||||
<PricingSection />
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
export default Landing
|
179
src/views/Landing/PricingSection.jsx
Normal file
179
src/views/Landing/PricingSection.jsx
Normal file
|
@ -0,0 +1,179 @@
|
|||
/* eslint-disable react/jsx-key */
|
||||
import { CheckRounded } from '@mui/icons-material'
|
||||
import { Box, Button, Card, Container, Typography } from '@mui/joy'
|
||||
import React from 'react'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
|
||||
const PricingSection = () => {
|
||||
const navigate = useNavigate()
|
||||
const FEATURES_FREE = [
|
||||
['Create Tasks and Chores', <CheckRounded color='primary' />],
|
||||
['Limited Task History', <CheckRounded color='primary' />],
|
||||
['Circle up to two members', <CheckRounded color='primary' />],
|
||||
]
|
||||
const FEATURES_PREMIUM = [
|
||||
['All Basic Features', <CheckRounded color='primary' />],
|
||||
['Hosted on DoneTick servers', <CheckRounded color='primary' />],
|
||||
['Up to 8 Circle Members', <CheckRounded color='primary' />],
|
||||
[
|
||||
'Notification through Telegram (Discord coming soon)',
|
||||
<CheckRounded color='primary' />,
|
||||
],
|
||||
['Unlimited History', <CheckRounded color='primary' />],
|
||||
[
|
||||
'All circle members get the same features as the owner',
|
||||
<CheckRounded color='primary' />,
|
||||
],
|
||||
]
|
||||
const FEATURES_YEARLY = [
|
||||
// ['All Basic Features', <CheckRounded color='primary' />],
|
||||
// ['Up to 8 Circle Members', <CheckRounded color='primary' />],
|
||||
['Notification through Telegram bot', <CheckRounded color='primary' />],
|
||||
['Custom Webhook/API Integration', <CheckRounded color='primary' />],
|
||||
['Unlimited History', <CheckRounded color='primary' />],
|
||||
|
||||
['Priority Support', <CheckRounded color='primary' />],
|
||||
]
|
||||
const PRICEITEMS = [
|
||||
{
|
||||
title: 'Basic',
|
||||
description:
|
||||
'Hosted on Donetick servers, supports up to 2 circle members and includes all the features of the free plan.',
|
||||
price: 0,
|
||||
previousPrice: 0,
|
||||
interval: 'month',
|
||||
discount: false,
|
||||
features: FEATURES_FREE,
|
||||
},
|
||||
|
||||
{
|
||||
title: 'Plus',
|
||||
description:
|
||||
// 'Supports up to 8 circle members and includes all the features of the Basic plan.',
|
||||
'Hosted on Donetick servers, supports up to 8 circle members and includes all the features of the Basic plan.',
|
||||
price: 30.0,
|
||||
// previousPrice: 76.89,
|
||||
interval: 'year',
|
||||
// discount: true,
|
||||
features: FEATURES_YEARLY,
|
||||
},
|
||||
]
|
||||
return (
|
||||
<Container
|
||||
sx={{ textAlign: 'center', mb: 2 }}
|
||||
maxWidth={'lg'}
|
||||
id='pricing-tiers'
|
||||
>
|
||||
<Typography level='h4' mt={2} mb={2}>
|
||||
Pricing
|
||||
</Typography>
|
||||
|
||||
<Container maxWidth={'sm'} sx={{ mb: 8 }}>
|
||||
<Typography level='body-md' color='neutral'>
|
||||
Choose the plan that works best for you.
|
||||
</Typography>
|
||||
</Container>
|
||||
|
||||
<div
|
||||
className='mt-8 grid grid-cols-1 gap-2 sm:grid-cols-1 lg:grid-cols-2'
|
||||
data-aos-id-pricing
|
||||
>
|
||||
{PRICEITEMS.map((pi, index) => (
|
||||
<Card
|
||||
key={index}
|
||||
data-aos-delay={50 * (1 + index)}
|
||||
data-aos-anchor='[data-aos-id-pricing]'
|
||||
data-aos='fade-up'
|
||||
className='hover:bg-white dark:hover:bg-teal-900'
|
||||
sx={{
|
||||
textAlign: 'center',
|
||||
p: 5,
|
||||
minHeight: 400,
|
||||
// maxWidth: 400,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'space-between',
|
||||
// when top reach the top change the background color:
|
||||
'&:hover': {
|
||||
// backgroundColor: '#FFFFFF',
|
||||
boxShadow: '0px 0px 20px rgba(0, 0, 0, 0.1)',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
display='flex'
|
||||
flexDirection='column'
|
||||
justifyContent='flex-start' // Updated property
|
||||
alignItems='center'
|
||||
>
|
||||
<Typography level='h2'>{pi.title}</Typography>
|
||||
<Typography level='body-md'>{pi.description}</Typography>
|
||||
</Box>
|
||||
<Box
|
||||
display='flex'
|
||||
flexDirection='column'
|
||||
justifyContent='center'
|
||||
alignItems='center'
|
||||
>
|
||||
<Box
|
||||
display='flex'
|
||||
flexDirection='row'
|
||||
alignItems='baseline'
|
||||
sx={{ my: 4 }}
|
||||
>
|
||||
{pi.discount && (
|
||||
<Typography
|
||||
level='h3'
|
||||
component='span'
|
||||
sx={{ textDecoration: 'line-through', opacity: 0.5 }}
|
||||
>
|
||||
${pi.previousPrice}
|
||||
</Typography>
|
||||
)}
|
||||
<Typography level='h2' component='span'>
|
||||
${pi.price}
|
||||
</Typography>
|
||||
<Typography level='body-md' component='span'>
|
||||
/ {pi.interval}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Typography level='title-md'>Features</Typography>
|
||||
{pi.features.map(feature => (
|
||||
<Typography
|
||||
startDecorator={feature[1]}
|
||||
level='body-md'
|
||||
color='neutral'
|
||||
lineHeight={1.6}
|
||||
>
|
||||
{feature[0]}
|
||||
</Typography>
|
||||
))}
|
||||
|
||||
{/* Here start the test */}
|
||||
<div style={{ marginTop: 'auto' }}>
|
||||
<Button
|
||||
sx={{ mt: 5 }}
|
||||
onClick={() => {
|
||||
navigate('/settings#account')
|
||||
}}
|
||||
>
|
||||
Get Started
|
||||
</Button>
|
||||
<Typography
|
||||
level='body-md'
|
||||
color='neutral'
|
||||
lineHeight={1.6}
|
||||
></Typography>
|
||||
</div>
|
||||
</Box>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Here start the test */}
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
export default PricingSection
|
Loading…
Add table
Add a link
Reference in a new issue