Merge pull request #113 from donetick/donetick.com-clean
Rebase to Donetick.com branch
This commit is contained in:
29
src/App.jsx
29
src/App.jsx
@@ -1,14 +1,18 @@
|
||||
import NavBar from '@/views/components/NavBar'
|
||||
import { Button, Typography, useColorScheme } from '@mui/joy'
|
||||
import Tracker from '@openreplay/tracker'
|
||||
import { useCallback, useEffect } from 'react'
|
||||
import { Outlet } from 'react-router-dom'
|
||||
import { useRegisterSW } from 'virtual:pwa-register/react'
|
||||
import { registerCapacitorListeners } from './CapacitorListener'
|
||||
import PageTransition from './components/animations/PageTransition'
|
||||
import { ImpersonateUserProvider } from './contexts/ImpersonateUserContext'
|
||||
import SSEProvider from './contexts/SSEContext'
|
||||
import { AuthProvider } from './hooks/useAuth.jsx'
|
||||
|
||||
import useStatusBar from './hooks/useStatusBar'
|
||||
import { useResource } from './queries/ResourceQueries'
|
||||
import './styles/safe-area.css'
|
||||
|
||||
import SSEProvider from './contexts/SSEContext'
|
||||
import { useNotification } from './service/NotificationProvider'
|
||||
|
||||
import NetworkBanner from './views/components/NetworkBanner'
|
||||
@@ -24,18 +28,14 @@ const remove = className => {
|
||||
// TODO: Update the interval to at 60 minutes
|
||||
const intervalMS = 5 * 60 * 1000 // 5 minutes
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
const AppContent = () => {
|
||||
const { showNotification } = useNotification()
|
||||
|
||||
// Initialize status bar with theme-aware configuration
|
||||
useStatusBar()
|
||||
|
||||
const {
|
||||
offlineReady: [offlineReady, setOfflineReady], // eslint-disable-line no-unused-vars
|
||||
needRefresh: [needRefresh, setNeedRefresh],
|
||||
updateServiceWorker,
|
||||
} = useRegisterSW({
|
||||
@@ -94,10 +94,11 @@ const AppContent = () => {
|
||||
}
|
||||
|
||||
function App() {
|
||||
// startOpenReplay()
|
||||
|
||||
const resource = useResource() // eslint-disable-line no-unused-vars
|
||||
const { mode, systemMode } = useColorScheme()
|
||||
|
||||
// startOpenReplay()
|
||||
|
||||
const setThemeClass = useCallback(() => {
|
||||
const value = JSON.parse(localStorage.getItem('themeMode')) || mode
|
||||
|
||||
@@ -124,7 +125,7 @@ function App() {
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<NetworkBanner />
|
||||
|
||||
<AuthProvider>
|
||||
@@ -132,7 +133,7 @@ function App() {
|
||||
<AppContent />
|
||||
</SSEProvider>
|
||||
</AuthProvider>
|
||||
</>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
56
src/hooks/useStatusBar.js
Normal file
56
src/hooks/useStatusBar.js
Normal file
@@ -0,0 +1,56 @@
|
||||
import { useColorScheme } from '@mui/joy'
|
||||
import { useEffect } from 'react'
|
||||
import statusBarManager from '../utils/StatusBarManager'
|
||||
|
||||
/**
|
||||
* Custom hook to manage status bar integration with Joy UI themes
|
||||
* This hook automatically syncs the status bar style with the current theme
|
||||
*/
|
||||
export const useStatusBar = () => {
|
||||
const { mode, systemMode } = useColorScheme()
|
||||
|
||||
useEffect(() => {
|
||||
// Initialize status bar on mount
|
||||
const initializeStatusBar = async () => {
|
||||
await statusBarManager.initialize(mode)
|
||||
}
|
||||
|
||||
initializeStatusBar()
|
||||
|
||||
// Cleanup on unmount
|
||||
return () => {
|
||||
statusBarManager.cleanup()
|
||||
}
|
||||
}, [mode]) // Include mode dependency
|
||||
|
||||
useEffect(() => {
|
||||
// Update status bar when theme changes
|
||||
const updateStatusBarTheme = async () => {
|
||||
let resolvedTheme = mode
|
||||
|
||||
// Handle system mode by using the detected system theme
|
||||
if (mode === 'system') {
|
||||
resolvedTheme = systemMode || 'light'
|
||||
}
|
||||
|
||||
// Update the status bar with the resolved theme
|
||||
await statusBarManager.updateResolvedTheme(resolvedTheme)
|
||||
|
||||
// Also update the base theme for future reference
|
||||
await statusBarManager.setTheme(mode)
|
||||
|
||||
// Notify any custom listeners
|
||||
statusBarManager.notifyThemeChange(resolvedTheme)
|
||||
}
|
||||
|
||||
updateStatusBarTheme()
|
||||
}, [mode, systemMode]) // Update when either mode or systemMode changes
|
||||
|
||||
return {
|
||||
statusBarManager,
|
||||
currentTheme: mode,
|
||||
resolvedTheme: mode === 'system' ? systemMode : mode,
|
||||
}
|
||||
}
|
||||
|
||||
export default useStatusBar
|
||||
127
src/styles/safe-area.css
Normal file
127
src/styles/safe-area.css
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Safe Area CSS Utilities
|
||||
* These utilities provide consistent safe area handling across the app
|
||||
* using CSS custom properties set by StatusBarManager
|
||||
*/
|
||||
|
||||
:root {
|
||||
/* Fallback values for safe area insets when not on native platforms */
|
||||
--safe-area-inset-top: 0px;
|
||||
--safe-area-inset-right: 0px;
|
||||
--safe-area-inset-bottom: 0px;
|
||||
--safe-area-inset-left: 0px;
|
||||
}
|
||||
|
||||
/* Utility classes for safe area handling */
|
||||
.safe-area-top {
|
||||
padding-top: var(--safe-area-inset-top);
|
||||
}
|
||||
|
||||
.safe-area-right {
|
||||
padding-right: var(--safe-area-inset-right);
|
||||
}
|
||||
|
||||
.safe-area-bottom {
|
||||
padding-bottom: var(--safe-area-inset-bottom);
|
||||
}
|
||||
|
||||
.safe-area-left {
|
||||
padding-left: var(--safe-area-inset-left);
|
||||
}
|
||||
|
||||
.safe-area-x {
|
||||
padding-left: var(--safe-area-inset-left);
|
||||
padding-right: var(--safe-area-inset-right);
|
||||
}
|
||||
|
||||
.safe-area-y {
|
||||
padding-top: var(--safe-area-inset-top);
|
||||
padding-bottom: var(--safe-area-inset-bottom);
|
||||
}
|
||||
|
||||
.safe-area-all {
|
||||
padding-top: var(--safe-area-inset-top);
|
||||
padding-right: var(--safe-area-inset-right);
|
||||
padding-bottom: var(--safe-area-inset-bottom);
|
||||
padding-left: var(--safe-area-inset-left);
|
||||
}
|
||||
|
||||
/* Margin variants */
|
||||
.safe-margin-top {
|
||||
margin-top: var(--safe-area-inset-top);
|
||||
}
|
||||
|
||||
.safe-margin-right {
|
||||
margin-right: var(--safe-area-inset-right);
|
||||
}
|
||||
|
||||
.safe-margin-bottom {
|
||||
margin-bottom: var(--safe-area-inset-bottom);
|
||||
}
|
||||
|
||||
.safe-margin-left {
|
||||
margin-left: var(--safe-area-inset-left);
|
||||
}
|
||||
|
||||
.safe-margin-x {
|
||||
margin-left: var(--safe-area-inset-left);
|
||||
margin-right: var(--safe-area-inset-right);
|
||||
}
|
||||
|
||||
.safe-margin-y {
|
||||
margin-top: var(--safe-area-inset-top);
|
||||
margin-bottom: var(--safe-area-inset-bottom);
|
||||
}
|
||||
|
||||
.safe-margin-all {
|
||||
margin-top: var(--safe-area-inset-top);
|
||||
margin-right: var(--safe-area-inset-right);
|
||||
margin-bottom: var(--safe-area-inset-bottom);
|
||||
margin-left: var(--safe-area-inset-left);
|
||||
}
|
||||
|
||||
/* Height utilities that account for safe areas */
|
||||
.min-h-screen-safe {
|
||||
min-height: calc(100vh - var(--safe-area-inset-top) - var(--safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
.h-screen-safe {
|
||||
height: calc(100vh - var(--safe-area-inset-top) - var(--safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
/* Top positioning that accounts for safe area */
|
||||
.top-safe {
|
||||
top: var(--safe-area-inset-top);
|
||||
}
|
||||
|
||||
/* Bottom positioning that accounts for safe area */
|
||||
.bottom-safe {
|
||||
bottom: var(--safe-area-inset-bottom);
|
||||
}
|
||||
|
||||
/* Fixed positioning utilities that respect safe areas */
|
||||
.fixed-top-safe {
|
||||
position: fixed;
|
||||
top: var(--safe-area-inset-top);
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1030;
|
||||
}
|
||||
|
||||
.fixed-bottom-safe {
|
||||
position: fixed;
|
||||
bottom: var(--safe-area-inset-bottom);
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1030;
|
||||
}
|
||||
|
||||
/* Container that provides full safe area coverage */
|
||||
.container-safe {
|
||||
padding-top: var(--safe-area-inset-top);
|
||||
padding-right: var(--safe-area-inset-right);
|
||||
padding-bottom: var(--safe-area-inset-bottom);
|
||||
padding-left: var(--safe-area-inset-left);
|
||||
min-height: 100vh;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
@@ -26,7 +26,7 @@ class StatusBarManager {
|
||||
}
|
||||
|
||||
try {
|
||||
// Configure basic status bar settings - use overlay: true for precise control
|
||||
// Configure basic status bar settings
|
||||
await StatusBar.setOverlaysWebView({ overlay: false })
|
||||
await StatusBar.show()
|
||||
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
import { Card, Grid, Typography } from '@mui/joy'
|
||||
import moment from 'moment'
|
||||
import { useState } from 'react'
|
||||
import ChoreCard from '../Chores/ChoreCard'
|
||||
|
||||
const DemoMyChore = () => {
|
||||
const [selectedCalendarDate, setSelectedCalendarDate] = useState(null)
|
||||
|
||||
const cards = [
|
||||
{
|
||||
id: 12,
|
||||
name: '♻️ Take out recycle ',
|
||||
frequencyType: 'days_of_the_week',
|
||||
frequency: 1,
|
||||
priority: 1,
|
||||
frequencyMetadata:
|
||||
'{"days":["thursday"],"time":"2024-07-07T22:00:00-04:00"}',
|
||||
nextDueDate: moment().add(1, 'days').hour(8).minute(0).toISOString(),
|
||||
@@ -96,6 +100,17 @@ const DemoMyChore = () => {
|
||||
]
|
||||
|
||||
const users = [{ displayName: 'Me', id: 1, userId: 1 }]
|
||||
|
||||
// Helper function to get chores for a specific date
|
||||
const getChoresForDate = date => {
|
||||
return cards.filter(chore => {
|
||||
if (!chore.nextDueDate) return false
|
||||
const choreDate = new Date(chore.nextDueDate).toLocaleDateString()
|
||||
const selectedDate = date.toLocaleDateString()
|
||||
return choreDate === selectedDate
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Grid item xs={12} sm={5} data-aos-first-tasks-list>
|
||||
|
||||
@@ -17,6 +17,10 @@ import TabletInstallationSection from './TabletInstallationSection'
|
||||
const Landing = () => {
|
||||
const Navigate = useNavigate()
|
||||
useEffect(() => {
|
||||
// if the host is https://app.donetick.com/ then redirect to https://app.donetick.com/my/chores:
|
||||
if (window.location.host === 'app.donetick.com') {
|
||||
Navigate('/chores')
|
||||
}
|
||||
AOS.init({
|
||||
once: false, // whether animation should happen only once - while scrolling down
|
||||
})
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import ipad_screenshot from '@/assets/ipad_dashbard_calendar.png'
|
||||
import { Box, Container, Typography } from '@mui/joy'
|
||||
|
||||
const TabletInstallationSection = () => {
|
||||
return (
|
||||
<Container maxWidth='xl' sx={{ py: { xs: 6, sm: 8, md: 12 } }}>
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import React from 'react'
|
||||
|
||||
const PrivacyPolicyView = () => {
|
||||
return (
|
||||
<div>
|
||||
|
||||
@@ -29,7 +29,10 @@ const AccountSettings = () => {
|
||||
async function configurePurchases() {
|
||||
if (Capacitor.isNativePlatform() && userProfile) {
|
||||
await Purchases.configure({
|
||||
apiKey: import.meta.env.VITE_REACT_APP_REVENUECAT_API_KEY,
|
||||
apiKey:
|
||||
Capacitor.getPlatform() === 'ios'
|
||||
? import.meta.env.VITE_REACT_APP_REVENUECAT_API_KEY_IOS
|
||||
: import.meta.env.VITE_REACT_APP_REVENUECAT_API_KEY_ANDROID,
|
||||
appUserID: String(userProfile?.id),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -139,7 +139,10 @@ const Settings = () => {
|
||||
async function configurePurchases() {
|
||||
if (Capacitor.isNativePlatform() && userProfile) {
|
||||
await Purchases.configure({
|
||||
apiKey: import.meta.env.VITE_REACT_APP_REVENUECAT_API_KEY,
|
||||
apiKey:
|
||||
Capacitor.getPlatform() === 'ios'
|
||||
? import.meta.env.VITE_REACT_APP_REVENUECAT_API_KEY_IOS
|
||||
: import.meta.env.VITE_REACT_APP_REVENUECAT_API_KEY_ANDROID,
|
||||
appUserID: String(userProfile?.id),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -221,7 +221,7 @@ const NavBar = () => {
|
||||
},
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<div className='drawer-content'>
|
||||
{/* <div className='align-center flex px-5 pt-4'>
|
||||
<ModalClose size='sm' sx={{ top: 'unset', right: 20 }} />
|
||||
</div> */}
|
||||
|
||||
Reference in New Issue
Block a user