aboutsummaryrefslogtreecommitdiffstats
path: root/src/views/Landing
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/views/Landing/FeaturesSection.jsx139
-rw-r--r--src/views/Landing/HomeHero.jsx186
-rw-r--r--src/views/Landing/Landing.jsx32
-rw-r--r--src/views/Landing/PricingSection.jsx179
4 files changed, 536 insertions, 0 deletions
diff --git a/src/views/Landing/FeaturesSection.jsx b/src/views/Landing/FeaturesSection.jsx
new file mode 100644
index 0000000..a7da1f0
--- /dev/null
+++ b/src/views/Landing/FeaturesSection.jsx
@@ -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
diff --git a/src/views/Landing/HomeHero.jsx b/src/views/Landing/HomeHero.jsx
new file mode 100644
index 0000000..a96374a
--- /dev/null
+++ b/src/views/Landing/HomeHero.jsx
@@ -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
diff --git a/src/views/Landing/Landing.jsx b/src/views/Landing/Landing.jsx
new file mode 100644
index 0000000..2041e42
--- /dev/null
+++ b/src/views/Landing/Landing.jsx
@@ -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
diff --git a/src/views/Landing/PricingSection.jsx b/src/views/Landing/PricingSection.jsx
new file mode 100644
index 0000000..634cf7d
--- /dev/null
+++ b/src/views/Landing/PricingSection.jsx
@@ -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}&nbsp;
+ </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