diff --git a/package.json b/package.json
index 253a62c..64307d3 100644
--- a/package.json
+++ b/package.json
@@ -50,6 +50,7 @@
"chrono-node": "^2.7.7",
"dotenv": "^16.4.5",
"esm": "^3.2.25",
+ "event-source-polyfill": "^1.0.31",
"farmhash": "^4.0.1",
"fuse.js": "^7.0.0",
"js-cookie": "^3.0.5",
diff --git a/src/components/RealTimeSettings.jsx b/src/components/RealTimeSettings.jsx
index 85ea585..1a24ad3 100644
--- a/src/components/RealTimeSettings.jsx
+++ b/src/components/RealTimeSettings.jsx
@@ -63,15 +63,15 @@ const RealTimeSettings = () => {
const getStatusDescription = () => {
if (!isPlusAccount(userProfile)) {
- return 'Real-time updates are not available in the Basic plan. Upgrade to Plus to receive instant notifications when chores are updated.'
+ return 'Real-time updates are not available in the Basic plan. Upgrade to Plus to receive instant notifications when tasks are updated.'
}
if (realtimeType === REALTIME_TYPES.DISABLED) {
- return 'Real-time updates are disabled. Enable them to see live changes when you or other circle members complete, skip, or modify chores.'
+ return 'Real-time updates are disabled. Enable them to see live changes when you or other circle members complete, skip, or modify tasks.'
}
if (context.isConnected) {
- return "Real-time updates are working. You'll see live changes when you or other circle members complete, skip, or modify chores."
+ return "Real-time updates are working. You'll see live changes when you or other circle members complete, skip, or modify tasks."
}
if (context.isConnecting) {
@@ -97,12 +97,18 @@ const RealTimeSettings = () => {
return (
- {realtimeType !== REALTIME_TYPES.DISABLED &&
- isPlusAccount(userProfile) ? (
-
- ) : (
-
- )}
+ {
+ handleRealtimeTypeChange(
+ null,
+ e.target.checked ? REALTIME_TYPES.SSE : REALTIME_TYPES.DISABLED,
+ )
+ }}
+ disabled={!isPlusAccount(userProfile)}
+ inputProps={{ 'aria-label': 'Enable Real-time Updates' }}
+ />
{
)}
- {
- handleRealtimeTypeChange(
- null,
- e.target.checked
- ? REALTIME_TYPES.SSE
- : REALTIME_TYPES.DISABLED,
- )
- }}
- disabled={!isPlusAccount(userProfile)}
- inputProps={{ 'aria-label': 'Enable Real-time Updates' }}
- />
+ {realtimeType !== REALTIME_TYPES.DISABLED &&
+ isPlusAccount(userProfile) ? (
+
+ ) : (
+
+ )}
- Get instant notifications when chores are updated
+ Get instant notifications when tasks are updated
@@ -181,7 +180,7 @@ const RealTimeSettings = () => {
Real-time updates are not available in the Basic plan. Upgrade to Plus
to receive instant notifications when you or other circle members
- complete, skip, or modify chores.
+ complete, skip, or modify tasks.
)}
diff --git a/src/views/Settings/APITokenSettings.jsx b/src/views/Settings/APITokenSettings.jsx
index 7addb98..899cc6b 100644
--- a/src/views/Settings/APITokenSettings.jsx
+++ b/src/views/Settings/APITokenSettings.jsx
@@ -13,19 +13,47 @@ import moment from 'moment'
import { useEffect, useState } from 'react'
import { useUserProfile } from '../../queries/UserQueries'
+import { useNotification } from '../../service/NotificationProvider'
import {
CreateLongLiveToken,
DeleteLongLiveToken,
GetLongLiveTokens,
} from '../../utils/Fetcher'
import { isPlusAccount } from '../../utils/Helpers'
+import ConfirmationModal from '../Modals/Inputs/ConfirmationModal'
import TextModal from '../Modals/Inputs/TextModal'
const APITokenSettings = () => {
const { data: userProfile } = useUserProfile()
+ const { showNotification } = useNotification()
const [tokens, setTokens] = useState([])
const [isGetTokenNameModalOpen, setIsGetTokenNameModalOpen] = useState(false)
const [showTokenId, setShowTokenId] = useState(null)
+ const [confirmModalConfig, setConfirmModalConfig] = useState({})
+
+ const showConfirmation = (
+ message,
+ title,
+ onConfirm,
+ confirmText = 'Confirm',
+ cancelText = 'Cancel',
+ color = 'primary',
+ ) => {
+ setConfirmModalConfig({
+ isOpen: true,
+ message,
+ title,
+ confirmText,
+ cancelText,
+ color,
+ onClose: isConfirmed => {
+ if (isConfirmed) {
+ onConfirm()
+ }
+ setConfirmModalConfig({})
+ },
+ })
+ }
useEffect(() => {
GetLongLiveTokens().then(resp => {
resp.json().then(data => {
@@ -100,18 +128,28 @@ const APITokenSettings = () => {
variant='outlined'
color='danger'
onClick={() => {
- const confirmed = confirm(
- `Are you sure you want to remove ${token.name} ?`,
+ showConfirmation(
+ `Are you sure you want to remove ${token.name}?`,
+ 'Remove Token',
+ () => {
+ DeleteLongLiveToken(token.id).then(resp => {
+ if (resp.ok) {
+ showNotification({
+ type: 'success',
+ title: 'Removed',
+ message: 'API token has been removed',
+ })
+ const newTokens = tokens.filter(
+ t => t.id !== token.id,
+ )
+ setTokens(newTokens)
+ }
+ })
+ },
+ 'Remove',
+ 'Cancel',
+ 'danger',
)
- if (confirmed) {
- DeleteLongLiveToken(token.id).then(resp => {
- if (resp.ok) {
- alert('Token removed')
- const newTokens = tokens.filter(t => t.id !== token.id)
- setTokens(newTokens)
- }
- })
- }
}}
>
Remove
@@ -130,7 +168,10 @@ const APITokenSettings = () => {
color='primary'
onClick={() => {
navigator.clipboard.writeText(token.token)
- alert('Token copied to clipboard')
+ showNotification({
+ type: 'success',
+ message: 'Token copied to clipboard',
+ })
setShowTokenId(null)
}}
>
@@ -166,6 +207,11 @@ const APITokenSettings = () => {
okText={'Generate Token'}
onSave={handleSaveToken}
/>
+
+ {/* Modals */}
+ {confirmModalConfig?.isOpen && (
+
+ )}
)
}
diff --git a/src/views/Settings/Settings.jsx b/src/views/Settings/Settings.jsx
index 395f76a..6e1dbc7 100644
--- a/src/views/Settings/Settings.jsx
+++ b/src/views/Settings/Settings.jsx
@@ -34,6 +34,7 @@ import {
UpdatePassword,
} from '../../utils/Fetcher'
import { isPlusAccount } from '../../utils/Helpers'
+import ConfirmationModal from '../Modals/Inputs/ConfirmationModal'
import PassowrdChangeModal from '../Modals/Inputs/PasswordChangeModal'
import APITokenSettings from './APITokenSettings'
import MFASettings from './MFASettings'
@@ -41,9 +42,11 @@ import NotificationSetting from './NotificationSetting'
import ProfileSettings from './ProfileSettings'
import StorageSettings from './StorageSettings'
import ThemeToggle from './ThemeToggle'
+import { useNotification } from '../../service/NotificationProvider'
const Settings = () => {
const { data: userProfile } = useUserProfile()
+ const { showNotification } = useNotification()
const [userCircles, setUserCircles] = useState([])
const [circleMemberRequests, setCircleMemberRequests] = useState([])
@@ -54,6 +57,31 @@ const Settings = () => {
const [isAdmin, setIsAdmin] = useState(false)
const [changePasswordModal, setChangePasswordModal] = useState(false)
+ const [confirmModalConfig, setConfirmModalConfig] = useState({})
+
+ const showConfirmation = (
+ message,
+ title,
+ onConfirm,
+ confirmText = 'Confirm',
+ cancelText = 'Cancel',
+ color = 'primary',
+ ) => {
+ setConfirmModalConfig({
+ isOpen: true,
+ message,
+ title,
+ confirmText,
+ cancelText,
+ color,
+ onClose: isConfirmed => {
+ if (isConfirmed) {
+ onConfirm()
+ }
+ setConfirmModalConfig({})
+ },
+ })
+ }
useEffect(() => {
GetUserCircle().then(resp => {
resp.json().then(data => {
@@ -165,7 +193,10 @@ const Settings = () => {
variant='soft'
onClick={() => {
navigator.clipboard.writeText(userCircles[0]?.invite_code)
- alert('Code Copied to clipboard')
+ showNotification({
+ type: 'success',
+ message: 'Code copied to clipboard',
+ })
}}
>
Copy Code
@@ -180,27 +211,42 @@ const Settings = () => {
window.location.host +
`/circle/join?code=${userCircles[0]?.invite_code}`,
)
- alert('Link Copied to clipboard')
+ showNotification({
+ type: 'success',
+ message: 'Link copied to clipboard',
+ })
}}
>
Copy Link
{userCircles.length > 0 && userCircles[0]?.userRole === 'member' && (