- Add Cookie Permission component

- Add Filter button instead of chips in mychores view
- show except days instead of showing evenything when days.length>4
This commit is contained in:
Mo Tarbin 2024-09-06 01:22:55 -04:00
commit 2d2cf6d378
18 changed files with 508 additions and 175 deletions

1
.env
View file

@ -1,2 +1,3 @@
VITE_APP_API_URL=http://localhost:2021
VITE_IS_LANDING_DEFAULT=false
VITE_OPENREPLAY_PROJECT_KEY=

50
package-lock.json generated
View file

@ -1,18 +1,19 @@
{
"name": "fe-template",
"version": "0.1.61",
"name": "donetick",
"version": "0.1.72",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "fe-template",
"version": "0.1.61",
"name": "donetick",
"version": "0.1.72",
"dependencies": {
"@emotion/react": "^11.11.3",
"@emotion/styled": "^11.11.0",
"@mui/icons-material": "^5.15.2",
"@mui/joy": "^5.0.0-beta.20",
"@mui/material": "^5.15.2",
"@openreplay/tracker": "^14.0.4",
"@tanstack/react-query": "^5.17.0",
"aos": "^2.3.4",
"dotenv": "^16.4.5",
@ -2481,6 +2482,12 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@medv/finder": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/@medv/finder/-/finder-3.2.0.tgz",
"integrity": "sha512-JmU7JIBwyL8RAzefvzALT4sP2M0biGk8i2invAgpQmma/QgfsaqoHIvJ7S0YC8n9hUVG8X3Leul2nGa06PvhbQ==",
"license": "MIT"
},
"node_modules/@mui/base": {
"version": "5.0.0-beta.29",
"resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.29.tgz",
@ -2839,6 +2846,20 @@
"node": ">= 8"
}
},
"node_modules/@openreplay/tracker": {
"version": "14.0.4",
"resolved": "https://registry.npmjs.org/@openreplay/tracker/-/tracker-14.0.4.tgz",
"integrity": "sha512-Mz+MPw9EYbH6tpZ3d1u2yLJsY+MaoBmJX0gQt4HtvGlwJnd7xJvF37xHY8/e3N1Tc7zENsrf7xcpiZXabNKoVQ==",
"license": "MIT",
"dependencies": {
"@medv/finder": "^3.2.0",
"error-stack-parser": "^2.0.6",
"fflate": "^0.8.2"
},
"engines": {
"node": ">=14.0"
}
},
"node_modules/@pkgjs/parseargs": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
@ -4747,6 +4768,15 @@
"is-arrayish": "^0.2.1"
}
},
"node_modules/error-stack-parser": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz",
"integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==",
"license": "MIT",
"dependencies": {
"stackframe": "^1.3.4"
}
},
"node_modules/es-abstract": {
"version": "1.22.3",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz",
@ -5327,6 +5357,12 @@
"reusify": "^1.0.4"
}
},
"node_modules/fflate": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz",
"integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==",
"license": "MIT"
},
"node_modules/file-entry-cache": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
@ -8064,6 +8100,12 @@
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
"deprecated": "Please use @jridgewell/sourcemap-codec instead"
},
"node_modules/stackframe": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz",
"integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==",
"license": "MIT"
},
"node_modules/streamx": {
"version": "2.18.0",
"resolved": "https://registry.npmjs.org/streamx/-/streamx-2.18.0.tgz",

View file

@ -1,7 +1,7 @@
{
"name": "donetick",
"private": true,
"version": "0.1.65",
"version": "0.1.74",
"type": "module",
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
@ -25,6 +25,7 @@
"@mui/icons-material": "^5.15.2",
"@mui/joy": "^5.0.0-beta.20",
"@mui/material": "^5.15.2",
"@openreplay/tracker": "^14.0.4",
"@tanstack/react-query": "^5.17.0",
"aos": "^2.3.4",
"dotenv": "^16.4.5",

View file

@ -1,5 +1,6 @@
import NavBar from '@/views/components/NavBar'
import { Button, Snackbar, Typography, useColorScheme } from '@mui/joy'
import Tracker from '@openreplay/tracker'
import { useEffect, useState } from 'react'
import { Outlet } from 'react-router-dom'
import { useRegisterSW } from 'virtual:pwa-register/react'
@ -19,6 +20,8 @@ const remove = className => {
const intervalMS = 5 * 60 * 1000 // 5 minutes
function App() {
startOpenReplay()
const { mode, systemMode } = useColorScheme()
const [userProfile, setUserProfile] = useState(null)
const [showUpdateSnackbar, setShowUpdateSnackbar] = useState(true)
@ -115,4 +118,11 @@ function App() {
)
}
const startOpenReplay = () => {
if (!import.meta.env.VITE_OPENREPLAY_PROJECT_KEY) return
const tracker = new Tracker({
projectKey: import.meta.env.VITE_OPENREPLAY_PROJECT_KEY,
})
tracker.start()
}
export default App

View file

@ -83,6 +83,15 @@ const SkipChore = id => {
body: JSON.stringify({}),
})
}
const UpdateChoreAssignee = (id, assignee) => {
return Fetch(`${API_URL}/chores/${id}/assignee`, {
method: 'PUT',
headers: HEADERS(),
body: JSON.stringify({ assignee:Number(assignee) }),
})
}
const CreateChore = chore => {
return Fetch(`${API_URL}/chores/`, {
method: 'POST',
@ -306,4 +315,5 @@ export {
UpdateChoreHistory,
UpdateThingState,
UpdateUserDetails,
UpdateChoreAssignee,
}

View file

@ -7,6 +7,7 @@ import {
FormHelperText,
Input,
Sheet,
Snackbar,
Typography,
} from '@mui/joy'
import React from 'react'
@ -25,6 +26,8 @@ const SignupView = () => {
const [emailError, setEmailError] = React.useState('')
const [displayNameError, setDisplayNameError] = React.useState('')
const [error, setError] = React.useState(null)
const [snackbarOpen, setSnackbarOpen] = React.useState(false)
const [snackbarMessage, setSnackbarMessage] = React.useState('')
const handleLogin = (username, password) => {
login(username, password).then(response => {
if (response.status === 200) {
@ -39,6 +42,7 @@ const SignupView = () => {
})
} else {
console.log('Login failed', response)
// Navigate('/login')
}
})
@ -101,7 +105,10 @@ const SignupView = () => {
handleLogin(username, password)
} else {
console.log('Signup failed')
setError('Signup failed')
response.json().then(res => {
setError(res.error)
}
)
}
})
}
@ -256,6 +263,14 @@ const SignupView = () => {
</Button>
</Sheet>
</Box>
<Snackbar
open={error !== null}
onClose={() => setError(null)}
autoHideDuration={5000}
message={error}
>
{error}
</Snackbar>
</Container>
)
}

View file

@ -3,6 +3,7 @@ import {
CancelScheduleSend,
Check,
Checklist,
Edit,
History,
PeopleAlt,
Person,
@ -258,7 +259,7 @@ const ChoreView = () => {
>
<Grid container spacing={1}>
{infoCards.map((detail, index) => (
<Grid item xs={4} key={index}>
<Grid item xs={6} key={index}>
{/* divider between the list items: */}
<ListItem key={index}>
@ -411,20 +412,7 @@ const ChoreView = () => {
}}
/>
)}
<Button
fullWidth
size='lg'
onClick={handleTaskCompletion}
disabled={isPendingCompletion}
color={isPendingCompletion ? 'danger' : 'success'}
startDecorator={<Check />}
>
<Box>Mark as done</Box>
</Button>
<Divider sx={{ my: 0.5 }}>or</Divider>
<Box
<Box
sx={{
display: 'flex',
flexDirection: 'row',
@ -433,6 +421,22 @@ const ChoreView = () => {
justifyContent: 'center',
}}
>
<Button
fullWidth
size='lg'
onClick={handleTaskCompletion}
disabled={isPendingCompletion}
color={isPendingCompletion ? 'danger' : 'success'}
startDecorator={<Check />}
sx={
{
flex: 4,
}
}
>
<Box>Mark as done</Box>
</Button>
<Button
fullWidth
size='lg'
@ -454,9 +458,26 @@ const ChoreView = () => {
})
}}
startDecorator={<SwitchAccessShortcut />}
sx={
{
flex: 1,
}
}
>
<Box>Skip</Box>
</Button>
</Box>
<Divider sx={{ my: 0.5 }}>More</Divider>
<Box
sx={{
display: 'flex',
flexDirection: 'row',
gap: 1,
alignContent: 'center',
justifyContent: 'center',
}}
>
<Button
startDecorator={<History />}
size='lg'
@ -469,8 +490,21 @@ const ChoreView = () => {
>
History
</Button>
</Box>
<Button
startDecorator={<Edit />}
size='lg'
color='primary'
variant='outlined'
fullWidth
onClick={() => {
navigate(`/chores/${choreId}/edit`)
}}
>
Edit
</Button>
</Box>
<Snackbar
open={isPendingCompletion}
endDecorator={

View file

@ -3,7 +3,6 @@ import {
Check,
Delete,
Edit,
HowToReg,
KeyboardDoubleArrowUp,
LocalOffer,
ManageSearch,
@ -39,7 +38,11 @@ import moment from 'moment'
import React, { useEffect } from 'react'
import { useNavigate } from 'react-router-dom'
import { API_URL } from '../../Config'
import { MarkChoreComplete, SkipChore } from '../../utils/Fetcher'
import {
MarkChoreComplete,
SkipChore,
UpdateChoreAssignee,
} from '../../utils/Fetcher'
import { Fetch } from '../../utils/TokenManager'
import ConfirmationModal from '../Modals/Inputs/ConfirmationModal'
import DateModal from '../Modals/Inputs/DateModal'
@ -219,7 +222,14 @@ const ChoreCard = ({
})
}
const handleAssigneChange = assigneeId => {
// TODO: Implement assignee change
UpdateChoreAssignee(chore.id, assigneeId).then(response => {
if (response.ok) {
response.json().then(data => {
const newChore = data.res
onChoreUpdate(newChore, 'assigned')
})
}
})
}
const handleCompleteWithNote = note => {
Fetch(`${API_URL}/chores/${chore.id}/do`, {
@ -305,8 +315,28 @@ const ChoreCard = ({
return 'Yearly'
} else if (chore.frequencyType === 'days_of_the_week') {
let days = JSON.parse(chore.frequencyMetadata).days
days = days.map(d => moment().day(d).format('ddd'))
return days.join(', ')
if (days.length > 4) {
const allDays = [
'Sunday',
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday',
]
const selectedDays = days.map(d => moment().day(d).format('dddd'))
const notSelectedDay = allDays.filter(
day => !selectedDays.includes(day),
)
const notSelectedShortdays = notSelectedDay.map(d =>
moment().day(d).format('ddd'),
)
return `Daily except ${notSelectedShortdays.join(', ')}`
} else {
days = days.map(d => moment().day(d).format('ddd'))
return days.join(', ')
}
} else if (chore.frequencyType === 'day_of_the_month') {
let freqData = JSON.parse(chore.frequencyMetadata)
const months = freqData.months.map(m => moment().month(m).format('MMM'))
@ -547,10 +577,6 @@ const ChoreCard = ({
<RecordVoiceOver />
Delegate to someone else
</MenuItem>
<MenuItem>
<HowToReg />
Complete as someone else
</MenuItem>
<Divider />
<MenuItem
onClick={() => {
@ -620,10 +646,13 @@ const ChoreCard = ({
options={performers}
displayKey='displayName'
title={`Delegate to someone else`}
placeholder={'Select a performer'}
onClose={() => {
setIsChangeAssigneeModalOpen(false)
}}
onSave={handleAssigneChange}
onSave={selected => {
handleAssigneChange(selected.id)
}}
/>
<ConfirmationModal config={confirmModelConfig} />
<TextModal

View file

@ -1,13 +1,17 @@
import { Add, CancelRounded, EditCalendar } from '@mui/icons-material'
import {
Badge,
Add,
CancelRounded,
EditCalendar,
FilterAlt,
FilterAltOff,
} from '@mui/icons-material'
import {
Box,
Checkbox,
Chip,
Container,
IconButton,
Input,
List,
ListItem,
Menu,
MenuItem,
Snackbar,
@ -192,95 +196,27 @@ const MyChores = () => {
My Chores
</Typography> */}
{/* <Sheet> */}
<List
orientation='horizontal'
wrap
{/* Search box to filter */}
<Box
sx={{
'--List-gap': '8px',
'--ListItem-radius': '20px',
'--ListItem-minHeight': '32px',
'--ListItem-gap': '4px',
mt: 0.2,
display: 'flex',
justifyContent: 'space-between',
alignContent: 'center',
alignItems: 'center',
gap: 1,
}}
>
{['All', 'Overdue', 'Due today', 'Due in week'].map(filter => (
<Badge
key={filter}
anchorOrigin={{
vertical: 'top',
horizontal: 'right',
}}
variant='outlined'
color={selectedFilter === filter ? 'primary' : 'neutral'}
badgeContent={FILTERS[filter](chores).length}
badgeInset={'5px'}
>
<ListItem key={filter}>
<Checkbox
key={'checkbox' + filter}
label={filter}
onClick={() => handleSelectedFilter(filter)}
checked={filter === selectedFilter}
disableIcon
overlay
size='sm'
/>
</ListItem>
</Badge>
))}
<ListItem onClick={handleFilterMenuOpen}>
<Checkbox key='checkboxAll' label='⋮' disableIcon overlay size='lg' />
</ListItem>
<Menu
ref={menuRef}
anchorEl={anchorEl}
open={Boolean(anchorEl)}
onClose={handleFilterMenuClose}
>
<MenuItem
onClick={() => {
setFilteredChores(
FILTERS['Assigned To Me'](chores, userProfile.id),
)
setSelectedFilter('Assigned To Me')
handleFilterMenuClose()
}}
>
Assigned to me
</MenuItem>
<MenuItem
onClick={() => {
setFilteredChores(
FILTERS['Created By Me'](chores, userProfile.id),
)
setSelectedFilter('Created By Me')
handleFilterMenuClose()
}}
>
Created by me
</MenuItem>
<MenuItem
onClick={() => {
setFilteredChores(FILTERS['No Due Date'](chores, userProfile.id))
setSelectedFilter('No Due Date')
handleFilterMenuClose()
}}
>
No Due Date
</MenuItem>
</Menu>
</List>
{/* Search box to filter */}
<Box>
<Input
placeholder='Search'
value={searchTerm}
fullWidth
sx={{
mt: 1,
mb: 1,
borderRadius: 20,
borderRadius: 24,
// border: '1px solid',
height: 24,
borderColor: 'text.disabled',
padding: 1,
}}
@ -296,6 +232,73 @@ const MyChores = () => {
)
}
/>
<IconButton
onClick={handleFilterMenuOpen}
variant='outlined'
color={
selectedFilter && selectedFilter != 'All' ? 'primary' : 'neutral'
}
size='sm'
sx={{
height: 24,
borderRadius: 24,
}}
>
{selectedFilter && selectedFilter != 'All' ? (
<FilterAltOff />
) : (
<FilterAlt />
)}
</IconButton>
<List
orientation='horizontal'
wrap
sx={{
// '--List-gap': '8px',
// '--ListItem-radius': '20px',
// '--ListItem-minHeight': '32px',
// '--ListItem-gap': '4px',
mt: 0.2,
}}
>
{/* <Checkbox
key='checkboxAll'
label=''
disableIcon
overlay
size='sm'
/> */}
<Menu
ref={menuRef}
anchorEl={anchorEl}
open={Boolean(anchorEl)}
onClose={handleFilterMenuClose}
>
{Object.keys(FILTERS).map(filter => (
<MenuItem
key={filter}
onClick={() => {
const filterFunction = FILTERS[filter]
const filteredChores =
filterFunction.length === 2
? filterFunction(chores, userProfile.id)
: filterFunction(chores)
setFilteredChores(filteredChores)
setSelectedFilter(filter)
handleFilterMenuClose()
}}
>
{filter}
<Chip color={selectedFilter === filter ? 'primary' : 'neutral'}>
{FILTERS[filter].length === 2
? FILTERS[filter](chores, userProfile.id).length
: FILTERS[filter](chores).length}
</Chip>
</MenuItem>
))}
</Menu>
</List>
</Box>
{/* </Sheet> */}

View file

@ -0,0 +1,40 @@
import { Button, Snackbar } from '@mui/joy'
import Cookies from 'js-cookie'
import { useEffect, useState } from 'react'
const CookiePermissionSnackbar = () => {
useEffect(() => {
const cookiePermission = Cookies.get('cookies_permission')
if (cookiePermission !== 'true') {
setOpen(true)
}
}, [])
const [open, setOpen] = useState(false)
const handleClose = () => {
Cookies.set('cookies_permission', 'true')
setOpen(false)
}
return (
<Snackbar
open={open}
anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
onClose={(event, reason) => {
if (reason === 'clickaway') {
return
}
// Cookies.set('cookies_permission', 'true')
handleClose()
}}
>
We use cookies to ensure you get the best experience on our website.
<Button variant='soft' onClick={handleClose}>
Accept
</Button>
</Snackbar>
)
}
export default CookiePermissionSnackbar

View file

@ -110,18 +110,6 @@ function FeaturesSection() {
return (
<Container sx={{ textAlign: 'center' }}>
<Typography level='h4' mt={2} mb={4}>
Donetick is under development
</Typography>
<Container maxWidth={'lg'} sx={{ mb: 8 }}>
<Typography level='body-md' color='neutral'>
Donetick is beta software. and is still under development. thing may
change, break, or disappear at any time. Please use it at your own
risk and discretion. I will do my best to keep the service running
</Typography>
</Container>
<Typography level='h4' mt={2} mb={4}>
Why Donetick?
</Typography>

View file

@ -4,6 +4,7 @@ import Box from '@mui/joy/Box'
import Link from '@mui/joy/Link'
import Typography from '@mui/joy/Typography'
import * as React from 'react'
import { version } from '../../../package.json'
function Footer() {
return (
@ -47,17 +48,6 @@ function Footer() {
tick
</span>
</Typography>
<span
style={{
fontSize: 12,
fontWeight: 700,
position: 'relative',
top: 12,
right: 45,
}}
>
Beta
</span>
</Box>
</Box>
<Box>
@ -65,11 +55,11 @@ function Footer() {
Github
</Typography>
<Link
href='https://github.com/donetick/core'
href='https://github.com/donetick/donetick'
level='body2'
sx={{ display: 'block' }}
>
Core(Backend)
Donetick
</Link>
<Link
href='https://github.com/donetick/frontend'
@ -86,11 +76,18 @@ function Footer() {
Home Assistant Addon
</Link>
<Link
href='https://github.com/orgs/Donetick/packages'
href='https://github.com/orgs/donetick/packages'
level='body2'
sx={{ display: 'block' }}
>
Packages
Docker Images
</Link>
<Link
href='https://github.com/donetick/donetick/releases'
level='body2'
sx={{ display: 'block' }}
>
Releases
</Link>
</Box>
<Box>
@ -107,6 +104,9 @@ function Footer() {
<Link disabled={true} level='body2' sx={{ display: 'block' }}>
Changelog(soon)
</Link>
<Link disabled={true} level='body2' sx={{ display: 'block' }}>
V{version}
</Link>
</Box>
{/* <Box>
<Typography level='body2' fontWeight='bold' mb={1}>

View file

@ -0,0 +1,171 @@
import {
AddHome,
AutoAwesome,
Cloud,
GitHub,
InstallMobile,
Storage,
} from '@mui/icons-material'
import { Box, Button, Card, Grid, styled, Typography } from '@mui/joy'
import { useNavigate } from 'react-router-dom'
const IconContainer = styled('div')({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
borderRadius: '50%',
minWidth: '60px',
height: '60px',
marginRight: '16px',
})
const ButtonContainer = styled('div')({
display: 'flex',
justifyContent: 'center',
marginTop: 'auto',
})
function StartOptionCard({ icon: Icon, title, description, button, index }) {
return (
<Card
variant='plain'
sx={{
p: 2,
display: 'flex',
minHeight: '300px',
py: 4,
flexDirection: 'column',
justifyContent: 'space-between',
}}
data-aos-delay={100 * index}
data-aos-anchor='[data-aos-id-getting-started-container]'
data-aos='fade-up'
>
{/* Changes are within this div */}
<Box
sx={{
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
}}
>
<IconContainer>{Icon}</IconContainer>
<Typography level='h4' textAlign={'center'}>
{title}
</Typography>
</Box>
<Typography level='body-md' color='neutral' lineHeight={1.6}>
{description}
</Typography>
<ButtonContainer>{button}</ButtonContainer>
</Card>
)
}
const GettingStarted = () => {
const navigate = useNavigate()
const information = [
{
title: 'Donetick Web',
icon: <Cloud style={{ fontSize: '48px' }} />,
description:
'The easiest way! just create account and start using DoneTick',
button: (
<Button
size='lg'
fullWidth
startDecorator={<AutoAwesome />}
onClick={() => {
navigate('/my/chores')
}}
>
Start Now!
</Button>
),
},
{
title: 'Selfhosted',
icon: <Storage style={{ fontSize: '48px' }} />,
description: 'Download the binary and manage your own DoneTick instance',
button: (
<Button
size='lg'
fullWidth
startDecorator={<GitHub />}
onClick={() => {
window.open(
'https://github.com/donetick/donetick/releases',
'_blank',
)
}}
>
Github Releases
</Button>
),
},
{
title: 'Hassio Addon',
icon: <AddHome style={{ fontSize: '48px' }} />,
description:
'have Home Assistant? install DoneTick as a Home Assistant Addon with single click',
button: (
<Button
size='lg'
fullWidth
startDecorator={<InstallMobile />}
onClick={() => {
window.open(
'https://my.home-assistant.io/redirect/supervisor_add_addon_repository/?repository_url=https%3A%2F%2Fgithub.com%2Fdonetick%2Fhassio-addons',
)
}}
>
Add Addon
</Button>
),
},
]
return (
<Box
sx={{
alignContent: 'center',
textAlign: 'center',
display: 'flex',
flexDirection: 'column',
mt: 2,
}}
>
<Typography level='h4' mt={2} mb={4}>
Getting Started
</Typography>
<Box maxWidth={'lg'} sx={{ mb: 8 }}>
<Typography level='body-md' color='neutral'>
you can start using DoneTick in multiple ways, easiest way is to use
Donetick Web and you can start in seconds, or if you are into
selfhosting you can download the binary and run it on your own server,
or if you are using Home Assistant you can install DoneTick as a Home
Assistant Addon
</Typography>
<div data-aos-id-getting-started-container>
<Grid container spacing={4} mt={4}>
{information.map((info, index) => (
<Grid item xs={12} md={4} key={index}>
<StartOptionCard
icon={info.icon}
title={info.title}
description={info.description}
button={info.button}
/>
</Grid>
))}
</Grid>
</div>
</Box>
</Box>
)
}
export default GettingStarted

View file

@ -61,17 +61,6 @@ const HomeHero = () => {
>
tick
</span>
<span
style={{
fontSize: 20,
fontWeight: 700,
position: 'relative',
top: 12,
right: 45,
}}
>
Beta
</span>
</Typography>
</Box>
)
@ -167,7 +156,7 @@ const HomeHero = () => {
className='hover:scale-105'
onClick={() => {
// new window open to https://github.com/Donetick:
window.open('https://github.com/donetick', '_blank')
window.open('https://github.com/donetick/donetick', '_blank')
}}
startDecorator={<GitHub />}
>

View file

@ -3,12 +3,14 @@ import AOS from 'aos'
import 'aos/dist/aos.css'
import { useEffect } from 'react'
import { useNavigate } from 'react-router-dom'
import CookiePermissionSnackbar from './CookiePermissionSnackbar'
import DemoAssignee from './DemoAssignee'
import DemoHistory from './DemoHistory'
import DemoMyChore from './DemoMyChore'
import DemoScheduler from './DemoScheduler'
import FeaturesSection from './FeaturesSection'
import Footer from './Footer'
import GettingStarted from './GettingStarted'
import HomeHero from './HomeHero'
const Landing = () => {
const Navigate = useNavigate()
@ -39,6 +41,8 @@ const Landing = () => {
<DemoHistory />
</Grid>
<FeaturesSection />
<GettingStarted />
{/* <PricingSection /> */}
<Box
sx={{
@ -49,7 +53,7 @@ const Landing = () => {
mb: 5,
}}
></Box>
<CookiePermissionSnackbar />
<Footer />
</Container>
)

View file

@ -9,7 +9,7 @@ import {
} from '@mui/joy'
import React from 'react'
function SelectModal({ isOpen, onClose, onSave, options, title, displayKey }) {
function SelectModal({ isOpen, onClose, onSave, options, title, displayKey,placeholder }) {
const [selected, setSelected] = React.useState(null)
const handleSave = () => {
onSave(options.find(item => item.id === selected))
@ -20,7 +20,7 @@ function SelectModal({ isOpen, onClose, onSave, options, title, displayKey }) {
<Modal open={isOpen} onClose={onClose}>
<ModalDialog>
<Typography variant='h4'>{title}</Typography>
<Select>
<Select placeholder={placeholder}>
{options.map((item, index) => (
<Option
value={item.id}

View file

@ -30,11 +30,11 @@ const links = [
label: 'Home',
icon: <HomeOutlined />,
},
{
to: '/chores',
label: 'Desktop View',
icon: <ListAltRounded />,
},
// {
// to: '/chores',
// label: 'Desktop View',
// icon: <ListAltRounded />,
// },
{
to: '/things',
label: 'Things',
@ -114,17 +114,6 @@ const NavBar = () => {
tick
</span>
</Typography>
<span
style={{
fontSize: 12,
fontWeight: 700,
position: 'relative',
top: 12,
right: 45,
}}
>
Beta
</span>
</Box>
<Drawer
open={drawerOpen}

View file

@ -14,7 +14,10 @@ export default defineConfig({
'safari-pinned-tab.svg',
'mstile-150x150.png',
],
injectManifest: true,
injectManifest: {
globPatterns: ['**/*.{js,css,html,png,svg}'],
globIgnores: ['index.html'],
},
manifest: {
name: 'Donetick: Simplify Tasks & Chores, Together.',
short_name: 'Donetick',
@ -55,6 +58,10 @@ export default defineConfig({
background_color: '#ffffff',
display: 'standalone',
},
workbox: {
skipWaiting: true, // Force the waiting service worker to become the active service worker
clientsClaim: true, // Take control of uncontrolled clients as soon as the service worker becomes active
},
}),
],