diff --git a/src/Application.jsx b/src/Application.jsx
new file mode 100644
index 0000000..5bd01fb
--- /dev/null
+++ b/src/Application.jsx
@@ -0,0 +1,10 @@
+import App from './App.jsx'
+import Contexts from './contexts/Contexts.jsx'
+
+const Application = () => (
+
+
+
+)
+
+export default Application
diff --git a/src/MarketingApp.jsx b/src/MarketingApp.jsx
new file mode 100644
index 0000000..4f862fb
--- /dev/null
+++ b/src/MarketingApp.jsx
@@ -0,0 +1,66 @@
+import { useColorScheme } from '@mui/joy'
+import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
+import { useEffect } from 'react'
+import { createBrowserRouter, RouterProvider } from 'react-router-dom'
+
+import { ImpersonateUserProvider } from './contexts/ImpersonateUserContext'
+import { LocalizationProvider } from './contexts/LocalizationContext'
+import ThemeContext from './contexts/ThemeContext'
+import Landing from './views/Landing/Landing'
+import PrivacyPolicyView from './views/PrivacyPolicy/PrivacyPolicyView'
+import TermsView from './views/Terms/TermsView'
+
+const AppRedirect = () => {
+ useEffect(() => {
+ const { hash, pathname, search } = window.location
+ window.location.replace(
+ `https://app.donetick.com${pathname}${search}${hash}`,
+ )
+ }, [])
+
+ return null
+}
+
+const router = createBrowserRouter([
+ { path: '/', element: },
+ { path: '/privacy', element: },
+ { path: '/terms', element: },
+ { path: '*', element: },
+])
+
+const queryClient = new QueryClient({
+ defaultOptions: {
+ queries: { enabled: false, refetchOnWindowFocus: false, retry: false },
+ },
+})
+
+const ThemeClass = () => {
+ const { mode, systemMode } = useColorScheme()
+
+ useEffect(() => {
+ const storedMode = JSON.parse(localStorage.getItem('themeMode') || 'null')
+ const selectedMode = storedMode || mode
+ const isDark =
+ selectedMode === 'dark' ||
+ (selectedMode === 'system' && systemMode === 'dark')
+
+ document.getElementById('root').classList.toggle('dark', isDark)
+ }, [mode, systemMode])
+
+ return null
+}
+
+const MarketingApp = () => (
+
+
+
+
+
+
+
+
+
+
+)
+
+export default MarketingApp
diff --git a/src/contexts/RouterContext.jsx b/src/contexts/RouterContext.jsx
index 3c17b90..bb5c8dd 100644
--- a/src/contexts/RouterContext.jsx
+++ b/src/contexts/RouterContext.jsx
@@ -1,3 +1,5 @@
+import { createBrowserRouter, RouterProvider } from 'react-router-dom'
+
import App from '@/App'
import ChoreEdit from '@/views/ChoreEdit/ChoreEdit'
import Error from '@/views/Error'
@@ -10,7 +12,7 @@ import Settings from '@/views/Settings/Settings'
import SettingsOverview from '@/views/Settings/SettingsOverview'
import SettingsRoutes from '@/views/Settings/SettingsRoutes'
import ThemeSettings from '@/views/Settings/ThemeSettings'
-import { RouterProvider, createBrowserRouter } from 'react-router-dom'
+
import AuthenticationLoading from '../views/Authorization/Authenticating'
import ForgotPasswordView from '../views/Authorization/ForgotPasswordView'
import LoginSettings from '../views/Authorization/LoginSettings'
@@ -49,16 +51,6 @@ import ThingsView from '../views/Things/ThingsView'
import TimerDetails from '../views/Timer/TimerDetails'
import UserActivities from '../views/User/UserActivities'
import UserPoints from '../views/User/UserPoints'
-const getMainRoute = () => {
- if (
- // if domain is www.donetick.com or donetick.com then show landing page:
- window.location.hostname === 'www.donetick.com' ||
- window.location.hostname === 'donetick.com'
- ) {
- return
- }
- return
-}
const Router = createBrowserRouter([
{
path: '/',
@@ -67,7 +59,7 @@ const Router = createBrowserRouter([
children: [
{
path: '/',
- element: getMainRoute(),
+ element: ,
},
{
path: '/settings',
diff --git a/src/main.jsx b/src/main.jsx
index b339e91..0aefb3d 100644
--- a/src/main.jsx
+++ b/src/main.jsx
@@ -1,14 +1,23 @@
-import React from 'react'
-import ReactDOM from 'react-dom/client'
-import App from './App.jsx'
-import Contexts from './contexts/Contexts.jsx'
import './i18n/config'
import './index.css'
+import React from 'react'
+import ReactDOM from 'react-dom/client'
+
+const marketingHosts = new Set(['donetick.com', 'www.donetick.com'])
+const isMarketingSite =
+ marketingHosts.has(window.location.hostname) ||
+ (import.meta.env.DEV &&
+ new URLSearchParams(window.location.search).get('site') === 'marketing')
+
+export const Site = React.lazy(() =>
+ isMarketingSite ? import('./MarketingApp.jsx') : import('./Application.jsx'),
+)
+
ReactDOM.createRoot(document.getElementById('root')).render(
-
-
-
+
+
+
,
)
diff --git a/src/queries/UserQueries.jsx b/src/queries/UserQueries.jsx
index 588f1a2..8200769 100644
--- a/src/queries/UserQueries.jsx
+++ b/src/queries/UserQueries.jsx
@@ -1,4 +1,5 @@
import { useQuery, useQueryClient } from '@tanstack/react-query'
+
import {
GetAllCircleMembers,
GetAllUsers,
@@ -54,7 +55,7 @@ export const useCircleMembers = () => {
return { data, error, isLoading, handleRefetch }
}
-export const useUserProfile = () => {
+export const useUserProfile = ({ enabled = true } = {}) => {
const queryClient = useQueryClient()
const token = localStorage.getItem('token')
@@ -80,7 +81,7 @@ export const useUserProfile = () => {
},
staleTime: 30 * 60 * 1000,
gcTime: 30 * 60 * 1000,
- enabled: !!token,
+ enabled: enabled && !!token,
})
return {
data,
diff --git a/src/views/ChoreEdit/RepeatSection.jsx b/src/views/ChoreEdit/RepeatSection.jsx
index 4cb4fa9..ed030fd 100644
--- a/src/views/ChoreEdit/RepeatSection.jsx
+++ b/src/views/ChoreEdit/RepeatSection.jsx
@@ -84,9 +84,7 @@ const generateSchedulePreview = (metadata, formatTimeFn) => {
.map(day => day.charAt(0).toUpperCase() + day.slice(1, 3))
.join(', ')
- const timeStr = metadata.time
- ? formatTimeFn(metadata.time)
- : '6:00 PM'
+ const timeStr = metadata.time ? formatTimeFn(metadata.time) : '6:00 PM'
if (metadata.weekPattern === 'every_week' || !metadata.weekPattern) {
return `Every ${dayNames} at ${timeStr}`
@@ -109,11 +107,11 @@ const generateSchedulePreview = (metadata, formatTimeFn) => {
}
export const RepeatOnSections = ({
- frequencyType,
frequency,
- onFrequencyUpdate,
frequencyMetadata,
+ frequencyType,
onFrequencyMetadataUpdate,
+ onFrequencyUpdate,
}) => {
const { fmt } = useLocalization()
// if time on frequencyMetadata is not set, try to set it to the nextDueDate if available,
@@ -527,20 +525,21 @@ export const RepeatOnSections = ({
}
const RepeatSection = ({
- frequencyType,
- frequency,
- onFrequencyUpdate,
- onFrequencyTypeUpdate,
- frequencyMetadata,
- onFrequencyMetadataUpdate,
- frequencyError,
- allUserThings,
- onTriggerUpdate,
OnTriggerValidate,
+ allUserThings,
+ frequency,
+ frequencyError,
+ frequencyMetadata,
+ frequencyType,
isAttemptToSave,
+ onFrequencyMetadataUpdate,
+ onFrequencyTypeUpdate,
+ onFrequencyUpdate,
+ onTriggerUpdate,
selectedThing,
+ viewOnly = false,
}) => {
- const { data: userProfile } = useUserProfile()
+ const { data: userProfile } = useUserProfile({ enabled: !viewOnly })
return (
diff --git a/src/views/Chores/ChoreCard.jsx b/src/views/Chores/ChoreCard.jsx
index cf04f64..69e06f1 100644
--- a/src/views/Chores/ChoreCard.jsx
+++ b/src/views/Chores/ChoreCard.jsx
@@ -49,7 +49,7 @@ const ChoreCard = ({
sx,
viewOnly,
}) => {
- const { data: userProfile } = useUserProfile()
+ const { data: userProfile } = useUserProfile({ enabled: !viewOnly })
const { timeFormat } = useLocalization()
const { data: pendingCmds } = usePendingCommands(chore.id)
diff --git a/src/views/Landing/DemoHistory.jsx b/src/views/Landing/DemoHistory.jsx
index 57ae8c8..227a8b7 100644
--- a/src/views/Landing/DemoHistory.jsx
+++ b/src/views/Landing/DemoHistory.jsx
@@ -1,5 +1,6 @@
import { Box, Card, Grid, List, Typography } from '@mui/joy'
import moment from 'moment'
+
import HistoryCard from '../History/HistoryCard'
const DemoHistory = () => {
@@ -7,29 +8,32 @@ const DemoHistory = () => {
{
id: 32,
choreId: 12,
- completedAt: moment().hour(4).format(),
+ performedAt: moment().hour(4).format(),
completedBy: 1,
assignedTo: 1,
notes: null,
dueDate: moment().format(),
+ status: 1,
},
{
id: 31,
choreId: 12,
- completedAt: moment().day(-1).format(),
+ performedAt: moment().day(-1).format(),
completedBy: 1,
assignedTo: 1,
notes: 'Need to be replaced with a new one',
dueDate: moment().day(-2).format(),
+ status: 1,
},
{
id: 31,
choreId: 12,
- completedAt: moment().day(-10).hour(1).format(),
+ performedAt: moment().day(-10).hour(1).format(),
completedBy: 2,
assignedTo: 1,
notes: null,
dueDate: moment().day(-10).format(),
+ status: 1,
},
]
const performers = [
@@ -61,6 +65,7 @@ const DemoHistory = () => {
key={index}
index={index}
performers={performers}
+ pendingCommands={[]}
/>
))}
diff --git a/src/views/Landing/DemoMyChore.jsx b/src/views/Landing/DemoMyChore.jsx
index a4a8dd7..201815b 100644
--- a/src/views/Landing/DemoMyChore.jsx
+++ b/src/views/Landing/DemoMyChore.jsx
@@ -1,6 +1,7 @@
import { Card, Grid, Typography } from '@mui/joy'
import moment from 'moment'
import { useState } from 'react'
+
import ChoreCard from '../Chores/ChoreCard'
const DemoMyChore = () => {
@@ -121,7 +122,12 @@ const DemoMyChore = () => {
data-aos-anchor='[data-aos-first-tasks-list]'
data-aos='fade-up'
>
-
+
))}
@@ -141,10 +147,10 @@ const DemoMyChore = () => {
Main view prioritize tasks due today, followed by overdue ones, and
finally, future tasks or those without due dates. With Donetick, you
- can view all the tasks you've created (whether assigned to you or
- not) as well as tasks assigned to you by others. Quickly mark them
- as done with just one click, ensuring a smooth and efficient task
- management experience.
+ can view all the tasks you've created (whether assigned to you
+ or not) as well as tasks assigned to you by others. Quickly mark
+ them as done with just one click, ensuring a smooth and efficient
+ task management experience.
diff --git a/src/views/Landing/DemoScheduler.jsx b/src/views/Landing/DemoScheduler.jsx
index 5e34adb..08ee63e 100644
--- a/src/views/Landing/DemoScheduler.jsx
+++ b/src/views/Landing/DemoScheduler.jsx
@@ -1,5 +1,6 @@
import { Box, Card, Grid, Typography } from '@mui/joy'
import { useState } from 'react'
+
import RepeatSection from '../ChoreEdit/RepeatSection'
const DemoScheduler = () => {
@@ -32,6 +33,7 @@ const DemoScheduler = () => {
OnTriggerValidate={() => {}}
isAttemptToSave={false}
selectedThing={null}
+ viewOnly
/>